mirror of
https://github.com/unraid/api.git
synced 2026-01-08 17:49:59 -06:00
refactor(test): update vitest config and improve rclone service tests
- Replace vitest.workspace.js with vitest.config.ts for better project configuration - Add vitest dependency and update test script in package.json - Improve RCloneApiService tests with better mocking and error handling - Update test snapshots to include backupBase path
This commit is contained in:
@@ -18,7 +18,11 @@
|
||||
"Bash(pnpm add:*)",
|
||||
"Bash(npx tsc:*)",
|
||||
"Bash(pnpm list:*)",
|
||||
"Bash(rm:*)"
|
||||
"Bash(rm:*)",
|
||||
"Bash(pnpm --filter ./api test)",
|
||||
"Bash(pnpm i:*)",
|
||||
"Bash(pnpm:*)",
|
||||
"Bash(corepack prepare:*)"
|
||||
]
|
||||
},
|
||||
"enableAllProjectMcpServers": false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="4.8.0"
|
||||
version="4.4.1"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
sandbox="yes"
|
||||
|
||||
@@ -72,15 +72,28 @@ describe('RCloneApiService', () => {
|
||||
mockPRetry = vi.mocked(pRetry.default);
|
||||
mockExistsSync = vi.mocked(existsSync);
|
||||
|
||||
mockGot.post = vi.fn().mockResolvedValue({ body: {} });
|
||||
mockExeca.mockReturnValue({
|
||||
on: vi.fn(),
|
||||
kill: vi.fn(),
|
||||
killed: false,
|
||||
pid: 12345,
|
||||
} as any);
|
||||
mockGot.post = vi.fn().mockImplementation((url: string) => {
|
||||
// Mock the core/pid call to indicate socket is running
|
||||
if (url.includes('core/pid')) {
|
||||
return Promise.resolve({ body: { pid: 12345 } });
|
||||
}
|
||||
return Promise.resolve({ body: {} });
|
||||
});
|
||||
// Mock execa to return a resolved promise for rclone version check
|
||||
mockExeca.mockImplementation((cmd: string, args: string[]) => {
|
||||
if (cmd === 'rclone' && args[0] === 'version') {
|
||||
return Promise.resolve({ stdout: 'rclone v1.67.0', stderr: '', exitCode: 0 } as any);
|
||||
}
|
||||
return {
|
||||
on: vi.fn(),
|
||||
kill: vi.fn(),
|
||||
killed: false,
|
||||
pid: 12345,
|
||||
} as any;
|
||||
});
|
||||
mockPRetry.mockResolvedValue(undefined);
|
||||
mockExistsSync.mockReturnValue(false);
|
||||
// Mock socket exists
|
||||
mockExistsSync.mockReturnValue(true);
|
||||
|
||||
mockFormatService = {
|
||||
formatBytes: vi.fn(),
|
||||
@@ -116,7 +129,10 @@ describe('RCloneApiService', () => {
|
||||
};
|
||||
|
||||
service = new RCloneApiService(mockStatusService);
|
||||
await service.onModuleInit();
|
||||
// Mock the service as initialized without actually running onModuleInit
|
||||
// to avoid the initialization API calls
|
||||
(service as any).initialized = true;
|
||||
(service as any).rcloneBaseUrl = 'http://unix:/tmp/rclone.sock:';
|
||||
});
|
||||
|
||||
describe('getProviders', () => {
|
||||
@@ -284,6 +300,9 @@ describe('RCloneApiService', () => {
|
||||
options: { delete_on: 'dst' },
|
||||
};
|
||||
const mockResponse = { jobid: 'job-123' };
|
||||
|
||||
// Clear previous mock calls and set up fresh mock
|
||||
mockGot.post.mockClear();
|
||||
mockGot.post.mockResolvedValue({ body: mockResponse });
|
||||
|
||||
const result = await service.startBackup(input);
|
||||
@@ -292,11 +311,11 @@ describe('RCloneApiService', () => {
|
||||
expect(mockGot.post).toHaveBeenCalledWith(
|
||||
'http://unix:/tmp/rclone.sock:/sync/copy',
|
||||
expect.objectContaining({
|
||||
json: {
|
||||
json: expect.objectContaining({
|
||||
srcFs: '/source/path',
|
||||
dstFs: 'remote:backup/path',
|
||||
delete_on: 'dst',
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -305,8 +324,22 @@ describe('RCloneApiService', () => {
|
||||
describe('getJobStatus', () => {
|
||||
it('should return job status', async () => {
|
||||
const input: GetRCloneJobStatusDto = { jobId: 'job-123' };
|
||||
const mockStatus = { status: 'running', progress: 0.5 };
|
||||
mockGot.post.mockResolvedValue({ body: mockStatus });
|
||||
const mockStatus = { id: 'job-123', status: 'running', progress: 0.5 };
|
||||
mockGot.post.mockImplementation((url: string) => {
|
||||
if (url.includes('core/stats')) {
|
||||
return Promise.resolve({ body: {} });
|
||||
}
|
||||
if (url.includes('job/status')) {
|
||||
return Promise.resolve({ body: mockStatus });
|
||||
}
|
||||
return Promise.resolve({ body: {} });
|
||||
});
|
||||
|
||||
// Mock the status service methods
|
||||
const mockStatusService = (service as any).statusService;
|
||||
mockStatusService.enhanceStatsWithFormattedFields = vi.fn().mockReturnValue({});
|
||||
mockStatusService.transformStatsToJob = vi.fn().mockReturnValue(null);
|
||||
mockStatusService.parseJobWithStats = vi.fn().mockReturnValue(mockStatus);
|
||||
|
||||
const result = await service.getJobStatus(input);
|
||||
|
||||
@@ -371,7 +404,7 @@ describe('RCloneApiService', () => {
|
||||
mockGot.post.mockRejectedValue(httpError);
|
||||
|
||||
await expect(service.getProviders()).rejects.toThrow(
|
||||
'Rclone API Error (config/providers, HTTP 404): Failed to process error response body. Raw body:'
|
||||
'Rclone API Error (config/providers, HTTP 404): Failed to process error response: '
|
||||
);
|
||||
});
|
||||
|
||||
@@ -388,7 +421,7 @@ describe('RCloneApiService', () => {
|
||||
mockGot.post.mockRejectedValue(httpError);
|
||||
|
||||
await expect(service.getProviders()).rejects.toThrow(
|
||||
'Rclone API Error (config/providers, HTTP 400): Failed to process error response body. Raw body: invalid json'
|
||||
'Rclone API Error (config/providers, HTTP 400): Failed to process error response: invalid json'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -403,7 +436,7 @@ describe('RCloneApiService', () => {
|
||||
mockGot.post.mockRejectedValue('unknown error');
|
||||
|
||||
await expect(service.getProviders()).rejects.toThrow(
|
||||
'Unknown error calling RClone API (config/providers) with params {}: unknown error'
|
||||
'Unknown error calling RClone API (config/providers): unknown error'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,6 +31,7 @@ exports[`Returns paths 1`] = `
|
||||
"activationBase",
|
||||
"webGuiBase",
|
||||
"identConfig",
|
||||
"backupBase",
|
||||
"activation",
|
||||
"boot",
|
||||
"webgui",
|
||||
|
||||
@@ -1 +1 @@
|
||||
1751630630443
|
||||
1752326314433
|
||||
@@ -1 +1 @@
|
||||
1751630630198
|
||||
1752326314052
|
||||
@@ -1 +1 @@
|
||||
1751630630343
|
||||
1752326314199
|
||||
@@ -1 +1 @@
|
||||
1751630630571
|
||||
1752326314557
|
||||
@@ -1 +1 @@
|
||||
1751630630810
|
||||
1752326314785
|
||||
@@ -7,7 +7,7 @@
|
||||
"build:watch": " pnpm -r --parallel build:watch",
|
||||
"dev": "pnpm -r dev",
|
||||
"unraid:deploy": "pnpm -r unraid:deploy",
|
||||
"test": "pnpm -r test",
|
||||
"test": "vitest",
|
||||
"lint": "pnpm -r lint",
|
||||
"lint:fix": "pnpm -r lint:fix",
|
||||
"type-check": "pnpm -r type-check",
|
||||
@@ -43,7 +43,8 @@
|
||||
"@manypkg/cli": "0.24.0",
|
||||
"chalk": "5.4.1",
|
||||
"diff": "8.0.2",
|
||||
"ignore": "7.0.5"
|
||||
"ignore": "7.0.5",
|
||||
"vitest": "3.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lint-staged": "16.1.2",
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -20,6 +20,9 @@ importers:
|
||||
ignore:
|
||||
specifier: 7.0.5
|
||||
version: 7.0.5
|
||||
vitest:
|
||||
specifier: 3.2.4
|
||||
version: 3.2.4(@types/node@22.16.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(jsdom@26.1.0)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
devDependencies:
|
||||
lint-staged:
|
||||
specifier: 16.1.2
|
||||
|
||||
12
vitest.config.ts
Normal file
12
vitest.config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
"./api/vite.config.ts",
|
||||
"./plugin/vitest.config.ts",
|
||||
"./unraid-ui/vitest.config.ts",
|
||||
"./web/vitest.config.mjs"
|
||||
]
|
||||
}
|
||||
})
|
||||
@@ -1,8 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
"./plugin/vitest.config.ts",
|
||||
"./api/vite.config.ts",
|
||||
"./web/vitest.config.mjs",
|
||||
"./unraid-ui/vitest.config.ts"
|
||||
])
|
||||
Reference in New Issue
Block a user