- commit
- f5cfbd38f71887d00f5c604e5ac38b2ff72f633e
- parent
- 805027900707bac43008b87180185cfe684a38a5
- author
- Dami <dami.etoile@gmail.com>
| M | apps/ | 5 | +++++ |
| A | apps/ | 23 | +++++++++++++++++++++++ |
| M | deno.json | 1 | + |
| M | jsr.json | 2 | ++ |
| M | package/ | 1 | + |
| M | package/ | 6 | ++++-- |
| M | package/ | 4 | ++++ |
| M | package/ | 3 | ++- |
@@ -24,5 +24,10 @@ Application work should not require edits in `src/_lofi/`. The M2 generator copi
2424 runtime-owned files without turning them into public framework APIs. M4 may replace the local seam2525 with proven `@nzip/lofi` subpath imports without changing product UI.2626 27+Browser journeys import readiness, offline, two-client, and sanitized failure-artifact helpers from28+`@nzip/lofi/testing`. The normal `deno task test` verifies that generated projects resolve this29+surface without launching Chromium; real browser and cloud-convergence journeys remain explicit30+developer-run gates.31+2732 Passkey backup and recovery are intentionally absent. The pinned Jazz alpha exposes a rejected2833 credential design, so this reference uses a device-local identity and does not imply recoverability.@@ -0,0 +1,23 @@
1+import type {2+ BrowserTestClient,3+ ConcurrentOfflineScenario,4+ ReadinessOptions,5+ TwoClientFixture,6+} from "@nzip/lofi/testing";7+8+function assert(condition: unknown, message: string): asserts condition {9+ if (!condition) throw new Error(message);10+}11+12+Deno.test("generated projects type-check the public local-first browser helpers", () => {13+ type TestingContract = {14+ client: BrowserTestClient;15+ fixture: TwoClientFixture;16+ readiness: ReadinessOptions;17+ scenario: ConcurrentOfflineScenario<string>;18+ };19+ const exportedNames = ["client", "fixture", "readiness", "scenario"] satisfies readonly (20+ keyof TestingContract21+ )[];22+ assert(exportedNames.length === 4, "@nzip/lofi/testing contract was not checked");23+});@@ -2,6 +2,7 @@
22 "imports": {33 "@astrojs/check": "npm:@astrojs/check@0.9.9",44 "@astrojs/preact": "npm:@astrojs/preact@6.0.1",5+ "@nzip/lofi/testing": "./package/testing/mod.ts",56 "astro": "npm:astro@7.0.9",67 "astro/config": "npm:astro@7.0.9/config",78 "jazz-tools": "npm:jazz-tools@2.0.0-alpha.53",@@ -10,6 +10,7 @@
1010 "./dev": "./package/commands/dev.ts",1111 "./doctor": "./package/commands/doctor.ts",1212 "./preview": "./package/commands/preview.ts",13+ "./testing": "./package/testing/mod.ts",1314 "./test": "./package/commands/run_tests.ts"1415 },1516 "publish": {@@ -25,6 +26,7 @@
2526 ],2627 "exclude": [2728 "package/**/*_test.ts",29+ "package/testing/fixture_integration.ts",2830 "package/testdata"2931 ]3032 }@@ -72,6 +72,7 @@ function generatedDenoConfig(packagePrefix: string): string {
7272 "@nzip/lofi/dev": packageCommand("dev", "commands/dev.ts"),7373 "@nzip/lofi/doctor": packageCommand("doctor", "commands/doctor.ts"),7474 "@nzip/lofi/preview": packageCommand("preview", "commands/preview.ts"),75+ "@nzip/lofi/testing": packageCommand("testing", "testing/mod.ts"),7576 "@nzip/lofi/test": packageCommand("test", "commands/run_tests.ts"),7677 "astro": "npm:astro@7.0.9",7778 "astro/config": "npm:astro@7.0.9/config",@@ -100,12 +100,13 @@ Deno.test("createProject materializes the complete starter snapshot", async () =
100100 }101101 const config = JSON.parse(await Deno.readTextFile(join(result.destination, "deno.json")));102102 assertEquals(config.imports["@nzip/lofi/"], "jsr:@nzip/lofi@0.1.0/");103+ assertEquals(config.imports["@nzip/lofi/testing"], "jsr:@nzip/lofi@0.1.0/testing");103104 const lofiSpecifiers = Object.entries(config.imports)104105 .filter(([name]) => name.startsWith("@nzip/lofi/"))105106 .map(([, specifier]) => String(specifier));106107 assert(107- lofiSpecifiers.length === 7,108- `expected one package prefix and six command mappings, received ${lofiSpecifiers.length}`,108+ lofiSpecifiers.length === 8,109+ `expected one package prefix, six commands, and testing, received ${lofiSpecifiers.length}`,109110 );110111 assert(111112 lofiSpecifiers.every((specifier) => specifier.startsWith("jsr:@nzip/lofi@0.1.0/")),@@ -119,6 +120,7 @@ Deno.test("createProject materializes the complete starter snapshot", async () =
119120 Deno.test("package manifest and generated version stay coupled", () => {120121 assertEquals(packageManifest.name, "@nzip/lofi");121122 assertEquals(packageManifest.version, LOFI_VERSION);123+ assertEquals(packageManifest.exports["./testing"], "./package/testing/mod.ts");122124 });123125 124126 Deno.test("createProject refuses a non-empty destination without changing it", async () => {@@ -59,6 +59,9 @@ import uiContract from "../apps/reference/src/ui-contract.ts" with { type: "text
5959 import authorBoundaryTest from "../apps/reference/tests/author-boundary_test.ts" with {6060 type: "text",6161 };62+import testingContractTest from "../apps/reference/tests/testing-contract_test.ts" with {63+ type: "text",64+};6265 import tsconfig from "../apps/reference/tsconfig.json" with { type: "text" };6366 6467 /** Every source-controlled file copied from the validated reference app into a new project. */@@ -100,5 +103,6 @@ export const STARTER_TEMPLATE: Readonly<Record<string, string>> = {
100103 "src/styles/global.css": globalStyles,101104 "src/ui-contract.ts": uiContract,102105 "tests/author-boundary_test.ts": authorBoundaryTest,106+ "tests/testing-contract_test.ts": testingContractTest,103107 "tsconfig.json": tsconfig,104108 };@@ -2,7 +2,7 @@
22 ".env.example": "c22aed73c7089168ac777fd4f68ad504f9b826ea7185b705514a4ac5505918b1",33 ".gitignore": "9efb15c6a9bfc20f296ed712e74273b6015a0dd9a40f7e861b8711dcf61825f1",44 "astro.config.ts": "8a19cae348af7fcbd9db119d2423dd2e464f0e5ace6e5723d06cd3a1cc9a0d4b",5- "deno.json": "11183a356cb65dc17394945622fffd16828c5f47fb88388451b61850c620d3f8",5+ "deno.json": "1285b00d154c19fe9104d7b13eff503cd95d628574d409177cdfbf7d652a98ac",66 "public/favicon.svg": "23efdb888dae688715faafe3ef94f7b5ad1976afcc715c0a742218b54732c6ad",77 "public/manifest.webmanifest": "d23457fe8df68a16181fde1d4ecca4b69d3b050b5fa3bf8f4051cb05bde1d3d6",88 "public/sw.js": "d816161fd5a35f2c477ca72eaa5ba58eb8d94795a4399d29a19838e886dafa31",@@ -40,5 +40,6 @@
4040 "src/styles/global.css": "7cbe243842f3bca32038d99a4872afe30c346cf7137387ce41861c9333a1f5c0",4141 "src/ui-contract.ts": "fc40d20dff6ba870c0de038839e66cb61d4349031e4a7748d963ca182e8bbec0",4242 "tests/author-boundary_test.ts": "7ea79031ed4ae7d7966bef2e456e02efe7d93d82c8f0bee219d885d300260ed2",43+ "tests/testing-contract_test.ts": "4257306060d42566b879d92b3a6c395805b20f53717bee55d670c0ef7a117eec",4344 "tsconfig.json": "fe2e5acc66101ed42d893d7e7063d07d298927621b351adcfb1ebde6c3a0a2ac"4445 }