fix: harden inline handlers against id injection, fix stale version label
Some checks failed
Caterium QA / qa (push) Failing after 8m6s
Some checks failed
Caterium QA / qa (push) Failing after 8m6s
Inline handlers built as onclick="fn('${esc(id)}')" were injectable:
esc() turns ' into ', which the browser decodes back to ' before
the JS runs, so an id like x');alert(1);// broke out of the string.
Ids can come from a restored backup file or a synced catalog. Add
SunSafe.jsArg (JSON.stringify + HTML escape) and use it in all 24
handlers across app-runtime.js and index.html, including the new
banquet-menu ones. Verified locally: an id containing a JS payload
is passed through as a plain string and nothing executes.
Also replace the Settings version label that still showed
v17.6.0 · 2026.09.07 with the current release, and bump the script
cache-busting string so the fix reaches browsers.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
2f7b8b9ea9
commit
0fc359dda6
@ -429,7 +429,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
|
|||||||
function renderOrderLines(){
|
function renderOrderLines(){
|
||||||
if(!$('lines'))return;
|
if(!$('lines'))return;
|
||||||
if(!(draft.lines||[]).length){$('lines').innerHTML='<p class="empty">Выберите позиции из каталога слева.</p>';return}
|
if(!(draft.lines||[]).length){$('lines').innerHTML='<p class="empty">Выберите позиции из каталога слева.</p>';return}
|
||||||
const rows=draft.lines.map((line,index)=>{const item=boxes.find(x=>String(x.id)===String(line.id));if(!item)return'';const qty=Math.max(1,Number(line.qty||1)),price=lineUnitPrice(line),isBox=[0,5].includes(Number(item.category||0));return `<div class="sun-order-line-row" data-line-index="${index}"><div class="sun-order-line-name" title="${esc(item.name)}">${esc(String(item.name||'').replace(/^(?:Фуршетный\s+)?бокс\s*№\s*(\d+)\s*(?:[—–-]\s*)?/i,'№ $1 '))}${isBox&&(item.weight||inferBoxPieces(item))?`<small>${item.weight?`<b>Вес:</b> ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`<b>Количество:</b> ${inferBoxPieces(item)} шт.`:''}</small>`:''}</div><div class="sun-order-line-qty"><button type="button" onclick="qty('${esc(line.id)}',${qty-1})">−</button><input type="number" min="1" value="${qty}" onchange="qty('${esc(line.id)}',+this.value)"><button type="button" onclick="qty('${esc(line.id)}',${qty+1})">+</button></div><div class="sun-order-line-price"><input type="text" inputmode="numeric" pattern="[0-9]*" autocomplete="off" value="${Math.round(price)}" onchange="sunOrderLinePriceChanged(${index},this)"></div><div class="sun-order-line-sum"><b>${money(price*qty)}</b></div></div>`}).join('');
|
const rows=draft.lines.map((line,index)=>{const item=boxes.find(x=>String(x.id)===String(line.id));if(!item)return'';const qty=Math.max(1,Number(line.qty||1)),price=lineUnitPrice(line),isBox=[0,5].includes(Number(item.category||0));return `<div class="sun-order-line-row" data-line-index="${index}"><div class="sun-order-line-name" title="${esc(item.name)}">${esc(String(item.name||'').replace(/^(?:Фуршетный\s+)?бокс\s*№\s*(\d+)\s*(?:[—–-]\s*)?/i,'№ $1 '))}${isBox&&(item.weight||inferBoxPieces(item))?`<small>${item.weight?`<b>Вес:</b> ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`<b>Количество:</b> ${inferBoxPieces(item)} шт.`:''}</small>`:''}</div><div class="sun-order-line-qty"><button type="button" onclick="qty(${SunSafe.jsArg(line.id)},${qty-1})">−</button><input type="number" min="1" value="${qty}" onchange="qty(${SunSafe.jsArg(line.id)},+this.value)"><button type="button" onclick="qty(${SunSafe.jsArg(line.id)},${qty+1})">+</button></div><div class="sun-order-line-price"><input type="text" inputmode="numeric" pattern="[0-9]*" autocomplete="off" value="${Math.round(price)}" onchange="sunOrderLinePriceChanged(${index},this)"></div><div class="sun-order-line-sum"><b>${money(price*qty)}</b></div></div>`}).join('');
|
||||||
$('lines').innerHTML=`<div class="sun-order-lines-table"><div class="sun-order-line-head"><span>Наименование</span><span>Кол.</span><span>Цена</span><span>Стоимость</span></div><div class="sun-order-line-body">${rows}</div><div class="sun-order-line-total"><span>Стоимость позиций</span><b>${money(baseTotal(draft))}</b></div></div>`;
|
$('lines').innerHTML=`<div class="sun-order-lines-table"><div class="sun-order-line-head"><span>Наименование</span><span>Кол.</span><span>Цена</span><span>Стоимость</span></div><div class="sun-order-line-body">${rows}</div><div class="sun-order-line-total"><span>Стоимость позиций</span><b>${money(baseTotal(draft))}</b></div></div>`;
|
||||||
}
|
}
|
||||||
window.sunOrderLinePriceChanged=(index,input)=>{const line=draft.lines?.[index];if(!line)return;line.price=Math.max(0,Math.round(Number(input.value||0)));const row=input.closest('.sun-order-line-row'),sum=row?.querySelector('.sun-order-line-sum b');if(sum)sum.textContent=money(line.price*Math.max(0,Number(line.qty||0)));const total=$('lines')?.querySelector('.sun-order-line-total b');if(total)total.textContent=money(baseTotal(draft));updateOrderSummary();};
|
window.sunOrderLinePriceChanged=(index,input)=>{const line=draft.lines?.[index];if(!line)return;line.price=Math.max(0,Math.round(Number(input.value||0)));const row=input.closest('.sun-order-line-row'),sum=row?.querySelector('.sun-order-line-sum b');if(sum)sum.textContent=money(line.price*Math.max(0,Number(line.qty||0)));const total=$('lines')?.querySelector('.sun-order-line-total b');if(total)total.textContent=money(baseTotal(draft));updateOrderSummary();};
|
||||||
@ -443,7 +443,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
|
|||||||
const sel=new Set(banquetSelection().map(String));
|
const sel=new Set(banquetSelection().map(String));
|
||||||
const groups=new Map();
|
const groups=new Map();
|
||||||
items.forEach(item=>{const g=String(item.catalogSection||'Без раздела').trim()||'Без раздела';if(!groups.has(g))groups.set(g,[]);groups.get(g).push(item)});
|
items.forEach(item=>{const g=String(item.catalogSection||'Без раздела').trim()||'Без раздела';if(!groups.has(g))groups.set(g,[]);groups.get(g).push(item)});
|
||||||
const groupsHtml=[...groups.entries()].map(([section,list])=>`<div class="sun-banquet-group"><h4>${esc(section)}</h4>${list.map(item=>`<label class="sun-banquet-row"><input type="checkbox" onchange="toggleBanquetItem('${esc(item.id)}')" ${sel.has(String(item.id))?'checked':''}><span class="sun-banquet-row-name">${esc(item.name)}${item.weight?`<small>${esc(item.weight)}</small>`:''}</span><span class="sun-banquet-row-price">${money(item.price||0)}</span><button type="button" class="sun-banquet-edit" onclick="event.preventDefault();editBox('${esc(item.id)}')" title="Изменить">✎</button></label>`).join('')}</div>`).join('');
|
const groupsHtml=[...groups.entries()].map(([section,list])=>`<div class="sun-banquet-group"><h4>${esc(section)}</h4>${list.map(item=>`<label class="sun-banquet-row"><input type="checkbox" onchange="toggleBanquetItem(${SunSafe.jsArg(item.id)})" ${sel.has(String(item.id))?'checked':''}><span class="sun-banquet-row-name">${esc(item.name)}${item.weight?`<small>${esc(item.weight)}</small>`:''}</span><span class="sun-banquet-row-price">${money(item.price||0)}</span><button type="button" class="sun-banquet-edit" onclick="event.preventDefault();editBox(${SunSafe.jsArg(item.id)})" title="Изменить">✎</button></label>`).join('')}</div>`).join('');
|
||||||
const selectedItems=items.filter(item=>sel.has(String(item.id)));
|
const selectedItems=items.filter(item=>sel.has(String(item.id)));
|
||||||
const total=selectedItems.reduce((s,i)=>s+Number(i.price||0),0);
|
const total=selectedItems.reduce((s,i)=>s+Number(i.price||0),0);
|
||||||
const summaryRows=selectedItems.map(item=>`<div class="sun-banquet-summary-row"><span>${esc(item.name)}</span><b>${money(item.price||0)}</b></div>`).join('');
|
const summaryRows=selectedItems.map(item=>`<div class="sun-banquet-summary-row"><span>${esc(item.name)}</span><b>${money(item.price||0)}</b></div>`).join('');
|
||||||
@ -454,7 +454,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
|
|||||||
renderCategoryTabs();ensureCatalogTools();const catalogSearch=$('sunCatalogSearch');if(catalogSearch){const boxMode=[0,5].includes(Number(activeCat));catalogSearch.placeholder=boxMode?'Поиск по № бокса':'Поиск по позиции';catalogSearch.inputMode=boxMode?'numeric':'search';}const title=document.querySelector('#new .catalog h1');if(title)title.textContent=catName(activeCat);
|
renderCategoryTabs();ensureCatalogTools();const catalogSearch=$('sunCatalogSearch');if(catalogSearch){const boxMode=[0,5].includes(Number(activeCat));catalogSearch.placeholder=boxMode?'Поиск по № бокса':'Поиск по позиции';catalogSearch.inputMode=boxMode?'numeric':'search';}const title=document.querySelector('#new .catalog h1');if(title)title.textContent=catName(activeCat);
|
||||||
const all=boxes.filter(item=>Number(item.category||0)===Number(activeCat)),items=all.filter(item=>itemMatches(item,catalogQuery));const cat=catById(activeCat)||{name:'Каталог',prep:true};
|
const all=boxes.filter(item=>Number(item.category||0)===Number(activeCat)),items=all.filter(item=>itemMatches(item,catalogQuery));const cat=catById(activeCat)||{name:'Каталог',prep:true};
|
||||||
if(Number(activeCat)===BANQUET_CATEGORY){$('tiles').innerHTML=renderBanquetView(items);renderOrderLines();updateOrderSummary();return;}
|
if(Number(activeCat)===BANQUET_CATEGORY){$('tiles').innerHTML=renderBanquetView(items);renderOrderLines();updateOrderSummary();return;}
|
||||||
const cards=items.map(item=>`<button class="tile" type="button" onclick="add('${esc(item.id)}')" title="Добавить в заказ">${item.photo?`<img src="${esc(item.photo)}" alt="" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='sun-logo.png'">`:'<div class="ph"><img src="sun-logo.png" class="sun-ph-logo" alt="Логотип Солнце Кейтеринг"></div>'}<span>${esc(item.name)}</span>${item.catalogSection?`<small class="tile-section">${esc(item.catalogSection)}</small>`:''}${(item.weight||inferBoxPieces(item))?`<small class="tile-meta">${item.weight?`Вес: ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`${inferBoxPieces(item)} шт.`:''}</small>`:''}<span class="tile-price-wrap"><small class="tile-price">${money(item.price||0)}</small>${Number(item.oldPrice||0)>Number(item.price||0)?`<small class="old-price">${money(item.oldPrice)}</small>`:''}</span>${Number(item.oldPrice||0)>Number(item.price||0)?`<span class="sale-badge">АКЦИЯ</span>`:''}</button>`).join('');
|
const cards=items.map(item=>`<button class="tile" type="button" onclick="add(${SunSafe.jsArg(item.id)})" title="Добавить в заказ">${item.photo?`<img src="${esc(item.photo)}" alt="" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='sun-logo.png'">`:'<div class="ph"><img src="sun-logo.png" class="sun-ph-logo" alt="Логотип Солнце Кейтеринг"></div>'}<span>${esc(item.name)}</span>${item.catalogSection?`<small class="tile-section">${esc(item.catalogSection)}</small>`:''}${(item.weight||inferBoxPieces(item))?`<small class="tile-meta">${item.weight?`Вес: ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`${inferBoxPieces(item)} шт.`:''}</small>`:''}<span class="tile-price-wrap"><small class="tile-price">${money(item.price||0)}</small>${Number(item.oldPrice||0)>Number(item.price||0)?`<small class="old-price">${money(item.oldPrice)}</small>`:''}</span>${Number(item.oldPrice||0)>Number(item.price||0)?`<span class="sale-badge">АКЦИЯ</span>`:''}</button>`).join('');
|
||||||
const addText=Number(activeCat)===0?'Добавить бокс':(Number(activeCat)===5?'Добавить премиум':'Добавить позицию');
|
const addText=Number(activeCat)===0?'Добавить бокс':(Number(activeCat)===5?'Добавить премиум':'Добавить позицию');
|
||||||
const empty=items.length?'':`<div class="catalog-empty">${catalogQuery?'По вашему запросу ничего не найдено.':`В разделе «${esc(cat.name)}» пока нет позиций.`}</div>`;
|
const empty=items.length?'':`<div class="catalog-empty">${catalogQuery?'По вашему запросу ничего не найдено.':`В разделе «${esc(cat.name)}» пока нет позиций.`}</div>`;
|
||||||
$('tiles').innerHTML=`<button class="tile add" type="button" onclick="editBox(null)">+<br>${addText}</button>${cards}${empty}`;
|
$('tiles').innerHTML=`<button class="tile add" type="button" onclick="editBox(null)">+<br>${addText}</button>${cards}${empty}`;
|
||||||
@ -471,7 +471,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
|
|||||||
function renderManagerV5(){
|
function renderManagerV5(){
|
||||||
ensureManagerToolbar();const managerSearch=$('sunManagerSearch');if(managerSearch){const boxMode=[0,5].includes(Number(activeCat));managerSearch.placeholder=boxMode?'Поиск по № бокса':'Поиск по позиции';managerSearch.inputMode=boxMode?'numeric':'search';}const title=document.querySelector('#manager .dialog-head h2'),add=document.querySelector('#manager .sun-manager-toolbar .primary')||document.querySelector('#manager .primary');if(title)title.textContent=catName(activeCat);if(add){add.textContent=Number(activeCat)===0?'Добавить бокс':(Number(activeCat)===5?'Добавить премиум':'Добавить позицию');add.onclick=()=>window.editBox(null)}
|
ensureManagerToolbar();const managerSearch=$('sunManagerSearch');if(managerSearch){const boxMode=[0,5].includes(Number(activeCat));managerSearch.placeholder=boxMode?'Поиск по № бокса':'Поиск по позиции';managerSearch.inputMode=boxMode?'numeric':'search';}const title=document.querySelector('#manager .dialog-head h2'),add=document.querySelector('#manager .sun-manager-toolbar .primary')||document.querySelector('#manager .primary');if(title)title.textContent=catName(activeCat);if(add){add.textContent=Number(activeCat)===0?'Добавить бокс':(Number(activeCat)===5?'Добавить премиум':'Добавить позицию');add.onclick=()=>window.editBox(null)}
|
||||||
const items=boxes.filter(i=>Number(i.category||0)===Number(activeCat)&&itemMatches(i,managerQuery)),cat=catById(activeCat)||{prep:true};
|
const items=boxes.filter(i=>Number(i.category||0)===Number(activeCat)&&itemMatches(i,managerQuery)),cat=catById(activeCat)||{prep:true};
|
||||||
$('managerList').innerHTML=items.length?items.map(item=>`<button type="button" onclick="editBox('${esc(item.id)}')">${item.photo?`<img src="${esc(item.photo)}" alt="" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='sun-logo.png'">`:'<div class="ph"><img src="sun-logo.png" class="sun-ph-logo" alt="Логотип Солнце Кейтеринг"></div>'}<b>${esc(item.name)}</b><span class="manager-price-wrap"><small class="manager-card-price">${money(item.price||0)}</small>${Number(item.oldPrice||0)>Number(item.price||0)?`<small class="old-price">${money(item.oldPrice)}</small>`:''}</span>${(item.weight||inferBoxPieces(item))?`<small class="manager-card-meta">${item.weight?`Вес: ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`${inferBoxPieces(item)} шт.`:''}</small>`:''}${cat.prep?`<small>${(item.ingredients||[]).length} позиций в составе</small>`:''}</button>`).join(''):'<p class="empty">Ничего не найдено.</p>';
|
$('managerList').innerHTML=items.length?items.map(item=>`<button type="button" onclick="editBox(${SunSafe.jsArg(item.id)})">${item.photo?`<img src="${esc(item.photo)}" alt="" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='sun-logo.png'">`:'<div class="ph"><img src="sun-logo.png" class="sun-ph-logo" alt="Логотип Солнце Кейтеринг"></div>'}<b>${esc(item.name)}</b><span class="manager-price-wrap"><small class="manager-card-price">${money(item.price||0)}</small>${Number(item.oldPrice||0)>Number(item.price||0)?`<small class="old-price">${money(item.oldPrice)}</small>`:''}</span>${(item.weight||inferBoxPieces(item))?`<small class="manager-card-meta">${item.weight?`Вес: ${esc(item.weight)}`:''}${item.weight&&inferBoxPieces(item)?' · ':''}${inferBoxPieces(item)?`${inferBoxPieces(item)} шт.`:''}</small>`:''}${cat.prep?`<small>${(item.ingredients||[]).length} позиций в составе</small>`:''}</button>`).join(''):'<p class="empty">Ничего не найдено.</p>';
|
||||||
}
|
}
|
||||||
window.openManager=()=>{managerQuery='';ensureManagerToolbar();if($('sunManagerSearch'))$('sunManagerSearch').value='';renderManagerV5();window.modal?.('manager');};
|
window.openManager=()=>{managerQuery='';ensureManagerToolbar();if($('sunManagerSearch'))$('sunManagerSearch').value='';renderManagerV5();window.modal?.('manager');};
|
||||||
window.editBox=id=>{
|
window.editBox=id=>{
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
})[ch]);
|
})[ch]);
|
||||||
const escapeAttr=escapeHTML;
|
const escapeAttr=escapeHTML;
|
||||||
const idToken=value=>String(value??'').replace(/[^a-zA-Z0-9_-]/g,'');
|
const idToken=value=>String(value??'').replace(/[^a-zA-Z0-9_-]/g,'');
|
||||||
|
const jsArg=value=>escapeHTML(JSON.stringify(String(value??'')));
|
||||||
const safeImageSrc=value=>{
|
const safeImageSrc=value=>{
|
||||||
const s=String(value??'').trim();
|
const s=String(value??'').trim();
|
||||||
if(!s)return '';
|
if(!s)return '';
|
||||||
@ -19,7 +20,7 @@
|
|||||||
if(reference&&reference.parentNode===parent)parent.insertBefore(node,reference);else parent.appendChild(node);
|
if(reference&&reference.parentNode===parent)parent.insertBefore(node,reference);else parent.appendChild(node);
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
window.SunSafe=Object.freeze({escapeHTML,escapeAttr,idToken,safeImageSrc,setText,insertBefore});
|
window.SunSafe=Object.freeze({escapeHTML,escapeAttr,idToken,jsArg,safeImageSrc,setText,insertBefore});
|
||||||
|
|
||||||
// Small bootstrap for account/profile UI. Keeping it here makes the account
|
// Small bootstrap for account/profile UI. Keeping it here makes the account
|
||||||
// center available on every Caterium screen without touching the legacy monolith.
|
// center available on every Caterium screen without touching the legacy monolith.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -15,7 +15,7 @@ check((runtime.match(/\/Type \/Catalog/g)||[]).length===0,'runtime contains no P
|
|||||||
check(read('core/pdf-engine.js').includes('595.28')&&read('core/pdf-engine.js').includes('841.89'),'PDF engine uses A4 MediaBox');
|
check(read('core/pdf-engine.js').includes('595.28')&&read('core/pdf-engine.js').includes('841.89'),'PDF engine uses A4 MediaBox');
|
||||||
check([...index.matchAll(/@page\{([^}]*)\}/g)].every(m=>/size:A4/i.test(m[1])),'compact @page rules use A4');
|
check([...index.matchAll(/@page\{([^}]*)\}/g)].every(m=>/size:A4/i.test(m[1])),'compact @page rules use A4');
|
||||||
check(sw.includes('v81-20260912-account-center-loader')&&sw.includes('data-layer-v1773.js')&&sw.includes('server-automation-v1770.js')&&sw.includes('offer-workspace-v1769.js'),'service worker cache is v17.7.3');
|
check(sw.includes('v81-20260912-account-center-loader')&&sw.includes('data-layer-v1773.js')&&sw.includes('server-automation-v1770.js')&&sw.includes('offer-workspace-v1769.js'),'service worker cache is v17.7.3');
|
||||||
check(index.includes('20260916-v18-1-2-banquet-menu-tab')&&index.includes('classic-offer-pdf-v1767.js')&&!index.includes('20260907-v17-6-0-stability-security'),'index cache-busting points to v17.7.3');
|
check(index.includes('20260920-v18-1-3-handler-hardening')&&index.includes('classic-offer-pdf-v1767.js')&&!index.includes('20260907-v17-6-0-stability-security'),'index cache-busting points to v17.7.3');
|
||||||
check(performance.includes('SunAttachmentGuard')&&performance.includes('TARGET=2*1024*1024'),'chat photo auto-compression is versioned');
|
check(performance.includes('SunAttachmentGuard')&&performance.includes('TARGET=2*1024*1024'),'chat photo auto-compression is versioned');
|
||||||
check(performance.includes("rpc('sun_dev_dashboard')")&&performance.includes('server_size')&&performance.includes('storage_size'),'Developer Console server/storage counters are versioned');
|
check(performance.includes("rpc('sun_dev_dashboard')")&&performance.includes('server_size')&&performance.includes('storage_size'),'Developer Console server/storage counters are versioned');
|
||||||
check(performance.includes('MEMORY_REFRESH_MS=30000')&&performance.includes('MEMORY_TIMEOUT_MS=8000')&&performance.includes('memoryPromise'),'Developer Console memory refresh is bounded');
|
check(performance.includes('MEMORY_REFRESH_MS=30000')&&performance.includes('MEMORY_TIMEOUT_MS=8000')&&performance.includes('memoryPromise'),'Developer Console memory refresh is bounded');
|
||||||
@ -65,7 +65,7 @@ check(offerWorkspace.includes('PDF и предпросмотр')&&offerWorkspace
|
|||||||
check(offerWorkspace.includes('SunClassicOfferPDFV1767')&&offerWorkspace.includes('finalGallery=galleryFor'),'custom gallery is injected into PDF renderer');
|
check(offerWorkspace.includes('SunClassicOfferPDFV1767')&&offerWorkspace.includes('finalGallery=galleryFor'),'custom gallery is injected into PDF renderer');
|
||||||
check(releaseManifest.offerWorkspaceTabs===true&&releaseManifest.offerTemplatesSeparateTab===true&&releaseManifest.offerTwoCustomGalleryPhotos===true,'release manifest records offer workspace changes');
|
check(releaseManifest.offerWorkspaceTabs===true&&releaseManifest.offerTemplatesSeparateTab===true&&releaseManifest.offerTwoCustomGalleryPhotos===true,'release manifest records offer workspace changes');
|
||||||
check(pkg.version==='17.7.3','package version is v17.7.3');
|
check(pkg.version==='17.7.3','package version is v17.7.3');
|
||||||
check(index.includes('20260916-v18-1-2-banquet-menu-tab'),'index cache bust is v17.7.3');
|
check(index.includes('20260920-v18-1-3-handler-hardening'),'index cache bust is v17.7.3');
|
||||||
check(sw.includes('v81-20260912-account-center-loader')&&sw.includes('data-layer-v1773.js')&&sw.includes('server-automation-v1770.js'),'PWA caches v17.7.3 client foundation modules');
|
check(sw.includes('v81-20260912-account-center-loader')&&sw.includes('data-layer-v1773.js')&&sw.includes('server-automation-v1770.js'),'PWA caches v17.7.3 client foundation modules');
|
||||||
check(fs.existsSync(path.join(root,'public/core/data-layer-v1773.js'))&&fs.existsSync(path.join(root,'public/core/server-automation-v1770.js')),'data layer and server automation modules exist');
|
check(fs.existsSync(path.join(root,'public/core/data-layer-v1773.js'))&&fs.existsSync(path.join(root,'public/core/server-automation-v1770.js')),'data layer and server automation modules exist');
|
||||||
check(ux.includes('CateriumServerAutomationV1770?.enabled'),'cloud browser auto completion is disabled when server automation is active');
|
check(ux.includes('CateriumServerAutomationV1770?.enabled'),'cloud browser auto completion is disabled when server automation is active');
|
||||||
|
|||||||
@ -29,7 +29,7 @@ if(legacyCount!==60)fail(`legacy catalog photo count ${legacyCount}, expected 60
|
|||||||
const gallery=fs.readdirSync(path.join(pub,'offer-gallery')).filter(x=>/\.jpg$/i.test(x));
|
const gallery=fs.readdirSync(path.join(pub,'offer-gallery')).filter(x=>/\.jpg$/i.test(x));
|
||||||
if(gallery.length!==2)fail(`offer gallery contains ${gallery.length} jpg files, expected 2`);else ok('offer gallery trimmed');
|
if(gallery.length!==2)fail(`offer gallery contains ${gallery.length} jpg files, expected 2`);else ok('offer gallery trimmed');
|
||||||
if(!sw.includes('20260912-account-center-loader')||!sw.includes('login-signature-v1776.js')||!sw.includes('data-layer-v1773.js')||!sw.includes('server-automation-v1770.js')||!sw.includes('offer-workspace-v1769.js')||sw.includes('offer-gallery-data.js'))fail('service worker cache is stale');else ok('PWA cache updated for login refresh');
|
if(!sw.includes('20260912-account-center-loader')||!sw.includes('login-signature-v1776.js')||!sw.includes('data-layer-v1773.js')||!sw.includes('server-automation-v1770.js')||!sw.includes('offer-workspace-v1769.js')||sw.includes('offer-gallery-data.js'))fail('service worker cache is stale');else ok('PWA cache updated for login refresh');
|
||||||
if(html.includes('20260907-v17-6-0-stability-security')||html.includes('20260909-v17-7-3-clients-server-read')||!html.includes('20260916-v18-1-2-banquet-menu-tab')||!html.includes('classic-offer-pdf-v1767.js'))fail('index still serves stale core asset version');else ok('index cache-busting is current');
|
if(html.includes('20260907-v17-6-0-stability-security')||html.includes('20260909-v17-7-3-clients-server-read')||!html.includes('20260920-v18-1-3-handler-hardening')||!html.includes('classic-offer-pdf-v1767.js'))fail('index still serves stale core asset version');else ok('index cache-busting is current');
|
||||||
if(!performance.includes('SunAttachmentGuard')||!performance.includes('MAX_SIDE=2048'))fail('chat photo compression guard missing');else ok('chat photo compression guard present');
|
if(!performance.includes('SunAttachmentGuard')||!performance.includes('MAX_SIDE=2048'))fail('chat photo compression guard missing');else ok('chat photo compression guard present');
|
||||||
if(!performance.includes("rpc('sun_dev_dashboard')")||!performance.includes('storage_size')||!performance.includes('server_size'))fail('Developer Console memory counters missing');else ok('Developer Console memory counters present');
|
if(!performance.includes("rpc('sun_dev_dashboard')")||!performance.includes('storage_size')||!performance.includes('server_size'))fail('Developer Console memory counters missing');else ok('Developer Console memory counters present');
|
||||||
if(performance.includes('records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)scan(n)}));enhanceDeveloperMemory()'))fail('Developer Console memory refresh is still coupled to MutationObserver');else ok('Developer Console memory refresh loop removed');
|
if(performance.includes('records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)scan(n)}));enhanceDeveloperMemory()'))fail('Developer Console memory refresh is still coupled to MutationObserver');else ok('Developer Console memory refresh loop removed');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user