diff --git a/e2e/helpers.ts b/e2e/helpers.ts index cd514d6e..29b3690e 100644 --- a/e2e/helpers.ts +++ b/e2e/helpers.ts @@ -1,4 +1,4 @@ -import { expect, type Page, test } from '@playwright/test' +import { expect, type Page } from '@playwright/test' /** Register a fresh user and land on /files. */ export async function signUpAndGoToFiles(page: Page) { @@ -15,9 +15,8 @@ export async function signUpAndGoToFiles(page: Page) { } /** - * Create a folder via the UI. Returns true if successful, false if the - * server rejected it (e.g. no storage configured in CI). - * Skips the calling test when creation fails. + * Create a folder via the UI. Waits for the API response to confirm success. + * If the API returns an error the test fails with a descriptive message. */ export async function createFolder(page: Page, name: string): Promise { await page.getByRole('button', { name: /new folder|folder/i }).click() @@ -29,14 +28,29 @@ export async function createFolder(page: Page, name: string): Promise { dialog.getByRole('button', { name: /create/i }).click(), ]) - if (!apiResp.ok()) { - // Close the dialog if it's still open (server error shown as toast) - await dialog - .getByRole('button', { name: /cancel/i }) - .click() - .catch(() => {}) - test.skip(true, `folder creation failed (${apiResp.status()}) — likely no storage in CI`) - } - + expect(apiResp.ok(), `folder creation failed (${apiResp.status()}) — ensure storage is configured`).toBe(true) await expect(dialog).not.toBeVisible({ timeout: 10000 }) } + +/** + * Seed a dummy storage backend via the admin API. + * The first registered user is admin, so this must be called + * after the first signUp in the test suite. The storage doesn't + * need real S3 credentials — folder creation only needs a DB record. + */ +export async function seedStorage(page: Page): Promise { + const resp = await page.request.post('/api/admin/storages', { + data: { + title: 'E2E Test Storage', + mode: 'private', + bucket: 'e2e-test', + endpoint: 'https://localhost', + region: 'auto', + accessKey: 'fake-key', + secretKey: 'fake-secret', + }, + }) + // Ignore 401/403 (non-admin user) — storage may already exist from a prior test + if (resp.status() === 401 || resp.status() === 403) return + expect(resp.ok(), `seed storage failed (${resp.status()})`).toBe(true) +} diff --git a/e2e/responsive-dialogs.spec.ts b/e2e/responsive-dialogs.spec.ts index a5cede42..2ceb8d64 100644 --- a/e2e/responsive-dialogs.spec.ts +++ b/e2e/responsive-dialogs.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test' -import { createFolder, signUpAndGoToFiles } from './helpers' +import { createFolder, seedStorage, signUpAndGoToFiles } from './helpers' // --------------------------------------------------------------------------- // Dialogs responsive behavior @@ -46,6 +46,7 @@ test.describe('File dialogs responsive', () => { test('mobile: rename dialog is usable', async ({ page }, testInfo) => { test.skip(testInfo.project.name !== 'mobile', 'mobile only') await signUpAndGoToFiles(page) + await seedStorage(page) await createFolder(page, 'rename-me') // Open row actions dropdown via the last button in the row @@ -72,6 +73,7 @@ test.describe('File dialogs responsive', () => { test('mobile: move dialog is usable', async ({ page }, testInfo) => { test.skip(testInfo.project.name !== 'mobile', 'mobile only') await signUpAndGoToFiles(page) + await seedStorage(page) await createFolder(page, 'move-me') // Open row actions dropdown via the last button in the row diff --git a/e2e/responsive-preview.spec.ts b/e2e/responsive-preview.spec.ts index 25c6715a..dbf608d9 100644 --- a/e2e/responsive-preview.spec.ts +++ b/e2e/responsive-preview.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test' -import { createFolder, signUpAndGoToFiles } from './helpers' +import { createFolder, seedStorage, signUpAndGoToFiles } from './helpers' // --------------------------------------------------------------------------- // Preview dialog: mobile uses full-screen drawer, desktop uses centered dialog @@ -8,6 +8,7 @@ test.describe('Preview responsive layout', () => { test('mobile: preview opens as full-screen drawer (not centered dialog)', async ({ page }, testInfo) => { test.skip(testInfo.project.name !== 'mobile', 'mobile only') await signUpAndGoToFiles(page) + await seedStorage(page) await createFolder(page, 'test-preview') // We need a file to trigger preview — check if any files exist diff --git a/e2e/responsive.spec.ts b/e2e/responsive.spec.ts index 97c03585..f8825326 100644 --- a/e2e/responsive.spec.ts +++ b/e2e/responsive.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test' -import { createFolder, signUpAndGoToFiles } from './helpers' +import { createFolder, seedStorage, signUpAndGoToFiles } from './helpers' // --------------------------------------------------------------------------- // Sidebar behavior per device @@ -95,6 +95,7 @@ test.describe('File table responsive columns', () => { test('desktop: all columns visible (name, size, modified, actions)', async ({ page }, testInfo) => { test.skip(testInfo.project.name !== 'desktop', 'desktop only') await signUpAndGoToFiles(page) + await seedStorage(page) await createFolder(page, 'test-folder') await expect(page.getByRole('columnheader', { name: /size/i })).toBeVisible() @@ -104,6 +105,7 @@ test.describe('File table responsive columns', () => { test('mobile: size and modified columns are hidden', async ({ page }, testInfo) => { test.skip(testInfo.project.name !== 'mobile', 'mobile only') await signUpAndGoToFiles(page) + await seedStorage(page) await createFolder(page, 'test-folder') await expect(page.getByRole('columnheader', { name: /size/i })).not.toBeVisible()