78 lines
3.4 KiB
TypeScript
78 lines
3.4 KiB
TypeScript
// @vitest-environment node
|
|
import { readFileSync, readdirSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
// 사용자 지정 문자열은 편집자가 회사 이름을 추측해 정규화하지 못하도록
|
|
// 화면 테스트와 문서 계약에서 원문 그대로 고정한다.
|
|
describe("릴리스 문서 계약", () => {
|
|
it("Node 최소 버전은 잠긴 의존성이 요구하는 22.22.2와 일치한다", () => {
|
|
const metadata = JSON.parse(readFileSync("package.json", "utf8"));
|
|
const lock = JSON.parse(readFileSync("package-lock.json", "utf8"));
|
|
expect.soft(metadata.engines.node).toBe(">=22.22.2");
|
|
expect.soft(lock.packages[""].engines.node).toBe(">=22.22.2");
|
|
expect(lock.packages["node_modules/jsdom"].engines.node).toContain(
|
|
"^22.22.2",
|
|
);
|
|
for (const path of ["README.md", "docs/DEPLOYMENT.md"]) {
|
|
const document = readFileSync(path, "utf8");
|
|
expect.soft(document, path).toContain("22.22.2");
|
|
expect.soft(document, path).not.toContain("22.12");
|
|
}
|
|
});
|
|
it("프로젝트는 비공개 권리 유보이며 저장소 주소를 명시한다", () => {
|
|
const metadata = JSON.parse(readFileSync("package.json", "utf8"));
|
|
const lock = JSON.parse(readFileSync("package-lock.json", "utf8"));
|
|
expect.soft(metadata.private).toBe(true);
|
|
expect.soft(metadata.license).toBe("UNLICENSED");
|
|
expect.soft(lock.packages[""].license).toBe("UNLICENSED");
|
|
expect.soft(metadata.repository).toEqual({
|
|
type: "git",
|
|
url: "https://source.ibit.kr/OZ-Group/Find-Word.git",
|
|
});
|
|
expect
|
|
.soft(metadata.homepage)
|
|
.toBe("https://source.ibit.kr/OZ-Group/Find-Word");
|
|
const license = readFileSync("LICENSE", "utf8");
|
|
expect(license).toMatch(/private/i);
|
|
expect(license).toContain("All rights reserved.");
|
|
expect(readFileSync("README.md", "utf8")).toContain(metadata.homepage);
|
|
});
|
|
it("잠금 파일의 모든 런타임 의존성 notice 전문을 배포용 사본에 보존한다", () => {
|
|
const lock = JSON.parse(readFileSync("package-lock.json", "utf8")) as {
|
|
packages: Record<string, { dev?: boolean; version: string }>;
|
|
};
|
|
const notice = readFileSync("THIRD_PARTY_NOTICES.md", "utf8");
|
|
expect(readFileSync("public/THIRD_PARTY_NOTICES.md", "utf8")).toBe(notice);
|
|
for (const [path, pkg] of Object.entries(lock.packages)) {
|
|
if (!path || pkg.dev) continue;
|
|
const name = path.split("node_modules/").at(-1)!;
|
|
const license = readFileSync(`${path}/LICENSE`, "utf8").trim();
|
|
expect(notice).toContain(`## ${name} ${pkg.version}\n\n${license}`);
|
|
}
|
|
});
|
|
it("브랜드 문구를 사용자 원문 그대로 문서에도 보존한다", () => {
|
|
const credit = "Designed by OZ at Heat-T Medical Inc.";
|
|
for (const path of [
|
|
"README.md",
|
|
".agent/TASK.md",
|
|
".agent/ACCEPTANCE.md",
|
|
".agent/CONTEXT.md",
|
|
]) {
|
|
expect.soft(readFileSync(path, "utf8"), path).toContain(credit);
|
|
}
|
|
for (const path of [
|
|
"README.md",
|
|
...["docs", ".agent"].flatMap((dir) =>
|
|
readdirSync(dir)
|
|
.filter((file) => file.endsWith(".md"))
|
|
.map((file) => `${dir}/${file}`),
|
|
),
|
|
]) {
|
|
// 잘못된 표기를 다시 권장하는 문서가 남아 있으면 다음 편집 때 회귀한다.
|
|
expect
|
|
.soft(readFileSync(path, "utf8"), path)
|
|
.not.toContain(["HearT", "M"].join("-"));
|
|
}
|
|
});
|
|
});
|