[TNL-7268] refactor tests to use factories

This commit is contained in:
Agrendalath
2020-07-23 16:41:39 +02:00
committed by David Joy
parent 7c046870e3
commit 8d7fbb5bd8
16 changed files with 573 additions and 378 deletions

View File

@@ -1,22 +1,28 @@
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import '@testing-library/jest-dom';
import './courseware/data/__factories__';
import './course-home/data/__factories__';
import { getConfig, mergeConfig } from '@edx/frontend-platform';
import { configure as configureI18n } from '@edx/frontend-platform/i18n';
import { configure as configureLogging } from '@edx/frontend-platform/logging';
import { configure as configureAuth, MockAuthService } from '@edx/frontend-platform/auth';
import { configure as configureAuth, getAuthenticatedHttpClient, MockAuthService } from '@edx/frontend-platform/auth';
import React from 'react';
import PropTypes from 'prop-types';
import { render as rtlRender } from '@testing-library/react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import { IntlProvider } from 'react-intl';
import MockAdapter from 'axios-mock-adapter';
import AppProvider from '@edx/frontend-platform/react/AppProvider';
import { reducer as courseHomeReducer } from './course-home/data';
import { reducer as coursewareReducer } from './courseware/data/slice';
import { reducer as modelsReducer } from './generic/model-store';
import { UserMessagesProvider } from './generic/user-messages';
import appMessages from './i18n';
import { fetchCourse, fetchSequence } from './courseware/data';
import executeThunk from './utils';
import buildSimpleCourseAndSequenceMetadata from './courseware/data/__factories__/sequenceMetadata.factory';
class MockLoggingService {
logInfo = jest.fn();
@@ -56,71 +62,8 @@ export default function initializeMockApp() {
window.scrollTo = jest.fn();
// Generated units for convenience.
const testUnits = [...Array(10).keys()].map(i => String(i + 1));
// Base state containing various use-cases.
const baseInitialState = {
courseware: {
sequenceStatus: 'loaded',
courseStatus: 'loaded',
courseId: '1',
},
models: {
courses: {
1: {
sectionIds: ['1'],
contentTypeGatingEnabled: true,
},
},
sections: {
1: {
sequenceIds: ['1', '2'],
},
},
sequences: {
1: {
unitIds: testUnits,
showCompletion: true,
title: 'test-sequence',
gatedContent: {
gated: false,
prereqId: '1',
gatedSectionName: 'test-gated-section',
},
},
2: {
unitIds: testUnits,
showCompletion: true,
title: 'test-sequence-2',
},
3: {
unitIds: testUnits,
showCompletion: true,
title: 'test-sequence-3',
bannerText: 'test-banner-3',
gatedContent: {
gated: true,
prereqId: '1',
gatedSectionName: 'test-gated-section',
},
},
},
units: testUnits.reduce(
(acc, unitId) => Object.assign(acc, {
[unitId]: {
id: unitId,
contentType: 'other',
title: unitId,
},
}),
{},
),
},
};
// MessageEvent used for indicating that a unit has been loaded.
const messageEvent = {
export const messageEvent = {
type: 'plugin.resize',
payload: {
height: 300,
@@ -128,22 +71,62 @@ const messageEvent = {
};
// Send MessageEvent indicating that a unit has been loaded.
function loadUnit(message = messageEvent) {
export function loadUnit(message = messageEvent) {
window.postMessage(message, '*');
}
let globalStore;
export async function initializeTestStore(options = {}, overrideStore = true) {
const store = configureStore({
reducer: {
models: modelsReducer,
courseware: coursewareReducer,
courseHome: courseHomeReducer,
},
});
if (overrideStore) {
globalStore = store;
}
initializeMockApp();
const axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock.reset();
const {
courseBlocks, sequenceBlock, courseMetadata, sequenceMetadata,
} = buildSimpleCourseAndSequenceMetadata(options);
const forbiddenCourseUrl = `${getConfig().LMS_BASE_URL}/api/courseware/course/${courseMetadata.id}`;
const courseBlocksUrlRegExp = new RegExp(`${getConfig().LMS_BASE_URL}/api/courses/v2/blocks/*`);
axiosMock.onGet(forbiddenCourseUrl).reply(200, courseMetadata);
axiosMock.onGet(courseBlocksUrlRegExp).reply(200, courseBlocks);
sequenceMetadata.forEach(metadata => {
const sequenceMetadataUrl = `${getConfig().LMS_BASE_URL}/api/courseware/sequence/${metadata.item_id}`;
axiosMock.onGet(sequenceMetadataUrl).reply(200, metadata);
});
axiosMock.onAny().reply((config) => {
// eslint-disable-next-line no-console
console.log(config.url);
return [200, {}];
});
// eslint-disable-next-line no-unused-expressions
!options.excludeFetchCourse && await executeThunk(fetchCourse(courseMetadata.id), store.dispatch);
if (!options.excludeFetchSequence) {
await Promise.all(sequenceBlock
.map(block => executeThunk(fetchSequence(block.id), store.dispatch)));
}
return store;
}
function render(
ui,
{
initialState = baseInitialState,
store = configureStore({
reducer: {
models: modelsReducer,
courseware: coursewareReducer,
courseHome: courseHomeReducer,
},
preloadedState: initialState,
}),
store = null,
...renderOptions
} = {},
) {
@@ -151,11 +134,11 @@ function render(
return (
// eslint-disable-next-line react/jsx-filename-extension
<IntlProvider locale="en">
<Provider store={store}>
<AppProvider store={store || globalStore}>
<UserMessagesProvider>
{children}
</UserMessagesProvider>
</Provider>
</AppProvider>
</IntlProvider>
);
}
@@ -170,7 +153,7 @@ function render(
// Re-export everything.
export * from '@testing-library/react';
// Override `render` method; export `screen` too to suppress errors.
// Override `render` method.
export {
render, testUnits, baseInitialState as initialState, messageEvent, loadUnit,
render,
};