diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/invoice_check.c | 54 | ||||
| -rw-r--r-- | tests/pdf_check.c | 9 | ||||
| -rw-r--r-- | tests/test_core.c | 108 |
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) |
