import { assert, assertEquals, assertMatch, assertNotEquals } from "@std/assert"; import { join } from "node:path"; import { tempDir } from "@berry/util"; import { denoCheck } from "./loader.ts"; import { extension, fixture, open, put } from "./loader-fixture.ts"; Deno.test("a reload checks the files first, and a failure keeps the running version", () => fixture({ "good/mod.ts": extension("good"), "good/version.ts": `export const VERSION = "one";`, }, async (root) => { const { loader, close, describe } = await open(root); await loader.loadAll(); await Deno.writeTextFile( join(root, "extensions/good/version.ts"), `export const VERSION: number = "two";`, ); const failed = await loader.reload("good"); assertEquals(failed.status, "failed"); assertMatch(failed.error!, /TS2322/); assertEquals(describe("good"), "one"); // only the relative import changes: the fresh copy is what makes it load anew await Deno.writeTextFile( join(root, "extensions/good/version.ts"), `export const VERSION = "three";`, ); assertEquals((await loader.reload("good")).status, "loaded"); assertEquals(describe("good"), "three"); await close(); })); Deno.test("a frontend that fails to build keeps both halves as they were", () => fixture({ "good/mod.ts": extension("good"), "good/version.ts": `export const VERSION = "one";`, "good/web.tsx": `export default { tools: {} };`, }, async (root) => { const { loader, close, describe } = await open(root); await loader.loadAll(); const built = loader.entries()[0].web; assert(built !== null); await Deno.writeTextFile( join(root, "extensions/good/version.ts"), `export const VERSION = "two";`, ); await Deno.writeTextFile( join(root, "extensions/good/web.tsx"), `export default { tools: {} } as unknown as (;`, ); assertEquals((await loader.reload("good")).status, "failed"); assertEquals(describe("good"), "one"); assertEquals(loader.entries()[0].web, built); await Deno.writeTextFile( join(root, "extensions/good/web.tsx"), `export default { tools: { t: {} } };`, ); const reloaded = await loader.reload("good"); assertEquals([reloaded.status, describe("good")], ["loaded", "two"]); assertNotEquals(loader.entries()[0].web, built); await close(); })); Deno.test("external extensions use Berry's dependencies for loading, checking, and frontend builds", () => fixture({}, async (root) => { await using user = await tempDir(); await put(user.path, { "personal/mod.ts": extension("personal"), "personal/version.ts": 'export const VERSION = "one";', "personal/web.tsx": ` import { Signal } from "@char/aftercare"; import { VERSION } from "./version.ts"; export default { signal: Signal, view: {VERSION} }; `, "deno.json": JSON.stringify({ imports: { "@berry/api": "./missing.ts" } }), }); const source = join(user.path, "personal"); const { loader, close, describe } = await open(root, [join(root, "extensions"), user.path]); try { await loader.loadAll(); assertEquals(describe("personal"), "one"); assertEquals(loader.entries()[0].directory, source); assert(loader.entries()[0].web); assertEquals( new Set(loader.files()), new Set([ join(source, "mod.ts"), join(source, "web.tsx"), ]), ); assertEquals(await denoCheck(root, loader.files()), null); await Deno.writeTextFile(join(source, "version.ts"), 'export const VERSION = "two";'); assertEquals((await loader.reload("personal")).status, "loaded"); assertEquals(describe("personal"), "two"); } finally { await close(); } }));