Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions tests/helpers/load-plugin-modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ let textToolbarControllerModulePromise;
let insertControllerModulePromise;
let arrangeControllerModulePromise;
let slideExtensionPreserveModulePromise;
let renderedPdfExportModulePromise;

globalThis.DOMParser ??= DOMParser;
globalThis.XMLSerializer ??= XMLSerializer;
Expand Down Expand Up @@ -379,6 +380,16 @@ export function loadLoggerModule() {
return loggerModulePromise;
}

export function loadRenderedPdfExportModule() {
renderedPdfExportModulePromise ??= bundleSource(
"src/renderedPdfExport.ts",
"rendered-pdf-export.cjs",
["html2canvas"],
[stubObsidianPlugin],
).then((outfile) => require(outfile));
return renderedPdfExportModulePromise;
}

export function loadNativePowerPointViewModule() {
viewModulePromise ??= bundleSource(
"src/NativePowerPointView.ts",
Expand Down
37 changes: 37 additions & 0 deletions tests/rendered-pdf-export.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { readFile } from 'node:fs/promises';
import path from 'node:path';
import test from 'node:test';
import { fileURLToPath } from 'node:url';
import { loadRenderedPdfExportModule } from './helpers/load-plugin-modules.mjs';

const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');

Expand All @@ -21,3 +22,39 @@ test('rendered PDF export uses detached canvases and prefers the SVG renderer',
'SVG rendering should be attempted before html2canvas',
);
});

test('dataUrlToBytes decodes standard data URLs, raw base64, empty payloads, and binary byte ranges', async () => {
const { dataUrlToBytes } = await loadRenderedPdfExportModule();

// Standard data URL with image/jpeg header
const helloWorldBase64 = Buffer.from('Hello World').toString('base64');
const jpegDataUrl = `data:image/jpeg;base64,${helloWorldBase64}`;
const bytes1 = dataUrlToBytes(jpegDataUrl);
assert.deepEqual(bytes1, new Uint8Array(Buffer.from('Hello World')));

// Data URL with custom MIME type and parameters
const textDataUrl = `data:text/plain;charset=utf-8;base64,${helloWorldBase64}`;
const bytes2 = dataUrlToBytes(textDataUrl);
assert.deepEqual(bytes2, new Uint8Array(Buffer.from('Hello World')));

// Raw base64 string without comma prefix
const bytes3 = dataUrlToBytes(helloWorldBase64);
assert.deepEqual(bytes3, new Uint8Array(Buffer.from('Hello World')));

// Empty payloads
const emptyStringBytes = dataUrlToBytes('');
assert.deepEqual(emptyStringBytes, new Uint8Array(0));

const emptyHeaderBytes = dataUrlToBytes('data:image/png;base64,');
assert.deepEqual(emptyHeaderBytes, new Uint8Array(0));

// Full 8-bit byte range round-trip (0x00 .. 0xFF)
const allBytes = new Uint8Array(256);
for (let i = 0; i < 256; i++) {
allBytes[i] = i;
}
const binaryBase64 = Buffer.from(allBytes).toString('base64');
const binaryDataUrl = `data:application/octet-stream;base64,${binaryBase64}`;
const bytes4 = dataUrlToBytes(binaryDataUrl);
assert.deepEqual(bytes4, allBytes);
});