first commit

This commit is contained in:
Jane
2024-02-19 17:25:32 +08:00
commit d21f90672b
455 changed files with 67178 additions and 0 deletions

8
test/unit/.eslintrc Normal file
View File

@@ -0,0 +1,8 @@
{
"env": {
"jest": true
},
"extends": [
"../../.eslintrc.js"
]
}

33
test/unit/jest.conf.js Normal file
View File

@@ -0,0 +1,33 @@
const path = require('path');
module.exports = {
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue',
],
moduleNameMapper: {
'\\.(css|scss)$': 'identity-obj-proxy',
'^!raw-loader!': 'identity-obj-proxy',
'^worker-loader!\\./templateWorker\\.js$': '<rootDir>/test/unit/mocks/templateWorkerMock',
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest',
'.*\\.(yml|html|md)$': 'jest-raw-loader',
},
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
setupFiles: [
'<rootDir>/test/unit/setup',
],
coverageDirectory: '<rootDir>/test/unit/coverage',
collectCoverageFrom: [
'src/**/*.{js,vue}',
'!src/main.js',
'!**/node_modules/**',
],
globals: {
NODE_ENV: 'production',
},
};

View File

@@ -0,0 +1,7 @@
window.crypto = {
getRandomValues(array) {
for (let i = 0; i < array.length; i += 1) {
array[i] = Math.floor(Math.random() * 1000000);
}
},
};

View File

@@ -0,0 +1,9 @@
const store = {};
window.localStorage = {
getItem(key) {
return store[key] || null;
},
setItem(key, value) {
store[key] = value.toString();
},
};

View File

@@ -0,0 +1,6 @@
/* eslint-disable class-methods-use-this */
class MutationObserver {
observe() {
}
}
window.MutationObserver = MutationObserver;

View File

@@ -0,0 +1 @@
module.exports = 'test-file-stub';

5
test/unit/setup.js Normal file
View File

@@ -0,0 +1,5 @@
import Vue from 'vue';
import './mocks/cryptoMock';
import './mocks/mutationObserverMock';
Vue.config.productionTip = false;

View File

@@ -0,0 +1,47 @@
import ButtonBar from '../../../../src/components/ButtonBar';
import store from '../../../../src/store';
import specUtils from '../specUtils';
describe('ButtonBar.vue', () => {
it('should toggle the navigation bar', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--navigation-bar-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].showNavigationBar,
'toggleNavigationBar',
));
it('should toggle the side preview', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--side-preview-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].showSidePreview,
'toggleSidePreview',
));
it('should toggle the editor', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--editor-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].showEditor,
'toggleEditor',
));
it('should toggle the focus mode', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--focus-mode-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].focusMode,
'toggleFocusMode',
));
it('should toggle the scroll sync', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--scroll-sync-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].scrollSync,
'toggleScrollSync',
));
it('should toggle the status bar', async () => specUtils.checkToggler(
ButtonBar,
wrapper => wrapper.find('.button-bar__button--status-bar-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].showStatusBar,
'toggleStatusBar',
));
});

View File

@@ -0,0 +1,32 @@
import { shallowMount } from '@vue/test-utils';
import ContextMenu from '../../../../src/components/ContextMenu';
import store from '../../../../src/store';
import '../specUtils';
const mount = () => shallowMount(ContextMenu, { store });
describe('ContextMenu.vue', () => {
const name = 'Name';
const makeOptions = () => ({
coordinates: {
left: 0,
top: 0,
},
items: [{ name }],
});
it('should open/close itself', async () => {
const wrapper = mount();
expect(wrapper.contains('.context-menu__item')).toEqual(false);
setTimeout(() => wrapper.find('.context-menu__item').trigger('click'), 1);
const item = await store.dispatch('contextMenu/open', makeOptions());
expect(item.name).toEqual(name);
});
it('should cancel itself', async () => {
const wrapper = mount();
setTimeout(() => wrapper.trigger('click'), 1);
const item = await store.dispatch('contextMenu/open', makeOptions());
expect(item).toEqual(null);
});
});

View File

@@ -0,0 +1,194 @@
import { shallowMount } from '@vue/test-utils';
import Explorer from '../../../../src/components/Explorer';
import store from '../../../../src/store';
import workspaceSvc from '../../../../src/services/workspaceSvc';
import specUtils from '../specUtils';
const mount = () => shallowMount(Explorer, { store });
const select = (id) => {
store.commit('explorer/setSelectedId', id);
expect(store.getters['explorer/selectedNode'].item.id).toEqual(id);
};
const ensureExists = file => expect(store.getters.allItemsById).toHaveProperty(file.id);
const ensureNotExists = file => expect(store.getters.allItemsById).not.toHaveProperty(file.id);
const refreshItem = item => store.getters.allItemsById[item.id];
describe('Explorer.vue', () => {
it('should create new file in the root folder', async () => {
expect(store.state.explorer.newChildNode.isNil).toBeTruthy();
const wrapper = mount();
wrapper.find('.side-title__button--new-file').trigger('click');
expect(store.state.explorer.newChildNode.isNil).toBeFalsy();
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'file',
parentId: null,
});
});
it('should create new file in a folder', async () => {
const folder = await workspaceSvc.storeItem({ type: 'folder' });
const wrapper = mount();
select(folder.id);
wrapper.find('.side-title__button--new-file').trigger('click');
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'file',
parentId: folder.id,
});
});
it('should not create new files in the trash folder', async () => {
const wrapper = mount();
select('trash');
wrapper.find('.side-title__button--new-file').trigger('click');
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'file',
parentId: null,
});
});
it('should create new folders in the root folder', async () => {
expect(store.state.explorer.newChildNode.isNil).toBeTruthy();
const wrapper = mount();
wrapper.find('.side-title__button--new-folder').trigger('click');
expect(store.state.explorer.newChildNode.isNil).toBeFalsy();
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'folder',
parentId: null,
});
});
it('should create new folders in a folder', async () => {
const folder = await workspaceSvc.storeItem({ type: 'folder' });
const wrapper = mount();
select(folder.id);
wrapper.find('.side-title__button--new-folder').trigger('click');
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'folder',
parentId: folder.id,
});
});
it('should not create new folders in the trash folder', async () => {
const wrapper = mount();
select('trash');
wrapper.find('.side-title__button--new-folder').trigger('click');
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'folder',
parentId: null,
});
});
it('should not create new folders in the temp folder', async () => {
const wrapper = mount();
select('temp');
wrapper.find('.side-title__button--new-folder').trigger('click');
expect(store.state.explorer.newChildNode.item).toMatchObject({
type: 'folder',
parentId: null,
});
});
it('should move file to the trash folder on delete', async () => {
const file = await workspaceSvc.createFile({}, true);
expect(file.parentId).toEqual(null);
const wrapper = mount();
select(file.id);
wrapper.find('.side-title__button--delete').trigger('click');
ensureExists(file);
expect(refreshItem(file).parentId).toEqual('trash');
await specUtils.expectBadge('removeFile');
});
it('should not delete the trash folder', async () => {
const wrapper = mount();
select('trash');
wrapper.find('.side-title__button--delete').trigger('click');
await specUtils.resolveModal('trashDeletion');
await specUtils.expectBadge('removeFile', false);
});
it('should not delete file in the trash folder', async () => {
const file = await workspaceSvc.createFile({ parentId: 'trash' }, true);
const wrapper = mount();
select(file.id);
wrapper.find('.side-title__button--delete').trigger('click');
await specUtils.resolveModal('trashDeletion');
ensureExists(file);
await specUtils.expectBadge('removeFile', false);
});
it('should delete the temp folder after confirmation', async () => {
const file = await workspaceSvc.createFile({ parentId: 'temp' }, true);
const wrapper = mount();
select('temp');
wrapper.find('.side-title__button--delete').trigger('click');
await specUtils.resolveModal('tempFolderDeletion');
ensureNotExists(file);
await specUtils.expectBadge('removeFolder');
});
it('should delete temp file after confirmation', async () => {
const file = await workspaceSvc.createFile({ parentId: 'temp' }, true);
const wrapper = mount();
select(file.id);
wrapper.find('.side-title__button--delete').trigger('click');
ensureExists(file);
await specUtils.resolveModal('tempFileDeletion');
ensureNotExists(file);
await specUtils.expectBadge('removeFile');
});
it('should delete folder after confirmation', async () => {
const folder = await workspaceSvc.storeItem({ type: 'folder' });
const file = await workspaceSvc.createFile({ parentId: folder.id }, true);
const wrapper = mount();
select(folder.id);
wrapper.find('.side-title__button--delete').trigger('click');
await specUtils.resolveModal('folderDeletion');
ensureNotExists(folder);
// Make sure file has been moved to Trash
ensureExists(file);
expect(refreshItem(file).parentId).toEqual('trash');
await specUtils.expectBadge('removeFolder');
});
it('should rename file', async () => {
const file = await workspaceSvc.createFile({}, true);
const wrapper = mount();
select(file.id);
wrapper.find('.side-title__button--rename').trigger('click');
expect(store.getters['explorer/editingNode'].item.id).toEqual(file.id);
});
it('should rename folder', async () => {
const folder = await workspaceSvc.storeItem({ type: 'folder' });
const wrapper = mount();
select(folder.id);
wrapper.find('.side-title__button--rename').trigger('click');
expect(store.getters['explorer/editingNode'].item.id).toEqual(folder.id);
});
it('should not rename the trash folder', async () => {
const wrapper = mount();
select('trash');
wrapper.find('.side-title__button--rename').trigger('click');
expect(store.getters['explorer/editingNode'].isNil).toBeTruthy();
});
it('should not rename the temp folder', async () => {
const wrapper = mount();
select('temp');
wrapper.find('.side-title__button--rename').trigger('click');
expect(store.getters['explorer/editingNode'].isNil).toBeTruthy();
});
it('should close itself', async () => {
store.dispatch('data/toggleExplorer', true);
specUtils.checkToggler(
Explorer,
wrapper => wrapper.find('.side-title__button--close').trigger('click'),
() => store.getters['data/layoutSettings'].showExplorer,
'toggleExplorer',
);
});
});

View File

@@ -0,0 +1,307 @@
import { shallowMount } from '@vue/test-utils';
import ExplorerNode from '../../../../src/components/ExplorerNode';
import store from '../../../../src/store';
import workspaceSvc from '../../../../src/services/workspaceSvc';
import explorerSvc from '../../../../src/services/explorerSvc';
import specUtils from '../specUtils';
const makeFileNode = async () => {
const file = await workspaceSvc.createFile({}, true);
const node = store.getters['explorer/nodeMap'][file.id];
expect(node.item.id).toEqual(file.id);
return node;
};
const makeFolderNode = async () => {
const folder = await workspaceSvc.storeItem({ type: 'folder' });
const node = store.getters['explorer/nodeMap'][folder.id];
expect(node.item.id).toEqual(folder.id);
return node;
};
const mount = node => shallowMount(ExplorerNode, {
store,
propsData: { node, depth: 1 },
});
const mountAndSelect = (node) => {
const wrapper = mount(node);
wrapper.find('.explorer-node__item').trigger('click');
expect(store.getters['explorer/selectedNode'].item.id).toEqual(node.item.id);
expect(wrapper.classes()).toContain('explorer-node--selected');
return wrapper;
};
const dragAndDrop = (sourceItem, targetItem) => {
const sourceNode = store.getters['explorer/nodeMap'][sourceItem.id];
mountAndSelect(sourceNode).find('.explorer-node__item').trigger('dragstart', {
dataTransfer: { setData: () => {} },
});
expect(store.state.explorer.dragSourceId).toEqual(sourceItem.id);
const targetNode = store.getters['explorer/nodeMap'][targetItem.id];
const wrapper = mount(targetNode);
wrapper.trigger('dragenter');
expect(store.state.explorer.dragTargetId).toEqual(targetItem.id);
wrapper.trigger('drop');
const expectedParentId = targetItem.type === 'file' ? targetItem.parentId : targetItem.id;
expect(store.getters['explorer/selectedNode'].item.parentId).toEqual(expectedParentId);
};
describe('ExplorerNode.vue', () => {
const modifiedName = 'Name';
it('should open file on select after a timeout', async () => {
const node = await makeFileNode();
mountAndSelect(node);
expect(store.getters['file/current'].id).not.toEqual(node.item.id);
await new Promise(resolve => setTimeout(resolve, 10));
expect(store.getters['file/current'].id).toEqual(node.item.id);
await specUtils.expectBadge('switchFile');
});
it('should not open already open file', async () => {
const node = await makeFileNode();
store.commit('file/setCurrentId', node.item.id);
mountAndSelect(node);
await new Promise(resolve => setTimeout(resolve, 10));
expect(store.getters['file/current'].id).toEqual(node.item.id);
await specUtils.expectBadge('switchFile', false);
});
it('should open folder on select after a timeout', async () => {
const node = await makeFolderNode();
const wrapper = mountAndSelect(node);
expect(wrapper.classes()).not.toContain('explorer-node--open');
await new Promise(resolve => setTimeout(resolve, 10));
expect(wrapper.classes()).toContain('explorer-node--open');
});
it('should open folder on new child', async () => {
const node = await makeFolderNode();
const wrapper = mountAndSelect(node);
// Close the folder
wrapper.find('.explorer-node__item').trigger('click');
await new Promise(resolve => setTimeout(resolve, 10));
expect(wrapper.classes()).not.toContain('explorer-node--open');
explorerSvc.newItem();
expect(wrapper.classes()).toContain('explorer-node--open');
});
it('should create new file in a folder', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('New file');
expect(wrapper.contains('.explorer-node__new-child')).toBe(true);
store.commit('explorer/setNewItemName', modifiedName);
wrapper.find('.explorer-node__new-child .text-input').trigger('blur');
await new Promise(resolve => setTimeout(resolve, 1));
expect(store.getters['explorer/selectedNode'].item).toMatchObject({
name: modifiedName,
type: 'file',
parentId: node.item.id,
});
expect(wrapper.contains('.explorer-node__new-child')).toBe(false);
await specUtils.expectBadge('createFile');
});
it('should cancel file creation on escape', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('New file');
expect(wrapper.contains('.explorer-node__new-child')).toBe(true);
store.commit('explorer/setNewItemName', modifiedName);
wrapper.find('.explorer-node__new-child .text-input').trigger('keydown', {
keyCode: 27,
});
await new Promise(resolve => setTimeout(resolve, 1));
expect(store.getters['explorer/selectedNode'].item).not.toMatchObject({
name: 'modifiedName',
type: 'file',
parentId: node.item.id,
});
expect(wrapper.contains('.explorer-node__new-child')).toBe(false);
await specUtils.expectBadge('createFile', false);
});
it('should not create new file in a file', async () => {
const node = await makeFileNode();
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('New file').disabled).toBe(true);
});
it('should not create new file in the trash folder', async () => {
const node = store.getters['explorer/nodeMap'].trash;
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('New file').disabled).toBe(true);
});
it('should create new folder in folder', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('New folder');
expect(wrapper.contains('.explorer-node__new-child--folder')).toBe(true);
store.commit('explorer/setNewItemName', modifiedName);
wrapper.find('.explorer-node__new-child--folder .text-input').trigger('blur');
await new Promise(resolve => setTimeout(resolve, 1));
expect(store.getters['explorer/selectedNode'].item).toMatchObject({
name: modifiedName,
type: 'folder',
parentId: node.item.id,
});
expect(wrapper.contains('.explorer-node__new-child--folder')).toBe(false);
await specUtils.expectBadge('createFolder');
});
it('should cancel folder creation on escape', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('New folder');
expect(wrapper.contains('.explorer-node__new-child--folder')).toBe(true);
store.commit('explorer/setNewItemName', modifiedName);
wrapper.find('.explorer-node__new-child--folder .text-input').trigger('keydown', {
keyCode: 27,
});
await new Promise(resolve => setTimeout(resolve, 1));
expect(store.getters['explorer/selectedNode'].item).not.toMatchObject({
name: modifiedName,
type: 'folder',
parentId: node.item.id,
});
expect(wrapper.contains('.explorer-node__new-child--folder')).toBe(false);
await specUtils.expectBadge('createFolder', false);
});
it('should not create new folder in a file', async () => {
const node = await makeFileNode();
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('New folder').disabled).toBe(true);
});
it('should not create new folder in the trash folder', async () => {
const node = store.getters['explorer/nodeMap'].trash;
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('New folder').disabled).toBe(true);
});
it('should not create new folder in the temp folder', async () => {
const node = store.getters['explorer/nodeMap'].temp;
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('New folder').disabled).toBe(true);
});
it('should rename file', async () => {
const node = await makeFileNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('Rename');
expect(wrapper.contains('.explorer-node__item-editor')).toBe(true);
wrapper.setData({ editingValue: modifiedName });
wrapper.find('.explorer-node__item-editor .text-input').trigger('blur');
expect(store.getters['explorer/selectedNode'].item.name).toEqual(modifiedName);
await specUtils.expectBadge('renameFile');
});
it('should cancel rename file on escape', async () => {
const node = await makeFileNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('Rename');
expect(wrapper.contains('.explorer-node__item-editor')).toBe(true);
wrapper.setData({ editingValue: modifiedName });
wrapper.find('.explorer-node__item-editor .text-input').trigger('keydown', {
keyCode: 27,
});
expect(store.getters['explorer/selectedNode'].item.name).not.toEqual(modifiedName);
await specUtils.expectBadge('renameFile', false);
});
it('should rename folder', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('Rename');
expect(wrapper.contains('.explorer-node__item-editor')).toBe(true);
wrapper.setData({ editingValue: modifiedName });
wrapper.find('.explorer-node__item-editor .text-input').trigger('blur');
expect(store.getters['explorer/selectedNode'].item.name).toEqual(modifiedName);
await specUtils.expectBadge('renameFolder');
});
it('should cancel rename folder on escape', async () => {
const node = await makeFolderNode();
const wrapper = mount(node);
wrapper.trigger('contextmenu');
await specUtils.resolveContextMenu('Rename');
expect(wrapper.contains('.explorer-node__item-editor')).toBe(true);
wrapper.setData({ editingValue: modifiedName });
wrapper.find('.explorer-node__item-editor .text-input').trigger('keydown', {
keyCode: 27,
});
expect(store.getters['explorer/selectedNode'].item.name).not.toEqual(modifiedName);
await specUtils.expectBadge('renameFolder', false);
});
it('should not rename the trash folder', async () => {
const node = store.getters['explorer/nodeMap'].trash;
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('Rename').disabled).toBe(true);
});
it('should not rename the temp folder', async () => {
const node = store.getters['explorer/nodeMap'].temp;
mount(node).trigger('contextmenu');
expect(specUtils.getContextMenuItem('Rename').disabled).toBe(true);
});
it('should move file into a folder', async () => {
const sourceItem = await workspaceSvc.createFile({}, true);
const targetItem = await workspaceSvc.storeItem({ type: 'folder' });
dragAndDrop(sourceItem, targetItem);
await specUtils.expectBadge('moveFile');
});
it('should move folder into a folder', async () => {
const sourceItem = await workspaceSvc.storeItem({ type: 'folder' });
const targetItem = await workspaceSvc.storeItem({ type: 'folder' });
dragAndDrop(sourceItem, targetItem);
await specUtils.expectBadge('moveFolder');
});
it('should move file into a file parent folder', async () => {
const targetItem = await workspaceSvc.storeItem({ type: 'folder' });
const file = await workspaceSvc.createFile({ parentId: targetItem.id }, true);
const sourceItem = await workspaceSvc.createFile({}, true);
dragAndDrop(sourceItem, file);
await specUtils.expectBadge('moveFile');
});
it('should not move the trash folder', async () => {
const sourceNode = store.getters['explorer/nodeMap'].trash;
mountAndSelect(sourceNode).find('.explorer-node__item').trigger('dragstart');
expect(store.state.explorer.dragSourceId).not.toEqual('trash');
});
it('should not move the temp folder', async () => {
const sourceNode = store.getters['explorer/nodeMap'].temp;
mountAndSelect(sourceNode).find('.explorer-node__item').trigger('dragstart');
expect(store.state.explorer.dragSourceId).not.toEqual('temp');
});
it('should not move file to the temp folder', async () => {
const targetNode = store.getters['explorer/nodeMap'].temp;
const wrapper = mount(targetNode);
wrapper.trigger('dragenter');
expect(store.state.explorer.dragTargetId).not.toEqual('temp');
});
it('should not move file to a file in the temp folder', async () => {
const file = await workspaceSvc.createFile({ parentId: 'temp' }, true);
const targetNode = store.getters['explorer/nodeMap'][file.id];
const wrapper = mount(targetNode);
wrapper.trigger('dragenter');
expect(store.state.explorer.dragTargetId).not.toEqual(file.id);
});
});

View File

@@ -0,0 +1,19 @@
import NavigationBar from '../../../../src/components/NavigationBar';
import store from '../../../../src/store';
import specUtils from '../specUtils';
describe('NavigationBar.vue', () => {
it('should toggle the explorer', async () => specUtils.checkToggler(
NavigationBar,
wrapper => wrapper.find('.navigation-bar__button--explorer-toggler').trigger('click'),
() => store.getters['data/layoutSettings'].showExplorer,
'toggleExplorer',
));
it('should toggle the side bar', async () => specUtils.checkToggler(
NavigationBar,
wrapper => wrapper.find('.navigation-bar__button--stackedit').trigger('click'),
() => store.getters['data/layoutSettings'].showSideBar,
'toggleSideBar',
));
});

View File

@@ -0,0 +1,38 @@
import { shallowMount } from '@vue/test-utils';
import Notification from '../../../../src/components/Notification';
import store from '../../../../src/store';
import '../specUtils';
const mount = () => shallowMount(Notification, { store });
describe('Notification.vue', () => {
it('should autoclose itself', async () => {
const wrapper = mount();
expect(wrapper.contains('.notification__item')).toBe(false);
store.dispatch('notification/showItem', {
type: 'info',
content: 'Test',
timeout: 10,
});
expect(wrapper.contains('.notification__item')).toBe(true);
await new Promise(resolve => setTimeout(resolve, 10));
expect(wrapper.contains('.notification__item')).toBe(false);
});
it('should show messages from top to bottom', async () => {
const wrapper = mount();
store.dispatch('notification/info', 'Test 1');
store.dispatch('notification/info', 'Test 2');
const items = wrapper.findAll('.notification__item');
expect(items.length).toEqual(2);
expect(items.at(0).text()).toMatch(/Test 1/);
expect(items.at(1).text()).toMatch(/Test 2/);
});
it('should not open the same message twice', async () => {
const wrapper = mount();
store.dispatch('notification/info', 'Test');
store.dispatch('notification/info', 'Test');
expect(wrapper.findAll('.notification__item').length).toEqual(1);
});
});

View File

@@ -0,0 +1,58 @@
import { shallowMount } from '@vue/test-utils';
import store from '../../../src/store';
import utils from '../../../src/services/utils';
import '../../../src/icons';
import '../../../src/components/common/vueGlobals';
const clone = object => JSON.parse(JSON.stringify(object));
const deepAssign = (target, origin) => {
Object.entries(origin).forEach(([key, value]) => {
const type = Object.prototype.toString.call(value);
if (type === '[object Object]' && Object.keys(value).length) {
deepAssign(target[key], value);
} else {
target[key] = value;
}
});
};
const freshState = clone(store.state);
beforeEach(() => {
// Restore store state before each test
deepAssign(store.state, clone(freshState));
});
export default {
async checkToggler(Component, toggler, checker, featureId) {
const wrapper = shallowMount(Component, { store });
const valueBefore = checker();
toggler(wrapper);
const valueAfter = checker();
expect(valueAfter).toEqual(!valueBefore);
await this.expectBadge(featureId);
},
async resolveModal(type) {
const config = store.getters['modal/config'];
expect(config).toBeTruthy();
expect(config.type).toEqual(type);
config.resolve();
await new Promise(resolve => setTimeout(resolve, 1));
},
getContextMenuItem(name) {
return utils.someResult(store.state.contextMenu.items, item => item.name === name && item);
},
async resolveContextMenu(name) {
const item = this.getContextMenuItem(name);
expect(item).toBeTruthy();
store.state.contextMenu.resolve(item);
await new Promise(resolve => setTimeout(resolve, 1));
},
async expectBadge(featureId, isEarned = true) {
await new Promise(resolve => setTimeout(resolve, 1));
expect(store.getters['data/allBadges'].filter(badge => badge.featureId === featureId)[0]).toMatchObject({
isEarned,
});
},
};