624 lines
19 KiB
JavaScript
624 lines
19 KiB
JavaScript
import configureMockStore from 'redux-mock-store';
|
||
import thunk from 'redux-thunk';
|
||
import fetchMock from 'fetch-mock';
|
||
|
||
import * as actions from '../../../pages/homepage/actions/posts.js';
|
||
import * as errorActions from '../../../pages/homepage/actions/error.js';
|
||
import * as constants from '../../../pages/homepage/constants.js';
|
||
|
||
const middlewares = [thunk];
|
||
const mockStore = configureMockStore(middlewares);
|
||
|
||
describe('post actions', () => {
|
||
afterEach(() => {
|
||
fetchMock.restore();
|
||
});
|
||
|
||
it('should create an action to request posts', () => {
|
||
const expectedAction = { type: actions.REQUEST_POSTS };
|
||
|
||
expect(actions.requestPosts()).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action to mark a post read', () => {
|
||
const expectedAction = { type: actions.MARKING_POST };
|
||
|
||
expect(actions.markingPostRead()).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action to toggle post saved state', () => {
|
||
const expectedAction = { type: actions.TOGGLING_POST };
|
||
|
||
expect(actions.togglingPost()).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action receive a post', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const expectedAction = {
|
||
type: actions.RECEIVE_POST,
|
||
post,
|
||
};
|
||
|
||
expect(actions.receivePost(post)).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action to select a post', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const expectedAction = {
|
||
type: actions.SELECT_POST,
|
||
post,
|
||
};
|
||
|
||
expect(actions.selectPost(post)).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action to unselect a post', () => {
|
||
const expectedAction = { type: actions.UNSELECT_POST };
|
||
|
||
expect(actions.unSelectPost()).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action mark a post read', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
const expectedAction = {
|
||
type: actions.MARK_POST_READ,
|
||
section: rule,
|
||
post,
|
||
};
|
||
|
||
expect(actions.postRead(post, rule)).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create an action toggling post saved', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const expectedAction = {
|
||
type: actions.TOGGLED_POST,
|
||
post,
|
||
};
|
||
|
||
expect(actions.postToggled(post)).toEqual(expectedAction);
|
||
});
|
||
|
||
it('should create multiple actions to mark post read', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const rule = {
|
||
id: 1,
|
||
name: 'Test rule',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
fetchMock.patchOnce('/api/posts/2067/', {
|
||
body: { ...post, read: true },
|
||
headers: { 'content-type': 'application/json' },
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: {
|
||
item: rule,
|
||
next: false,
|
||
lastReached: false,
|
||
post: {},
|
||
},
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.MARKING_POST },
|
||
{
|
||
type: actions.RECEIVE_POST,
|
||
post: { ...post, read: true },
|
||
},
|
||
{
|
||
type: actions.MARK_POST_READ,
|
||
post: { ...post, read: true },
|
||
section: rule,
|
||
},
|
||
];
|
||
|
||
return store.dispatch(actions.markPostRead(post, 'TOKEN')).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should create multiple actions to toggle a post saved', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const rule = {
|
||
id: 1,
|
||
name: 'Test rule',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
fetchMock.patchOnce('/api/posts/2067/', {
|
||
body: { ...post, saved: true },
|
||
headers: { 'content-type': 'application/json' },
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: {
|
||
item: rule,
|
||
next: false,
|
||
lastReached: false,
|
||
post: {},
|
||
},
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.TOGGLING_POST },
|
||
{
|
||
type: actions.RECEIVE_POST,
|
||
post: { ...post, saved: true },
|
||
},
|
||
{
|
||
type: actions.TOGGLED_POST,
|
||
post: { ...post, saved: true },
|
||
},
|
||
];
|
||
|
||
return store.dispatch(actions.toggleSaved(post, 'TOKEN')).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should create multiple actions to fetch posts by rule', () => {
|
||
const posts = [
|
||
{
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 4,
|
||
read: false,
|
||
saved: false,
|
||
},
|
||
{
|
||
id: 2141,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648757',
|
||
title: 'The most complete brain map ever is here: A fly’s “connectome”',
|
||
body:
|
||
'It took 12 years and at least $40 million to chart a region about 250µm across.',
|
||
author: 'WIRED',
|
||
publicationDate: '2020-01-25T11:06:46Z',
|
||
url: 'https://arstechnica.com/?p=1648757',
|
||
rule: 4,
|
||
read: false,
|
||
saved: false,
|
||
},
|
||
];
|
||
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
type: constants.RULE_TYPE,
|
||
};
|
||
|
||
fetchMock.getOnce('/api/rules/4/posts/?read=false', {
|
||
body: {
|
||
count: 2,
|
||
next: 'https://durp.com/api/rules/4/posts/?cursor=jabadabar&read=false',
|
||
previous: null,
|
||
results: posts,
|
||
},
|
||
headers: { 'content-type': 'application/json' },
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: {}, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.REQUEST_POSTS },
|
||
{
|
||
type: actions.RECEIVE_POSTS,
|
||
next: 'https://durp.com/api/rules/4/posts/?cursor=jabadabar&read=false',
|
||
posts,
|
||
},
|
||
];
|
||
|
||
return store.dispatch(actions.fetchPostsBySection(rule)).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should create multiple actions to fetch posts by category', () => {
|
||
const posts = [
|
||
{
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 4,
|
||
read: false,
|
||
saved: false,
|
||
},
|
||
{
|
||
id: 2141,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648757',
|
||
title: 'The most complete brain map ever is here: A fly’s “connectome”',
|
||
body:
|
||
'It took 12 years and at least $40 million to chart a region about 250µm across.',
|
||
author: 'WIRED',
|
||
publicationDate: '2020-01-25T11:06:46Z',
|
||
url: 'https://arstechnica.com/?p=1648757',
|
||
rule: 4,
|
||
read: false,
|
||
saved: false,
|
||
},
|
||
];
|
||
|
||
const category = {
|
||
id: 1,
|
||
name: 'Tech',
|
||
unread: 2,
|
||
type: constants.CATEGORY_TYPE,
|
||
};
|
||
|
||
fetchMock.getOnce('/api/categories/1/posts/?read=false', {
|
||
body: {
|
||
count: 2,
|
||
next: 'https://durp.com/api/categories/4/posts/?cursor=jabadabar&read=false',
|
||
previous: null,
|
||
results: posts,
|
||
},
|
||
headers: { 'content-type': 'application/json' },
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: {}, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.REQUEST_POSTS },
|
||
{
|
||
type: actions.RECEIVE_POSTS,
|
||
next: 'https://durp.com/api/categories/4/posts/?cursor=jabadabar&read=false',
|
||
posts,
|
||
},
|
||
];
|
||
|
||
return store.dispatch(actions.fetchPostsBySection(category)).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should create multiple actions to fetch posts by saved state', () => {
|
||
const posts = [
|
||
{
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 4,
|
||
read: false,
|
||
saved: true,
|
||
},
|
||
{
|
||
id: 2141,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648757',
|
||
title: 'The most complete brain map ever is here: A fly’s “connectome”',
|
||
body:
|
||
'It took 12 years and at least $40 million to chart a region about 250µm across.',
|
||
author: 'WIRED',
|
||
publicationDate: '2020-01-25T11:06:46Z',
|
||
url: 'https://arstechnica.com/?p=1648757',
|
||
rule: 4,
|
||
read: false,
|
||
saved: true,
|
||
},
|
||
];
|
||
|
||
fetchMock.getOnce('/api/posts/?saved=true', {
|
||
body: {
|
||
next: 'https://durp.com/api/posts/?cursor=jabadabar&saved=true',
|
||
previous: null,
|
||
results: posts,
|
||
},
|
||
headers: { 'content-type': 'application/json' },
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: {}, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.REQUEST_POSTS },
|
||
{
|
||
type: actions.RECEIVE_POSTS,
|
||
next: 'https://durp.com/api/posts/?cursor=jabadabar&saved=true',
|
||
posts,
|
||
},
|
||
];
|
||
|
||
return store.dispatch(actions.fetchSavedPosts()).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should create no actions when fetching posts and section is read', () => {
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 0,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: {}, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [];
|
||
|
||
store.dispatch(actions.fetchPostsBySection(rule));
|
||
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
|
||
it('should handle exceptions when marking a post read', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
const errorMessage = 'Permission denied';
|
||
|
||
fetchMock.patch(`/api/posts/${post.id}/`, () => {
|
||
throw new Error(errorMessage);
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: { ...rule }, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.MARKING_POST },
|
||
{ type: actions.RECEIVE_POST, post: {} },
|
||
{ type: errorActions.RECEIVE_API_ERROR, error: TypeError(errorMessage) },
|
||
];
|
||
|
||
return store.dispatch(actions.markPostRead(post, 'FAKE_TOKEN')).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should handle exceptions when toggling a post saved/unsaved', () => {
|
||
const post = {
|
||
id: 2067,
|
||
remoteIdentifier: 'https://arstechnica.com/?p=1648607',
|
||
title:
|
||
'This amazing glitch puts Star Fox 64 ships in an unmodified Zelda cartridge',
|
||
body:
|
||
'"Stale-reference manipulation," 300-character file names, and a clash between worlds.',
|
||
author: 'Kyle Orland',
|
||
publicationDate: '2020-01-24T19:50:12Z',
|
||
url: 'https://arstechnica.com/?p=1648607',
|
||
rule: 5,
|
||
read: false,
|
||
saved: false,
|
||
};
|
||
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
};
|
||
|
||
const errorMessage = 'Permission denied';
|
||
|
||
fetchMock.patch(`/api/posts/${post.id}/`, () => {
|
||
throw new Error(errorMessage);
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: { ...rule }, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.TOGGLING_POST },
|
||
{ type: actions.RECEIVE_POST, post: {} },
|
||
{ type: errorActions.RECEIVE_API_ERROR, error: Error(errorMessage) },
|
||
];
|
||
|
||
return store.dispatch(actions.toggleSaved(post, 'FAKE_TOKEN')).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
|
||
it('should handle exceptions when fetching posts by section', () => {
|
||
const rule = {
|
||
id: 4,
|
||
name: 'Ars Technica',
|
||
unread: 100,
|
||
category: 1,
|
||
url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
|
||
favicon: 'https://cdn.arstechnica.net/favicon.ico',
|
||
type: constants.RULE_TYPE,
|
||
};
|
||
|
||
const errorMessage = 'Page not found';
|
||
|
||
fetchMock.getOnce(`/api/rules/${rule.id}/posts/?read=false`, () => {
|
||
throw new Error(errorMessage);
|
||
});
|
||
|
||
const store = mockStore({
|
||
categories: { items: {}, isFetching: false },
|
||
rules: { items: {}, isFetching: false },
|
||
posts: { items: {}, isFetching: false, isUpdating: false },
|
||
selected: { item: { ...rule }, next: false, lastReached: false, post: {} },
|
||
});
|
||
|
||
const expectedActions = [
|
||
{ type: actions.REQUEST_POSTS },
|
||
{ type: actions.RECEIVE_POSTS, posts: [] },
|
||
{ type: errorActions.RECEIVE_API_ERROR, error: Error(errorMessage) },
|
||
];
|
||
|
||
return store.dispatch(actions.fetchPostsBySection(rule)).then(() => {
|
||
expect(store.getActions()).toEqual(expectedActions);
|
||
});
|
||
});
|
||
});
|