Files
minori/test/services/dependencyAnalyzerService.spec.ts
T
naomi 5bc2cfbe43
Node.js CI / CI (push) Failing after 7s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 50s
feat: initial prototype attempt
2026-02-03 17:13:57 -08:00

295 lines
10 KiB
TypeScript

/**
* @copyright NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable vitest/valid-expect -- Test expectations don't need messages */
/* eslint-disable max-lines-per-function -- Test suites require many test cases */
/* eslint-disable @typescript-eslint/naming-convention -- Test data uses npm package names and destructured imports */
/* eslint-disable @typescript-eslint/consistent-type-assertions -- Required for mocking */
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("@nhcarrigan/logger", () => {
return {
Logger: class MockLogger {
public error = vi.fn();
public log = vi.fn();
},
};
});
interface MockNpmService {
getPackageChangelog: ReturnType<typeof vi.fn>;
getPackageInfo: ReturnType<typeof vi.fn>;
}
const createMockNpmService = (): MockNpmService => {
return {
getPackageChangelog: vi.fn(),
getPackageInfo: vi.fn(),
};
};
describe("dependencyAnalyzerService", () => {
beforeEach(() => {
vi.clearAllMocks();
});
afterEach(() => {
vi.resetAllMocks();
});
it("should return empty array when no dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({});
expect(result).toStrictEqual([]);
});
it("should find updates for dependencies", async() => {
expect.assertions(2);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockResolvedValue({
"dist-tags": { latest: "2.0.0" },
"name": "test-package",
"versions": {},
});
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"test-package": "1.0.0",
},
});
expect(result).toHaveLength(1);
expect(result[0]).toStrictEqual({
currentVersion: "1.0.0",
latestVersion: "2.0.0",
packageName: "test-package",
type: "dependencies",
});
});
it("should skip file: protocol dependencies", async() => {
expect.assertions(2);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"local-package": "file:../local-package",
},
});
expect(result).toStrictEqual([]);
expect(mockNpmService.getPackageInfo).not.toHaveBeenCalled();
});
it("should skip git: protocol dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"git-package": "git:github.com/user/repo",
},
});
expect(result).toStrictEqual([]);
});
it("should skip http: protocol dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"http-package": "http://example.com/package.tgz",
},
});
expect(result).toStrictEqual([]);
});
it("should skip https: protocol dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"https-package": "https://example.com/package.tgz",
},
});
expect(result).toStrictEqual([]);
});
it("should skip github: shorthand dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"github-package": "github:user/repo",
},
});
expect(result).toStrictEqual([]);
});
it("should skip * version dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"star-package": "*",
},
});
expect(result).toStrictEqual([]);
});
it("should skip latest version dependencies", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"latest-package": "latest",
},
});
expect(result).toStrictEqual([]);
});
it("should not include packages that are already up-to-date", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockResolvedValue({
"dist-tags": { latest: "1.0.0" },
"name": "test-package",
"versions": {},
});
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"test-package": "1.0.0",
},
});
expect(result).toStrictEqual([]);
});
it("should handle packages not found on npm", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockResolvedValue(null);
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"non-existent": "1.0.0",
},
});
expect(result).toStrictEqual([]);
});
it("should handle version prefixes like ^", async() => {
expect.assertions(2);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockResolvedValue({
"dist-tags": { latest: "2.0.0" },
"name": "test-package",
"versions": {},
});
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"test-package": "^1.0.0",
},
});
expect(result).toHaveLength(1);
expect(result[0]?.currentVersion).toBe("^1.0.0");
});
it("should handle npm errors gracefully", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockRejectedValue(new Error("Network error"));
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"test-package": "1.0.0",
},
});
expect(result).toStrictEqual([]);
});
it("should handle semver comparison errors", async() => {
expect.assertions(1);
const mockNpmService = createMockNpmService();
mockNpmService.getPackageInfo.mockResolvedValue({
"dist-tags": { latest: "invalid-version" },
"name": "test-package",
"versions": {},
});
const { DependencyAnalyzerService }
= await import("../../src/services/dependencyAnalyzerService.js");
const analyzerService = new DependencyAnalyzerService(
mockNpmService as Parameters<typeof DependencyAnalyzerService>[0],
);
const result = await analyzerService.analyzePackageJson({
dependencies: {
"test-package": "also-invalid",
},
});
expect(result).toStrictEqual([]);
});
});