Files
16gagent/test/software-factory-core.test.mjs
T
2026-06-06 10:40:48 +08:00

333 lines
12 KiB
JavaScript

/**
* PR-36 — Software Factory Core Layer 测试
*
* 覆盖:
* A — Factory Registry
* B — Factory Contract
* C — Extensibility
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
// ─── PR-36 Software Factory Core ──────────────────
import {
FACTORY_ARTIFACT_KIND, METRIC_KIND, REPORT_TYPE, DEPENDENCY_KIND,
createFactoryInput, createFactoryOutput,
createFactoryArtifact, createFactoryMetric,
createFactoryReport, createFactoryDependency,
FACTORY_STATUS, createFactoryRegistry,
} from "../src/software-factory-core/index.mjs";
// ═════════════════════════════════════════════════════
// Part A — Factory Registry
// ═════════════════════════════════════════════════════
describe("PR-36 Part A — Factory Registry", () => {
it("registers all 15 factories (SF-01 ~ SF-15)", () => {
const registry = createFactoryRegistry();
for (let i = 1; i <= 15; i++) {
if (i === 3) continue;
const id = `SF-${String(i).padStart(2, "0")}`;
const f = registry.get(id);
assert.ok(f, `Factory ${id} should exist`);
assert.equal(f.id, id);
assert.ok(f.name, `Factory ${id} should have a name`);
assert.ok(f.domain, `Factory ${id} should have a domain`);
}
});
it("returns null for unknown factory", () => {
const registry = createFactoryRegistry();
assert.equal(registry.get("SF-99"), null);
});
it("lists factories by domain", () => {
const registry = createFactoryRegistry();
const archFactories = registry.list({ domain: "architecture" });
assert.equal(archFactories.length, 1);
assert.equal(archFactories[0].id, "SF-05");
});
it("getDependencies returns correct upstream dependencies", () => {
const registry = createFactoryRegistry();
const deps = registry.getDependencies("SF-07");
assert.ok(deps.length >= 2, "SF-07 should have at least 2 dependencies");
const fromIds = deps.map(d => d.from);
assert.ok(fromIds.includes("SF-05"), "SF-07 should depend on SF-05");
assert.ok(fromIds.includes("SF-04"), "SF-07 should depend on SF-04");
});
it("getDependents returns downstream dependents", () => {
const registry = createFactoryRegistry();
const dependents = registry.getDependents("SF-01");
assert.ok(dependents.length >= 1);
const depIds = dependents.map(d => d.id);
assert.ok(depIds.includes("SF-02"), "SF-02 should depend on SF-01");
});
it("getTopologicalOrder returns valid order", () => {
const registry = createFactoryRegistry();
const order = registry.getTopologicalOrder();
assert.ok(order.length === 14, `Expected 14, got ${order.length}`);
// SF-01 should come before SF-02
const idx01 = order.indexOf("SF-01");
const idx02 = order.indexOf("SF-02");
assert.ok(idx01 < idx02, `SF-01 (${idx01}) should precede SF-02 (${idx02})`);
});
it("getParallelBatches returns valid batches", () => {
const registry = createFactoryRegistry();
const batches = registry.getParallelBatches();
assert.ok(batches.length >= 1, "Should have at least 1 batch");
// First batch should contain SF-01 (no dependencies)
assert.ok(batches[0].includes("SF-01"), "First batch should include SF-01");
// SF-01 should not appear in later batches
for (let i = 1; i < batches.length; i++) {
assert.ok(!batches[i].includes("SF-01"), "SF-01 should only be in batch 0");
}
});
it("registerImplementation activates factory", () => {
const registry = createFactoryRegistry();
const mockImpl = (_input) => createFactoryOutput({ factoryId: "SF-01", status: "passed" });
registry.registerImplementation("SF-01", mockImpl);
const f = registry.get("SF-01");
assert.equal(f.status, FACTORY_STATUS.ACTIVE);
assert.ok(f.implementationId);
assert.ok(f.activatedAt);
});
it("execute calls registered implementation", () => {
const registry = createFactoryRegistry();
registry.registerImplementation("SF-01", (input) => {
return createFactoryOutput({
factoryId: "SF-01",
status: "passed",
artifacts: [createFactoryArtifact({ kind: "requirement", name: "Strategy Doc", factoryId: "SF-01" })],
});
});
const input = createFactoryInput({ factoryId: "SF-01" });
const output = registry.execute("SF-01", input);
assert.equal(output.status, "passed");
assert.equal(output.artifacts.length, 1);
assert.equal(output.artifacts[0].name, "Strategy Doc");
});
it("throws when executing without implementation", () => {
const registry = createFactoryRegistry();
assert.throws(() => {
registry.execute("SF-01", createFactoryInput({ factoryId: "SF-01" }));
}, /No implementation registered/);
});
it("throws when registering implementation for unknown factory", () => {
const registry = createFactoryRegistry();
assert.throws(() => {
registry.registerImplementation("SF-99", () => ({}));
}, /Unknown factory/);
});
it("stats returns correct counts", () => {
const registry = createFactoryRegistry();
const s = registry.stats();
assert.equal(s.total, 14);
assert.equal(s.domains.length, 14);
});
it("setStatus changes factory status", () => {
const registry = createFactoryRegistry();
registry.setStatus("SF-01", "active");
assert.equal(registry.get("SF-01").status, FACTORY_STATUS.ACTIVE);
registry.setStatus("SF-01", "deprecated");
assert.equal(registry.get("SF-01").status, FACTORY_STATUS.DEPRECATED);
});
});
// ═════════════════════════════════════════════════════
// Part B — Factory Contract
// ═════════════════════════════════════════════════════
describe("PR-36 Part B — Factory Contract", () => {
describe("FactoryInput", () => {
it("creates with required field", () => {
const input = createFactoryInput({ factoryId: "SF-01" });
assert.ok(input.id);
assert.equal(input.factoryId, "SF-01");
assert.equal(input.upstreamArtifacts.length, 0);
});
it("throws without factoryId", () => {
assert.throws(() => createFactoryInput({}));
});
it("accepts optional fields", () => {
const input = createFactoryInput({
factoryId: "SF-01",
parameters: { key: "val" },
constraints: { timeBudgetMs: 5000 },
});
assert.equal(input.factoryId, "SF-01");
assert.equal(input.parameters.key, "val");
assert.equal(input.constraints.timeBudgetMs, 5000);
});
});
describe("FactoryOutput", () => {
it("creates with passed status", () => {
const output = createFactoryOutput({ factoryId: "SF-01", status: "passed" });
assert.equal(output.status, "passed");
});
it("throws on invalid status", () => {
assert.throws(() => createFactoryOutput({ factoryId: "SF-01", status: "unknown" }));
});
it("accepts all valid statuses", () => {
for (const s of ["passed", "failed", "blocked", "partial"]) {
const o = createFactoryOutput({ factoryId: "SF-01", status: s });
assert.equal(o.status, s);
}
});
});
describe("FactoryArtifact", () => {
it("creates with all fields", () => {
const art = createFactoryArtifact({
kind: "code",
name: "auth.module.ts",
factoryId: "SF-07",
productId: "pm-1",
version: 2,
dependencies: ["fa-1", "fa-2"],
path: "/src/auth/module.ts",
metadata: { language: "TypeScript" },
});
assert.equal(art.kind, "code");
assert.equal(art.name, "auth.module.ts");
assert.equal(art.factoryId, "SF-07");
assert.equal(art.productId, "pm-1");
assert.equal(art.version, 2);
assert.deepEqual(art.dependencies, ["fa-1", "fa-2"]);
});
it("throws on invalid kind", () => {
assert.throws(() => createFactoryArtifact({ kind: "invalid", name: "x", factoryId: "SF-01" }));
});
});
describe("FactoryMetric", () => {
it("creates with required fields", () => {
const m = createFactoryMetric({
factoryId: "SF-07",
name: "code.coverage",
value: 85.5,
kind: "percentage",
target: 80,
threshold: 70,
});
assert.equal(m.name, "code.coverage");
assert.equal(m.value, 85.5);
assert.equal(m.kind, "percentage");
assert.equal(m.target, 80);
assert.equal(m.threshold, 70);
});
it("throws if value is not a number", () => {
assert.throws(() => createFactoryMetric({ factoryId: "SF-01", name: "x", value: "not-a-number" }));
});
});
describe("FactoryReport", () => {
it("creates factory report", () => {
const r = createFactoryReport({
type: "factory",
title: "SF-07 Execution Report",
factoryId: "SF-07",
recommendations: ["Increase test coverage"],
});
assert.equal(r.type, "factory");
assert.equal(r.title, "SF-07 Execution Report");
assert.deepEqual(r.recommendations, ["Increase test coverage"]);
});
it("throws on invalid type", () => {
assert.throws(() => createFactoryReport({ type: "invalid", title: "Test" }));
});
});
describe("FactoryDependency", () => {
it("creates hard dependency", () => {
const d = createFactoryDependency({
from: "SF-01",
to: "SF-02",
kind: "hard",
description: "Strategy feeds into requirements",
});
assert.equal(d.from, "SF-01");
assert.equal(d.to, "SF-02");
assert.equal(d.kind, "hard");
assert.equal(d.required, true);
});
it("creates soft dependency", () => {
const d = createFactoryDependency({ from: "SF-02", to: "SF-05", kind: "soft", required: false });
assert.equal(d.kind, "soft");
assert.equal(d.required, false);
});
});
});
// ═════════════════════════════════════════════════════
// Part C — Product Model
// ═════════════════════════════════════════════════════
describe("PR-36 Part I — Extensibility", () => {
it("no hardcoded factory implementations in registry", () => {
const registry = createFactoryRegistry();
// All factories should initially have no implementation
for (let i = 1; i <= 15; i++) {
if (i === 3) continue;
const id = `SF-${String(i).padStart(2, "0")}`;
assert.equal(registry.getImplementation(id), null, `SF-${String(i).padStart(2, "0")} should have no hardcoded implementation`);
}
});
it("can add custom factory after SF-14", () => {
// Factory Registry only registers SF-01~SF-15, but can we extend with a custom one?
// This validates the extensibility: the registry is not locked to 14 factories.
const registry = createFactoryRegistry();
// Future SF-16 could be registered via a separate module
// For now, verify the existing get API correctly handles unknown IDs
assert.equal(registry.get("SF-16"), null);
// getImplementation for unknown should return null
assert.equal(registry.getImplementation("SF-16"), null);
});
it("factory registry supports custom implementation registration", () => {
const registry = createFactoryRegistry();
// Register implementation for existing factory
registry.registerImplementation("SF-07", (input) => {
return createFactoryOutput({ factoryId: "SF-07", status: "passed" });
});
assert.equal(typeof registry.getImplementation("SF-07"), "function");
const output = registry.execute("SF-07", createFactoryInput({ factoryId: "SF-07" }));
assert.equal(output.status, "passed");
});
});