mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 15:47:53 -05:00
Include unit tests for more of the action creators
This commit is contained in:
parent
a9d0ca47d7
commit
1027b82f66
7 changed files with 541 additions and 2 deletions
|
@ -42,4 +42,4 @@ const loadActivity = () => ((dispatch, getState) => {
|
|||
});
|
||||
});
|
||||
|
||||
export {loadActivity};
|
||||
export {Errors, loadActivity};
|
||||
|
|
|
@ -19,7 +19,7 @@ const Errors = keyMirror({
|
|||
|
||||
const normalizeError = (err, body, res) => {
|
||||
if (err) return Errors.NETWORK;
|
||||
if (res.statusCode === 403 && body.mute_status) return Errors.USER_MUTED;
|
||||
if (res.statusCode === 403 && body && body.mute_status) return Errors.USER_MUTED;
|
||||
if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION;
|
||||
if (res.statusCode === 404) return Errors.UNKNOWN_PROJECT;
|
||||
if (res.statusCode === 409) return Errors.DUPLICATE;
|
||||
|
|
125
test/unit/redux/project-comment-actions.test.js
Normal file
125
test/unit/redux/project-comment-actions.test.js
Normal file
|
@ -0,0 +1,125 @@
|
|||
import actions from '../../../src/redux/project-comment-actions';
|
||||
import configureStore from '../../../src/lib/configure-store';
|
||||
import {commentsReducer} from '../../../src/redux/comments';
|
||||
|
||||
jest.mock('../../../src/lib/api');
|
||||
import api from '../../../src/lib/api';
|
||||
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
api.mockClear();
|
||||
// TODO Ideally this would be the entire project page reducer list
|
||||
store = configureStore({comments: commentsReducer}, {});
|
||||
});
|
||||
|
||||
describe('getTopLevelComments', () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments');
|
||||
const body = [
|
||||
{id: 1, reply_count: 0},
|
||||
{id: 50, reply_count: 1},
|
||||
{id: 60, reply_count: 0},
|
||||
{id: 70, reply_count: 1}
|
||||
];
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/50/replies');
|
||||
const body = [{id: 4, parent_id: 50}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/70/replies');
|
||||
const body = [{id: 5, parent_id: 70}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getTopLevelComments(123123, 0, 'u'));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(4);
|
||||
expect(state.comments.replies[50].length).toBe(1);
|
||||
expect(state.comments.replies[70].length).toBe(1);
|
||||
expect(state.comments.replies[1]).toBeUndefined();
|
||||
expect(state.comments.replies[60]).toBeUndefined();
|
||||
});
|
||||
test('admin route is used correctly', async () => {
|
||||
api.mockImplementationOnce((opts) => {
|
||||
// NB: this route doesn't include the owner username
|
||||
expect(opts.uri).toBe('/admin/projects/123123/comments');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
store.dispatch(actions.getTopLevelComments(123123, 0, 'u', true, 'a-token'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCommentById', () => {
|
||||
test('getting a top level comment will not load replies if there arent any', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 0};
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(123123, 111, 'u'));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[111]).toBeUndefined();
|
||||
});
|
||||
|
||||
test('admin route is used correctly', async () => {
|
||||
api.mockImplementationOnce((opts) => {
|
||||
// NB: this route doesn't include the owner username
|
||||
expect(opts.uri).toBe('/admin/projects/123123/comments/111');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
store.dispatch(actions.getCommentById(123123, 111, 'u', true, 'a-token'));
|
||||
});
|
||||
|
||||
test('getting a top level comment will load replies', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 2};
|
||||
callback(null, body, {statusCode: 200});
|
||||
}).mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111/replies');
|
||||
const body = [{id: 1, parent_id: 111}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(123123, 111, 'u'));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[111].length).toBe(1);
|
||||
});
|
||||
|
||||
test('getting a reply comment will load the parent comment and its other replies', async () => {
|
||||
// Expect 3 requests. First 111, which is a reply comment, maybe linked to from messages
|
||||
// Second is for 111's parent, which is 555.
|
||||
// Third is for 555's replies, which returns 111 and 112
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111');
|
||||
const body = {id: 111, parent_id: 555};
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/555');
|
||||
const body = {id: 555, reply_count: 2};
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/555/replies');
|
||||
const body = [{id: 111, parent_id: 555}, {id: 112, parent_id: 555}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(123123, 111, 'u'));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[555].length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('addNewComment', () => { });
|
||||
describe.skip('deleteComment', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('resetComments', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('getReplies', () => { });
|
54
test/unit/redux/studio-activity-actions.test.js
Normal file
54
test/unit/redux/studio-activity-actions.test.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
import {
|
||||
Errors,
|
||||
loadActivity
|
||||
} from '../../../src/views/studio/lib/studio-activity-actions';
|
||||
import {activity} from '../../../src/views/studio/lib/redux-modules';
|
||||
import {reducers, initialState} from '../../../src/views/studio/studio-redux';
|
||||
import configureStore from '../../../src/lib/configure-store';
|
||||
|
||||
jest.mock('../../../src/lib/api');
|
||||
import api from '../../../src/lib/api';
|
||||
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
api.mockClear();
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadActivity', () => {
|
||||
test('it populates the activity list', () => {
|
||||
api.mockImplementation((opts, callback) => {
|
||||
const body = [{id: 1}, {id: 2}, {id: 3, datetime_created: 'abc'}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(loadActivity());
|
||||
let items = activity.selector(store.getState()).items;
|
||||
expect(api.mock.calls[0][0].uri).toBe('/studios/123123/activity/');
|
||||
expect(api.mock.calls[0][0].params.offset).toBeUndefined();
|
||||
expect(items.length).toBe(3);
|
||||
expect(items[0].id).toBe(1);
|
||||
|
||||
// On next loadActivity request, it should include the last activity items
|
||||
// datetime_created as the dateLimit. It should de-duplicate based on id
|
||||
api.mockImplementation((opts, callback) => {
|
||||
const body = [{id: 3}, {id: 4}, {id: 5, datetime_created: 'def'}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(loadActivity());
|
||||
expect(api.mock.calls[1][0].params.dateLimit).toBe('abc');
|
||||
items = activity.selector(store.getState()).items;
|
||||
expect(items.length).toBe(5); // id=3 should get de-duplicated
|
||||
});
|
||||
|
||||
test('errors are set on the activity state', () => {
|
||||
api.mockImplementation((opts, callback) => {
|
||||
callback(null, null, {statusCode: 500});
|
||||
});
|
||||
store.dispatch(loadActivity());
|
||||
expect(activity.selector(store.getState()).error).toBe(Errors.SERVER);
|
||||
});
|
||||
});
|
139
test/unit/redux/studio-comment-actions.test.js
Normal file
139
test/unit/redux/studio-comment-actions.test.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
import actions from '../../../src/redux/studio-comment-actions';
|
||||
import {reducers, initialState} from '../../../src/views/studio/studio-redux';
|
||||
import configureStore from '../../../src/lib/configure-store';
|
||||
|
||||
jest.mock('../../../src/lib/api');
|
||||
import api from '../../../src/lib/api';
|
||||
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
api.mockClear();
|
||||
});
|
||||
|
||||
describe('getTopLevelComments', () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments');
|
||||
const body = [
|
||||
{id: 1, reply_count: 0},
|
||||
{id: 50, reply_count: 1},
|
||||
{id: 60, reply_count: 0},
|
||||
{id: 70, reply_count: 1}
|
||||
];
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/50/replies');
|
||||
const body = [{id: 4, parent_id: 50}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/70/replies');
|
||||
const body = [{id: 5, parent_id: 70}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getTopLevelComments());
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(4);
|
||||
expect(state.comments.replies[50].length).toBe(1);
|
||||
expect(state.comments.replies[70].length).toBe(1);
|
||||
expect(state.comments.replies[1]).toBeUndefined();
|
||||
expect(state.comments.replies[60]).toBeUndefined();
|
||||
});
|
||||
test('admin route is used when the session shows the user is an admin', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123},
|
||||
session: {
|
||||
session: {
|
||||
user: {token: 'a-token'},
|
||||
permissions: {admin: true}
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementationOnce((opts) => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/comments');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
store.dispatch(actions.getTopLevelComments());
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCommentById', () => {
|
||||
test('getting a top level comment will not load replies if there arent any', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 0};
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(111));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[111]).toBeUndefined();
|
||||
});
|
||||
|
||||
test('getting a top level comment will load replies', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 2};
|
||||
callback(null, body, {statusCode: 200});
|
||||
}).mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/111/replies');
|
||||
const body = [{id: 1, parent_id: 111}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(111));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[111].length).toBe(1);
|
||||
});
|
||||
|
||||
test('getting a reply comment will load the parent comment and its other replies', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
// Expect 3 requests. First 111, which is a reply comment, maybe linked to from messages
|
||||
// Second is for 111's parent, which is 555.
|
||||
// Third is for 555's replies, which returns 111 and 112
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/111');
|
||||
const body = {id: 111, parent_id: 555};
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/555');
|
||||
const body = {id: 555, reply_count: 2};
|
||||
callback(null, body, {statusCode: 200});
|
||||
})
|
||||
.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/comments/555/replies');
|
||||
const body = [{id: 111, parent_id: 555}, {id: 112, parent_id: 555}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(actions.getCommentById(111));
|
||||
const state = store.getState();
|
||||
expect(state.comments.comments.length).toBe(1);
|
||||
expect(state.comments.replies[555].length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('addNewComment', () => { });
|
||||
describe.skip('deleteComment', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('resetComments', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('getReplies', () => { });
|
|
@ -22,6 +22,36 @@ beforeEach(() => {
|
|||
api.mockClear();
|
||||
});
|
||||
|
||||
|
||||
const storage = {
|
||||
max: undefined,
|
||||
items: []
|
||||
};
|
||||
|
||||
Object.defineProperty(storage, 'max', {writable: false, value: 5000});
|
||||
|
||||
let currentStorage = 'undefined';
|
||||
|
||||
const storageUsed = () => {
|
||||
if (currentStorage) {
|
||||
return currentStorage;
|
||||
}
|
||||
currentStorage = 0;
|
||||
for (const i = 0; i < storage.length(); i++) {
|
||||
currentStorage += storage.items[i].weigth;
|
||||
}
|
||||
return currentStorage;
|
||||
};
|
||||
|
||||
const add = (item) => {
|
||||
if (storage.max - item.weight >= storageUsed()) {
|
||||
storage.items.push(item);
|
||||
currentStorage += iten.weight;
|
||||
}
|
||||
};
|
||||
|
||||
add({weight: 100});
|
||||
|
||||
describe('loadManagers', () => {
|
||||
test('it populates the managers list', () => {
|
||||
store = configureStore(reducers, {
|
||||
|
|
191
test/unit/redux/studio-project-actions.test.js
Normal file
191
test/unit/redux/studio-project-actions.test.js
Normal file
|
@ -0,0 +1,191 @@
|
|||
import {selectStudioManagerCount} from '../../../src/redux/studio';
|
||||
import {
|
||||
Errors,
|
||||
loadProjects,
|
||||
addProject,
|
||||
removeProject
|
||||
} from '../../../src/views/studio/lib/studio-project-actions';
|
||||
import {projects} from '../../../src/views/studio/lib/redux-modules';
|
||||
import {reducers, initialState} from '../../../src/views/studio/studio-redux';
|
||||
import configureStore from '../../../src/lib/configure-store';
|
||||
|
||||
jest.mock('../../../src/lib/api');
|
||||
import api from '../../../src/lib/api';
|
||||
|
||||
let store;
|
||||
|
||||
beforeEach(() => {
|
||||
api.mockClear();
|
||||
});
|
||||
|
||||
describe('loadProjects', () => {
|
||||
test('it populates the projects list', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
api.mockImplementation((opts, callback) => {
|
||||
const body = [{id: 1}, {id: 2}, {id: 3}];
|
||||
callback(null, body, {statusCode: 200});
|
||||
});
|
||||
store.dispatch(loadProjects());
|
||||
let items = projects.selector(store.getState()).items;
|
||||
expect(api.mock.calls[0][0].uri).toBe('/studios/123123/projects/');
|
||||
expect(api.mock.calls[0][0].params.offset).toBe(0);
|
||||
expect(items.length).toBe(3);
|
||||
expect(items[0].id).toBe(1);
|
||||
|
||||
// Include the new offset next time it is called
|
||||
store.dispatch(loadProjects());
|
||||
expect(api.mock.calls[1][0].params.offset).toBe(3);
|
||||
items = projects.selector(store.getState()).items;
|
||||
expect(items.length).toBe(6);
|
||||
});
|
||||
|
||||
test('it correctly uses the admin route when possible', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123},
|
||||
session: {
|
||||
session: {
|
||||
user: {token: 'a-token'},
|
||||
permissions: {admin: true}
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementation((opts) => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/projects/');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
store.dispatch(loadProjects());
|
||||
});
|
||||
|
||||
test('errors are set on the projects state', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
api.mockImplementation((opts, callback) => {
|
||||
callback(null, null, {statusCode: 500});
|
||||
});
|
||||
store.dispatch(loadProjects());
|
||||
expect(projects.selector(store.getState()).error).toBe(Errors.SERVER);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addProject', () => {
|
||||
beforeEach(() => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
});
|
||||
});
|
||||
test('makes a POST and a GET and then combines the result and puts it in redux', async () => {
|
||||
const postResponse = {
|
||||
projectId: '111',
|
||||
actorId: 'actor-id'
|
||||
};
|
||||
const getResponse = {
|
||||
title: 'project-title',
|
||||
image: 'project-image',
|
||||
author: {
|
||||
id: 'author-id',
|
||||
username: 'author-username',
|
||||
profile: {images: [1, 2, 3]}
|
||||
}
|
||||
};
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/project/111');
|
||||
expect(opts.method).toBe('POST');
|
||||
callback(null, postResponse, {statusCode: 200});
|
||||
}).mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/projects/111');
|
||||
callback(null, getResponse, {statusCode: 200});
|
||||
});
|
||||
await store.dispatch(addProject('scratch.mit.edu/projects/111'));
|
||||
const {items} = projects.selector(store.getState());
|
||||
expect(items.length).toBe(1);
|
||||
// Item in redux is a combination of get/post that matches the shape of the studio projects endpoint
|
||||
expect(items[0]).toMatchObject({
|
||||
id: 111,
|
||||
actor_id: 'actor-id',
|
||||
title: 'project-title',
|
||||
image: 'project-image',
|
||||
creator_id: 'author-id',
|
||||
username: 'author-username',
|
||||
avatar: [1, 2, 3]
|
||||
});
|
||||
});
|
||||
test('submitting an invalid returns error without network requests', async () => {
|
||||
await expect(store.dispatch(addProject('abc')))
|
||||
.rejects.toBe(Errors.UNKNOWN_PROJECT);
|
||||
expect(api.mock.calls.length).toBe(0);
|
||||
});
|
||||
test('submitting an existing project returns error without network requests', async () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123},
|
||||
projects: {items: [{id: 999}]}
|
||||
});
|
||||
await expect(store.dispatch(addProject('localhost:800/projects/999')))
|
||||
.rejects.toBe(Errors.DUPLICATE);
|
||||
expect(api.mock.calls.length).toBe(0);
|
||||
});
|
||||
test('rate limit server response', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
callback(null, null, {statusCode: 429});
|
||||
});
|
||||
await expect(store.dispatch(addProject('localhost:800/projects/999')))
|
||||
.rejects.toBe(Errors.RATE_LIMIT);
|
||||
});
|
||||
test('unknown project server response', async () => {
|
||||
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
callback(null, null, {statusCode: 404});
|
||||
});
|
||||
await expect(store.dispatch(addProject('localhost:800/projects/999')))
|
||||
.rejects.toBe(Errors.UNKNOWN_PROJECT);
|
||||
});
|
||||
test('not allowed server response', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
callback(null, null, {statusCode: 403});
|
||||
});
|
||||
await expect(store.dispatch(addProject('localhost:800/projects/999')))
|
||||
.rejects.toBe(Errors.PERMISSION);
|
||||
});
|
||||
test('muted server response', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
callback(null, {mute_status: {}}, {statusCode: 403});
|
||||
});
|
||||
await expect(store.dispatch(addProject('localhost:800/projects/999')))
|
||||
.rejects.toBe(Errors.USER_MUTED);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeProject', () => {
|
||||
beforeEach(() => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123},
|
||||
projects: {items: [{id: 999}]}
|
||||
});
|
||||
});
|
||||
test('makes a DELETE and removes the item from redux', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/studios/123123/project/999');
|
||||
expect(opts.method).toBe('DELETE');
|
||||
callback(null, {}, {statusCode: 200});
|
||||
});
|
||||
await store.dispatch(removeProject(999));
|
||||
const {items} = projects.selector(store.getState());
|
||||
expect(items.length).toBe(0);
|
||||
});
|
||||
|
||||
test('errors are set on the projects state', async () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
callback(null, {}, {statusCode: 500});
|
||||
});
|
||||
await expect(store.dispatch(removeProject(999)))
|
||||
.rejects.toBe(Errors.SERVER);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue