104 lines
3.7 KiB
TypeScript
104 lines
3.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
captureGpoFolderFiles,
|
|
captureReadableGpoSelectedFiles,
|
|
collectGpoDirectoryFiles
|
|
} from '../../src/features/project-import/GpoFolderImport';
|
|
|
|
describe('GPO folder browser file capture', () => {
|
|
it('starts every selected file read before the transport requests the first result', async () => {
|
|
const started: string[] = [];
|
|
const selected = ['first', 'second', 'third'].map(name => ({
|
|
webkitRelativePath: `Synthetic/${name}.xml`,
|
|
size: name.length,
|
|
arrayBuffer: async () => {
|
|
started.push(name);
|
|
return new TextEncoder().encode(name).buffer;
|
|
}
|
|
})) as unknown as File[];
|
|
|
|
const sources = captureGpoFolderFiles(selected);
|
|
expect(started).toEqual(['first', 'second', 'third']);
|
|
expect(new TextDecoder().decode(await sources[0].readBytes())).toBe('first');
|
|
});
|
|
|
|
it('turns an inaccessible browser file into the bounded local-read error', async () => {
|
|
const selected = [{
|
|
webkitRelativePath: 'Synthetic/unavailable.xml',
|
|
size: 1,
|
|
arrayBuffer: async () => { throw new DOMException('unavailable', 'NotFoundError'); }
|
|
}] as unknown as File[];
|
|
|
|
const [source] = captureGpoFolderFiles(selected);
|
|
await expect(source.readBytes()).rejects.toThrow('konnte nicht lokal gelesen werden');
|
|
});
|
|
|
|
it('rejects oversized metadata before starting any browser file read', () => {
|
|
let started = 0;
|
|
const selected = [{
|
|
webkitRelativePath: 'Synthetic/oversized.bin',
|
|
size: 513 * 1024 * 1024,
|
|
arrayBuffer: async () => {
|
|
started += 1;
|
|
return new ArrayBuffer(0);
|
|
}
|
|
}] as unknown as File[];
|
|
|
|
expect(() => captureGpoFolderFiles(selected)).toThrow('ungültige oder zu große Dateigröße');
|
|
expect(started).toBe(0);
|
|
});
|
|
|
|
it('collects a directly granted directory recursively with stable relative paths', async () => {
|
|
const file = {
|
|
size: 3,
|
|
arrayBuffer: async () => new TextEncoder().encode('gpo').buffer
|
|
} as unknown as File;
|
|
const nested = {
|
|
kind: 'directory',
|
|
name: 'DomainSysvol',
|
|
async *values() {
|
|
yield { kind: 'file', name: 'gpt.ini', getFile: async () => file };
|
|
}
|
|
};
|
|
const root = {
|
|
kind: 'directory',
|
|
name: 'SyntheticBackup',
|
|
async *values() { yield nested; }
|
|
};
|
|
|
|
const selected = await collectGpoDirectoryFiles(root as never);
|
|
expect(selected.unreadableEntries).toBe(0);
|
|
expect(selected.files.map(entry => entry.relativePath)).toEqual([
|
|
'SyntheticBackup/DomainSysvol/gpt.ini'
|
|
]);
|
|
});
|
|
|
|
it('keeps readable entries and counts inaccessible handles and file bodies', async () => {
|
|
const readable = {
|
|
size: 3,
|
|
arrayBuffer: async () => new TextEncoder().encode('gpo').buffer
|
|
} as File;
|
|
const unreadableBody = {
|
|
size: 1,
|
|
arrayBuffer: async () => { throw new DOMException('unavailable', 'NotFoundError'); }
|
|
} as unknown as File;
|
|
const root = {
|
|
kind: 'directory',
|
|
name: 'SyntheticBackup',
|
|
async *values() {
|
|
yield { kind: 'file', name: 'gpt.ini', getFile: async () => readable };
|
|
yield { kind: 'file', name: 'missing.xml', getFile: async () => { throw new DOMException('missing', 'NotFoundError'); } };
|
|
yield { kind: 'file', name: 'locked.xml', getFile: async () => unreadableBody };
|
|
}
|
|
};
|
|
|
|
const collected = await collectGpoDirectoryFiles(root as never);
|
|
const captured = await captureReadableGpoSelectedFiles(collected.files);
|
|
expect(collected.unreadableEntries).toBe(1);
|
|
expect(captured.unreadableEntries).toBe(1);
|
|
expect(captured.sources.map(source => source.relativePath)).toEqual([
|
|
'SyntheticBackup/gpt.ini'
|
|
]);
|
|
});
|
|
});
|