chore: initialize from frontend template 4dc033c
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
createApplication,
|
||||
type ApplicationOutputPorts,
|
||||
} from "../../src/application/create-application.ts";
|
||||
import { createTestApplication } from "../helpers/create-test-application.ts";
|
||||
import { createRuntimeCapabilitiesStub } from "../helpers/runtime-capabilities-stub.ts";
|
||||
|
||||
declare module "../../src/application/ports/in/application-api.ts" {
|
||||
interface ApplicationFeatureInputs {
|
||||
"test-feature": Readonly<{
|
||||
run(): "ok";
|
||||
}>;
|
||||
}
|
||||
}
|
||||
|
||||
describe("application input/output boundary", () => {
|
||||
it("exposes intent-oriented input APIs without leaking output ports", async () => {
|
||||
const application = createTestApplication();
|
||||
|
||||
expect(Object.keys(application)).toEqual([
|
||||
"session",
|
||||
"preferences",
|
||||
"diagnostics",
|
||||
"runtime",
|
||||
"recovery",
|
||||
"features",
|
||||
]);
|
||||
expect(application).not.toHaveProperty("storage");
|
||||
expect(application).not.toHaveProperty("telemetry");
|
||||
expect(application).not.toHaveProperty("releaseInfo");
|
||||
expect(application.features.has("not-installed")).toBe(false);
|
||||
expect(() =>
|
||||
Reflect.apply(application.features.get, application.features, [
|
||||
"not-installed",
|
||||
]),
|
||||
).toThrow("Application feature is not installed");
|
||||
await expect(application.runtime.getReleaseSummary()).resolves.toEqual({
|
||||
buildId: "test-build",
|
||||
releaseId: "test-release",
|
||||
configSchemaVersion: "1",
|
||||
apiContractVersion: "1",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a typed input for an installed generic feature", () => {
|
||||
const featureInput = Object.freeze({
|
||||
run: () => "ok" as const,
|
||||
});
|
||||
const application = createTestApplication({
|
||||
featureInputs: { "test-feature": featureInput },
|
||||
});
|
||||
|
||||
expect(application.features.has("test-feature")).toBe(true);
|
||||
expect(application.features.get("test-feature")).toBe(featureInput);
|
||||
expect(application.features.get("test-feature").run()).toBe("ok");
|
||||
});
|
||||
|
||||
it("uses fake output ports for preference, session, and safe diagnostics flows", async () => {
|
||||
const write = vi.fn(() => ({ ok: true as const }));
|
||||
const emit = vi.fn();
|
||||
const record = vi.fn();
|
||||
const subscribe = vi.fn(() => () => {});
|
||||
const beginSignIn = vi.fn(async () => {});
|
||||
const signOut = vi.fn(async () => {});
|
||||
const recover = vi.fn(async () => "restored" as const);
|
||||
const ports = {
|
||||
session: {
|
||||
getState: () => "authenticated" as const,
|
||||
subscribe,
|
||||
beginSignIn,
|
||||
signOut,
|
||||
recover,
|
||||
},
|
||||
preferences: {
|
||||
read: () => ({ ok: true as const, value: "dark" }),
|
||||
write,
|
||||
remove: () => ({ ok: true as const }),
|
||||
},
|
||||
diagnostics: { record },
|
||||
telemetry: { emit },
|
||||
releaseInfo: {
|
||||
getCurrent: async () => ({
|
||||
buildId: "build-a",
|
||||
releaseId: "release-a",
|
||||
configSchemaVersion: "1",
|
||||
apiContractVersion: "1",
|
||||
assetManifestHash: "hash-a",
|
||||
routeChunks: { "route-home": "assets/home.js" },
|
||||
}),
|
||||
refresh: async () => ({
|
||||
buildId: "build-a",
|
||||
releaseId: "release-a",
|
||||
configSchemaVersion: "1",
|
||||
apiContractVersion: "1",
|
||||
assetManifestHash: "hash-a",
|
||||
routeChunks: { "route-home": "assets/home.js" },
|
||||
}),
|
||||
},
|
||||
runtimeCapabilities: createRuntimeCapabilitiesStub(),
|
||||
navigation: { reload: () => {} },
|
||||
} satisfies ApplicationOutputPorts;
|
||||
const application = createApplication(ports);
|
||||
|
||||
expect(application.session.getSnapshot()).toBe("authenticated");
|
||||
const listener = vi.fn();
|
||||
expect(application.session.subscribe(listener)).toBeTypeOf("function");
|
||||
expect(subscribe).toHaveBeenCalledWith(listener);
|
||||
await application.session.beginSignIn("/return");
|
||||
expect(beginSignIn).toHaveBeenCalledWith("/return");
|
||||
await application.session.signOut();
|
||||
expect(signOut).toHaveBeenCalledOnce();
|
||||
await expect(application.session.recover()).resolves.toBe("restored");
|
||||
expect(application.preferences.getColorScheme()).toBe("dark");
|
||||
expect(application.preferences.setColorScheme("light")).toEqual({ ok: true });
|
||||
expect(write).toHaveBeenCalledWith("COLOR_SCHEME", "light");
|
||||
|
||||
application.diagnostics.reportRenderFailure({
|
||||
routeId: "APP_HOME",
|
||||
buildId: "build-a",
|
||||
boundaryName: "route",
|
||||
});
|
||||
expect(record).toHaveBeenCalledWith({
|
||||
level: "error",
|
||||
eventId: "ui.render.failed",
|
||||
context: {
|
||||
route_id: "APP_HOME",
|
||||
build_id: "build-a",
|
||||
component_boundary: "route",
|
||||
},
|
||||
});
|
||||
expect(emit).toHaveBeenCalledWith("ui.render.failed", {
|
||||
route_id: "APP_HOME",
|
||||
build_id: "build-a",
|
||||
component_boundary: "route",
|
||||
});
|
||||
application.diagnostics.reportRouteChanged({
|
||||
routeId: "APP_HOME",
|
||||
buildId: "build-a",
|
||||
});
|
||||
expect(record).toHaveBeenCalledWith({
|
||||
level: "info",
|
||||
eventId: "route.changed",
|
||||
context: { route_id: "APP_HOME", build_id: "build-a" },
|
||||
});
|
||||
});
|
||||
|
||||
it("does not let a failing diagnostics output escape into presentation", () => {
|
||||
const application = createTestApplication({
|
||||
diagnostics: {
|
||||
record() {
|
||||
throw new Error("sink details");
|
||||
},
|
||||
},
|
||||
telemetry: {
|
||||
emit() {
|
||||
throw new Error("telemetry details");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(() =>
|
||||
application.diagnostics.reportRenderFailure({
|
||||
routeId: "APP_HOME",
|
||||
buildId: "build-a",
|
||||
boundaryName: "feature",
|
||||
}),
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user