Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import type {LGraphNode} from "@comfyorg/frontend";
|
||||
|
||||
import {NodeTypesString} from "../constants.js";
|
||||
import {wait} from "rgthree/common/shared_utils.js";
|
||||
import {describe, should, beforeEach, expect, describeRun} from "../testing/runner.js";
|
||||
import {ComfyUITestEnvironment} from "../testing/comfyui_env.js";
|
||||
|
||||
const env = new ComfyUITestEnvironment();
|
||||
|
||||
function verifyInputAndOutputName(
|
||||
node: LGraphNode,
|
||||
index: number,
|
||||
inputName: string | null,
|
||||
isLinked?: boolean,
|
||||
) {
|
||||
if (inputName != null) {
|
||||
expect(node.inputs[index]!.name).toBe(`input ${index} name`, inputName);
|
||||
}
|
||||
if (isLinked) {
|
||||
expect(node.inputs[index]!.link).toBeANumber(`input ${index} connection`);
|
||||
} else if (isLinked === false) {
|
||||
expect(node.inputs[index]!.link).toBeNullOrUndefined(`input ${index} connection`);
|
||||
}
|
||||
if (inputName != null) {
|
||||
if (inputName === "+") {
|
||||
expect(node.outputs[index]).toBeUndefined(`output ${index}`);
|
||||
} else {
|
||||
let outputName =
|
||||
inputName === "base_ctx" ? "CONTEXT" : inputName.replace(/^\+\s/, "").toUpperCase();
|
||||
expect(node.outputs[index]!.name).toBe(`output ${index} name`, outputName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function vertifyInputsStructure(node: LGraphNode, expectedLength: number) {
|
||||
expect(node.inputs.length).toBe("inputs length", expectedLength);
|
||||
expect(node.outputs.length).toBe("outputs length", expectedLength - 1);
|
||||
verifyInputAndOutputName(node, expectedLength - 1, "+", false);
|
||||
}
|
||||
|
||||
describe("TestContextDynamic", async () => {
|
||||
let nodeConfig!: LGraphNode;
|
||||
let nodeCtx!: LGraphNode;
|
||||
|
||||
let lastNode: LGraphNode | null = null;
|
||||
|
||||
await beforeEach(async () => {
|
||||
await env.clear();
|
||||
lastNode = nodeConfig = await env.addNode(NodeTypesString.KSAMPLER_CONFIG);
|
||||
lastNode = nodeCtx = await env.addNode(NodeTypesString.DYNAMIC_CONTEXT);
|
||||
nodeConfig.connect(0, nodeCtx, 1); // steps
|
||||
nodeConfig.connect(2, nodeCtx, 2); // cfg
|
||||
nodeConfig.connect(4, nodeCtx, 3); // scheduler
|
||||
nodeConfig.connect(0, nodeCtx, 4); // This is the step.1
|
||||
nodeConfig.connect(0, nodeCtx, 5); // This is the step.2
|
||||
nodeCtx.disconnectInput(2);
|
||||
nodeCtx.disconnectInput(5);
|
||||
nodeConfig.connect(0, nodeCtx, 6); // This is the step.3
|
||||
nodeCtx.disconnectInput(6);
|
||||
await wait();
|
||||
});
|
||||
|
||||
await should("add correct inputs", async () => {
|
||||
vertifyInputsStructure(nodeCtx, 8);
|
||||
let i = 0;
|
||||
verifyInputAndOutputName(nodeCtx, i++, "base_ctx", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ cfg", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ scheduler", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.1", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.2", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.3", false);
|
||||
});
|
||||
|
||||
await should("add evaluate correct outputs", async () => {
|
||||
const displayAny1 = await env.addNode(NodeTypesString.DISPLAY_ANY, {placement: "right"});
|
||||
const displayAny2 = await env.addNode(NodeTypesString.DISPLAY_ANY, {placement: "under"});
|
||||
const displayAny3 = await env.addNode(NodeTypesString.DISPLAY_ANY, {placement: "under"});
|
||||
const displayAny4 = await env.addNode(NodeTypesString.DISPLAY_ANY, {placement: "under"});
|
||||
|
||||
nodeCtx.connect(1, displayAny1, 0); // steps
|
||||
nodeCtx.connect(3, displayAny2, 0); // scheduler
|
||||
nodeCtx.connect(4, displayAny3, 0); // steps.1
|
||||
nodeCtx.connect(6, displayAny4, 0); // steps.3 (unlinked)
|
||||
|
||||
await env.queuePrompt();
|
||||
|
||||
expect(displayAny1.widgets![0]!.value).toBe("output 1", 30);
|
||||
expect(displayAny2.widgets![0]!.value).toBe("output 3", '"normal"');
|
||||
expect(displayAny3.widgets![0]!.value).toBe("output 4", 30);
|
||||
expect(displayAny4.widgets![0]!.value).toBe("output 6", "None");
|
||||
});
|
||||
|
||||
await describeRun("Nested", async () => {
|
||||
let nodeConfig2!: LGraphNode;
|
||||
let nodeCtx2!: LGraphNode;
|
||||
|
||||
await beforeEach(async () => {
|
||||
nodeConfig2 = await env.addNode(NodeTypesString.KSAMPLER_CONFIG, {placement: "start"});
|
||||
nodeConfig2.widgets = nodeConfig2.widgets || [];
|
||||
nodeConfig2.widgets[0]!.value = 111;
|
||||
nodeConfig2.widgets[2]!.value = 11.1;
|
||||
nodeCtx2 = await env.addNode(NodeTypesString.DYNAMIC_CONTEXT, {placement: "right"});
|
||||
nodeConfig2.connect(0, nodeCtx2, 1); // steps
|
||||
nodeConfig2.connect(2, nodeCtx2, 2); // cfg
|
||||
nodeConfig2.connect(3, nodeCtx2, 3); // sampler
|
||||
nodeConfig2.connect(2, nodeCtx2, 4); // This is the cfg.1
|
||||
nodeConfig2.connect(0, nodeCtx2, 5); // This is the steps.1
|
||||
nodeCtx2.disconnectInput(2);
|
||||
nodeCtx2.disconnectInput(5);
|
||||
nodeConfig2.connect(2, nodeCtx2, 6); // This is the cfg.2
|
||||
nodeCtx2.disconnectInput(6);
|
||||
|
||||
await wait();
|
||||
});
|
||||
|
||||
await should("disallow context node to be connected to non-first spot.", async () => {
|
||||
// Connect to first node.
|
||||
let expectedInputs = 8;
|
||||
|
||||
nodeCtx2.connect(0, nodeCtx, expectedInputs - 1);
|
||||
console.log(nodeCtx.inputs);
|
||||
|
||||
vertifyInputsStructure(nodeCtx, expectedInputs);
|
||||
verifyInputAndOutputName(nodeCtx, 0, "base_ctx", false);
|
||||
verifyInputAndOutputName(nodeCtx, nodeCtx.inputs.length - 1, null, false);
|
||||
|
||||
nodeCtx2.connect(0, nodeCtx, 0);
|
||||
expectedInputs = 14;
|
||||
vertifyInputsStructure(nodeCtx, expectedInputs);
|
||||
verifyInputAndOutputName(nodeCtx, 0, "base_ctx", true);
|
||||
verifyInputAndOutputName(nodeCtx, expectedInputs - 1, null, false);
|
||||
});
|
||||
|
||||
await should("add inputs from connected above owned.", async () => {
|
||||
// Connect to first node.
|
||||
nodeCtx2.connect(0, nodeCtx, 0);
|
||||
|
||||
let expectedInputs = 14;
|
||||
vertifyInputsStructure(nodeCtx, expectedInputs);
|
||||
let i = 0;
|
||||
verifyInputAndOutputName(nodeCtx, i++, "base_ctx", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "steps", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "cfg", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "sampler", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "cfg.1", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "steps.1", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "cfg.2", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.2", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ cfg.3", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ scheduler", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.3", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.4", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.5", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+", false);
|
||||
});
|
||||
|
||||
await should("add then remove inputs when disconnected.", async () => {
|
||||
// Connect to first node.
|
||||
nodeCtx2.connect(0, nodeCtx, 0);
|
||||
|
||||
let expectedInputs = 14;
|
||||
expect(nodeCtx.inputs.length).toBe("inputs length", expectedInputs);
|
||||
expect(nodeCtx.outputs.length).toBe("outputs length", expectedInputs - 1);
|
||||
|
||||
nodeCtx.disconnectInput(0);
|
||||
|
||||
expectedInputs = 8;
|
||||
expect(nodeCtx.inputs.length).toBe("inputs length", expectedInputs);
|
||||
expect(nodeCtx.outputs.length).toBe("outputs length", expectedInputs - 1);
|
||||
let i = 0;
|
||||
verifyInputAndOutputName(nodeCtx, i++, "base_ctx", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ cfg", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ scheduler", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.1", true);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.2", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+ steps.3", false);
|
||||
verifyInputAndOutputName(nodeCtx, i++, "+", false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
import type {LGraphNode} from "@comfyorg/frontend";
|
||||
|
||||
import {NodeTypesString} from "../constants";
|
||||
import {ComfyUITestEnvironment} from "../testing/comfyui_env";
|
||||
import {describe, should, beforeEach, expect, describeRun} from "../testing/runner.js";
|
||||
import {pasteImageToLoadImageNode, PNG_1x1, PNG_1x2, PNG_2x1} from "../testing/utils_test.js";
|
||||
|
||||
const env = new ComfyUITestEnvironment();
|
||||
|
||||
describe("TestImageOrLatentSize", async () => {
|
||||
await beforeEach(async () => {
|
||||
await env.clear();
|
||||
});
|
||||
|
||||
await describeRun("LoadImage", async () => {
|
||||
let imageNode: LGraphNode;
|
||||
let displayAnyW: LGraphNode;
|
||||
let displayAnyH: LGraphNode;
|
||||
|
||||
await beforeEach(async () => {
|
||||
await env.clear();
|
||||
imageNode = await env.addNode("LoadImage");
|
||||
const sizeNode = await env.addNode(NodeTypesString.IMAGE_OR_LATENT_SIZE);
|
||||
displayAnyW = await env.addNode(NodeTypesString.DISPLAY_ANY);
|
||||
displayAnyH = await env.addNode(NodeTypesString.DISPLAY_ANY);
|
||||
imageNode.connect(0, sizeNode, 0);
|
||||
sizeNode.connect(0, displayAnyW, 0);
|
||||
sizeNode.connect(1, displayAnyH, 0);
|
||||
await env.wait();
|
||||
});
|
||||
|
||||
await should("get correct size for a 1x1 image", async () => {
|
||||
await pasteImageToLoadImageNode(env, PNG_1x1, imageNode);
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 1);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 1);
|
||||
});
|
||||
|
||||
await should("get correct size for a 1x2 image", async () => {
|
||||
await pasteImageToLoadImageNode(env, PNG_1x2, imageNode);
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 1);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 2);
|
||||
});
|
||||
|
||||
await should("get correct size for a 2x1 image", async () => {
|
||||
await pasteImageToLoadImageNode(env, PNG_2x1, imageNode);
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 2);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 1);
|
||||
});
|
||||
});
|
||||
|
||||
await describeRun("Latent", async () => {
|
||||
let latentNode: LGraphNode;
|
||||
let displayAnyW: LGraphNode;
|
||||
let displayAnyH: LGraphNode;
|
||||
|
||||
await beforeEach(async () => {
|
||||
await env.clear();
|
||||
latentNode = await env.addNode("EmptyLatentImage");
|
||||
const sizeNode = await env.addNode(NodeTypesString.IMAGE_OR_LATENT_SIZE);
|
||||
displayAnyW = await env.addNode(NodeTypesString.DISPLAY_ANY);
|
||||
displayAnyH = await env.addNode(NodeTypesString.DISPLAY_ANY);
|
||||
latentNode.connect(0, sizeNode, 0);
|
||||
sizeNode.connect(0, displayAnyW, 0);
|
||||
sizeNode.connect(1, displayAnyH, 0);
|
||||
await env.wait();
|
||||
latentNode.widgets![0]!.value = 16; // Width
|
||||
latentNode.widgets![1]!.value = 16; // Height
|
||||
latentNode.widgets![2]!.value = 1; // Batch
|
||||
await env.wait();
|
||||
});
|
||||
|
||||
await should("get correct size for a 16x16 latent", async () => {
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 16);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 16);
|
||||
});
|
||||
|
||||
await should("get correct size for a 16x32 latent", async () => {
|
||||
latentNode.widgets![1]!.value = 32;
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 16);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 32);
|
||||
});
|
||||
|
||||
await should("get correct size for a 32x16 image", async () => {
|
||||
latentNode.widgets![0]!.value = 32;
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 32);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 16);
|
||||
});
|
||||
|
||||
await should("get correct size with a batch", async () => {
|
||||
latentNode.widgets![0]!.value = 32;
|
||||
latentNode.widgets![2]!.value = 2;
|
||||
await env.queuePrompt();
|
||||
expect(displayAnyW.widgets![0]!.value).toBe("width", 32);
|
||||
expect(displayAnyH.widgets![0]!.value).toBe("height", 16);
|
||||
});
|
||||
});
|
||||
});
|
||||
162
custom_nodes/rgthree-comfy/src_web/comfyui/tests/power_puter.ts
Normal file
162
custom_nodes/rgthree-comfy/src_web/comfyui/tests/power_puter.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import type {LGraphNode} from "@comfyorg/frontend";
|
||||
|
||||
import {NodeTypesString} from "../constants";
|
||||
import {ComfyUITestEnvironment} from "../testing/comfyui_env";
|
||||
import {describe, should, beforeEach, expect, describeRun} from "../testing/runner.js";
|
||||
import {pasteImageToLoadImageNode, PNG_1x1, PNG_1x2, PNG_2x1} from "../testing/utils_test.js";
|
||||
|
||||
const env = new ComfyUITestEnvironment();
|
||||
|
||||
function setPowerPuterValue(node: LGraphNode, outputType: string, value: string) {
|
||||
// Strip as much whitespace on first non-empty line from all lines.
|
||||
if (value.includes("\n")) {
|
||||
value = value.replace(/^\n/gm, "");
|
||||
const strip = value.match(/^(.*?)\S/)?.[1]?.length;
|
||||
if (strip) {
|
||||
value = value.replace(new RegExp(`^.{${strip}}`, "mg"), "");
|
||||
}
|
||||
}
|
||||
node.widgets![1]!.value = value;
|
||||
node.widgets![0]!.value = outputType;
|
||||
}
|
||||
|
||||
describe("TestPowerPuter", async () => {
|
||||
let powerPuter!: LGraphNode;
|
||||
let displayAny!: LGraphNode;
|
||||
|
||||
await beforeEach(async () => {
|
||||
await env.clear();
|
||||
powerPuter = await env.addNode(NodeTypesString.POWER_PUTER);
|
||||
displayAny = await env.addNode(NodeTypesString.DISPLAY_ANY);
|
||||
powerPuter.connect(0, displayAny, 0);
|
||||
await env.wait();
|
||||
});
|
||||
|
||||
await should("output constants and concatenation", async () => {
|
||||
const checks: Array<[string, string, string]> = [
|
||||
["1", "1", "STRING"],
|
||||
['"abc"', "abc", "STRING"],
|
||||
["1 + 2", "3", "STRING"],
|
||||
['"abc" + "xyz"', "abcxyz", "STRING"],
|
||||
// INT
|
||||
["1", "1", "INT"],
|
||||
["1 + 2", "3", "INT"],
|
||||
// FLOAT
|
||||
["1", "1.0", "FLOAT"],
|
||||
["1.3 + 2.8", "4.1", "FLOAT"],
|
||||
// BOOLEAN
|
||||
["1", "True", "BOOLEAN"],
|
||||
["1 - 1", "False", "BOOLEAN"],
|
||||
];
|
||||
for (const data of checks) {
|
||||
setPowerPuterValue(powerPuter, data[2], data[0]);
|
||||
await env.queuePrompt();
|
||||
expect(displayAny.widgets![0]!.value).toBe(data[0], data[1]);
|
||||
}
|
||||
});
|
||||
|
||||
await should("handle inputs", async () => {
|
||||
// TODO
|
||||
});
|
||||
|
||||
await should("handle complex inputs", async () => {
|
||||
// TODO
|
||||
});
|
||||
|
||||
await should("handle a for loop", async () => {
|
||||
setPowerPuterValue(
|
||||
powerPuter,
|
||||
"STRING",
|
||||
`
|
||||
a = 0
|
||||
b = ''
|
||||
for n in range(4):
|
||||
a += n
|
||||
for m in range(2):
|
||||
b += f'{str(n)}-{str(m)}.'
|
||||
f'a:{a} b:{b}'
|
||||
`,
|
||||
);
|
||||
await env.queuePrompt();
|
||||
expect(displayAny.widgets![0]!.value).toBe("a:6 b:0-0.0-1.1-0.1-1.2-0.2-1.3-0.3-1.");
|
||||
});
|
||||
|
||||
await should("handle assigning with a subscript slice", async () => {
|
||||
setPowerPuterValue(
|
||||
powerPuter,
|
||||
"STRING",
|
||||
`
|
||||
a = [1,2,0]
|
||||
a[a[2]] = 3
|
||||
tuple(a)
|
||||
`,
|
||||
);
|
||||
await env.queuePrompt();
|
||||
expect(displayAny.widgets![0]!.value).toBe("(3, 2, 0)");
|
||||
});
|
||||
|
||||
await should("handle aug assigning with a subscript slice", async () => {
|
||||
setPowerPuterValue(
|
||||
powerPuter,
|
||||
"STRING",
|
||||
`
|
||||
a = [1,2,0]
|
||||
a[a[2]] += 3
|
||||
tuple(a)
|
||||
`,
|
||||
);
|
||||
await env.queuePrompt();
|
||||
expect(displayAny.widgets![0]!.value).toBe("(4, 2, 0)");
|
||||
});
|
||||
|
||||
await should("disallow calls to some methods", async () => {
|
||||
const imageNode = await pasteImageToLoadImageNode(env);
|
||||
imageNode.connect(0, powerPuter, 0);
|
||||
setPowerPuterValue(
|
||||
powerPuter,
|
||||
"STRING",
|
||||
`a.numpy().tofile('/tmp/test')
|
||||
`,
|
||||
);
|
||||
await env.queuePrompt();
|
||||
|
||||
// Check to see if there's an error.
|
||||
expect(document.querySelector(".p-dialog-mask .p-card-body")!.textContent).toContain(
|
||||
"error message",
|
||||
"Disallowed access to \"tofile\" for type <class 'numpy.ndarray'>",
|
||||
);
|
||||
(document.querySelector(".p-dialog-mask .p-dialog-close-button")! as HTMLButtonElement).click();
|
||||
});
|
||||
|
||||
await should("handle boolean operators correctly", async () => {
|
||||
const checks: Array<[string, string, string, ('toMatchJson'|'toBe')?]> = [
|
||||
// And operator all success
|
||||
["1 and 42", "42", "STRING"],
|
||||
["True and [42]", "[42]", "STRING", "toMatchJson"],
|
||||
["a = 42\nTrue and [a]", "[42]", "STRING", "toMatchJson"],
|
||||
["1 and 3 and True and [1] and 42", "42", "STRING"],
|
||||
// And operator w/ a failure
|
||||
["1 and 3 and True and [] and 42", "[]", "STRING", "toMatchJson"],
|
||||
["1 and 0 and True and [] and 42", "0", "STRING"],
|
||||
["1 and 2 and False and [] and 42", "False", "STRING"],
|
||||
["b = None\n1 and 2 and True and b and 42", "None", "STRING"],
|
||||
// Or operator
|
||||
["1 or 42", "1", "STRING"],
|
||||
["0 or 42", "42", "STRING"],
|
||||
["0 or None or False or [] or 42", "42", "STRING"],
|
||||
["b=42\n0 or None or False or [] or b", "42", "STRING"],
|
||||
["b=42\n0 or None or False or [b] or b", "[42]", "STRING", "toMatchJson"],
|
||||
["b=42\n0 or None or True or [b] or b", "True", "STRING"],
|
||||
// Mix
|
||||
["1 and 2 and 0 or 5", "5", "STRING"],
|
||||
["None and 1 or True", "True", "STRING"],
|
||||
["0 or False and True", "False", "STRING"],
|
||||
|
||||
];
|
||||
for (const data of checks) {
|
||||
setPowerPuterValue(powerPuter, data[2], data[0]);
|
||||
await env.queuePrompt();
|
||||
expect(displayAny.widgets![0]!.value)[data[3] || 'toBe'](data[0], data[1]);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user