feat(schema): add OperationNodeAttrs and CallNodeAttrs TypeBox schemas
This commit is contained in:
131
test/schema/node.test.ts
Normal file
131
test/schema/node.test.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { Value } from "@alkdev/typebox/value";
|
||||
import {
|
||||
OperationNodeAttrs,
|
||||
type OperationNodeAttrs as OperationNodeAttrsType,
|
||||
CallNodeAttrs,
|
||||
type CallNodeAttrs as CallNodeAttrsType,
|
||||
} from "../../src/schema/node";
|
||||
|
||||
describe("OperationNodeAttrs", () => {
|
||||
const valid: OperationNodeAttrsType = {
|
||||
name: "classify",
|
||||
namespace: "task",
|
||||
version: "1.0.0",
|
||||
type: "query",
|
||||
inputSchema: { type: "object" },
|
||||
outputSchema: { type: "object" },
|
||||
};
|
||||
|
||||
it("accepts valid attributes without optional fields", () => {
|
||||
expect(Value.Check(OperationNodeAttrs, valid)).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts valid attributes with all optional fields", () => {
|
||||
const withOptional: OperationNodeAttrsType = {
|
||||
...valid,
|
||||
description: "Classifies input",
|
||||
tags: ["ml", "nlp"],
|
||||
};
|
||||
expect(Value.Check(OperationNodeAttrs, withOptional)).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts all operation types", () => {
|
||||
for (const type of ["query", "mutation", "subscription"] as const) {
|
||||
expect(Value.Check(OperationNodeAttrs, { ...valid, type })).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects missing required fields", () => {
|
||||
expect(Value.Check(OperationNodeAttrs, {})).toBe(false);
|
||||
expect(Value.Check(OperationNodeAttrs, { name: "classify" })).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects invalid operation type", () => {
|
||||
expect(
|
||||
Value.Check(OperationNodeAttrs, { ...valid, type: "invalid" }),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects wrong types for optional tags", () => {
|
||||
expect(Value.Check(OperationNodeAttrs, { ...valid, tags: [1, 2] })).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("CallNodeAttrs", () => {
|
||||
const valid: CallNodeAttrsType = {
|
||||
requestId: "req_abc123",
|
||||
operationId: "task.classify",
|
||||
status: "pending",
|
||||
input: { text: "hello" },
|
||||
};
|
||||
|
||||
it("accepts valid attributes without optional fields", () => {
|
||||
expect(Value.Check(CallNodeAttrs, valid)).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts valid attributes with all optional fields", () => {
|
||||
const withOptional: CallNodeAttrsType = {
|
||||
...valid,
|
||||
parentRequestId: "req_parent",
|
||||
output: { label: "greeting" },
|
||||
error: {
|
||||
code: "INTERNAL",
|
||||
message: "Something went wrong",
|
||||
details: { stack: "..." },
|
||||
},
|
||||
identity: {
|
||||
id: "user_1",
|
||||
scopes: ["read", "write"],
|
||||
resources: { org: ["org_1"] },
|
||||
},
|
||||
startedAt: "2026-05-21T10:00:00Z",
|
||||
completedAt: "2026-05-21T10:00:01Z",
|
||||
};
|
||||
expect(Value.Check(CallNodeAttrs, withOptional)).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts all call statuses", () => {
|
||||
for (const status of ["pending", "running", "completed", "failed", "aborted"] as const) {
|
||||
expect(Value.Check(CallNodeAttrs, { ...valid, status })).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("accepts error without optional details", () => {
|
||||
const withError: CallNodeAttrsType = {
|
||||
...valid,
|
||||
error: { code: "NOT_FOUND", message: "Operation not found" },
|
||||
};
|
||||
expect(Value.Check(CallNodeAttrs, withError)).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts identity without optional resources", () => {
|
||||
const withIdentity: CallNodeAttrsType = {
|
||||
...valid,
|
||||
identity: { id: "user_1", scopes: ["read"] },
|
||||
};
|
||||
expect(Value.Check(CallNodeAttrs, withIdentity)).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects missing required fields", () => {
|
||||
expect(Value.Check(CallNodeAttrs, {})).toBe(false);
|
||||
expect(Value.Check(CallNodeAttrs, { requestId: "req_1" })).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects invalid call status", () => {
|
||||
expect(
|
||||
Value.Check(CallNodeAttrs, { ...valid, status: "idle" }),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects error with missing required fields", () => {
|
||||
expect(
|
||||
Value.Check(CallNodeAttrs, { ...valid, error: { code: "X" } }),
|
||||
).toBe(false);
|
||||
expect(
|
||||
Value.Check(CallNodeAttrs, { ...valid, error: { message: "X" } }),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user