config: commit without preview
This commit is contained in:
@@ -6,7 +6,6 @@ import {
|
||||
fetchConfigEntry,
|
||||
fetchConfigRevision,
|
||||
fetchConfigTree,
|
||||
previewConfigTree,
|
||||
} from "../../src/lib/workspace/config-source/api.ts";
|
||||
|
||||
function response(body: unknown, status = 200): Response {
|
||||
@@ -16,7 +15,7 @@ function response(body: unknown, status = 200): Response {
|
||||
});
|
||||
}
|
||||
|
||||
Deno.test("config source API stays workspace-scoped and separates preview from commit", async () => {
|
||||
Deno.test("config source API commits directly through the workspace scope", async () => {
|
||||
const calls: Array<{ url: string; init?: RequestInit }> = [];
|
||||
const fetcher = ((input: string | URL | Request, init?: RequestInit) => {
|
||||
calls.push({ url: String(input), init });
|
||||
@@ -26,37 +25,38 @@ Deno.test("config source API stays workspace-scoped and separates preview from c
|
||||
await fetchConfigTree("w/one", fetcher);
|
||||
await fetchConfigRevision("w/one", 7, fetcher);
|
||||
await fetchConfigEntry("w/one", "profiles/main.dcdl", fetcher);
|
||||
await previewConfigTree("w/one", { changes: [], entrypoints: [] }, fetcher);
|
||||
await commitConfigTree("w/one", {
|
||||
base_revision: 4,
|
||||
base_digest: "sha256:base",
|
||||
changes: [],
|
||||
entrypoints: [],
|
||||
toolchain_fingerprint: "sha256:toolchain",
|
||||
}, fetcher);
|
||||
|
||||
assertEquals(calls.map((call) => call.url), [
|
||||
"/api/w/w%2Fone/config/source-tree",
|
||||
"/api/w/w%2Fone/config/source-tree/revisions/7",
|
||||
"/api/w/w%2Fone/config/source-tree/entries/profiles%2Fmain.dcdl",
|
||||
"/api/w/w%2Fone/config/source-tree/preview",
|
||||
"/api/w/w%2Fone/config/source-tree/commit",
|
||||
]);
|
||||
assertEquals(calls[3].init?.method, "POST");
|
||||
assertEquals(calls[4].init?.method, "POST");
|
||||
assert(
|
||||
String(calls[4].init?.body).includes('"base_digest":"sha256:base"'),
|
||||
String(calls[3].init?.body).includes('"base_digest":"sha256:base"'),
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("config source API surfaces failed evaluation instead of treating it as a draft write", async () => {
|
||||
Deno.test("config source API surfaces failed evaluation instead of treating it as a successful commit", async () => {
|
||||
const fetcher = (() =>
|
||||
Promise.resolve(
|
||||
new Response("structured diagnostics", { status: 422 }),
|
||||
)) as typeof fetch;
|
||||
let message = "";
|
||||
try {
|
||||
await previewConfigTree("w", { changes: [], entrypoints: [] }, fetcher);
|
||||
await commitConfigTree("w", {
|
||||
base_revision: 1,
|
||||
base_digest: "sha256:base",
|
||||
changes: [],
|
||||
entrypoints: [],
|
||||
}, fetcher);
|
||||
} catch (error) {
|
||||
message = String(error);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ Deno.test("main entrypoint always enables the fixed schema wrapper", async () =>
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("preview and commit format every draft Decodal source", async () => {
|
||||
Deno.test("commit formats every working Decodal source without a preview roundtrip", async () => {
|
||||
const source = await Deno.readTextFile(
|
||||
new URL(
|
||||
"../../src/lib/workspace/config-source/ConfigSourceEditor.svelte",
|
||||
@@ -108,7 +108,7 @@ Deno.test("preview and commit format every draft Decodal source", async () => {
|
||||
);
|
||||
|
||||
assert(
|
||||
source.includes("async function formatDraftSources()") &&
|
||||
source.includes("async function formatWorkingSources()") &&
|
||||
source.includes('change.kind === "create" || change.kind === "update"') &&
|
||||
source.includes('change.kind === "rename"') &&
|
||||
source.includes('entry.content_type !== "decodal"') &&
|
||||
@@ -116,15 +116,39 @@ Deno.test("preview and commit format every draft Decodal source", async () => {
|
||||
"all changed Decodal entries should be formatted rather than only the selected source",
|
||||
);
|
||||
assert(
|
||||
source.includes("await formatDraftSources();") &&
|
||||
source.includes("await requestCandidatePreview();") &&
|
||||
source.includes("await formatWorkingSources();") &&
|
||||
source.includes("entrypoints: entrypoints()") &&
|
||||
source.includes("Committed formatted revision"),
|
||||
"preview and commit should format first and refresh stale preflight before persistence",
|
||||
"commit should format first and send the working changes directly to Backend authority",
|
||||
);
|
||||
assert(
|
||||
!source.includes(
|
||||
"Preview the complete candidate successfully before Commit.",
|
||||
!source.includes("previewConfigTree") &&
|
||||
!source.includes("requestCandidatePreview") &&
|
||||
!source.includes("toolchain_fingerprint"),
|
||||
"normal commit must not depend on a separate preview or client-echoed toolchain fingerprint",
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("config diagnostics analyze continuously with debounce and generation fencing", async () => {
|
||||
const source = await Deno.readTextFile(
|
||||
new URL(
|
||||
"../../src/lib/workspace/config-source/ConfigSourceEditor.svelte",
|
||||
import.meta.url,
|
||||
),
|
||||
"format-driven candidate changes should trigger automatic preflight instead of a dead-end error",
|
||||
);
|
||||
|
||||
assert(
|
||||
source.includes("setTimeout(() =>") &&
|
||||
source.includes("}, 250)") &&
|
||||
source.includes("analyzer.analyze(path, value)") &&
|
||||
source.includes("generation === analysisGeneration") &&
|
||||
source.includes("analysisReady"),
|
||||
"source changes should trigger only the latest debounced analysis after snapshot initialization",
|
||||
);
|
||||
assert(
|
||||
!source.includes("onclick={analyze}") &&
|
||||
!source.includes(">Analyze</button>") &&
|
||||
!source.includes(">Preview</button>"),
|
||||
"manual Analyze and Preview controls should be removed",
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user