Skip to content
Closed
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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ transfers.
- A CLI (`groups`, `balances <group>`, `export <group>`) alongside the web
page and API.

## Run it

```sh
bun install
bun run dev # serves http://localhost:3200
```

The first run creates `splitbill.sqlite` and seeds two demo groups
(`goa-trip`, `flat-4b`).

The CLI reads the same database:

```sh
bun run src/cli.ts groups
```

`bun run src/cli.ts balances <group>` and `bun run src/cli.ts export <group>`
are also available, e.g. `bun run src/cli.ts balances goa-trip`.

## Stack

Bun, TypeScript, Hono, `bun:sqlite`. No build step for the web page
Expand Down
50 changes: 50 additions & 0 deletions tests/readme.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, expect, test } from "bun:test";

const root = new URL("..", import.meta.url).pathname;

async function readme(): Promise<string> {
return Bun.file(new URL("../README.md", import.meta.url)).text();
}

function runItSection(text: string): string {
const start = text.indexOf("## Run it");
expect(start).toBeGreaterThanOrEqual(0);
const next = text.indexOf("\n## ", start + 1);
return next === -1 ? text.slice(start) : text.slice(start, next);
}

describe("README Run it section", () => {
test("README has a Run it section with install, dev and CLI commands", async () => {
const section = runItSection(await readme());
expect(section).toContain("bun install");
expect(section).toContain("bun run dev");
expect(section).toContain("http://localhost:3200");
expect(section).toContain("bun run src/cli.ts groups");
});

test("README dev URL port matches the server default", async () => {
const section = runItSection(await readme());
const port = section.match(/http:\/\/localhost:(\d+)/)?.[1];
expect(port).toBeDefined();
const server = await Bun.file(new URL("../src/server.ts", import.meta.url)).text();
expect(server).toMatch(new RegExp(`process\\.env\\.PORT\\s*\\?\\?\\s*${port}\\b`));
});

test("documented CLI example lists the demo groups", async () => {
const proc = Bun.spawn([process.execPath, "run", "src/cli.ts", "groups"], {
cwd: root,
env: { ...process.env, SPLITBILL_DB: ":memory:" },
stdout: "pipe",
stderr: "pipe",
timeout: 10_000,
});
const [output, errors, code] = await Promise.all([
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
proc.exited,
]);
expect({ code, errors }).toEqual({ code: 0, errors: "" });
expect(output).toContain("goa-trip");
expect(output).toContain("flat-4b");
});
});
Loading