@samitouri / QOSami-HFS / commits / c4ee25ea

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();