mirror of
https://github.com/willchen96/mike.git
synced 2026-07-24 23:41:04 +02:00
test: minimal vitest harness for backend and frontend
Ported from amal66/mike#24 onto current main; lockfiles regenerated against this tree. Adds vitest as a dev dependency with a `test` script in both packages, excludes test files from the backend tsc build, and seeds one suite per package (backend: downloadTokens, 12 tests; frontend: cn() utils, 8 tests). Verified locally: backend 12/12, frontend 8/8 passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
dafac6b0a4
commit
4039b94980
7 changed files with 2683 additions and 31 deletions
1320
frontend/package-lock.json
generated
1320
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,6 +7,7 @@
|
|||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint",
|
||||
"test": "vitest run",
|
||||
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||
"upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
|
||||
|
|
@ -73,6 +74,7 @@
|
|||
"tailwindcss": "^4",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "^5",
|
||||
"vitest": "^4.1.9",
|
||||
"wrangler": "^4.90.0"
|
||||
},
|
||||
"license": "AGPL-3.0-only"
|
||||
|
|
|
|||
45
frontend/src/app/lib/utils.test.ts
Normal file
45
frontend/src/app/lib/utils.test.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { cn, diceCoefficient, isFuzzyMatch } from "./utils";
|
||||
|
||||
describe("cn", () => {
|
||||
it("joins truthy class names and drops falsy ones", () => {
|
||||
expect(cn("a", false && "b", undefined, "c")).toBe("a c");
|
||||
});
|
||||
|
||||
it("merges conflicting tailwind classes, keeping the last", () => {
|
||||
expect(cn("px-2", "px-4")).toBe("px-4");
|
||||
});
|
||||
});
|
||||
|
||||
describe("diceCoefficient", () => {
|
||||
it("returns 1 for identical strings (ignoring case and punctuation)", () => {
|
||||
expect(diceCoefficient("Hello, World!", "hello world")).toBe(1);
|
||||
});
|
||||
|
||||
it("returns 0 when either input is empty", () => {
|
||||
expect(diceCoefficient("", "anything")).toBe(0);
|
||||
expect(diceCoefficient("anything", "")).toBe(0);
|
||||
});
|
||||
|
||||
it("returns a partial score for partially overlapping strings", () => {
|
||||
const score = diceCoefficient("night", "nacht");
|
||||
expect(score).toBeGreaterThan(0);
|
||||
expect(score).toBeLessThan(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isFuzzyMatch", () => {
|
||||
it("matches near-identical strings above the default threshold", () => {
|
||||
expect(isFuzzyMatch("organization", "organisation")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects clearly different strings", () => {
|
||||
expect(isFuzzyMatch("apple", "zebra")).toBe(false);
|
||||
});
|
||||
|
||||
it("respects a custom threshold", () => {
|
||||
// "night" vs "nacht" scores ~0.25 — passes a low bar, fails a high one.
|
||||
expect(isFuzzyMatch("night", "nacht", 0.1)).toBe(true);
|
||||
expect(isFuzzyMatch("night", "nacht", 0.9)).toBe(false);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue