Merge branch 'main' into glary/replace-delay-with-retrying-assertions

This commit is contained in:
Alexander Brown
2026-04-08 11:29:47 -07:00
committed by GitHub
207 changed files with 1991 additions and 884 deletions

View File

@@ -0,0 +1,39 @@
{
"last_node_id": 2,
"last_link_id": 0,
"nodes": [
{
"id": 1,
"type": "ResizeImageMaskNode",
"pos": [100, 100],
"size": [315, 200],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [{ "name": "result", "type": "IMAGE", "links": null }],
"properties": {
"Node name for S&R": "ResizeImageMaskNode"
},
"widgets_values": ["scale dimensions", 512, 512, "center", "area"]
},
{
"id": 2,
"type": "SaveImage",
"pos": [500, 100],
"size": [210, 58],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [{ "name": "images", "type": "IMAGE", "link": null }],
"properties": {}
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": { "offset": [0, 0], "scale": 1 }
},
"version": 0.4
}

View File

@@ -0,0 +1,85 @@
{
"last_node_id": 2,
"last_link_id": 0,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [100, 100],
"size": [315, 98],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": null
},
{
"name": "CLIP",
"type": "CLIP",
"links": null
},
{
"name": "VAE",
"type": "VAE",
"links": null
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["fake_model.safetensors"]
},
{
"id": 2,
"type": "CheckpointLoaderSimple",
"pos": [500, 100],
"size": [315, 98],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": null
},
{
"name": "CLIP",
"type": "CLIP",
"links": null
},
{
"name": "VAE",
"type": "VAE",
"links": null
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["fake_model.safetensors"]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [0, 0]
}
},
"models": [
{
"name": "fake_model.safetensors",
"url": "http://localhost:8188/api/devtools/fake_model.safetensors",
"directory": "text_encoders"
}
],
"version": 0.4
}

View File

@@ -0,0 +1,72 @@
{
"last_node_id": 10,
"last_link_id": 0,
"nodes": [
{
"id": 1,
"type": "UNKNOWN NODE",
"pos": [48, 86],
"size": [358, 314],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": null,
"slot_index": 0
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": [],
"slot_index": 0,
"shape": 6
}
],
"properties": {
"Node name for S&R": "UNKNOWN NODE"
},
"widgets_values": ["wd-v1-4-moat-tagger-v2", 0.35, 0.85, false, false, ""]
},
{
"id": 10,
"type": "LoadImage",
"pos": [450, 86],
"size": [315, 314],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": null
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": ["nonexistent_test_image_12345.png", "image"]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -1,7 +1,7 @@
import type { Mouse } from '@playwright/test'
import type { ComfyPage } from './ComfyPage'
import type { Position } from './types'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import type { Position } from '@e2e/fixtures/types'
/**
* Used for drag and drop ops

View File

@@ -2,7 +2,7 @@ import type { APIRequestContext, Locator, Page } from '@playwright/test'
import { test as base } from '@playwright/test'
import { config as dotenvConfig } from 'dotenv'
import { NodeBadgeMode } from '../../src/types/nodeSource'
import { NodeBadgeMode } from '@/types/nodeSource'
import { ComfyActionbar } from '@e2e/helpers/actionbar'
import { ComfyTemplates } from '@e2e/helpers/templates'
import { ComfyMouse } from '@e2e/fixtures/ComfyMouse'
@@ -45,7 +45,7 @@ import { SettingsHelper } from '@e2e/fixtures/helpers/SettingsHelper'
import { SubgraphHelper } from '@e2e/fixtures/helpers/SubgraphHelper'
import { ToastHelper } from '@e2e/fixtures/helpers/ToastHelper'
import { WorkflowHelper } from '@e2e/fixtures/helpers/WorkflowHelper'
import type { WorkspaceStore } from '../types/globals'
import type { WorkspaceStore } from '@e2e/types/globals'
dotenvConfig()

View File

@@ -3,8 +3,8 @@
*/
import type { Locator, Page } from '@playwright/test'
import { TestIds } from './selectors'
import { VueNodeFixture } from './utils/vueNodeFixtures'
import { TestIds } from '@e2e/fixtures/selectors'
import { VueNodeFixture } from '@e2e/fixtures/utils/vueNodeFixtures'
export class VueNodeHelpers {
constructor(private page: Page) {}
@@ -109,6 +109,14 @@ export class VueNodeHelpers {
await this.page.keyboard.press('Delete')
}
/**
* Select a node by ID and delete it.
*/
async deleteNode(nodeId: string): Promise<void> {
await this.selectNode(nodeId)
await this.deleteSelected()
}
/**
* Delete selected Vue nodes using Backspace key
*/
@@ -158,6 +166,21 @@ export class VueNodeHelpers {
})
}
/**
* Select an option from a combo widget on a node.
*/
async selectComboOption(
nodeTitle: string,
widgetName: string,
optionName: string
): Promise<void> {
const node = this.getNodeByTitle(nodeTitle)
await node.getByRole('combobox', { name: widgetName, exact: true }).click()
await this.page
.getByRole('option', { name: optionName, exact: true })
.click()
}
/**
* Get controls for input number widgets (increment/decrement buttons and input)
*/

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
export class ComfyNodeSearchBoxV2 {
readonly dialog: Locator

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { WorkspaceStore } from '../../types/globals'
import type { WorkspaceStore } from '@e2e/types/globals'
type KeysOfType<T, Match> = {
[K in keyof T]: T[K] extends Match ? K : never

View File

@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import { comfyExpect as expect } from '../ComfyPage'
import { TestIds } from '../selectors'
import { comfyExpect as expect } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
export class QueuePanel {
readonly overlayToggle: Locator

View File

@@ -1,8 +1,8 @@
import type { Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import { BaseDialog } from './BaseDialog'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
import { BaseDialog } from '@e2e/fixtures/components/BaseDialog'
export class SettingDialog extends BaseDialog {
constructor(

View File

@@ -1,8 +1,8 @@
import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import type { WorkspaceStore } from '../../types/globals'
import { TestIds } from '../selectors'
import type { WorkspaceStore } from '@e2e/types/globals'
import { TestIds } from '@e2e/fixtures/selectors'
class SidebarTab {
constructor(

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import { BaseDialog } from './BaseDialog'
import { BaseDialog } from '@e2e/fixtures/components/BaseDialog'
export class SignInDialog extends BaseDialog {
readonly emailInput: Locator

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { WorkspaceStore } from '../../types/globals'
import type { WorkspaceStore } from '@e2e/types/globals'
export class Topbar {
private readonly menuLocator: Locator

View File

@@ -1,4 +1,4 @@
import type { Position } from './types'
import type { Position } from '@e2e/fixtures/constants/types'
/**
* Hardcoded positions for the default graph loaded in tests.

View File

@@ -1,13 +1,13 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
import { AppModeWidgetHelper } from './AppModeWidgetHelper'
import { BuilderFooterHelper } from './BuilderFooterHelper'
import { BuilderSaveAsHelper } from './BuilderSaveAsHelper'
import { BuilderSelectHelper } from './BuilderSelectHelper'
import { BuilderStepsHelper } from './BuilderStepsHelper'
import { AppModeWidgetHelper } from '@e2e/fixtures/helpers/AppModeWidgetHelper'
import { BuilderFooterHelper } from '@e2e/fixtures/helpers/BuilderFooterHelper'
import { BuilderSaveAsHelper } from '@e2e/fixtures/helpers/BuilderSaveAsHelper'
import { BuilderSelectHelper } from '@e2e/fixtures/helpers/BuilderSelectHelper'
import { BuilderStepsHelper } from '@e2e/fixtures/helpers/BuilderStepsHelper'
export class AppModeHelper {
readonly steps: BuilderStepsHelper
@@ -39,13 +39,15 @@ export class AppModeHelper {
await this.comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
}
/** Enter builder mode via the "Workflow actions" dropdown → "Build app". */
/** Enter builder mode via the "Workflow actions" dropdown. */
async enterBuilder() {
await this.page
.getByRole('button', { name: 'Workflow actions' })
.first()
.click()
await this.page.getByRole('menuitem', { name: 'Build app' }).click()
await this.page
.getByRole('menuitem', { name: /Build app|Edit app/ })
.click()
await this.comfyPage.nextFrame()
}
@@ -92,6 +94,16 @@ export class AppModeHelper {
await this.toggleAppMode()
}
/** The "Connect an output" popover shown when saving without outputs. */
get connectOutputPopover(): Locator {
return this.page.getByTestId(TestIds.builder.connectOutputPopover)
}
/** The empty-state placeholder shown when no outputs are selected. */
get outputPlaceholder(): Locator {
return this.page.getByTestId(TestIds.builder.outputPlaceholder)
}
/** The linear-mode widget list container (visible in app mode). */
get linearWidgets(): Locator {
return this.page.locator('[data-testid="linear-widgets"]')

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
/**
* Helper for interacting with widgets rendered in app mode (linear view).

View File

@@ -9,7 +9,7 @@ import {
generateModels,
generateInputFiles,
generateOutputAssets
} from '../data/assetFixtures'
} from '@e2e/fixtures/data/assetFixtures'
export interface MutationRecord {
endpoint: string

View File

@@ -1,7 +1,7 @@
import type { Page, Route } from '@playwright/test'
import type { JobsListResponse } from '@comfyorg/ingest-types'
import type { RawJobListItem } from '../../../src/platform/remote/comfyui/jobs/jobTypes'
import type { RawJobListItem } from '@/platform/remote/comfyui/jobs/jobTypes'
const jobsListRoutePattern = /\/api\/jobs(?:\?.*)?$/
const inputFilesRoutePattern = /\/internal\/files\/input(?:\?.*)?$/

View File

@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
export class BuilderFooterHelper {
constructor(private readonly comfyPage: ComfyPage) {}

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
export class BuilderSaveAsHelper {
constructor(private readonly comfyPage: ComfyPage) {}

View File

@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
/**
* Drag an element from one index to another within a list of locators.
@@ -145,6 +145,26 @@ export class BuilderSelectHelper {
await this.comfyPage.nextFrame()
}
/**
* Get the subtitle locator for a builder IoItem by its title text.
* Useful for asserting "Widget not visible" on disconnected inputs.
*/
getInputItemSubtitle(title: string): Locator {
return this.page
.getByTestId(TestIds.builder.ioItem)
.filter({
has: this.page
.getByTestId(TestIds.builder.ioItemTitle)
.getByText(title, { exact: true })
})
.getByTestId(TestIds.builder.ioItemSubtitle)
}
/** All IoItem locators in the current step sidebar. */
get inputItems(): Locator {
return this.page.getByTestId(TestIds.builder.ioItem)
}
/** All IoItem title locators in the inputs step sidebar. */
get inputItemTitles(): Locator {
return this.page.getByTestId(TestIds.builder.ioItemTitle)

View File

@@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
export class BuilderStepsHelper {
constructor(private readonly comfyPage: ComfyPage) {}

View File

@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import { DefaultGraphPositions } from '../constants/defaultGraphPositions'
import type { Position } from '../types'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
import type { Position } from '@e2e/fixtures/types'
export class CanvasHelper {
constructor(

View File

@@ -3,8 +3,8 @@ import { basename } from 'path'
import type { Locator, Page } from '@playwright/test'
import type { KeyboardHelper } from './KeyboardHelper'
import { getMimeType } from './mimeTypeUtil'
import type { KeyboardHelper } from '@e2e/fixtures/helpers/KeyboardHelper'
import { getMimeType } from '@e2e/fixtures/helpers/mimeTypeUtil'
export class ClipboardHelper {
constructor(

View File

@@ -1,6 +1,6 @@
import type { Page } from '@playwright/test'
import type { KeyCombo } from '../../../src/platform/keybindings/types'
import type { KeyCombo } from '@/platform/keybindings/types'
export class CommandHelper {
constructor(private readonly page: Page) {}
@@ -41,6 +41,7 @@ export class CommandHelper {
commands: [
{
id: commandId,
// oxlint-disable-next-line no-eval -- intentional: eval reconstructs a serialized function inside Playwright's page context
function: eval(commandStr)
}
]
@@ -76,6 +77,7 @@ export class CommandHelper {
commands: [
{
id: commandId,
// oxlint-disable-next-line no-eval -- intentional: eval reconstructs a serialized function inside Playwright's page context
function: eval(commandStr)
}
]

View File

@@ -2,9 +2,9 @@ import { readFileSync } from 'fs'
import type { Page } from '@playwright/test'
import type { Position } from '../types'
import { getMimeType } from './mimeTypeUtil'
import { assetPath } from '../utils/paths'
import type { Position } from '@e2e/fixtures/types'
import { getMimeType } from '@e2e/fixtures/helpers/mimeTypeUtil'
import { assetPath } from '@e2e/fixtures/utils/paths'
export class DragDropHelper {
constructor(private readonly page: Page) {}

View File

@@ -3,7 +3,7 @@ import type { Page, Route } from '@playwright/test'
import type {
ModelFile,
ModelFolderInfo
} from '../../../src/platform/assets/schemas/assetSchema'
} from '@/platform/assets/schemas/assetSchema'
const modelFoldersRoutePattern = /\/api\/experiment\/models$/
const modelFilesRoutePattern = /\/api\/experiment\/models\/([^?]+)/

View File

@@ -1,14 +1,11 @@
import type { Locator } from '@playwright/test'
import type {
LGraph,
LGraphNode
} from '../../../src/lib/litegraph/src/litegraph'
import type { NodeId } from '../../../src/platform/workflow/validation/schemas/workflowSchema'
import type { ComfyPage } from '../ComfyPage'
import { DefaultGraphPositions } from '../constants/defaultGraphPositions'
import type { Position, Size } from '../types'
import { NodeReference } from '../utils/litegraphUtils'
import type { LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph'
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
import type { Position, Size } from '@e2e/fixtures/types'
import { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
export class NodeOperationsHelper {
constructor(private comfyPage: ComfyPage) {}

View File

@@ -7,10 +7,10 @@ import type {
} from '@/lib/litegraph/src/litegraph'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import type { NodeReference } from '../utils/litegraphUtils'
import { SubgraphSlotReference } from '../utils/litegraphUtils'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
import { SubgraphSlotReference } from '@e2e/fixtures/utils/litegraphUtils'
export class SubgraphHelper {
constructor(private readonly comfyPage: ComfyPage) {}

View File

@@ -1,13 +1,13 @@
import { readFileSync } from 'fs'
import type { AppMode } from '../../../src/composables/useAppMode'
import type { AppMode } from '@/composables/useAppMode'
import type {
ComfyApiWorkflow,
ComfyWorkflowJSON
} from '../../../src/platform/workflow/validation/schemas/workflowSchema'
import type { WorkspaceStore } from '../../types/globals'
import type { ComfyPage } from '../ComfyPage'
import { assetPath } from '../utils/paths'
} from '@/platform/workflow/validation/schemas/workflowSchema'
import type { WorkspaceStore } from '@e2e/types/globals'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { assetPath } from '@e2e/fixtures/utils/paths'
type FolderStructure = {
[key: string]: FolderStructure | string

View File

@@ -41,10 +41,21 @@ export const TestIds = {
missingNodeCard: 'missing-node-card',
errorCardFindOnGithub: 'error-card-find-on-github',
errorCardCopy: 'error-card-copy',
errorDialog: 'error-dialog',
errorDialogShowReport: 'error-dialog-show-report',
errorDialogContactSupport: 'error-dialog-contact-support',
errorDialogCopyReport: 'error-dialog-copy-report',
errorDialogFindIssues: 'error-dialog-find-issues',
about: 'about-panel',
whatsNewSection: 'whats-new-section',
missingNodePacksGroup: 'error-group-missing-node',
missingModelsGroup: 'error-group-missing-model',
missingModelExpand: 'missing-model-expand',
missingModelLocate: 'missing-model-locate',
missingModelCopyName: 'missing-model-copy-name',
missingModelCopyUrl: 'missing-model-copy-url',
missingModelDownload: 'missing-model-download',
missingModelImportUnsupported: 'missing-model-import-unsupported',
missingMediaGroup: 'error-group-missing-media',
missingMediaRow: 'missing-media-row',
missingMediaUploadDropzone: 'missing-media-upload-dropzone',
@@ -110,10 +121,13 @@ export const TestIds = {
saveAsChevron: 'builder-save-as-chevron',
ioItem: 'builder-io-item',
ioItemTitle: 'builder-io-item-title',
ioItemSubtitle: 'builder-io-item-subtitle',
widgetActionsMenu: 'widget-actions-menu',
opensAs: 'builder-opens-as',
widgetItem: 'builder-widget-item',
widgetLabel: 'builder-widget-label'
widgetLabel: 'builder-widget-label',
outputPlaceholder: 'builder-output-placeholder',
connectOutputPopover: 'builder-connect-output-popover'
},
appMode: {
widgetItem: 'app-mode-widget-item'

View File

@@ -1,7 +1,7 @@
import type { ExpectMatcherState, Locator } from '@playwright/test'
import { expect } from '@playwright/test'
import type { NodeReference } from './litegraphUtils'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
function makeMatcher<T>(
getValue: (node: NodeReference) => Promise<T> | T,

View File

@@ -1,10 +1,10 @@
import { expect } from '@playwright/test'
import type { Page } from '@playwright/test'
import type { NodeId } from '../../../src/platform/workflow/validation/schemas/workflowSchema'
import { ManageGroupNode } from '../../helpers/manageGroupNode'
import type { ComfyPage } from '../ComfyPage'
import type { Position, Size } from '../types'
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
import { ManageGroupNode } from '@e2e/helpers/manageGroupNode'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import type { Position, Size } from '@e2e/fixtures/types'
export const getMiddlePoint = (pos1: Position, pos2: Position) => {
return {

View File

@@ -1,6 +1,6 @@
import type { Locator } from '@playwright/test'
import { TestIds } from '../selectors'
import { TestIds } from '@e2e/fixtures/selectors'
/** DOM-centric helper for a single Vue-rendered node on the canvas. */
export class VueNodeFixture {

View File

@@ -1,6 +1,6 @@
import { config as dotenvConfig } from 'dotenv'
import { backupPath } from './utils/backupUtils'
import { backupPath } from '@e2e/utils/backupUtils'
dotenvConfig()

View File

@@ -1,7 +1,7 @@
import { config as dotenvConfig } from 'dotenv'
import { writePerfReport } from './helpers/perfReporter'
import { restorePath } from './utils/backupUtils'
import { writePerfReport } from '@e2e/helpers/perfReporter'
import { restorePath } from '@e2e/utils/backupUtils'
dotenvConfig()

View File

@@ -1,8 +1,8 @@
import type { Locator, Page } from '@playwright/test'
import type { AutoQueueMode } from '../../src/stores/queueStore'
import { TestIds } from '../fixtures/selectors'
import type { WorkspaceStore } from '../types/globals'
import type { AutoQueueMode } from '@/stores/queueStore'
import { TestIds } from '@e2e/fixtures/selectors'
import type { WorkspaceStore } from '@e2e/types/globals'
export class ComfyActionbar {
public readonly root: Locator

View File

@@ -1,11 +1,11 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import type { AppModeHelper } from '../fixtures/helpers/AppModeHelper'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import type { AppModeHelper } from '@e2e/fixtures/helpers/AppModeHelper'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
import { comfyExpect } from '../fixtures/ComfyPage'
import { fitToViewInstant } from './fitToView'
import { comfyExpect } from '@e2e/fixtures/ComfyPage'
import { fitToViewInstant } from '@e2e/helpers/fitToView'
interface BuilderSetupResult {
inputNodeTitle: string

View File

@@ -0,0 +1,19 @@
import type { Page } from '@playwright/test'
export async function interceptClipboardWrite(page: Page) {
await page.evaluate(() => {
const w = window as Window & { __copiedText?: string }
w.__copiedText = ''
navigator.clipboard.writeText = async (text: string) => {
w.__copiedText = text
}
})
}
export async function getClipboardText(page: Page): Promise<string> {
return (
(await page.evaluate(
() => (window as Window & { __copiedText?: string }).__copiedText
)) ?? ''
)
}

View File

@@ -1,5 +1,5 @@
import type { ReadOnlyRect } from '../../src/lib/litegraph/src/interfaces'
import type { ComfyPage } from '../fixtures/ComfyPage'
import type { ReadOnlyRect } from '@/lib/litegraph/src/interfaces'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
interface FitToViewOptions {
selectionOnly?: boolean

View File

@@ -1,7 +1,7 @@
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs'
import { join } from 'path'
import type { PerfMeasurement } from '../fixtures/helpers/PerformanceHelper'
import type { PerfMeasurement } from '@e2e/fixtures/helpers/PerformanceHelper'
export interface PerfReport {
timestamp: string
@@ -41,6 +41,7 @@ export function logMeasurement(
if (formatter) return formatter(m)
return `${f}=${m[f]}`
})
// oxlint-disable-next-line no-console -- perf reporter intentionally logs to stdout
console.log(`${label}: ${parts.join(', ')}`)
}

View File

@@ -1,4 +1,4 @@
import type { ComfyPage } from '../fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
export type PromotedWidgetEntry = [string, string]

View File

@@ -5,8 +5,8 @@ import path from 'path'
import type {
TemplateInfo,
WorkflowTemplates
} from '../../src/platform/workflow/templates/types/template'
import { TestIds } from '../fixtures/selectors'
} from '@/platform/workflow/templates/types/template'
import { TestIds } from '@e2e/fixtures/selectors'
export class ComfyTemplates {
readonly content: Locator

View File

@@ -1,10 +1,10 @@
import type { Response } from '@playwright/test'
import { expect, mergeTests } from '@playwright/test'
import type { StatusWsMessage } from '../../src/schemas/apiSchema'
import type { StatusWsMessage } from '@/schemas/apiSchema'
import { comfyPageFixture } from '@e2e/fixtures/ComfyPage'
import { webSocketFixture } from '@e2e/fixtures/ws'
import type { WorkspaceStore } from '../types/globals'
import type { WorkspaceStore } from '@e2e/types/globals'
const test = mergeTests(comfyPageFixture, webSocketFixture)

View File

@@ -3,7 +3,7 @@ import type { Page } from '@playwright/test'
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
/**
* Default workflow widget inputs as [nodeId, widgetName] tuples.

View File

@@ -0,0 +1,105 @@
import type { ComfyPage } from '../fixtures/ComfyPage'
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
import { setupBuilder } from '../helpers/builderTestUtils'
import { fitToViewInstant } from '../helpers/fitToView'
const RESIZE_NODE_TITLE = 'Resize Image/Mask'
const RESIZE_NODE_ID = '1'
const SAVE_IMAGE_NODE_ID = '9'
/**
* Load the dynamic combo workflow, enter builder,
* select a dynamic sub-widget as input and SaveImage as output.
*/
async function setupDynamicComboBuilder(comfyPage: ComfyPage) {
const { appMode } = comfyPage
await comfyPage.workflow.loadWorkflow('inputs/dynamic_combo')
await fitToViewInstant(comfyPage)
await appMode.enterBuilder()
await appMode.steps.goToInputs()
await appMode.select.selectInputWidget(RESIZE_NODE_TITLE, 'resize_type.width')
await appMode.steps.goToOutputs()
await appMode.select.selectOutputNode('Save Image')
}
test.describe('App Mode Pruning', { tag: ['@ui'] }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.appMode.enableLinearMode()
await comfyPage.settings.setSetting(
'Comfy.AppBuilder.VueNodeSwitchDismissed',
true
)
})
test('prunes deleted outputs', async ({ comfyPage }) => {
const { appMode } = comfyPage
// Enter builder with default workflow (seed input + SaveImage output)
await setupBuilder(comfyPage)
// Verify save-as dialog opens
await appMode.footer.saveAsButton.click()
await expect(appMode.saveAs.dialog).toBeVisible()
await appMode.saveAs.dialog.press('Escape')
// Exit builder, delete SaveImage node
await appMode.footer.exitBuilder()
await comfyPage.vueNodes.deleteNode(SAVE_IMAGE_NODE_ID)
await expect(
comfyPage.vueNodes.getNodeLocator(SAVE_IMAGE_NODE_ID)
).not.toBeAttached()
// Re-enter builder - pruning should auto-clean stale outputs
await appMode.enterBuilder()
await appMode.steps.goToOutputs()
await expect(appMode.outputPlaceholder).toBeVisible()
// Verify can't save
await appMode.footer.saveAsButton.click()
await expect(appMode.connectOutputPopover).toBeVisible()
})
test('does not prune missing widgets when node still exists for dynamic widgets', async ({
comfyPage
}) => {
const { appMode } = comfyPage
await setupDynamicComboBuilder(comfyPage)
await appMode.footer.exitBuilder()
await fitToViewInstant(comfyPage)
// Change dynamic combo from "scale dimensions" to "scale by multiplier"
// This removes the width/height widgets and adds factor
await comfyPage.vueNodes.selectComboOption(
RESIZE_NODE_TITLE,
'resize_type',
'scale by multiplier'
)
// Re-enter builder - node exists but widget is gone
await appMode.enterBuilder()
await appMode.steps.goToInputs()
// The input should still be listed but show "Widget not visible"
const subtitle = appMode.select.getInputItemSubtitle('resize_type.width')
await expect(subtitle).toHaveText('Widget not visible')
})
test('prunes missing widgets when node deleted', async ({ comfyPage }) => {
const { appMode } = comfyPage
await setupDynamicComboBuilder(comfyPage)
await appMode.footer.exitBuilder()
// Delete the ResizeImageMaskNode entirely
await comfyPage.vueNodes.deleteNode(RESIZE_NODE_ID)
// Re-enter builder - pruning should auto-clean stale inputs
await appMode.enterBuilder()
await appMode.steps.goToInputs()
await expect(appMode.select.inputItems).toHaveCount(0)
})
})

View File

@@ -1,11 +1,11 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
import {
saveAndReopenInAppMode,
setupSubgraphBuilder
} from '../helpers/builderTestUtils'
} from '@e2e/helpers/builderTestUtils'
test.describe('App mode widget rename', { tag: ['@ui', '@subgraph'] }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,7 +1,7 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
/** One representative of each widget type from the default workflow. */
type WidgetType = 'textarea' | 'number' | 'select' | 'text'

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import {
createAssetHelper,
withModels,
@@ -9,13 +9,13 @@ import {
withAsset,
withPagination,
withUploadResponse
} from '../fixtures/helpers/AssetHelper'
} from '@e2e/fixtures/helpers/AssetHelper'
import {
STABLE_CHECKPOINT,
STABLE_LORA,
STABLE_INPUT_IMAGE,
STABLE_OUTPUT
} from '../fixtures/data/assetFixtures'
} from '@e2e/fixtures/data/assetFixtures'
test.describe('AssetHelper', () => {
test.describe('operators and configuration', () => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Bottom Panel Logs', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { WorkspaceStore } from '../types/globals'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import type { WorkspaceStore } from '@e2e/types/globals'
test.describe('Browser tab title', { tag: '@smoke' }, () => {
test.describe('Beta Menu', () => {

View File

@@ -1,14 +1,14 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
import type { ComfyPage } from '../fixtures/ComfyPage'
import type { AppModeHelper } from '../fixtures/helpers/AppModeHelper'
} from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import type { AppModeHelper } from '@e2e/fixtures/helpers/AppModeHelper'
import {
builderSaveAs,
openWorkflowFromSidebar,
setupBuilder
} from '../helpers/builderTestUtils'
} from '@e2e/helpers/builderTestUtils'
const WIDGETS = ['seed', 'steps', 'cfg']

View File

@@ -1,14 +1,14 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
import type { AppModeHelper } from '../fixtures/helpers/AppModeHelper'
} from '@e2e/fixtures/ComfyPage'
import type { AppModeHelper } from '@e2e/fixtures/helpers/AppModeHelper'
import {
builderSaveAs,
openWorkflowFromSidebar,
setupBuilder
} from '../helpers/builderTestUtils'
import { fitToViewInstant } from '../helpers/fitToView'
} from '@e2e/helpers/builderTestUtils'
import { fitToViewInstant } from '@e2e/helpers/fitToView'
/**
* After a first save, open save-as again from the chevron,

View File

@@ -1,8 +1,8 @@
import type { ComfyPage } from '../fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
async function beforeChange(comfyPage: ComfyPage) {
await comfyPage.page.evaluate(() => {

View File

@@ -1,8 +1,8 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
import type { WorkspaceStore } from '../types/globals'
} from '@e2e/fixtures/ComfyPage'
import type { WorkspaceStore } from '@e2e/types/globals'
test.describe(
'Change Tracker - isLoadingGraph guard',

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { assertNodeSlotsWithinBounds } from '../fixtures/utils/slotBoundsUtil'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { assertNodeSlotsWithinBounds } from '@e2e/fixtures/utils/slotBoundsUtil'
const NODE_ID = '3'
const NODE_TITLE = 'KSampler'

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { WorkspaceStore } from '../types/globals'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import type { WorkspaceStore } from '@e2e/types/globals'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Confirm dialog text wrapping', { tag: ['@mobile'] }, () => {
test('@mobile confirm dialog buttons are visible with long unbreakable text', async ({

View File

@@ -1,8 +1,8 @@
import { expect } from '@playwright/test'
import type { PerfMeasurement } from '../fixtures/helpers/PerformanceHelper'
import type { PerfMeasurement } from '@e2e/fixtures/helpers/PerformanceHelper'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
interface ContainCandidate {
selector: string

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { DefaultGraphPositions } from '../fixtures/constants/defaultGraphPositions'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import type { Locator } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
async function verifyCustomIconSvg(iconElement: Locator) {
const svgVariable = await iconElement.evaluate((element) => {

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
async function pressKeyAndExpectRequest(
comfyPage: ComfyPage,

View File

@@ -1,263 +1,13 @@
import { expect } from '@playwright/test'
import type { Keybinding } from '../../src/platform/keybindings/types'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { DefaultGraphPositions } from '../fixtures/constants/defaultGraphPositions'
import { TestIds } from '../fixtures/selectors'
import type { Keybinding } from '@/platform/keybindings/types'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')
})
test.describe('Missing nodes in Error Overlay', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
})
test('Should show error overlay when loading a workflow with missing nodes', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
const messages = errorOverlay.getByTestId(
TestIds.dialogs.errorOverlayMessages
)
await expect(messages).toBeVisible()
await expect(messages).toHaveText(/missing.*installed/i)
})
test('Should show error overlay when loading a workflow with missing nodes in subgraphs', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes_in_subgraph')
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
const messages = errorOverlay.getByTestId(
TestIds.dialogs.errorOverlayMessages
)
await expect(messages).toBeVisible()
await expect(messages).toHaveText(/missing.*installed/i)
// Click "See Errors" to open the errors tab and verify subgraph node content
await errorOverlay
.getByTestId(TestIds.dialogs.errorOverlaySeeErrors)
.click()
await expect(errorOverlay).not.toBeVisible()
const missingNodeCard = comfyPage.page.getByTestId(
TestIds.dialogs.missingNodeCard
)
await expect(missingNodeCard).toBeVisible()
// Expand the pack group row to reveal node type names
await missingNodeCard
.getByRole('button', { name: /expand/i })
.first()
.click()
await expect(
missingNodeCard.getByText('MISSING_NODE_TYPE_IN_SUBGRAPH')
).toBeVisible()
})
test('Should show MissingNodeCard in errors tab when clicking See Errors', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
// Click "See Errors" to open the right side panel errors tab
await errorOverlay
.getByTestId(TestIds.dialogs.errorOverlaySeeErrors)
.click()
await expect(errorOverlay).not.toBeVisible()
// Verify MissingNodeCard is rendered in the errors tab
const missingNodeCard = comfyPage.page.getByTestId(
TestIds.dialogs.missingNodeCard
)
await expect(missingNodeCard).toBeVisible()
})
})
test('Does not resurface missing nodes on undo/redo', async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
const errorOverlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(errorOverlay).toBeVisible()
// Dismiss the error overlay
await errorOverlay.getByTestId(TestIds.dialogs.errorOverlayDismiss).click()
await expect(errorOverlay).not.toBeVisible()
// Make a change to the graph by moving a node
await comfyPage.canvas.click()
await comfyPage.nextFrame()
await comfyPage.page.keyboard.press('Control+a')
await comfyPage.page.mouse.move(400, 300)
await comfyPage.page.mouse.down()
await comfyPage.page.mouse.move(450, 350, { steps: 5 })
await comfyPage.page.mouse.up()
await comfyPage.nextFrame()
// Undo and redo should not resurface the error overlay
await comfyPage.keyboard.undo()
await expect(errorOverlay).not.toBeVisible({ timeout: 5000 })
await comfyPage.keyboard.redo()
await expect(errorOverlay).not.toBeVisible({ timeout: 5000 })
})
test.describe('Execution error', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
await comfyPage.setup()
})
test('Should display an error message when an execution error occurs', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('nodes/execution_error')
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
await comfyPage.nextFrame()
// Wait for the error overlay to be visible
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
})
})
test.describe('Error actions in Errors Tab', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
})
test('Should show Find on GitHub and Copy buttons in error card after execution error', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('nodes/execution_error')
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
await comfyPage.nextFrame()
// Wait for error overlay and click "See Errors"
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
await errorOverlay
.getByTestId(TestIds.dialogs.errorOverlaySeeErrors)
.click()
await expect(errorOverlay).not.toBeVisible()
// Verify Find on GitHub button is present in the error card
const findOnGithubButton = comfyPage.page.getByTestId(
TestIds.dialogs.errorCardFindOnGithub
)
await expect(findOnGithubButton).toBeVisible()
// Verify Copy button is present in the error card
const copyButton = comfyPage.page.getByTestId(TestIds.dialogs.errorCardCopy)
await expect(copyButton).toBeVisible()
})
})
test.describe('Missing models in Error Tab', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
const cleanupOk = await comfyPage.page.evaluate(async (url: string) => {
const response = await fetch(`${url}/api/devtools/cleanup_fake_model`)
return response.ok
}, comfyPage.url)
expect(cleanupOk).toBeTruthy()
})
test('Should show error overlay with missing models when workflow has missing models', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_models')
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
const messages = errorOverlay.getByTestId(
TestIds.dialogs.errorOverlayMessages
)
await expect(messages).toBeVisible()
await expect(messages).toHaveText(/required model.*missing/i)
})
test('Should show missing models from node properties', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow(
'missing/missing_models_from_node_properties'
)
const errorOverlay = comfyPage.page.getByTestId(
TestIds.dialogs.errorOverlay
)
await expect(errorOverlay).toBeVisible()
const messages = errorOverlay.getByTestId(
TestIds.dialogs.errorOverlayMessages
)
await expect(messages).toBeVisible()
await expect(messages).toHaveText(/required model.*missing/i)
})
test('Should not show missing models when widget values have changed', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow(
'missing/model_metadata_widget_mismatch'
)
await expect(
comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
).not.toBeVisible()
await expect(
comfyPage.page.getByTestId(TestIds.dialogs.errorOverlayMessages)
).not.toBeVisible()
})
})
test.describe('Settings', () => {
test('@mobile Should be visible on mobile', async ({ comfyPage }) => {
await comfyPage.page.keyboard.press('Control+,')
@@ -379,38 +129,6 @@ test.describe('Support', () => {
})
})
test.describe('Error dialog', () => {
test('Should display an error dialog when graph configure fails', async ({
comfyPage
}) => {
await comfyPage.page.evaluate(() => {
const graph = window.graph!
;(graph as { configure: () => void }).configure = () => {
throw new Error('Error on configure!')
}
})
await comfyPage.workflow.loadWorkflow('default')
const errorDialog = comfyPage.page.locator('.comfy-error-report')
await expect(errorDialog).toBeVisible()
})
test('Should display an error dialog when prompt execution fails', async ({
comfyPage
}) => {
await comfyPage.page.evaluate(async () => {
const app = window.app!
app.api.queuePrompt = () => {
throw new Error('Error on queuePrompt!')
}
await app.queuePrompt(0)
})
const errorDialog = comfyPage.page.locator('.comfy-error-report')
await expect(errorDialog).toBeVisible()
})
})
test.describe('Signin dialog', () => {
test('Paste content to signin dialog should not paste node on canvas', async ({
comfyPage

View File

@@ -1,7 +1,7 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Queue Clear History Dialog', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../../fixtures/ComfyPage'
import { SignInDialog } from '../../fixtures/components/SignInDialog'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { SignInDialog } from '@e2e/fixtures/components/SignInDialog'
test.describe('Sign In dialog', { tag: '@ui' }, () => {
let dialog: SignInDialog

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -0,0 +1,139 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
import {
interceptClipboardWrite,
getClipboardText
} from '@e2e/helpers/clipboardSpy'
async function triggerConfigureError(
comfyPage: ComfyPage,
message = 'Error on configure!'
) {
await comfyPage.page.evaluate((msg: string) => {
const graph = window.graph!
;(graph as { configure: () => void }).configure = () => {
throw new Error(msg)
}
}, message)
await comfyPage.workflow.loadWorkflow('default')
return comfyPage.page.getByTestId(TestIds.dialogs.errorDialog)
}
async function waitForPopupNavigation(page: Page, action: () => Promise<void>) {
const popupPromise = page.waitForEvent('popup')
await action()
const popup = await popupPromise
await popup.waitForLoadState()
return popup
}
test.describe('Error dialog', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')
})
test('Should display an error dialog when graph configure fails', async ({
comfyPage
}) => {
const errorDialog = await triggerConfigureError(comfyPage)
await expect(errorDialog).toBeVisible()
})
test('Should display an error dialog when prompt execution fails', async ({
comfyPage
}) => {
await comfyPage.page.evaluate(async () => {
const app = window.app!
app.api.queuePrompt = () => {
throw new Error('Error on queuePrompt!')
}
await app.queuePrompt(0)
})
const errorDialog = comfyPage.page.getByTestId(TestIds.dialogs.errorDialog)
await expect(errorDialog).toBeVisible()
})
test('Should display error message body', async ({ comfyPage }) => {
const errorDialog = await triggerConfigureError(
comfyPage,
'Test error message body'
)
await expect(errorDialog).toBeVisible()
await expect(errorDialog).toContainText('Test error message body')
})
test('Should show report section when "Show Report" is clicked', async ({
comfyPage
}) => {
const errorDialog = await triggerConfigureError(comfyPage)
await expect(errorDialog).toBeVisible()
await expect(errorDialog.locator('pre')).not.toBeVisible()
await errorDialog.getByTestId(TestIds.dialogs.errorDialogShowReport).click()
const reportPre = errorDialog.locator('pre')
await expect(reportPre).toBeVisible()
await expect(reportPre).toHaveText(/\S/)
await expect(
errorDialog.getByTestId(TestIds.dialogs.errorDialogShowReport)
).not.toBeVisible()
})
test('Should copy report to clipboard when "Copy to Clipboard" is clicked', async ({
comfyPage
}) => {
const errorDialog = await triggerConfigureError(comfyPage)
await expect(errorDialog).toBeVisible()
await errorDialog.getByTestId(TestIds.dialogs.errorDialogShowReport).click()
await expect(errorDialog.locator('pre')).toBeVisible()
await interceptClipboardWrite(comfyPage.page)
await errorDialog.getByTestId(TestIds.dialogs.errorDialogCopyReport).click()
const reportText = await errorDialog.locator('pre').textContent()
const copiedText = await getClipboardText(comfyPage.page)
expect(copiedText).toBe(reportText)
})
test('Should open GitHub issues search when "Find Issues" is clicked', async ({
comfyPage
}) => {
const errorDialog = await triggerConfigureError(comfyPage)
await expect(errorDialog).toBeVisible()
const popup = await waitForPopupNavigation(comfyPage.page, () =>
errorDialog.getByTestId(TestIds.dialogs.errorDialogFindIssues).click()
)
const url = new URL(popup.url())
expect(url.hostname).toBe('github.com')
expect(url.pathname).toContain('/issues')
await popup.close()
})
test('Should open contact support when "Help Fix This" is clicked', async ({
comfyPage
}) => {
const errorDialog = await triggerConfigureError(comfyPage)
await expect(errorDialog).toBeVisible()
const popup = await waitForPopupNavigation(comfyPage.page, () =>
errorDialog.getByTestId(TestIds.dialogs.errorDialogContactSupport).click()
)
const url = new URL(popup.url())
expect(url.hostname).toBe('support.comfy.org')
await popup.close()
})
})

View File

@@ -0,0 +1,195 @@
import type { Page } from '@playwright/test'
import {
comfyPageFixture as test,
comfyExpect as expect
} from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.describe('Error overlay', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
})
function getOverlay(page: Page) {
return page.getByTestId(TestIds.dialogs.errorOverlay)
}
function getSeeErrorsButton(page: Page) {
return getOverlay(page).getByTestId(TestIds.dialogs.errorOverlaySeeErrors)
}
test.describe('Labels', () => {
test('Should display singular error count label for single error', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
await expect(getOverlay(comfyPage.page)).toBeVisible()
await expect(getOverlay(comfyPage.page)).toContainText(/1 ERROR/i)
})
test('Should display "Show missing nodes" button for missing node errors', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
await expect(getOverlay(comfyPage.page)).toBeVisible()
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
/Show missing nodes/i
)
})
test('Should display "Show missing models" button for missing model errors', async ({
comfyPage
}) => {
const cleanupOk = await comfyPage.page.evaluate(async (url: string) => {
const response = await fetch(`${url}/api/devtools/cleanup_fake_model`)
return response.ok
}, comfyPage.url)
expect(cleanupOk).toBeTruthy()
await comfyPage.workflow.loadWorkflow('missing/missing_models')
await expect(getOverlay(comfyPage.page)).toBeVisible()
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
/Show missing models/i
)
})
test('Should display "Show missing inputs" button for missing media errors', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_media_single')
await expect(getOverlay(comfyPage.page)).toBeVisible()
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
/Show missing inputs/i
)
})
test('Should display generic "See Errors" button for multiple error types', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes_and_media')
await expect(getOverlay(comfyPage.page)).toBeVisible()
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
/See Errors/i
)
})
})
test.describe('Persistence', () => {
test('Does not resurface missing nodes on undo/redo', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
const errorOverlay = getOverlay(comfyPage.page)
await expect(errorOverlay).toBeVisible()
await errorOverlay
.getByTestId(TestIds.dialogs.errorOverlayDismiss)
.click()
await expect(errorOverlay).not.toBeVisible()
await comfyPage.canvas.click()
await comfyPage.nextFrame()
await comfyPage.page.keyboard.press('Control+a')
await comfyPage.page.mouse.move(400, 300)
await comfyPage.page.mouse.down()
await comfyPage.page.mouse.move(450, 350, { steps: 5 })
await comfyPage.page.mouse.up()
await comfyPage.nextFrame()
await comfyPage.keyboard.undo()
await expect(errorOverlay).not.toBeVisible({ timeout: 5000 })
await comfyPage.keyboard.redo()
await expect(errorOverlay).not.toBeVisible({ timeout: 5000 })
})
})
test.describe('See Errors flow', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setup()
})
async function triggerExecutionError(comfyPage: {
canvasOps: { disconnectEdge: () => Promise<void> }
page: Page
command: { executeCommand: (cmd: string) => Promise<void> }
}) {
await comfyPage.canvasOps.disconnectEdge()
await comfyPage.page.keyboard.press('Escape')
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
}
test('Error overlay appears on execution error', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
await expect(getOverlay(comfyPage.page)).toBeVisible()
})
test('Error overlay shows error message', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = getOverlay(comfyPage.page)
await expect(overlay).toBeVisible()
await expect(overlay).toHaveText(/\S/)
})
test('"See Errors" opens right side panel', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = getOverlay(comfyPage.page)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
await expect(comfyPage.page.getByTestId('properties-panel')).toBeVisible()
})
test('"See Errors" dismisses the overlay', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = getOverlay(comfyPage.page)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
await expect(overlay).not.toBeVisible()
})
test('"Dismiss" closes overlay without opening panel', async ({
comfyPage
}) => {
await triggerExecutionError(comfyPage)
const overlay = getOverlay(comfyPage.page)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlayDismiss).click()
await expect(overlay).not.toBeVisible()
await expect(
comfyPage.page.getByTestId('properties-panel')
).not.toBeVisible()
})
test('Close button (X) dismisses overlay', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = getOverlay(comfyPage.page)
await expect(overlay).toBeVisible()
await overlay.getByRole('button', { name: /close/i }).click()
await expect(overlay).not.toBeVisible()
})
})
})

View File

@@ -1,93 +0,0 @@
import type { Page } from '@playwright/test'
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
test.describe('Error overlay See Errors flow', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.settings.setSetting(
'Comfy.RightSidePanel.ShowErrorsTab',
true
)
await comfyPage.setup()
})
async function triggerExecutionError(comfyPage: {
canvasOps: { disconnectEdge: () => Promise<void> }
page: Page
command: { executeCommand: (cmd: string) => Promise<void> }
}) {
await comfyPage.canvasOps.disconnectEdge()
await comfyPage.page.keyboard.press('Escape')
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
}
test('Error overlay appears on execution error', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
await expect(
comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
).toBeVisible()
})
test('Error overlay shows error message', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(overlay).toBeVisible()
await expect(overlay).toHaveText(/\S/)
})
test('"See Errors" opens right side panel', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
await expect(comfyPage.page.getByTestId('properties-panel')).toBeVisible()
})
test('"See Errors" dismisses the overlay', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
await expect(overlay).not.toBeVisible()
})
test('"Dismiss" closes overlay without opening panel', async ({
comfyPage
}) => {
await triggerExecutionError(comfyPage)
const overlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(overlay).toBeVisible()
await overlay.getByTestId(TestIds.dialogs.errorOverlayDismiss).click()
await expect(overlay).not.toBeVisible()
await expect(
comfyPage.page.getByTestId('properties-panel')
).not.toBeVisible()
})
test('Close button (X) dismisses overlay', async ({ comfyPage }) => {
await triggerExecutionError(comfyPage)
const overlay = comfyPage.page.getByTestId(TestIds.dialogs.errorOverlay)
await expect(overlay).toBeVisible()
await overlay.getByRole('button', { name: /close/i }).click()
await expect(overlay).not.toBeVisible()
})
})

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,8 +1,8 @@
import { expect } from '@playwright/test'
import type { Settings } from '../../src/schemas/apiSchema'
import type { SettingParams } from '../../src/platform/settings/types'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { Settings } from '@/schemas/apiSchema'
import type { SettingParams } from '@/platform/settings/types'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
/**
* Type helper for test settings with arbitrary IDs.

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Focus Mode', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Group Copy Paste', { tag: ['@canvas'] }, () => {
test.afterEach(async ({ comfyPage }) => {

View File

@@ -2,12 +2,12 @@ import { expect } from '@playwright/test'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { NodeLibrarySidebarTab } from '../fixtures/components/SidebarTab'
import { TestIds } from '../fixtures/selectors'
import { DefaultGraphPositions } from '../fixtures/constants/defaultGraphPositions'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import type { NodeLibrarySidebarTab } from '@e2e/fixtures/components/SidebarTab'
import { TestIds } from '@e2e/fixtures/selectors'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
/**
* Returns the client-space position of a group's title bar (for clicking).

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Image Compare', () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe(
'Image paste priority over stale node metadata',

View File

@@ -5,12 +5,12 @@ import type { Position } from '@vueuse/core'
import {
comfyPageFixture as test,
testComfySnapToGridGridSize
} from '../fixtures/ComfyPage'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { DefaultGraphPositions } from '../fixtures/constants/defaultGraphPositions'
import { TestIds } from '../fixtures/selectors'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
import type { WorkspaceStore } from '../types/globals'
} from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { DefaultGraphPositions } from '@e2e/fixtures/constants/defaultGraphPositions'
import { TestIds } from '@e2e/fixtures/selectors'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
import type { WorkspaceStore } from '@e2e/types/globals'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -3,7 +3,7 @@ import type { Locator } from '@playwright/test'
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Job History Actions', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -5,7 +5,7 @@ import path from 'node:path'
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
const TEST_PRESET = {
name: 'test-preset',

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import {
comfyPageFixture as test,
comfyExpect as expect
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Linear Mode', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Mask Editor', () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.describe('Menu', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.describe('Minimap', { tag: '@canvas' }, () => {
test.beforeEach(async ({ comfyPage }) => {

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.describe(
'Mobile Baseline Snapshots',

View File

@@ -1,8 +1,8 @@
import { expect } from '@playwright/test'
import type { ComfyApp } from '../../src/scripts/app'
import { NodeBadgeMode } from '../../src/types/nodeSource'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { ComfyApp } from '@/scripts/app'
import { NodeBadgeMode } from '@/types/nodeSource'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { TestIds } from '../fixtures/selectors'
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')

View File

@@ -1,7 +1,7 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
type ComfyPage = Parameters<Parameters<typeof test>[2]>[0]['comfyPage']

View File

@@ -1,11 +1,11 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { fitToViewInstant } from '../helpers/fitToView'
import type { WorkspaceStore } from '../types/globals'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
} from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { fitToViewInstant } from '@e2e/helpers/fitToView'
import type { WorkspaceStore } from '@e2e/types/globals'
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
// TODO: there might be a better solution for this
// Helper function to pan canvas and select node

View File

@@ -1,7 +1,7 @@
import {
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'
} from '@e2e/fixtures/ComfyPage'
test.describe('Node Library Essentials Tab', { tag: '@ui' }, () => {
test.beforeEach(async ({ comfyPage }) => {

Some files were not shown because too many files have changed in this diff Show More