diff --git a/browser_tests/fixtures/components/Topbar.ts b/browser_tests/fixtures/components/Topbar.ts index c91ccf11e8..608a262f07 100644 --- a/browser_tests/fixtures/components/Topbar.ts +++ b/browser_tests/fixtures/components/Topbar.ts @@ -82,7 +82,7 @@ export class Topbar { } getSaveDialog(): Locator { - return this.page.locator('.p-dialog-content input') + return this.page.getByRole('dialog').getByRole('textbox') } saveWorkflow(workflowName: string): Promise { @@ -116,9 +116,9 @@ export class Topbar { // Check if a confirmation dialog appeared (e.g., "Overwrite existing file?") // If so, return early to let the test handle the confirmation - const confirmationDialog = this.page.locator( - '.p-dialog:has-text("Overwrite")' - ) + const confirmationDialog = this.page + .getByRole('dialog') + .filter({ hasText: 'Overwrite' }) if (await confirmationDialog.isVisible()) { return } diff --git a/browser_tests/fixtures/helpers/BuilderSelectHelper.ts b/browser_tests/fixtures/helpers/BuilderSelectHelper.ts index 6b56182e6b..5a878556c4 100644 --- a/browser_tests/fixtures/helpers/BuilderSelectHelper.ts +++ b/browser_tests/fixtures/helpers/BuilderSelectHelper.ts @@ -127,9 +127,7 @@ export class BuilderSelectHelper { await popoverTrigger.click() await this.page.getByText('Rename', { exact: true }).click() - const dialogInput = this.page.locator( - '.p-dialog-content input[type="text"]' - ) + const dialogInput = this.page.getByRole('dialog').getByRole('textbox') await dialogInput.fill(newName) await this.page.keyboard.press('Enter') await dialogInput.waitFor({ state: 'hidden' }) diff --git a/browser_tests/fixtures/helpers/NodeOperationsHelper.ts b/browser_tests/fixtures/helpers/NodeOperationsHelper.ts index 9ad8cc8009..a0fadd2f74 100644 --- a/browser_tests/fixtures/helpers/NodeOperationsHelper.ts +++ b/browser_tests/fixtures/helpers/NodeOperationsHelper.ts @@ -18,9 +18,7 @@ export class NodeOperationsHelper { public readonly promptDialogInput: Locator constructor(private comfyPage: ComfyPage) { - this.promptDialogInput = this.page.locator( - '.p-dialog-content input[type="text"]' - ) + this.promptDialogInput = this.page.getByRole('dialog').getByRole('textbox') } private get page() { diff --git a/browser_tests/tests/defaultKeybindings.spec.ts b/browser_tests/tests/defaultKeybindings.spec.ts index 3ecdf0e89a..54ea64f90d 100644 --- a/browser_tests/tests/defaultKeybindings.spec.ts +++ b/browser_tests/tests/defaultKeybindings.spec.ts @@ -229,9 +229,9 @@ test.describe('Default Keybindings', { tag: '@keyboard' }, () => { // The dialog appearing proves the keybinding was intercepted by the app. await comfyPage.keyboard.press('Control+s') - // The Save As dialog should appear (p-dialog overlay) - const dialogOverlay = comfyPage.page.locator('.p-dialog-mask') - await expect(dialogOverlay).toBeVisible() + // The Save As dialog should appear + const saveDialog = comfyPage.page.getByRole('dialog') + await expect(saveDialog).toBeVisible() // Dismiss the dialog await comfyPage.keyboard.press('Escape') diff --git a/browser_tests/tests/dialogs/publishDialog.spec.ts b/browser_tests/tests/dialogs/publishDialog.spec.ts index 00d7db0bbe..4820d35851 100644 --- a/browser_tests/tests/dialogs/publishDialog.spec.ts +++ b/browser_tests/tests/dialogs/publishDialog.spec.ts @@ -16,9 +16,9 @@ async function saveAndOpenPublishDialog( workflowName: string ): Promise { await comfyPage.menu.topbar.saveWorkflow(workflowName) - const overwriteDialog = comfyPage.page.locator( - '.p-dialog:has-text("Overwrite")' - ) + const overwriteDialog = comfyPage.page + .getByRole('dialog') + .filter({ hasText: 'Overwrite' }) // Bounded wait: point-in-time isVisible() can miss dialogs that open // slightly after saveWorkflow() resolves. try { diff --git a/src/components/dialog/GlobalDialog.vue b/src/components/dialog/GlobalDialog.vue index b3d24ceeaf..67f21481d7 100644 --- a/src/components/dialog/GlobalDialog.vue +++ b/src/components/dialog/GlobalDialog.vue @@ -11,6 +11,7 @@ { + renderComponent({ type: 'default' }) + expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument() + expect( + screen.getByRole('button', { name: 'Confirm' }) + ).toBeInTheDocument() }) - await userEvent.click(screen.getByRole('button', { name: 'Close anyway' })) + it("type='delete' renders Cancel and Delete", () => { + renderComponent({ type: 'delete' }) + expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument() + }) - expect(onConfirm).toHaveBeenCalledWith(false) + it("type='overwrite' renders Cancel and Overwrite", () => { + renderComponent({ type: 'overwrite' }) + expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument() + expect( + screen.getByRole('button', { name: 'Overwrite' }) + ).toBeInTheDocument() + }) + + it("type='dirtyClose' renders No and Save (no Cancel)", () => { + renderComponent({ type: 'dirtyClose' }) + expect( + screen.queryByRole('button', { name: 'Cancel' }) + ).not.toBeInTheDocument() + expect(screen.getByRole('button', { name: 'No' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument() + }) + + it("type='info' renders only OK (no Cancel)", () => { + renderComponent({ type: 'info' }) + expect(screen.getByRole('button', { name: 'OK' })).toBeInTheDocument() + expect( + screen.queryByRole('button', { name: 'Cancel' }) + ).not.toBeInTheDocument() + }) }) - it('calls onConfirm(true) when save is clicked on dirtyClose', async () => { + it('confirm callback receives true and closes the dialog', async () => { const onConfirm = vi.fn() - renderComponent({ type: 'dirtyClose', onConfirm }) + const { user } = renderComponent({ type: 'default', onConfirm }) + const closeSpy = vi.spyOn(useDialogStore(), 'closeDialog') - await userEvent.click(screen.getByRole('button', { name: 'g.save' })) + await user.click(screen.getByRole('button', { name: 'Confirm' })) expect(onConfirm).toHaveBeenCalledWith(true) + expect(closeSpy).toHaveBeenCalledOnce() }) - it('falls back to "no" label when denyLabel is not provided', () => { - renderComponent({ type: 'dirtyClose' }) - expect(screen.getByText('g.no')).toBeInTheDocument() + describe('dirtyClose deny label', () => { + it('uses the provided denyLabel for the deny button', () => { + renderComponent({ type: 'dirtyClose', denyLabel: 'Sign out anyway' }) + expect(screen.getByText('Sign out anyway')).toBeInTheDocument() + expect( + screen.queryByRole('button', { name: 'No' }) + ).not.toBeInTheDocument() + }) + + it('falls back to "No" when denyLabel is not provided', () => { + renderComponent({ type: 'dirtyClose' }) + expect(screen.getByRole('button', { name: 'No' })).toBeInTheDocument() + }) + + it('calls onConfirm(false) when deny is clicked', async () => { + const onConfirm = vi.fn() + const { user } = renderComponent({ + type: 'dirtyClose', + denyLabel: 'Close anyway', + onConfirm + }) + + await user.click(screen.getByRole('button', { name: 'Close anyway' })) + + expect(onConfirm).toHaveBeenCalledWith(false) + }) + + it('calls onConfirm(true) when save is clicked', async () => { + const onConfirm = vi.fn() + const { user } = renderComponent({ type: 'dirtyClose', onConfirm }) + + await user.click(screen.getByRole('button', { name: 'Save' })) + + expect(onConfirm).toHaveBeenCalledWith(true) + }) }) }) diff --git a/src/components/dialog/content/ConfirmationDialogContent.vue b/src/components/dialog/content/ConfirmationDialogContent.vue index daa9b259b3..683f0b9781 100644 --- a/src/components/dialog/content/ConfirmationDialogContent.vue +++ b/src/components/dialog/content/ConfirmationDialogContent.vue @@ -9,16 +9,14 @@ {{ item }} - - {{ hint }} - +