test: add mutex to clipboard copy & paste operation to reduce flaky (#11884)

This commit is contained in:
Brooooooklyn
2025-04-22 11:02:29 +00:00
parent 4fd468c46f
commit bfd3c64615
10 changed files with 32 additions and 28 deletions
@@ -7,7 +7,6 @@ import {
} from '@affine-test/kit/utils/editor';
import { importImage } from '@affine-test/kit/utils/image';
import {
pasteByKeyboard,
selectAllByKeyboard,
writeTextToClipboard,
} from '@affine-test/kit/utils/keyboard';
@@ -253,7 +252,6 @@ test('should show toolbar when inline link is preceded by image or surface-ref',
const url = new URL(page.url());
await writeTextToClipboard(page, url.toString());
await pasteByKeyboard(page);
const toolbar = locateToolbar(page);
+2 -8
View File
@@ -64,7 +64,6 @@ test('not allowed to switch to embed view when linking to the same document', as
const url0 = new URL(page.url());
await writeTextToClipboard(page, url0.toString());
await pasteByKeyboard(page);
const { toolbar, switchViewBtn, inlineViewBtn, cardViewBtn, embedViewBtn } =
toolbarButtons(page);
@@ -296,7 +295,6 @@ test('allow switching to embed view when linking to the other document with mode
await page.keyboard.press('Enter');
await writeTextToClipboard(page, url.toString());
await pasteByKeyboard(page);
// Inline
await inlineLink.hover();
@@ -516,9 +514,8 @@ test('the viewport should be fit when the linked document is with edgeless mode'
// move viewport
const { x, y } = noteBoundingBox;
await page.mouse.click(x - 10, y - 10);
await page.mouse.click(x - 10, y + 100);
await page.keyboard.down('Space');
await page.waitForTimeout(50);
await page.mouse.down();
await page.mouse.move(x + 1000, y);
await page.mouse.up();
@@ -538,7 +535,6 @@ test('the viewport should be fit when the linked document is with edgeless mode'
await page.keyboard.press('Enter');
await writeTextToClipboard(page, url.toString());
await pasteByKeyboard(page);
// Inline
await page.locator('affine-reference').hover();
@@ -608,7 +604,7 @@ test('should show edgeless content when switching card view of linked mode doc i
await clickEdgelessModeButton(page);
await page.mouse.move(x, y);
await writeTextToClipboard(page, url.toString());
await writeTextToClipboard(page, url.toString(), false);
// Inline
const embed = page.locator('affine-embed-edgeless-linked-doc-block');
@@ -1116,7 +1112,6 @@ test('should show full email address', async ({ page }) => {
await page.keyboard.press('Enter');
await writeTextToClipboard(page, 'dev@affine.pro');
await pasteByKeyboard(page);
const inlineLink = page.locator('affine-link');
@@ -1140,7 +1135,6 @@ test('should not show view toggle button when protocol of link is not http(s)',
await page.keyboard.press('Enter');
await writeTextToClipboard(page, 'ftp://affine.pro/blocksuite.pdf');
await pasteByKeyboard(page);
const inlineLink = page.locator('affine-link');
@@ -515,8 +515,6 @@ test('can paste a doc link to create link reference', async ({ page }) => {
// paste the url
await writeTextToClipboard(page, url);
// check the link reference
await page.waitForTimeout(500);
await expect(
page.locator('affine-reference:has-text("Getting Started")')
).toBeVisible();
@@ -524,8 +522,6 @@ test('can paste a doc link to create link reference', async ({ page }) => {
// can ctrl-z to revert to normal link
await page.keyboard.press('ControlOrMeta+z');
// check the normal link
await page.waitForTimeout(500);
await expect(page.locator(`affine-link:has-text("${url}")`)).toBeVisible();
});
+1
View File
@@ -15,6 +15,7 @@
"@blocksuite/affine": "workspace:*",
"@node-rs/argon2": "^2.0.2",
"@playwright/test": "=1.51.1",
"@toeverything/infra": "workspace:*",
"express": "^5.0.0",
"http-proxy-middleware": "^3.0.3"
},
+17 -8
View File
@@ -1,4 +1,5 @@
import type { Page } from '@playwright/test';
import { type Page } from '@playwright/test';
import { AsyncLock } from '@toeverything/infra/utils';
const IS_MAC = process.platform === 'darwin';
@@ -102,13 +103,18 @@ export async function undoByKeyboard(page: Page) {
await keyUpCtrlOrMeta(page);
}
export async function writeTextToClipboard(page: Page, text: string) {
const clipboardMutex = new AsyncLock();
export async function writeTextToClipboard(
page: Page,
text: string,
paste = true
) {
using _release = await clipboardMutex.acquire();
// paste the url
await page.evaluate(
async ([text]) => {
const clipData = {
'text/plain': text,
};
navigator.clipboard.writeText('');
const e = new ClipboardEvent('paste', {
clipboardData: new DataTransfer(),
});
@@ -116,11 +122,14 @@ export async function writeTextToClipboard(page: Page, text: string) {
writable: false,
value: document,
});
Object.entries(clipData).forEach(([key, value]) => {
e.clipboardData?.setData(key, value);
});
e.clipboardData!.setData('text/plain', text);
document.dispatchEvent(e);
},
[text]
);
if (paste) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('v', { delay: 50 });
await keyUpCtrlOrMeta(page);
}
}
+1 -2
View File
@@ -60,8 +60,7 @@ export async function type(page: Page, content: string, delay = 50) {
}
export const createLinkedPage = async (page: Page, pageName?: string) => {
// fixme: workaround for @ popover not showing up when editor is not ready
await page.waitForTimeout(500);
await waitForEditorLoad(page);
await page.keyboard.type('@', { delay: 50 });
const linkedPagePopover = page.locator('.linked-doc-popover');
await expect(linkedPagePopover).toBeVisible();
+2 -1
View File
@@ -8,6 +8,7 @@
"include": ["./src"],
"references": [
{ "path": "../../tools/utils" },
{ "path": "../../blocksuite/affine/all" }
{ "path": "../../blocksuite/affine/all" },
{ "path": "../../packages/common/infra" }
]
}
+3 -2
View File
@@ -85,11 +85,12 @@ function getBundleConfigs(pkg: Package) {
const IN_CI = !!process.env.CI;
const httpProxyMiddlewareLogLevel = IN_CI ? 'silent' : 'error';
const defaultDevServerConfig = {
const defaultDevServerConfig: DevServerConfiguration = {
host: '0.0.0.0',
allowedHosts: 'all',
hot: false,
liveReload: true,
compress: !process.env.CI,
client: {
overlay: process.env.DISABLE_DEV_OVERLAY === 'true' ? false : undefined,
logging: process.env.CI ? 'none' : 'error',
@@ -124,7 +125,7 @@ const defaultDevServerConfig = {
logLevel: httpProxyMiddlewareLogLevel,
},
],
} as DevServerConfiguration;
};
export class BundleCommand extends PackageCommand {
static override paths = [['bundle'], ['webpack'], ['pack'], ['bun']];
+5 -1
View File
@@ -1209,7 +1209,11 @@ export const PackageList = [
{
location: 'tests/kit',
name: '@affine-test/kit',
workspaceDependencies: ['tools/utils', 'blocksuite/affine/all'],
workspaceDependencies: [
'tools/utils',
'blocksuite/affine/all',
'packages/common/infra',
],
},
{
location: 'tools/@types/build-config',
+1
View File
@@ -101,6 +101,7 @@ __metadata:
"@blocksuite/affine": "workspace:*"
"@node-rs/argon2": "npm:^2.0.2"
"@playwright/test": "npm:=1.51.1"
"@toeverything/infra": "workspace:*"
express: "npm:^5.0.0"
http-proxy-middleware: "npm:^3.0.3"
peerDependencies: