test(web): cover compacting status presentation
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
"dev": "deno run -A npm:vite@7.2.7 dev",
|
||||
"dev:backend": "cd ../.. && cargo run -p yoi-workspace-server --bin yoi-server -- serve --listen 127.0.0.1:8787",
|
||||
"check": "deno run -A npm:@sveltejs/kit@2.49.4 sync && deno run -A npm:svelte-check@4.3.4 --tsconfig ./tsconfig.json",
|
||||
"test": "deno test --allow-read=src,test,tests --allow-env=LOG,VSCODE_TEXTMATE_DEBUG,NODE_ENV tests/workspace-model.test.ts tests/workspace-catalog.test.ts tests/profile-api.test.ts tests/skill-api.test.ts src/lib/workspace/auth/model.test.ts tests/auth-api.test.ts src/lib/workspace/api/http.test.ts src/lib/workspace/api/workers.test.ts src/lib/workspace/header/breadcrumb-model.test.ts src/lib/workspace/console/chat-submit.test.ts src/lib/workspace/console/composer-delivery.test.ts test/composer-history.test.ts tests/composer-paste.test.ts src/lib/workspace/console/composer-command.test.ts src/lib/workspace/console/composer-draft.test.ts src/lib/workspace/console/composer-completion.test.ts src/lib/workspace/console/markdown.test.ts test/console/ansi.test.ts src/lib/workspace/console/model.test.ts src/lib/workspace/companion/api.test.ts tests/workdir-api.test.ts src/lib/workspace/console/tasks.test.ts test/ticket-detail-route-reuse.test.ts test/objective-pages.test.ts test/repositories/ui.test.ts src/lib/workspace/console/worker-console.ui.test.ts src/lib/workspace/settings/model.test.ts tests/runtime-connection.test.ts tests/runtime-management.test.ts tests/runtime-management-source.test.ts src/lib/workspace/sidebar/override-stack.test.ts src/lib/workspace/sidebar/workers.test.ts src/lib/workspace/sidebar/workspace-switcher.test.ts src/lib/workspace/sidebar/worker-subscription.test.ts src/lib/workspace/sidebar/worker-launch.test.ts test/sidebar/worker-actions.test.ts src/lib/workspace/tickets/merge-request-resources.test.ts src/lib/workspace/tickets/ticket-panel.test.ts test/merge-request-status.test.ts test/config-source/decodal-grammar.test.ts test/config-source/editor-state.test.ts test/config-source/fixed-schema-wrapper.test.ts test/config-source/toolchain.test.ts test/config-source/wasm-parity.test.ts test/repository-access/api.test.ts test/repository-access/loader.test.ts test/repository-access/ui.test.ts test/repository-ssh-connection-ui.test.ts",
|
||||
"test": "deno test --allow-read=src,test,tests --allow-env=LOG,VSCODE_TEXTMATE_DEBUG,NODE_ENV tests/workspace-model.test.ts tests/workspace-catalog.test.ts tests/profile-api.test.ts tests/skill-api.test.ts src/lib/workspace/auth/model.test.ts tests/auth-api.test.ts src/lib/workspace/api/http.test.ts src/lib/workspace/api/workers.test.ts src/lib/workspace/header/breadcrumb-model.test.ts src/lib/workspace/console/chat-submit.test.ts src/lib/workspace/console/composer-delivery.test.ts test/composer-history.test.ts tests/composer-paste.test.ts src/lib/workspace/console/composer-command.test.ts src/lib/workspace/console/composer-draft.test.ts src/lib/workspace/console/composer-completion.test.ts src/lib/workspace/console/markdown.test.ts test/console/ansi.test.ts src/lib/workspace/console/model.test.ts src/lib/workspace/console/run-status.test.ts src/lib/workspace/companion/api.test.ts tests/workdir-api.test.ts src/lib/workspace/console/tasks.test.ts test/ticket-detail-route-reuse.test.ts test/objective-pages.test.ts test/repositories/ui.test.ts src/lib/workspace/console/worker-console.ui.test.ts src/lib/workspace/settings/model.test.ts tests/runtime-connection.test.ts tests/runtime-management.test.ts tests/runtime-management-source.test.ts src/lib/workspace/sidebar/override-stack.test.ts src/lib/workspace/sidebar/workers.test.ts src/lib/workspace/sidebar/workspace-switcher.test.ts src/lib/workspace/sidebar/worker-subscription.test.ts src/lib/workspace/sidebar/worker-launch.test.ts test/sidebar/worker-actions.test.ts src/lib/workspace/tickets/merge-request-resources.test.ts src/lib/workspace/tickets/ticket-panel.test.ts test/merge-request-status.test.ts test/config-source/decodal-grammar.test.ts test/config-source/editor-state.test.ts test/config-source/fixed-schema-wrapper.test.ts test/config-source/toolchain.test.ts test/config-source/wasm-parity.test.ts test/repository-access/api.test.ts test/repository-access/loader.test.ts test/repository-access/ui.test.ts test/repository-ssh-connection-ui.test.ts",
|
||||
"build": "deno run -A npm:vite@7.2.7 build",
|
||||
"preview": "deno run -A npm:vite@7.2.7 preview"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { InFlightCompaction } from "$lib/generated/protocol.ts";
|
||||
import type {
|
||||
InFlightCompaction,
|
||||
WorkerStateSnapshot,
|
||||
} from "$lib/generated/protocol.ts";
|
||||
import Spinner from "./Spinner.svelte";
|
||||
import { formatRunElapsed, formatRunTokens } from "./run-status";
|
||||
import {
|
||||
formatRunElapsed,
|
||||
formatRunTokens,
|
||||
resolveCompactionStatusPresentation,
|
||||
} from "./run-status";
|
||||
|
||||
type Props = {
|
||||
startedAtMs: number | null;
|
||||
@@ -9,12 +16,24 @@
|
||||
uploadTokens: number;
|
||||
outputTokens: number;
|
||||
compaction?: InFlightCompaction | null;
|
||||
workerState?: WorkerStateSnapshot | null;
|
||||
};
|
||||
|
||||
let { startedAtMs, requests, uploadTokens, outputTokens, compaction = null }: Props =
|
||||
$props();
|
||||
let {
|
||||
startedAtMs,
|
||||
requests,
|
||||
uploadTokens,
|
||||
outputTokens,
|
||||
compaction = null,
|
||||
workerState = null,
|
||||
}: Props = $props();
|
||||
let nowMs = $state(Date.now());
|
||||
const clockStartedAtMs = $derived(compaction?.started_at_ms ?? startedAtMs);
|
||||
const compactionStatus = $derived(
|
||||
resolveCompactionStatusPresentation(compaction, workerState),
|
||||
);
|
||||
const clockStartedAtMs = $derived(
|
||||
compactionStatus?.progress.started_at_ms ?? startedAtMs,
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
clockStartedAtMs;
|
||||
@@ -33,8 +52,8 @@
|
||||
|
||||
<div class="worker-run-status" role="status" aria-live="off">
|
||||
<Spinner />
|
||||
{#if compaction}
|
||||
<span>Compacting · {compaction.phase}</span>
|
||||
{#if compactionStatus}
|
||||
<span>{compactionStatus.label}</span>
|
||||
<span aria-hidden="true">|</span>
|
||||
{/if}
|
||||
<span>{elapsed}</span>
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
formatRunElapsed,
|
||||
formatRunElapsedCompact,
|
||||
formatRunTokens,
|
||||
resolveCompactionStatusPresentation,
|
||||
visibleCompactionProgress,
|
||||
} from "./run-status.ts";
|
||||
|
||||
@@ -100,7 +101,7 @@ Deno.test("run status formatting matches the compact TUI shape", () => {
|
||||
assertEquals(formatRunTokens(999), "999");
|
||||
});
|
||||
|
||||
Deno.test("visible compaction requires a matching busy worker state", () => {
|
||||
Deno.test("WorkerRunStatus presentation follows compaction and busy state", () => {
|
||||
const manual = {
|
||||
phase: "preparing",
|
||||
started_at_ms: 1_700_000_000_000,
|
||||
@@ -137,4 +138,19 @@ Deno.test("visible compaction requires a matching busy worker state", () => {
|
||||
assertEquals(visibleCompactionProgress(manual, idle), null);
|
||||
assertEquals(visibleCompactionProgress(manual, null), null);
|
||||
assertEquals(visibleCompactionProgress(null, maintenance), null);
|
||||
|
||||
assertEquals(resolveCompactionStatusPresentation(manual, maintenance), {
|
||||
progress: manual,
|
||||
label: "Compacting · preparing",
|
||||
});
|
||||
assertEquals(resolveCompactionStatusPresentation(automatic, run), {
|
||||
progress: automatic,
|
||||
label: "Compacting · summarizing",
|
||||
});
|
||||
assertEquals(resolveCompactionStatusPresentation(manual, run), null);
|
||||
assertEquals(
|
||||
resolveCompactionStatusPresentation(automatic, maintenance),
|
||||
null,
|
||||
);
|
||||
assertEquals(resolveCompactionStatusPresentation(manual, idle), null);
|
||||
});
|
||||
|
||||
@@ -76,6 +76,21 @@ export function formatRunTokens(tokens: number): string {
|
||||
return String(tokens);
|
||||
}
|
||||
|
||||
export type CompactionStatusPresentation = {
|
||||
progress: InFlightCompaction;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export function resolveCompactionStatusPresentation(
|
||||
compaction: InFlightCompaction | null,
|
||||
workerState: WorkerStateSnapshot | null,
|
||||
): CompactionStatusPresentation | null {
|
||||
const progress = visibleCompactionProgress(compaction, workerState);
|
||||
return progress
|
||||
? { progress, label: `Compacting · ${progress.phase}` }
|
||||
: null;
|
||||
}
|
||||
|
||||
export function visibleCompactionProgress(
|
||||
compaction: InFlightCompaction | null,
|
||||
workerState: WorkerStateSnapshot | null,
|
||||
|
||||
@@ -1129,15 +1129,16 @@ Deno.test("Web Console gates compaction progress before rendering run status", a
|
||||
);
|
||||
|
||||
assert(
|
||||
consolePage.includes("visibleCompactionProgress(") &&
|
||||
consolePage.includes("consoleProjection.compaction") &&
|
||||
consolePage.includes("consoleProjection.workerState") &&
|
||||
consolePage.includes("compaction={compactionProgress}"),
|
||||
"Console page should pass only state-consistent compaction progress to the status component",
|
||||
consolePage.includes("compaction={consoleProjection.compaction}") &&
|
||||
consolePage.includes("workerState={consoleProjection.workerState}"),
|
||||
"Console page should pass compaction metadata with authoritative worker state to the status component",
|
||||
);
|
||||
assert(
|
||||
runStatus.includes("compaction?.started_at_ms ?? startedAtMs") &&
|
||||
runStatus.includes("Compacting · {compaction.phase}"),
|
||||
"run status should render the compaction phase and derive elapsed time from the authoritative start timestamp",
|
||||
runStatus.includes("resolveCompactionStatusPresentation(") &&
|
||||
runStatus.includes("{compactionStatus.label}") &&
|
||||
runStatus.includes(
|
||||
"compactionStatus?.progress.started_at_ms ?? startedAtMs",
|
||||
),
|
||||
"run status should render the guarded presentation and derive elapsed time from its authoritative start timestamp",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
type ComposerCompletionToken,
|
||||
} from "$lib/workspace/console/composer-completion";
|
||||
import WorkerRunStatus from "$lib/workspace/console/WorkerRunStatus.svelte";
|
||||
import { visibleCompactionProgress } from "$lib/workspace/console/run-status";
|
||||
import { resolveWorkerControlShortcut } from "$lib/workspace/console/worker-control-shortcuts";
|
||||
import {
|
||||
consoleWorkerViews,
|
||||
@@ -249,12 +248,6 @@
|
||||
liveWorkerState ?? (worker?.state === "stopped" ? "stopped" : "loading"),
|
||||
);
|
||||
const workerRunning = $derived(workerState === "running");
|
||||
const compactionProgress = $derived(
|
||||
visibleCompactionProgress(
|
||||
consoleProjection.compaction,
|
||||
consoleProjection.workerState,
|
||||
),
|
||||
);
|
||||
const workerPaused = $derived(workerState === "paused");
|
||||
const composerEditable = $derived(protocolState === "open" && !sending);
|
||||
const draftHasText = $derived(draft.content.trim().length > 0);
|
||||
@@ -1912,7 +1905,8 @@
|
||||
requests={consoleProjection.runActivity.requests}
|
||||
uploadTokens={consoleProjection.runActivity.uploadTokens}
|
||||
outputTokens={consoleProjection.runActivity.outputTokens}
|
||||
compaction={compactionProgress}
|
||||
compaction={consoleProjection.compaction}
|
||||
workerState={consoleProjection.workerState}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user