Skip to content

Write tests for name verification logic (<ToolBar />, <FileNode />) #1410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 22, 2020
149 changes: 130 additions & 19 deletions client/components/__test__/FileNode.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,74 @@ import React from 'react';
import { shallow } from 'enzyme';
import { FileNode } from '../../modules/IDE/components/FileNode';

beforeAll(() => {});
describe('<FileNode />', () => {
let component;
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(() => {
props = {
...props,
id: '0',
children: [],
name: 'test.jsx',
fileType: 'dunno',
fileType: 'file',
canEdit: true,
children: [],
authenticated: false,
setSelectedFile: jest.fn(),
deleteFile: jest.fn(),
updateFileName: jest.fn(),
Expand All @@ -23,22 +78,12 @@ describe('<FileNode />', () => {
newFolder: jest.fn(),
showFolderChildren: jest.fn(),
hideFolderChildren: jest.fn(),
canEdit: true,
authenticated: false,
openUploadFileModal: jest.fn()
};
component = shallow(<FileNode {...props} />);
});

describe('when changing name', () => {
let input;
let renameTriggerButton;
const changeName = (newFileName) => {
renameTriggerButton.simulate('click');
input.simulate('change', { target: { value: newFileName } });
input.simulate('blur');
};

beforeEach(() => {
input = component.find('.sidebar__file-item-input');
renameTriggerButton = component
Expand All @@ -59,13 +104,79 @@ describe('<FileNode />', () => {
});
});

describe('to an empty filename', () => {
const newName = '';
// Failure Scenarios

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));

it('should not save the name', () => {
expect(props.updateFileName).not.toHaveBeenCalled();
});
it('should not save', () => expect(props.setProjectName).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));
});
});
});
Expand Down
105 changes: 105 additions & 0 deletions client/components/__test__/Toolbar.test.jsx
Original file line number Diff line number Diff line change
@@ -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({}));
});
});
});
1 change: 1 addition & 0 deletions client/modules/IDE/components/Toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ const mapDispatchToProps = {
...projectActions,
};

export const ToolbarComponent = Toolbar;
export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);