Merge pull request #1410 from ghalestrilo/test/file-node
Write tests for name verification logic (<ToolBar />, <FileNode />)
This commit is contained in:
commit
67f9824642
3 changed files with 236 additions and 19 deletions
|
@ -2,19 +2,30 @@ import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { FileNode } from '../../modules/IDE/components/FileNode';
|
import { FileNode } from '../../modules/IDE/components/FileNode';
|
||||||
|
|
||||||
beforeAll(() => {});
|
|
||||||
describe('<FileNode />', () => {
|
describe('<FileNode />', () => {
|
||||||
let component;
|
let component;
|
||||||
let props = {};
|
let props = {};
|
||||||
|
let input;
|
||||||
|
let renameTriggerButton;
|
||||||
|
const changeName = (newFileName) => {
|
||||||
|
renameTriggerButton.simulate('click');
|
||||||
|
input.simulate('change', { target: { value: newFileName } });
|
||||||
|
input.simulate('blur');
|
||||||
|
};
|
||||||
|
const getState = () => component.state();
|
||||||
|
const getUpdatedName = () => getState().updatedName;
|
||||||
|
|
||||||
describe('with valid props', () => {
|
describe('with valid props, regardless of filetype', () => {
|
||||||
|
['folder', 'file'].forEach((fileType) => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
props = {
|
props = {
|
||||||
...props,
|
...props,
|
||||||
id: '0',
|
id: '0',
|
||||||
children: [],
|
|
||||||
name: 'test.jsx',
|
name: 'test.jsx',
|
||||||
fileType: 'dunno',
|
fileType,
|
||||||
|
canEdit: true,
|
||||||
|
children: [],
|
||||||
|
authenticated: false,
|
||||||
setSelectedFile: jest.fn(),
|
setSelectedFile: jest.fn(),
|
||||||
deleteFile: jest.fn(),
|
deleteFile: jest.fn(),
|
||||||
updateFileName: jest.fn(),
|
updateFileName: jest.fn(),
|
||||||
|
@ -23,22 +34,56 @@ describe('<FileNode />', () => {
|
||||||
newFolder: jest.fn(),
|
newFolder: jest.fn(),
|
||||||
showFolderChildren: jest.fn(),
|
showFolderChildren: jest.fn(),
|
||||||
hideFolderChildren: jest.fn(),
|
hideFolderChildren: jest.fn(),
|
||||||
|
openUploadFileModal: jest.fn(),
|
||||||
|
setProjectName: jest.fn(),
|
||||||
|
};
|
||||||
|
component = shallow(<FileNode {...props} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when changing name', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
input = component.find('.sidebar__file-item-input');
|
||||||
|
renameTriggerButton = component
|
||||||
|
.find('.sidebar__file-item-option')
|
||||||
|
.first();
|
||||||
|
component.setState({ isEditing: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('to an empty name', () => {
|
||||||
|
const newName = '';
|
||||||
|
beforeEach(() => changeName(newName));
|
||||||
|
|
||||||
|
it('should not save', () => expect(props.updateFileName).not.toHaveBeenCalled());
|
||||||
|
it('should reset name', () => expect(getUpdatedName()).toEqual(props.name));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('as file with valid props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
id: '0',
|
||||||
|
name: 'test.jsx',
|
||||||
|
fileType: 'file',
|
||||||
canEdit: true,
|
canEdit: true,
|
||||||
|
children: [],
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
|
setSelectedFile: jest.fn(),
|
||||||
|
deleteFile: jest.fn(),
|
||||||
|
updateFileName: jest.fn(),
|
||||||
|
resetSelectedFile: jest.fn(),
|
||||||
|
newFile: jest.fn(),
|
||||||
|
newFolder: jest.fn(),
|
||||||
|
showFolderChildren: jest.fn(),
|
||||||
|
hideFolderChildren: jest.fn(),
|
||||||
openUploadFileModal: jest.fn()
|
openUploadFileModal: jest.fn()
|
||||||
};
|
};
|
||||||
component = shallow(<FileNode {...props} />);
|
component = shallow(<FileNode {...props} />);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when changing name', () => {
|
describe('when changing name', () => {
|
||||||
let input;
|
|
||||||
let renameTriggerButton;
|
|
||||||
const changeName = (newFileName) => {
|
|
||||||
renameTriggerButton.simulate('click');
|
|
||||||
input.simulate('change', { target: { value: newFileName } });
|
|
||||||
input.simulate('blur');
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
input = component.find('.sidebar__file-item-input');
|
input = component.find('.sidebar__file-item-input');
|
||||||
renameTriggerButton = component
|
renameTriggerButton = component
|
||||||
|
@ -59,13 +104,79 @@ describe('<FileNode />', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('to an empty filename', () => {
|
// Failure Scenarios
|
||||||
const newName = '';
|
|
||||||
|
describe('to an extensionless filename', () => {
|
||||||
|
const newName = 'extensionless';
|
||||||
|
beforeEach(() => changeName(newName));
|
||||||
|
});
|
||||||
|
it('should not save', () => expect(props.setProjectName).not.toHaveBeenCalled());
|
||||||
|
it('should reset name', () => expect(getUpdatedName()).toEqual(props.name));
|
||||||
|
describe('to different extension', () => {
|
||||||
|
const newName = 'name.gif';
|
||||||
beforeEach(() => changeName(newName));
|
beforeEach(() => changeName(newName));
|
||||||
|
|
||||||
it('should not save the name', () => {
|
it('should not save', () => expect(props.setProjectName).not.toHaveBeenCalled());
|
||||||
expect(props.updateFileName).not.toHaveBeenCalled();
|
it('should reset name', () => expect(getUpdatedName()).toEqual(props.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('to just an extension', () => {
|
||||||
|
const newName = '.jsx';
|
||||||
|
beforeEach(() => changeName(newName));
|
||||||
|
|
||||||
|
it('should not save', () => expect(props.updateFileName).not.toHaveBeenCalled());
|
||||||
|
it('should reset name', () => expect(getUpdatedName()).toEqual(props.name));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('as folder with valid props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
id: '0',
|
||||||
|
children: [],
|
||||||
|
name: 'filename',
|
||||||
|
fileType: 'folder',
|
||||||
|
canEdit: true,
|
||||||
|
authenticated: false,
|
||||||
|
setSelectedFile: jest.fn(),
|
||||||
|
deleteFile: jest.fn(),
|
||||||
|
updateFileName: jest.fn(),
|
||||||
|
resetSelectedFile: jest.fn(),
|
||||||
|
newFile: jest.fn(),
|
||||||
|
newFolder: jest.fn(),
|
||||||
|
showFolderChildren: jest.fn(),
|
||||||
|
hideFolderChildren: jest.fn(),
|
||||||
|
openUploadFileModal: jest.fn()
|
||||||
|
};
|
||||||
|
component = shallow(<FileNode {...props} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when changing name', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
input = component.find('.sidebar__file-item-input');
|
||||||
|
renameTriggerButton = component
|
||||||
|
.find('.sidebar__file-item-option')
|
||||||
|
.first();
|
||||||
|
component.setState({ isEditing: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('to a foldername', () => {
|
||||||
|
const newName = 'newfoldername';
|
||||||
|
beforeEach(() => changeName(newName));
|
||||||
|
|
||||||
|
it('should save', () => expect(props.updateFileName).toBeCalledWith(props.id, newName));
|
||||||
|
it('should update name', () => expect(getUpdatedName()).toEqual(newName));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('to a filename', () => {
|
||||||
|
const newName = 'filename.jsx';
|
||||||
|
beforeEach(() => changeName(newName));
|
||||||
|
|
||||||
|
it('should not save', () => expect(props.updateFileName).not.toHaveBeenCalled());
|
||||||
|
it('should reset name', () => expect(getUpdatedName()).toEqual(props.name));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
105
client/components/__test__/Toolbar.test.jsx
Normal file
105
client/components/__test__/Toolbar.test.jsx
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import { ToolbarComponent } from '../../modules/IDE/components/Toolbar';
|
||||||
|
|
||||||
|
|
||||||
|
const initialProps = {
|
||||||
|
isPlaying: false,
|
||||||
|
preferencesIsVisible: false,
|
||||||
|
stopSketch: jest.fn(),
|
||||||
|
setProjectName: jest.fn(),
|
||||||
|
openPreferences: jest.fn(),
|
||||||
|
showEditProjectName: jest.fn(),
|
||||||
|
hideEditProjectName: jest.fn(),
|
||||||
|
infiniteLoop: false,
|
||||||
|
autorefresh: false,
|
||||||
|
setAutorefresh: jest.fn(),
|
||||||
|
setTextOutput: jest.fn(),
|
||||||
|
setGridOutput: jest.fn(),
|
||||||
|
startSketch: jest.fn(),
|
||||||
|
startAccessibleSketch: jest.fn(),
|
||||||
|
saveProject: jest.fn(),
|
||||||
|
currentUser: 'me',
|
||||||
|
originalProjectName: 'testname',
|
||||||
|
|
||||||
|
owner: {
|
||||||
|
username: 'me'
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
name: 'testname',
|
||||||
|
isEditingName: false,
|
||||||
|
id: 'id',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
describe('<ToolbarComponent />', () => {
|
||||||
|
let component;
|
||||||
|
let props = initialProps;
|
||||||
|
let input;
|
||||||
|
let renameTriggerButton;
|
||||||
|
const changeName = (newFileName) => {
|
||||||
|
component.find('.toolbar__project-name').simulate('click', { preventDefault: jest.fn() });
|
||||||
|
input = component.find('.toolbar__project-name-input');
|
||||||
|
renameTriggerButton = component.find('.toolbar__edit-name-button');
|
||||||
|
renameTriggerButton.simulate('click');
|
||||||
|
input.simulate('change', { target: { value: newFileName } });
|
||||||
|
input.simulate('blur');
|
||||||
|
};
|
||||||
|
const setProps = (additionalProps) => {
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
...additionalProps,
|
||||||
|
|
||||||
|
project: {
|
||||||
|
...props.project,
|
||||||
|
...(additionalProps || {}).project
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test Cases
|
||||||
|
|
||||||
|
describe('with valid props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setProps();
|
||||||
|
component = shallow(<ToolbarComponent {...props} />);
|
||||||
|
});
|
||||||
|
it('renders', () => expect(component).toBeDefined());
|
||||||
|
|
||||||
|
describe('when use owns sketch', () => {
|
||||||
|
beforeEach(() => setProps({ currentUser: props.owner.username }));
|
||||||
|
|
||||||
|
describe('when changing sketch name', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setProps({
|
||||||
|
project: { isEditingName: true, name: 'testname' },
|
||||||
|
setProjectName: jest.fn(name => component.setProps({ project: { name } })),
|
||||||
|
});
|
||||||
|
component = shallow(<ToolbarComponent {...props} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('to a valid name', () => {
|
||||||
|
beforeEach(() => changeName('hello'));
|
||||||
|
it('should save', () => expect(props.setProjectName).toBeCalledWith('hello'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('to an empty name', () => {
|
||||||
|
beforeEach(() => changeName(''));
|
||||||
|
it('should set name to empty', () => expect(props.setProjectName).toBeCalledWith(''));
|
||||||
|
it(
|
||||||
|
'should detect empty name and revert to original',
|
||||||
|
() => expect(props.setProjectName).toHaveBeenLastCalledWith(initialProps.project.name)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when user does not own sketch', () => {
|
||||||
|
beforeEach(() => setProps({ currentUser: 'not-the-owner' }));
|
||||||
|
|
||||||
|
it('should disable edition', () => expect(component.find('.toolbar__edit-name-button')).toEqual({}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -214,4 +214,5 @@ const mapDispatchToProps = {
|
||||||
...projectActions,
|
...projectActions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ToolbarComponent = Toolbar;
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);
|
export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);
|
||||||
|
|
Loading…
Reference in a new issue