Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

309 lines
10 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from "vitest";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import {
discoverInstalledPackages,
findDuplicates,
findOutdated,
compareSemver,
uniquePackageNames,
type DiscoveredPackage,
} from "../../src/commands/doctor";
interface PackageSpec {
name: string;
version: string;
installPath: string; // relative to fixture root
}
function writePackage(root: string, spec: PackageSpec): void {
const dir = path.join(root, spec.installPath);
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(
path.join(dir, "package.json"),
JSON.stringify({ name: spec.name, version: spec.version }),
);
}
describe("compareSemver", () => {
it("orders by major, minor, patch", () => {
expect(compareSemver("1.0.0", "1.0.1")).toBeLessThan(0);
expect(compareSemver("1.1.0", "1.0.9")).toBeGreaterThan(0);
expect(compareSemver("2.0.0", "1.99.99")).toBeGreaterThan(0);
expect(compareSemver("1.2.3", "1.2.3")).toBe(0);
});
it("treats a prerelease as less than the matching stable", () => {
expect(compareSemver("1.0.0-alpha", "1.0.0")).toBeLessThan(0);
expect(compareSemver("1.0.0", "1.0.0-alpha")).toBeGreaterThan(0);
expect(compareSemver("1.0.0-alpha.1", "1.0.0-alpha.2")).toBeLessThan(0);
expect(compareSemver("0.3.0-rc.1", "0.3.0")).toBeLessThan(0);
});
it("falls back to lexical comparison for unparseable strings", () => {
expect(compareSemver("a", "b")).toBeLessThan(0);
});
});
describe("doctor — package discovery", () => {
let root: string;
beforeAll(() => {
root = fs.mkdtempSync(path.join(os.tmpdir(), "aui-doctor-"));
fs.writeFileSync(
path.join(root, "package.json"),
JSON.stringify({
name: "fixture",
version: "1.0.0",
dependencies: {
"@assistant-ui/react": "0.14.5",
"@assistant-ui/react-ai-sdk": "1.3.26",
},
}),
);
// Top-level installs
writePackage(root, {
name: "@assistant-ui/react",
version: "0.14.5",
installPath: "node_modules/@assistant-ui/react",
});
writePackage(root, {
name: "@assistant-ui/core",
version: "0.2.5",
installPath: "node_modules/@assistant-ui/core",
});
writePackage(root, {
name: "@assistant-ui/react-ai-sdk",
version: "1.3.26",
installPath: "node_modules/@assistant-ui/react-ai-sdk",
});
writePackage(root, {
name: "assistant-stream",
version: "0.3.14",
installPath: "node_modules/assistant-stream",
});
// Transitive copy of @assistant-ui/core nested inside react-ai-sdk
writePackage(root, {
name: "@assistant-ui/core",
version: "0.2.2",
installPath:
"node_modules/@assistant-ui/react-ai-sdk/node_modules/@assistant-ui/core",
});
// Unrelated package that should be ignored
writePackage(root, {
name: "lodash",
version: "4.17.21",
installPath: "node_modules/lodash",
});
// A tracked package nested inside an *untracked* package — current
// behavior is to skip recursion into untracked subtrees so doctor
// stays fast on large repos.
writePackage(root, {
name: "@assistant-ui/core",
version: "0.0.0-buried",
installPath: "node_modules/lodash/node_modules/@assistant-ui/core",
});
// Dot-prefixed directories must be skipped
fs.mkdirSync(path.join(root, "node_modules", ".pnpm"), { recursive: true });
});
afterAll(() => {
fs.rmSync(root, { recursive: true, force: true });
});
it("collects every assistant-ui package, including nested transitives", () => {
const found = discoverInstalledPackages(root);
const summary = found
.map((p) => `${p.name}@${p.version}`)
.sort()
.join(",");
expect(summary).toContain("@assistant-ui/core@0.2.2");
expect(summary).toContain("@assistant-ui/core@0.2.5");
expect(summary).toContain("@assistant-ui/react@0.14.5");
expect(summary).toContain("@assistant-ui/react-ai-sdk@1.3.26");
expect(summary).toContain("assistant-stream@0.3.14");
expect(summary).not.toContain("lodash");
});
it("does not recurse into untracked packages' node_modules", () => {
const found = discoverInstalledPackages(root);
expect(found.find((p) => p.version === "0.0.0-buried")).toBeUndefined();
});
it("flags @assistant-ui/core as duplicated across versions", () => {
const dups = findDuplicates(discoverInstalledPackages(root));
expect(dups).toHaveLength(1);
expect(dups[0]!.name).toBe("@assistant-ui/core");
const versions = dups[0]!.installations.map((i) => i.version).sort();
expect(versions).toEqual(["0.2.2", "0.2.5"]);
});
});
describe("doctor — pnpm store discovery", () => {
let root: string;
beforeAll(() => {
root = fs.mkdtempSync(path.join(os.tmpdir(), "aui-doctor-pnpm-"));
fs.writeFileSync(
path.join(root, "package.json"),
JSON.stringify({
name: "fixture",
version: "1.0.0",
dependencies: { "@assistant-ui/react": "0.14.5" },
}),
);
// Direct dependency hoisted into the top-level node_modules.
writePackage(root, {
name: "@assistant-ui/react",
version: "0.14.5",
installPath: "node_modules/@assistant-ui/react",
});
// Two peer-closure-split copies of @assistant-ui/core, each in its own
// .pnpm virtual-store entry — the exact duplication class from #4101.
writePackage(root, {
name: "@assistant-ui/core",
version: "0.2.5",
installPath:
"node_modules/.pnpm/@assistant-ui+core@0.2.5_react@18.3.1/node_modules/@assistant-ui/core",
});
writePackage(root, {
name: "@assistant-ui/core",
version: "0.2.2",
installPath:
"node_modules/.pnpm/@assistant-ui+core@0.2.2_react@19.0.0/node_modules/@assistant-ui/core",
});
// Unscoped tracked package living in the store.
writePackage(root, {
name: "assistant-stream",
version: "0.3.14",
installPath:
"node_modules/.pnpm/assistant-stream@0.3.14/node_modules/assistant-stream",
});
// Unrelated package in the store must be ignored.
writePackage(root, {
name: "lodash",
version: "4.17.21",
installPath: "node_modules/.pnpm/lodash@4.17.21/node_modules/lodash",
});
});
afterAll(() => {
fs.rmSync(root, { recursive: true, force: true });
});
it("collects assistant-ui copies from the .pnpm virtual store", () => {
const found = discoverInstalledPackages(root);
const summary = found
.map((p) => `${p.name}@${p.version}`)
.sort()
.join(",");
expect(summary).toContain("@assistant-ui/core@0.2.2");
expect(summary).toContain("@assistant-ui/core@0.2.5");
expect(summary).toContain("@assistant-ui/react@0.14.5");
expect(summary).toContain("assistant-stream@0.3.14");
expect(summary).not.toContain("lodash");
});
it("flags the peer-split @assistant-ui/core copies as duplicated", () => {
const dups = findDuplicates(discoverInstalledPackages(root));
expect(dups).toHaveLength(1);
expect(dups[0]!.name).toBe("@assistant-ui/core");
const versions = dups[0]!.installations.map((i) => i.version).sort();
expect(versions).toEqual(["0.2.2", "0.2.5"]);
});
});
describe("doctor — no pnpm store", () => {
it("returns nothing extra and does not throw when .pnpm is absent", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "aui-doctor-npm-"));
try {
fs.writeFileSync(
path.join(root, "package.json"),
JSON.stringify({ name: "fixture", version: "1.0.0" }),
);
writePackage(root, {
name: "@assistant-ui/react",
version: "0.14.5",
installPath: "node_modules/@assistant-ui/react",
});
const found = discoverInstalledPackages(root);
expect(found.map((p) => `${p.name}@${p.version}`)).toEqual([
"@assistant-ui/react@0.14.5",
]);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
});
describe("findOutdated", () => {
it("flags packages whose installed version is older than the latest", () => {
const installed: DiscoveredPackage[] = [
{ name: "@assistant-ui/react", version: "0.14.5", installPath: "" },
{ name: "@assistant-ui/core", version: "0.2.5", installPath: "" },
{ name: "assistant-stream", version: "0.3.14", installPath: "" },
];
const latest = new Map<string, string | null>([
["@assistant-ui/react", "0.15.0"],
["@assistant-ui/core", "0.2.5"],
["assistant-stream", "0.3.16"],
]);
const outdated = findOutdated(installed, latest);
const summary = outdated
.map((o) => `${o.name}:${o.current}->${o.latest}`)
.join(",");
expect(summary).toContain("@assistant-ui/react:0.14.5->0.15.0");
expect(summary).toContain("assistant-stream:0.3.14->0.3.16");
expect(summary).not.toContain("@assistant-ui/core");
});
it("uses the newest installed version when multiple are found", () => {
const installed: DiscoveredPackage[] = [
{ name: "@assistant-ui/core", version: "0.2.2", installPath: "a" },
{ name: "@assistant-ui/core", version: "0.2.5", installPath: "b" },
];
const latest = new Map<string, string | null>([
["@assistant-ui/core", "0.2.5"],
]);
expect(findOutdated(installed, latest)).toEqual([]);
});
it("skips packages with no latest version (e.g. network failed)", () => {
const installed: DiscoveredPackage[] = [
{ name: "@assistant-ui/react", version: "0.14.5", installPath: "" },
];
const latest = new Map<string, string | null>([
["@assistant-ui/react", null],
]);
expect(findOutdated(installed, latest)).toEqual([]);
});
});
describe("uniquePackageNames", () => {
it("returns sorted unique names", () => {
const installed: DiscoveredPackage[] = [
{ name: "@assistant-ui/react", version: "0.14.5", installPath: "" },
{ name: "@assistant-ui/core", version: "0.2.2", installPath: "" },
{ name: "@assistant-ui/core", version: "0.2.5", installPath: "" },
];
expect(uniquePackageNames(installed)).toEqual([
"@assistant-ui/core",
"@assistant-ui/react",
]);
});
});