Skip to content

Commit 4156bc7

Browse files
chore: tests for ts api hooks
1 parent 61d70a1 commit 4156bc7

File tree

7 files changed

+357
-1636
lines changed

7 files changed

+357
-1636
lines changed

jest.config.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { createConfig } = require('@edx/frontend-build');
22

3-
module.exports = createConfig('jest', {
3+
const config = createConfig('jest', {
44
// setupFilesAfterEnv is used after the jest environment has been loaded. In general this is what you want.
55
// If you want to add config BEFORE jest loads, use setupFiles instead.
66
setupFilesAfterEnv: [
@@ -11,3 +11,8 @@ module.exports = createConfig('jest', {
1111
'src/i18n',
1212
],
1313
});
14+
15+
config.moduleDirectories = ['node_modules', 'src'];
16+
// config.moduleNameMapper['@/(.*)'] = '<rootDir>/src/$1';
17+
18+
module.exports = config;

package-lock.json

Lines changed: 221 additions & 1633 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"classnames": "^2.3.2",
5252
"core-js": "3.31.1",
5353
"filesize": "^8.0.6",
54+
"jest-when": "^3.6.0",
5455
"prop-types": "15.8.1",
5556
"query-string": "^8.1.0",
5657
"react": "16.14.0",

src/data/services/lms/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const feedbackRequirement = StrictDict({
88

99
export const queryKeys = StrictDict({
1010
oraConfig: 'oraConfig',
11-
submissionData: 'submissionData',
11+
pageData: 'pageData',
1212
});
1313

1414
export default { feedbackRequirement, queryKeys };
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { useQuery } from '@tanstack/react-query';
2+
import { useRouteMatch } from 'react-router-dom';
3+
import { snakeCaseObject, camelCaseObject } from '@edx/frontend-platform';
4+
import { when } from 'jest-when';
5+
6+
import routes from 'routes';
7+
import * as types from '../types';
8+
import { queryKeys } from '../constants';
9+
import fakeData from '../fakeData';
10+
11+
import { useORAConfig, usePageData } from './api';
12+
13+
jest.mock('@tanstack/react-query', () => ({ useQuery: jest.fn() }));
14+
15+
jest.mock('react-router-dom', () => ({ useRouteMatch: jest.fn() }));
16+
17+
interface QueryFn { (): string }
18+
interface QueryArgs { queryKey: string, queryFn: QueryFn }
19+
20+
interface MockORAQuery extends QueryArgs { data: types.ORAConfig }
21+
interface MockUseORAQuery { (QueryArgs): MockORAQuery }
22+
interface MockORAUseConfigHook { (): MockORAQuery }
23+
24+
interface MockPageDataQuery extends QueryArgs { data: types.PageData }
25+
interface MockUsePageDataQuery { (QueryArgs): MockPageDataQuery }
26+
interface MockPageDataUseConfigHook { (): MockPageDataQuery }
27+
28+
let out;
29+
describe('lms api hooks', () => {
30+
describe('useORAConfig', () => {
31+
const mockUseQuery = (hasData: boolean): MockUseORAQuery => ({ queryKey, queryFn }) => ({
32+
data: hasData ? camelCaseObject(fakeData.oraConfig.assessmentText) : undefined,
33+
queryKey,
34+
queryFn,
35+
});
36+
37+
const mockUseQueryForORA = (hasData) => {
38+
when(useQuery)
39+
.calledWith(expect.objectContaining({ queryKey: [queryKeys.oraConfig] }))
40+
.mockImplementationOnce(mockUseQuery(hasData));
41+
};
42+
43+
const testUseORAConfig = useORAConfig as unknown as MockORAUseConfigHook;
44+
45+
beforeEach(() => {
46+
mockUseQueryForORA(true);
47+
out = testUseORAConfig();
48+
});
49+
it('initializes query with oraConfig queryKey', () => {
50+
expect(out.queryKey).toEqual([queryKeys.oraConfig]);
51+
});
52+
it('initializes query with promise pointing to assessment text', async () => {
53+
const response = await out.queryFn();
54+
expect(response).toEqual(fakeData.oraConfig.assessmentText);
55+
});
56+
it('returns camelCase object from data if data has been returned', () => {
57+
expect(out.data).toEqual(camelCaseObject(fakeData.oraConfig.assessmentText));
58+
});
59+
it('returns empty object from data if data has not been returned', () => {
60+
mockUseQueryForORA(false);
61+
out = testUseORAConfig();
62+
expect(out.data).toEqual({});
63+
});
64+
});
65+
describe('usePageData', () => {
66+
const mockUseQuery = (data?: types.PageData): MockUsePageDataQuery => ({ queryKey, queryFn }) => ({
67+
data: data ? camelCaseObject(data) : undefined,
68+
queryKey,
69+
queryFn,
70+
});
71+
72+
const mockUseQueryForPageData = (data, isAssessment) => {
73+
when(useQuery)
74+
.calledWith(expect.objectContaining({ queryKey: [queryKeys.pageData, isAssessment] }))
75+
.mockImplementationOnce(mockUseQuery(data));
76+
};
77+
78+
const mockUseRouteMatch = (path) => {
79+
when(useRouteMatch)
80+
.calledWith()
81+
.mockReturnValueOnce({ path });
82+
};
83+
84+
const testUsePageData = usePageData as unknown as MockPageDataUseConfigHook;
85+
describe('submission', () => {
86+
beforeEach(() => {
87+
mockUseRouteMatch(routes.submission);
88+
mockUseQueryForPageData(fakeData.pageData.shapes.emptySubmission, false);
89+
out = testUsePageData();
90+
});
91+
it('initializes query with pageData queryKey and isAssessment: false', () => {
92+
expect(out.queryKey).toEqual([queryKeys.pageData, false]);
93+
});
94+
it('initializes query with promise pointing to empty submission page data', async () => {
95+
const response = await out.queryFn();
96+
expect(response).toEqual(fakeData.pageData.shapes.emptySubmission);
97+
});
98+
it('returns camelCase object from data if data has been returned', () => {
99+
expect(out.data).toEqual(camelCaseObject(fakeData.pageData.shapes.emptySubmission));
100+
});
101+
});
102+
describe('assessment', () => {
103+
beforeEach(() => {
104+
mockUseRouteMatch(routes.assessment);
105+
mockUseQueryForPageData(fakeData.pageData.shapes.peerAssessment, true);
106+
out = testUsePageData();
107+
});
108+
it('initializes query with pageData queryKey and isAssessment: true', () => {
109+
expect(out.queryKey).toEqual([queryKeys.pageData, true]);
110+
});
111+
it('initializes query with promise pointing to peer assessment page data', async () => {
112+
const response = await out.queryFn();
113+
expect(response).toEqual(fakeData.pageData.shapes.peerAssessment);
114+
});
115+
it('returns camelCase object from data if data has been returned', () => {
116+
expect(out.data).toEqual(camelCaseObject(fakeData.pageData.shapes.peerAssessment));
117+
});
118+
});
119+
it('returns empty object from data if data has not been returned', () => {
120+
mockUseRouteMatch(routes.submission);
121+
mockUseQueryForPageData(undefined, false);
122+
out = testUsePageData();
123+
expect(out.data).toEqual({});
124+
});
125+
});
126+
});

src/data/services/lms/hooks/api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ export const usePageData = (): types.QueryData<types.PageData> => {
2626
const returnData = isAssessment
2727
? fakeData.pageData.shapes.peerAssessment
2828
: fakeData.pageData.shapes.emptySubmission;
29+
2930
const { data, ...status } = useQuery({
30-
queryKey: [queryKeys.submissionData, isAssessment],
31+
queryKey: [queryKeys.pageData, isAssessment],
3132
// queryFn: () => getAuthenticatedClient().get(...),
3233
queryFn: () => Promise.resolve(returnData),
3334
});
File renamed without changes.

0 commit comments

Comments
 (0)