Compare commits
224 Commits
create_fol
...
export-vue
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84a675de88 | ||
|
|
e45f5bdebb | ||
|
|
c270e7734a | ||
|
|
8d7a21e008 | ||
|
|
29e63baca6 | ||
|
|
b22713daf0 | ||
|
|
c8b8953e0a | ||
|
|
731ce8599d | ||
|
|
ec8e55c1c1 | ||
|
|
04d38f2538 | ||
|
|
1c41db75f8 | ||
|
|
c7a7397000 | ||
|
|
e660e1d678 | ||
|
|
fb19752389 | ||
|
|
d098d6ae4e | ||
|
|
e4a5355f58 | ||
|
|
42c004d41d | ||
|
|
009c389607 | ||
|
|
b449dbd26b | ||
|
|
67835edfca | ||
|
|
60c0ce228a | ||
|
|
1990f25638 | ||
|
|
30c473db77 | ||
|
|
2371288fed | ||
|
|
2337fe6f8e | ||
|
|
25e6386b2a | ||
|
|
a03841cb1a | ||
|
|
dc5d7ea1be | ||
|
|
59e20964a0 | ||
|
|
8f00d8ca6a | ||
|
|
05e0036898 | ||
|
|
9e7690405a | ||
|
|
d687ea2cde | ||
|
|
c801a0c854 | ||
|
|
615c183059 | ||
|
|
27c8389b9f | ||
|
|
261f671ef0 | ||
|
|
22ae30132c | ||
|
|
7d3bf372b0 | ||
|
|
cd35373c25 | ||
|
|
a500a96c4a | ||
|
|
dc9ea44f3a | ||
|
|
2dc33b1eb9 | ||
|
|
ed8f9a5a4f | ||
|
|
6e72e1924e | ||
|
|
f7854a4e0b | ||
|
|
05023b7889 | ||
|
|
609496957b | ||
|
|
a879f413bb | ||
|
|
21d679a662 | ||
|
|
34f9603961 | ||
|
|
cf27a896f3 | ||
|
|
e9a98161ca | ||
|
|
fa132e4106 | ||
|
|
a489c19b07 | ||
|
|
46af2f03f3 | ||
|
|
3a1c95fb10 | ||
|
|
7a6f0e210e | ||
|
|
ac3bd7a848 | ||
|
|
77b5e487cf | ||
|
|
a7a8459e18 | ||
|
|
65c9c264c6 | ||
|
|
8ea070df12 | ||
|
|
2c02d4ebb3 | ||
|
|
a2b3048b94 | ||
|
|
549a42716f | ||
|
|
fa75614dc3 | ||
|
|
ac53296b2e | ||
|
|
6eb2b76621 | ||
|
|
9dd3b9fff5 | ||
|
|
785cad70ba | ||
|
|
026f076b8a | ||
|
|
65f1561ec6 | ||
|
|
bb094cf0ae | ||
|
|
ec684ee6b8 | ||
|
|
3978613f14 | ||
|
|
0a40e07f7e | ||
|
|
577af51ff8 | ||
|
|
df7c7383e2 | ||
|
|
1279f30f5a | ||
|
|
9ab4b549c0 | ||
|
|
10de4e5445 | ||
|
|
30420f2c0a | ||
|
|
39c3a57c11 | ||
|
|
6d09b7165f | ||
|
|
8fc6840434 | ||
|
|
db575425fe | ||
|
|
ccb71bf1a3 | ||
|
|
733d71aaac | ||
|
|
e059b9b82f | ||
|
|
cfaf769a65 | ||
|
|
b80e0e1a3c | ||
|
|
7b7d9905a7 | ||
|
|
594fc5945c | ||
|
|
e5abf765bd | ||
|
|
712c127bb5 | ||
|
|
854501ef27 | ||
|
|
aea4493b4d | ||
|
|
df47226fd4 | ||
|
|
f26f5f25bb | ||
|
|
284902cabe | ||
|
|
58dec5ea42 | ||
|
|
7e76665a22 | ||
|
|
cb06d96930 | ||
|
|
b01ddb6aff | ||
|
|
10bed33383 | ||
|
|
a57e60d60a | ||
|
|
8c789bd05d | ||
|
|
28def833f9 | ||
|
|
fcc22f06ac | ||
|
|
3922a5882b | ||
|
|
4a40e83b98 | ||
|
|
21e0caa1b1 | ||
|
|
04af8cda4d | ||
|
|
504b717575 | ||
|
|
62fdcd4949 | ||
|
|
cb7adaef9b | ||
|
|
6aad5222ab | ||
|
|
690326c374 | ||
|
|
25ce267b2e | ||
|
|
78e3a20773 | ||
|
|
56dbcbbd22 | ||
|
|
4bfc8e9e33 | ||
|
|
6e72207927 | ||
|
|
71968ae133 | ||
|
|
4702cd18ce | ||
|
|
00d281c7fa | ||
|
|
3e25e08b10 | ||
|
|
1d66d6d7d3 | ||
|
|
cae5bbe86f | ||
|
|
4d35d937cf | ||
|
|
60afa5cf6c | ||
|
|
a1a33c8c9b | ||
|
|
9988fb8f1e | ||
|
|
0518b170d3 | ||
|
|
562cd7ea70 | ||
|
|
d3c64d404b | ||
|
|
24dcaa7f72 | ||
|
|
6c18781663 | ||
|
|
b6988e8d5c | ||
|
|
ae64721555 | ||
|
|
abe65e58a0 | ||
|
|
a1cfb68116 | ||
|
|
5bee36a73e | ||
|
|
a4b0f5ab5e | ||
|
|
f8a2c90138 | ||
|
|
27c252f74a | ||
|
|
7e26cffb26 | ||
|
|
cb8354bfce | ||
|
|
d5ebd7b7cb | ||
|
|
845d045991 | ||
|
|
c3154fe297 | ||
|
|
f90d61fad5 | ||
|
|
17834459a1 | ||
|
|
564c4d557f | ||
|
|
f852639758 | ||
|
|
eae538b08e | ||
|
|
d23108433e | ||
|
|
e6e7449ece | ||
|
|
22a1200bdf | ||
|
|
ee20b63bc1 | ||
|
|
0752e8b986 | ||
|
|
b234a68cf8 | ||
|
|
0863fda6a4 | ||
|
|
8530406c3e | ||
|
|
f7bfb6ec57 | ||
|
|
830933e78f | ||
|
|
65693ed2be | ||
|
|
ed153dccd9 | ||
|
|
fc7ed1bf09 | ||
|
|
4dad89369a | ||
|
|
5b730517a3 | ||
|
|
af0bf05883 | ||
|
|
d9e62ff860 | ||
|
|
d9ae6cb395 | ||
|
|
b162963593 | ||
|
|
c34cc301f1 | ||
|
|
afdb94f12f | ||
|
|
cc8dc3dbfb | ||
|
|
42d99fc37e | ||
|
|
1f03984d12 | ||
|
|
d49815fcb4 | ||
|
|
4899a1d8f6 | ||
|
|
71444d8c69 | ||
|
|
867ed4c1d7 | ||
|
|
0c6957bfd8 | ||
|
|
fffce30e91 | ||
|
|
c554138887 | ||
|
|
5bbceea76c | ||
|
|
0f0601100f | ||
|
|
ff59245a7f | ||
|
|
c5af11d1ea | ||
|
|
bc3e2e1597 | ||
|
|
e2a8456ff0 | ||
|
|
361c5ba930 | ||
|
|
bae47b80b3 | ||
|
|
a049e9ae2d | ||
|
|
44edec7ad2 | ||
|
|
db43f587a6 | ||
|
|
8997ff4b2a | ||
|
|
91a8591249 | ||
|
|
ef74d7cb01 | ||
|
|
8ab2334270 | ||
|
|
59dbcc5261 | ||
|
|
06488cc811 | ||
|
|
5a12bf33f3 | ||
|
|
96ff8a7785 | ||
|
|
a85a1bf794 | ||
|
|
52bad3d0d1 | ||
|
|
e8997a7653 | ||
|
|
0a6d3c0231 | ||
|
|
2db29fc2af | ||
|
|
329bdff677 | ||
|
|
906eb750ad | ||
|
|
1a120adaea | ||
|
|
26a7ebdd77 | ||
|
|
da415e9d80 | ||
|
|
384b3f3218 | ||
|
|
65cf157958 | ||
|
|
7af003fcab | ||
|
|
7e66e99c3a | ||
|
|
9e9459815d | ||
|
|
57b93a0007 | ||
|
|
8923ec51fd |
@@ -1,4 +1,5 @@
|
||||
# Local development playwright target
|
||||
# Note: Don't add a trailing / after the port
|
||||
PLAYWRIGHT_TEST_URL=http://localhost:5173
|
||||
# PLAYWRIGHT_TEST_URL=http://localhost:8188
|
||||
|
||||
|
||||
2
.github/workflows/test-ui.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
with:
|
||||
repository: 'Comfy-Org/ComfyUI_devtools'
|
||||
path: 'ComfyUI/custom_nodes/ComfyUI_devtools'
|
||||
ref: '080e6d4af809a46852d1c4b7ed85f06e8a3a72be'
|
||||
ref: '49c8220be49120dbaff85f32813d854d6dff2d05'
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
2
.gitignore
vendored
@@ -38,7 +38,7 @@ tests-ui/workflows/examples
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
browser_tests/*/*-win32.png
|
||||
browser_tests/**/*-win32.png
|
||||
|
||||
.env
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ module.exports = defineConfig({
|
||||
entry: 'src/locales/en',
|
||||
entryLocale: 'en',
|
||||
output: 'src/locales',
|
||||
outputLocales: ['zh', 'ru', 'ja', 'ko', 'fr'],
|
||||
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, controlnet, lora.
|
||||
outputLocales: ['zh', 'ru', 'ja', 'ko', 'fr', 'es'],
|
||||
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora.
|
||||
'latent' is the short form of 'latent space'.
|
||||
'mask' is in the context of image processing.
|
||||
`
|
||||
|
||||
@@ -9,15 +9,26 @@ If `TEST_COMFYUI_DIR` in `.env` isn't set to your `(Comfy Path)/ComfyUI` directo
|
||||
|
||||
## Setup
|
||||
|
||||
Clone <https://github.com/Comfy-Org/ComfyUI_devtools> to your `custom_nodes` directory.
|
||||
ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing.
|
||||
### ComfyUI devtools
|
||||
Clone <https://github.com/Comfy-Org/ComfyUI_devtools> to your `custom_nodes` directory.
|
||||
_ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing._
|
||||
|
||||
### Node.js & Playwright Prerequisites
|
||||
Ensure you have Node.js v20 or later installed. Then, set up the Chromium test driver:
|
||||
|
||||
```bash
|
||||
npx playwright install chromium --with-deps
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
Ensure the environment variables in `.env` are set correctly according to your setup.
|
||||
|
||||
The `.env` file will not exist until you create it yourself.
|
||||
|
||||
A template with helpful information can be found in `.env_example`.
|
||||
|
||||
### Multiple Tests
|
||||
If you are running Playwright tests in parallel or running the same test multiple times, the flag `--multi-user` must be added to the main ComfyUI process.
|
||||
|
||||
## Running Tests
|
||||
|
||||
There are two ways to run the tests:
|
||||
@@ -34,8 +45,6 @@ There are two ways to run the tests:
|
||||
```
|
||||
This opens a user interface where you can select specific tests to run and inspect the test execution timeline.
|
||||
|
||||
To run the same test multiple times in Playwright's UI mode, you must launch the main ComfyUI process with the `--multi-user` flag.
|
||||
|
||||

|
||||
|
||||
## Screenshot Expectations
|
||||
|
||||
126
browser_tests/assets/bad_link.json
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"id": "51b9b184-770d-40ac-a478-8cc31667ff23",
|
||||
"revision": 0,
|
||||
"last_node_id": 5,
|
||||
"last_link_id": 3,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 4,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
867.4669799804688,
|
||||
347.22369384765625
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "steps",
|
||||
"type": "INT",
|
||||
"widget": {
|
||||
"name": "steps"
|
||||
},
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
"randomize",
|
||||
20,
|
||||
8,
|
||||
"euler",
|
||||
"normal",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "PrimitiveInt",
|
||||
"pos": [
|
||||
443.0852355957031,
|
||||
441.131591796875
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "INT",
|
||||
"type": "INT",
|
||||
"links": [
|
||||
3
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PrimitiveInt"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
"randomize"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
5,
|
||||
"INT"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.9487171000000016,
|
||||
"offset": [
|
||||
-325.57196748514497,
|
||||
-168.13150517966463
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
53
browser_tests/assets/default_input.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "9bcb9451-8319-492a-88d4-fb711d8c3d25",
|
||||
"revision": 0,
|
||||
"last_node_id": 6,
|
||||
"last_link_id": 0,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 6,
|
||||
"type": "DevToolsNodeWithDefaultInput",
|
||||
"pos": [
|
||||
8.39722728729248,
|
||||
29.727279663085938
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "float_input",
|
||||
"shape": 7,
|
||||
"type": "FLOAT",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "DevToolsNodeWithDefaultInput"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
1,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 2.1600300525920346,
|
||||
"offset": [
|
||||
63.071794466403446,
|
||||
75.18055335968394
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
82
browser_tests/assets/dynamically_added_input.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"last_node_id": 9,
|
||||
"last_link_id": 13,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 3,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
0,
|
||||
30
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 262
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": null
|
||||
} ,
|
||||
{
|
||||
"name": "dynamic_input",
|
||||
"type": "FLOAT",
|
||||
"link": null,
|
||||
"_meta": "Dynamically added input via frontend JS logic"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
156680208700286,
|
||||
"randomize",
|
||||
20,
|
||||
8,
|
||||
"euler",
|
||||
"normal",
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
74
browser_tests/assets/input_order_swap.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"id": "51b9b184-770d-40ac-a478-8cc31667ff23",
|
||||
"revision": 0,
|
||||
"last_node_id": 2,
|
||||
"last_link_id": 1,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [904, 466],
|
||||
"size": [400, 200],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "text"
|
||||
},
|
||||
"link": 1
|
||||
},
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [""]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PrimitiveString",
|
||||
"pos": [556.8589477539062, 472.94342041015625],
|
||||
"size": [315, 58],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [1]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PrimitiveString"
|
||||
},
|
||||
"widgets_values": ["foo"]
|
||||
}
|
||||
],
|
||||
"links": [[1, 2, 0, 1, 0, "STRING"]],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.7715610000000013,
|
||||
"offset": [-388.521484375, -162.31336975097656]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -51,7 +51,10 @@
|
||||
0.85,
|
||||
false,
|
||||
false,
|
||||
""
|
||||
"",
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
104
browser_tests/assets/primitive/static_primitive_unconnected.json
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"last_node_id": 2,
|
||||
"last_link_id": 1,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 2,
|
||||
"type": "KSampler",
|
||||
"pos": {
|
||||
"0": 304.3653259277344,
|
||||
"1": 42.15586471557617
|
||||
},
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
0,
|
||||
"randomize",
|
||||
20,
|
||||
8,
|
||||
"euler",
|
||||
"normal",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "PrimitiveInt",
|
||||
"pos": {
|
||||
"0": 14,
|
||||
"1": 43
|
||||
},
|
||||
"size": [
|
||||
203.1999969482422,
|
||||
40.368401303242536
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Int"
|
||||
},
|
||||
"widgets_values": [10]
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
BIN
browser_tests/assets/workflow.glb
Normal file
@@ -214,6 +214,10 @@ export class ComfyPage {
|
||||
`Failed to setup workflows directory: ${await resp.text()}`
|
||||
)
|
||||
}
|
||||
|
||||
await this.page.evaluate(async () => {
|
||||
await window['app'].extensionManager.workflow.syncWorkflows()
|
||||
})
|
||||
}
|
||||
|
||||
async setupUser(username: string) {
|
||||
@@ -408,7 +412,7 @@ export class ComfyPage {
|
||||
}
|
||||
|
||||
async getVisibleToastCount() {
|
||||
return await this.page.locator('.p-toast:visible').count()
|
||||
return await this.page.locator('.p-toast-message:visible').count()
|
||||
}
|
||||
|
||||
async clickTextEncodeNode1() {
|
||||
@@ -459,7 +463,14 @@ export class ComfyPage {
|
||||
await this.nextFrame()
|
||||
}
|
||||
|
||||
async dragAndDropFile(fileName: string) {
|
||||
async dragAndDropFile(
|
||||
fileName: string,
|
||||
options: {
|
||||
dropPosition?: Position
|
||||
} = {}
|
||||
) {
|
||||
const { dropPosition = { x: 100, y: 100 } } = options
|
||||
|
||||
const filePath = this.assetPath(fileName)
|
||||
|
||||
// Read the file content
|
||||
@@ -471,38 +482,63 @@ export class ComfyPage {
|
||||
if (fileName.endsWith('.webp')) return 'image/webp'
|
||||
if (fileName.endsWith('.webm')) return 'video/webm'
|
||||
if (fileName.endsWith('.json')) return 'application/json'
|
||||
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
|
||||
return 'application/octet-stream'
|
||||
}
|
||||
|
||||
const fileType = getFileType(fileName)
|
||||
|
||||
await this.page.evaluate(
|
||||
async ({ buffer, fileName, fileType }) => {
|
||||
async ({ buffer, fileName, fileType, dropPosition }) => {
|
||||
const file = new File([new Uint8Array(buffer)], fileName, {
|
||||
type: fileType
|
||||
})
|
||||
const dataTransfer = new DataTransfer()
|
||||
dataTransfer.items.add(file)
|
||||
|
||||
const dropEvent = new DragEvent('drop', {
|
||||
const targetElement = document.elementFromPoint(
|
||||
dropPosition.x,
|
||||
dropPosition.y
|
||||
)
|
||||
|
||||
if (!targetElement) {
|
||||
console.error('No element found at drop position:', dropPosition)
|
||||
return { success: false, error: 'No element at position' }
|
||||
}
|
||||
|
||||
const eventOptions = {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
dataTransfer
|
||||
})
|
||||
dataTransfer,
|
||||
clientX: dropPosition.x,
|
||||
clientY: dropPosition.y
|
||||
}
|
||||
|
||||
const dragOverEvent = new DragEvent('dragover', eventOptions)
|
||||
const dropEvent = new DragEvent('drop', eventOptions)
|
||||
|
||||
Object.defineProperty(dropEvent, 'preventDefault', {
|
||||
value: () => {},
|
||||
writable: false
|
||||
})
|
||||
|
||||
Object.defineProperty(dropEvent, 'stopPropagation', {
|
||||
value: () => {},
|
||||
writable: false
|
||||
})
|
||||
|
||||
document.dispatchEvent(dropEvent)
|
||||
targetElement.dispatchEvent(dragOverEvent)
|
||||
targetElement.dispatchEvent(dropEvent)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
targetInfo: {
|
||||
tagName: targetElement.tagName,
|
||||
id: targetElement.id,
|
||||
classList: Array.from(targetElement.classList)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ buffer: [...new Uint8Array(buffer)], fileName, fileType }
|
||||
{ buffer: [...new Uint8Array(buffer)], fileName, fileType, dropPosition }
|
||||
)
|
||||
|
||||
await this.nextFrame()
|
||||
@@ -553,11 +589,20 @@ export class ComfyPage {
|
||||
await this.dragAndDrop(this.clipTextEncodeNode1InputSlot, this.emptySpace)
|
||||
}
|
||||
|
||||
async connectEdge() {
|
||||
await this.dragAndDrop(
|
||||
this.loadCheckpointNodeClipOutputSlot,
|
||||
this.clipTextEncodeNode1InputSlot
|
||||
)
|
||||
async connectEdge(
|
||||
options: {
|
||||
reverse?: boolean
|
||||
} = {}
|
||||
) {
|
||||
const { reverse = false } = options
|
||||
const start = reverse
|
||||
? this.clipTextEncodeNode1InputSlot
|
||||
: this.loadCheckpointNodeClipOutputSlot
|
||||
const end = reverse
|
||||
? this.loadCheckpointNodeClipOutputSlot
|
||||
: this.clipTextEncodeNode1InputSlot
|
||||
|
||||
await this.dragAndDrop(start, end)
|
||||
}
|
||||
|
||||
async adjustWidgetValue() {
|
||||
|
||||
@@ -81,7 +81,7 @@ export class NodeWidgetReference {
|
||||
if (!widget) throw new Error(`Widget ${index} not found.`)
|
||||
|
||||
const [x, y, w, h] = node.getBounding()
|
||||
return window['app'].canvas.ds.convertOffsetToCanvas([
|
||||
return window['app'].canvasPosToClientPos([
|
||||
x + w / 2,
|
||||
y + window['LiteGraph']['NODE_TITLE_HEIGHT'] + widget.last_y + 1
|
||||
])
|
||||
@@ -94,6 +94,36 @@ export class NodeWidgetReference {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The position of the widget's associated socket
|
||||
*/
|
||||
async getSocketPosition(): Promise<Position> {
|
||||
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
|
||||
([id, index]) => {
|
||||
const node = window['app'].graph.getNodeById(id)
|
||||
if (!node) throw new Error(`Node ${id} not found.`)
|
||||
const widget = node.widgets[index]
|
||||
if (!widget) throw new Error(`Widget ${index} not found.`)
|
||||
|
||||
const slot = node.inputs.find(
|
||||
(slot) => slot.widget?.name === widget.name
|
||||
)
|
||||
if (!slot) throw new Error(`Socket ${widget.name} not found.`)
|
||||
|
||||
const [x, y] = node.getBounding()
|
||||
return window['app'].canvasPosToClientPos([
|
||||
x + slot.pos[0],
|
||||
y + slot.pos[1] + window['LiteGraph']['NODE_TITLE_HEIGHT']
|
||||
])
|
||||
},
|
||||
[this.node.id, this.index] as const
|
||||
)
|
||||
return {
|
||||
x: pos[0],
|
||||
y: pos[1]
|
||||
}
|
||||
}
|
||||
|
||||
async click() {
|
||||
await this.node.comfyPage.canvas.click({
|
||||
position: await this.getPosition()
|
||||
@@ -115,8 +145,20 @@ export class NodeWidgetReference {
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async getValue() {
|
||||
return await this.node.comfyPage.page.evaluate(
|
||||
([id, index]) => {
|
||||
const node = window['app'].graph.getNodeById(id)
|
||||
if (!node) throw new Error(`Node ${id} not found.`)
|
||||
const widget = node.widgets[index]
|
||||
if (!widget) throw new Error(`Widget ${index} not found.`)
|
||||
return widget.value
|
||||
},
|
||||
[this.node.id, this.index] as const
|
||||
)
|
||||
}
|
||||
}
|
||||
export class NodeReference {
|
||||
constructor(
|
||||
readonly id: NodeId,
|
||||
@@ -238,7 +280,7 @@ export class NodeReference {
|
||||
const targetWidget = await targetNode.getWidget(targetWidgetIndex)
|
||||
await this.comfyPage.dragAndDrop(
|
||||
await originSlot.getPosition(),
|
||||
await targetWidget.getPosition()
|
||||
await targetWidget.getSocketPosition()
|
||||
)
|
||||
return originSlot
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 102 KiB |
@@ -1,34 +0,0 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import type { NodeReference } from './fixtures/utils/litegraphUtils'
|
||||
|
||||
test.describe('Primitive Node', () => {
|
||||
test('Can load with correct size', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('primitive_node')
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('primitive_node.png')
|
||||
})
|
||||
|
||||
// When link is dropped on widget, it should automatically convert the widget
|
||||
// to input.
|
||||
test('Can connect to widget', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('primitive_node_unconnected')
|
||||
const primitiveNode: NodeReference = await comfyPage.getNodeRefById(1)
|
||||
const ksamplerNode: NodeReference = await comfyPage.getNodeRefById(2)
|
||||
// Connect the output of the primitive node to the input of first widget of the ksampler node
|
||||
await primitiveNode.connectWidget(0, ksamplerNode, 0)
|
||||
await expect(comfyPage.canvas).toHaveScreenshot(
|
||||
'primitive_node_connected.png'
|
||||
)
|
||||
})
|
||||
|
||||
test('Can connect to dom widget', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('primitive_node_unconnected_dom_widget')
|
||||
const primitiveNode: NodeReference = await comfyPage.getNodeRefById(1)
|
||||
const clipEncoderNode: NodeReference = await comfyPage.getNodeRefById(2)
|
||||
await primitiveNode.connectWidget(0, clipEncoderNode, 0)
|
||||
await expect(comfyPage.canvas).toHaveScreenshot(
|
||||
'primitive_node_connected_dom_widget.png'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 108 KiB |
@@ -1,9 +1,9 @@
|
||||
import type { Response } from '@playwright/test'
|
||||
import { expect, mergeTests } from '@playwright/test'
|
||||
|
||||
import type { StatusWsMessage } from '../src/schemas/apiSchema.ts'
|
||||
import { comfyPageFixture } from './fixtures/ComfyPage'
|
||||
import { webSocketFixture } from './fixtures/ws.ts'
|
||||
import type { StatusWsMessage } from '../../src/schemas/apiSchema.ts'
|
||||
import { comfyPageFixture } from '../fixtures/ComfyPage.ts'
|
||||
import { webSocketFixture } from '../fixtures/ws.ts'
|
||||
|
||||
const test = mergeTests(comfyPageFixture, webSocketFixture)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Browser tab title', () => {
|
||||
test.describe('Beta Menu', () => {
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
ComfyPage,
|
||||
comfyExpect as expect,
|
||||
comfyPageFixture as test
|
||||
} from './fixtures/ComfyPage'
|
||||
} from '../fixtures/ComfyPage'
|
||||
|
||||
async function beforeChange(comfyPage: ComfyPage) {
|
||||
await comfyPage.page.evaluate(() => {
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import type { Palette } from '../src/schemas/colorPaletteSchema'
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import type { Palette } from '../../src/schemas/colorPaletteSchema'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
const customColorPalettes: Record<string, Palette> = {
|
||||
obsidian: {
|
||||
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
@@ -1,6 +1,6 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Keybindings', () => {
|
||||
test('Should execute command', async ({ comfyPage }) => {
|
||||
@@ -32,7 +32,7 @@ test.describe('Keybindings', () => {
|
||||
})
|
||||
|
||||
await comfyPage.executeCommand('TestCommand')
|
||||
await expect(comfyPage.page.locator('.p-toast')).toBeVisible()
|
||||
expect(await comfyPage.getToastErrorCount()).toBe(1)
|
||||
})
|
||||
|
||||
test('Should handle async command errors', async ({ comfyPage }) => {
|
||||
@@ -45,6 +45,6 @@ test.describe('Keybindings', () => {
|
||||
})
|
||||
|
||||
await comfyPage.executeCommand('TestCommand')
|
||||
await expect(comfyPage.page.locator('.p-toast')).toBeVisible()
|
||||
expect(await comfyPage.getToastErrorCount()).toBe(1)
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Copy Paste', () => {
|
||||
test('Can copy and paste node', async ({ comfyPage }) => {
|
||||
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
@@ -1,7 +1,7 @@
|
||||
import { Locator, expect } from '@playwright/test'
|
||||
|
||||
import type { Keybinding } from '../src/schemas/keyBindingSchema'
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import type { Keybinding } from '../../src/schemas/keyBindingSchema'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Load workflow warning', () => {
|
||||
test('Should display a warning when loading a workflow with missing nodes', async ({
|
||||
@@ -309,3 +309,35 @@ test.describe('Feedback dialog', () => {
|
||||
await expect(feedbackHeader).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
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.configure = () => {
|
||||
throw new Error('Error on configure!')
|
||||
}
|
||||
})
|
||||
|
||||
await comfyPage.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()
|
||||
})
|
||||
})
|
||||
@@ -1,12 +1,12 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('DOM Widget', () => {
|
||||
test('Collapsed multiline textarea is not visible', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('collapsed_multiline')
|
||||
|
||||
expect(comfyPage.page.locator('.comfy-multiline-input')).not.toBeVisible()
|
||||
const textareaWidget = comfyPage.page.locator('.comfy-multiline-input')
|
||||
await expect(textareaWidget).not.toBeVisible()
|
||||
})
|
||||
|
||||
test('Multiline textarea correctly collapses', async ({ comfyPage }) => {
|
||||
20
browser_tests/tests/execution.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Execution', () => {
|
||||
test('Report error on unconnected slot', async ({ comfyPage }) => {
|
||||
await comfyPage.disconnectEdge()
|
||||
await comfyPage.clickEmptySpace()
|
||||
|
||||
await comfyPage.executeCommand('Comfy.QueuePrompt')
|
||||
await expect(comfyPage.page.locator('.comfy-error-report')).toBeVisible()
|
||||
await comfyPage.page.locator('.p-dialog-close-button').click()
|
||||
await comfyPage.page.locator('.comfy-error-report').waitFor({
|
||||
state: 'hidden'
|
||||
})
|
||||
await expect(comfyPage.canvas).toHaveScreenshot(
|
||||
'execution-error-unconnected-slot.png'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
After Width: | Height: | Size: 97 KiB |
@@ -1,7 +1,7 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { SettingParams } from '../src/types/settingTypes'
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { SettingParams } from '../../src/types/settingTypes'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Topbar commands', () => {
|
||||
test.beforeEach(async ({ comfyPage }) => {
|
||||
21
browser_tests/tests/graph.spec.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Graph', () => {
|
||||
// Should be able to fix link input slot index after swap the input order
|
||||
// Ref: https://github.com/Comfy-Org/ComfyUI_frontend/issues/3348
|
||||
test('Fix link input slots', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('input_order_swap')
|
||||
expect(
|
||||
await comfyPage.page.evaluate(() => {
|
||||
return window['app'].graph.links.get(1)?.target_slot
|
||||
})
|
||||
).toBe(1)
|
||||
})
|
||||
|
||||
test('Validate workflow links', async ({ comfyPage }) => {
|
||||
await comfyPage.loadWorkflow('bad_link')
|
||||
await expect(comfyPage.getVisibleToastCount()).resolves.toBe(2)
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Graph Canvas Menu', () => {
|
||||
test.beforeEach(async ({ comfyPage }) => {
|
||||
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
@@ -1,7 +1,7 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { ComfyPage, comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import type { NodeReference } from './fixtures/utils/litegraphUtils'
|
||||
import { ComfyPage, comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
|
||||
|
||||
test.describe('Group Node', () => {
|
||||
test.describe('Node library sidebar', () => {
|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
@@ -1,6 +1,6 @@
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { comfyPageFixture as test } from './fixtures/ComfyPage'
|
||||
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
||||
|
||||
test.describe('Item Interaction', () => {
|
||||
test('Can select/delete all items', async ({ comfyPage }) => {
|
||||
@@ -91,15 +91,20 @@ test.describe('Node Interaction', () => {
|
||||
await comfyPage.setSetting('Comfy.LinkRelease.ActionShift', 'no action')
|
||||
})
|
||||
|
||||
test('Can disconnect/connect edge', async ({ comfyPage }) => {
|
||||
await comfyPage.disconnectEdge()
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
|
||||
await comfyPage.connectEdge()
|
||||
// Move mouse to empty area to avoid slot highlight.
|
||||
await comfyPage.moveMouseToEmptyArea()
|
||||
// Litegraph renders edge with a slight offset.
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('default.png', {
|
||||
maxDiffPixels: 50
|
||||
// Test both directions of edge connection.
|
||||
;[{ reverse: false }, { reverse: true }].forEach(({ reverse }) => {
|
||||
test(`Can disconnect/connect edge ${reverse ? 'reverse' : 'normal'}`, async ({
|
||||
comfyPage
|
||||
}) => {
|
||||
await comfyPage.disconnectEdge()
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
|
||||
await comfyPage.connectEdge({ reverse })
|
||||
// Move mouse to empty area to avoid slot highlight.
|
||||
await comfyPage.moveMouseToEmptyArea()
|
||||
// Litegraph renders edge with a slight offset.
|
||||
await expect(comfyPage.canvas).toHaveScreenshot('default.png', {
|
||||
maxDiffPixels: 50
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |