118 lines
3.8 KiB
JavaScript
118 lines
3.8 KiB
JavaScript
import { describe, it, expect } from "vitest";
|
|
import {
|
|
createVisibilityMatrix,
|
|
isValidVisibilityMatrix,
|
|
VISIBILITY_STATES,
|
|
VISIBILITY_MATRIX_VERSION,
|
|
} from "../../../src/contracts/visibility-matrix.js";
|
|
|
|
describe("visibility-matrix contract", () => {
|
|
describe("createVisibilityMatrix()", () => {
|
|
it("creates a matrix with default empty state", () => {
|
|
const m = createVisibilityMatrix();
|
|
expect(m._version).toBe(VISIBILITY_MATRIX_VERSION);
|
|
expect(m.matrix).toEqual({});
|
|
});
|
|
|
|
it("creates a matrix with provided entries", () => {
|
|
const m = createVisibilityMatrix({ "user-1": "active", "user-2": "hidden" });
|
|
expect(m.matrix["user-1"]).toBe("active");
|
|
expect(m.matrix["user-2"]).toBe("hidden");
|
|
});
|
|
|
|
it("returns a shallow copy of the provided matrix", () => {
|
|
const input = /** @type {{ "user-1": import("../../../src/contracts/visibility-matrix.js").VisibilityState }} */ ({ "user-1": "active" });
|
|
const m = createVisibilityMatrix(input);
|
|
input["user-1"] = "hidden";
|
|
expect(m.matrix["user-1"]).toBe("active"); // not mutated
|
|
});
|
|
});
|
|
|
|
describe("isValidVisibilityMatrix()", () => {
|
|
it("accepts a valid matrix with all known states", () => {
|
|
for (const state of VISIBILITY_STATES) {
|
|
const data = { _version: 1, matrix: { "user-1": state } };
|
|
expect(() => isValidVisibilityMatrix(data)).not.toThrow();
|
|
}
|
|
});
|
|
|
|
it("accepts an empty matrix", () => {
|
|
expect(() => isValidVisibilityMatrix({ _version: 1, matrix: {} })).not.toThrow();
|
|
});
|
|
|
|
it("throws if not an object", () => {
|
|
expect(() => isValidVisibilityMatrix(null)).toThrow(TypeError);
|
|
expect(() => isValidVisibilityMatrix("string")).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on unknown top-level keys", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: {}, extra: true })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on wrong _version", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 2, matrix: {} })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws if matrix is not a plain object", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: null })
|
|
).toThrow(TypeError);
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: ["active"] })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on empty userId key", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: { "": "active" } })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on invalid state value", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: { "user-1": "invisible" } })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on null state value", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: { "user-1": null } })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on non-string state value (Symbol)", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: { "user-1": Symbol("test") } })
|
|
).toThrow(TypeError);
|
|
});
|
|
|
|
it("throws on non-string state value (object)", () => {
|
|
expect(() =>
|
|
isValidVisibilityMatrix({ _version: 1, matrix: { "user-1": { value: "active" } } })
|
|
).toThrow(TypeError);
|
|
});
|
|
});
|
|
|
|
describe("VISIBILITY_STATES", () => {
|
|
it("contains exactly 8 states", () => {
|
|
expect(VISIBILITY_STATES).toHaveLength(8);
|
|
});
|
|
|
|
it("is frozen", () => {
|
|
expect(Object.isFrozen(VISIBILITY_STATES)).toBe(true);
|
|
});
|
|
|
|
it("contains the 8 expected state values", () => {
|
|
const expected = [
|
|
"active", "hidden", "self-muted", "offline",
|
|
"cam-lost", "reconnecting", "never-connected", "ghost",
|
|
];
|
|
expect([...VISIBILITY_STATES].sort()).toEqual(expected.sort());
|
|
});
|
|
});
|
|
});
|