|
@@ -0,0 +1,83 @@
|
|
|
|
+import { describe, it, expect } from "vitest";
|
|
|
|
+import { Mixins } from "./Mixins.js";
|
|
|
|
+
|
|
|
|
+describe("Mixins", () => {
|
|
|
|
+ it("Base resolution", () => {
|
|
|
|
+ const mixins = new Mixins<{
|
|
|
|
+ foo: (v: number, ctx: { a: number }) => number;
|
|
|
|
+ }>({ autoIncrementPriority: true });
|
|
|
|
+
|
|
|
|
+ mixins.add("foo", (v) => v ^ 0b0001); // 1 (prio 0)
|
|
|
|
+ mixins.add("foo", (v) => v ^ 0b1000); // 2 (prio 1)
|
|
|
|
+ mixins.add("foo", (v, c) => v ^ c.a); // 3 (prio 2)
|
|
|
|
+
|
|
|
|
+ // input: 0b1100
|
|
|
|
+ // 1: 0b1100 ^ 0b0001 = 0b1101
|
|
|
|
+ // 2: 0b1101 ^ 0b1000 = 0b0101
|
|
|
|
+ // 3: 0b0101 ^ 0b0100 = 0b0001
|
|
|
|
+ // result: 0b0001 = 1
|
|
|
|
+
|
|
|
|
+ expect(mixins.resolve("foo", 0b1100, { a: 0b0100 })).toBe(1);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it("Priority resolution", () => {
|
|
|
|
+ const mixins = new Mixins<{
|
|
|
|
+ foo: (v: number) => number;
|
|
|
|
+ }>();
|
|
|
|
+
|
|
|
|
+ mixins.add("foo", (v) => v / 2, 1); // 2 (prio 1)
|
|
|
|
+ mixins.add("foo", (v) => Math.round(Math.log(v) * 10), -1); // 4 (prio -1)
|
|
|
|
+ mixins.add("foo", (v) => Math.pow(v, 2)); // 3 (prio 0)
|
|
|
|
+ mixins.add("foo", (v) => Math.sqrt(v), Number.MAX_SAFE_INTEGER); // 1 (prio max)
|
|
|
|
+
|
|
|
|
+ // input: 100
|
|
|
|
+ // 1: sqrt(100) = 10
|
|
|
|
+ // 2: 10 / 2 = 5
|
|
|
|
+ // 3: 5 ^ 2 = 25
|
|
|
|
+ // 4: round(log(25) * 10) = round(32.188758248682006) = 32
|
|
|
|
+ // result: 3
|
|
|
|
+
|
|
|
|
+ expect(mixins.resolve("foo", 100)).toBe(32);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it("Sync/async resolution & cleanup", async () => {
|
|
|
|
+ const acAll = new AbortController();
|
|
|
|
+
|
|
|
|
+ const mixins = new Mixins<{
|
|
|
|
+ foo: (v: number) => Promise<number>;
|
|
|
|
+ }>({
|
|
|
|
+ defaultSignal: acAll.signal,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const ac1 = new AbortController();
|
|
|
|
+
|
|
|
|
+ mixins.add("foo", (v) => Math.sqrt(v), { signal: ac1.signal }); // 1 (prio 0, index 0)
|
|
|
|
+ mixins.add("foo", (v) => Math.pow(v, 4)); // 2 (prio 0, index 1)
|
|
|
|
+ const rem3 = mixins.add("foo", async (v) => { // 3 (prio 0, index 2)
|
|
|
|
+ await new Promise((r) => setTimeout(r, 50));
|
|
|
|
+ return v + 2;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const res1 = mixins.resolve("foo", 100);
|
|
|
|
+ expect(res1).toBeInstanceOf(Promise);
|
|
|
|
+ expect(await res1).toBe(10002);
|
|
|
|
+
|
|
|
|
+ rem3();
|
|
|
|
+
|
|
|
|
+ const res2 = mixins.resolve("foo", 100);
|
|
|
|
+ expect(res2).not.toBeInstanceOf(Promise);
|
|
|
|
+ expect(res2).toBe(10000);
|
|
|
|
+
|
|
|
|
+ ac1.abort();
|
|
|
|
+
|
|
|
|
+ const res3 = mixins.resolve("foo", 100);
|
|
|
|
+ expect(res3).not.toBeInstanceOf(Promise);
|
|
|
|
+ expect(res3).toBe(100000000);
|
|
|
|
+
|
|
|
|
+ acAll.abort();
|
|
|
|
+
|
|
|
|
+ const res4 = mixins.resolve("foo", 100);
|
|
|
|
+ expect(res4).not.toBeInstanceOf(Promise);
|
|
|
|
+ expect(res4).toBe(100);
|
|
|
|
+ });
|
|
|
|
+});
|