chore: initial commit
This commit is contained in:
commit
c2c8aaa953
20 files changed
+4688
No files matched your search
@@ -0,0 +1,157 @@
|
||||
import { mkdir, readFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { convertPngsToPdf, convertPngsToPdfs } from "../src/lib/convert.js";
|
||||
import {
|
||||
createTempDirectory,
|
||||
removeTempDirectory,
|
||||
writeTinyPng,
|
||||
} from "./helpers.js";
|
||||
|
||||
const tempDirectories: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
tempDirectories
|
||||
.splice(0)
|
||||
.map((directory) => removeTempDirectory(directory)),
|
||||
);
|
||||
});
|
||||
|
||||
async function makeTempDirectory(): Promise<string> {
|
||||
const directory = await createTempDirectory();
|
||||
tempDirectories.push(directory);
|
||||
return directory;
|
||||
}
|
||||
|
||||
describe("convertPngsToPdfs", () => {
|
||||
it("converts each PNG to its own PDF beside the source", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const first = path.join(directory, "first.png");
|
||||
const second = path.join(directory, "second.PNG");
|
||||
await writeTinyPng(first);
|
||||
await writeTinyPng(second);
|
||||
|
||||
const result = await convertPngsToPdfs([first, second]);
|
||||
|
||||
expect(result.failed).toEqual([]);
|
||||
expect(result.converted).toHaveLength(2);
|
||||
|
||||
for (const conversion of result.converted) {
|
||||
expect(conversion.outputPath).toBe(
|
||||
path.join(
|
||||
directory,
|
||||
`${path.basename(conversion.inputPath, path.extname(conversion.inputPath))}.pdf`,
|
||||
),
|
||||
);
|
||||
|
||||
const pdf = await PDFDocument.load(await readFile(conversion.outputPath));
|
||||
expect(pdf.getPageCount()).toBe(1);
|
||||
expect(pdf.getPage(0).getWidth()).toBeCloseTo(0.75);
|
||||
expect(pdf.getPage(0).getHeight()).toBeCloseTo(0.75);
|
||||
}
|
||||
});
|
||||
|
||||
it("writes batch output to the selected directory", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const inputDirectory = path.join(directory, "input");
|
||||
const outputDirectory = path.join(directory, "output");
|
||||
await mkdir(inputDirectory);
|
||||
const input = path.join(inputDirectory, "image.png");
|
||||
await writeTinyPng(input);
|
||||
|
||||
const result = await convertPngsToPdfs([input], {
|
||||
outDir: outputDirectory,
|
||||
});
|
||||
|
||||
expect(result.converted[0]?.outputPath).toBe(
|
||||
path.join(outputDirectory, "image.pdf"),
|
||||
);
|
||||
expect(
|
||||
(await readFile(path.join(outputDirectory, "image.pdf"))).length,
|
||||
).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("refuses existing outputs unless force is enabled", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const input = path.join(directory, "image.png");
|
||||
await writeTinyPng(input);
|
||||
|
||||
const initial = await convertPngsToPdfs([input]);
|
||||
expect(initial.failed).toEqual([]);
|
||||
|
||||
const refused = await convertPngsToPdfs([input]);
|
||||
expect(refused.converted).toEqual([]);
|
||||
expect(refused.failed).toHaveLength(1);
|
||||
expect(refused.failed[0]?.error.message).toMatch(/already exists/i);
|
||||
|
||||
const forced = await convertPngsToPdfs([input], { force: true });
|
||||
expect(forced.failed).toEqual([]);
|
||||
expect(forced.converted).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("detects output basename collisions before writing", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const firstDirectory = path.join(directory, "one");
|
||||
const secondDirectory = path.join(directory, "two");
|
||||
const outputDirectory = path.join(directory, "output");
|
||||
await mkdir(firstDirectory);
|
||||
await mkdir(secondDirectory);
|
||||
const first = path.join(firstDirectory, "image.png");
|
||||
const second = path.join(secondDirectory, "image.png");
|
||||
await writeTinyPng(first);
|
||||
await writeTinyPng(second);
|
||||
|
||||
await expect(
|
||||
convertPngsToPdfs([first, second], { outDir: outputDirectory }),
|
||||
).rejects.toThrow(/Output collision/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertPngsToPdf", () => {
|
||||
it("merges multiple PNGs into one multi-page PDF", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const first = path.join(directory, "first.png");
|
||||
const second = path.join(directory, "second.png");
|
||||
await writeTinyPng(first);
|
||||
await writeTinyPng(second);
|
||||
const output = path.join(directory, "album.pdf");
|
||||
|
||||
const actualOutput = await convertPngsToPdf([first, second], output);
|
||||
|
||||
expect(actualOutput).toBe(output);
|
||||
const pdf = await PDFDocument.load(await readFile(output));
|
||||
expect(pdf.getPageCount()).toBe(2);
|
||||
});
|
||||
|
||||
it("appends a PDF extension when merged output has none", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const input = path.join(directory, "image.png");
|
||||
await writeTinyPng(input);
|
||||
|
||||
const output = await convertPngsToPdf(
|
||||
[input],
|
||||
path.join(directory, "album"),
|
||||
);
|
||||
|
||||
expect(output).toBe(path.join(directory, "album.pdf"));
|
||||
expect((await readFile(output)).length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("refuses to overwrite merged outputs without force", async () => {
|
||||
const directory = await makeTempDirectory();
|
||||
const input = path.join(directory, "image.png");
|
||||
const output = path.join(directory, "album.pdf");
|
||||
await writeTinyPng(input);
|
||||
await convertPngsToPdf([input], output);
|
||||
|
||||
await expect(convertPngsToPdf([input], output)).rejects.toThrow(
|
||||
/already exists/i,
|
||||
);
|
||||
|
||||
await expect(
|
||||
convertPngsToPdf([input], output, { force: true }),
|
||||
).resolves.toBe(output);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user