import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import {chromium,expect} from '@playwright/test'; import {trainingInit} from './training-catalog-fixture.mjs'; // Exercise the actual published assets with a synthetic profile. All traffic // except same-origin static GETs is blocked, so no real workspace is touched. const base=new URL(process.env.TIMEWEB_BASE_URL||'https://app.caterium.ru'); if(base.protocol!=='https:')throw new Error('Published UI verification requires HTTPS'); const output='production-ui-results';await fs.mkdir(output,{recursive:true}); const browser=await chromium.launch(),results=[]; try{ for(const width of [390,1440]){ const context=await browser.newContext({viewport:{width,height:900},serviceWorkers:'block'}); try{ await context.route('**/*',route=>{const r=route.request(),u=new URL(r.url());return r.method()==='GET'&&u.origin===base.origin&&!u.pathname.startsWith('/api/')?route.continue():route.abort();}); await context.addInitScript(trainingInit); const page=await context.newPage();page.on('dialog',d=>d.accept()); await page.goto(base.href,{waitUntil:'domcontentloaded',timeout:60000}); await expect(page.locator('body > header')).toBeVisible({timeout:20000}); await page.waitForFunction(()=>window.CateriumDataV1773&&window.SunOpsUXV1762&&window.CateriumTrialDemo&&window.CateriumTrainingCatalog); const nav=page.locator('header nav'),toggle=page.locator('#ctTrainingEnabled'); const settings=async()=>{await nav.getByRole('button',{name:'Настройки',exact:true}).click();await expect(toggle).toBeVisible();}; await settings();await expect(toggle).not.toBeChecked(); const before=await page.evaluate(()=>({orders:localStorage.sunOrders,box:boxes.find(b=>b.id==='own-box'),stock:JSON.parse(localStorage.sunStock).find(p=>p.id==='own-stock')})); await toggle.check();await expect(toggle).toBeEnabled(); await expect.poll(()=>page.evaluate(()=>CateriumTrainingCatalog.enabled())).toBe(true); assert.equal(await page.evaluate(()=>boxes.length),45); await page.locator('#ctTrainingSettings').scrollIntoViewIfNeeded(); await page.screenshot({path:`${output}/training-settings-${width}.png`,animations:'disabled'}); await nav.getByRole('button',{name:'Меню',exact:true}).click();await expect(page.locator('[data-menu-item-v1762]')).toHaveCount(11); await expect(page.locator('[data-menu-item-v1762="demo-v1-bruschetta-tomato"] .ct-training-badge')).toHaveText('Учебное'); await page.screenshot({path:`${output}/training-catalog-${width}.png`,animations:'disabled'}); await settings();await toggle.uncheck();await expect(toggle).toBeEnabled(); await expect.poll(()=>page.evaluate(()=>CateriumTrainingCatalog.enabled())).toBe(false); await nav.getByRole('button',{name:'Меню',exact:true}).click();await expect(page.locator('[data-menu-item-v1762]')).toHaveCount(1); const after=await page.evaluate(()=>({orders:localStorage.sunOrders,box:boxes.find(b=>b.id==='own-box'),stock:JSON.parse(localStorage.sunStock).find(p=>p.id==='own-stock')})); assert.deepEqual(after,before); assert.equal(await page.evaluate(()=>boxes.length),45); await settings();await toggle.check();await expect(toggle).toBeEnabled(); assert.equal(await page.evaluate(()=>boxes.length),45); results.push({width,defaultOff:true,readyExamples:44,hideRestoresOwnCatalog:true,repeatDoesNotDuplicate:true,ordersAndOwnDataPreserved:true}); console.log(`PASS published training catalog ${width}px: opt-in, complete examples, hide/show, preserved own data and orders`); }finally{await context.close();} } await fs.writeFile(`${output}/training-catalog-result.json`,JSON.stringify({base:base.href,checkedAt:new Date().toISOString(),backend:'synthetic, network-blocked',results},null,2)); }finally{await browser.close();}