98 lines
3.1 KiB
TypeScript
98 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "@suaveplan/testing/runner";
|
|
import z from "zod";
|
|
import { AbstractAudioFxPlugin } from "../base/audio-fx-plugin.js";
|
|
import {
|
|
AUDIO_FX_CODES,
|
|
type AudioFxError,
|
|
} from "../error-codes/error-codes.js";
|
|
import { PluginRegistry } from "./registry.js";
|
|
|
|
const SCHEMA = z.object({}).strict();
|
|
const STEREO_IO = {
|
|
inputs: [{ count: 2 as const }],
|
|
outputs: [{ count: "preserve" as const }],
|
|
};
|
|
|
|
class FixturePlugin extends AbstractAudioFxPlugin {
|
|
public constructor(id: string) {
|
|
super({
|
|
metadata: { id, name: id, version: "1.0.0", category: "utility" },
|
|
schema: SCHEMA,
|
|
io: STEREO_IO,
|
|
parameters: [],
|
|
supportedSchemaVersion: 1,
|
|
});
|
|
}
|
|
protected processBlock(
|
|
input: Float32Array[],
|
|
output: Float32Array[]
|
|
): void {
|
|
for (let ch = 0; ch < input.length; ch++) {
|
|
output[ch]!.set(input[ch]!);
|
|
}
|
|
}
|
|
}
|
|
|
|
describe("PluginRegistry: register + create", () => {
|
|
it("registers a factory and creates fresh instances", {
|
|
timeout: 5_000,
|
|
}, () => {
|
|
const r = new PluginRegistry();
|
|
r.register("fx-a", () => new FixturePlugin("fx-a"));
|
|
const a = r.create("fx-a");
|
|
const b = r.create("fx-a");
|
|
expect(a.metadata.id).toBe("fx-a");
|
|
expect(b.metadata.id).toBe("fx-a");
|
|
expect(a).not.toBe(b);
|
|
});
|
|
|
|
it("has(pluginType) reflects registration state", {
|
|
timeout: 5_000,
|
|
}, () => {
|
|
const r = new PluginRegistry();
|
|
expect(r.has("fx-a")).toBe(false);
|
|
r.register("fx-a", () => new FixturePlugin("fx-a"));
|
|
expect(r.has("fx-a")).toBe(true);
|
|
});
|
|
|
|
it("list() returns registered types in insertion order", {
|
|
timeout: 5_000,
|
|
}, () => {
|
|
const r = new PluginRegistry();
|
|
r.register("fx-b", () => new FixturePlugin("fx-b"));
|
|
r.register("fx-a", () => new FixturePlugin("fx-a"));
|
|
r.register("fx-c", () => new FixturePlugin("fx-c"));
|
|
expect(r.list()).toEqual(["fx-b", "fx-a", "fx-c"]);
|
|
});
|
|
|
|
it("re-registering a type overwrites the previous factory", {
|
|
timeout: 5_000,
|
|
}, () => {
|
|
const r = new PluginRegistry();
|
|
r.register("fx-a", () => new FixturePlugin("fx-a"));
|
|
r.register("fx-a", () => new FixturePlugin("fx-a-2"));
|
|
expect(r.create("fx-a").metadata.id).toBe("fx-a-2");
|
|
expect(r.list()).toEqual(["fx-a"]);
|
|
});
|
|
});
|
|
|
|
describe("PluginRegistry: missing factory rejection", () => {
|
|
it("create() rejects an unregistered type with CHAIN_SLOT_NOT_FOUND", {
|
|
timeout: 5_000,
|
|
}, () => {
|
|
const r = new PluginRegistry();
|
|
try {
|
|
r.create("fx-missing");
|
|
} catch (error) {
|
|
expect((error as AudioFxError).code).toBe(
|
|
AUDIO_FX_CODES.CHAIN_SLOT_NOT_FOUND
|
|
);
|
|
expect((error as AudioFxError).context).toEqual({
|
|
pluginType: "fx-missing",
|
|
});
|
|
return;
|
|
}
|
|
throw new Error("expected CHAIN_SLOT_NOT_FOUND");
|
|
});
|
|
});
|