Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
- To run tests for a specific file, use `deno task test ./src/server.test.tsx`
- Prefer running tests more narrowly to reduce token usage. Output is large
when running all tests.
- Use `--reporter=dot` when running all tests, or any run where you don't need
a test's console output — it prints detail only for failures, keeping output
small. Drop it only when you need debug logs from the specific test you're
inspecting.
- Temporarily change `describe` or `it` to `describe.only` or `it.only` to
focus specific test groups or cases.
- Workspace-specific test tasks are available:
Expand Down
12 changes: 7 additions & 5 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,11 @@ APP_ENV=production
NODE_ENV=production
```

**`.env.test`** - Test settings (uses a different port so tests can run
alongside the dev server):
**`.env.test`** - Test settings:

```bash
APP_ENV=test
OTEL_SERVICE_NAME=my-app-test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
```

> **Note:** These environment files contain only non-sensitive configuration.
Expand Down Expand Up @@ -334,13 +332,17 @@ deno task serve:prod

### Running Tests

Run your test suite on a separate port (8100) so tests don't conflict with the
dev server:
Run your test suite:

```bash
deno task test
```

Tests that spawn the server inject `DENO_SERVE_ADDRESS=tcp:127.0.0.1:0` so it
binds an OS-assigned free port, then discover the actual URL from the server's
`Listening on` line. Parallel test runs never collide with each other or with
the dev server.

### Code Quality

Check formatting, linting, and type errors:
Expand Down
15 changes: 11 additions & 4 deletions docs/tutorials/blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ Create `main.test.ts` to test the server serves your application:

```typescript
// main.test.ts
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -948,6 +948,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -956,13 +957,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand All @@ -975,7 +979,10 @@ describe("serves application when running main.ts", () => {
This test:

- Verifies static files are served correctly
- Spawns the actual server process and makes HTTP requests
- Spawns the actual server process with `DENO_SERVE_ADDRESS=tcp:127.0.0.1:0` so
the OS assigns a free port — parallel test runs never collide
- Discovers the server's actual URL from its `Listening on` line before making
HTTP requests
- Checks the HTML response contains expected content

For more testing patterns including loader testing, action testing, mocking, and
Expand Down
1 change: 0 additions & 1 deletion example/.env.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
DATABASE_URL=postgresql://test:password@localhost:9401/test
3 changes: 2 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ Run your test suite:
deno task test
```

Tests run on port 8100 by default so they don't conflict with the dev server.
Tests use an OS-assigned port so they don't conflict with the dev server or with
parallel test runs.

## Code Quality

Expand Down
17 changes: 7 additions & 10 deletions example/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -31,6 +31,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -39,20 +40,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
const address = Deno.build.os === "windows"
? "http://localhost:8100/"
: "http://0.0.0.0:8100/ (http://localhost:8100/)";
assertEquals(
line,
`Listening on ${address}`,
);
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand Down
2 changes: 1 addition & 1 deletion src/utils/global-jsdom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import globalJsdom from "global-jsdom";
import { stubFormData } from "./testing.ts";

// DENO_SERVE_ADDRESS format: "tcp:0.0.0.0:8100".
// DENO_SERVE_ADDRESS format: "tcp:0.0.0.0:8000".
const address = Deno.env.get("DENO_SERVE_ADDRESS");
let port = 8000;
if (address) {
Expand Down
1 change: 0 additions & 1 deletion templates/minimal/.env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
3 changes: 2 additions & 1 deletion templates/minimal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Run your test suite:
deno task test
```

Tests run on port 8100 by default so they don't conflict with the dev server.
Tests use an OS-assigned port so they don't conflict with the dev server or with
parallel test runs.

## Code Quality

Expand Down
17 changes: 7 additions & 10 deletions templates/minimal/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -31,6 +31,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -39,20 +40,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
const address = Deno.build.os === "windows"
? "http://localhost:8100/"
: "http://0.0.0.0:8100/ (http://localhost:8100/)";
assertEquals(
line,
`Listening on ${address}`,
);
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand Down
1 change: 0 additions & 1 deletion templates/postgres/.env.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app_test
6 changes: 3 additions & 3 deletions templates/postgres/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ point at your managed PostgreSQL instance.
deno task test
```

Tests run on port 8100 and connect to the `app_test` database, so make sure
PostgreSQL is running and migrated (`deno task docker:start` then
`deno task db:migrate`) before running them.
Tests use an OS-assigned port (parallel-safe) and connect to the `app_test`
database, so make sure PostgreSQL is running and migrated
(`deno task docker:start` then `deno task db:migrate`) before running them.

Any test that triggers a query should call `await closeDb()` in an `afterAll`
hook (see [services/message.test.ts](services/message.test.ts)) to release the
Expand Down
17 changes: 7 additions & 10 deletions templates/postgres/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -31,6 +31,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -39,20 +40,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
const address = Deno.build.os === "windows"
? "http://localhost:8100/"
: "http://0.0.0.0:8100/ (http://localhost:8100/)";
assertEquals(
line,
`Listening on ${address}`,
);
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand Down
1 change: 0 additions & 1 deletion templates/tailwindcss/.env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
3 changes: 2 additions & 1 deletion templates/tailwindcss/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Run your test suite:
deno task test
```

Tests run on port 8100 by default so they don't conflict with the dev server.
Tests use an OS-assigned port so they don't conflict with the dev server or with
parallel test runs.

## Code Quality

Expand Down
17 changes: 7 additions & 10 deletions templates/tailwindcss/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -31,6 +31,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -39,20 +40,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
const address = Deno.build.os === "windows"
? "http://localhost:8100/"
: "http://0.0.0.0:8100/ (http://localhost:8100/)";
assertEquals(
line,
`Listening on ${address}`,
);
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand Down
1 change: 0 additions & 1 deletion templates/tanstack/.env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
3 changes: 2 additions & 1 deletion templates/tanstack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Run your test suite:
deno task test
```

Tests run on port 8100 by default so they don't conflict with the dev server.
Tests use an OS-assigned port so they don't conflict with the dev server or with
parallel test runs.

## Code Quality

Expand Down
17 changes: 7 additions & 10 deletions templates/tanstack/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertEquals, assertStringIncludes } from "@std/assert";
import { assert, assertEquals, assertStringIncludes } from "@std/assert";
import { resolve } from "@std/path/resolve";
import { mergeReadableStreams, TextLineStream } from "@std/streams";
import { describe, it } from "@std/testing/bdd";
Expand Down Expand Up @@ -31,6 +31,7 @@ describe("serves application when running main.ts", () => {
`--env-file=${resolve(import.meta.dirname!, "./.env.test")}`,
resolve(import.meta.dirname!, "./main.ts"),
],
env: { DENO_SERVE_ADDRESS: "tcp:127.0.0.1:0" },
stdout: "piped",
stderr: "piped",
});
Expand All @@ -39,20 +40,16 @@ describe("serves application when running main.ts", () => {
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());

let url = "";
for await (const line of stdout.values({ preventCancel: true })) {
if (line.includes("Listening on")) {
const address = Deno.build.os === "windows"
? "http://localhost:8100/"
: "http://0.0.0.0:8100/ (http://localhost:8100/)";
assertEquals(
line,
`Listening on ${address}`,
);
if (line.includes("Listening on ")) {
url = line.split("Listening on ")[1].split(" ")[0];
break;
}
}
assert(url, "server did not report its address");

const res = await fetch("http://localhost:8100/");
const res = await fetch(url);
assertEquals(res.status, 200);
assertEquals(res.headers.get("content-type"), "text/html; charset=utf-8");
const html = await res.text();
Expand Down
1 change: 0 additions & 1 deletion tutorials/blog/.env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
APP_ENV=test
OTEL_SERVICE_NAME=test
DENO_SERVE_ADDRESS=tcp:0.0.0.0:8100
3 changes: 2 additions & 1 deletion tutorials/blog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Run your test suite:
deno task test
```

Tests run on port 8100 by default so they don't conflict with the dev server.
Tests use an OS-assigned port so they don't conflict with the dev server or with
parallel test runs.

## Code Quality

Expand Down
Loading
Loading