feat: release design system engine, studio and component contracts
This commit is contained in:
1 parent
ff1065fb27
commit
3943b946d6
693 files changed
+175546
-3894
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
@@ -0,0 +1,38 @@
|
||||
const { chromium } = require('C:/Users/ADMIN/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
|
||||
const assert=require('node:assert/strict');
|
||||
(async()=>{
|
||||
const browser=await chromium.launch({headless:true});
|
||||
const page=await browser.newPage({viewport:{width:1200,height:900}});const errors=[];
|
||||
page.on('pageerror',e=>errors.push(e.message));await page.goto('http://localhost:4319/');
|
||||
await page.waitForFunction(()=>window.TestChart && document.querySelectorAll('canvas').length===10 && [...document.querySelectorAll('canvas')].every(c=>window.TestChart.getChart(c)));
|
||||
const charts=await page.evaluate(()=>[...document.querySelectorAll('canvas')].map(c=>{const chart=TestChart.getChart(c);return {type:chart.config.type,width:chart.width,height:chart.height,points:chart.getDatasetMeta(0).data.length,status:c.closest('figure').querySelector('[data-chart-status]').textContent}}));
|
||||
assert.equal(charts.length,10);assert(charts.every(c=>c.width>100&&c.height===260&&c.points>0&&c.status===''));
|
||||
await page.screenshot({path:'output/chartjs-verify/all-chart-types.png',fullPage:true});
|
||||
await page.evaluate(()=>{window.events=[];const root=document.querySelector('figure');for(const name of ['select','dataPointClick','legendToggle'])root.addEventListener(name,e=>events.push({name,index:e.detail.index,datasetIndex:e.detail.datasetIndex,hidden:e.detail.hidden}));});
|
||||
const point=await page.evaluate(()=>{const c=document.querySelector('canvas'),chart=TestChart.getChart(c),p=chart.getDatasetMeta(0).data[1],r=c.getBoundingClientRect();return {x:r.x+p.x,y:r.y+p.y+5};});
|
||||
await page.mouse.click(point.x,point.y);await page.waitForTimeout(100);
|
||||
const legend=await page.evaluate(()=>{const c=document.querySelector('canvas'),chart=TestChart.getChart(c),p=chart.legend.legendHitBoxes[0],r=c.getBoundingClientRect();return {x:r.x+p.left+5,y:r.y+p.top+5}});
|
||||
await page.mouse.click(legend.x,legend.y);await page.waitForTimeout(100);
|
||||
assert.deepEqual((await page.evaluate(()=>events)).map(e=>e.name),['dataPointClick','select','legendToggle']);
|
||||
await page.evaluate(()=>{const root=document.querySelector('figure'),config=JSON.parse(root.dataset.chartConfig);config.data.datasets[0].data[0]=-50;root.dataset.chartConfig=JSON.stringify(config);});
|
||||
await page.waitForFunction(()=>TestChart.getChart(document.querySelector('canvas')).data.datasets[0].data[0]===-50);
|
||||
await page.evaluate(()=>{const root=document.querySelector('figure'),config=JSON.parse(root.dataset.chartConfig);config.type='doughnut';root.dataset.chartConfig=JSON.stringify(config)});
|
||||
await page.waitForFunction(()=>TestChart.getChart(document.querySelector('canvas')).config.type==='doughnut');
|
||||
// Arc legends toggle individual slices.
|
||||
await page.evaluate(()=>{const chart=TestChart.getChart(document.querySelector('canvas'));chart.options.plugins.legend.onClick({native:null},chart.legend.legendItems[0],chart.legend)});
|
||||
assert.equal(await page.evaluate(()=>TestChart.getChart(document.querySelector('canvas')).getDataVisibility(0)),false);
|
||||
await page.setViewportSize({width:390,height:844});await page.waitForTimeout(250);
|
||||
assert(await page.evaluate(()=>[...document.querySelectorAll('canvas')].every(c=>TestChart.getChart(c).width<=350)));
|
||||
await page.screenshot({path:'output/chartjs-verify/charts-mobile.png',fullPage:true});
|
||||
await page.setViewportSize({width:1200,height:900});await page.waitForTimeout(250);await page.screenshot({path:'output/chartjs-verify/charts-desktop.png',fullPage:true});
|
||||
await page.evaluate(()=>{window.removed=document.querySelector('canvas');removed.closest('figure').remove()});
|
||||
await page.waitForFunction(()=>!TestChart.getChart(removed));
|
||||
await page.evaluate(()=>{const root=document.querySelector('figure'),config=JSON.parse(root.dataset.chartConfig);config.type='invalid';root.dataset.chartConfig=JSON.stringify(config);window.badRoot=root});
|
||||
await page.waitForFunction(()=>badRoot.querySelector('[data-chart-status]').textContent.includes('Unsupported chart type'));
|
||||
await page.waitForTimeout(100);
|
||||
await page.evaluate(()=>{const config=JSON.parse(badRoot.dataset.chartConfig);config.type='line';config.options.plugins=false;badRoot.dataset.chartConfig=JSON.stringify(config)});
|
||||
await page.waitForFunction(()=>TestChart.getChart(badRoot.querySelector('canvas'))?.config.type==='line');
|
||||
assert.deepEqual(errors,[]);
|
||||
console.log(JSON.stringify({rendered:charts,checks:['point outputs','legend outputs','reactive data update','chart type switch','arc legend','mobile resize','destroy on removal'],errors},null,2));
|
||||
await browser.close();
|
||||
})().catch(e=>{console.error(e);process.exit(1)});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
@@ -0,0 +1,4 @@
|
||||
import Chart from '../../packages/ui/node_modules/chart.js/auto/auto.js';
|
||||
import '../../packages/ui/src/chart-runtime';
|
||||
(window as any).TestChart = Chart;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
const {chromium}=require('C:/Users/ADMIN/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
|
||||
const assert=require('node:assert/strict');
|
||||
(async()=>{const browser=await chromium.launch({headless:true});const page=await browser.newPage({viewport:{width:1440,height:1000}});const errors=[];page.on('pageerror',e=>errors.push(e.message));await page.goto('http://localhost:4320/components/chart');await page.waitForFunction(()=>document.querySelectorAll('[data-chart-canvas]').length===12&&[...document.querySelectorAll('[data-chart-canvas]')].every(c=>c.style.width));await page.waitForTimeout(500);
|
||||
const results=await page.evaluate(()=>[...document.querySelectorAll('[data-ui-component="Chart"]')].map(root=>{const c=root.querySelector('canvas');const pixels=c.getContext('2d').getImageData(0,0,c.width,c.height).data;return {type:JSON.parse(root.dataset.chartConfig).type,width:c.clientWidth,height:c.clientHeight,rendered:pixels.some((v,i)=>i%4===3&&v>0),status:root.querySelector('[data-chart-status]').textContent,table:root.querySelectorAll('table tr').length}}));assert.equal(results.length,12);assert(results.every(r=>r.width>0&&r.rendered&&r.status===''&&r.table>1));
|
||||
await page.locator('#chart-demo-1').screenshot({path:'output/chartjs-verify/showcase-bar.png'});await page.locator('#chart-demo-8').screenshot({path:'output/chartjs-verify/showcase-scatter.png'});
|
||||
assert.deepEqual(errors,[]);console.log(JSON.stringify({productionCharts:results,errors},null,2));await browser.close()})().catch(e=>{console.error(e);process.exit(1)});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { resolve, join } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { validateAndHashStage } from '../../scripts/lib/package-integrity';
|
||||
const root=resolve('.'), registry=process.env.WRNEXUS_NPM_REGISTRY;
|
||||
if(registry!=='https://registry.workroot.in/repository/npm/') throw new Error('Unexpected release registry');
|
||||
const npmCli='D:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js';
|
||||
function npm(args:string[],allowFailure=false){
|
||||
const result=spawnSync('node',[npmCli,'--registry',registry!,...args],{cwd:root,encoding:'utf8'});
|
||||
if(result.error)throw result.error;
|
||||
if(result.status!==0&&!allowFailure)throw new Error(result.stderr||result.stdout||'npm failed');
|
||||
return result;
|
||||
}
|
||||
const release=JSON.parse(readFileSync('.publish/PACKAGE-INTEGRITY.json','utf8'));
|
||||
const packed=[];const destination=resolve('output/chart-release-tarballs');mkdirSync(destination,{recursive:true});
|
||||
for(const expected of release.packages){
|
||||
const stage=join(root,'.publish',expected.name.replace('@wrnexus/',''));
|
||||
const manifest=JSON.parse(readFileSync(join(stage,'package.json'),'utf8'));
|
||||
if(JSON.stringify(validateAndHashStage(stage,manifest))!==JSON.stringify(expected))throw new Error('Staged package changed: '+expected.name);
|
||||
const info=JSON.parse(npm(['pack',stage,'--pack-destination',destination,'--json']).stdout)[0];
|
||||
const existing=npm(['view',expected.name+'@'+expected.version,'dist.integrity','--json'],true);
|
||||
let published=false;
|
||||
if(existing.status===0){
|
||||
if(JSON.parse(existing.stdout)!==info.integrity)throw new Error('Version already contains different bytes: '+expected.name+'@'+expected.version);
|
||||
published=true;
|
||||
}else if(!/E404|404 Not Found/.test(existing.stderr))throw new Error('Registry preflight failed: '+existing.stderr);
|
||||
packed.push({name:expected.name,version:expected.version,path:join(destination,info.filename),integrity:info.integrity,published});
|
||||
}
|
||||
writeFileSync('output/chart-release-manifest.json',JSON.stringify(packed,null,2)+'\n');
|
||||
for(const pkg of packed){
|
||||
if(!pkg.published){
|
||||
console.log('Publishing '+pkg.name+'@'+pkg.version);
|
||||
const result=npm(['publish',pkg.path,'--access','restricted']);
|
||||
process.stdout.write(result.stdout);
|
||||
}
|
||||
const remote=JSON.parse(npm(['view',pkg.name+'@'+pkg.version,'dist.integrity','--json']).stdout);
|
||||
if(remote!==pkg.integrity)throw new Error('Published integrity mismatch: '+pkg.name);
|
||||
console.log('Verified '+pkg.name+'@'+pkg.version);
|
||||
}
|
||||
console.log('Published and verified '+packed.length+' private packages.');
|
||||
@@ -0,0 +1,16 @@
|
||||
import {readFileSync} from 'node:fs';
|
||||
import {renderComponent} from '../../packages/test/src/index';
|
||||
import {getReactiveRuntime,getComponentControllerRuntime} from '../../packages/csr/src/index';
|
||||
const source=readFileSync('packages/ui/components/Chart.wrn','utf8');
|
||||
const types=['bar','line','area','pie','doughnut','radar','polarArea','scatter','bubble','mixed'];
|
||||
const bundle=await Bun.build({entrypoints:['output/chartjs-verify/entry.ts'],target:'browser',minify:false});
|
||||
if(!bundle.success) throw new Error(String(bundle.logs));
|
||||
const js=await bundle.outputs[0].text();
|
||||
let html='<!doctype html><html><head><style>body{font:14px Arial;background:#f7f7f8;margin:20px}main{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}figure{background:white;padding:20px;margin:0}canvas{max-width:100%}.wrn-chart__stage{position:relative}.wrn-chart__accessible{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}@media(max-width:600px){main{grid-template-columns:1fr}}</style></head><body><main>';
|
||||
for(const type of types){
|
||||
const data=type==='scatter'||type==='bubble'?{datasets:[{label:'Coordinates',data:[{x:1,y:4,r:8},{x:3,y:8,r:16},{x:5,y:3,r:12}]}]}:{labels:['Mon','Tue','Wed','Thu','Fri'],datasets:[{label:'Sample',data:type==='bar'?[-20,38,29,52,45]:[24,38,29,52,45]},...(type==='mixed'?[{type:'line',label:'Target',data:[25,30,40,45,50]}]:[])]};
|
||||
html+=await renderComponent(source,{title:type,description:'Sample data',type:type==='mixed'?'bar':type,data,showValues:false,options:{animation:false},height:260});
|
||||
}
|
||||
html+='</main><script src="/csr.js"></script><script type="module" src="/chart.js"></script></body></html>';
|
||||
const server=Bun.serve({port:4319,fetch(req){const path=new URL(req.url).pathname;return new Response(path==='/chart.js'?js:path==='/csr.js'?getReactiveRuntime()+'\n'+getComponentControllerRuntime():html,{headers:{'Content-Type':path.endsWith('.js')?'text/javascript':'text/html'}})}});
|
||||
console.log('Chart verification listening on '+server.url);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Reference in new issue
Block a user