59 lines
2.6 KiB
TypeScript
59 lines
2.6 KiB
TypeScript
import { mkdtemp, rm } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
import { FileSystemBackendArtifactStore } from '../../server/artifacts/backend-artifact-store';
|
|
import { GpoBackupJobProcessor } from '../../server/gpo/gpo-backup-job-processor';
|
|
import { GpoBackupSubmissionService } from '../../server/gpo/gpo-backup-submission-service';
|
|
import { listProjectGpoBackupStatus } from '../../server/gpo/gpo-backup-status-service';
|
|
import { directGpoBackupWorkerExecutor, directGpoInventoryExecutor } from '../../server/gpo/gpo-inventory-executor';
|
|
import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository';
|
|
import { syntheticGpoBackupZip } from './gpo-synthetic-fixture';
|
|
|
|
const submittedAt = '2026-07-21T10:00:00.000Z';
|
|
const project = { id: 'gpo-status-project', name: 'Synthetic status', createdAt: submittedAt, updatedAt: submittedAt, attributes: {} };
|
|
|
|
describe('persistent project GPO status', () => {
|
|
let directory: string;
|
|
let repository: LocalAssessorRepository;
|
|
let store: FileSystemBackendArtifactStore;
|
|
|
|
beforeEach(async () => {
|
|
directory = await mkdtemp(join(tmpdir(), 'assessor-gpo-status-'));
|
|
repository = new LocalAssessorRepository();
|
|
store = new FileSystemBackendArtifactStore(directory);
|
|
await repository.saveProject(project);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(directory, { recursive: true, force: true });
|
|
});
|
|
|
|
it('derives queued and completed-partial display states from persistent repository data', async () => {
|
|
await new GpoBackupSubmissionService(repository, store, directGpoInventoryExecutor, 1024 * 1024).submit({
|
|
projectId: project.id,
|
|
fileName: 'status.zip',
|
|
bytes: syntheticGpoBackupZip(),
|
|
receivedAt: submittedAt
|
|
});
|
|
|
|
await expect(listProjectGpoBackupStatus(repository, project.id, submittedAt)).resolves.toMatchObject({
|
|
projectId: project.id,
|
|
records: [{ fileName: 'status.zip', state: 'queued', attempts: 0, gpoCount: 0, backupInstanceCount: 0 }]
|
|
});
|
|
|
|
await new GpoBackupJobProcessor(repository, store, directGpoBackupWorkerExecutor, {
|
|
maximumArtifactBytes: 1024 * 1024,
|
|
leaseDurationMs: 60_000,
|
|
retryDelayMs: 1_000,
|
|
now: () => new Date(submittedAt)
|
|
}).processNext('status-worker');
|
|
|
|
await expect(listProjectGpoBackupStatus(repository, project.id, '2026-07-21T10:01:00.000Z')).resolves.toMatchObject({
|
|
records: [{
|
|
fileName: 'status.zip', state: 'partial', attempts: 1, processingStatus: 'partial', gpoCount: 1, backupInstanceCount: 1
|
|
}]
|
|
});
|
|
});
|
|
});
|