Skip to content

Commit e8206e9

Browse files
authored
Merge pull request codeBelt#31 from codeBelt/store-tests
Store tests
2 parents 7612666 + 74871ea commit e8206e9

File tree

6 files changed

+221
-131
lines changed

6 files changed

+221
-131
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"@types/react-dom": "16.9.5",
7777
"@types/react-redux": "7.1.7",
7878
"@types/react-router-dom": "5.1.3",
79+
"@types/redux-mock-store": "1.0.2",
7980
"@types/uuid": "7.0.0",
8081
"@typescript-eslint/eslint-plugin": "2.21.0",
8182
"@typescript-eslint/parser": "2.21.0",
@@ -88,10 +89,12 @@
8889
"generate-template-files": "2.2.1",
8990
"gh-pages": "2.2.0",
9091
"husky": "4.2.3",
92+
"nock": "12.0.3",
9193
"node-sass": "4.13.1",
9294
"prettier": "1.19.1",
9395
"pretty-quick": "2.0.1",
9496
"react-scripts": "3.4.0",
97+
"redux-mock-store": "1.5.4",
9598
"typescript": "3.8.3"
9699
}
97100
}

src/__fixtures__/reduxFixtures.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import configureStore from 'redux-mock-store';
2+
import thunk from 'redux-thunk';
3+
4+
export const mockStoreFixture = (state) => {
5+
const middlewares = [thunk];
6+
const storeCreator = configureStore(middlewares);
7+
8+
return storeCreator(state);
9+
};

src/stores/shows/ShowsAction.spec.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import ShowsAction from './ShowsAction';
2+
import ActionUtility from '../../utilities/ActionUtility';
3+
import { mockStoreFixture } from '../../__fixtures__/reduxFixtures';
4+
import ShowModel from './models/shows/ShowModel';
5+
import ShowsEffect from './ShowsEffect';
6+
import EpisodeModel from './models/episodes/EpisodeModel';
7+
import CastModel from './models/cast/CastModel';
8+
9+
describe('ShowsAction', () => {
10+
let store;
11+
12+
beforeEach(() => {
13+
store = mockStoreFixture({
14+
shows: {
15+
currentShowId: '74',
16+
},
17+
});
18+
});
19+
20+
afterEach(() => {
21+
jest.clearAllMocks();
22+
jest.restoreAllMocks();
23+
});
24+
25+
describe('requestShow', () => {
26+
it('has a successful response', async () => {
27+
const expectedResponse = new ShowModel({});
28+
29+
jest.spyOn(ShowsEffect, 'requestShow').mockImplementation(async () => expectedResponse);
30+
31+
await store.dispatch(ShowsAction.requestShow());
32+
33+
const actualResult = store.getActions();
34+
const expectedResult = [
35+
ActionUtility.createAction(ShowsAction.REQUEST_SHOW),
36+
ActionUtility.createAction(ShowsAction.REQUEST_SHOW_FINISHED, expectedResponse),
37+
];
38+
39+
expect(actualResult).toEqual(expectedResult);
40+
});
41+
});
42+
43+
describe('requestEpisodes', () => {
44+
it('has a successful response', async () => {
45+
const expectedResponse = [new EpisodeModel({})];
46+
47+
jest.spyOn(ShowsEffect, 'requestEpisodes').mockImplementation(async () => expectedResponse);
48+
49+
await store.dispatch(ShowsAction.requestEpisodes());
50+
51+
const actualResult = store.getActions();
52+
const expectedResult = [
53+
ActionUtility.createAction(ShowsAction.REQUEST_EPISODES),
54+
ActionUtility.createAction(ShowsAction.REQUEST_EPISODES_FINISHED, expectedResponse),
55+
];
56+
57+
expect(actualResult).toEqual(expectedResult);
58+
});
59+
});
60+
61+
describe('requestCast', () => {
62+
it('has a successful response', async () => {
63+
const expectedResponse = [new CastModel({})];
64+
65+
jest.spyOn(ShowsEffect, 'requestCast').mockImplementation(async () => expectedResponse);
66+
67+
await store.dispatch(ShowsAction.requestCast());
68+
69+
const actualResult = store.getActions();
70+
const expectedResult = [
71+
ActionUtility.createAction(ShowsAction.REQUEST_CAST),
72+
ActionUtility.createAction(ShowsAction.REQUEST_CAST_FINISHED, expectedResponse),
73+
];
74+
75+
expect(actualResult).toEqual(expectedResult);
76+
});
77+
});
78+
});

src/stores/shows/ShowsEffect.spec.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import ShowsEffect from './ShowsEffect';
2+
import nock from 'nock';
3+
import axios from 'axios';
4+
import environment from 'environment';
5+
import ShowModel from './models/shows/ShowModel';
6+
import StringUtil from '../../utilities/StringUtil';
7+
import EpisodeModel from './models/episodes/EpisodeModel';
8+
import CastModel from './models/cast/CastModel';
9+
10+
axios.defaults.adapter = require('axios/lib/adapters/http');
11+
12+
describe('ShowsEffect', () => {
13+
describe('requestShow', () => {
14+
it('has a successful response', async () => {
15+
const showId = '74';
16+
const endpoint = environment.api.shows.replace(':showId', showId);
17+
const [baseUrl, sourceUrl] = StringUtil.splitBySeparator(endpoint, '.com');
18+
19+
const scope = nock(baseUrl)
20+
.get(sourceUrl)
21+
.reply(200, { name: 'Robert' });
22+
23+
const actualResult = await ShowsEffect.requestShow(showId);
24+
25+
expect(actualResult).toBeInstanceOf(ShowModel);
26+
expect(actualResult.name).toEqual('Robert');
27+
28+
// Assert that the expected request was made.
29+
scope.done();
30+
});
31+
});
32+
33+
describe('requestEpisodes', () => {
34+
it('has a successful response', async () => {
35+
const showId = '74';
36+
const endpoint = environment.api.episodes.replace(':showId', showId);
37+
const [baseUrl, sourceUrl] = StringUtil.splitBySeparator(endpoint, '.com');
38+
39+
const scope = nock(baseUrl)
40+
.get(sourceUrl)
41+
.reply(200, [{ summary: 'Robert is cool' }]);
42+
43+
const actualResult = await ShowsEffect.requestEpisodes(showId);
44+
45+
expect(actualResult[0]).toBeInstanceOf(EpisodeModel);
46+
expect(actualResult[0].summary).toEqual('Robert is cool');
47+
48+
// Assert that the expected request was made.
49+
scope.done();
50+
});
51+
});
52+
53+
describe('requestCast', () => {
54+
it('has a successful response', async () => {
55+
const showId = '74';
56+
const endpoint = environment.api.cast.replace(':showId', showId);
57+
const [baseUrl, sourceUrl] = StringUtil.splitBySeparator(endpoint, '.com');
58+
59+
const scope = nock(baseUrl)
60+
.get(sourceUrl)
61+
.reply(200, [{ self: true }]);
62+
63+
const actualResult = await ShowsEffect.requestCast(showId);
64+
65+
expect(actualResult[0]).toBeInstanceOf(CastModel);
66+
expect(actualResult[0].self).toBe(true);
67+
68+
// Assert that the expected request was made.
69+
scope.done();
70+
});
71+
});
72+
});

src/utilities/StringUtil.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default class StringUtil {
2+
/**
3+
* Splits a string in half by a separator
4+
*
5+
* @param str string
6+
* @param separator string
7+
* @example
8+
* splitBySeparator('https://api.tvmaze.com/search/shows?q=Friends', '.com');
9+
*
10+
* // ['https://api.tvmaze.com', '/search/shows?q=Friends']
11+
*/
12+
static splitBySeparator = (str, separator) => {
13+
return str.split(new RegExp(`(.*?${separator})`, 'g')).filter(Boolean);
14+
};
15+
}

0 commit comments

Comments
 (0)