quill/val Public Public: anyone can read this; nobody can change it.

forked from benjivers/val

workbenchthis machine
Files 30150dd4411f8ba5a6d6f491b04252cf4f760e38
70 lines · 2.6 KB · ~763 tok Raw History
1
import { expect, test } from "bun:test";
2
import { mkdtempSync } from "node:fs";
3
import { tmpdir } from "node:os";
4
import { join } from "node:path";
5
6
process.env.FORGE_APP_DATA = mkdtempSync(join(tmpdir(), "app-"));
7
process.env.PORT = "0";
8
const { server } = await import("./server.ts");
9
const base = `http://${server.hostname}:${server.port}`;
10
11
test("serves the page", async () => {
12
  const response = await fetch(base + "/");
13
  expect(response.status).toBe(200);
14
  expect(await response.text()).toContain("<h1>");
15
});
16
17
test("keeps a note", async () => {
18
  const form = new FormData();
19
  form.set("body", "hello from a test");
20
  const posted = await fetch(base + "/notes", { method: "POST", body: form, redirect: "manual" });
21
  expect(posted.status).toBe(303);
22
  expect(await (await fetch(base + "/")).text()).toContain("hello from a test");
23
});
24
25
test("stands on the security floor", async () => {
26
  const response = await fetch(base + "/");
27
  expect(response.headers.get("content-security-policy")).toContain("default-src 'self'");
28
  expect(response.headers.get("x-content-type-options")).toBe("nosniff");
29
});
30
31
test("a bug answers with the floor, not the runtime's page", async () => {
32
  // A percent-escape that is not one makes the search params throw.
33
  const response = await fetch(base + "/notes", {
34
    method: "POST",
35
    headers: { "content-type": "application/x-www-form-urlencoded" },
36
    body: "body=%E0%A4%A",
37
  });
38
  expect(response.status).toBe(200);
39
  expect(response.headers.get("content-security-policy")).toContain("default-src 'self'");
40
});
41
42
test("a body is capped by the bytes read, whatever it claims", async () => {
43
  // The cap counts bytes as they arrive and never reads Content-Length, so
44
  // a chunked body with no length is refused the same way this one is.
45
  const response = await fetch(base + "/notes", {
46
    method: "POST",
47
    headers: { "content-type": "application/x-www-form-urlencoded" },
48
    body: "body=" + "x".repeat(1024 * 1024),
49
  });
50
  expect(response.status).toBe(413);
51
});
52
53
test("HEAD sees the app up", async () => {
54
  const response = await server.fetch(new Request(base + "/", { method: "HEAD" }));
55
  expect(response.status).toBe(200);
56
  expect(await response.text()).toBe("");
57
});
58
59
test("refuses a cross-site post", async () => {
60
  const form = new FormData();
61
  form.set("body", "from another site");
62
  const posted = await fetch(base + "/notes", {
63
    method: "POST",
64
    body: form,
65
    redirect: "manual",
66
    headers: { origin: "https://evil.example", "sec-fetch-site": "cross-site" },
67
  });
68
  expect(posted.status).toBe(403);
69
  expect(await (await fetch(base + "/")).text()).not.toContain("from another site");
70
});
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts