feat: open multi-part packages in browser
This commit is contained in:
@@ -52,10 +52,14 @@ class SuccessfulParserWorker implements WorkerPort {
|
||||
onmessage: ((event: MessageEvent<WorkerResponse>) => void) | null = null;
|
||||
onerror: ((event: ErrorEvent) => void) | null = null;
|
||||
terminated = false;
|
||||
lastMessage: WorkerRequest | undefined;
|
||||
lastTransfer: Transferable[] = [];
|
||||
|
||||
constructor(private readonly packageResult?: OneNotePackageDto) {}
|
||||
|
||||
postMessage(message: WorkerRequest): void {
|
||||
postMessage(message: WorkerRequest, transfer: Transferable[] = []): void {
|
||||
this.lastMessage = message;
|
||||
this.lastTransfer = transfer;
|
||||
queueMicrotask(() => {
|
||||
if (message.type === 'parse-one') {
|
||||
this.respond({
|
||||
@@ -158,7 +162,7 @@ describe('OneNoteApplication', () => {
|
||||
);
|
||||
|
||||
await user.upload(
|
||||
screen.getByLabelText('Choose a OneNote file'),
|
||||
screen.getByLabelText('Choose OneNote files'),
|
||||
new File([new Uint8Array([1, 2, 3])], 'Section.one')
|
||||
);
|
||||
|
||||
@@ -189,23 +193,74 @@ describe('OneNoteApplication', () => {
|
||||
tree: { interpreted: false, nodes: [] },
|
||||
diagnostics: [],
|
||||
};
|
||||
const worker = new SuccessfulParserWorker(notebook);
|
||||
render(
|
||||
<OneNoteApplication
|
||||
createWorkerClient={() =>
|
||||
new OneNoteWorkerClient(() => new SuccessfulParserWorker(notebook))
|
||||
}
|
||||
createWorkerClient={() => new OneNoteWorkerClient(() => worker)}
|
||||
/>
|
||||
);
|
||||
|
||||
const part3 = new File([new Uint8Array([3])], 'Notebook-3.cab');
|
||||
const primary = new File([new Uint8Array([1])], 'Notebook.onepkg');
|
||||
const part2 = new File([new Uint8Array([2])], 'Notebook-2.cab');
|
||||
fireEvent.drop(screen.getByTestId('file-drop-zone'), {
|
||||
dataTransfer: {
|
||||
files: [new File([new Uint8Array([1])], 'Notebook.onepkg')],
|
||||
files: [part3, primary, part2],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'Package summary' })
|
||||
).toBeInTheDocument();
|
||||
expect(worker.lastMessage).toEqual(
|
||||
expect.objectContaining({
|
||||
type: 'parse-onepkg',
|
||||
fileName: 'Notebook.onepkg',
|
||||
cabinetParts: [
|
||||
expect.objectContaining({ fileName: 'Notebook-3.cab' }),
|
||||
expect.objectContaining({ fileName: 'Notebook-2.cab' }),
|
||||
],
|
||||
})
|
||||
);
|
||||
expect(worker.lastTransfer).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('hands a multi-file picker selection to the package worker', async () => {
|
||||
const notebook: OneNotePackageDto = {
|
||||
format: 'onepkg',
|
||||
sourceName: 'Notebook.onepkg',
|
||||
sourceSize: 2,
|
||||
entries: [],
|
||||
sections: [],
|
||||
tree: { interpreted: false, nodes: [] },
|
||||
diagnostics: [],
|
||||
};
|
||||
const worker = new SuccessfulParserWorker(notebook);
|
||||
const user = userEvent.setup();
|
||||
render(
|
||||
<OneNoteApplication
|
||||
createWorkerClient={() => new OneNoteWorkerClient(() => worker)}
|
||||
/>
|
||||
);
|
||||
|
||||
const input = screen.getByLabelText('Choose OneNote files');
|
||||
expect(input).toHaveAttribute('multiple');
|
||||
expect(input).toHaveAttribute('accept', '.one,.onepkg,.cab');
|
||||
await user.upload(input, [
|
||||
new File([new Uint8Array([2])], 'Notebook-2.cab'),
|
||||
new File([new Uint8Array([1])], 'Notebook.onepkg'),
|
||||
]);
|
||||
|
||||
expect(
|
||||
await screen.findByRole('heading', { name: 'Package summary' })
|
||||
).toBeInTheDocument();
|
||||
expect(worker.lastMessage).toEqual(
|
||||
expect.objectContaining({
|
||||
type: 'parse-onepkg',
|
||||
fileName: 'Notebook.onepkg',
|
||||
cabinetParts: [expect.objectContaining({ fileName: 'Notebook-2.cab' })],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps a failed packaged section visible beside a readable one', async () => {
|
||||
@@ -299,7 +354,7 @@ describe('OneNoteApplication', () => {
|
||||
);
|
||||
|
||||
await user.upload(
|
||||
screen.getByLabelText('Choose a OneNote file'),
|
||||
screen.getByLabelText('Choose OneNote files'),
|
||||
new File([new Uint8Array([1])], 'Notebook.onepkg')
|
||||
);
|
||||
|
||||
@@ -336,7 +391,7 @@ describe('OneNoteApplication', () => {
|
||||
);
|
||||
|
||||
await user.upload(
|
||||
screen.getByLabelText('Choose a OneNote file'),
|
||||
screen.getByLabelText('Choose OneNote files'),
|
||||
new File(['not OneNote'], 'Broken.one')
|
||||
);
|
||||
|
||||
@@ -353,12 +408,12 @@ describe('OneNoteApplication', () => {
|
||||
render(<OneNoteApplication />);
|
||||
|
||||
await user.upload(
|
||||
screen.getByLabelText('Choose a OneNote file'),
|
||||
screen.getByLabelText('Choose OneNote files'),
|
||||
new File(['not a notebook'], 'notes.zip')
|
||||
);
|
||||
|
||||
expect(await screen.findByRole('alert')).toHaveTextContent(
|
||||
'Choose a file whose name ends in .one or .onepkg.'
|
||||
'Choose one .one file, or one .onepkg file together with its .cab parts.'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -371,7 +426,7 @@ describe('OneNoteApplication', () => {
|
||||
value: MAX_SOURCE_FILE_BYTES + 1,
|
||||
});
|
||||
|
||||
await user.upload(screen.getByLabelText('Choose a OneNote file'), file);
|
||||
await user.upload(screen.getByLabelText('Choose OneNote files'), file);
|
||||
|
||||
expect(await screen.findByRole('alert')).toHaveTextContent('512 MiB');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user