'use strict'; const test=require('node:test'); const assert=require('node:assert/strict'); const ux=require('../app/static/studio-experience-v829.js'); const blocks={hero:{name:'顶部横幅'},richtext:{name:'文字介绍'},collection:{name:'产品列表'},layout:{name:'多列布局'},faq:{name:'常见问题'},gallery:{name:'图片画廊'}}; test('palette groups are useful to a beginner and preserve every block',()=>{ const grouped=ux.groupBlocks(blocks); assert.deepEqual(Object.keys(grouped),['basic','visual','business','advanced']); assert.equal(grouped.visual.some(x=>x.key==='hero'),true); assert.equal(grouped.business.some(x=>x.key==='collection'),true); assert.equal(grouped.advanced.some(x=>x.key==='layout'),true); assert.equal(Object.values(grouped).flat().length,Object.keys(blocks).length); }); test('palette query searches Chinese user facing names and avoids mutation',()=>{ assert.deepEqual(ux.groupBlocks(blocks,'产品').business.map(x=>x.key),['collection']); assert.equal(Object.values(ux.groupBlocks(blocks,'not-found')).flat().length,0); assert.equal(blocks.collection.name,'产品列表'); }); test('theme preview path is limited to approved themes and page types',()=>{ assert.equal(ux.previewUrl('automotive','product'),'/api/factory/themes/automotive/preview?page_type=product'); assert.equal(ux.previewUrl('../admin','home'),null); assert.equal(ux.previewUrl('corporate','javascript:alert(1)'),null); assert.equal(ux.previewUrl('minimal','about'),'/api/factory/themes/minimal/preview?page_type=about'); }); test('three visual style presets keep schema-safe values',()=>{ for(const theme of ['automotive','industrial','corporate','minimal']){ for(const preset of ['clean','soft','feature']){ const style=ux.stylePreset(theme,preset); assert.match(style.background,/^#[a-f0-9]{6}$/i); assert.match(style.text_color,/^#[a-f0-9]{6}$/i); assert.equal(Number.isInteger(style.padding),true); assert.ok(style.padding>=0&&style.padding<=120); } } assert.equal(ux.stylePreset('minimal','