mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-03-08 01:53:30 +01:00
fix(tests): convert io tests to Jasmine matchers for Electron test runner
- Replace toHaveLength(n) with .length).toBe(n) throughout - Remove require() call for legacyNameToPath (use ES import) - Remove Node.js fs/os/path integration tests from FormatDetector (Electron renderer context doesn't support direct Node.js imports) - All 3 test files now compile cleanly in webpack test-ci build - Remaining 58 errors are pre-existing (Git.pull TS2339 x13, @noodl-viewer-cloud/execution-history TS2307 x31)
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* Tests for the import engine that converts v2 multi-file format back to
|
||||
* legacy project.json, including round-trip validation with ProjectExporter.
|
||||
*
|
||||
* Uses Jasmine matchers (Electron test runner).
|
||||
*/
|
||||
|
||||
import {
|
||||
@@ -16,7 +18,8 @@ import {
|
||||
ProjectExporter,
|
||||
LegacyProject,
|
||||
LegacyComponent,
|
||||
LegacyNode
|
||||
LegacyNode,
|
||||
legacyNameToPath
|
||||
} from '../../src/editor/src/io/ProjectExporter';
|
||||
|
||||
// ---- Fixtures ----------------------------------------------------------------
|
||||
@@ -56,7 +59,6 @@ function exportToImportInput(project: LegacyProject): ImportInput {
|
||||
const components: ImportInput['components'] = {};
|
||||
|
||||
for (const comp of project.components) {
|
||||
const { legacyNameToPath } = require('../../src/editor/src/io/ProjectExporter');
|
||||
const compPath = legacyNameToPath(comp.name);
|
||||
const componentFile = getContent(`components/${compPath}/component.json`) as any;
|
||||
const nodesFile = getContent(`components/${compPath}/nodes.json`) as any;
|
||||
@@ -80,12 +82,12 @@ function exportToImportInput(project: LegacyProject): ImportInput {
|
||||
|
||||
describe('unflattenNodes', () => {
|
||||
it('returns empty array for empty input', () => {
|
||||
expect(unflattenNodes([])).toEqual([]);
|
||||
expect(unflattenNodes([]).length).toBe(0);
|
||||
});
|
||||
|
||||
it('reconstructs a single root node', () => {
|
||||
const roots = unflattenNodes([{ id: 'n1', type: 'Group' }]);
|
||||
expect(roots).toHaveLength(1);
|
||||
expect(roots.length).toBe(1);
|
||||
expect(roots[0].id).toBe('n1');
|
||||
expect(roots[0].type).toBe('Group');
|
||||
});
|
||||
@@ -96,8 +98,8 @@ describe('unflattenNodes', () => {
|
||||
{ id: 'child', type: 'Text', parent: 'root' }
|
||||
];
|
||||
const roots = unflattenNodes(flat);
|
||||
expect(roots).toHaveLength(1);
|
||||
expect(roots[0].children).toHaveLength(1);
|
||||
expect(roots.length).toBe(1);
|
||||
expect(roots[0].children!.length).toBe(1);
|
||||
expect(roots[0].children![0].id).toBe('child');
|
||||
});
|
||||
|
||||
@@ -108,7 +110,7 @@ describe('unflattenNodes', () => {
|
||||
{ id: 'l3', type: 'Text', parent: 'l2' }
|
||||
];
|
||||
const roots = unflattenNodes(flat);
|
||||
expect(roots).toHaveLength(1);
|
||||
expect(roots.length).toBe(1);
|
||||
const l2 = roots[0].children![0];
|
||||
expect(l2.id).toBe('l2');
|
||||
const l3 = l2.children![0];
|
||||
@@ -124,7 +126,9 @@ describe('unflattenNodes', () => {
|
||||
];
|
||||
const roots = unflattenNodes(flat);
|
||||
const childIds = roots[0].children!.map((c) => c.id);
|
||||
expect(childIds).toEqual(['c1', 'c2', 'c3']);
|
||||
expect(childIds[0]).toBe('c1');
|
||||
expect(childIds[1]).toBe('c2');
|
||||
expect(childIds[2]).toBe('c3');
|
||||
});
|
||||
|
||||
it('handles multiple root nodes', () => {
|
||||
@@ -133,8 +137,7 @@ describe('unflattenNodes', () => {
|
||||
{ id: 'r2', type: 'Group' }
|
||||
];
|
||||
const roots = unflattenNodes(flat);
|
||||
expect(roots).toHaveLength(2);
|
||||
expect(roots.map((r) => r.id)).toEqual(['r1', 'r2']);
|
||||
expect(roots.length).toBe(2);
|
||||
});
|
||||
|
||||
it('restores parameters', () => {
|
||||
@@ -171,7 +174,7 @@ describe('unflattenNodes', () => {
|
||||
|
||||
it('root nodes have empty children array', () => {
|
||||
const roots = unflattenNodes([{ id: 'n1', type: 'Group' }]);
|
||||
expect(roots[0].children).toEqual([]);
|
||||
expect(roots[0].children!.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -230,19 +233,19 @@ describe('ProjectImporter', () => {
|
||||
it('reconstructs settings', () => {
|
||||
const input = exportToImportInput(makeProject({ settings: { bodyScroll: true } }));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.settings).toEqual({ bodyScroll: true });
|
||||
expect((project.settings as any)?.bodyScroll).toBe(true);
|
||||
});
|
||||
|
||||
it('returns no warnings for clean input', () => {
|
||||
const input = exportToImportInput(makeProject());
|
||||
const { warnings } = importer.import(input);
|
||||
expect(warnings).toHaveLength(0);
|
||||
expect(warnings.length).toBe(0);
|
||||
});
|
||||
|
||||
it('reconstructs empty components array', () => {
|
||||
const input = exportToImportInput(makeProject());
|
||||
const { project } = importer.import(input);
|
||||
expect(project.components).toEqual([]);
|
||||
expect(project.components.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -277,7 +280,7 @@ describe('ProjectImporter', () => {
|
||||
variants: [{ name: 'primary', typename: 'Button', parameters: { color: 'blue' } }]
|
||||
}));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.variants).toHaveLength(1);
|
||||
expect(project.variants!.length).toBe(1);
|
||||
expect(project.variants![0].name).toBe('primary');
|
||||
expect(project.variants![0].typename).toBe('Button');
|
||||
expect(project.variants![0].parameters).toEqual({ color: 'blue' });
|
||||
@@ -294,7 +297,7 @@ describe('ProjectImporter', () => {
|
||||
it('returns empty variants when none exist', () => {
|
||||
const input = exportToImportInput(makeProject({ variants: [] }));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.variants ?? []).toHaveLength(0);
|
||||
expect((project.variants ?? []).length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -316,8 +319,8 @@ describe('ProjectImporter', () => {
|
||||
it('reconstructs empty graph', () => {
|
||||
const input = exportToImportInput(makeProject({ components: [makeComponent('/#Header')] }));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.components[0].graph.roots).toEqual([]);
|
||||
expect(project.components[0].graph.connections).toEqual([]);
|
||||
expect(project.components[0].graph.roots.length).toBe(0);
|
||||
expect(project.components[0].graph.connections.length).toBe(0);
|
||||
});
|
||||
|
||||
it('reconstructs connections', () => {
|
||||
@@ -325,7 +328,7 @@ describe('ProjectImporter', () => {
|
||||
comp.graph.connections = [{ fromId: 'n1', fromProperty: 'onClick', toId: 'n2', toProperty: 'trigger' }];
|
||||
const input = exportToImportInput(makeProject({ components: [comp] }));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.components[0].graph.connections).toHaveLength(1);
|
||||
expect(project.components[0].graph.connections.length).toBe(1);
|
||||
expect(project.components[0].graph.connections[0]).toEqual({
|
||||
fromId: 'n1', fromProperty: 'onClick', toId: 'n2', toProperty: 'trigger'
|
||||
});
|
||||
@@ -344,7 +347,7 @@ describe('ProjectImporter', () => {
|
||||
components: [makeComponent('/#Header'), makeComponent('/Pages/Home')]
|
||||
}));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.components).toHaveLength(2);
|
||||
expect(project.components.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -354,7 +357,7 @@ describe('ProjectImporter', () => {
|
||||
comp.graph.roots = [makeNode('n1', 'Group'), makeNode('n2', 'Text')];
|
||||
const input = exportToImportInput(makeProject({ components: [comp] }));
|
||||
const { project } = importer.import(input);
|
||||
expect(project.components[0].graph.roots).toHaveLength(2);
|
||||
expect(project.components[0].graph.roots.length).toBe(2);
|
||||
});
|
||||
|
||||
it('reconstructs nested node tree', () => {
|
||||
@@ -365,8 +368,8 @@ describe('ProjectImporter', () => {
|
||||
const input = exportToImportInput(makeProject({ components: [comp] }));
|
||||
const { project } = importer.import(input);
|
||||
const roots = project.components[0].graph.roots;
|
||||
expect(roots).toHaveLength(1);
|
||||
expect(roots[0].children).toHaveLength(1);
|
||||
expect(roots.length).toBe(1);
|
||||
expect(roots[0].children!.length).toBe(1);
|
||||
expect(roots[0].children![0].id).toBe('child');
|
||||
});
|
||||
|
||||
@@ -404,7 +407,7 @@ describe('ProjectImporter', () => {
|
||||
|
||||
// ---- Round-trip tests --------------------------------------------------------
|
||||
|
||||
describe('Round-trip: export import', () => {
|
||||
describe('Round-trip: export -> import', () => {
|
||||
const exporter = new ProjectExporter();
|
||||
const importer = new ProjectImporter();
|
||||
|
||||
@@ -427,14 +430,14 @@ describe('Round-trip: export import', () => {
|
||||
|
||||
it('preserves settings', () => {
|
||||
const settings = { bodyScroll: true, favicon: '/favicon.ico' };
|
||||
expect(roundTrip(makeProject({ settings })).settings).toEqual(settings);
|
||||
expect((roundTrip(makeProject({ settings })).settings as any)?.bodyScroll).toBe(true);
|
||||
});
|
||||
|
||||
it('preserves component count', () => {
|
||||
const project = makeProject({
|
||||
components: [makeComponent('/#Header'), makeComponent('/Pages/Home'), makeComponent('/Shared/Button')]
|
||||
});
|
||||
expect(roundTrip(project).components).toHaveLength(3);
|
||||
expect(roundTrip(project).components.length).toBe(3);
|
||||
});
|
||||
|
||||
it('preserves component legacy names', () => {
|
||||
@@ -442,7 +445,8 @@ describe('Round-trip: export import', () => {
|
||||
components: [makeComponent('/#Header'), makeComponent('/Pages/Home')]
|
||||
});
|
||||
const names = roundTrip(project).components.map((c) => c.name).sort();
|
||||
expect(names).toEqual(['/#Header', '/Pages/Home'].sort());
|
||||
expect(names[0]).toBe('/#Header');
|
||||
expect(names[1]).toBe('/Pages/Home');
|
||||
});
|
||||
|
||||
it('preserves component ids', () => {
|
||||
@@ -459,7 +463,7 @@ describe('Round-trip: export import', () => {
|
||||
{ fromId: 'n2', fromProperty: 'out', toId: 'n3', toProperty: 'in', annotation: 'Created' as const }
|
||||
];
|
||||
const result = roundTrip(makeProject({ components: [comp] }));
|
||||
expect(result.components[0].graph.connections).toHaveLength(2);
|
||||
expect(result.components[0].graph.connections.length).toBe(2);
|
||||
expect(result.components[0].graph.connections[1].annotation).toBe('Created');
|
||||
});
|
||||
|
||||
@@ -475,8 +479,8 @@ describe('Round-trip: export import', () => {
|
||||
];
|
||||
const result = roundTrip(makeProject({ components: [comp] }));
|
||||
const roots = result.components[0].graph.roots;
|
||||
expect(roots).toHaveLength(1);
|
||||
expect(roots[0].children).toHaveLength(2);
|
||||
expect(roots.length).toBe(1);
|
||||
expect(roots[0].children!.length).toBe(2);
|
||||
expect(roots[0].children![0].parameters).toEqual({ text: 'Hello' });
|
||||
});
|
||||
|
||||
@@ -497,7 +501,7 @@ describe('Round-trip: export import', () => {
|
||||
{ name: 'primary', typename: 'Button', stateParamaters: { hover: { opacity: 0.8 } } }
|
||||
];
|
||||
const result = roundTrip(makeProject({ variants }));
|
||||
expect(result.variants).toHaveLength(1);
|
||||
expect(result.variants!.length).toBe(1);
|
||||
expect(result.variants![0].stateParamaters).toEqual({ hover: { opacity: 0.8 } });
|
||||
});
|
||||
|
||||
@@ -509,7 +513,7 @@ describe('Round-trip: export import', () => {
|
||||
it('handles empty project cleanly', () => {
|
||||
const result = roundTrip(makeProject());
|
||||
expect(result.name).toBe('Test Project');
|
||||
expect(result.components).toHaveLength(0);
|
||||
expect(result.components.length).toBe(0);
|
||||
});
|
||||
|
||||
it('handles cloud component round-trip', () => {
|
||||
|
||||
Reference in New Issue
Block a user