52 lines
3.1 KiB
JavaScript
52 lines
3.1 KiB
JavaScript
|
|
const test=require('node:test');
|
||
|
|
const assert=require('node:assert/strict');
|
||
|
|
const H=require('../app/static/editor-helpers.js');
|
||
|
|
function sample(){return [
|
||
|
|
{id:'root1111',type:'layout',columns:[
|
||
|
|
{width:1,blocks:[{id:'inner2222',type:'layout',gap:20,columns:[
|
||
|
|
{width:1,blocks:[{id:'deep3333',type:'image_text',title:'Original',description:'Text'}]},
|
||
|
|
{width:1,blocks:[{id:'deep4444',type:'cta',title:'CTA'}]}]}]},
|
||
|
|
{width:1,blocks:[{id:'shallow5',type:'features',title:'Features'}]}
|
||
|
|
]},
|
||
|
|
{id:'otherRoot',type:'layout',columns:[{width:1,blocks:[{id:'foreign6',type:'cta',title:'Other'}]}]}
|
||
|
|
]}
|
||
|
|
const types={image_text:{fields:['title','description']},cta:{fields:['title']},layout:{fields:['columns']},features:{fields:['title']}};
|
||
|
|
test('locate second-level block by immediate parent and id, not client-supplied indexes',()=>{
|
||
|
|
let rows=sample();let f=H.findNestedChild(rows,'inner2222','deep3333');
|
||
|
|
assert.equal(f.parentIndex,0);assert.equal(f.depth,1);assert.equal(f.parent.id,'inner2222');
|
||
|
|
assert.equal(f.child.title,'Original');assert.deepEqual(f.ancestors,['root1111','inner2222']);
|
||
|
|
assert.equal(H.findNestedChild(rows,'root1111','deep3333'),null);
|
||
|
|
assert.equal(H.findNestedChild(rows,'otherRoot','deep3333'),null);
|
||
|
|
assert.equal(H.findChildInRoot(rows,'root1111','deep3333').child.id,'deep3333');
|
||
|
|
assert.equal(H.findChildInRoot(rows,'otherRoot','deep3333'),null);
|
||
|
|
});
|
||
|
|
test('only allow safe operations and supported inline text changes',()=>{
|
||
|
|
const rows=sample();const ok={action:'child-inline-text',blockId:'inner2222',childId:'deep3333',field:'title',value:'Safe title'};
|
||
|
|
assert.equal(H.safeNestedCanvasCommand(ok,rows,types),true);
|
||
|
|
assert.equal(H.safeNestedCanvasCommand({...ok,field:'body'},rows,types),false);
|
||
|
|
assert.equal(H.safeNestedCanvasCommand({...ok,field:'title',value:'x'.repeat(501)},rows,types),false);
|
||
|
|
assert.equal(H.safeNestedCanvasCommand({...ok,blockId:'root1111'},rows,types),false);
|
||
|
|
assert.equal(H.safeNestedCanvasCommand({...ok,action:'child-script'},rows,types),false);
|
||
|
|
assert.equal(H.safeNestedCanvasCommand({...ok,childId:'foreign6'},rows,types),false);
|
||
|
|
});
|
||
|
|
test('nested layout resolution preserves site/page boundaries and width constraints',()=>{
|
||
|
|
let rows=sample();let inner=H.findLayout(rows,'inner2222');
|
||
|
|
assert.equal(inner.rootIndex,0);assert.equal(inner.depth,1);
|
||
|
|
assert.equal(H.findLayout(rows,'shallow5'),null);
|
||
|
|
assert.deepEqual(H.layoutPreset(inner.layout,'left-wide'),[2,1]);
|
||
|
|
assert.deepEqual(H.adjacentWidths(inner.layout,[2,1]),[2,1]);
|
||
|
|
assert.equal(H.adjacentWidths(inner.layout,[.1,1]),null);
|
||
|
|
assert.equal(H.findLayout(rows,'nonexistent'),null);
|
||
|
|
assert.equal(H.findLayout(rows,'otherRoot').rootIndex,1);
|
||
|
|
});
|
||
|
|
test('duplication rewrites all nested IDs and reordering is scoped',()=>{
|
||
|
|
const rows=sample(),seen=[];
|
||
|
|
const copy=H.duplicate(rows[0].columns[0].blocks[0],()=>('copy'+(++seen.length)).padEnd(8,'z'));
|
||
|
|
assert.equal(copy.type,'layout');
|
||
|
|
assert.notEqual(copy.id,rows[0].columns[0].blocks[0].id);
|
||
|
|
assert.notEqual(copy.columns[0].blocks[0].id,'deep3333');
|
||
|
|
const original=rows[0].columns[0].blocks[0].columns[0].blocks;
|
||
|
|
assert.equal(H.moveNested(rows[0].columns[0].blocks[0],0,0,-1),null);
|
||
|
|
assert.equal(original[0].id,'deep3333');
|
||
|
|
});
|