mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 15:22:55 +01:00
Initial commit
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
This commit is contained in:
536
packages/noodl-editor/tests/components/componentspanel.js
Normal file
536
packages/noodl-editor/tests/components/componentspanel.js
Normal file
@@ -0,0 +1,536 @@
|
||||
const { ComponentsPanelView } = require('@noodl-views/panels/componentspanel/ComponentsPanel');
|
||||
const { ProjectModel } = require('@noodl-models/projectmodel');
|
||||
const { UndoQueue } = require('@noodl-models/undo-queue-model');
|
||||
const NodeGraphEditor = require('@noodl-views/nodegrapheditor').NodeGraphEditor;
|
||||
const ViewerConnection = require('../../src/editor/src/ViewerConnection');
|
||||
|
||||
describe('Components panel unit tests', function () {
|
||||
var cp;
|
||||
var p1;
|
||||
|
||||
var project = {
|
||||
components: [
|
||||
{
|
||||
name: 'Root',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/test/f1/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/test/f2/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/b',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/test/ff/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/q',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/dup/f1/a',
|
||||
graph: {}
|
||||
},
|
||||
// Undo tests
|
||||
{
|
||||
name: '/delete_folder/delete_comp',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/rename_folder/rename_comp',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/drop/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/drop2/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/dropundo',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/nested-target/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/nested-dropme/test/b',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/delete-me/with-content/a',
|
||||
graph: {}
|
||||
},
|
||||
{
|
||||
name: '/delete-me/b',
|
||||
graph: {}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
// Mock node graph editor
|
||||
NodeGraphEditor.instance = {
|
||||
getActiveComponent() {
|
||||
return p1.getComponentWithName('Root');
|
||||
},
|
||||
on() {},
|
||||
off() {},
|
||||
switchToComponent() {}
|
||||
};
|
||||
|
||||
// Viewerconnection mock
|
||||
ViewerConnection.instance = {
|
||||
on() {},
|
||||
off() {}
|
||||
};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
NodeGraphEditor.instance = undefined;
|
||||
ViewerConnection.instance = undefined;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
p1 = ProjectModel.instance = ProjectModel.fromJSON(project);
|
||||
cp = new ComponentsPanelView({});
|
||||
cp.setNodeGraphEditor(NodeGraphEditor.instance);
|
||||
cp.render();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cp.dispose();
|
||||
ProjectModel.instance = undefined;
|
||||
});
|
||||
|
||||
it('can setup view', function () {
|
||||
expect(cp).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('can add new folders', function () {
|
||||
// Existing folder
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'folder',
|
||||
name: 'test'
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'folder',
|
||||
name: ''
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Add
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'folder',
|
||||
name: 'f3'
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(cp.getFolderWithPath('/f3/')).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('can add components', function () {
|
||||
// Existing name
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'component',
|
||||
name: 'b',
|
||||
parentPath: '/'
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'component',
|
||||
name: ''
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Add
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'component',
|
||||
name: 'c',
|
||||
parentPath: '/'
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/c')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/').hasComponentWithName('c')).toBe(true);
|
||||
|
||||
// Add to sub directory
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'component',
|
||||
name: 'subsub',
|
||||
parentPath: '/test/ff/'
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/test/ff/subsub')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/test/ff/').hasComponentWithName('subsub')).toBe(true);
|
||||
});
|
||||
|
||||
it('can rename folders', function () {
|
||||
// Existing name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'folder',
|
||||
name: 'f2',
|
||||
folder: cp.getFolderWithPath('/test/ff/')
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'folder',
|
||||
name: '',
|
||||
folder: cp.getFolderWithPath('/test/ff/')
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'folder',
|
||||
name: 'f4',
|
||||
folder: cp.getFolderWithPath('/test/ff/')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/test/ff/a')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/test/f4/a')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/test/ff/')).toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/test/f4/')).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('can rename components', function () {
|
||||
// Existing name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'component',
|
||||
name: 'b',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/q')
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'component',
|
||||
name: '',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/q')
|
||||
}).success
|
||||
).toBe(false);
|
||||
|
||||
// Empty name
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'component',
|
||||
name: 'q2',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/q')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/q')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/q2')).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('can detect duplicates', function () {
|
||||
// Cannot move to folder containing a comp with same name
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'component',
|
||||
component: p1.getComponentWithName('/a'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f1/')
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
// Cannot move folder to folder containing a folder with same name
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/dup/f1/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/')
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('can make correct drops of folders', function () {
|
||||
// Can move a folder into a folder
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/test/f1/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/')
|
||||
})
|
||||
).toBe('folder');
|
||||
|
||||
// Make the move
|
||||
cp.dropOn({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/test/f1/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/')
|
||||
});
|
||||
|
||||
expect(p1.getComponentWithName('/test/f2/f1/a')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/test/f2/f1/').name).toBe('f1');
|
||||
// expect(cp.getFolderWithPath('/test/f1/')).toBe(undefined);
|
||||
|
||||
// Moving to an ancestor or same folder should not be acceptable
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/test/f2/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/f1/')
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/test/f2/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/')
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('can make correct drops of components', function () {
|
||||
// Can move into a new folder
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'component',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/b'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/')
|
||||
})
|
||||
).toBe('component');
|
||||
|
||||
// Cannot drop to same folder
|
||||
expect(
|
||||
cp.getAcceptableDropType({
|
||||
type: 'component',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/b'),
|
||||
targetFolder: cp.getFolderWithPath('/')
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
// Make the drop
|
||||
cp.dropOn({
|
||||
type: 'component',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/b'),
|
||||
targetFolder: cp.getFolderWithPath('/test/f2/')
|
||||
});
|
||||
|
||||
expect(p1.getComponentWithName('/test/f2/b')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/').hasComponentWithName('b')).toBe(false);
|
||||
expect(cp.getFolderWithPath('/test/f2/').hasComponentWithName('b')).toBe(true);
|
||||
expect(p1.getComponentWithName('/b')).toBe(undefined);
|
||||
});
|
||||
|
||||
//TODO: empty folders are removed when moved, but the undo function does not restore them. This is a bug.
|
||||
xit('can drop empty folders', function () {
|
||||
cp.performAdd({
|
||||
type: 'folder',
|
||||
name: 'empty_folder',
|
||||
parentFolder: cp.getFolderWithPath('/')
|
||||
});
|
||||
|
||||
expect(cp.getFolderWithPath('/empty_folder/')).not.toBe(undefined);
|
||||
|
||||
// Drop empty folder
|
||||
cp.dropOn({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/empty_folder/'),
|
||||
targetFolder: cp.getFolderWithPath('/test/')
|
||||
});
|
||||
|
||||
expect(cp.getFolderWithPath('/empty_folder/')).toBe(undefined);
|
||||
//empty folders are removed when moved
|
||||
expect(cp.getFolderWithPath('/test/empty_folder/')).toBe(undefined);
|
||||
|
||||
UndoQueue.instance.undo();
|
||||
|
||||
expect(cp.getFolderWithPath('/empty_folder/')).not.toBe(undefined);
|
||||
// expect(cp.getFolderWithPath('/test/empty_folder/')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('can undo add/delete/rename component and folder', function () {
|
||||
// Add component
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'component',
|
||||
name: 'undome',
|
||||
parentPath: '/'
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/undome')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('add component');
|
||||
expect(p1.getComponentWithName('/undome')).toBe(undefined);
|
||||
|
||||
// Add folder
|
||||
expect(
|
||||
cp.performAdd({
|
||||
type: 'folder',
|
||||
name: 'undome',
|
||||
parentPath: '/'
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(cp.getFolderWithPath('/undome/')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('add folder');
|
||||
expect(cp.getFolderWithPath('/undome/')).toBe(undefined);
|
||||
|
||||
// Delete component
|
||||
expect(
|
||||
cp.performDelete({
|
||||
type: 'component',
|
||||
folder: cp.getFolderWithPath('/delete_folder/'),
|
||||
component: p1.getComponentWithName('/delete_folder/delete_comp')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/delete_folder/delete_comp')).toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('delete component');
|
||||
expect(p1.getComponentWithName('/delete_folder/delete_comp')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.redo().label).toBe('delete component'); // Folder must be empty for next test to run
|
||||
|
||||
// Delete folder
|
||||
expect(
|
||||
cp.performDelete({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/delete_folder/')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(cp.getFolderWithPath('/delete_folder/')).toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('delete folder');
|
||||
expect(cp.getFolderWithPath('/delete_folder/')).not.toBe(undefined);
|
||||
|
||||
// Rename component
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'component',
|
||||
name: 'newname',
|
||||
folder: cp.getFolderWithPath('/rename_folder/'),
|
||||
component: p1.getComponentWithName('/rename_folder/rename_comp')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/rename_folder/newname')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/rename_folder/rename_comp')).toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('rename component');
|
||||
expect(p1.getComponentWithName('/rename_folder/newname')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/rename_folder/rename_comp')).not.toBe(undefined);
|
||||
|
||||
// Rename folder
|
||||
expect(
|
||||
cp.performRename({
|
||||
type: 'folder',
|
||||
name: 'newname',
|
||||
folder: cp.getFolderWithPath('/rename_folder/')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(p1.getComponentWithName('/newname/rename_comp')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/rename_folder/rename_comp')).toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/rename_folder/')).toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/newname/')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('rename folder');
|
||||
expect(p1.getComponentWithName('/newname/rename_comp')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/rename_folder/rename_comp')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/rename_folder/')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/newname/')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('can undo drop on folder', function () {
|
||||
// Component on folder
|
||||
cp.dropOn({
|
||||
type: 'component',
|
||||
folder: cp.getFolderWithPath('/'),
|
||||
component: p1.getComponentWithName('/dropundo'),
|
||||
targetFolder: cp.getFolderWithPath('/drop/')
|
||||
});
|
||||
|
||||
expect(p1.getComponentWithName('/drop/dropundo')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('move component to folder');
|
||||
// expect(p1.getComponentWithName('/drop/dropundo')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/dropundo')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/drop/').hasComponentWithName('dropundo')).toBe(false);
|
||||
|
||||
// Folder on folder
|
||||
cp.dropOn({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/drop/'),
|
||||
targetFolder: cp.getFolderWithPath('/drop2/')
|
||||
});
|
||||
expect(cp.getFolderWithPath('/drop2/drop/')).not.toBe(undefined);
|
||||
expect(UndoQueue.instance.undo().label).toBe('move folder to folder');
|
||||
// expect(cp.getFolderWithPath('/drop2/drop/')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('can make correct drops of nested folders and undo', function () {
|
||||
cp.dropOn({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/nested-dropme/'),
|
||||
targetFolder: cp.getFolderWithPath('/nested-target/')
|
||||
});
|
||||
expect(cp.getFolderWithPath('/nested-target/nested-dropme/')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/nested-target/nested-dropme/test/b')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/nested-dropme/test/b')).toBe(undefined);
|
||||
// expect(cp.getFolderWithPath('/nested-dropme/')).toBe(undefined);
|
||||
UndoQueue.instance.undo();
|
||||
// expect(cp.getFolderWithPath('/nested-target/nested-dropme/')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/nested-target/nested-dropme/test/b')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/nested-dropme/test/b')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/nested-dropme/')).not.toBe(undefined);
|
||||
});
|
||||
|
||||
it('can delete folder with content', function () {
|
||||
// Delete folder
|
||||
expect(
|
||||
cp.performDelete({
|
||||
type: 'folder',
|
||||
folder: cp.getFolderWithPath('/delete-me/')
|
||||
}).success
|
||||
).toBe(true);
|
||||
|
||||
expect(cp.getFolderWithPath('/delete-me/')).toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/delete-me/with-content/')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/delete-me/with-content/a')).toBe(undefined);
|
||||
expect(p1.getComponentWithName('/delete-me/b')).toBe(undefined);
|
||||
UndoQueue.instance.undo();
|
||||
expect(cp.getFolderWithPath('/delete-me/')).not.toBe(undefined);
|
||||
expect(cp.getFolderWithPath('/delete-me/with-content/')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/delete-me/with-content/a')).not.toBe(undefined);
|
||||
expect(p1.getComponentWithName('/delete-me/b')).not.toBe(undefined);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user