Migrate all tests to TypeScript (#19)

* Merge 2 npm repos

* Install ts-jest

* Update jestconfig

* Fix jest types

* jest fix

* Fix babel config ref issue

* Fix import

* Fix import meta issue

* fix generate

* Skip multi-user tests
This commit is contained in:
Chenlei Hu
2024-06-17 11:25:56 -04:00
committed by GitHub
parent 48d5870d9c
commit f85cb3d5e9
50 changed files with 7753 additions and 5789 deletions

View File

@@ -2,7 +2,7 @@
/// <reference path="../../src/types/litegraph.d.ts" />
/**
* @typedef { import("../../dist/scripts/app")["app"] } app
* @typedef { import("./src/scripts/app")["app"] } app
* @typedef { import("../../src/types/litegraph") } LG
* @typedef { import("../../src/types/litegraph").IWidget } IWidget
* @typedef { import("../../src/types/litegraph").ContextMenuItem } ContextMenuItem
@@ -12,6 +12,8 @@
* @typedef { (...args: EzOutput[] | [...EzOutput[], Record<string, unknown>]) => EzNode } EzNodeFactory
*/
export type EzNameSpace = Record<string, (...args) => EzNode>;
export class EzConnection {
/** @type { app } */
app;
@@ -366,6 +368,7 @@ export class EzGraph {
this.app.graph.clear();
setTimeout(async () => {
await this.app.loadGraphData(graph);
// @ts-ignore
r();
}, 10);
});

View File

@@ -1,10 +1,22 @@
const { mockApi } = require("./setup");
const { Ez } = require("./ezgraph");
const lg = require("./litegraph");
const fs = require("fs");
const path = require("path");
import { APIConfig, mockApi } from "./setup";
import { Ez, EzGraph, EzNameSpace } from "./ezgraph";
import lg from "./litegraph";
import fs from "fs";
import path from "path";
const html = fs.readFileSync(path.resolve(__dirname, "../../dist/index.html"))
const html = fs.readFileSync(path.resolve(__dirname, "../../index.html"))
interface StartConfig extends APIConfig {
resetEnv?: boolean;
preSetup?(app): Promise<void>;
localStorage?: Record<string, string>;
}
interface StartResult {
app: any;
graph: EzGraph;
ez: EzNameSpace;
}
/**
*
@@ -15,7 +27,7 @@ const html = fs.readFileSync(path.resolve(__dirname, "../../dist/index.html"))
* } } config
* @returns
*/
export async function start(config = {}) {
export async function start(config: StartConfig = {}): Promise<StartResult> {
if(config.resetEnv) {
jest.resetModules();
jest.resetAllMocks();
@@ -25,13 +37,14 @@ export async function start(config = {}) {
}
Object.assign(localStorage, config.localStorage ?? {});
document.body.innerHTML = html;
document.body.innerHTML = html.toString();
mockApi(config);
const { app } = require("../../dist/scripts/app");
const { app } = await import("../../src/scripts/app");
config.preSetup?.(app);
await app.setup();
// @ts-ignore
return { ...Ez.graph(app, global["LiteGraph"], global["LGraphCanvas"]), app };
}
@@ -49,7 +62,7 @@ export async function checkBeforeAndAfterReload(graph, cb) {
* @param { string } name
* @param { Record<string, string | [string | string[], any]> } input
* @param { (string | string[])[] | Record<string, string | string[]> } output
* @returns { Record<string, import("../../dist/types/comfy").ComfyObjectInfo> }
* @returns { Record<string, import("./src/types/comfy").ComfyObjectInfo> }
*/
export function makeNodeDef(name, input, output = {}) {
const nodeDef = {
@@ -72,8 +85,11 @@ export function makeNodeDef(name, input, output = {}) {
}, {});
}
for (const k in output) {
// @ts-ignore
nodeDef.output.push(output[k]);
// @ts-ignore
nodeDef.output_name.push(k);
// @ts-ignore
nodeDef.output_is_list.push(false);
}
@@ -120,7 +136,7 @@ export function createDefaultWorkflow(ez, graph) {
}
export async function getNodeDefs() {
const { api } = require("../../dist/scripts/api");
const { api } = await import("../../src/scripts/api");
return api.getNodeDefs();
}

View File

@@ -1,36 +0,0 @@
const fs = require("fs");
const path = require("path");
const { nop } = require("../utils/nopProxy");
function forEachKey(cb) {
for (const k of [
"LiteGraph",
"LGraph",
"LLink",
"LGraphNode",
"LGraphGroup",
"DragAndScale",
"LGraphCanvas",
"ContextMenu",
]) {
cb(k);
}
}
export function setup(ctx) {
const lg = fs.readFileSync(path.resolve("../dist/lib/litegraph.core.js"), "utf-8");
const globalTemp = {};
(function (console) {
eval(lg);
}).call(globalTemp, nop);
forEachKey((k) => (ctx[k] = globalTemp[k]));
require(path.resolve("../dist/lib/litegraph.extensions.js"));
}
export function teardown(ctx) {
forEachKey((k) => delete ctx[k]);
// Clear document after each run
document.getElementsByTagName("html")[0].innerHTML = "";
}

View File

@@ -0,0 +1,39 @@
import fs from "fs";
import path from "path";
import { nop } from "../utils/nopProxy";
function forEachKey(cb) {
for (const k of [
"LiteGraph",
"LGraph",
"LLink",
"LGraphNode",
"LGraphGroup",
"DragAndScale",
"LGraphCanvas",
"ContextMenu",
]) {
cb(k);
}
}
export default {
setup(ctx) {
const lg = fs.readFileSync(path.resolve("./src/lib/litegraph.core.js"), "utf-8");
const globalTemp = {};
(function (console) {
eval(lg);
}).call(globalTemp, nop);
forEachKey((k) => (ctx[k] = globalTemp[k]));
const lg_ext = fs.readFileSync(path.resolve("./src/lib/litegraph.extensions.js"), "utf-8");
eval(lg_ext);
},
teardown(ctx) {
forEachKey((k) => delete ctx[k]);
// Clear document after each run
document.getElementsByTagName("html")[0].innerHTML = "";
}
};

View File

@@ -1,8 +1,8 @@
require("../../dist/scripts/api");
import "../../src/scripts/api";
const fs = require("fs");
const path = require("path");
function* walkSync(dir) {
function* walkSync(dir: string): Generator<string> {
const files = fs.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
@@ -13,8 +13,16 @@ function* walkSync(dir) {
}
}
export interface APIConfig {
mockExtensions?: string[];
mockNodeDefs?: Record<string, any>;
settings?: Record<string, string>;
userConfig?: { storage: "server" | "browser"; users?: Record<string, any>; migrated?: boolean };
userData?: Record<string, any>;
}
/**
* @typedef { import("../../dist/types/comfy").ComfyObjectInfo } ComfyObjectInfo
* @typedef { import("./src/types/comfy").ComfyObjectInfo } ComfyObjectInfo
*/
/**
@@ -26,20 +34,19 @@ function* walkSync(dir) {
* userData?: Record<string, any>
* }} config
*/
export function mockApi(config = {}) {
export function mockApi(config: APIConfig = {}) {
let { mockExtensions, mockNodeDefs, userConfig, settings, userData } = {
userConfig,
settings: {},
userData: {},
...config,
};
if (!mockExtensions) {
mockExtensions = Array.from(walkSync(path.resolve("../dist/extensions/core")))
mockExtensions = Array.from(walkSync(path.resolve("./src/extensions/core")))
.filter((x) => x.endsWith(".js"))
.map((x) => path.relative(path.resolve("../dist/"), x).replace(/\\/g, "/"));
.map((x) => path.relative(path.resolve("./src/"), x).replace(/\\/g, "/"));
}
if (!mockNodeDefs) {
mockNodeDefs = JSON.parse(fs.readFileSync(path.resolve("./data/object_info.json")));
mockNodeDefs = JSON.parse(fs.readFileSync(path.resolve("./tests-ui/data/object_info.json")));
}
const events = new EventTarget();
@@ -51,11 +58,13 @@ export function mockApi(config = {}) {
getExtensions: jest.fn(() => mockExtensions),
getNodeDefs: jest.fn(() => mockNodeDefs),
init: jest.fn(),
apiURL: jest.fn((x) => "../../dist/" + x),
apiURL: jest.fn((x) => "src/" + x),
createUser: jest.fn((username) => {
// @ts-ignore
if(username in userConfig.users) {
return { status: 400, json: () => "Duplicate" }
}
// @ts-ignore
userConfig.users[username + "!"] = username;
return { status: 200, json: () => username + "!" }
}),
@@ -73,7 +82,7 @@ export function mockApi(config = {}) {
userData[file] = data;
}),
};
jest.mock("../../dist/scripts/api", () => ({
jest.mock("../../src/scripts/api", () => ({
get api() {
return mockApi;
},