Skip to content

Commit

Permalink
Add e2e tests for export modal
Browse files Browse the repository at this point in the history
  • Loading branch information
12joan committed Nov 11, 2023
1 parent 2afb764 commit 9d2038f
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 17 deletions.
6 changes: 3 additions & 3 deletions client/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
useSaveSelection,
} from '~/lib/editor/restoreSelection';
import { SelectionToolbar } from '~/lib/editor/SelectionToolbar';
import { useSlatePlaywrightUtils } from '~/lib/editor/slate-playwright';
import { SlatePlaywrightEffects } from '~/lib/editor/slate-playwright';
import { useInitialValue } from '~/lib/editor/useInitialValue';
import { useNavigateAwayOnDelete } from '~/lib/editor/useNavigateAwayOnDelete';
import { useSyncDocument } from '~/lib/editor/useSyncDocument';
Expand Down Expand Up @@ -208,6 +208,8 @@ export const Editor = ({ clientId, initialDocument }: EditorProps) => {
debouncedUpdateBody={debouncedUpdateBody}
/>

<SlatePlaywrightEffects />

{!isReadOnly && <SelectionToolbar />}
</Plate>
),
Expand Down Expand Up @@ -354,8 +356,6 @@ const WithEditorState = ({

useSaveSelection(initialDocument.id, editor);

useSlatePlaywrightUtils();

const [forceUpdateBodyKey, forceUpdateBody] = useReducer((x) => x + 1, 0);

useGlobalEvent('s3File:uploadComplete', () => forceUpdateBody());
Expand Down
2 changes: 2 additions & 0 deletions client/components/exportModalSections/ExportHTMLSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { setLocalStorage, useLocalStorage } from '~/lib/browserStorage';
import { copyText } from '~/lib/copyText';
import { getHtmlForExport } from '~/lib/editor/getHtmlForExport';
import { SlatePlaywrightEffects } from '~/lib/editor/slate-playwright';
import { useEffectAfterFirst } from '~/lib/useEffectAfterFirst';
import CopyIcon from '~/components/icons/CopyIcon';
import DownloadIcon from '~/components/icons/DownloadIcon';
Expand Down Expand Up @@ -87,6 +88,7 @@ export const ExportHTMLSection = ({
initialValue={initialValue}
setIsModified={setIsModified}
/>
<SlatePlaywrightEffects />
</Plate>
</pre>

Expand Down
4 changes: 2 additions & 2 deletions client/e2e/basic-editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.describe('Basic editor', () => {
});

test('save document to server and reload', async ({ page }) => {
const editable = await getEditable(page);
const editable = getEditable(page);
const editorHandle = await getEditorHandle(page, editable);

await clickAtPath(page, editorHandle, [0]);
Expand All @@ -33,7 +33,7 @@ test.describe('Basic editor', () => {
await expectUpToDate(page);

await page.reload();
await expect(await getEditable(page)).toContainText('Hello World!');
await expect(getEditable(page)).toContainText('Hello World!');
});

test('create blocks with markdown and remove with backspace', async ({
Expand Down
75 changes: 75 additions & 0 deletions client/e2e/export-html.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { expect, Page, test } from '@playwright/test';
import { clickAtPath, getEditable, getEditorHandle } from './slate';
import {
createDocument,
createProject,
logIn,
openExportHTMLSection,
} from './utils';

const getDocumentTitleCheckbox = (page: Page) =>
page.getByLabel('Include document title');

const getExportEditable = (page: Page) => getEditable(page.locator('pre'));
// const getExportEditorHandle = (page: Page) => getEditorHandle(page, getExportEditable(page));

const getUndoButton = (page: Page) =>
page.getByRole('button', { name: 'Undo changes' });

test.describe('Export HTML modal', () => {
test.beforeEach(async ({ page }) => {
await logIn(page);
await createProject(page);
await createDocument(page, 'My document');

const editorHandle = await getEditorHandle(page);
await clickAtPath(page, editorHandle, [0]);
await page.keyboard.type('Hello World!');

await openExportHTMLSection(page);
await page.waitForTimeout(200);
});

test('shows the HTML for the document', async ({ page }) => {
const editable = getExportEditable(page);
await expect(editable).toContainText('<p>Hello World!</p>');
});

// Too flaky
// test('undo changes', async ({ page }) => {
// const undoButton = getUndoButton(page);
// await expect(undoButton).not.toBeVisible();

// const editable = getExportEditable(page);
// const editorHandle = await getExportEditorHandle(page);
// await clickAtPath(page, editorHandle, [0]);
// await page.keyboard.type('MODIFIED');
// await expect(editable).toContainText('MODIFIED');
// await expect(undoButton).toBeVisible();

// await undoButton.click();
// await expect(editable).not.toContainText('MODIFIED');
// await expect(undoButton).not.toBeVisible();
// });

test('includes the document title by default', async ({ page }) => {
const checkbox = getDocumentTitleCheckbox(page);
expect(await checkbox.isChecked()).toBe(true);

const editable = getExportEditable(page);
await expect(editable).toContainText('<h1>My document</h1>');
});

test('unticking the checkbox removes the document title', async ({
page,
}) => {
const checkbox = getDocumentTitleCheckbox(page);
await checkbox.uncheck();

const editable = getExportEditable(page);
await expect(editable).not.toContainText('<h1>My document</h1>');

const undoButton = getUndoButton(page);
await expect(undoButton).not.toBeVisible();
});
});
8 changes: 3 additions & 5 deletions client/e2e/slate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import { Path, Range } from 'slate';

import '../lib/globals.d';

export const getEditable = async (page: Page) =>
page.locator('[data-slate-editor]');
export const getEditable = (context: Page | Locator) =>
context.locator('[data-slate-editor]');

export const getEditorHandle = async (
page: Page,
editable?: Locator
): Promise<JSHandle<PlateEditor>> => {
const editableHandle = await (
editable || (await getEditable(page))
).elementHandle();
const editableHandle = await (editable || getEditable(page)).elementHandle();

return page.evaluateHandle((editable) => {
const editor = window.playwrightUtils.EDITABLE_TO_EDITOR.get(
Expand Down
26 changes: 20 additions & 6 deletions client/e2e/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,34 @@ export const createDocument = async (page: Page, title?: string) => {
await fillDocumentTitle(page, title);
}

const editable = await getEditable(page);
const editable = getEditable(page);
await expect(editable).toHaveText('Write something...');
};

export const openDocumentMenu = async (page: Page) => {
await page.getByLabel('Document menu').click();
};

export const expectSyncState = async (page: Page, state: string) => {
await page.waitForTimeout(500);
await page.getByLabel('Document menu').click();
await openDocumentMenu(page);
await expect(page.getByText(state)).toBeVisible();
await page.keyboard.press('Escape');
};

export const expectUpToDate = async (page: Page) =>
expectSyncState(page, 'Up to date');

export const openExportModal = async (page: Page) => {
await openDocumentMenu(page);
await page.getByText('Export document').click();
};

export const openExportHTMLSection = async (page: Page) => {
await openExportModal(page);
await page.getByRole('tab', { name: 'Export HTML' }).click();
};

export type CreateDataTransfer = {
filePath: string;
fileName: string;
Expand Down Expand Up @@ -106,6 +120,10 @@ export const dragAndDropFile = async (
await target.dispatchEvent('drop', eventOptions);
};

export const openSearchModal = async (page: Page) => {
await locateSidebar(page).getByText('Search').click();
};

export const openAccountModal = async (page: Page) => {
await page.getByLabel('Account').hover();
await page.getByText('Account info').click();
Expand All @@ -115,7 +133,3 @@ export const openFileStorageSection = async (page: Page) => {
await openAccountModal(page);
await page.getByText('File storage').click();
};

export const openSearchModal = async (page: Page) => {
await locateSidebar(page).getByText('Search').click();
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getNode, PlateEditor, toDOMNode, useEditorRef } from '@udecode/plate';

const EDITABLE_TO_EDITOR = new WeakMap<HTMLElement, PlateEditor>();

export const useSlatePlaywrightUtils = () => {
export const SlatePlaywrightEffects = () => {
const editor = useEditorRef();

useEffect(() => {
Expand All @@ -14,6 +14,8 @@ export const useSlatePlaywrightUtils = () => {
EDITABLE_TO_EDITOR.delete(editable);
};
}, [editor]);

return null;
};

window.playwrightUtils = {
Expand Down

0 comments on commit 9d2038f

Please sign in to comment.