Files
ComfyUI_frontend/browser_tests/tests/subscriptionPaywallError.spec.ts
Dante 67b884d0f7 fix(billing): route subscription/sign-in/credit preconditions to modal, out of error panel (FE-878) (#12785)
## Summary

Account preconditions (sign-in / subscription / credits) on running a
workflow now open their modal directly and stay out of the error panel +
error count — previously `subscription_required` fell through to a red
"1 ERROR — Subscription required to queue workflows" banner. This covers
**both** paths: the `execution_error` websocket event and the `POST
/prompt` 402 queue paywall (`{ type: "PAYMENT_REQUIRED", message:
"Subscription required to queue workflows" }`), which is the exact
payload reported in #12840.

## Changes

- **What**: `execution_error` is classified by a pure
`accountPreconditionRouting` resolver (precedence sign-in > subscription
> credits) and routed to the existing modal via
`useAccountPreconditionDialog`; `executionStore` returns early for
preconditions so they never populate `lastExecutionError` /
`lastPromptError` / `lastNodeErrors` → fully excluded from the panel and
`totalErrorCount`. Runtime credit error at a node → credits modal (out
of panel; can name the node).
- **Queue paywall**: the `queuePrompt` catch resolves the same
precondition from the `POST /prompt` 402 response and opens the modal,
short-circuiting before `lastPromptError`, so the queue paywall stays
out of the panel too. The runtime matcher learns the `"Subscription
required to queue workflows"` message.
- **Breaking**: none.

## Before / After

Free-tier queue paywall (`POST /prompt` → 402) on a cloud build:

**Before** — raw `Subscription required to queue workflows` surfaced in
the error panel (no actionable upgrade):

<img width="1600" height="873" alt="before-error-panel"
src="https://github.com/user-attachments/assets/1b76b742-16bf-47e3-9245-17e35f8f1e70"
/>

**After** — clean subscription modal opens; nothing in the error panel
or error count:

<img width="1600" height="873" alt="after-subscription-modal"
src="https://github.com/user-attachments/assets/13d238cb-20bf-4795-a530-5abcf9968dc7"
/>

## Review Focus

- **Routing-only — the run button is intentionally untouched.** The
original AC#3 ("no Subscribe-to-Run button") is superseded by the FE-978
run-lock decision (pre-emptive role-aware lock, Figma 3253-18671).
Complements #12786 (FE-978 run-lock); disjoint file sets.
- Tests: `accountPreconditionRouting` / `useAccountPreconditionDialog` /
`executionStore` — each precondition routes to its modal and is excluded
from the panel/count; precedence resolves on co-occurrence. Plus
Playwright `browser_tests/tests/subscriptionPaywallError.spec.ts` — the
queue paywall (402) stays out of the error panel, with a control
asserting ordinary queue errors still surface. typecheck / oxlint /
eslint / stylelint / oxfmt / knip clean.

Fixes FE-878
Fixes #12840
2026-06-19 00:51:52 +00:00

69 lines
2.2 KiB
TypeScript

import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import type { PromptResponse } from '@/schemas/apiSchema'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
// Regression for #12840: a free-tier paywall on queue (`POST /prompt` 402 with
// `{ error: { type: 'PAYMENT_REQUIRED', message: 'Subscription required to
// queue workflows' } }`) is an account precondition. It must open its own modal
// and stay out of the error panel, instead of surfacing the raw backend string
// with non-actionable Find-on-GitHub / Copy actions.
test.describe('Subscription paywall on queue', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
})
async function mockQueueError(page: Page, error: PromptResponse['error']) {
const body: PromptResponse = { node_errors: {}, error }
await page.route('**/api/prompt', async (route) => {
await route.fulfill({
status: 402,
contentType: 'application/json',
body: JSON.stringify(body)
})
})
}
test('keeps the subscription paywall out of the error panel', async ({
comfyPage
}) => {
await mockQueueError(comfyPage.page, {
type: 'PAYMENT_REQUIRED',
message: 'Subscription required to queue workflows',
details: ''
})
const queued = comfyPage.page.waitForResponse('**/api/prompt')
await comfyPage.actionbar.queueButton.primaryButton.click()
await queued
await expect(
comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
).toBeHidden()
})
test('still surfaces ordinary queue errors in the error panel', async ({
comfyPage
}) => {
await mockQueueError(comfyPage.page, {
type: 'server_error',
message: 'The server exploded',
details: ''
})
const queued = comfyPage.page.waitForResponse('**/api/prompt')
await comfyPage.actionbar.queueButton.primaryButton.click()
await queued
await expect(
comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
).toBeVisible()
})
})