From 106c2c67fd5d603ee45cd7c25fc2a9dd71a62990 Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Tue, 27 Oct 2026 00:24:48 -0700 Subject: [PATCH] test(system): compare Auto-tagging with the concept against the real backend --- tests/browser/system-tagging-concept.spec.mjs | 7 +++++-- tests/browser/workspace-system-tagging.spec.mjs | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/browser/system-tagging-concept.spec.mjs b/tests/browser/system-tagging-concept.spec.mjs index 43cb2bd2..61b19710 100644 --- a/tests/browser/system-tagging-concept.spec.mjs +++ b/tests/browser/system-tagging-concept.spec.mjs @@ -285,7 +285,7 @@ function mapBatchConcept(reference, plan) { title: 'Review tag output images', tree: ['h3', 'dl.meta-grid', 'p.small', 'div.notice', 'div.dialog-actions'], heading: { ...reference.heading, text: 'Tag output images' }, - grid: { ...reference.grid, rows: [['Model', 'WD14 SwinV2 · ~400 MB'], ['Existing tags', 'Skip already tagged'], + grid: { ...reference.grid, rows: [['Model', 'WD14 SwinV2 · ~400 MB'], ['Existing tags', 'Merge with existing'], ['Images linked', number(plan.images)], ['Prompts', number(plan.prompts)], ['Already tagged', number(plan.already_tagged)], ['Prompts to tag', `up to ${number(plan.to_tag)}`], ['Settings', 'General 0.35 · Character 0.85'], ['Backup', 'Create and verify before changes']] }, @@ -308,6 +308,9 @@ async function conceptReview(page, theme) { async function productionReview(page, theme) { await productionTagging(page, theme); + // Every concept-fixture prompt with an image is already tagged, so under the saved Skip there is nothing to start + // (the Cancel-only review). Merge reviews a batch with work: the full review the concept's shell is compared with. + await page.locator('#workspace-main #tag-existing').selectOption('merge'); const answer = page.waitForResponse(response => response.url().endsWith(PREVIEW_URL)); await page.locator('#workspace-main .operation').getByRole('button', { name: 'Review', exact: true }).click(); const plan = await (await answer).json(); @@ -323,7 +326,7 @@ for (const theme of THEMES) for (const [width, height] of SIZES) { expect(concept.tree).toEqual(['p.demo-note', 'h3', 'dl.meta-grid', 'p.small', 'div.dialog-actions']); await page.screenshot({ path: testInfo.outputPath(`concept-plan-review-${theme}-${width}.png`) }); const { plan, production } = await productionReview(page, theme); - // The concept fixture links images to prompts, some untagged: the batch has work to review. + // Under Merge every prompt with a linked image is tagged again: the batch has work to review. expect(plan.to_tag).toBeGreaterThan(0); await page.screenshot({ path: testInfo.outputPath(`production-tagging-review-${theme}-${width}.png`) }); expect(diffInventory(mapBatchConcept(concept, plan), production)).toEqual([]); diff --git a/tests/browser/workspace-system-tagging.spec.mjs b/tests/browser/workspace-system-tagging.spec.mjs index e2bb51d5..26191357 100644 --- a/tests/browser/workspace-system-tagging.spec.mjs +++ b/tests/browser/workspace-system-tagging.spec.mjs @@ -164,7 +164,8 @@ test('defaults save through Save preferences and the Tag image dialog uses them' test('a refused value shows the server\'s message', async ({ page, request }) => { const before = (await serverJson(request, SETTINGS_URL)).settings; - await openTagging(page); + // An image is selected, so Preview tagging review is held back only by the invalid value below. + await selectThenOpen(page, FIRST); await page.locator('#threshold-general').fill('1.5'); await page.locator('#threshold-general').press('Tab'); await save(page).click(); @@ -173,13 +174,18 @@ test('a refused value shows the server\'s message', async ({ page, request }) => // Nothing was written; the draft is kept for the next Save. expect((await serverJson(request, SETTINGS_URL)).settings.autotag_general_threshold).toBe(before.autotag_general_threshold); await expect(page.locator('#threshold-general')).toHaveValue('1.5'); - // While the value is invalid, Preview tagging review explains instead of opening. - await actionOf(page, 'Preview tagging review').click(); + // While the value is invalid, Preview tagging review is aria-disabled and explains instead of opening (Playwright + // waits on an aria-disabled control, so it is pressed from the keyboard, as a user can). + await expect(actionOf(page, 'Preview tagging review')).toHaveAttribute('aria-disabled', 'true'); + await actionOf(page, 'Preview tagging review').focus(); + await page.keyboard.press('Enter'); await expect(toast(page)).toHaveText('General-tag confidence must be between 0 and 1.'); + await expect(tagDialog(page)).toHaveCount(0); await page.locator('#threshold-general').fill('0.5'); await page.locator('#threshold-general').press('Tab'); await expect(page.locator('#threshold-general')).not.toHaveAttribute('aria-invalid', 'true'); await expect(status(page)).toHaveText('Unsaved changes.'); + await expect(actionOf(page, 'Preview tagging review')).not.toHaveAttribute('aria-disabled', 'true'); }); test('Download starts the job and Activity shows it without Cancel', async ({ page, request }) => { @@ -341,7 +347,9 @@ test('a model that is not downloaded cannot be reviewed for a batch; the button await openTagging(page); await page.locator('#tag-model').selectOption('gguf'); await expect(reviewButton(page)).toHaveAttribute('aria-disabled', 'true'); - await reviewButton(page).click(); + // Playwright waits on an aria-disabled control: press it from the keyboard, as a user can. + await reviewButton(page).focus(); + await page.keyboard.press('Enter'); await expect(toast(page)).toHaveText('GGUF JoyCaption is not downloaded. Download it first.'); await expect(dialog(page)).toHaveCount(0); expect(page.modelCalls.filter(call => call.includes('/batch/preview'))).toEqual([]);