dx: fix flaky test
Massimo Melina committed
Feb 26, 2026 at 23:44 UTC
c4ee25ea119568716a3f13a63f73f94b602031f1
2 files changed
+19
-15
e2e/frontend.spec.ts
+8
-8
@@ -245,7 +245,7 @@ test('admin1', async ({ page }) => {
245
await page.getByRole('tab').nth(4).click()
246
await page.getByRole('button', { name: '(Options)' }).click()
247
await page.locator('div').filter({ hasText: 'ServedRequests are logged here. Empty to disable it.Not servedWrite errors in a different file. Empty to use same file.' }).nth(3).click()
248
- await page.getByRole('button', { name: '(Close)' }).click()
248
+ await page.getByRole('button', { name: 'Close' }).click()
249
await expect(page.getByText('LogsServedNot')).toBeVisible()
250
await clickAdminMenu(page, 'Language')
251
await dataTableLoading()
@@ -341,7 +341,7 @@ test('admin2', async ({ page }) => {
341
await logApisToggle.click()
342
await expect(logApisToggle).toBeChecked()
343
}
344
- await page.getByRole('button', { name: '(Close)' }).click()
344
+ await page.getByRole('button', { name: 'Close' }).click()
345
346
await clickAdminMenu(page, 'Plugins')
347
await expect(page.getByText('antibrute')).toBeVisible()
@@ -363,7 +363,7 @@ test('admin2', async ({ page }) => {
363
// Same reason as log options: accessible name may include shortcut hints.
364
const pluginSaveBtn = pluginOptionsDialog.locator('button:has-text("Save")').first()
365
await expect(pluginSaveBtn).toBeEnabled()
366
- await page.getByRole('button', { name: '(Close)' }).click()
366
+ await page.getByRole('button', { name: 'Close' }).click()
367
}
368
}
369
@@ -419,10 +419,10 @@ test('anew', async ({ page, browserName }) => {
419
if (page.viewportSize()?.width! < 1000 || browserName !== 'chromium') return // test only for desktop chromium
420
// reset config so each run starts from the same default workspace state
421
const port = 8082
422
- while (await page.goto(`http://localhost:${port}/`).then(() => 0, () => 1)) {
422
+ do {
423
fs.writeFileSync('tests/work2/config.yaml', `port: ${port}\nopen_browser_at_start: false\n`)
424
- await wait(100)
425
- }
424
+ await wait(500)
425
+ } while (await page.goto(`http://localhost:${port}/`).then(() => 0, () => 1))
426
await expect(page.getByText('Nothing here')).toBeVisible()
427
await page.getByRole('button', { name: 'Options' }).click()
428
const page1Promise = page.waitForEvent('popup')
@@ -452,12 +452,12 @@ test('anew', async ({ page, browserName }) => {
452
await adminPage.getByText('folder1', { exact: true }).click()
453
await adminPage.getByRole('button', { name: 'Cut' }).click()
454
await adminPage.locator('div').filter({ hasText: 'InfoNow that this is marked' }).nth(1).click()
455
- await adminPage.getByRole('button', { name: '(Close)' }).click()
455
+ await adminPage.getByRole('button', { name: 'Close' }).click()
456
await adminPage.getByText('Home folder').click()
457
await adminPage.getByRole('button', { name: '(/work2/folder1/)' }).click() // paste button
458
await adminPage.getByText('data.kv').click()
459
await adminPage.getByRole('button', { name: 'Cut' }).click()
460
- await adminPage.getByRole('button', { name: '(Close)' }).click()
460
+ await adminPage.getByRole('button', { name: 'Close' }).click()
461
await adminPage.getByText('folder1').click()
462
await adminPage.getByRole('button', { name: '(/data.kv)' }).click() // paste
463
await page.getByRole('button', { name: 'Close' }).click()
e2e/serial.spec.ts
+11
-7
@@ -1,5 +1,4 @@
1
import { expect, test } from '@playwright/test'
2
-import { wait } from '../src/cross'
2
import { clearUploads, password, uploadName, URL, username } from './common'
3
4
// this test is separated to run serially, as it will modify folder timestamp for a few seconds, during which other tests may fail
@@ -39,14 +38,19 @@ test('upload1', async ({ page, context, browserName }) => {
38
const cdpSession = await context.newCDPSession(page)
39
await cdpSession.send('Network.emulateNetworkConditions', NETWORK_PRESETS.Regular2G)
40
await page.getByRole('button', { name: 'Edit' }).click();
42
- await page.getByRole('textbox').fill(uploadName);
43
- await page.getByRole('button', { name: 'Continue' }).click();
41
+ const renameDialog = page.locator('.dialog-prompt')
42
+ const renameInput = renameDialog.getByRole('textbox')
43
+ await expect(renameInput).toHaveValue(fileToUpload.name) // promptDialog initializes the field value in useEffect, so we wait for that init to avoid our fill being overwritten
44
+ await renameInput.fill(uploadName);
45
+ await renameDialog.getByRole('button', { name: 'Continue' }).click();
46
await expect(page.getByText(uploadName)).toBeVisible() // rename was effective
47
await page.getByRole('button', { name: 'Send 1 file' }).click();
46
- await wait(1500)
47
- await pageAdmin.getByRole('cell', { name: uploadName }).click();
48
- await pageAdmin.getByRole('button', { name: '(Disconnect)' }).click();
49
- await pageAdmin.getByRole('button', { name: '(Close)' }).click();
48
+ const uploadCells = pageAdmin.getByRole('cell', { name: `${uploadName} /for-admins/upload` })
49
+ await expect(uploadCells.first()).toBeVisible()
50
+ // during upload resume, monitoring can briefly show two rows for the same path
51
+ await uploadCells.last().click()
52
+ await pageAdmin.getByRole('button', { name: 'Disconnect' }).click();
53
+ await pageAdmin.getByRole('button', { name: 'Close' }).click();
54
await pageAdmin.close()
55
await page.getByText('Copy links').click();
56
await page.getByText('Operation successful').click();