Skip to content
This repository was archived by the owner on Sep 6, 2022. It is now read-only.

Commit 3ab0f48

Browse files
committed
utils test cases finished, linting errors fixed
1 parent ae0fe38 commit 3ab0f48

15 files changed

+1091
-1960
lines changed

app/components/A/tests/index.test.tsx

Lines changed: 0 additions & 53 deletions
This file was deleted.

app/utils/injectSaga.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as React from 'react';
22
import hoistNonReactStatics from 'hoist-non-react-statics';
3-
import { ReactReduxContext } from 'react-redux';
3+
import { useStore } from 'react-redux';
44

5-
import getInjectors from './sagaInjectors';
5+
import { getInjectors } from './sagaInjectors';
66
import { InjectSagaParams, LifeStore } from 'types';
77

88
/**
@@ -25,7 +25,7 @@ export default function hocWithSaga<P>({ key, saga, mode }: InjectSagaParams) {
2525
class InjectSaga extends React.Component<P> {
2626
public static WrappedComponent = WrappedComponent;
2727

28-
public static contextType = ReactReduxContext;
28+
// public static contextType = ReactReduxContext;
2929
public injectors: any;
3030

3131
public static displayName = `withSaga(${WrappedComponent.displayName ||
@@ -55,9 +55,9 @@ export default function hocWithSaga<P>({ key, saga, mode }: InjectSagaParams) {
5555
}
5656

5757
const useInjectSaga = ({ key, saga, mode }: InjectSagaParams) => {
58-
const context = React.useContext(ReactReduxContext);
58+
const store = useStore() as LifeStore;
5959
React.useEffect(() => {
60-
const injectors = getInjectors(context.store as LifeStore);
60+
const injectors = getInjectors(store);
6161
injectors.injectSaga(key, { saga: saga, mode: mode });
6262

6363
return () => {

app/utils/reducerInjectors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import createReducer from '../reducers';
88
import { LifeStore } from 'types';
99
import { Reducer } from 'redux';
1010

11-
export function injectReducerFactory(store: LifeStore, isValid: boolean) {
11+
export function injectReducerFactory(store: LifeStore, isValid: boolean = false) {
1212
return function injectReducer(key: string, reducer: Reducer<object>) {
1313
if (!isValid) {
1414
checkStore(store);
@@ -33,7 +33,7 @@ export function injectReducerFactory(store: LifeStore, isValid: boolean) {
3333
};
3434
}
3535

36-
export default function getInjectors(store: LifeStore) {
36+
export function getInjectors(store: LifeStore) {
3737
checkStore(store);
3838

3939
return {

app/utils/request.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export class ResponseError extends Error {
77
this.response = response;
88
}
99
}
10-
1110
/**
1211
* Parses the JSON returned by a network request
1312
*
@@ -16,6 +15,9 @@ export class ResponseError extends Error {
1615
* @return {object} The parsed JSON from the request
1716
*/
1817
function parseJSON(response) {
18+
if (response.status === 204 || response.status === 205) {
19+
return null;
20+
}
1921
return response.json();
2022
}
2123

@@ -26,12 +28,14 @@ function parseJSON(response) {
2628
*
2729
* @return {object|undefined} Returns either the response, or throws an error
2830
*/
29-
function checkStatus(response): Response {
31+
function checkStatus(response) {
3032
if (response.status >= 200 && response.status < 300) {
3133
return response;
3234
}
3335

34-
throw new ResponseError(response);
36+
const error = new ResponseError(response.statusText);
37+
error.response = response;
38+
throw error;
3539
}
3640

3741
/**
@@ -40,12 +44,10 @@ function checkStatus(response): Response {
4044
* @param {string} url The URL we want to request
4145
* @param {object} [options] The options we want to pass to "fetch"
4246
*
43-
* @return {object} An object containing either "data" or "err"
47+
* @return {object} The response data
4448
*/
45-
export default function request(url: string, options?: RequestInit): Promise<{ } | { err: ResponseError }> {
46-
return fetch(url, options)
47-
.then(checkStatus)
48-
.then(parseJSON)
49-
.then((data) => (data))
50-
.catch((err) => (err));
49+
export default async function request(url: string, options?: RequestInit): Promise<{ } | { err: ResponseError }> {
50+
const fetchResponse = await fetch(url, options);
51+
const response = await checkStatus(fetchResponse);
52+
return parseJSON(response);
5153
}

app/utils/sagaInjectors.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const checkDescriptor = (descriptor: SagaDescriptor) => {
3232
);
3333
};
3434

35-
export function injectSagaFactory(store: LifeStore, isValid: boolean) {
35+
export function injectSagaFactory(store: LifeStore, isValid: boolean = false) {
3636
return function injectSaga(
3737
key: string,
3838
descriptor: SagaDescriptor = {},
@@ -76,7 +76,7 @@ export function injectSagaFactory(store: LifeStore, isValid: boolean) {
7676
};
7777
}
7878

79-
export function ejectSagaFactory(store: LifeStore, isValid: boolean) {
79+
export function ejectSagaFactory(store: LifeStore, isValid: boolean = false) {
8080
return function ejectSaga(key: string) {
8181
if (!isValid) {
8282
checkStore(store);
@@ -98,7 +98,7 @@ export function ejectSagaFactory(store: LifeStore, isValid: boolean) {
9898
};
9999
}
100100

101-
export default function getInjectors(store: LifeStore) {
101+
export function getInjectors(store: LifeStore) {
102102
checkStore(store);
103103

104104
return {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`loadable should render LazyComponent after waiting for it to load 1`] = `
4+
<div>
5+
My lazy-loaded component
6+
</div>
7+
`;
8+
9+
exports[`loadable should render fallback if given one 1`] = `
10+
<div>
11+
Loading
12+
</div>
13+
`;
14+
15+
exports[`loadable should render null by default 1`] = `null`;

app/utils/tests/injectReducer.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
* Test injectors
33
*/
44

5-
import * as React from 'react';
5+
import React from 'react';
66
import { Provider } from 'react-redux';
77
import renderer from 'react-test-renderer';
88
import { render } from '@testing-library/react';
99

1010
import configureStore from '../../configureStore';
1111
import { getInjectors } from '../reducerInjectors';
1212

13+
import { createMemoryHistory } from 'history';
14+
15+
const memoryHistory = createMemoryHistory();
1316
jest.mock('../reducerInjectors');
1417

1518
import { useInjectReducer } from '../injectReducer';
@@ -19,9 +22,6 @@ const Component = () => null;
1922

2023
const reducer = s => s;
2124

22-
import { createMemoryHistory } from 'history';
23-
24-
const memoryHistory = createMemoryHistory();
2525

2626
describe('injectReducer decorator', () => {
2727
let store;

app/utils/tests/injectSaga.test.tsx

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
* Test injectors
33
*/
44

5-
import * as React from 'react';
6-
75
import { put } from 'redux-saga/effects';
8-
import { shallow } from 'enzyme';
9-
6+
import renderer from 'react-test-renderer';
7+
import { render } from '@testing-library/react';
8+
import React from 'react';
9+
import { Provider } from 'react-redux';
1010

1111
import configureStore from '../../configureStore';
12+
import injectSaga, { useInjectSaga } from '../injectSaga';
13+
import { getInjectors } from '../sagaInjectors';
14+
15+
1216
import { createMemoryHistory } from 'history';
13-
import { DAEMON } from '../constants';
1417

1518
const memoryHistory = createMemoryHistory();
1619

@@ -21,19 +24,17 @@ function* testSaga() {
2124
yield put({ type: 'TEST', payload: 'yup' });
2225
}
2326

27+
jest.mock('../sagaInjectors');
2428
describe('injectSaga decorator', () => {
2529
let store;
2630
let injectors;
2731
let ComponentWithSaga;
28-
let injectSaga;
2932

3033
beforeAll(() => {
31-
jest.mock('../sagaInjectors', () => ({
32-
__esModule: true,
33-
default: jest.fn().mockImplementation(() => injectors),
34-
}));
35-
36-
injectSaga = require('../injectSaga').default;
34+
const mockedGetInjectors = (getInjectors as unknown) as jest.Mock<
35+
typeof getInjectors
36+
>; // compiler doesn't know that it's mocked. So manually cast it.
37+
mockedGetInjectors.mockImplementation(() => injectors);
3738
});
3839

3940
beforeEach(() => {
@@ -45,28 +46,35 @@ describe('injectSaga decorator', () => {
4546
ComponentWithSaga = injectSaga({
4647
key: 'test',
4748
saga: testSaga,
48-
mode: DAEMON,
49+
mode: 'testMode',
4950
})(Component);
50-
jest.unmock('../sagaInjectors');
5151
});
5252

5353
it('should inject given saga, mode, and props', () => {
5454
const props = { test: 'test' };
55-
shallow(<ComponentWithSaga {...props} />, { context: { store: store } });
55+
renderer.create(
56+
// tslint:disable-next-line: jsx-wrap-multiline
57+
<Provider store={store}>
58+
<ComponentWithSaga {...props} />
59+
</Provider>,
60+
);
5661

5762
expect(injectors.injectSaga).toHaveBeenCalledTimes(1);
5863
expect(injectors.injectSaga).toHaveBeenCalledWith(
5964
'test',
60-
{ saga: testSaga, mode: DAEMON },
65+
{ saga: testSaga, mode: 'testMode' },
6166
props,
6267
);
6368
});
6469

6570
it('should eject on unmount with a correct saga key', () => {
6671
const props = { test: 'test' };
67-
const renderedComponent = shallow(<ComponentWithSaga {...props} />, {
68-
context: { store: store },
69-
});
72+
const renderedComponent = renderer.create(
73+
// tslint:disable-next-line: jsx-wrap-multiline
74+
<Provider store={store}>
75+
<ComponentWithSaga {...props} />
76+
</Provider>,
77+
);
7078
renderedComponent.unmount();
7179

7280
expect(injectors.ejectSaga).toHaveBeenCalledTimes(1);
@@ -82,10 +90,73 @@ describe('injectSaga decorator', () => {
8290

8391
it('should propagate props', () => {
8492
const props = { testProp: 'test' };
85-
const renderedComponent = shallow(<ComponentWithSaga {...props} />, {
86-
context: { store: store },
93+
const renderedComponent = renderer.create(
94+
// tslint:disable-next-line: jsx-wrap-multiline
95+
<Provider store={store}>
96+
<ComponentWithSaga {...props} />
97+
</Provider>,
98+
);
99+
const {
100+
props: { children },
101+
} = renderedComponent.getInstance();
102+
expect(children.props).toEqual(props);
103+
});
104+
});
105+
106+
describe('useInjectSaga hook', () => {
107+
let store;
108+
let injectors;
109+
let ComponentWithSaga;
110+
111+
beforeAll(() => {
112+
const mockedGetInjectors = (getInjectors as unknown) as jest.Mock<
113+
typeof getInjectors
114+
>; // compiler doesn't know that it's mocked. So manually cast it.
115+
mockedGetInjectors.mockImplementation(() => injectors); });
116+
117+
beforeEach(() => {
118+
store = configureStore({}, memoryHistory);
119+
injectors = {
120+
injectSaga: jest.fn(),
121+
ejectSaga: jest.fn(),
122+
};
123+
ComponentWithSaga = () => {
124+
useInjectSaga({
125+
key: 'test',
126+
saga: testSaga,
127+
mode: 'testMode',
128+
});
129+
return null;
130+
};
131+
});
132+
133+
it('should inject given saga and mode', () => {
134+
const props = { test: 'test' };
135+
render(
136+
// tslint:disable-next-line: jsx-wrap-multiline
137+
<Provider store={store}>
138+
<ComponentWithSaga {...props} />
139+
</Provider>,
140+
);
141+
142+
expect(injectors.injectSaga).toHaveBeenCalledTimes(1);
143+
expect(injectors.injectSaga).toHaveBeenCalledWith('test', {
144+
saga: testSaga,
145+
mode: 'testMode',
87146
});
147+
});
88148

89-
expect(renderedComponent.prop('testProp')).toBe('test');
149+
it('should eject on unmount with a correct saga key', () => {
150+
const props = { test: 'test' };
151+
const { unmount } = render(
152+
// tslint:disable-next-line: jsx-wrap-multiline
153+
<Provider store={store}>
154+
<ComponentWithSaga {...props} />
155+
</Provider>,
156+
);
157+
unmount();
158+
159+
expect(injectors.ejectSaga).toHaveBeenCalledTimes(1);
160+
expect(injectors.ejectSaga).toHaveBeenCalledWith('test');
90161
});
91162
});

0 commit comments

Comments
 (0)