feat: Add built dist files with EU compliance routes
Some checks failed
Deploy to Production / Deploy to Server (push) Failing after 20s
Some checks failed
Deploy to Production / Deploy to Server (push) Failing after 20s
- Include compiled TypeScript with new /impressum, /privacy, /terms routes - Temporary commit of dist files for Docker deployment
This commit is contained in:
parent
5ef8f34133
commit
1ef8f5743c
21 changed files with 2179 additions and 0 deletions
122
dist/__tests__/api.test.js
vendored
Normal file
122
dist/__tests__/api.test.js
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
||||
import { app } from "../index.js";
|
||||
// Note: These tests require Puppeteer/Chrome to be available
|
||||
// For CI, use the Dockerfile which includes Chrome
|
||||
const BASE = "http://localhost:3199";
|
||||
let server;
|
||||
beforeAll(async () => {
|
||||
process.env.API_KEYS = "test-key";
|
||||
process.env.PORT = "3199";
|
||||
// Import fresh to pick up env
|
||||
server = app.listen(3199);
|
||||
// Wait for browser init
|
||||
await new Promise((r) => setTimeout(r, 2000));
|
||||
});
|
||||
afterAll(async () => {
|
||||
server?.close();
|
||||
});
|
||||
describe("Auth", () => {
|
||||
it("rejects requests without API key", async () => {
|
||||
const res = await fetch(`${BASE}/v1/convert/html`, { method: "POST" });
|
||||
expect(res.status).toBe(401);
|
||||
});
|
||||
it("rejects invalid API key", async () => {
|
||||
const res = await fetch(`${BASE}/v1/convert/html`, {
|
||||
method: "POST",
|
||||
headers: { Authorization: "Bearer wrong-key" },
|
||||
});
|
||||
expect(res.status).toBe(403);
|
||||
});
|
||||
});
|
||||
describe("Health", () => {
|
||||
it("returns ok", async () => {
|
||||
const res = await fetch(`${BASE}/health`);
|
||||
expect(res.status).toBe(200);
|
||||
const data = await res.json();
|
||||
expect(data.status).toBe("ok");
|
||||
});
|
||||
});
|
||||
describe("HTML to PDF", () => {
|
||||
it("converts simple HTML", async () => {
|
||||
const res = await fetch(`${BASE}/v1/convert/html`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer test-key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ html: "<h1>Test</h1>" }),
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("content-type")).toBe("application/pdf");
|
||||
const buf = await res.arrayBuffer();
|
||||
expect(buf.byteLength).toBeGreaterThan(100);
|
||||
// PDF magic bytes
|
||||
const header = new Uint8Array(buf.slice(0, 5));
|
||||
expect(String.fromCharCode(...header)).toBe("%PDF-");
|
||||
});
|
||||
it("rejects missing html field", async () => {
|
||||
const res = await fetch(`${BASE}/v1/convert/html`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer test-key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
});
|
||||
describe("Markdown to PDF", () => {
|
||||
it("converts markdown", async () => {
|
||||
const res = await fetch(`${BASE}/v1/convert/markdown`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer test-key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ markdown: "# Hello\n\nWorld" }),
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("content-type")).toBe("application/pdf");
|
||||
});
|
||||
});
|
||||
describe("Templates", () => {
|
||||
it("lists templates", async () => {
|
||||
const res = await fetch(`${BASE}/v1/templates`, {
|
||||
headers: { Authorization: "Bearer test-key" },
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
const data = await res.json();
|
||||
expect(data.templates).toBeInstanceOf(Array);
|
||||
expect(data.templates.length).toBeGreaterThan(0);
|
||||
});
|
||||
it("renders invoice template", async () => {
|
||||
const res = await fetch(`${BASE}/v1/templates/invoice/render`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer test-key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
invoiceNumber: "TEST-001",
|
||||
date: "2026-02-14",
|
||||
from: { name: "Seller", email: "s@test.com" },
|
||||
to: { name: "Buyer", email: "b@test.com" },
|
||||
items: [{ description: "Widget", quantity: 2, unitPrice: 50, taxRate: 20 }],
|
||||
}),
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers.get("content-type")).toBe("application/pdf");
|
||||
});
|
||||
it("returns 404 for unknown template", async () => {
|
||||
const res = await fetch(`${BASE}/v1/templates/nonexistent/render`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer test-key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue