forked from sashin/sashinexists
run npm install to generate a package lock
This commit is contained in:
68
node_modules/@weborigami/language/test/runtime/EventTargetMixin.test.js
generated
vendored
Normal file
68
node_modules/@weborigami/language/test/runtime/EventTargetMixin.test.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import EventTargetMixin from "../../src/runtime/EventTargetMixin.js";
|
||||
|
||||
class EventTargetTest extends EventTargetMixin(Object) {}
|
||||
|
||||
describe("EventTargetMixin", () => {
|
||||
test("add and dispatch event", () => {
|
||||
const fixture = new EventTargetTest();
|
||||
const event = new Event("test");
|
||||
let callCount = 0;
|
||||
const callback = () => {
|
||||
callCount++;
|
||||
};
|
||||
fixture.addEventListener("test", callback);
|
||||
// Add twice, ensure that the callback is only called once.
|
||||
fixture.addEventListener("test", callback);
|
||||
const dispatched = fixture.dispatchEvent(event);
|
||||
assert(dispatched);
|
||||
assert.equal(callCount, 1);
|
||||
});
|
||||
|
||||
test("dispatch event with no listeners", () => {
|
||||
const fixture = new EventTargetTest();
|
||||
const event = new Event("test");
|
||||
const takeDefaultAction = fixture.dispatchEvent(event);
|
||||
assert(takeDefaultAction);
|
||||
});
|
||||
|
||||
test("remove event listener", () => {
|
||||
const fixture = new EventTargetTest();
|
||||
const event = new Event("test");
|
||||
let callCount = 0;
|
||||
const callback = () => {
|
||||
callCount++;
|
||||
};
|
||||
fixture.addEventListener("test", callback);
|
||||
fixture.removeEventListener("test", callback);
|
||||
fixture.dispatchEvent(event);
|
||||
assert.equal(callCount, 0);
|
||||
});
|
||||
|
||||
test("stop immediate propagation", () => {
|
||||
const fixture = new EventTargetTest();
|
||||
const event = new Event("test");
|
||||
let callCount = 0;
|
||||
fixture.addEventListener("test", (event) => {
|
||||
callCount++;
|
||||
event.stopImmediatePropagation();
|
||||
});
|
||||
fixture.addEventListener("test", () => {
|
||||
callCount++;
|
||||
});
|
||||
fixture.dispatchEvent(event);
|
||||
assert.equal(callCount, 1);
|
||||
});
|
||||
|
||||
test("prevent default", () => {
|
||||
const fixture = new EventTargetTest();
|
||||
const event = new Event("test");
|
||||
fixture.addEventListener("test", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
const takeDefaultAction = fixture.dispatchEvent(event);
|
||||
assert(!takeDefaultAction);
|
||||
assert(event.defaultPrevented);
|
||||
});
|
||||
});
|
||||
37
node_modules/@weborigami/language/test/runtime/OrigamiFiles.test.js
generated
vendored
Normal file
37
node_modules/@weborigami/language/test/runtime/OrigamiFiles.test.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import assert from "node:assert";
|
||||
import * as fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import OrigamiFiles from "../../src/runtime/OrigamiFiles.js";
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const tempDirectory = path.join(dirname, "fixtures/temp");
|
||||
|
||||
describe("OrigamiFiles", () => {
|
||||
test("can watch its folder for changes", { timeout: 2000 }, async () => {
|
||||
await createTempDirectory();
|
||||
const tempFiles = new OrigamiFiles(tempDirectory);
|
||||
const changedFileName = await new Promise(async (resolve) => {
|
||||
// @ts-ignore
|
||||
tempFiles.addEventListener("change", (event) => {
|
||||
resolve(/** @type {any} */ (event).options.key);
|
||||
});
|
||||
// @ts-ignore
|
||||
await tempFiles.set(
|
||||
"foo.txt",
|
||||
"This file is left over from testing and can be removed."
|
||||
);
|
||||
});
|
||||
await removeTempDirectory();
|
||||
assert.equal(changedFileName, "foo.txt");
|
||||
});
|
||||
});
|
||||
|
||||
async function createTempDirectory() {
|
||||
await fs.mkdir(tempDirectory, { recursive: true });
|
||||
}
|
||||
|
||||
async function removeTempDirectory() {
|
||||
await fs.rm(tempDirectory, { recursive: true });
|
||||
}
|
||||
85
node_modules/@weborigami/language/test/runtime/evaluate.test.js
generated
vendored
Normal file
85
node_modules/@weborigami/language/test/runtime/evaluate.test.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import { ObjectTree } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import * as ops from "../../src/runtime/ops.js";
|
||||
|
||||
import evaluate from "../../src/runtime/evaluate.js";
|
||||
|
||||
describe("evaluate", () => {
|
||||
test("can retrieve values from scope", async () => {
|
||||
const code = createCode([ops.scope, "message"]);
|
||||
const parent = new ObjectTree({
|
||||
message: "Hello",
|
||||
});
|
||||
const tree = new ObjectTree({});
|
||||
tree.parent = parent;
|
||||
const result = await evaluate.call(tree, code);
|
||||
assert.equal(result, "Hello");
|
||||
});
|
||||
|
||||
test("can invoke functions in scope", async () => {
|
||||
// Match the array representation of code generated by the parser.
|
||||
const code = createCode([
|
||||
[ops.scope, "greet"],
|
||||
[ops.scope, "name"],
|
||||
]);
|
||||
|
||||
const tree = new ObjectTree({
|
||||
async greet(name) {
|
||||
return `Hello ${name}`;
|
||||
},
|
||||
name: "world",
|
||||
});
|
||||
|
||||
const result = await evaluate.call(tree, code);
|
||||
assert.equal(result, "Hello world");
|
||||
});
|
||||
|
||||
test("passes context to invoked functions", async () => {
|
||||
const code = createCode([ops.scope, "fn"]);
|
||||
const tree = new ObjectTree({
|
||||
async fn() {
|
||||
assert.equal(this, tree);
|
||||
},
|
||||
});
|
||||
await evaluate.call(tree, code);
|
||||
});
|
||||
|
||||
test("evaluates a function with fixed number of arguments", async () => {
|
||||
const fn = (x, y) => ({
|
||||
c: `${x}${y}c`,
|
||||
});
|
||||
const code = createCode([ops.traverse, fn, "a", "b", "c"]);
|
||||
assert.equal(await evaluate.call(null, code), "abc");
|
||||
});
|
||||
|
||||
test("if object in function position isn't a function, can unpack it", async () => {
|
||||
const fn = (...args) => args.join(",");
|
||||
const packed = new String();
|
||||
/** @type {any} */ (packed).unpack = async () => fn;
|
||||
const code = createCode([packed, "a", "b", "c"]);
|
||||
const result = await evaluate.call(null, code);
|
||||
assert.equal(result, "a,b,c");
|
||||
});
|
||||
|
||||
test("by defalut sets the parent of a returned tree to the current tree", async () => {
|
||||
const fn = () => new ObjectTree({});
|
||||
const code = createCode([fn]);
|
||||
const tree = new ObjectTree({});
|
||||
const result = await evaluate.call(tree, code);
|
||||
assert.equal(result.parent, tree);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @returns {import("../../index.ts").Code}
|
||||
*/
|
||||
function createCode(array) {
|
||||
const code = array;
|
||||
/** @type {any} */ (code).location = {
|
||||
source: {
|
||||
text: "",
|
||||
},
|
||||
};
|
||||
return code;
|
||||
}
|
||||
76
node_modules/@weborigami/language/test/runtime/expressionObject.test.js
generated
vendored
Normal file
76
node_modules/@weborigami/language/test/runtime/expressionObject.test.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import { ObjectTree, symbols, Tree } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
|
||||
import expressionObject from "../../src/runtime/expressionObject.js";
|
||||
import { ops } from "../../src/runtime/internal.js";
|
||||
|
||||
describe("expressionObject", () => {
|
||||
test("can instantiate an object", async () => {
|
||||
const scope = new ObjectTree({
|
||||
upper: (s) => s.toUpperCase(),
|
||||
});
|
||||
|
||||
const entries = [
|
||||
["hello", [[ops.scope, "upper"], "hello"]],
|
||||
["world", [[ops.scope, "upper"], "world"]],
|
||||
];
|
||||
|
||||
const object = await expressionObject(entries, scope);
|
||||
assert.equal(await object.hello, "HELLO");
|
||||
assert.equal(await object.world, "WORLD");
|
||||
assert.equal(object[symbols.parent], scope);
|
||||
});
|
||||
|
||||
test("can define a property getter", async () => {
|
||||
let count = 0;
|
||||
const increment = () => count++;
|
||||
const entries = [["count", [ops.getter, [increment]]]];
|
||||
const object = await expressionObject(entries, null);
|
||||
assert.equal(await object.count, 0);
|
||||
assert.equal(await object.count, 1);
|
||||
});
|
||||
|
||||
test("treats a getter for a primitive value as a regular property", async () => {
|
||||
const entries = [["name", [ops.getter, "world"]]];
|
||||
const object = await expressionObject(entries, null);
|
||||
assert.equal(object.name, "world");
|
||||
});
|
||||
|
||||
test("can instantiate an Origami tree", async () => {
|
||||
const entries = [
|
||||
["name", "world"],
|
||||
["message", [ops.concat, "Hello, ", [ops.scope, "name"], "!"]],
|
||||
];
|
||||
const parent = new ObjectTree({});
|
||||
const object = await expressionObject(entries, parent);
|
||||
assert.deepEqual(await Tree.plain(object), {
|
||||
name: "world",
|
||||
message: "Hello, world!",
|
||||
});
|
||||
assert.equal(object[symbols.parent], parent);
|
||||
});
|
||||
|
||||
test("returned object values can be unpacked", async () => {
|
||||
const entries = [["data.json", `{ "a": 1 }`]];
|
||||
const parent = new ObjectTree({
|
||||
"json.handler": {
|
||||
unpack: JSON.parse,
|
||||
},
|
||||
});
|
||||
const result = await expressionObject(entries, parent);
|
||||
const dataJson = await result["data.json"];
|
||||
const json = await dataJson.unpack();
|
||||
assert.deepEqual(json, { a: 1 });
|
||||
});
|
||||
|
||||
test("a key declared with parentheses is not enumerable", async () => {
|
||||
const entries = [
|
||||
["(hidden)", "shh"],
|
||||
["visible", "hey"],
|
||||
];
|
||||
const object = await expressionObject(entries, null);
|
||||
assert.deepEqual(Object.keys(object), ["visible"]);
|
||||
assert.equal(object["hidden"], "shh");
|
||||
});
|
||||
});
|
||||
1
node_modules/@weborigami/language/test/runtime/fixtures/foo.js
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/foo.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default () => "bar";
|
||||
1
node_modules/@weborigami/language/test/runtime/fixtures/makeTest/a
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/makeTest/a
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Hello, world.
|
||||
0
node_modules/@weborigami/language/test/runtime/fixtures/makeTest/b = a
generated
vendored
Normal file
0
node_modules/@weborigami/language/test/runtime/fixtures/makeTest/b = a
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/foo.txt
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/foo.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Foo
|
||||
3
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/greeting = this('world').js
generated
vendored
Normal file
3
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/greeting = this('world').js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function (name) {
|
||||
return `Hello, ${name}.`;
|
||||
}
|
||||
5
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/obj = this.json
generated
vendored
Normal file
5
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/obj = this.json
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"a": "Hello, a.",
|
||||
"b": "Hello, b.",
|
||||
"c": "Hello, c."
|
||||
}
|
||||
3
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/sample.txt = this().js
generated
vendored
Normal file
3
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/sample.txt = this().js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function () {
|
||||
return "Hello, world.";
|
||||
}
|
||||
1
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/string = this.json
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/string = this.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"Hello, world."
|
||||
0
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/value = fn()
generated
vendored
Normal file
0
node_modules/@weborigami/language/test/runtime/fixtures/metagraphs/value = fn()
generated
vendored
Normal file
5
node_modules/@weborigami/language/test/runtime/fixtures/subgraph = this.js
generated
vendored
Normal file
5
node_modules/@weborigami/language/test/runtime/fixtures/subgraph = this.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { ObjectTree } from "@weborigami/async-tree";
|
||||
export default new ObjectTree({
|
||||
a: "Hello, a.",
|
||||
b: "Hello, b.",
|
||||
});
|
||||
4
node_modules/@weborigami/language/test/runtime/fixtures/templates/greet.orit
generated
vendored
Normal file
4
node_modules/@weborigami/language/test/runtime/fixtures/templates/greet.orit
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
Greetings:
|
||||
|
||||
{{ map(=`Hello, {{ _ }}.
|
||||
`)(names.yaml) }}
|
||||
15
node_modules/@weborigami/language/test/runtime/fixtures/templates/index.orit
generated
vendored
Normal file
15
node_modules/@weborigami/language/test/runtime/fixtures/templates/index.orit
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Greetings
|
||||
message: !ori title
|
||||
---
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>{{ title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{ message }}
|
||||
</body>
|
||||
</html>
|
||||
3
node_modules/@weborigami/language/test/runtime/fixtures/templates/names.yaml
generated
vendored
Normal file
3
node_modules/@weborigami/language/test/runtime/fixtures/templates/names.yaml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
- Alice
|
||||
- Bob
|
||||
- Carol
|
||||
1
node_modules/@weborigami/language/test/runtime/fixtures/templates/plain.txt
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/templates/plain.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Hello, world.
|
||||
1
node_modules/@weborigami/language/test/runtime/fixtures/virtualKeys/.keys.json
generated
vendored
Normal file
1
node_modules/@weborigami/language/test/runtime/fixtures/virtualKeys/.keys.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
["a", "b", "c"]
|
||||
24
node_modules/@weborigami/language/test/runtime/functionResultsMap.test.js
generated
vendored
Normal file
24
node_modules/@weborigami/language/test/runtime/functionResultsMap.test.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ObjectTree, Tree, scope } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import functionResultsMap from "../../src/runtime/functionResultsMap.js";
|
||||
|
||||
describe("functionResultsMap", () => {
|
||||
test("get() invokes functions using scope, returns other values as is", async () => {
|
||||
const parent = new ObjectTree({
|
||||
message: "Hello",
|
||||
});
|
||||
const tree = new ObjectTree({
|
||||
fn: /** @this {import("@weborigami/types").AsyncTree} */ function () {
|
||||
return scope(this).get("message");
|
||||
},
|
||||
string: "string",
|
||||
});
|
||||
tree.parent = parent;
|
||||
const fixture = functionResultsMap(tree);
|
||||
assert.deepEqual(await Tree.plain(fixture), {
|
||||
fn: "Hello",
|
||||
string: "string",
|
||||
});
|
||||
});
|
||||
});
|
||||
39
node_modules/@weborigami/language/test/runtime/handlers.test.js
generated
vendored
Normal file
39
node_modules/@weborigami/language/test/runtime/handlers.test.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { ObjectTree } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import { handleExtension } from "../../src/runtime/handlers.js";
|
||||
|
||||
describe("handlers", () => {
|
||||
test("attaches an unpack method to a value with an extension", async () => {
|
||||
const fixture = createFixture();
|
||||
const numberValue = await fixture.get("foo");
|
||||
assert(typeof numberValue === "number");
|
||||
assert.equal(numberValue, 1);
|
||||
const jsonFile = await fixture.get("bar.json");
|
||||
const withHandler = await handleExtension(fixture, jsonFile, "bar.json");
|
||||
assert.equal(String(withHandler), `{ "bar": 2 }`);
|
||||
const data = await withHandler.unpack();
|
||||
assert.deepEqual(data, { bar: 2 });
|
||||
});
|
||||
|
||||
test("immediately unpacks if key ends in slash", async () => {
|
||||
const fixture = createFixture();
|
||||
const jsonFile = await fixture.get("bar.json");
|
||||
const data = await handleExtension(fixture, jsonFile, "bar.json/");
|
||||
assert.deepEqual(data, { bar: 2 });
|
||||
});
|
||||
});
|
||||
|
||||
function createFixture() {
|
||||
const parent = new ObjectTree({
|
||||
"json.handler": {
|
||||
unpack: (buffer) => JSON.parse(String(buffer)),
|
||||
},
|
||||
});
|
||||
let tree = new ObjectTree({
|
||||
foo: 1, // No extension, should be left alone
|
||||
"bar.json": `{ "bar": 2 }`,
|
||||
});
|
||||
tree.parent = parent;
|
||||
return tree;
|
||||
}
|
||||
50
node_modules/@weborigami/language/test/runtime/mergeTrees.test.js
generated
vendored
Normal file
50
node_modules/@weborigami/language/test/runtime/mergeTrees.test.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Tree } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import mergeTrees from "../../src/runtime/mergeTrees.js";
|
||||
|
||||
describe("mergeTrees", () => {
|
||||
test("merges trees", async () => {
|
||||
const tree = await mergeTrees.call(
|
||||
null,
|
||||
{
|
||||
a: 1,
|
||||
b: 2,
|
||||
},
|
||||
{
|
||||
b: 3,
|
||||
c: 4,
|
||||
}
|
||||
);
|
||||
// @ts-ignore
|
||||
assert.deepEqual(await Tree.plain(tree), {
|
||||
a: 1,
|
||||
b: 3,
|
||||
c: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test("if all arguments are plain objects, result is a plain object", async () => {
|
||||
const result = await mergeTrees.call(
|
||||
null,
|
||||
{
|
||||
a: 1,
|
||||
b: 2,
|
||||
},
|
||||
{
|
||||
b: 3,
|
||||
c: 4,
|
||||
}
|
||||
);
|
||||
assert.deepEqual(result, {
|
||||
a: 1,
|
||||
b: 3,
|
||||
c: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test("if all arguments are arrays, result is an array", async () => {
|
||||
const result = await mergeTrees.call(null, [1, 2], [3, 4]);
|
||||
assert.deepEqual(result, [1, 2, 3, 4]);
|
||||
});
|
||||
});
|
||||
358
node_modules/@weborigami/language/test/runtime/ops.test.js
generated
vendored
Normal file
358
node_modules/@weborigami/language/test/runtime/ops.test.js
generated
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
import { ObjectTree } from "@weborigami/async-tree";
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
|
||||
import { evaluate, ops } from "../../src/runtime/internal.js";
|
||||
|
||||
describe("ops", () => {
|
||||
test("ops.addition adds two numbers", async () => {
|
||||
assert.strictEqual(ops.addition(2, 2), 4);
|
||||
assert.strictEqual(ops.addition(2, true), 3);
|
||||
});
|
||||
|
||||
test("ops.addition concatenates two strings", async () => {
|
||||
assert.strictEqual(ops.addition("hello ", "everyone"), "hello everyone");
|
||||
assert.strictEqual(
|
||||
ops.addition("2001", ": A Space Odyssey"),
|
||||
"2001: A Space Odyssey"
|
||||
);
|
||||
});
|
||||
|
||||
test("ops.array creates an array", async () => {
|
||||
const code = createCode([ops.array, 1, 2, 3]);
|
||||
const result = await evaluate.call(null, code);
|
||||
assert.deepEqual(result, [1, 2, 3]);
|
||||
});
|
||||
|
||||
test("ops.bitwiseAnd", () => {
|
||||
assert.strictEqual(ops.bitwiseAnd(5, 3), 1);
|
||||
});
|
||||
|
||||
test("ops.bitwiseNot", () => {
|
||||
assert.strictEqual(ops.bitwiseNot(5), -6);
|
||||
assert.strictEqual(ops.bitwiseNot(-3), 2);
|
||||
});
|
||||
|
||||
test("ops.bitwiseOr", () => {
|
||||
assert.strictEqual(ops.bitwiseOr(5, 3), 7);
|
||||
});
|
||||
|
||||
test("ops.bitwiseXor", () => {
|
||||
assert.strictEqual(ops.bitwiseXor(5, 3), 6);
|
||||
});
|
||||
|
||||
test("ops.builtin gets a value from the top of the scope chain", async () => {
|
||||
const root = new ObjectTree({
|
||||
a: 1,
|
||||
});
|
||||
const tree = new ObjectTree({});
|
||||
tree.parent = root;
|
||||
const code = createCode([ops.builtin, "a"]);
|
||||
const result = await evaluate.call(tree, code);
|
||||
assert.strictEqual(result, 1);
|
||||
});
|
||||
|
||||
test("ops.comma returns the last value", async () => {
|
||||
const code = createCode([ops.comma, 1, 2, 3]);
|
||||
const result = await evaluate.call(null, code);
|
||||
assert.strictEqual(result, 3);
|
||||
});
|
||||
|
||||
test("ops.concat concatenates tree value text", async () => {
|
||||
const scope = new ObjectTree({
|
||||
name: "world",
|
||||
});
|
||||
|
||||
const code = createCode([ops.concat, "Hello, ", [ops.scope, "name"], "."]);
|
||||
|
||||
const result = await evaluate.call(scope, code);
|
||||
assert.strictEqual(result, "Hello, world.");
|
||||
});
|
||||
|
||||
test("ops.conditional", async () => {
|
||||
assert.strictEqual(await ops.conditional(true, trueFn, falseFn), true);
|
||||
assert.strictEqual(await ops.conditional(true, falseFn, trueFn), false);
|
||||
assert.strictEqual(await ops.conditional(false, trueFn, falseFn), false);
|
||||
assert.strictEqual(await ops.conditional(false, falseFn, trueFn), true);
|
||||
|
||||
// Short-circuiting
|
||||
assert.strictEqual(await ops.conditional(false, errorFn, trueFn), true);
|
||||
});
|
||||
|
||||
test("ops.division divides two numbers", async () => {
|
||||
assert.strictEqual(ops.division(12, 2), 6);
|
||||
assert.strictEqual(ops.division(3, 2), 1.5);
|
||||
assert.strictEqual(ops.division(6, "3"), 2);
|
||||
assert.strictEqual(ops.division(2, 0), Infinity);
|
||||
});
|
||||
|
||||
test("ops.equal", () => {
|
||||
assert(ops.equal(1, 1));
|
||||
assert(!ops.equal(1, 2));
|
||||
assert(ops.equal("1", 1));
|
||||
assert(ops.equal("1", "1"));
|
||||
assert(ops.equal(null, undefined));
|
||||
});
|
||||
|
||||
test("ops.exponentiation", () => {
|
||||
assert.strictEqual(ops.exponentiation(2, 3), 8);
|
||||
assert.strictEqual(ops.exponentiation(2, 0), 1);
|
||||
});
|
||||
|
||||
test("ops.external looks up a value in scope and memoizes it", async () => {
|
||||
let count = 0;
|
||||
const tree = new ObjectTree({
|
||||
get count() {
|
||||
return ++count;
|
||||
},
|
||||
});
|
||||
const code = createCode([ops.external, "count", {}]);
|
||||
const result = await evaluate.call(tree, code);
|
||||
assert.strictEqual(result, 1);
|
||||
const result2 = await evaluate.call(tree, code);
|
||||
assert.strictEqual(result2, 1);
|
||||
});
|
||||
|
||||
test("ops.greaterThan", () => {
|
||||
assert(ops.greaterThan(5, 3));
|
||||
assert(!ops.greaterThan(3, 3));
|
||||
assert(ops.greaterThan("ab", "aa"));
|
||||
});
|
||||
|
||||
test("ops.greaterThanOrEqual", () => {
|
||||
assert(ops.greaterThanOrEqual(5, 3));
|
||||
assert(ops.greaterThanOrEqual(3, 3));
|
||||
assert(ops.greaterThanOrEqual("ab", "aa"));
|
||||
});
|
||||
|
||||
test("ops.inherited searches inherited scope", async () => {
|
||||
const parent = new ObjectTree({
|
||||
a: 1, // This is the inherited value we want
|
||||
});
|
||||
/** @type {any} */
|
||||
const child = new ObjectTree({
|
||||
a: 2, // Should be ignored
|
||||
});
|
||||
child.parent = parent;
|
||||
const code = createCode([ops.inherited, "a"]);
|
||||
const result = await evaluate.call(child, code);
|
||||
assert.strictEqual(result, 1);
|
||||
});
|
||||
|
||||
test("ops.lambda defines a function with no inputs", async () => {
|
||||
const code = createCode([ops.lambda, [], [ops.literal, "result"]]);
|
||||
const fn = await evaluate.call(null, code);
|
||||
const result = await fn.call();
|
||||
assert.strictEqual(result, "result");
|
||||
});
|
||||
|
||||
test("ops.lambda defines a function with underscore input", async () => {
|
||||
const scope = new ObjectTree({
|
||||
message: "Hello",
|
||||
});
|
||||
|
||||
const code = createCode([ops.lambda, ["_"], [ops.scope, "message"]]);
|
||||
|
||||
const fn = await evaluate.call(scope, code);
|
||||
const result = await fn.call(scope);
|
||||
assert.strictEqual(result, "Hello");
|
||||
});
|
||||
|
||||
test("ops.lambda adds input parameters to scope", async () => {
|
||||
const code = createCode([
|
||||
ops.lambda,
|
||||
["a", "b"],
|
||||
[ops.concat, [ops.scope, "b"], [ops.scope, "a"]],
|
||||
]);
|
||||
const fn = await evaluate.call(null, code);
|
||||
const result = await fn("x", "y");
|
||||
assert.strictEqual(result, "yx");
|
||||
});
|
||||
|
||||
test("ops.lessThan", () => {
|
||||
assert(!ops.lessThan(5, 3));
|
||||
assert(!ops.lessThan(3, 3));
|
||||
assert(ops.lessThan("aa", "ab"));
|
||||
});
|
||||
|
||||
test("ops.lessThanOrEqual", () => {
|
||||
assert(!ops.lessThanOrEqual(5, 3));
|
||||
assert(ops.lessThanOrEqual(3, 3));
|
||||
assert(ops.lessThanOrEqual("aa", "ab"));
|
||||
});
|
||||
|
||||
test("ops.logicalAnd", async () => {
|
||||
assert.strictEqual(await ops.logicalAnd(true, trueFn), true);
|
||||
assert.strictEqual(await ops.logicalAnd(true, falseFn), false);
|
||||
assert.strictEqual(await ops.logicalAnd(false, trueFn), false);
|
||||
assert.strictEqual(await ops.logicalAnd(false, falseFn), false);
|
||||
|
||||
assert.strictEqual(await ops.logicalAnd(true, "hi"), "hi");
|
||||
|
||||
// Short-circuiting
|
||||
assert.strictEqual(await ops.logicalAnd(false, errorFn), false);
|
||||
assert.strictEqual(await ops.logicalAnd(0, true), 0);
|
||||
});
|
||||
|
||||
test("ops.logicalNot", async () => {
|
||||
assert.strictEqual(await ops.logicalNot(true), false);
|
||||
assert.strictEqual(await ops.logicalNot(false), true);
|
||||
assert.strictEqual(await ops.logicalNot(0), true);
|
||||
assert.strictEqual(await ops.logicalNot(1), false);
|
||||
});
|
||||
|
||||
test("ops.logicalOr", async () => {
|
||||
assert.strictEqual(await ops.logicalOr(true, trueFn), true);
|
||||
assert.strictEqual(await ops.logicalOr(true, falseFn), true);
|
||||
assert.strictEqual(await ops.logicalOr(false, trueFn), true);
|
||||
assert.strictEqual(await ops.logicalOr(false, falseFn), false);
|
||||
|
||||
assert.strictEqual(await ops.logicalOr(false, "hi"), "hi");
|
||||
|
||||
// Short-circuiting
|
||||
assert.strictEqual(await ops.logicalOr(true, errorFn), true);
|
||||
});
|
||||
|
||||
test("ops.multiplication multiplies two numbers", async () => {
|
||||
assert.strictEqual(ops.multiplication(3, 4), 12);
|
||||
assert.strictEqual(ops.multiplication(-3, 4), -12);
|
||||
assert.strictEqual(ops.multiplication("3", 2), 6);
|
||||
assert.strictEqual(ops.multiplication("foo", 2), NaN);
|
||||
});
|
||||
|
||||
test("ops.notEqual", () => {
|
||||
assert(!ops.notEqual(1, 1));
|
||||
assert(ops.notEqual(1, 2));
|
||||
assert(!ops.notEqual("1", 1));
|
||||
assert(!ops.notEqual("1", "1"));
|
||||
assert(!ops.notEqual(null, undefined));
|
||||
});
|
||||
|
||||
test("ops.notStrictEqual", () => {
|
||||
assert(!ops.notStrictEqual(1, 1));
|
||||
assert(ops.notStrictEqual(1, 2));
|
||||
assert(ops.notStrictEqual("1", 1));
|
||||
assert(!ops.notStrictEqual("1", "1"));
|
||||
assert(ops.notStrictEqual(null, undefined));
|
||||
});
|
||||
|
||||
test("ops.nullishCoalescing", async () => {
|
||||
assert.strictEqual(await ops.nullishCoalescing(1, falseFn), 1);
|
||||
assert.strictEqual(await ops.nullishCoalescing(null, trueFn), true);
|
||||
assert.strictEqual(await ops.nullishCoalescing(undefined, trueFn), true);
|
||||
|
||||
// Short-circuiting
|
||||
assert.strictEqual(await ops.nullishCoalescing(1, errorFn), 1);
|
||||
});
|
||||
|
||||
test("ops.object instantiates an object", async () => {
|
||||
const scope = new ObjectTree({
|
||||
upper: (s) => s.toUpperCase(),
|
||||
});
|
||||
|
||||
const code = createCode([
|
||||
ops.object,
|
||||
["hello", [[ops.scope, "upper"], "hello"]],
|
||||
["world", [[ops.scope, "upper"], "world"]],
|
||||
]);
|
||||
|
||||
const result = await evaluate.call(scope, code);
|
||||
assert.strictEqual(result.hello, "HELLO");
|
||||
assert.strictEqual(result.world, "WORLD");
|
||||
});
|
||||
|
||||
test("ops.object instantiates an array", async () => {
|
||||
const scope = new ObjectTree({
|
||||
upper: (s) => s.toUpperCase(),
|
||||
});
|
||||
const code = createCode([
|
||||
ops.array,
|
||||
"Hello",
|
||||
1,
|
||||
[[ops.scope, "upper"], "world"],
|
||||
]);
|
||||
const result = await evaluate.call(scope, code);
|
||||
assert.deepEqual(result, ["Hello", 1, "WORLD"]);
|
||||
});
|
||||
|
||||
test("ops.remainder calculates the remainder of two numbers", async () => {
|
||||
assert.strictEqual(ops.remainder(13, 5), 3);
|
||||
assert.strictEqual(ops.remainder(-13, 5), -3);
|
||||
assert.strictEqual(ops.remainder(4, 2), 0);
|
||||
assert.strictEqual(ops.remainder(-4, 2), -0);
|
||||
});
|
||||
|
||||
test("ops.shiftLeft", () => {
|
||||
assert.strictEqual(ops.shiftLeft(5, 2), 20);
|
||||
});
|
||||
|
||||
test("ops.shiftRightSigned", () => {
|
||||
assert.strictEqual(ops.shiftRightSigned(20, 2), 5);
|
||||
assert.strictEqual(ops.shiftRightSigned(-20, 2), -5);
|
||||
});
|
||||
|
||||
test("ops.shiftRightUnsigned", () => {
|
||||
assert.strictEqual(ops.shiftRightUnsigned(20, 2), 5);
|
||||
assert.strictEqual(ops.shiftRightUnsigned(-5, 2), 1073741822);
|
||||
});
|
||||
|
||||
test("ops.strictEqual", () => {
|
||||
assert(ops.strictEqual(1, 1));
|
||||
assert(!ops.strictEqual(1, 2));
|
||||
assert(!ops.strictEqual("1", 1));
|
||||
assert(ops.strictEqual("1", "1"));
|
||||
assert(!ops.strictEqual(null, undefined));
|
||||
assert(ops.strictEqual(null, null));
|
||||
assert(ops.strictEqual(undefined, undefined));
|
||||
});
|
||||
|
||||
test("ops.subtraction subtracts two numbers", async () => {
|
||||
assert.strictEqual(ops.subtraction(5, 3), 2);
|
||||
assert.strictEqual(ops.subtraction(3.5, 5), -1.5);
|
||||
assert.strictEqual(ops.subtraction(5, "hello"), NaN);
|
||||
assert.strictEqual(ops.subtraction(5, true), 4);
|
||||
});
|
||||
|
||||
test("ops.unaryMinus", () => {
|
||||
assert.strictEqual(ops.unaryMinus(4), -4);
|
||||
assert.strictEqual(ops.unaryMinus(-4), 4);
|
||||
});
|
||||
|
||||
test("ops.unaryPlus", () => {
|
||||
assert.strictEqual(ops.unaryPlus(1), 1);
|
||||
assert.strictEqual(ops.unaryPlus(-1), -1);
|
||||
assert.strictEqual(ops.unaryPlus(""), 0);
|
||||
});
|
||||
|
||||
test("ops.unpack unpacks a value", async () => {
|
||||
const fixture = new String("packed");
|
||||
/** @type {any} */ (fixture).unpack = async () => "unpacked";
|
||||
const result = await ops.unpack.call(null, fixture);
|
||||
assert.strictEqual(result, "unpacked");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @returns {import("../../index.ts").Code}
|
||||
*/
|
||||
function createCode(array) {
|
||||
const code = array;
|
||||
/** @type {any} */ (code).location = {
|
||||
source: {
|
||||
text: "",
|
||||
},
|
||||
};
|
||||
return code;
|
||||
}
|
||||
|
||||
function errorFn() {
|
||||
throw new Error("This should not be called");
|
||||
}
|
||||
|
||||
function falseFn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function trueFn() {
|
||||
return true;
|
||||
}
|
||||
10
node_modules/@weborigami/language/test/runtime/taggedTemplate.test.js
generated
vendored
Normal file
10
node_modules/@weborigami/language/test/runtime/taggedTemplate.test.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import taggedTemplate from "../../src/runtime/taggedTemplate.js";
|
||||
|
||||
describe("taggedTemplate", () => {
|
||||
test("joins strings and values together", () => {
|
||||
const result = taggedTemplate`a ${"b"} c`;
|
||||
assert.equal(result, "a b c");
|
||||
});
|
||||
});
|
||||
21
node_modules/@weborigami/language/test/runtime/typos.test.js
generated
vendored
Normal file
21
node_modules/@weborigami/language/test/runtime/typos.test.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import { isTypo, typos } from "../../src/runtime/typos.js";
|
||||
|
||||
describe("typos", () => {
|
||||
test("isTypo", () => {
|
||||
assert(isTypo("cat", "bat")); // substitution
|
||||
assert(isTypo("cat", "cats")); // insertion
|
||||
assert(isTypo("cat", "cast")); // insertion
|
||||
assert(isTypo("cat", "at")); // deletion
|
||||
assert(isTypo("cat", "ca")); // deletion
|
||||
assert(isTypo("cat", "cta")); // transposition
|
||||
assert(isTypo("cat", "act")); // transposition
|
||||
assert(!isTypo("cat", "dog")); // more than 1 edit
|
||||
});
|
||||
|
||||
test("typos", () => {
|
||||
const result = typos("cas", ["ask", "cat", "cast", "cats", "cart"]);
|
||||
assert.deepEqual(result, ["cat", "cast", "cats"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user