Files
quasar/backend/tests/services/fsScanner.archiveEntries.spec.ts
Benito Rodríguez 2667e11284
Some checks failed
CI / lint (push) Failing after 10s
CI / test-backend (push) Has been skipped
CI / test-frontend (push) Has been skipped
CI / test-e2e (push) Has been skipped
Refactor code structure for improved readability and maintainability
2026-03-22 11:34:38 +01:00

87 lines
3.0 KiB
TypeScript

import path from 'path';
import os from 'os';
import { promises as fs } from 'fs';
import { afterEach, it, expect, vi } from 'vitest';
import type { Mock } from 'vitest';
vi.mock('../../src/services/archiveReader', () => ({ listArchiveEntries: vi.fn() }));
import scanDirectory from '../../src/services/fsScanner';
import { listArchiveEntries } from '../../src/services/archiveReader';
afterEach(() => {
vi.restoreAllMocks();
});
it('expone entradas internas de archivos como items virtuales', async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'fsScanner-test-'));
const collectionFile = path.join(tmpDir, 'collection.zip');
await fs.writeFile(collectionFile, '');
(listArchiveEntries as unknown as Mock).mockResolvedValue([
{ name: 'inner/rom1.bin', size: 1234 },
]);
const results = await scanDirectory(tmpDir);
const expectedPath = `${collectionFile}::inner/rom1.bin`;
const found = results.find((r: any) => r.path === expectedPath);
expect(found).toBeDefined();
if (found) {
expect(found.isArchiveEntry).toBe(true);
expect(found.containerPath).toBe(collectionFile);
expect(found.entryPath).toBe('inner/rom1.bin');
expect(found.filename).toBe('rom1.bin');
expect(found.format).toBe('bin');
}
await fs.rm(tmpDir, { recursive: true, force: true });
});
it('ignora entradas con traversal o paths absolutos', async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'fsScanner-test-'));
const collectionFile = path.join(tmpDir, 'collection.zip');
await fs.writeFile(collectionFile, '');
(listArchiveEntries as unknown as Mock).mockResolvedValue([
{ name: '../evil.rom', size: 10 },
{ name: '/abs/evil.rom', size: 20 },
{ name: 'good/rom.bin', size: 30 },
]);
const results = await scanDirectory(tmpDir);
const safePath = `${collectionFile}::good/rom.bin`;
expect(results.find((r: any) => r.path === safePath)).toBeDefined();
expect(results.find((r: any) => r.path === `${collectionFile}::../evil.rom`)).toBeUndefined();
expect(results.find((r: any) => r.path === `${collectionFile}::/abs/evil.rom`)).toBeUndefined();
await fs.rm(tmpDir, { recursive: true, force: true });
});
it('respeta ARCHIVE_MAX_ENTRIES', async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'fsScanner-test-'));
const collectionFile = path.join(tmpDir, 'collection.zip');
await fs.writeFile(collectionFile, '');
// Set env var temporarily
const prev = process.env.ARCHIVE_MAX_ENTRIES;
process.env.ARCHIVE_MAX_ENTRIES = '1';
(listArchiveEntries as unknown as Mock).mockResolvedValue([
{ name: 'one.bin', size: 1 },
{ name: 'two.bin', size: 2 },
{ name: 'three.bin', size: 3 },
]);
const results = await scanDirectory(tmpDir);
const matches = results.filter((r: any) => String(r.path).startsWith(collectionFile + '::'));
expect(matches.length).toBe(1);
// restore
if (prev === undefined) delete process.env.ARCHIVE_MAX_ENTRIES;
else process.env.ARCHIVE_MAX_ENTRIES = prev;
await fs.rm(tmpDir, { recursive: true, force: true });
});