From 6600936eb8d2d4516fce37f9a8f00f2a89bfd8a3 Mon Sep 17 00:00:00 2001 From: Gildas Garcia <1122076+djhi@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:21:21 +0100 Subject: [PATCH] Ensure queue operations cleanup after themselves --- .../features/queue-table-operations.spec.ts | 159 ++++++++++-------- 1 file changed, 87 insertions(+), 72 deletions(-) diff --git a/e2e/studio/features/queue-table-operations.spec.ts b/e2e/studio/features/queue-table-operations.spec.ts index c3eacb6ba71..99946c6f0b8 100644 --- a/e2e/studio/features/queue-table-operations.spec.ts +++ b/e2e/studio/features/queue-table-operations.spec.ts @@ -1,8 +1,9 @@ import { expect, Page } from '@playwright/test' + import { createTable, dropTable } from '../utils/db/index.js' import { releaseFileOnceCleanup, withFileOnceSetup } from '../utils/once-per-file.js' import { deleteTable } from '../utils/table-helpers.js' -import { test } from '../utils/test.js' +import { test, withSetupCleanup } from '../utils/test.js' import { toUrl } from '../utils/to-url.js' import { waitForTableToLoad } from '../utils/wait-for-response.js' @@ -16,38 +17,6 @@ const enableQueueOperations = async (page: Page) => { } test.describe('Queue Table Operations', () => { - test.beforeAll(async ({ browser, ref }) => { - await withFileOnceSetup(import.meta.url, async () => { - const ctx = await browser.newContext() - const page = await ctx.newPage() - - const loadPromise = waitForTableToLoad(page, ref) - await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) - await loadPromise - - const viewButtons = page.getByRole('button', { name: /^View / }) - const names = await Promise.all( - (await viewButtons.all()).map(async (btn) => { - const ariaLabel = await btn.getAttribute('aria-label') - const name = ariaLabel ? ariaLabel.replace(/^View\s+/, '').trim() : '' - return name - }) - ) - const tablesToDelete = names.filter((tableName) => tableName.startsWith(tableNamePrefix)) - - for (const tableName of tablesToDelete) { - await deleteTable(page, ref, tableName) - await expect - .poll(async () => { - return await page.getByLabel(`View ${tableName}`, { exact: true }).count() - }) - .toBe(0) - } - - await ctx.close() - }) - }) - test.beforeEach(async ({ page, ref }) => { const loadPromise = waitForTableToLoad(page, ref) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) @@ -64,7 +33,14 @@ test.describe('Queue Table Operations', () => { const tableName = `${tableNamePrefix}_cell_edit` const columnName = 'name' - await createTable(tableName, columnName, [{ name: 'original value' }]) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName, [{ name: 'original value' }]) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -99,15 +75,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'edited value' })).toBeVisible() await expect(page.getByRole('gridcell', { name: 'original value' })).not.toBeVisible() - - await dropTable(tableName) }) test('cell edits can be cancelled', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_cell_cancel` const columnName = 'name' - await createTable(tableName, columnName, [{ name: 'keep this value' }]) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName, [{ name: 'keep this value' }]) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -134,15 +115,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'should be cancelled' })).not.toBeVisible() await expect(page.getByText('pending change')).not.toBeVisible() - - await dropTable(tableName) }) test('row inserts are queued and can be saved', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_row_insert` const columnName = 'name' - await createTable(tableName, columnName) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -172,16 +158,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByText('Changes saved successfully')).toBeVisible() await expect(page.getByRole('gridcell', { name: 'new row value' })).toBeVisible() - - await dropTable(tableName) }) test('multiple operations can be batched and saved together', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_batch_ops` const columnName = 'name' - await createTable(tableName, columnName) - + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) await page.reload() @@ -213,16 +203,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'row one' })).toBeVisible() await expect(page.getByRole('gridcell', { name: 'row two' })).toBeVisible() - - await dropTable(tableName) }) test('individual operations can be removed from the queue', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_remove_op` const columnName = 'name' - await createTable(tableName, columnName) - + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) await page.reload() @@ -256,16 +250,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'keep this row' })).toBeVisible() await expect(page.getByRole('gridcell', { name: 'remove this row' })).not.toBeVisible() - - await dropTable(tableName) }) test('keyboard shortcuts work for queue operations', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_shortcuts` const columnName = 'name' - await createTable(tableName, columnName) - + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) await page.reload() @@ -291,15 +289,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByText('Changes saved successfully')).toBeVisible() await expect(page.getByRole('gridcell', { name: 'shortcut test' })).toBeVisible() - - await dropTable(tableName) }) test('row deletes via context menu are queued', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_row_delete` const columnName = 'name' - await createTable(tableName, columnName, [{ name: 'row to delete' }]) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName, [{ name: 'row to delete' }]) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -330,15 +333,20 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'row to delete' })).not.toBeVisible() await expect(page.getByText('0 records')).toBeVisible() - - await deleteTable(page, ref, tableName) }) test('row deletes can be cancelled', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_delete_cancel` const columnName = 'name' - await createTable(tableName, columnName, [{ name: 'should not be deleted' }]) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName, [{ name: 'should not be deleted' }]) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -359,18 +367,22 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'should not be deleted' })).toBeVisible() await expect(page.getByText('pending change')).not.toBeVisible() - - await dropTable(tableName) }) test('mixed operations (add, edit, delete) can be batched', async ({ page, ref }) => { const tableName = `${tableNamePrefix}_mixed_ops` const columnName = 'name' - - await createTable(tableName, columnName, [ - { name: 'row to edit' }, - { name: 'row to delete' }, - ]) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName, columnName, [ + { name: 'row to edit' }, + { name: 'row to delete' }, + ]) + }, + async () => { + await dropTable(tableName) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -411,8 +423,6 @@ test.describe('Queue Table Operations', () => { await expect(page.getByRole('gridcell', { name: 'new row' })).toBeVisible() await expect(page.getByRole('gridcell', { name: 'row to delete' })).not.toBeVisible() await expect(page.getByRole('gridcell', { name: 'row to edit' })).not.toBeVisible() - - await dropTable(tableName) }) test('pending changes persist when switching between tables', async ({ page, ref }) => { @@ -420,8 +430,16 @@ test.describe('Queue Table Operations', () => { const tableName2 = `${tableNamePrefix}_persist2` const columnName = 'name' - await createTable(tableName1, columnName) - await createTable(tableName2, columnName) + await using _ = await withSetupCleanup( + async () => { + await createTable(tableName1, columnName) + await createTable(tableName2, columnName) + }, + async () => { + await dropTable(tableName1) + await dropTable(tableName2) + } + ) await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) await enableQueueOperations(page) @@ -459,8 +477,5 @@ test.describe('Queue Table Operations', () => { await page.getByRole('button', { name: `View ${tableName2}`, exact: true }).click() await expect(page.getByRole('gridcell', { name: 'pending in table 2' })).toBeVisible() - - await dropTable(tableName1) - await dropTable(tableName2) }) })