Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mavidser committed Oct 16, 2023
1 parent b961d0f commit 7d959c2
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 12 deletions.
9 changes: 5 additions & 4 deletions src/components/AssetsDropZone/AssetsDropZone.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { courseDetails } from '../../utils/testConstants';
import { mountWithIntl } from '../../utils/i18n/enzymeHelper';

const defaultProps = {
preUploadCheck: () => {},
uploadAssets: () => {},
uploadExceedMaxCount: () => {},
uploadExceedMaxSize: () => {},
Expand Down Expand Up @@ -70,13 +71,13 @@ describe('<AssetsDropZone />', () => {
wrapper.instance().onDrop([{}, {}], [{}]);
expect(mockUploadInvalidFileType).toBeCalled();
});
it('call uploadAssets() for successful uploads', () => {
const mockUploadAssets = jest.fn();
it('call preUploadCheck() for approved files', () => {
const mockPreUploadCheck = jest.fn();
wrapper.setProps({
uploadAssets: mockUploadAssets,
preUploadCheck: mockPreUploadCheck,
});
wrapper.instance().onDrop([{}, {}], []);
expect(mockUploadAssets).toBeCalled();
expect(mockPreUploadCheck).toBeCalled();
});
});

Expand Down
107 changes: 107 additions & 0 deletions src/components/AssetsUploadConfirm/AssetsUploadConfirm.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import { Button, StatusAlert } from '@edx/paragon';

import AssetUploadConfirm from './index';
import { mountWithIntl } from '../../utils/i18n/enzymeHelper';

const statusAlertIsClosed = (wrapper) => {
expect(wrapper.state('statusAlertOpen')).toEqual(false);
expect(wrapper.find(StatusAlert).prop('open')).toEqual(false);
expect(wrapper.find(AssetUploadConfirm).prop('pre_upload_error')).toEqual('');
};

const statusAlertIsOpen = (wrapper) => {
expect(wrapper.state('statusAlertOpen')).toEqual(true);
expect(wrapper.find(StatusAlert).prop('open')).toEqual(true);
expect(wrapper.find(AssetUploadConfirm).prop('pre_upload_error')).toBeTruthy();
};

const errorMessageHasCorrectFiles = (wrapper, files) => {
const statusAlert = wrapper.find(AssetUploadConfirm);
const statusAlertMessage = statusAlert.prop('pre_upload_error');

files.map(file => {
expect(statusAlertMessage).toContain(file);
})
};

const defaultProps = {
files: [],
uploadAssets: () => { },
clearPreUploadProps: () => {},
courseDetails: {},
pre_upload_error: '',
};

let wrapper;

describe('AssetsUploadConfirm', () => {
describe('renders', () => {
it('closed by default', () => {
wrapper = mountWithIntl(
<AssetUploadConfirm
{...defaultProps}
/>,
);

statusAlertIsClosed(wrapper)
});

it('open if there is an error message', () => {
wrapper = mountWithIntl(
<AssetUploadConfirm
{...defaultProps}
/>,
);
wrapper.setProps({
pre_upload_error: 'The following files already exist: asset.jpg',
});

statusAlertIsOpen(wrapper);
errorMessageHasCorrectFiles(wrapper, ['asset.jpg']);
});
});
describe('behaves', () => {
it('Overwrite calls uploadAssets', () => {
wrapper = mountWithIntl(
<AssetUploadConfirm
{...defaultProps}
/>,
);
const mockUploadAssets = jest.fn();
const files = ['file1', 'file2'];
const courseDetails = {
id: 'course-v1:edX+DemoX+Demo_Course',
};
wrapper.setProps({
files,
courseDetails,
uploadAssets: mockUploadAssets,
});

wrapper.find(Button).filterWhere(button => button.text() === 'Overwrite').simulate('click');
expect(mockUploadAssets).toBeCalledWith(files, courseDetails)
});

it('clicking close button closes the status alert', () => {
wrapper = mountWithIntl(
<AssetUploadConfirm
{...defaultProps}
/>,
);
wrapper.setProps({
pre_upload_error: 'The following files already exist: asset.jpg',
clearPreUploadProps: () => {
wrapper.setProps({
...defaultProps,
})
},
});

const statusAlert = wrapper.find(StatusAlert);
const closeStatusAlertButton = statusAlert.find('button').filterWhere(button => button.text() === '×');
closeStatusAlertButton.simulate('click');
statusAlertIsClosed(wrapper);
});
});
});
3 changes: 2 additions & 1 deletion src/components/AssetsUploadConfirm/container.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';

import { uploadAssets } from '../../data/actions/assets';
import { uploadAssets, clearPreUploadProps } from '../../data/actions/assets';
import AssetsUploadConfirm from '.';

const mapStateToProps = state => ({
Expand All @@ -11,6 +11,7 @@ const mapStateToProps = state => ({

const mapDispatchToProps = dispatch => ({
uploadAssets: (assets, courseDetails) => dispatch(uploadAssets(assets, courseDetails)),
clearPreUploadProps: () => dispatch(clearPreUploadProps()),
});

const WrappedAssetsUploadConfirm = connect(
Expand Down
11 changes: 7 additions & 4 deletions src/components/AssetsUploadConfirm/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default class AssetsUploadConfirm extends React.Component {
}

componentWillReceiveProps(nextProps) {
const { files, courseDetails, pre_upload_error } = nextProps;
this.updateStates(files, courseDetails, pre_upload_error);
const { pre_upload_error } = nextProps;
this.updateAlertOpenState(pre_upload_error);
}

updateStates = (files, courseDetails, pre_upload_error) => {
updateAlertOpenState = (pre_upload_error) => {
this.setState({
statusAlertOpen: pre_upload_error ? true : false,
})
Expand All @@ -37,13 +37,14 @@ export default class AssetsUploadConfirm extends React.Component {

onClose = () => {
this.setState(defaultState);
this.props.clearPreUploadProps();
}

render() {
const uploadFiles = this.uploadFiles;
const { statusAlertOpen } = this.state
const { pre_upload_error } = this.props
content = (
const content = (
<div>
<WrappedMessage
message={messages.assetsUploadConfirmMessage}
Expand Down Expand Up @@ -72,6 +73,7 @@ export default class AssetsUploadConfirm extends React.Component {
AssetsUploadConfirm.propTypes = {
files: PropTypes.arrayOf(PropTypes.string),
uploadAssets: PropTypes.func.isRequired,
clearPreUploadProps: PropTypes.func.isRequired,
courseDetails: PropTypes.shape({
lang: PropTypes.string,
url_name: PropTypes.string,
Expand All @@ -87,4 +89,5 @@ AssetsUploadConfirm.propTypes = {

AssetsUploadConfirm.defaultProps = {
files: [],
pre_upload_error: '',
};
10 changes: 7 additions & 3 deletions src/data/actions/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,7 @@ export const uploadAssetFailure = (asset, response) => ({
});

export const uploadAssets = (assets, courseDetails) => (dispatch) => {
dispatch(setPreUploadError(''))
dispatch(setFilesToUpload([]));
dispatch(clearPreUploadProps());
dispatch(uploadingAssets(assets.length));
// gather all the promises into a single promise that can be returned
return Promise.all(assets.map(asset => (
Expand All @@ -294,7 +293,7 @@ export const uploadAssets = (assets, courseDetails) => (dispatch) => {
};

export const preUploadCheck = (assets, courseDetails) => (dispatch) => {
clientApi.preUploadCheck(courseDetails.id, assets.map(asset => asset.name))
return clientApi.preUploadCheck(courseDetails.id, assets.map(asset => asset.name))
.then((response) => {
if (response.ok) {
return response.json().then((json) => {
Expand All @@ -308,6 +307,11 @@ export const preUploadCheck = (assets, courseDetails) => (dispatch) => {
})
};

export const clearPreUploadProps = () => (dispatch) => {
dispatch(setFilesToUpload([]));
dispatch(setPreUploadError(''));
};

export const setFilesToUpload = (files) => ({
type: assetActions.files.FILES_UPDATE,
files,
Expand Down
63 changes: 63 additions & 0 deletions src/data/actions/assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ const getUploadResponse = isSuccess => (
})
);

// currying a function that can be passed to fetch-mock to determine what
// response should be based on whether or not pre-upload check succeeds or fails
const getPreUploadCheckResponse = isSuccess => (
(url, opts) => ({
status: isSuccess ? 200 : 409,
body: {
allowed: isSuccess,
reason: isSuccess ? '' : 'error',
},
})
);

describe('Assets Action Creators', () => {
beforeEach(() => {
store = mockStore(initialState);
Expand Down Expand Up @@ -712,6 +724,53 @@ describe('Assets Action Creators', () => {
expect(store.dispatch(actionCreators.uploadingAssets(99, 'response'))).toEqual(expectedAction);
});

it('returns expected state from preUploadCheck success', () => {
const assetsResponse = {
status: 200,
body: {
assets: ['a.txt'],
},
};

fetchMock.mock(`begin:${assetsEndpoint}`, getPreUploadCheckResponse(true), { method: 'post' });
fetchMock.mock(`begin:${assetsEndpoint}`, assetsResponse, { method: 'get' });

const assets = ['a.txt', 'b.txt', 'c.txt'];

const expectedActions = [
{ files: [], type: assetActions.files.FILES_UPDATE },
{ pre_upload_error: '', type: assetActions.files.FILES_PRE_UPLOAD_ERROR },
];

return store.dispatch(actionCreators.preUploadCheck(assets, courseDetails)).then(() => {
expect(store.getActions().slice(0,2)).toEqual(expectedActions);
// the rest of the actions are similar to what executes in uploadAssets, and tested there
});
})

it('returns expected state from preUploadCheck failure', () => {
const assetsResponse = {
status: 200,
body: {
assets: ['a.txt'],
},
};

fetchMock.mock(`begin:${assetsEndpoint}`, getPreUploadCheckResponse(false), { method: 'post' });
fetchMock.mock(`begin:${assetsEndpoint}`, assetsResponse, { method: 'get' });

const assets = ['a.txt', 'b.txt', 'c.txt'];

const expectedActions = [
{ files: assets, type: assetActions.files.FILES_UPDATE },
{ pre_upload_error: 'error', type: assetActions.files.FILES_PRE_UPLOAD_ERROR },
];

return store.dispatch(actionCreators.preUploadCheck(assets, courseDetails)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
})

it('returns expected state from uploadAssets success', () => {
const assetsResponse = {
status: 200,
Expand All @@ -726,6 +785,8 @@ describe('Assets Action Creators', () => {
const assets = ['a.txt', 'b.txt', 'c.txt'];

const expectedActions = [
{ files: [], type: assetActions.files.FILES_UPDATE },
{ pre_upload_error: '', type: assetActions.files.FILES_PRE_UPLOAD_ERROR },
{ count: assets.length, type: assetActions.upload.UPLOADING_ASSETS },
];

Expand Down Expand Up @@ -761,6 +822,8 @@ describe('Assets Action Creators', () => {
const assets = ['a.txt', 'b.txt', 'c.txt'];

const expectedActions = [
{ files: [], type: assetActions.files.FILES_UPDATE },
{ pre_upload_error: '', type: assetActions.files.FILES_PRE_UPLOAD_ERROR },
{ count: assets.length, type: assetActions.upload.UPLOADING_ASSETS },
];

Expand Down
26 changes: 26 additions & 0 deletions src/data/reducers/assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,30 @@ describe('Assets Reducers', () => {
});
});
});
describe('files reducer', () => {
it('returns correct files state on FILES_UPDATE action', () => {
defaultState = [];

action = {
files: ['file1', 'file2'],
type:assetActions.files.FILES_UPDATE,
};

state = reducers.files(defaultState, action);

expect(state).toEqual(['file1', 'file2']);
});
it('returns correct pre_upload_error state on FILES_PRE_UPLOAD_ERROR action', () => {
defaultState = '';

action = {
pre_upload_error: 'error',
type: assetActions.files.FILES_PRE_UPLOAD_ERROR,
};

state = reducers.pre_upload_error(defaultState, action);

expect(state).toEqual('error');
});
});
});

0 comments on commit 7d959c2

Please sign in to comment.