mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 13:59:28 +00:00
Merge branch 'main' into glary/replace-delay-with-retrying-assertions
This commit is contained in:
39
browser_tests/assets/inputs/dynamic_combo.json
Normal file
39
browser_tests/assets/inputs/dynamic_combo.json
Normal 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
|
||||
}
|
||||
85
browser_tests/assets/missing/missing_models_with_nodes.json
Normal file
85
browser_tests/assets/missing/missing_models_with_nodes.json
Normal 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
|
||||
}
|
||||
72
browser_tests/assets/missing/missing_nodes_and_media.json
Normal file
72
browser_tests/assets/missing/missing_nodes_and_media.json
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"]')
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
generateModels,
|
||||
generateInputFiles,
|
||||
generateOutputAssets
|
||||
} from '../data/assetFixtures'
|
||||
} from '@e2e/fixtures/data/assetFixtures'
|
||||
|
||||
export interface MutationRecord {
|
||||
endpoint: string
|
||||
|
||||
@@ -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(?:\?.*)?$/
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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\/([^?]+)/
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { config as dotenvConfig } from 'dotenv'
|
||||
|
||||
import { backupPath } from './utils/backupUtils'
|
||||
import { backupPath } from '@e2e/utils/backupUtils'
|
||||
|
||||
dotenvConfig()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
19
browser_tests/helpers/clipboardSpy.ts
Normal file
19
browser_tests/helpers/clipboardSpy.ts
Normal 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
|
||||
)) ?? ''
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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(', ')}`)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ComfyPage } from '../fixtures/ComfyPage'
|
||||
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
|
||||
|
||||
export type PromotedWidgetEntry = [string, string]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
105
browser_tests/tests/appModePruning.spec.ts
Normal file
105
browser_tests/tests/appModePruning.spec.ts
Normal 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)
|
||||
})
|
||||
})
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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']
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 ({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
139
browser_tests/tests/errorDialog.spec.ts
Normal file
139
browser_tests/tests/errorDialog.spec.ts
Normal 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()
|
||||
})
|
||||
})
|
||||
195
browser_tests/tests/errorOverlay.spec.ts
Normal file
195
browser_tests/tests/errorOverlay.spec.ts
Normal 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()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
@@ -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')
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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']
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user