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

120 lines
4.4 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { installPackageIfNeeded } from "../../src/lib/utils/package-installer";
import * as packageManager from "../../src/lib/utils/package-manager";
import * as fileScanner from "../../src/lib/utils/file-scanner";
vi.mock("../../src/lib/utils/package-manager");
vi.mock("../../src/lib/utils/file-scanner");
describe("package-installer utilities", () => {
let testDir: string;
let consoleLogSpy: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
testDir = fs.mkdtempSync(path.join(os.tmpdir(), "cli-test-"));
consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => {});
});
afterEach(() => {
if (fs.existsSync(testDir)) {
fs.rmSync(testDir, { recursive: true, force: true });
}
consoleLogSpy.mockRestore();
vi.clearAllMocks();
});
describe("installPackageIfNeeded", () => {
it("should skip installation when import patterns not found", async () => {
vi.mocked(fileScanner.scanForImport).mockReturnValue(false);
await installPackageIfNeeded({
packageName: "@assistant-ui/react",
importPatterns: ["@assistant-ui/react"],
promptMessage: "Install?",
skipMessage: "Already installed",
notFoundMessage: "Not found",
});
expect(consoleLogSpy).toHaveBeenCalledWith("Not found");
expect(packageManager.isPackageInstalled).not.toHaveBeenCalled();
});
it("should skip installation when package already installed", async () => {
vi.mocked(fileScanner.scanForImport).mockReturnValue(true);
vi.mocked(packageManager.isPackageInstalled).mockReturnValue(true);
await installPackageIfNeeded({
packageName: "@assistant-ui/react",
importPatterns: ["@assistant-ui/react"],
promptMessage: "Install?",
skipMessage: "Already installed",
notFoundMessage: "Not found",
});
expect(consoleLogSpy).toHaveBeenCalledWith("Already installed");
expect(packageManager.installPackage).not.toHaveBeenCalled();
});
it("should prompt for installation when package needed but not installed", async () => {
vi.mocked(fileScanner.scanForImport).mockReturnValue(true);
vi.mocked(packageManager.isPackageInstalled).mockReturnValue(false);
vi.mocked(packageManager.askQuestion).mockResolvedValue("y");
vi.mocked(packageManager.installPackage).mockResolvedValue(true);
await installPackageIfNeeded({
packageName: "@assistant-ui/react",
importPatterns: ["@assistant-ui/react"],
promptMessage: "Install @assistant-ui/react? (Y/n) ",
skipMessage: "Already installed",
notFoundMessage: "Not found",
});
expect(packageManager.askQuestion).toHaveBeenCalledWith(
"Install @assistant-ui/react? (Y/n) ",
);
expect(packageManager.installPackage).toHaveBeenCalledWith(
"@assistant-ui/react",
);
});
it("should skip installation when user declines", async () => {
vi.mocked(fileScanner.scanForImport).mockReturnValue(true);
vi.mocked(packageManager.isPackageInstalled).mockReturnValue(false);
vi.mocked(packageManager.askQuestion).mockResolvedValue("n");
await installPackageIfNeeded({
packageName: "@assistant-ui/react",
importPatterns: ["@assistant-ui/react"],
promptMessage: "Install?",
skipMessage: "Already installed",
notFoundMessage: "Not found",
});
expect(packageManager.installPackage).not.toHaveBeenCalled();
expect(consoleLogSpy).toHaveBeenCalledWith("Skipping installation.");
});
it("should install when user provides empty input (default yes)", async () => {
vi.mocked(fileScanner.scanForImport).mockReturnValue(true);
vi.mocked(packageManager.isPackageInstalled).mockReturnValue(false);
vi.mocked(packageManager.askQuestion).mockResolvedValue("");
vi.mocked(packageManager.installPackage).mockResolvedValue(true);
await installPackageIfNeeded({
packageName: "@assistant-ui/react",
importPatterns: ["@assistant-ui/react"],
promptMessage: "Install?",
skipMessage: "Already installed",
notFoundMessage: "Not found",
});
expect(packageManager.installPackage).toHaveBeenCalledWith(
"@assistant-ui/react",
);
});
});
});