kanban-dev-webapp/src/lib/git/conventional.test.ts

88 lines
No EOL
3.1 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { parseCommitMessage } from "@/lib/git/conventional";
describe("parseCommitMessage", () => {
it("pulls out type, scope and subject", () => {
expect(parseCommitMessage("feat(stock): inline qty editing")).toEqual({
type: "feat",
scope: "stock",
subject: "inline qty editing",
breaking: false,
});
});
it("handles a missing scope", () => {
expect(parseCommitMessage("fix: correct the total")).toEqual({
type: "fix",
scope: "",
subject: "correct the total",
breaking: false,
});
});
it("flags a breaking change with and without a scope", () => {
expect(parseCommitMessage("feat!: drop v1 API").breaking).toBe(true);
expect(parseCommitMessage("feat(api)!: drop v1").breaking).toBe(true);
expect(parseCommitMessage("feat(api)!: drop v1").scope).toBe("api");
});
it("reads only the first line", () => {
const message =
"feat(customers): lift the toggle\n\nA long body that\nmentions fix(other): things\n";
expect(parseCommitMessage(message)).toEqual({
type: "feat",
scope: "customers",
subject: "lift the toggle",
breaking: false,
});
});
it("lowercases the type and the scope", () => {
const parsed = parseCommitMessage("Feat(Stock): thing");
expect(parsed.type).toBe("feat");
expect(parsed.scope).toBe("stock");
});
it("classifies an unparseable message as other, keeping the subject", () => {
expect(parseCommitMessage("just some words")).toEqual({
type: "other",
scope: "",
subject: "just some words",
breaking: false,
});
});
it("does not accept a space before the parenthesis", () => {
// "feat (stock): x" is not a conventional commit. Accepting it would make
// the scope breakdown depend on invisible whitespace.
expect(parseCommitMessage("feat (stock): x").type).toBe("other");
});
it("accepts any single lowercase word as a type, but not a phrase", () => {
// "note" is not a conventional type, but the parser cannot tell an unknown
// type from prose shaped like one, and it must not police a whitelist —
// see the note after Step 4.
expect(parseCommitMessage("note: this is not conventional").type).toBe("note");
// A space before the colon means it is a sentence, not a prefix.
expect(parseCommitMessage("TODO tomorrow: finish").type).toBe("other");
});
it("rejects a type containing non-letters", () => {
expect(parseCommitMessage("feat2(x): thing").type).toBe("other");
});
it("trims and caps an over-long subject", () => {
const parsed = parseCommitMessage(`feat(x): ${"s".repeat(400)}`);
expect(parsed.subject).toHaveLength(200);
});
it("returns other for an empty message", () => {
expect(parseCommitMessage("").type).toBe("other");
expect(parseCommitMessage(" \n ").subject).toBe("");
});
it("handles a scope containing a hyphen or slash", () => {
expect(parseCommitMessage("fix(delivery-notes): x").scope).toBe("delivery-notes");
expect(parseCommitMessage("fix(api/v1): x").scope).toBe("api/v1");
});
});