Skip to content

Commit

Permalink
refactor: tests refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Mar 13, 2024
1 parent c50915e commit c7d6a1e
Show file tree
Hide file tree
Showing 31 changed files with 243 additions and 270 deletions.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions src/__mocks__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as clipboardUnit } from './clipboardUnit';
export { default as clipboardXBlock } from './clipboardXBlock';
11 changes: 11 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,14 @@ export const COURSE_BLOCK_NAMES = /** @type {const} */ ({
});

export const UPLOAD_FILE_MAX_SIZE = 20 * 1000 * 1000; // 20mb

export const STUDIO_CLIPBOARD_CHANNEL = 'studio_clipboard_channel';

export const CLIPBOARD_STATUS = {
loading: 'loading',
ready: 'ready',
expired: 'expired',
error: 'error',
};

export const NOT_XBLOCK_TYPES = ['vertical', 'sequential', 'chapter', 'course'];
45 changes: 19 additions & 26 deletions src/course-outline/CourseOutline.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeMockApp } from '@edx/frontend-platform';
import { getConfig, initializeMockApp } from '@edx/frontend-platform';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { cloneDeep } from 'lodash';
Expand Down Expand Up @@ -35,6 +35,7 @@ import {
courseSectionMock,
courseSubsectionMock,
} from './__mocks__';
import { clipboardUnit } from '../__mocks__';
import { executeThunk } from '../utils';
import { COURSE_BLOCK_NAMES, VIDEO_SHARING_OPTIONS } from './constants';
import CourseOutline from './CourseOutline';
Expand All @@ -44,7 +45,7 @@ import headerMessages from './header-navigations/messages';
import cardHeaderMessages from './card-header/messages';
import enableHighlightsModalMessages from './enable-highlights-modal/messages';
import statusBarMessages from './status-bar/messages';
import pasteButtonMessages from './paste-button/messages';
import pasteButtonMessages from '../generic/clipboard/paste-button/messages';
import subsectionMessages from './subsection-card/messages';
import pageAlertMessages from './page-alerts/messages';
import messages from './messages';
Expand All @@ -56,6 +57,13 @@ const courseId = '123';

window.HTMLElement.prototype.scrollIntoView = jest.fn();

const clipboardBroadcastChannelMock = {
postMessage: jest.fn(),
close: jest.fn(),
};

global.BroadcastChannel = jest.fn(() => clipboardBroadcastChannelMock);

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
Expand Down Expand Up @@ -1803,7 +1811,7 @@ describe('<CourseOutline />', () => {
});

it('check whether unit copy & paste option works correctly', async () => {
const { findAllByTestId } = render(<RootWrapper />);
const { findAllByTestId, queryByTestId } = render(<RootWrapper />);
// get first section -> first subsection -> first unit element
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
const [sectionElement] = await findAllByTestId('section-card');
Expand All @@ -1814,27 +1822,11 @@ describe('<CourseOutline />', () => {
const [unit] = subsection.childInfo.children;
const [unitElement] = await within(subsectionElement).findAllByTestId('unit-card');

const expectedClipboardContent = {
content: {
blockType: 'vertical',
blockTypeDisplay: 'Unit',
created: '2024-01-29T07:58:36.844249Z',
displayName: unit.displayName,
id: 15,
olxUrl: 'http://localhost:18010/api/content-staging/v1/staged-content/15/olx',
purpose: 'clipboard',
status: 'ready',
userId: 3,
},
sourceUsageKey: unit.id,
sourceContexttitle: courseOutlineIndexMock.courseStructure.displayName,
sourceEditUrl: unit.studioUrl,
};
// mock api call
axiosMock
.onPost(getClipboardUrl(), {
usage_key: unit.id,
}).reply(200, expectedClipboardContent);
}).reply(200, clipboardUnit);
// check that initialUserClipboard state is empty
const { initialUserClipboard } = store.getState().courseOutline;
expect(initialUserClipboard).toBeUndefined();
Expand All @@ -1848,19 +1840,20 @@ describe('<CourseOutline />', () => {
await act(async () => fireEvent.click(copyButton));

// check that initialUserClipboard state is updated
expect(store.getState().courseOutline.initialUserClipboard).toEqual(expectedClipboardContent);
expect(store.getState().courseOutline.initialUserClipboard).toEqual(clipboardUnit);

[subsectionElement] = await within(sectionElement).findAllByTestId('subsection-card');
// find clipboard content label
const clipboardLabel = await within(subsectionElement).findByText(
pasteButtonMessages.clipboardContentLabel.defaultMessage,
pasteButtonMessages.pasteButtonWhatsInClipboardText.defaultMessage,
);
await act(async () => fireEvent.mouseOver(clipboardLabel));

// find clipboard content popup link
expect(
subsectionElement.querySelector('#vertical-paste-button-overlay'),
).toHaveAttribute('href', unit.studioUrl);
// find clipboard content popover link
const popoverContent = queryByTestId('popover-content');
const apiBaseUrl = getConfig().STUDIO_BASE_URL;
expect(popoverContent.tagName).toBe('A');
expect(popoverContent).toHaveAttribute('href', apiBaseUrl + unit.studioUrl);

// check paste button functionality
// mock api call
Expand Down
7 changes: 3 additions & 4 deletions src/course-outline/data/thunk.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RequestStatus } from '../../data/constants';
import { NOTIFICATION_MESSAGES } from '../../constants';
import { CLIPBOARD_STATUS, NOTIFICATION_MESSAGES } from '../../constants';
import { COURSE_BLOCK_NAMES } from '../constants';
import {
hideProcessingNotification,
Expand Down Expand Up @@ -581,17 +581,16 @@ export function setUnitOrderListQuery(sectionId, subsectionId, unitListIds, rest
};
}

export function setClipboardContent(usageKey, broadcastClipboard) {
export function setClipboardContent(usageKey) {
return async (dispatch) => {
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.copying));

try {
await copyBlockToClipboard(usageKey).then(async (result) => {
const status = result?.content?.status;
if (status === 'ready') {
if (status === CLIPBOARD_STATUS.ready) {
dispatch(updateClipboardContent(result));
broadcastClipboard(result);
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
dispatch(hideProcessingNotification());
} else {
Expand Down
7 changes: 1 addition & 6 deletions src/course-outline/hooks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import { getConfig } from '@edx/frontend-platform';

import { RequestStatus } from '../data/constants';
import { COURSE_BLOCK_NAMES } from './constants';
import { useBroadcastChannel } from '../generic/broadcast-channel/hooks';
import {
setCurrentItem,
setCurrentSection,
updateSavingStatus,
updateClipboardContent,
} from './data/slice';
import {
getLoadingStatus,
Expand Down Expand Up @@ -91,12 +89,9 @@ const useCourseOutline = ({ courseId }) => {
const [isPublishModalOpen, openPublishModal, closePublishModal] = useToggle(false);
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
const clipboardBroadcastChannel = useBroadcastChannel('studio_clipboard_channel', (message) => {
dispatch(updateClipboardContent(message));
});

const handleCopyToClipboardClick = (usageKey) => {
dispatch(setClipboardContent(usageKey, clipboardBroadcastChannel.postMessage));
dispatch(setClipboardContent(usageKey));
};

const handlePasteClipboardClick = (parentLocator, sectionId) => {
Expand Down
15 changes: 7 additions & 8 deletions src/course-outline/subsection-card/SubsectionCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ import { Button, useToggle } from '@openedx/paragon';
import { Add as IconAdd } from '@openedx/paragon/icons';
import classNames from 'classnames';

import { getInitialUserClipboard } from 'CourseAuthoring/course-outline/data/selectors';
import { getInitialUserClipboard } from '../data/selectors';
import { setCurrentItem, setCurrentSection, setCurrentSubsection } from '../data/slice';
import { RequestStatus } from '../../data/constants';
import { COURSE_BLOCK_NAMES } from '../constants';
import CardHeader from '../card-header/CardHeader';
import ConditionalSortableElement from '../../generic/drag-helper/ConditionalSortableElement';
import { useCopyToClipboard, PasteButton } from '../../generic/clipboard';
import TitleButton from '../card-header/TitleButton';
import XBlockStatus from '../xblock-status/XBlockStatus';
// import PasteButton from '../paste-button/PasteButton';
import { getItemStatus, getItemStatusBorder, scrollToElement } from '../utils';
import messages from './messages';
import PasteButton from '../../generic/paste-button';

const SubsectionCard = ({
section,
Expand Down Expand Up @@ -47,6 +45,7 @@ const SubsectionCard = ({
const [isFormOpen, openForm, closeForm] = useToggle(false);
const namePrefix = 'subsection';
const initialUserClipboard = useSelector(getInitialUserClipboard);
const { sharedClipboardData, showPasteUnit } = useCopyToClipboard(initialUserClipboard);

const {
id,
Expand All @@ -62,7 +61,7 @@ const SubsectionCard = ({

// re-create actions object for customizations
const actions = { ...subsectionActions };
// add actions to control display of move up & down menu buton.
// add actions to control display of move up & down menu button.
actions.allowMoveUp = canMoveItem(index, -1);
actions.allowMoveDown = canMoveItem(index, 1);

Expand Down Expand Up @@ -196,11 +195,11 @@ const SubsectionCard = ({
>
{intl.formatMessage(messages.newUnitButton)}
</Button>
{enableCopyPasteUnits && (
{enableCopyPasteUnits && showPasteUnit && (
<PasteButton
className="mt-4"
text={intl.formatMessage(messages.pasteButton)}
clipboardData={initialUserClipboard}
blockType={COURSE_BLOCK_NAMES.vertical.id}
clipboardData={sharedClipboardData}
onClick={handlePasteButtonClick}
/>
)}
Expand Down
8 changes: 7 additions & 1 deletion src/course-outline/subsection-card/SubsectionCard.test.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import {
act, render, fireEvent, within,
Expand All @@ -25,6 +24,13 @@ jest.mock('react-router-dom', () => ({
}),
}));

const clipboardBroadcastChannelMock = {
postMessage: jest.fn(),
close: jest.fn(),
};

global.BroadcastChannel = jest.fn(() => clipboardBroadcastChannelMock);

const section = {
id: '123',
displayName: 'Section Name',
Expand Down
2 changes: 1 addition & 1 deletion src/course-unit/CourseUnit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import SubHeader from '../generic/sub-header/SubHeader';
import { RequestStatus } from '../data/constants';
import getPageHeadTitle from '../generic/utils';
import AlertMessage from '../generic/alert-message';
import PasteButton from '../generic/paste-button';
import { PasteButton } from '../generic/clipboard';
import ProcessingNotification from '../generic/processing-notification';
import { SavingErrorAlert } from '../generic/saving-error-alert';
import ConnectionErrorAlert from '../generic/ConnectionErrorAlert';
Expand Down
22 changes: 12 additions & 10 deletions src/course-unit/CourseUnit.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,20 @@ import {
} from './data/thunk';
import initializeStore from '../store';
import {
clipboardUnit,
clipboardXBlock,
courseCreateXblockMock,
courseSectionVerticalMock,
courseUnitIndexMock,
courseUnitMock,
courseVerticalChildrenMock,
clipboardMockResponse,
} from './__mocks__';
import {
clipboardUnit,
clipboardXBlock,
} from '../__mocks__';
import { executeThunk } from '../utils';
import deleteModalMessages from '../generic/delete-modal/messages';
import pasteComponentMessages from './clipboard/paste-component/messages';
import pasteButtonMessages from '../generic/clipboard/paste-button/messages';
import pasteNotificationsMessages from './clipboard/paste-notification/messages';
import headerNavigationsMessages from './header-navigations/messages';
import headerTitleMessages from './header-title/messages';
Expand Down Expand Up @@ -928,7 +930,7 @@ describe('<CourseUnit />', () => {

await waitFor(() => {
expect(queryByText(sidebarMessages.actionButtonCopyUnitTitle.defaultMessage)).toBeNull();
expect(queryByRole('button', { name: pasteComponentMessages.pasteComponentButtonText.defaultMessage })).toBeNull();
expect(queryByRole('button', { name: messages.pasteComponentButtonText.defaultMessage })).toBeNull();
});

axiosMock
Expand Down Expand Up @@ -961,10 +963,10 @@ describe('<CourseUnit />', () => {
});

await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
expect(getByRole('button', { name: pasteComponentMessages.pasteComponentButtonText.defaultMessage })).toBeInTheDocument();
expect(getByRole('button', { name: messages.pasteComponentButtonText.defaultMessage })).toBeInTheDocument();

const whatsInClipboardText = getByText(
pasteComponentMessages.pasteComponentWhatsInClipboardText.defaultMessage,
pasteButtonMessages.pasteButtonWhatsInClipboardText.defaultMessage,
);

userEvent.hover(whatsInClipboardText);
Expand Down Expand Up @@ -1010,7 +1012,7 @@ describe('<CourseUnit />', () => {
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
await executeThunk(copyToClipboard(blockId), store.dispatch);

userEvent.click(getByRole('button', { name: pasteComponentMessages.pasteComponentButtonText.defaultMessage }));
userEvent.click(getByRole('button', { name: messages.pasteComponentButtonText.defaultMessage }));

await waitFor(() => {
expect(getAllByTestId('course-xblock')).toHaveLength(2);
Expand Down Expand Up @@ -1053,7 +1055,7 @@ describe('<CourseUnit />', () => {

await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
await executeThunk(copyToClipboard(blockId), store.dispatch);
expect(getByRole('button', { name: pasteComponentMessages.pasteComponentButtonText.defaultMessage })).toBeInTheDocument();
expect(getByRole('button', { name: messages.pasteComponentButtonText.defaultMessage })).toBeInTheDocument();
});

it('should copy a unit, paste it as a new unit, and update the course section vertical data', async () => {
Expand Down Expand Up @@ -1319,10 +1321,10 @@ describe('<CourseUnit />', () => {
await executeThunk(fetchCourseVerticalChildrenData(blockId), store.dispatch);

expect(queryByRole('button', {
name: pasteComponentMessages.pasteComponentButtonText.defaultMessage,
name: messages.pasteComponentButtonText.defaultMessage,
})).not.toBeInTheDocument();
expect(queryByText(
pasteComponentMessages.pasteComponentWhatsInClipboardText.defaultMessage,
pasteButtonMessages.pasteButtonWhatsInClipboardText.defaultMessage,
)).not.toBeInTheDocument();
});
});
Expand Down
2 changes: 0 additions & 2 deletions src/course-unit/__mocks__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ export { default as courseSectionVerticalMock } from './courseSectionVertical';
export { default as courseUnitMock } from './courseUnit';
export { default as courseCreateXblockMock } from './courseCreateXblock';
export { default as courseVerticalChildrenMock } from './courseVerticalChildren';
export { default as clipboardUnit } from './clipboardUnit';
export { default as clipboardXBlock } from './clipboardXBlock';
export { default as clipboardMockResponse } from './clipboardResponse';
Loading

0 comments on commit c7d6a1e

Please sign in to comment.