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
11 changes: 10 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,14 @@ if ! bun run build; then
exit 1
fi

# Run unit tests
echo "Running bun test..."
if ! bun run test; then
echo ""
echo "Error: Unit tests failed! Please fix failing tests before committing."
echo "Run 'cd frontend && bun run test' to see the failures."
exit 1
fi

echo "All checks passed! Proceeding with commit..."
exit 0
exit 0
48 changes: 48 additions & 0 deletions .github/workflows/frontend-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Frontend Tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
test-frontend:
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.2.2

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
frontend/node_modules
key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install dependencies
working-directory: ./frontend
run: bun install

- name: Format check
working-directory: ./frontend
run: bun run format:check

- name: Lint
working-directory: ./frontend
run: bun run lint

- name: Typecheck
working-directory: ./frontend
run: bun run typecheck

- name: Unit tests
working-directory: ./frontend
run: bun run test
3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"build": "tsc -b && vite build",
"build:fast": "vite build",
"lint": "eslint './src/**/*.{ts,tsx}'",
"typecheck": "tsc -b",
"test": "bun test",
"test:coverage": "bun test --coverage",
"preview": "vite preview",
"add": "bunx shadcn-ui@latest add",
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
Expand Down
35 changes: 35 additions & 0 deletions frontend/src/lib/test/der-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type BunPluginApi = {
plugin: (options: {
name: string;
setup: (build: {
onLoad: (
options: { filter: RegExp },
callback: (args: {
path: string;
}) => { contents: string; loader?: string } | Promise<{ contents: string; loader?: string }>
) => void;
}) => void;
}) => void;
file: (path: string) => { arrayBuffer: () => Promise<ArrayBuffer> };
};

const bun = (globalThis as unknown as { Bun?: BunPluginApi }).Bun;

if (bun) {
bun.plugin({
name: "der-loader",
setup(build) {
build.onLoad({ filter: /\.der$/ }, async (args) => {
const buffer = await bun.file(args.path).arrayBuffer();
const bytes = new Uint8Array(buffer);

return {
contents: `export default new Uint8Array([${Array.from(bytes).join(",")}]);`,
loader: "js"
};
});
}
});
}

export {};
1 change: 1 addition & 0 deletions frontend/src/lib/test/preload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
Comment thread
AnthonyRonning marked this conversation as resolved.
75 changes: 75 additions & 0 deletions frontend/src/utils/markdown.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { describe, expect, it } from "bun:test";

import { truncateMarkdownPreservingLinks } from "./markdown";

describe("truncateMarkdownPreservingLinks", () => {
it("returns the original text when already within maxLength", () => {
expect(truncateMarkdownPreservingLinks("hello", 10)).toBe("hello");
});

it("safely truncates when there are no links", () => {
expect(truncateMarkdownPreservingLinks("abcdef", 3)).toBe("abc...");
});

it("converts a plain URL into a markdown link when truncation would cut it", () => {
const before = "Check this ";
const url = "https://example.com/very/long/path";
const after = " for more";
const text = `${before}${url}${after}`;

const maxLength = before.length + 12;
expect(maxLength).toBeGreaterThan(before.length);
expect(maxLength).toBeLessThan(before.length + url.length);

const result = truncateMarkdownPreservingLinks(text, maxLength);
expect(result).toBe(`${before}[${url.slice(0, 12)}...](${url})`);
});

it("does not convert a URL that is already inside a markdown link", () => {
const before = "Go to ";
const link = "[site](https://example.com/very/long/path)";
const after = " now";
const text = `${before}${link}${after}`;

const maxLength = before.length + 5;
const result = truncateMarkdownPreservingLinks(text, maxLength);

expect(result).toBe("Go to...");
});

it("truncates before a markdown link if truncation would break it", () => {
const before = "Start ";
const link = "[docs](https://example.com/docs)";
const after = " end";
const text = `${before}${link}${after}`;

const maxLength = before.length + 1;
const result = truncateMarkdownPreservingLinks(text, maxLength);

expect(result).toBe("Start...");
});

it("does not convert a URL when truncation happens exactly at the URL boundary", () => {
const before = "Before ";
const url = "https://example.com/very/long/path";
const after = " after";
const text = `${before}${url}${after}`;

expect(truncateMarkdownPreservingLinks(text, before.length)).toBe(`${before}...`);
expect(truncateMarkdownPreservingLinks(text, before.length + url.length)).toBe(
`${before}${url}...`
);
});

it("converts the correct plain URL when multiple links exist", () => {
const md = "See [x](https://x.test) and ";
const url = "https://example.com/very/long/path";
const after = " for details";
const text = `${md}${url}${after}`;

const maxLength = md.length + 8;
const result = truncateMarkdownPreservingLinks(text, maxLength);

expect(result).toBe(`${md}[${url.slice(0, 8)}...](${url})`);
});
});
3 changes: 2 additions & 1 deletion setup-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ git config core.hooksPath .githooks
echo "✅ Git hooks configured successfully!"
echo "The pre-commit hook will now:"
echo " 1. Check code formatting with 'bun run format:check'"
echo " 2. Run 'bun run build' to ensure the project builds"
echo " 2. Run 'bun run build' to ensure the project builds"
echo " 3. Run 'bun run test' to ensure unit tests pass"
Loading