Skip to content

Commit 475f2b5

Browse files
committed
test(playwright): added helper fixtures for tests
1 parent d4447b1 commit 475f2b5

File tree

4 files changed

+155
-1
lines changed

4 files changed

+155
-1
lines changed

tests/playwright/core/editor.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import type {Expect, Page} from '@playwright/test';
2+
3+
import type {DataTransferType, MarkdownEditorMode} from 'src';
4+
5+
class MarkdownEditorLocators {
6+
readonly component;
7+
readonly editor;
8+
9+
readonly settingsButton;
10+
readonly settingsContent;
11+
12+
readonly contenteditable;
13+
14+
constructor(page: Page) {
15+
this.component = page.getByTestId('playground-md-editor');
16+
this.editor = page.getByTestId('g-md-editor-mode');
17+
18+
this.settingsButton = page.getByTestId('g-md-settings-button');
19+
this.settingsContent = page.getByTestId('g-md-settings-content');
20+
21+
this.contenteditable = this.editor.locator('[contenteditable=true]');
22+
}
23+
}
24+
25+
type PasteData = Partial<Record<DataTransferType, string>>;
26+
27+
export class MarkdownEditorPage {
28+
protected readonly page: Page;
29+
protected readonly expect: Expect;
30+
protected readonly locators;
31+
32+
constructor(page: Page, expect: Expect) {
33+
this.page = page;
34+
this.expect = expect;
35+
36+
this.locators = new MarkdownEditorLocators(page);
37+
}
38+
39+
async getMode(): Promise<MarkdownEditorMode> {
40+
const value = await this.locators.editor.getAttribute('data-mode');
41+
const mode = value as MarkdownEditorMode | null;
42+
if (mode === 'wysiwyg' || mode === 'markup') return mode;
43+
throw new Error(`MarkdownEditorPage.getMode(): unknown editor mode "${mode}"`);
44+
}
45+
46+
async openSettingsPopup() {
47+
if (await this.locators.settingsContent.isVisible()) return;
48+
49+
await this.locators.settingsButton.click();
50+
await this.locators.settingsContent.waitFor({state: 'visible'});
51+
}
52+
53+
async switchMode(mode: MarkdownEditorMode) {
54+
if ((await this.getMode()) === mode) return;
55+
56+
await this.openSettingsPopup();
57+
await this.locators.settingsContent.getByTestId(`md-settings-mode-${mode}`).click();
58+
await this.assertMode(mode);
59+
}
60+
61+
async assertMode(mode: MarkdownEditorMode) {
62+
await this.expect.poll(() => this.getMode()).toBe(mode);
63+
}
64+
65+
async blur() {
66+
await this.locators.contenteditable.blur();
67+
}
68+
69+
async press(key: string) {
70+
await this.locators.contenteditable.press(key);
71+
}
72+
73+
async clearContent() {
74+
await this.press('ControlOrMeta+A');
75+
await this.press('Backspace');
76+
}
77+
78+
async paste(value: PasteData | string) {
79+
const data: PasteData = typeof value === 'string' ? {'text/plain': value} : value;
80+
81+
await this.locators.contenteditable.evaluate((element, data) => {
82+
const clipboardData = new DataTransfer();
83+
84+
for (const [key, value] of Object.entries(data)) {
85+
clipboardData.setData(key, value);
86+
}
87+
88+
element.focus();
89+
element.dispatchEvent(new ClipboardEvent('paste', {clipboardData}));
90+
}, data);
91+
}
92+
93+
async fill(text: string) {
94+
this.locators.contenteditable.fill(text);
95+
}
96+
97+
async selectTextIn(selector?: string) {
98+
let loc = this.locators.contenteditable;
99+
if (selector) loc = loc.locator(selector);
100+
101+
loc.selectText();
102+
await this.page.waitForTimeout(100);
103+
}
104+
}

tests/playwright/core/helpers.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type {BrowserContext, Page} from '@playwright/test';
2+
3+
class Keymap {
4+
readonly selectAll = 'ControlOrMeta+A';
5+
readonly copy = 'ControlOrMeta+C';
6+
readonly cut = 'ControlOrMeta+X';
7+
readonly paste = 'ControlOrMeta+V';
8+
}
9+
10+
export class PlaywrightHelpers {
11+
readonly keys = new Keymap();
12+
13+
private readonly page;
14+
private readonly context;
15+
16+
constructor({page, context}: {page: Page; context: BrowserContext}) {
17+
this.page = page;
18+
this.context = context;
19+
}
20+
21+
async getClipboardData() {
22+
await this.context.grantPermissions(['clipboard-read']);
23+
return this.page.evaluate(async () => {
24+
const item = (await navigator.clipboard.read())[0];
25+
const data: Record<string, string> = {};
26+
const types = Array.from(item.types);
27+
for (const type of types) {
28+
data[type] = await (await item.getType(type)).text();
29+
}
30+
return data;
31+
});
32+
}
33+
}

tests/playwright/core/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import {test as base} from '@playwright/experimental-ct-react';
1+
import {test as base, expect} from '@playwright/experimental-ct-react';
22

3+
import {MarkdownEditorPage} from './editor';
34
import {expectScreenshot} from './expectScreenshot';
5+
import {PlaywrightHelpers} from './helpers';
46
import {mount} from './mount';
57
import type {Fixtures} from './types';
68
import {wait} from './wait';
@@ -9,6 +11,15 @@ export const test = base.extend<Fixtures>({
911
mount,
1012
expectScreenshot,
1113
wait,
14+
editor: async ({page}, use) => {
15+
const editor = new MarkdownEditorPage(page, expect);
16+
await use(editor);
17+
},
18+
helpers: async ({page, context}, use) => {
19+
const helpers = new PlaywrightHelpers({page, context});
20+
await use(helpers);
21+
},
22+
platform: [process.platform, {scope: 'test'}],
1223
});
1324

1425
export {expect} from '@playwright/experimental-ct-react';

tests/playwright/core/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import type {
1212
TestFixture,
1313
} from '@playwright/test';
1414

15+
import type {MarkdownEditorPage} from './editor';
16+
import type {PlaywrightHelpers} from './helpers';
17+
1518
interface ComponentFixtures {
1619
mount<HooksConfig>(
1720
component: JSX.Element,
@@ -31,6 +34,9 @@ export type Fixtures = {
3134
mount: MountFixture;
3235
expectScreenshot: ExpectScreenshotFixture;
3336
wait: WaitFixture;
37+
editor: MarkdownEditorPage;
38+
helpers: PlaywrightHelpers;
39+
platform: NodeJS.Platform;
3440
};
3541

3642
export type MountFixture = ComponentFixtures['mount'];

0 commit comments

Comments
 (0)