Skip to content

Commit 85c17fa

Browse files
fix: nested index route not working in prod builds (#3132)
This was due to a mismatch in the disk snapshot compared to in memory.
1 parent e9f0a4b commit 85c17fa

File tree

7 files changed

+69
-28
lines changed

7 files changed

+69
-28
lines changed

init/src/init.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ app.fsRoutes();`;
379379
`import type { ComponentChildren } from "preact";
380380
381381
export interface ButtonProps {
382+
id?: string;
382383
onClick?: () => void;
383384
children?: ComponentChildren;
384385
disabled?: boolean;
@@ -472,9 +473,9 @@ interface CounterProps {
472473
export default function Counter(props: CounterProps) {
473474
return (
474475
<div class="flex gap-8 py-6">
475-
<Button onClick={() => props.count.value -= 1}>-1</Button>
476+
<Button id="decrement" onClick={() => props.count.value -= 1}>-1</Button>
476477
<p class="text-3xl tabular-nums">{props.count}</p>
477-
<Button onClick={() => props.count.value += 1}>+1</Button>
478+
<Button id="increment" onClick={() => props.count.value += 1}>+1</Button>
478479
</div>
479480
);
480481
}`;

init/src/init_test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ Deno.test("init - can start dev server", async () => {
177177
await patchProject(dir);
178178
await withChildProcessServer(
179179
dir,
180-
"dev",
180+
["task", "dev"],
181181
async (address) => {
182182
await withBrowser(async (page) => {
183183
await page.goto(address);
184-
await page.locator("button").click();
184+
await page.locator("#decrement").click();
185185
await waitForText(page, "button + p", "2");
186186
});
187187
},
@@ -210,7 +210,7 @@ Deno.test("init - can start built project", async () => {
210210

211211
await withChildProcessServer(
212212
dir,
213-
"start",
213+
["task", "start"],
214214
async (address) => {
215215
await withBrowser(async (page) => {
216216
await page.goto(address);

src/dev/builder_test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import * as path from "@std/path";
33
import { Builder, specToName } from "./builder.ts";
44
import { App } from "../app.ts";
55
import { BUILD_ID } from "../runtime/build_id.ts";
6-
import { withTmpDir } from "../test_utils.ts";
6+
import { withTmpDir, writeFiles } from "../test_utils.ts";
7+
import { withChildProcessServer } from "../../tests/test_utils.tsx";
78

89
Deno.test({
910
name: "Builder - chain onTransformStaticFile",
@@ -241,6 +242,42 @@ Deno.test({
241242
sanitizeResources: false,
242243
});
243244

245+
Deno.test({
246+
name: "Builder - write prod routePattern",
247+
fn: async () => {
248+
const root = path.join(import.meta.dirname!, "..", "..");
249+
await using _tmp = await withTmpDir({ dir: root, prefix: "tmp_builder_" });
250+
const tmp = _tmp.dir;
251+
252+
await writeFiles(tmp, {
253+
"routes/foo/index.ts": `export const handler = () => new Response("ok")`,
254+
"main.ts": `import { App } from "fresh";
255+
export const app = new App().fsRoutes()`,
256+
});
257+
258+
const builder = new Builder({
259+
root: tmp,
260+
outDir: path.join(tmp, "dist"),
261+
});
262+
263+
await builder.build();
264+
265+
let text = "fail";
266+
await withChildProcessServer(
267+
tmp,
268+
["serve", "-A", "dist/server.js"],
269+
async (address) => {
270+
const res = await fetch(`${address}/foo`);
271+
text = await res.text();
272+
},
273+
);
274+
275+
expect(text).toEqual("ok");
276+
},
277+
sanitizeOps: false,
278+
sanitizeResources: false,
279+
});
280+
244281
Deno.test("specToName", () => {
245282
// HTTP
246283
expect(specToName("http://example.com")).toEqual("example");

src/dev/dev_build_cache.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,10 @@ ${
405405
.map((item, i) => {
406406
const id = JSON.stringify(item.id);
407407
const pattern = JSON.stringify(item.pattern);
408+
const type = JSON.stringify(item.type);
409+
const routePattern = JSON.stringify(item.routePattern);
408410
409-
return ` { id: ${id}, mod: fsRoute_${i}, type: ${
410-
JSON.stringify(item.type)
411-
}, pattern: ${pattern} },`;
411+
return ` { id: ${id}, mod: fsRoute_${i}, type: ${type}, pattern: ${pattern}, routePattern: ${routePattern} },`;
412412
})
413413
.join("\n")
414414
}

src/test_utils.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { WalkEntry } from "@std/fs/walk";
66
import { DEFAULT_CONN_INFO } from "./app.ts";
77
import type { Command } from "./commands.ts";
88
import { fsItemsToCommands, type FsRouteFile } from "./fs_routes.ts";
9+
import * as path from "@std/path";
910

1011
const STUB = {} as unknown as Deno.ServeHandlerInfo;
1112

@@ -159,3 +160,19 @@ export class MockBuildCache<State> implements BuildCache<State> {
159160
return Promise.resolve(null);
160161
}
161162
}
163+
164+
export async function writeFiles(dir: string, files: Record<string, string>) {
165+
const entries = Object.entries(files);
166+
await Promise.all(entries.map(async (entry) => {
167+
const [pathname, content] = entry;
168+
const fullPath = path.join(dir, pathname);
169+
try {
170+
await Deno.mkdir(path.dirname(fullPath), { recursive: true });
171+
await Deno.writeTextFile(fullPath, content);
172+
} catch (err) {
173+
if (!(err instanceof Deno.errors.AlreadyExists)) {
174+
throw err;
175+
}
176+
}
177+
}));
178+
}

tests/test_utils.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ export async function withBrowser(fn: (page: Page) => void | Promise<void>) {
9797

9898
export async function withChildProcessServer(
9999
dir: string,
100-
task: string,
100+
args: string[],
101101
fn: (address: string) => void | Promise<void>,
102102
) {
103103
const aborter = new AbortController();
104104
const cp = await new Deno.Command(Deno.execPath(), {
105-
args: ["task", task],
105+
args,
106106
stdin: "null",
107107
stdout: "piped",
108108
stderr: "piped",
@@ -137,6 +137,8 @@ export async function withChildProcessServer(
137137
}
138138

139139
if (!found) {
140+
// deno-lint-ignore no-console
141+
console.log(output);
140142
throw new Error(`Could not find server address`);
141143
}
142144

update/src/update_test.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,7 @@ import {
88
import { expect } from "@std/expect";
99
import { spy, type SpyCall } from "@std/testing/mock";
1010
import { walk } from "@std/fs/walk";
11-
import { withTmpDir } from "../../src/test_utils.ts";
12-
13-
async function writeFiles(dir: string, files: Record<string, string>) {
14-
const entries = Object.entries(files);
15-
await Promise.all(entries.map(async (entry) => {
16-
const [pathname, content] = entry;
17-
const fullPath = path.join(dir, pathname);
18-
try {
19-
await Deno.mkdir(path.dirname(fullPath), { recursive: true });
20-
await Deno.writeTextFile(fullPath, content);
21-
} catch (err) {
22-
if (!(err instanceof Deno.errors.AlreadyExists)) {
23-
throw err;
24-
}
25-
}
26-
}));
27-
}
11+
import { withTmpDir, writeFiles } from "../../src/test_utils.ts";
2812

2913
async function readFiles(dir: string): Promise<Record<string, string>> {
3014
const files: Record<string, string> = {};

0 commit comments

Comments
 (0)