aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/invoice_check.c54
-rw-r--r--tests/pdf_check.c9
-rw-r--r--tests/test_core.c108
3 files changed, 171 insertions, 0 deletions
diff --git a/tests/invoice_check.c b/tests/invoice_check.c
index 01b5ca3..e61a41d 100644
--- a/tests/invoice_check.c
+++ b/tests/invoice_check.c
@@ -129,6 +129,19 @@ static int contains(const unsigned char *data, size_t len, const char *needle)
return 0;
}
+static int count_of(const unsigned char *data, size_t len, const char *needle)
+{
+ size_t n = strlen(needle);
+ int count = 0;
+
+ if (!n)
+ return 0;
+ for (size_t i = 0; i + n <= len; i++)
+ if (memcmp(data + i, needle, n) == 0)
+ count++;
+ return count;
+}
+
static void test_render(const char *path)
{
struct invoice_doc d;
@@ -147,6 +160,8 @@ static void test_render(const char *path)
if (data) {
check(memcmp(data, "%PDF-1.4", 8) == 0, "render header");
check(contains(data, len, "Testleverant"), "render seller text");
+ check(count_of(data, len, "Testleverant") == 2,
+ "render seller name in header and footer");
check(contains(data, len, "Testkund AB"), "render customer text");
check(contains(data, len, "Summa att betala SEK"), "render summary");
check(contains(data, len, "Test Person"), "render our ref");
@@ -166,6 +181,45 @@ static void test_render(const char *path)
free(data);
{
+ unsigned char *colored = NULL;
+ size_t colored_len = 0;
+
+ d.header_color = "#ff0000";
+ check(invoice_render_pdf(&d, &colored, &colored_len) == 0,
+ "render custom colour returns 0");
+ if (colored)
+ check(contains(colored, colored_len, "1 0 0 rg"),
+ "render custom header colour");
+ free(colored);
+
+ colored = NULL;
+ d.header_color = "not-a-colour";
+ check(invoice_render_pdf(&d, &colored, &colored_len) == 0,
+ "render invalid colour returns 0");
+ if (colored)
+ check(!contains(colored, colored_len, "1 0 0 rg"),
+ "render invalid colour falls back");
+ free(colored);
+ d.header_color = NULL;
+ }
+ {
+ static char long_name[240];
+ unsigned char *long_pdf = NULL;
+ size_t long_len = 0;
+
+ memset(long_name, 'A', sizeof long_name - 1);
+ long_name[sizeof long_name - 1] = '\0';
+ d.seller.name = long_name;
+ check(invoice_render_pdf(&d, &long_pdf, &long_len) == 0,
+ "render long name returns 0");
+ if (long_pdf)
+ check(contains(long_pdf, long_len, "..."),
+ "render long name is truncated");
+ free(long_pdf);
+ d.seller.name = "Testleverantör AB";
+ }
+
+ {
unsigned char *bad = NULL;
size_t n = 0;
diff --git a/tests/pdf_check.c b/tests/pdf_check.c
index 4d56cab..4eaf24d 100644
--- a/tests/pdf_check.c
+++ b/tests/pdf_check.c
@@ -82,6 +82,12 @@ int main(int argc, char **argv)
pdf_line(p, 0, 80, 595, 80, 0.5, "#314c59");
pdf_line(p, 20, 100, 575, 100, 0.25, "#314c59");
+ pdf_text_fit(p, 20, 220, "HB", 16, 8, 200, "#314c59", "Fitted");
+ pdf_text_fit(p, 20, 240, "H", 10, 8, 40, "#314c59",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+ pdf_text_fit(p, 20, 260, "H", 10, 8, 40, "#314c59", NULL);
+ pdf_text_fit(p, 20, 260, "H", 10, 8, 40, "#314c59", "");
+
put_text(p, "MAKANDRA", 20, 70, "HB", 16, "#ffffff");
put_text(p, "FAKTURA", 575 - pdf_text_width("H", 16, "FAKTURA"), 70,
"H", 16, "#ffffff");
@@ -123,6 +129,9 @@ int main(int argc, char **argv)
check(contains(data, len, "1 0 obj"), "object 1");
check(contains(data, len, "6 0 obj"), "object 6");
check(!contains(data, len, "\r"), "no CR");
+ check(contains(data, len, "Fitted"), "text_fit keeps short text");
+ check(contains(data, len, "(AAAAAA...)"),
+ "text_fit truncates long text");
if (argc > 1) {
FILE *f = fopen(argv[1], "wb");
diff --git a/tests/test_core.c b/tests/test_core.c
index e56c5d3..a000ffe 100644
--- a/tests/test_core.c
+++ b/tests/test_core.c
@@ -40,6 +40,18 @@ static void mark_failed(void)
g_failed[g_failed_n++] = g_test;
}
+static int count_of(const char *text, const char *needle)
+{
+ size_t n = strlen(needle);
+ int count = 0;
+
+ if (!n)
+ return 0;
+ for (const char *p = text; (p = strstr(p, needle)) != NULL; p++)
+ count++;
+ return count;
+}
+
struct tctx {
char tmpdir[512];
char backupdir[512];
@@ -2336,6 +2348,50 @@ static void test_settings(struct tctx *t)
CHECK_OK(d);
CHECK_STR(d, "result.value", "anders@example.com");
yyjson_doc_free(d);
+
+ /* the invoice header colour must be #rrggbb */
+ d = call(reqf("{\"v\":1,\"id\":\"hdr0\",\"cmd\":\"settings.get\","
+ "\"session\":\"%s\",\"org\":%d}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ CHECK_STR(d, "result.document_header_color", "#314c59");
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"hdr1\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#1a2b3c\"}}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ CHECK_STR(d, "result.value", "#1a2b3c");
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"hdr2\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"1a2b3c\"}}",
+ g_session, (int)t->org_id));
+ CHECK_STR(d, "error.code", "INVALID_ARGS");
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"hdr3\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#12345\"}}",
+ g_session, (int)t->org_id));
+ CHECK_STR(d, "error.code", "INVALID_ARGS");
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"hdr4\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#1234567\"}}",
+ g_session, (int)t->org_id));
+ CHECK_STR(d, "error.code", "INVALID_ARGS");
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"hdr5\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#GGGGGG\"}}",
+ g_session, (int)t->org_id));
+ CHECK_STR(d, "error.code", "INVALID_ARGS");
+ yyjson_doc_free(d);
}
static void test_series(struct tctx *t)
@@ -3316,6 +3372,41 @@ static void test_invoices(struct tctx *t)
CHECK(stored && preview_b64 && strcmp(stored, preview_b64) == 0);
yyjson_doc_free(d);
+ /* the invoice header colour setting reaches the rendered document */
+ d = call(reqf("{\"v\":1,\"id\":\"354a\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#ff0000\"}}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"354b\",\"cmd\":\"invoice.preview\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":%s}",
+ g_session, (int)t->org_id, draft_args));
+ CHECK_OK(d);
+ const char *red_b64 = jstr(d, "result.content_base64");
+ unsigned char *red_pdf = NULL;
+ size_t red_len = 0;
+ CHECK(red_b64 &&
+ util_b64_decode(red_b64, strlen(red_b64), &red_pdf, &red_len) == 0);
+ if (red_pdf) {
+ char *red_text = xmalloc(red_len + 1);
+
+ memcpy(red_text, red_pdf, red_len);
+ red_text[red_len] = '\0';
+ CHECK(strstr(red_text, "1 0 0 rg") != NULL);
+ free(red_text);
+ }
+ free(red_pdf);
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"354c\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#314c59\"}}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+
d = call(reqf("{\"v\":1,\"id\":\"355\",\"cmd\":\"invoice.issue\","
"\"session\":\"%s\",\"org\":%d,\"args\":{\"customer_id\":"
"%lld,\"invoice_date\":\"2026-09-21\",\"due_date\":"
@@ -5085,6 +5176,14 @@ static void test_payslip(struct tctx *t)
CHECK_STR(d, "error.code", "NOT_FOUND");
yyjson_doc_free(d);
+ /* the shared document header colour reaches the payslip too */
+ d = call(reqf("{\"v\":1,\"id\":\"ps5b\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#ff0000\"}}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+
char req[512];
snprintf(req, sizeof req,
"{\"v\":1,\"id\":\"ps6\",\"cmd\":\"payroll.payslip\","
@@ -5116,12 +5215,21 @@ static void test_payslip(struct tctx *t)
CHECK(strstr(text, "-4 208,00") != NULL);
CHECK(strstr(text, "Arbetsgivaravgifter 31,42 % betalas av"
" arbetsgivaren.") != NULL);
+ CHECK(strstr(text, "1 0 0 rg") != NULL);
+ CHECK(count_of(text, "AB Ett") == 2);
free(text);
}
free(pdf);
}
yyjson_doc_free(rd);
free(raw);
+
+ d = call(reqf("{\"v\":1,\"id\":\"ps7\",\"cmd\":\"settings.set\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"key\":"
+ "\"document_header_color\",\"value\":\"#314c59\"}}",
+ g_session, (int)t->org_id));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
}
static void test_payslip_mail(struct tctx *t)