Merge pull request #1410 from ghalestrilo/test/file-node

Write tests for name verification logic (<ToolBar />, <FileNode />)
This commit is contained in:
Cassie Tarakajian 2020-05-22 14:12:31 -04:00 committed by GitHub
commit 67f9824642
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 236 additions and 19 deletions

View file

@ -2,19 +2,74 @@ 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(() => {
props = {
...props,
id: '0',
name: 'test.jsx',
fileType,
canEdit: true,
children: [],
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(),
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(() => { beforeEach(() => {
props = { props = {
...props, ...props,
id: '0', id: '0',
children: [],
name: 'test.jsx', name: 'test.jsx',
fileType: 'dunno', fileType: 'file',
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 +78,12 @@ describe('<FileNode />', () => {
newFolder: jest.fn(), newFolder: jest.fn(),
showFolderChildren: jest.fn(), showFolderChildren: jest.fn(),
hideFolderChildren: jest.fn(), hideFolderChildren: jest.fn(),
canEdit: true,
authenticated: false,
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));
}); });
}); });
}); });

View 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({}));
});
});
});

View file

@ -214,4 +214,5 @@ const mapDispatchToProps = {
...projectActions, ...projectActions,
}; };
export const ToolbarComponent = Toolbar;
export default connect(mapStateToProps, mapDispatchToProps)(Toolbar); export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);