mirror of
https://github.com/fluxscape/fluxscape.git
synced 2026-01-11 23:02:55 +01:00
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>
537 lines
15 KiB
JavaScript
537 lines
15 KiB
JavaScript
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);
|
|
});
|
|
});
|