import assert from "node:assert/strict"; import test from "node:test"; import { ImageClient } from "../src/client"; import { ProtocolError } from "../src/protocol"; import { parseValue } from "../src/values"; import { startImage } from "./server"; test( "source diagnostics validate unsaved text and compile failures preserve actor behavior", { timeout: 10000 }, async (t) => { const image = await startImage(); let changes = 0; const client = await ImageClient.connect( image.address, (error) => assert.equal(error, undefined), () => changes++, ); t.after(async () => { await client.close(); await image.stop(); }); const file = await client.readSource("actors/counter"); const actor = await client.spawn(file.path, parseValue("0")); const before = await client.inspectActor(actor); const initialChanges = changes; const diagnostics = await client.checkSource('pub fn main() {\r\n "é😀" + missing\r\n}'); const error = diagnostics.find((diagnostic) => diagnostic.severity === "error"); assert.ok(error); assert.match(error.message, /missing/); assert.deepEqual(error.range, { start: { line: 1, character: 12 }, end: { line: 1, character: 19 }, }); const warnings = await client.checkSource("pub fn main() { `hello` }"); assert.ok(warnings.some((diagnostic) => diagnostic.severity === "warning")); assert.deepEqual(await client.checkSource("pub fn main() { 1 }"), []); assert.equal(changes, initialChanges, "validation does not emit image_changed"); assert.doesNotMatch( image.diagnostics(), /missing/, "editor validation does not emit terminal diagnostics", ); await assert.rejects( client.writeActorBehavior(actor, file.source_id, "pub fn handle( {"), (error) => error instanceof ProtocolError && error.diagnostics.some( (diagnostic) => diagnostic.severity === "error" && diagnostic.range !== null, ), ); assert.deepEqual(await client.inspectActor(actor), before); assert.deepEqual(await client.readSource(file.path), file); assert.deepEqual(await client.sourceHistory(file.path), []); }, );