- Migrates the `courseDetails` part from the Redux Store to React Query. - Creates a new `CourseAuthoringContext` - Update the pages in `<CourseAuthoringRoutes>` to use the newly created context. - Migrates some files to Typescript - Migrates some tests to use `src/testUtils.tsx`
159 lines
5.2 KiB
JavaScript
159 lines
5.2 KiB
JavaScript
import {
|
|
render,
|
|
act,
|
|
fireEvent,
|
|
waitFor,
|
|
queryByRole,
|
|
queryByTestId,
|
|
queryByText,
|
|
getByRole,
|
|
waitForElementToBeRemoved,
|
|
initializeMocks,
|
|
} from 'CourseAuthoring/testUtils';
|
|
|
|
import ReactDOM from 'react-dom';
|
|
import { executeThunk } from 'CourseAuthoring/utils';
|
|
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
|
|
|
|
import { CourseAuthoringProvider } from 'CourseAuthoring/CourseAuthoringContext';
|
|
import LiveSettings from './Settings';
|
|
import {
|
|
generateLiveConfigurationApiResponse,
|
|
courseId,
|
|
initialState,
|
|
configurationProviders,
|
|
} from './factories/mockApiResponses';
|
|
|
|
import { fetchLiveConfiguration, fetchLiveProviders } from './data/thunks';
|
|
import { providerConfigurationApiUrl, providersApiUrl } from './data/api';
|
|
import messages from './messages';
|
|
|
|
let axiosMock;
|
|
let container;
|
|
let store;
|
|
const liveSettingsUrl = `/course/${courseId}/pages-and-resources/live/settings`;
|
|
|
|
// Modal creates a portal. Overriding ReactDOM.createPortal allows portals to be tested in jest.
|
|
ReactDOM.createPortal = jest.fn(node => node);
|
|
|
|
const renderComponent = () => {
|
|
const wrapper = render(
|
|
<PagesAndResourcesProvider courseId={courseId}>
|
|
<CourseAuthoringProvider>
|
|
<LiveSettings onClose={() => {}} />
|
|
</CourseAuthoringProvider>
|
|
</PagesAndResourcesProvider>,
|
|
{
|
|
path: liveSettingsUrl,
|
|
routerProps: {
|
|
initialEntries: [liveSettingsUrl],
|
|
},
|
|
params: {
|
|
courseId,
|
|
},
|
|
},
|
|
);
|
|
container = wrapper.container;
|
|
};
|
|
|
|
const mockStore = async ({
|
|
usernameSharing = false,
|
|
emailSharing = false,
|
|
enabled = true,
|
|
piiSharingAllowed = true,
|
|
}) => {
|
|
const fetchProviderConfigUrl = `${providersApiUrl}/${courseId}/`;
|
|
const fetchLiveConfigUrl = `${providerConfigurationApiUrl}/${courseId}/`;
|
|
|
|
axiosMock.onGet(fetchProviderConfigUrl).reply(200, configurationProviders(emailSharing, usernameSharing));
|
|
axiosMock.onGet(fetchLiveConfigUrl).reply(200, generateLiveConfigurationApiResponse(enabled, piiSharingAllowed));
|
|
|
|
await executeThunk(fetchLiveProviders(courseId), store.dispatch);
|
|
await executeThunk(fetchLiveConfiguration(courseId), store.dispatch);
|
|
};
|
|
|
|
describe('LiveSettings', () => {
|
|
beforeEach(async () => {
|
|
const mocks = initializeMocks({
|
|
initialState,
|
|
});
|
|
store = mocks.reduxStore;
|
|
axiosMock = mocks.axiosMock;
|
|
});
|
|
|
|
test('Live Configuration modal is visible', async () => {
|
|
renderComponent();
|
|
expect(queryByRole(container, 'dialog')).toBeVisible();
|
|
});
|
|
|
|
test('Displays "Configure Live" heading', async () => {
|
|
renderComponent();
|
|
const headingElement = queryByTestId(container, 'modal-title');
|
|
expect(headingElement).toHaveTextContent(messages.heading.defaultMessage);
|
|
});
|
|
|
|
test('Displays title, helper text and badge when live configuration button is enabled', async () => {
|
|
await mockStore({ enabled: true });
|
|
renderComponent();
|
|
|
|
const label = container.querySelector('label[for="enable-live-toggle"]');
|
|
const helperText = container.querySelector('#enable-live-toggleHelpText');
|
|
const enableBadge = queryByTestId(container, 'enable-badge');
|
|
|
|
expect(label).toHaveTextContent(messages.enableLiveLabel.defaultMessage);
|
|
expect(enableBadge).toHaveTextContent('Enabled');
|
|
expect(helperText).toHaveTextContent(messages.enableLiveHelp.defaultMessage);
|
|
});
|
|
|
|
test('Displays title, helper text and hides badge when live configuration button is disabled', async () => {
|
|
await mockStore({ enabled: false, piiSharingAllowed: false });
|
|
renderComponent();
|
|
|
|
const label = container.querySelector('label[for="enable-live-toggle"]');
|
|
const helperText = container.querySelector('#enable-live-toggleHelpText');
|
|
|
|
expect(label).toHaveTextContent('Live');
|
|
expect(label.firstChild).not.toHaveTextContent('Enabled');
|
|
expect(helperText).toHaveTextContent(messages.enableLiveHelp.defaultMessage);
|
|
});
|
|
|
|
test('Displays provider heading, helper text and all providers', async () => {
|
|
await mockStore({
|
|
enabled: true,
|
|
piiSharingAllowed: true,
|
|
usernameSharing: false,
|
|
emailSharing: true,
|
|
});
|
|
renderComponent();
|
|
|
|
const spinner = getByRole(container, 'status');
|
|
await waitForElementToBeRemoved(spinner);
|
|
const providers = queryByRole(container, 'group');
|
|
const helperText = queryByTestId(container, 'helper-text');
|
|
|
|
expect(providers.childElementCount).toBe(2);
|
|
expect(providers).toHaveTextContent('Zoom');
|
|
expect(providers).toHaveTextContent('BigBlueButton');
|
|
expect(helperText).toHaveTextContent(
|
|
messages.providerHelperText.defaultMessage.replace('{providerName}', 'Zoom'),
|
|
);
|
|
});
|
|
|
|
test('Unable to save error should be shown on submission if a field is empty', async () => {
|
|
const apiDefaultResponse = generateLiveConfigurationApiResponse(true, true);
|
|
apiDefaultResponse.lti_configuration.lti_1p1_client_key = '';
|
|
await mockStore({ emailSharing: false, piiSharingAllowed: false });
|
|
renderComponent();
|
|
|
|
const spinner = getByRole(container, 'status');
|
|
await waitForElementToBeRemoved(spinner);
|
|
|
|
const saveButton = queryByText(container, 'Save');
|
|
|
|
await waitFor(async () => {
|
|
await act(async () => fireEvent.click(saveButton));
|
|
expect(queryByRole(container, 'alert')).toBeVisible();
|
|
});
|
|
});
|
|
});
|