Compare commits

...

8 Commits

Author SHA1 Message Date
dante01yoon
ae95dfe3a7 fix: simplify cancel dialog test to match OSS runtime behavior
The legacy cancel path swallows auth errors via
wrapWithErrorHandlingAsync, so the dialog closes on click
regardless of auth state. Test the actual observable behavior:
button click initiates the flow and closes the dialog.
2026-04-10 11:11:46 +09:00
dante01yoon
9ca7708b6d test: deepen billing dialog E2E tests per review feedback
- Cancel dialog: mock /customers/billing route, click button, assert API
  call via expect.poll; add error handling test
- TopUp dialog: assert pay input updates on preset click, use aria-label
  for close button, verify pricing link href and target
- Add aria-label to TopUpCredits close buttons for semantic locators
- Extract shared helpers to reduce duplication
2026-04-10 10:53:02 +09:00
dante01yoon
6ffa0cc573 test: fix TopUpCredits strict mode violations and remove OSS-incompatible API tests 2026-04-09 13:02:12 +09:00
dante01yoon
4adc3d7ff9 test: remove OSS-incompatible cancel API tests, keep UI behavior tests 2026-04-09 12:51:40 +09:00
dante01yoon
c77cab7387 test: fix billing dialog CI failures — API assertion and strict mode 2026-04-09 12:33:46 +09:00
dante01yoon
b85ae04611 test: use midday UTC timestamp for timezone stability 2026-04-09 06:01:17 +09:00
dante01yoon
babfdbf5cf test: fix billing dialog E2E test quality — stronger selectors and missing coverage 2026-04-09 05:58:56 +09:00
dante01yoon
3f8d9fe0b2 test: add E2E tests for CancelSubscription and TopUpCredits dialogs 2026-04-09 05:47:32 +09:00
4 changed files with 192 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import type { WorkspaceStore } from '@e2e/types/globals'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
async function openCancelSubscriptionDialog(page: Page, cancelAt?: string) {
await page.evaluate((date) => {
void (
window.app!.extensionManager as WorkspaceStore
).dialog.showCancelSubscriptionDialog(date)
}, cancelAt)
}
test.describe('CancelSubscription dialog', { tag: '@ui' }, () => {
test('displays dialog with title and formatted date', async ({
comfyPage
}) => {
const { page } = comfyPage
await openCancelSubscriptionDialog(page, '2025-12-31T12:00:00Z')
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await expect(
dialog.getByRole('heading', { name: 'Cancel subscription' })
).toBeVisible()
await expect(dialog).toContainText('December 31, 2025')
})
test('"Keep subscription" button closes dialog', async ({ comfyPage }) => {
const { page } = comfyPage
await openCancelSubscriptionDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await dialog.getByRole('button', { name: 'Keep subscription' }).click()
await expect(dialog).toBeHidden()
})
test('Escape key closes dialog', async ({ comfyPage }) => {
const { page } = comfyPage
await openCancelSubscriptionDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await page.keyboard.press('Escape')
await expect(dialog).toBeHidden()
})
test('"Cancel subscription" button initiates cancellation flow', async ({
comfyPage
}) => {
const { page } = comfyPage
await openCancelSubscriptionDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
const cancelBtn = dialog.getByRole('button', {
name: 'Cancel subscription'
})
await expect(cancelBtn).toBeVisible()
await expect(cancelBtn).toBeEnabled()
await cancelBtn.click()
// Clicking triggers the cancellation flow which closes the dialog
await expect(dialog).toBeHidden()
})
})

View File

@@ -0,0 +1,113 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import type { WorkspaceStore } from '@e2e/types/globals'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
async function openTopUpCreditsDialog(
page: Page,
options?: { isInsufficientCredits?: boolean }
) {
await page.evaluate((opts) => {
void (
window.app!.extensionManager as WorkspaceStore
).dialog.showTopUpCreditsDialog(opts)
}, options)
}
test.describe('TopUpCredits dialog', { tag: '@ui' }, () => {
test('displays dialog with heading and preset amounts', async ({
comfyPage
}) => {
const { page } = comfyPage
await openTopUpCreditsDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await expect(
dialog.getByRole('heading', { name: 'Add more credits' })
).toBeVisible()
await expect(
dialog.getByRole('button', { name: '$10' }).first()
).toBeVisible()
await expect(
dialog.getByRole('button', { name: '$25' }).first()
).toBeVisible()
await expect(
dialog.getByRole('button', { name: '$50' }).first()
).toBeVisible()
await expect(
dialog.getByRole('button', { name: '$100' }).first()
).toBeVisible()
})
test('displays insufficient credits message when opened with flag', async ({
comfyPage
}) => {
const { page } = comfyPage
await openTopUpCreditsDialog(page, { isInsufficientCredits: true })
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await expect(
dialog.getByRole('heading', { name: 'Add more credits to run' })
).toBeVisible()
await expect(dialog).toContainText(
"You don't have enough credits to run this workflow"
)
})
test('selecting a preset amount updates the pay amount', async ({
comfyPage
}) => {
const { page } = comfyPage
await openTopUpCreditsDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
// Default preset is $50, click $10 instead
const tenDollarBtn = dialog.getByRole('button', { name: '$10' }).first()
await tenDollarBtn.click()
// The "You Pay" input should reflect $10
const payInput = dialog.locator('input').first()
await expect(payInput).toHaveValue('10')
})
test('close button dismisses dialog', async ({ comfyPage }) => {
const { page } = comfyPage
await openTopUpCreditsDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
await dialog.getByRole('button', { name: 'Close' }).click()
await expect(dialog).toBeHidden()
})
test('pricing details link points to docs pricing page', async ({
comfyPage
}) => {
const { page } = comfyPage
await openTopUpCreditsDialog(page)
const dialog = page.getByRole('dialog')
await expect(dialog).toBeVisible()
const pricingLink = dialog.getByRole('link', {
name: 'View pricing details'
})
await expect(pricingLink).toBeVisible()
await expect(pricingLink).toHaveAttribute('href', /partner-nodes\/pricing/)
await expect(pricingLink).toHaveAttribute('target', '_blank')
})
})

View File

@@ -13,6 +13,7 @@
</h2>
<button
class="focus-visible:ring-secondary-foreground cursor-pointer rounded-sm border-none bg-transparent p-0 text-muted-foreground transition-colors hover:text-base-foreground focus-visible:ring-1 focus-visible:outline-none"
:aria-label="$t('g.close')"
@click="() => handleClose()"
>
<i class="icon-[lucide--x] size-6" />

View File

@@ -13,6 +13,7 @@
</h2>
<button
class="focus-visible:ring-secondary-foreground cursor-pointer rounded-sm border-none bg-transparent p-0 text-muted-foreground transition-colors hover:text-base-foreground focus-visible:ring-1 focus-visible:outline-none"
:aria-label="$t('g.close')"
@click="() => handleClose()"
>
<i class="icon-[lucide--x] size-6" />