chore: migrate tests from tests-ui/ to colocate with source files (#7811)

## Summary

Migrates all unit tests from `tests-ui/` to colocate with their source
files in `src/`, improving discoverability and maintainability.

## Changes

- **What**: Relocated all unit tests to be adjacent to the code they
test, following the `<source>.test.ts` naming convention
- **Config**: Updated `vitest.config.ts` to remove `tests-ui` include
pattern and `@tests-ui` alias
- **Docs**: Moved testing documentation to `docs/testing/` with updated
paths and patterns

## Review Focus

- Migration patterns documented in
`temp/plans/migrate-tests-ui-to-src.md`
- Tests use `@/` path aliases instead of relative imports
- Shared fixtures placed in `__fixtures__/` directories

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7811-chore-migrate-tests-from-tests-ui-to-colocate-with-source-files-2da6d73d36508147a4cce85365dee614)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Alexander Brown
2026-01-05 16:32:24 -08:00
committed by GitHub
parent 832588c7a9
commit 10feb1fd5b
272 changed files with 483 additions and 1239 deletions

View File

@@ -1,123 +0,0 @@
{
"id": "e5ffd5e1-1c01-45ac-90dd-b7d83a206b0f",
"revision": 0,
"last_node_id": 3,
"last_link_id": 3,
"nodes": [
{
"id": 1,
"type": "InvertMask",
"pos": [100, 130],
"size": [140, 26],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"localized_name": "mask",
"name": "mask",
"type": "MASK",
"link": null
}
],
"outputs": [
{
"localized_name": "MASK",
"name": "MASK",
"type": "MASK",
"links": [2, 3]
}
],
"properties": { "Node name for S&R": "InvertMask" },
"widgets_values": []
},
{
"id": 3,
"type": "InvertMask",
"pos": [400, 220],
"size": [140, 26],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{ "localized_name": "mask", "name": "mask", "type": "MASK", "link": 3 }
],
"outputs": [
{
"localized_name": "MASK",
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": { "Node name for S&R": "InvertMask" },
"widgets_values": []
},
{
"id": 2,
"type": "InvertMask",
"pos": [400, 130],
"size": [140, 26],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{ "localized_name": "mask", "name": "mask", "type": "MASK", "link": 2 }
],
"outputs": [
{
"localized_name": "MASK",
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": { "Node name for S&R": "InvertMask" },
"widgets_values": []
}
],
"links": [
[2, 1, 0, 2, 0, "MASK"],
[3, 1, 0, 3, 0, "MASK"]
],
"floatingLinks": [
{
"id": 6,
"origin_id": 1,
"origin_slot": 0,
"target_id": -1,
"target_slot": -1,
"type": "MASK",
"parentId": 1
}
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.2100000000000002,
"offset": [319.8264462809916, 109.2148760330578]
},
"linkExtensions": [
{ "id": 2, "parentId": 3 },
{ "id": 3, "parentId": 3 }
],
"reroutes": [
{
"id": 1,
"parentId": 2,
"pos": [350, 110],
"linkIds": [],
"floating": { "slotType": "output" }
},
{ "id": 2, "parentId": 4, "pos": [310, 150], "linkIds": [2, 3] },
{ "id": 3, "parentId": 2, "pos": [360, 170], "linkIds": [2, 3] },
{
"id": 4,
"pos": [271.9090881347656, 146.9834747314453],
"linkIds": [2, 3]
}
]
},
"version": 0.4
}

View File

@@ -1,68 +0,0 @@
{
"id": "d175890f-716a-4ece-ba33-1d17a513b7be",
"revision": 0,
"last_node_id": 2,
"last_link_id": 1,
"nodes": [
{
"id": 2,
"type": "VAEDecode",
"pos": [63.44815444946289, 178.71633911132812],
"size": [210, 46],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null
},
{
"name": "vae",
"type": "VAE",
"link": null
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": []
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
}
],
"links": [],
"floatingLinks": [
{
"id": 4,
"origin_id": 2,
"origin_slot": 0,
"target_id": -1,
"target_slot": -1,
"type": "IMAGE",
"parentId": 1
}
],
"groups": [],
"config": {},
"extra": {
"linkExtensions": [],
"reroutes": [
{
"id": 1,
"pos": [393.2383117675781, 194.61941528320312],
"linkIds": [],
"floating": {
"slotType": "output"
}
}
]
},
"version": 0.4
}

View File

@@ -1,96 +0,0 @@
{
"id": "26a34f13-1767-4847-b25f-a21dedf6840d",
"revision": 0,
"last_node_id": 3,
"last_link_id": 2,
"nodes": [
{
"id": 2,
"type": "VAEDecode",
"pos": [
63.44815444946289,
178.71633911132812
],
"size": [
210,
46
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null
},
{
"name": "vae",
"type": "VAE",
"link": null
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
2
]
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 3,
"type": "SaveImage",
"pos": [
419.36920166015625,
179.71388244628906
],
"size": [
226.3714141845703,
58
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 2
}
],
"outputs": [],
"properties": {},
"widgets_values": [
"ComfyUI"
]
}
],
"links": [
[
2,
2,
0,
3,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {
"linkExtensions": [
{
"id": 2,
"parentId": 1
}
]
},
"version": 0.4
}

View File

@@ -1 +0,0 @@
{"id":"e5ffd5e1-1c01-45ac-90dd-b7d83a206b0f","revision":0,"last_node_id":9,"last_link_id":12,"nodes":[{"id":3,"type":"InvertMask","pos":[390,270],"size":[140,26],"flags":{},"order":8,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":3}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":7,"type":"InvertMask","pos":[390,560],"size":[140,26],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":10}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":8,"type":"InvertMask","pos":[390,640],"size":[140,26],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":9}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":5,"type":"InvertMask","pos":[390,480],"size":[140,26],"flags":{"collapsed":false},"order":5,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":11}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":6,"type":"InvertMask","pos":[390,400],"size":[140,26],"flags":{},"order":6,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":12}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":4,"type":"InvertMask","pos":[50,640],"size":[140,26],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":null}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":[9,10,11,12]}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":2,"type":"InvertMask","pos":[390,180],"size":[140,26],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":2}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":1,"type":"InvertMask","pos":[50,170],"size":[140,26],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":null}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":[2,3]}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]},{"id":9,"type":"InvertMask","pos":[50,410],"size":[140,26],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"mask","name":"mask","type":"MASK","link":null}],"outputs":[{"localized_name":"MASK","name":"MASK","type":"MASK","links":[]}],"properties":{"Node name for S&R":"InvertMask"},"widgets_values":[]}],"links":[[2,1,0,2,0,"MASK"],[3,1,0,3,0,"MASK"],[9,4,0,8,0,"MASK"],[10,4,0,7,0,"MASK"],[11,4,0,5,0,"MASK"],[12,4,0,6,0,"MASK"]],"floatingLinks":[{"id":6,"origin_id":1,"origin_slot":0,"target_id":-1,"target_slot":-1,"type":"MASK","parentId":1}],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[0,0]},"linkExtensions":[{"id":2,"parentId":3},{"id":3,"parentId":3},{"id":9,"parentId":12},{"id":10,"parentId":15},{"id":11,"parentId":7},{"id":12,"parentId":7}],"reroutes":[{"id":1,"parentId":2,"pos":[340,160],"linkIds":[],"floating":{"slotType":"output"}},{"id":2,"parentId":4,"pos":[290,190],"linkIds":[2,3]},{"id":3,"parentId":2,"pos":[350,220],"linkIds":[2,3]},{"id":4,"pos":[250,190],"linkIds":[2,3]},{"id":6,"parentId":8,"pos":[300,450],"linkIds":[11,12]},{"id":7,"parentId":6,"pos":[350,450],"linkIds":[11,12]},{"id":8,"parentId":13,"pos":[250,450],"linkIds":[11,12]},{"id":10,"pos":[250,650],"linkIds":[9,10,11,12]},{"id":11,"parentId":10,"pos":[300,650],"linkIds":[9]},{"id":12,"parentId":11,"pos":[350,650],"linkIds":[9]},{"id":13,"parentId":10,"pos":[250,570],"linkIds":[10,11,12]},{"id":14,"parentId":13,"pos":[300,570],"linkIds":[10]},{"id":15,"parentId":14,"pos":[350,570],"linkIds":[10]}]},"version":0.4}

View File

@@ -1,75 +0,0 @@
import type {
ISerialisedGraph,
SerialisableGraph
} from '@/lib/litegraph/src/litegraph'
export const oldSchemaGraph: ISerialisedGraph = {
id: 'b4e984f1-b421-4d24-b8b4-ff895793af13',
revision: 0,
version: 0.4,
config: {},
last_node_id: 0,
last_link_id: 0,
groups: [
{
id: 123,
bounding: [20, 20, 1, 3],
color: '#6029aa',
font_size: 14,
title: 'A group to test with'
}
],
nodes: [
// @ts-expect-error TODO: Fix after merge - missing required properties for test
{
id: 1
}
],
links: []
}
export const minimalSerialisableGraph: SerialisableGraph = {
id: 'd175890f-716a-4ece-ba33-1d17a513b7be',
revision: 0,
version: 1,
config: {},
state: {
lastNodeId: 0,
lastLinkId: 0,
lastGroupId: 0,
lastRerouteId: 0
},
nodes: [],
links: [],
groups: []
}
export const basicSerialisableGraph: SerialisableGraph = {
id: 'ca9da7d8-fddd-4707-ad32-67be9be13140',
revision: 0,
version: 1,
config: {},
state: {
lastNodeId: 0,
lastLinkId: 0,
lastGroupId: 0,
lastRerouteId: 0
},
groups: [
{
id: 123,
bounding: [20, 20, 1, 3],
color: '#6029aa',
font_size: 14,
title: 'A group to test with'
}
],
nodes: [
// @ts-expect-error TODO: Fix after merge - missing required properties for test
{
id: 1,
type: 'mustBeSet'
}
],
links: []
}

View File

@@ -1,82 +0,0 @@
import { test as baseTest } from 'vitest'
import { LGraph } from '@/lib/litegraph/src/LGraph'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import type {
ISerialisedGraph,
SerialisableGraph
} from '@/lib/litegraph/src/types/serialisation'
import floatingBranch from './assets/floatingBranch.json' with { type: 'json' }
import floatingLink from './assets/floatingLink.json' with { type: 'json' }
import linkedNodes from './assets/linkedNodes.json' with { type: 'json' }
import reroutesComplex from './assets/reroutesComplex.json' with { type: 'json' }
import {
basicSerialisableGraph,
minimalSerialisableGraph,
oldSchemaGraph
} from './assets/testGraphs'
interface LitegraphFixtures {
minimalGraph: LGraph
minimalSerialisableGraph: SerialisableGraph
oldSchemaGraph: ISerialisedGraph
floatingLinkGraph: ISerialisedGraph
linkedNodesGraph: ISerialisedGraph
floatingBranchGraph: LGraph
reroutesComplexGraph: LGraph
}
/** These fixtures alter global state, and are difficult to reset. Relies on a single test per-file to reset state. */
interface DirtyFixtures {
basicSerialisableGraph: SerialisableGraph
}
export const test = baseTest.extend<LitegraphFixtures>({
// eslint-disable-next-line no-empty-pattern
minimalGraph: async ({}, use) => {
// Before each test function
const serialisable = structuredClone(minimalSerialisableGraph)
const lGraph = new LGraph(serialisable)
// use the fixture value
await use(lGraph)
},
minimalSerialisableGraph: structuredClone(minimalSerialisableGraph),
oldSchemaGraph: structuredClone(oldSchemaGraph),
floatingLinkGraph: structuredClone(
floatingLink as unknown as ISerialisedGraph
),
linkedNodesGraph: structuredClone(linkedNodes as unknown as ISerialisedGraph),
// eslint-disable-next-line no-empty-pattern
floatingBranchGraph: async ({}, use) => {
const cloned = structuredClone(
floatingBranch as unknown as ISerialisedGraph
)
const graph = new LGraph(cloned)
await use(graph)
},
// eslint-disable-next-line no-empty-pattern
reroutesComplexGraph: async ({}, use) => {
const cloned = structuredClone(
reroutesComplex as unknown as ISerialisedGraph
)
const graph = new LGraph(cloned)
await use(graph)
}
})
/** Test that use {@link DirtyFixtures}. One test per file. */
export const dirtyTest = test.extend<DirtyFixtures>({
// eslint-disable-next-line no-empty-pattern
basicSerialisableGraph: async ({}, use) => {
if (!basicSerialisableGraph.nodes) throw new Error('Invalid test object')
// Register node types
for (const node of basicSerialisableGraph.nodes) {
LiteGraph.registerNodeType(node.type!, LiteGraph.LGraphNode)
}
await use(structuredClone(basicSerialisableGraph))
}
})