mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
refactor: update unit tests to use secureFs for file existence checks
This commit modifies the unit tests in dev-server-service.test.ts to replace the usage of the native fs.existsSync method with secureFs.access for improved security and consistency in file handling. Key changes include: - Updated all instances of existsSync to utilize secureFs.access, ensuring that file existence checks are performed using the secure file system operations. - Adjusted mock implementations to reflect the new secureFs methods, enhancing the reliability of the tests. These changes aim to align the testing strategy with the recent refactor for enhanced security in file operations.
This commit is contained in:
@@ -1,37 +1,33 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { EventEmitter } from "events";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import fs from "fs/promises";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { EventEmitter } from 'events';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
// Mock child_process
|
||||
vi.mock("child_process", () => ({
|
||||
vi.mock('child_process', () => ({
|
||||
spawn: vi.fn(),
|
||||
execSync: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock fs existsSync
|
||||
vi.mock("fs", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("fs")>();
|
||||
return {
|
||||
...actual,
|
||||
existsSync: vi.fn(),
|
||||
};
|
||||
});
|
||||
// Mock secure-fs
|
||||
vi.mock('@/lib/secure-fs.js', () => ({
|
||||
access: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock net
|
||||
vi.mock("net", () => ({
|
||||
vi.mock('net', () => ({
|
||||
default: {
|
||||
createServer: vi.fn(),
|
||||
},
|
||||
createServer: vi.fn(),
|
||||
}));
|
||||
|
||||
import { spawn, execSync } from "child_process";
|
||||
import { existsSync } from "fs";
|
||||
import net from "net";
|
||||
import { spawn, execSync } from 'child_process';
|
||||
import * as secureFs from '@/lib/secure-fs.js';
|
||||
import net from 'net';
|
||||
|
||||
describe("dev-server-service.ts", () => {
|
||||
describe('dev-server-service.ts', () => {
|
||||
let testDir: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -41,20 +37,20 @@ describe("dev-server-service.ts", () => {
|
||||
testDir = path.join(os.tmpdir(), `dev-server-test-${Date.now()}`);
|
||||
await fs.mkdir(testDir, { recursive: true });
|
||||
|
||||
// Default mock for existsSync - return true
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
// Default mock for secureFs.access - return resolved (file exists)
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
// Default mock for net.createServer - port available
|
||||
const mockServer = new EventEmitter() as any;
|
||||
mockServer.listen = vi.fn().mockImplementation((port: number, host: string) => {
|
||||
process.nextTick(() => mockServer.emit("listening"));
|
||||
process.nextTick(() => mockServer.emit('listening'));
|
||||
});
|
||||
mockServer.close = vi.fn();
|
||||
vi.mocked(net.createServer).mockReturnValue(mockServer);
|
||||
|
||||
// Default mock for execSync - no process on port
|
||||
vi.mocked(execSync).mockImplementation(() => {
|
||||
throw new Error("No process found");
|
||||
throw new Error('No process found');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,11 +62,9 @@ describe("dev-server-service.ts", () => {
|
||||
}
|
||||
});
|
||||
|
||||
describe("getDevServerService", () => {
|
||||
it("should return a singleton instance", async () => {
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
describe('getDevServerService', () => {
|
||||
it('should return a singleton instance', async () => {
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
|
||||
const instance1 = getDevServerService();
|
||||
const instance2 = getDevServerService();
|
||||
@@ -79,148 +73,125 @@ describe("dev-server-service.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("startDevServer", () => {
|
||||
it("should return error if worktree path does not exist", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(false);
|
||||
describe('startDevServer', () => {
|
||||
it('should return error if worktree path does not exist', async () => {
|
||||
vi.mocked(secureFs.access).mockRejectedValueOnce(new Error('File not found'));
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
const result = await service.startDevServer(
|
||||
"/project",
|
||||
"/nonexistent/worktree"
|
||||
);
|
||||
const result = await service.startDevServer('/project', '/nonexistent/worktree');
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("does not exist");
|
||||
expect(result.error).toContain('does not exist');
|
||||
});
|
||||
|
||||
it("should return error if no package.json found", async () => {
|
||||
vi.mocked(existsSync).mockImplementation((p: any) => {
|
||||
if (p.includes("package.json")) return false;
|
||||
return true;
|
||||
it('should return error if no package.json found', async () => {
|
||||
vi.mocked(secureFs.access).mockImplementation(async (p: any) => {
|
||||
if (typeof p === 'string' && p.includes('package.json')) {
|
||||
throw new Error('File not found');
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
const result = await service.startDevServer(testDir, testDir);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("No package.json found");
|
||||
expect(result.error).toContain('No package.json found');
|
||||
});
|
||||
|
||||
it("should detect npm as package manager with package-lock.json", async () => {
|
||||
vi.mocked(existsSync).mockImplementation((p: any) => {
|
||||
if (p.includes("bun.lockb")) return false;
|
||||
if (p.includes("pnpm-lock.yaml")) return false;
|
||||
if (p.includes("yarn.lock")) return false;
|
||||
if (p.includes("package-lock.json")) return true;
|
||||
if (p.includes("package.json")) return true;
|
||||
return true;
|
||||
it('should detect npm as package manager with package-lock.json', async () => {
|
||||
vi.mocked(secureFs.access).mockImplementation(async (p: any) => {
|
||||
const pathStr = typeof p === 'string' ? p : '';
|
||||
if (pathStr.includes('bun.lockb')) throw new Error('Not found');
|
||||
if (pathStr.includes('pnpm-lock.yaml')) throw new Error('Not found');
|
||||
if (pathStr.includes('yarn.lock')) throw new Error('Not found');
|
||||
if (pathStr.includes('package-lock.json')) return undefined;
|
||||
if (pathStr.includes('package.json')) return undefined;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"npm",
|
||||
["run", "dev"],
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(spawn).toHaveBeenCalledWith('npm', ['run', 'dev'], expect.any(Object));
|
||||
});
|
||||
|
||||
it("should detect yarn as package manager with yarn.lock", async () => {
|
||||
vi.mocked(existsSync).mockImplementation((p: any) => {
|
||||
if (p.includes("bun.lockb")) return false;
|
||||
if (p.includes("pnpm-lock.yaml")) return false;
|
||||
if (p.includes("yarn.lock")) return true;
|
||||
if (p.includes("package.json")) return true;
|
||||
return true;
|
||||
it('should detect yarn as package manager with yarn.lock', async () => {
|
||||
vi.mocked(secureFs.access).mockImplementation(async (p: any) => {
|
||||
const pathStr = typeof p === 'string' ? p : '';
|
||||
if (pathStr.includes('bun.lockb')) throw new Error('Not found');
|
||||
if (pathStr.includes('pnpm-lock.yaml')) throw new Error('Not found');
|
||||
if (pathStr.includes('yarn.lock')) return undefined;
|
||||
if (pathStr.includes('package.json')) return undefined;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
|
||||
expect(spawn).toHaveBeenCalledWith("yarn", ["dev"], expect.any(Object));
|
||||
expect(spawn).toHaveBeenCalledWith('yarn', ['dev'], expect.any(Object));
|
||||
});
|
||||
|
||||
it("should detect pnpm as package manager with pnpm-lock.yaml", async () => {
|
||||
vi.mocked(existsSync).mockImplementation((p: any) => {
|
||||
if (p.includes("bun.lockb")) return false;
|
||||
if (p.includes("pnpm-lock.yaml")) return true;
|
||||
if (p.includes("package.json")) return true;
|
||||
return true;
|
||||
it('should detect pnpm as package manager with pnpm-lock.yaml', async () => {
|
||||
vi.mocked(secureFs.access).mockImplementation(async (p: any) => {
|
||||
const pathStr = typeof p === 'string' ? p : '';
|
||||
if (pathStr.includes('bun.lockb')) throw new Error('Not found');
|
||||
if (pathStr.includes('pnpm-lock.yaml')) return undefined;
|
||||
if (pathStr.includes('package.json')) return undefined;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"pnpm",
|
||||
["run", "dev"],
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(spawn).toHaveBeenCalledWith('pnpm', ['run', 'dev'], expect.any(Object));
|
||||
});
|
||||
|
||||
it("should detect bun as package manager with bun.lockb", async () => {
|
||||
vi.mocked(existsSync).mockImplementation((p: any) => {
|
||||
if (p.includes("bun.lockb")) return true;
|
||||
if (p.includes("package.json")) return true;
|
||||
return true;
|
||||
it('should detect bun as package manager with bun.lockb', async () => {
|
||||
vi.mocked(secureFs.access).mockImplementation(async (p: any) => {
|
||||
const pathStr = typeof p === 'string' ? p : '';
|
||||
if (pathStr.includes('bun.lockb')) return undefined;
|
||||
if (pathStr.includes('package.json')) return undefined;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"bun",
|
||||
["run", "dev"],
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(spawn).toHaveBeenCalledWith('bun', ['run', 'dev'], expect.any(Object));
|
||||
});
|
||||
|
||||
it("should return existing server info if already running", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should return existing server info if already running', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
// Start first server
|
||||
@@ -230,18 +201,16 @@ describe("dev-server-service.ts", () => {
|
||||
// Try to start again - should return existing
|
||||
const result2 = await service.startDevServer(testDir, testDir);
|
||||
expect(result2.success).toBe(true);
|
||||
expect(result2.result?.message).toContain("already running");
|
||||
expect(result2.result?.message).toContain('already running');
|
||||
});
|
||||
|
||||
it("should start dev server successfully", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should start dev server successfully', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
const result = await service.startDevServer(testDir, testDir);
|
||||
@@ -249,32 +218,28 @@ describe("dev-server-service.ts", () => {
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.result).toBeDefined();
|
||||
expect(result.result?.port).toBeGreaterThanOrEqual(3001);
|
||||
expect(result.result?.url).toContain("http://localhost:");
|
||||
expect(result.result?.url).toContain('http://localhost:');
|
||||
});
|
||||
});
|
||||
|
||||
describe("stopDevServer", () => {
|
||||
it("should return success if server not found", async () => {
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
describe('stopDevServer', () => {
|
||||
it('should return success if server not found', async () => {
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
const result = await service.stopDevServer("/nonexistent/path");
|
||||
const result = await service.stopDevServer('/nonexistent/path');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.result?.message).toContain("already stopped");
|
||||
expect(result.result?.message).toContain('already stopped');
|
||||
});
|
||||
|
||||
it("should stop a running server", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should stop a running server', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
// Start server
|
||||
@@ -284,15 +249,13 @@ describe("dev-server-service.ts", () => {
|
||||
const result = await service.stopDevServer(testDir);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(mockProcess.kill).toHaveBeenCalledWith("SIGTERM");
|
||||
expect(mockProcess.kill).toHaveBeenCalledWith('SIGTERM');
|
||||
});
|
||||
});
|
||||
|
||||
describe("listDevServers", () => {
|
||||
it("should return empty list when no servers running", async () => {
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
describe('listDevServers', () => {
|
||||
it('should return empty list when no servers running', async () => {
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
const result = service.listDevServers();
|
||||
@@ -301,15 +264,13 @@ describe("dev-server-service.ts", () => {
|
||||
expect(result.result.servers).toEqual([]);
|
||||
});
|
||||
|
||||
it("should list running servers", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should list running servers', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
@@ -322,25 +283,21 @@ describe("dev-server-service.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("isRunning", () => {
|
||||
it("should return false for non-running server", async () => {
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
describe('isRunning', () => {
|
||||
it('should return false for non-running server', async () => {
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
expect(service.isRunning("/some/path")).toBe(false);
|
||||
expect(service.isRunning('/some/path')).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true for running server", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should return true for running server', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
@@ -349,25 +306,21 @@ describe("dev-server-service.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getServerInfo", () => {
|
||||
it("should return undefined for non-running server", async () => {
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
describe('getServerInfo', () => {
|
||||
it('should return undefined for non-running server', async () => {
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
expect(service.getServerInfo("/some/path")).toBeUndefined();
|
||||
expect(service.getServerInfo('/some/path')).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return info for running server", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
it('should return info for running server', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
@@ -379,16 +332,14 @@ describe("dev-server-service.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAllocatedPorts", () => {
|
||||
it("should return allocated ports", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
describe('getAllocatedPorts', () => {
|
||||
it('should return allocated ports', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
@@ -399,16 +350,14 @@ describe("dev-server-service.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("stopAll", () => {
|
||||
it("should stop all running servers", async () => {
|
||||
vi.mocked(existsSync).mockReturnValue(true);
|
||||
describe('stopAll', () => {
|
||||
it('should stop all running servers', async () => {
|
||||
vi.mocked(secureFs.access).mockResolvedValue(undefined);
|
||||
|
||||
const mockProcess = createMockProcess();
|
||||
vi.mocked(spawn).mockReturnValue(mockProcess as any);
|
||||
|
||||
const { getDevServerService } = await import(
|
||||
"@/services/dev-server-service.js"
|
||||
);
|
||||
const { getDevServerService } = await import('@/services/dev-server-service.js');
|
||||
const service = getDevServerService();
|
||||
|
||||
await service.startDevServer(testDir, testDir);
|
||||
|
||||
Reference in New Issue
Block a user