Skip to content

Commit 964fa00

Browse files
authored
Merge pull request #1780 from khanniie/develop-sketchlist-tests
Creates Index.integration.test.jsx and Sketchlist.unit.test.jsx
2 parents cd79754 + beebe7e commit 964fa00

14 files changed

+2008
-421
lines changed

Diff for: client/__mocks__/i18n.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { enUS, es, ja, hi } from 'date-fns/locale';
2+
import i18n from '../i18n-test';
3+
4+
export function languageKeyToLabel(lang) {
5+
const languageMap = {
6+
'en-US': 'English',
7+
'es-419': 'Español',
8+
ja: '日本語',
9+
hi: 'हिन्दी'
10+
};
11+
return languageMap[lang];
12+
}
13+
14+
export function languageKeyToDateLocale(lang) {
15+
const languageMap = {
16+
'en-US': enUS,
17+
'es-419': es,
18+
ja,
19+
hi
20+
};
21+
return languageMap[lang];
22+
}
23+
24+
export function currentDateLocale() {
25+
return languageKeyToDateLocale(i18n.language);
26+
}
27+
28+
export default i18n;

Diff for: client/__mocks__/styleMock.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

Diff for: client/components/Nav.unit.test.jsx

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { render } from '@testing-library/react';
33

44
import { NavComponent } from './Nav';
55

6+
jest.mock('../i18n');
7+
68
describe('Nav', () => {
79
const props = {
810
newProject: jest.fn(),

Diff for: client/index.integration.test.jsx

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { setupServer } from 'msw/node';
2+
import { rest } from 'msw';
3+
import React from 'react';
4+
import { Router, browserHistory } from 'react-router';
5+
6+
import {
7+
reduxRender,
8+
act,
9+
waitFor,
10+
fireEvent,
11+
screen,
12+
within
13+
} from './test-utils';
14+
import configureStore from './store';
15+
import routes from './routes';
16+
import * as Actions from './modules/User/actions';
17+
import { userResponse } from './testData/testServerResponses';
18+
19+
// setup for the app
20+
const history = browserHistory;
21+
const initialState = window.__INITIAL_STATE__;
22+
const store = configureStore(initialState);
23+
24+
// need to mock this file or it'll throw ERRCONNECTED
25+
jest.mock('./i18n');
26+
27+
// setup for the msw fake server
28+
const server = setupServer(
29+
rest.get('/session', (req, res, ctx) =>
30+
// console.log("called server get session");
31+
res(ctx.json(userResponse))
32+
)
33+
);
34+
35+
beforeAll(() =>
36+
server.listen({
37+
onUnhandledRequest: 'warn'
38+
})
39+
);
40+
afterEach(() => server.resetHandlers());
41+
afterAll(() => server.close());
42+
43+
// below are fixes for jsdom-specific errors
44+
// https://stackoverflow.com/questions/57311971/error-not-implemented-window-scrollto-how-do-we-remove-this-error-from-jest-t
45+
const noop = () => {};
46+
Object.defineProperty(window, 'focus', { value: noop, writable: true });
47+
48+
// https://github.com/jsdom/jsdom/issues/3002
49+
document.createRange = () => {
50+
const range = new Range();
51+
52+
range.getBoundingClientRect = jest.fn();
53+
54+
range.getClientRects = () => ({
55+
item: () => null,
56+
length: 0,
57+
[Symbol.iterator]: jest.fn()
58+
});
59+
60+
return range;
61+
};
62+
63+
// start testing
64+
describe('index.jsx integration', () => {
65+
// the subject under test
66+
const subject = () =>
67+
reduxRender(<Router history={history} routes={routes(store)} />, { store });
68+
69+
// spy on this function and wait for it to be called before making assertions
70+
const spy = jest.spyOn(Actions, 'getUser');
71+
72+
beforeEach(async () => {
73+
act(() => {
74+
subject();
75+
});
76+
77+
await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
78+
});
79+
80+
afterEach(() => {
81+
spy.mockClear();
82+
});
83+
84+
it('navbar items and the dropdowns in the navbar exist', () => {
85+
const navigation = screen.getByRole('navigation');
86+
expect(navigation).toBeInTheDocument();
87+
88+
const fileButton = within(navigation).getByRole('button', {
89+
name: /^file$/i
90+
});
91+
expect(fileButton).toBeInTheDocument();
92+
93+
const newFileButton = within(navigation).getByRole('button', {
94+
name: /^new$/i
95+
});
96+
expect(newFileButton).toBeInTheDocument();
97+
98+
// save file button not shown?
99+
100+
// const exampleFileButton = within(navigation).getByRole('link', {name: /^examples$/i});
101+
// expect(exampleFileButton).toBeInTheDocument();
102+
103+
const editButton = within(navigation).getByRole('button', {
104+
name: /^edit$/i
105+
});
106+
expect(editButton).toBeInTheDocument();
107+
108+
const sketchButton = within(navigation).getByRole('button', {
109+
name: /^sketch$/i
110+
});
111+
expect(sketchButton).toBeInTheDocument();
112+
113+
const helpButton = within(navigation).getByRole('button', {
114+
name: /^help$/i
115+
});
116+
expect(helpButton).toBeInTheDocument();
117+
});
118+
119+
it('toolbar elements exist', () => {
120+
const playButton = screen.getByRole('button', {
121+
name: /play only visual sketch/i
122+
});
123+
expect(playButton).toBeInTheDocument();
124+
125+
const stopButton = screen.getByRole('button', {
126+
name: /stop sketch/i
127+
});
128+
expect(stopButton).toBeInTheDocument();
129+
130+
const editSketchNameButton = screen.getByRole('button', {
131+
name: /edit sketch name/i
132+
});
133+
expect(editSketchNameButton).toBeInTheDocument();
134+
135+
expect(screen.getByText('Auto-refresh')).toBeInTheDocument();
136+
});
137+
138+
it('preview exists', () => {
139+
expect(
140+
screen.getByRole('heading', { name: /preview/i })
141+
).toBeInTheDocument();
142+
const preview = screen.getByRole('main', { name: /sketch output/i });
143+
expect(preview).toBeInTheDocument();
144+
});
145+
146+
it('code editor exists', () => {
147+
const codeeditor = screen.getByRole('article');
148+
expect(codeeditor).toBeInTheDocument();
149+
});
150+
151+
it('sidebar exists', () => {
152+
expect(screen.getByText('Sketch Files')).toBeInTheDocument();
153+
});
154+
155+
it('clicking on play updates the preview iframe with a srcdoc, stop clears it', () => {
156+
const playButton = screen.getByRole('button', {
157+
name: /play only visual sketch/i
158+
});
159+
const preview = screen.getByRole('main', { name: /sketch output/i });
160+
expect(preview.getAttribute('srcdoc')).toBeFalsy();
161+
act(() => {
162+
fireEvent.click(playButton);
163+
});
164+
165+
expect(preview.getAttribute('srcdoc')).toBeTruthy();
166+
167+
const stopButton = screen.getByRole('button', {
168+
name: /stop sketch/i
169+
});
170+
act(() => {
171+
fireEvent.click(stopButton);
172+
});
173+
expect(preview.getAttribute('srcdoc')).toMatch(/(^|")\s*($|")/);
174+
});
175+
});

Diff for: client/modules/IDE/actions/projects.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function getProjects(username) {
1212
} else {
1313
url = '/projects';
1414
}
15-
apiClient
15+
return apiClient
1616
.get(url)
1717
.then((response) => {
1818
dispatch({

Diff for: client/modules/IDE/actions/projects.unit.test.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import configureStore from 'redux-mock-store';
2+
import thunk from 'redux-thunk';
3+
import { setupServer } from 'msw/node';
4+
import { rest } from 'msw';
5+
6+
import * as ProjectActions from './projects';
7+
import * as ActionTypes from '../../../constants';
8+
import {
9+
initialTestState,
10+
mockProjects
11+
} from '../../../testData/testReduxStore';
12+
13+
const mockStore = configureStore([thunk]);
14+
15+
const server = setupServer(
16+
rest.get(`/${initialTestState.user.username}/projects`, (req, res, ctx) =>
17+
res(ctx.json(mockProjects))
18+
)
19+
);
20+
21+
beforeAll(() => server.listen());
22+
afterEach(() => server.resetHandlers());
23+
afterAll(() => server.close());
24+
25+
describe('projects action creator tests', () => {
26+
let store;
27+
28+
afterEach(() => {
29+
store.clearActions();
30+
});
31+
32+
it('creates GET_PROJECTS after successfuly fetching projects', () => {
33+
store = mockStore(initialTestState);
34+
35+
const expectedActions = [
36+
{ type: ActionTypes.START_LOADING },
37+
{ type: ActionTypes.SET_PROJECTS, projects: mockProjects },
38+
{ type: ActionTypes.STOP_LOADING }
39+
];
40+
41+
return store
42+
.dispatch(ProjectActions.getProjects('happydog'))
43+
.then(() => expect(store.getActions()).toEqual(expectedActions));
44+
});
45+
});

Diff for: client/modules/IDE/components/Editor.unit.test.jsx

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import configureStore from 'redux-mock-store';
3+
import thunk from 'redux-thunk';
4+
import { act } from 'react-dom/test-utils';
5+
import Editor from './Editor';
6+
import { reduxRender } from '../../../test-utils';
7+
import { initialTestState } from '../../../testData/testReduxStore';
8+
9+
jest.mock('../../../i18n');
10+
11+
describe('<Editor />', () => {
12+
const mockStore = configureStore([thunk]);
13+
const store = mockStore(initialTestState);
14+
15+
const subjectProps = { provideController: jest.fn() };
16+
17+
const subject = () => reduxRender(<Editor {...subjectProps} />, { store });
18+
19+
afterEach(() => {
20+
store.clearActions();
21+
});
22+
23+
it('renders successfully', () => {
24+
act(() => {
25+
subject();
26+
});
27+
});
28+
});

0 commit comments

Comments
 (0)