feat: import job runner in-memory

- Añade ImportRunner en memoria con concurrencia configurable
- Tests TDD para enqueue, concurrencia y comportamiento tras stop
- Actualiza /api/import/scan para encolar jobs y registrar errores
- Ajusta tsconfig.json para incluir tests en comprobaciones de tipo
This commit is contained in:
2026-02-08 22:24:56 +01:00
parent 1a42422c7e
commit 4298b003d9
20 changed files with 696 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
import { describe, it, expect } from 'vitest';
import path from 'path';
import { computeHashes } from '../../src/services/checksumService';
const fixturesDir = path.join(__dirname, '..', 'fixtures');
const simpleRom = path.join(fixturesDir, 'simple-rom.bin');
describe('services/checksumService', () => {
it('exporta computeHashes', () => {
expect(typeof computeHashes).toBe('function');
});
it('calcula hashes', async () => {
const meta = await computeHashes(simpleRom);
expect(meta).toBeDefined();
expect(meta.size).toBeGreaterThan(0);
expect(meta.md5).toBeDefined();
expect(meta.sha1).toBeDefined();
expect(meta.crc32).toBeDefined();
});
});

View File

@@ -0,0 +1,35 @@
import { describe, it, expect } from 'vitest';
import path from 'path';
import fs from 'fs';
import { parseDat, verifyRomAgainstDat } from '../../src/services/datVerifier';
const fixturesDir = path.join(__dirname, '..', 'fixtures');
const datPath = path.join(fixturesDir, 'dats', 'sample-no-intro.dat.xml');
const simpleRom = path.join(fixturesDir, 'simple-rom.bin');
const runIntegration = !!process.env.INTEGRATION;
const describeIf = runIntegration ? describe : describe.skip;
describeIf('services/datVerifier', () => {
it('parsea DAT xml', () => {
const xml = fs.readFileSync(datPath, 'utf8');
const parsed = parseDat(xml);
expect(parsed).toBeDefined();
});
it('verifica rom contra DAT', async () => {
const stats = fs.statSync(simpleRom);
const romMeta = {
filename: 'simple-rom.bin',
size: stats.size,
md5: 'placeholder',
sha1: 'placeholder',
crc32: 'placeholder',
} as any;
const xml = fs.readFileSync(datPath, 'utf8');
const parsed = parseDat(xml);
const res = await verifyRomAgainstDat(romMeta, parsed);
expect(res).toBeDefined();
});
});

View File

@@ -0,0 +1,28 @@
import { describe, it, expect } from 'vitest';
import path from 'path';
import { scanDirectory } from '../../src/services/fsScanner';
const fixturesDir = path.join(__dirname, '..', 'fixtures');
const emptyDir = path.join(fixturesDir, 'empty');
describe('services/fsScanner', () => {
it('exporta scanDirectory', () => {
expect(typeof scanDirectory).toBe('function');
});
it('carpeta vacía devuelve array', async () => {
const res = await scanDirectory(emptyDir);
expect(Array.isArray(res)).toBe(true);
expect((res as any[]).length).toBe(0);
});
it('detecta simple-rom.bin', async () => {
const res = await scanDirectory(fixturesDir);
const found = (res as any[]).find(
(r: any) => r.filename === 'simple-rom.bin' || r.name === 'simple-rom.bin'
);
expect(found).toBeTruthy();
expect(found.size).toBeGreaterThan(0);
expect(found.format).toBeDefined();
});
});