Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d00bfdc
test: add unit tests for main and db and improve coverage
Laertes87 Aug 2, 2026
761cc8a
test: fix db test actually exercising db.ts code
Laertes87 Aug 2, 2026
82af881
test: test isolated test db
Laertes87 Aug 2, 2026
8c204a7
test: translate comments to English
Laertes87 Aug 2, 2026
2108975
test: adapt main.test.ts to test against isolated db
Laertes87 Aug 2, 2026
1d72254
test: improve test cleanup in libreoffice.test.ts
Laertes87 Aug 2, 2026
396dd9f
test: correctly use isolated test db instead of production db in tests
Laertes87 Aug 2, 2026
c2bebb1
test: correctly create isolated test db in main.test.ts
Laertes87 Aug 2, 2026
7b80678
test: set DB_PATH in process.env for main.test.ts
Laertes87 Aug 2, 2026
7d7415b
test: make sure data directory exists when executing main.test.ts
Laertes87 Aug 2, 2026
7d411b1
test: restore parent-directory creation for db
Laertes87 Aug 2, 2026
b32c28d
test: fall back to isolated test db instead of production db
Laertes87 Aug 2, 2026
210fa5b
test: remove duplicate initializeDatabase call
Laertes87 Aug 2, 2026
1d328f4
test: create isolated test db in temp directory and clean up afterward
Laertes87 Aug 2, 2026
a2f0005
test: remove dead fallback logic
Laertes87 Aug 2, 2026
dd85304
test: fix copy and paste comment
Laertes87 Aug 2, 2026
ab92a06
test: rename commonTests.ts to not be included in coverage report
Laertes87 Aug 2, 2026
165c487
test: revert renaming of commonTests.ts and add bunfig.toml to ignore…
Laertes87 Aug 2, 2026
b316452
test: add unit test for printVersions
Laertes87 Aug 3, 2026
87924f3
test: ensure that test does not touch production database
Laertes87 Aug 3, 2026
aa81ed1
test: ensure that test database connection is properly closed
Laertes87 Aug 3, 2026
823c83e
test: ensure that migrateDb database always gets cleaned up
Laertes87 Aug 3, 2026
81334c7
test: do not silently swallow every unexpected error
Laertes87 Aug 3, 2026
6fac7cb
test: fix test name and comment
Laertes87 Aug 3, 2026
152be90
test: test the actual default export
Laertes87 Aug 3, 2026
ecfa591
test: test that handleConvert does not throw
Laertes87 Aug 4, 2026
2fa4dcf
test: remove dead mock code line
Laertes87 Aug 4, 2026
310a065
test: consolidate db test
Laertes87 Aug 4, 2026
46705b6
test: ensure that module is loaded after environment variable is set
Laertes87 Aug 4, 2026
86cf842
test: wait for resolves to finish before assertion
Laertes87 Aug 4, 2026
bbe5748
test: fix test name and comment language
Laertes87 Aug 4, 2026
0e91478
test: make sure to only update database version if needed
Laertes87 Aug 4, 2026
ce540ca
test: improve readability of sql in db test
Laertes87 Aug 4, 2026
ee8137b
test: make check for status column case-insensitive
Laertes87 Aug 4, 2026
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
5 changes: 5 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[test]
coverage = true
coveragePathIgnorePatterns = [
"tests/converters/helpers/commonTests.ts"
]
6 changes: 6 additions & 0 deletions src/converters/libreoffice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,9 @@ export function convert(
});
});
}

/**
* @internal For testing only. Do not use in production.
* Tests need direct access to cover all filters.
*/
export { filters, getFilters };
6 changes: 6 additions & 0 deletions src/converters/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,9 @@ for (const converterName in properties) {
export const getAllInputs = (converter: string) => {
return allInputs[converter] || [];
};

/**
* @internal For testing only. Do not use in production.
* Tests need direct access to cover all branches of converter discovery and chunking logic.
*/
export { chunks, mainConverter };
85 changes: 50 additions & 35 deletions src/db/db.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,58 @@
import { mkdirSync } from "node:fs";
import { Database } from "bun:sqlite";
import { mkdirSync } from "node:fs";
import { dirname } from "node:path";

mkdirSync("./data", { recursive: true });
const db = new Database("./data/mydb.sqlite", { create: true });
export function initializeDatabase(db: Database): void {
const dbVersion = db.query("PRAGMA user_version").get() as { user_version?: number };
const hasTables = db.query("SELECT * FROM sqlite_master WHERE type='table'").get();

if (!db.query("SELECT * FROM sqlite_master WHERE type='table'").get()) {
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS file_names (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
file_name TEXT NOT NULL,
output_file_name TEXT NOT NULL,
status TEXT DEFAULT 'not started',
FOREIGN KEY (job_id) REFERENCES jobs(id)
);
CREATE TABLE IF NOT EXISTS jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
date_created TEXT NOT NULL,
status TEXT DEFAULT 'not started',
num_files INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users(id)
);
PRAGMA user_version = 1;`);
}
if (!hasTables) {
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS file_names (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
file_name TEXT NOT NULL,
output_file_name TEXT NOT NULL,
status TEXT DEFAULT 'not started',
FOREIGN KEY (job_id) REFERENCES jobs(id)
);
CREATE TABLE IF NOT EXISTS jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
date_created TEXT NOT NULL,
status TEXT DEFAULT 'not started',
num_files INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users(id)
);
`);
db.exec("PRAGMA user_version = 1;");
} else if ((dbVersion?.user_version ?? 0) < 1) {
// Don't trust user_version alone — verify the column is actually
// missing before altering. This makes the migration safe to re-run
// even against a file left in an inconsistent state.
const columns = db.query("PRAGMA table_info(file_names)").all() as { name: string }[];
const hasStatusColumn = columns.some((c) => c.name.toLowerCase() === "status");

if (!hasStatusColumn) {
db.exec("ALTER TABLE file_names ADD COLUMN status TEXT DEFAULT 'not started';");
}

db.exec("PRAGMA user_version = 1;");
console.log("Updated database to version 1.");
}

const dbVersion = (db.query("PRAGMA user_version").get() as { user_version?: number }).user_version;
if (dbVersion === 0) {
db.exec("ALTER TABLE file_names ADD COLUMN status TEXT DEFAULT 'not started';");
db.exec("PRAGMA user_version = 1;");
console.log("Updated database to version 1.");
// enable WAL mode
db.exec("PRAGMA journal_mode = WAL;");
}

// enable WAL mode
db.exec("PRAGMA journal_mode = WAL;");
const dbPath = process.env.DB_PATH ?? "./data/mydb.sqlite";
mkdirSync(dirname(dbPath), { recursive: true });
const db = new Database(dbPath, { create: true });
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
initializeDatabase(db);

export default db;
21 changes: 18 additions & 3 deletions src/helpers/printVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ if (process.env.NODE_ENV === "production") {
}

if (stdout) {
console.log(`resvg v${stdout.split("\n")[0]}`);
// stdout may contain the command plus version (e.g. "resvg -V v1.0.0").
// Extract the last token and print it as version to avoid duplication.
const firstLine = (stdout || "").split("\n")[0] || "";
const lastToken = (firstLine.split(" ").filter(Boolean).pop() ?? "").toString();
console.log(`resvg ${lastToken}`);
}
});

Expand All @@ -121,7 +125,13 @@ if (process.env.NODE_ENV === "production") {
}

if (stdout) {
console.log(`assimp ${stdout.split("\n")[5]}`);
// assimp prints its version on a specific line in real output; if the
// expected line isn't present (e.g. in tests/mocks), fall back to the
// first non-empty line. Then extract the last token as version.
const lines = (stdout || "").split("\n").filter(Boolean);
const candidate = (lines[5] ?? lines[0] ?? "").toString();
const lastToken = (candidate.split(" ").filter(Boolean).pop() ?? "").toString();
console.log(`assimp ${lastToken}`);
}
});

Expand Down Expand Up @@ -181,7 +191,12 @@ if (process.env.NODE_ENV === "production") {
}

if (stdout) {
console.log(`Bun v${stdout.split("\n")[0]}`);
// stdout may include the command itself (e.g. "bun -v v1.0.0"). Extract
// the last token which should contain the version (possibly prefixed
// with 'v').
const firstLine = (stdout || "").split("\n")[0] || "";
const lastToken = (firstLine.split(" ").filter(Boolean).pop() ?? "").toString();
console.log(`Bun ${lastToken}`);
}
});
}
17 changes: 17 additions & 0 deletions tests/converters/libreoffice.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { afterEach, beforeEach, expect, test } from "bun:test";
import { convert } from "../../src/converters/libreoffice";
import type { ExecFileFn } from "../../src/converters/types";
import { filters, getFilters } from "../../src/converters/libreoffice";

function requireDefined<T>(value: T, msg: string): NonNullable<T> {
if (value === undefined || value === null) throw new Error(msg);
Expand Down Expand Up @@ -209,3 +210,19 @@ test("logs stderr on exec error as well", async () => {
// The callback still provided stderr; your implementation logs it before settling
expect(errors).toContain("stderr: EPIPE");
});

// --- calc filter branch (test-only exports) ---------------------------------
test("getFilters returns calc mapping when present", () => {
// temporarily add entries to calc mapping
filters.calc["testfoo"] = "TestFooFilter";
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
filters.calc["testbar"] = "TestBarFilter";

try {
const res = getFilters("testfoo", "testbar");
expect(res).toEqual(["TestFooFilter", "TestBarFilter"]);
} finally {
// cleanup
delete filters.calc["testfoo"];
delete filters.calc["testbar"];
}
});
Loading
Loading