From 2af8d29ca99510612fdb005d4ec7d39d83aed6ba Mon Sep 17 00:00:00 2001 From: pajowu Date: Fri, 25 Sep 2026 16:54:58 +0200 Subject: [PATCH] Add pdf render tests (#6566) * Add pdf tests * pdf tests: Save temporary pdfs for failed test debugging * Review comments --- MANIFEST.in | 1 + pyproject.toml | 1 + src/tests/conftest.py | 24 +- .../plugins/badges/assets/bg-cropbox/bg.pdf | 99 ++++++++ .../badges/assets/bg-cropbox/expected.pdf | 213 +++++++++++++++++ .../badges/assets/bg-mediabox-offset/bg.pdf | 98 ++++++++ .../assets/bg-mediabox-offset/expected.pdf | 213 +++++++++++++++++ .../plugins/badges/assets/bg-rotated/bg.pdf | Bin 0 -> 6080 bytes .../badges/assets/bg-rotated/expected.pdf | 216 ++++++++++++++++++ src/tests/plugins/badges/test_pdf.py | 55 +++++ 10 files changed, 919 insertions(+), 1 deletion(-) create mode 100644 src/tests/plugins/badges/assets/bg-cropbox/bg.pdf create mode 100644 src/tests/plugins/badges/assets/bg-cropbox/expected.pdf create mode 100644 src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf create mode 100644 src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf create mode 100644 src/tests/plugins/badges/assets/bg-rotated/bg.pdf create mode 100644 src/tests/plugins/badges/assets/bg-rotated/expected.pdf diff --git a/MANIFEST.in b/MANIFEST.in index 300ad2fa17..7de274470c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -42,6 +42,7 @@ recursive-include src *.py recursive-include src *.svg recursive-include src *.txt recursive-include src Makefile +recursive-include src *.pdf recursive-exclude doc * recursive-exclude deployment * diff --git a/pyproject.toml b/pyproject.toml index f06ee4b532..9f062bd199 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,6 +129,7 @@ dev = [ "pytest==9.1.*", "playwright", "responses", + "pypdfium2" ] [project.entry-points."distutils.commands"] diff --git a/src/tests/conftest.py b/src/tests/conftest.py index da5628856f..2406c23e3f 100644 --- a/src/tests/conftest.py +++ b/src/tests/conftest.py @@ -21,6 +21,8 @@ # import inspect import os +import re +from pathlib import Path import pytest from django.core.cache import cache @@ -28,7 +30,6 @@ from django.test import override_settings from django.utils import translation from django_scopes import scopes_disabled from fakeredis import FakeRedisConnection -from hierarkey.proxy import dirty_cache_keys from xdist.dsession import DSession from pretix.testutils.mock import get_redis_connection @@ -85,6 +86,7 @@ def reset_locale(): @pytest.fixture(autouse=True) def reset_hierarkey_cache_state(): + from hierarkey.proxy import dirty_cache_keys dirty_cache_keys.set(set()) @@ -143,3 +145,23 @@ def set_lock_namespaces(request): @pytest.fixture def class_monkeypatch(request, monkeypatch): request.cls.monkeypatch = monkeypatch + + +def pytest_addoption(parser): + parser.addoption( + '--pdf-dir', action='store', help="output dir for files generated by pdf tests", type=Path + ) + parser.addoption( + '--pdf-tmp-keep', action='store_true', help="keep the temporary directory created for pdf tests" + ) + + +@pytest.fixture +def pdf_dir(request, tmp_path_factory): + dirname = re.sub('[^a-zA-Z0-9]+', '_', request.node.name).strip("_") + if dir := request.config.getoption('--pdf-dir'): + pdf_dir: Path = (dir / dirname).absolute() + pdf_dir.mkdir(exist_ok=True, parents=True) + yield pdf_dir + else: + yield tmp_path_factory.mktemp(dirname) diff --git a/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf b/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf new file mode 100644 index 0000000000..a81d104ae6 --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf @@ -0,0 +1,99 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/PageMode /UseNone +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/Count 1 +/Kids [ 3 0 R ] +/Type /Pages +>> +endobj +3 0 obj +<< +/Contents 4 0 R +/MediaBox [ 0 0 595.2756 841.8898 ] +/Parent 2 0 R +/Resources << +/Font 5 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/CropBox [ 10 10 307.84 220 ] +>> +endobj +4 0 obj +<< +/Length 117 +>> +stream +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q + +endstream +endobj +5 0 obj +<< +/F1 6 0 R +>> +endobj +6 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +7 0 obj +<< +/Author (anonymous) +/CreationDate (D\07220260917173038\05302\04700\047) +/Creator (anonymous) +/Keywords () +/ModDate (D\07220260917173038\05302\04700\047) +/Producer (ReportLab PDF Library \055 \050opensource\051) +/Subject (unspecified) +/Title (untitled) +/Trapped /False +>> +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000083 00000 n +0000000142 00000 n +0000000371 00000 n +0000000539 00000 n +0000000570 00000 n +0000000677 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +/Info 7 0 R +/ID [ ] +>> +startxref +966 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf b/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf new file mode 100644 index 0000000000..e0f7a11e4f --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf @@ -0,0 +1,213 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 6 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +/F1-0 8 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +9 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 13 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +/F1-0 8 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000361 00000 n +0000000393 00000 n +0000000436 00000 n +0000000543 00000 n +0000000650 00000 n +0000000871 00000 n +0000001029 00000 n +0000001224 00000 n +0000001258 00000 n +0000001303 00000 n +0000001411 00000 n +0000001633 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +1791 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf b/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf new file mode 100644 index 0000000000..85ac42c236 --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf @@ -0,0 +1,98 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/PageMode /UseNone +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/Count 1 +/Kids [ 3 0 R ] +/Type /Pages +>> +endobj +3 0 obj +<< +/Contents 4 0 R +/MediaBox [ 10 10 307.84 220 ] +/Parent 2 0 R +/Resources << +/Font 5 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +>> +endobj +4 0 obj +<< +/Length 117 +>> +stream +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q + +endstream +endobj +5 0 obj +<< +/F1 6 0 R +>> +endobj +6 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +7 0 obj +<< +/Author (anonymous) +/CreationDate (D\07220260917173038\05302\04700\047) +/Creator (anonymous) +/Keywords () +/ModDate (D\07220260917173038\05302\04700\047) +/Producer (ReportLab PDF Library \055 \050opensource\051) +/Subject (unspecified) +/Title (untitled) +/Trapped /False +>> +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000083 00000 n +0000000142 00000 n +0000000336 00000 n +0000000504 00000 n +0000000535 00000 n +0000000642 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +/Info 7 0 R +/ID [ ] +>> +startxref +931 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf b/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf new file mode 100644 index 0000000000..e0f7a11e4f --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf @@ -0,0 +1,213 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 6 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +/F1-0 8 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +9 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 13 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +/F1-0 8 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000361 00000 n +0000000393 00000 n +0000000436 00000 n +0000000543 00000 n +0000000650 00000 n +0000000871 00000 n +0000001029 00000 n +0000001224 00000 n +0000001258 00000 n +0000001303 00000 n +0000001411 00000 n +0000001633 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +1791 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-rotated/bg.pdf b/src/tests/plugins/badges/assets/bg-rotated/bg.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6be972deafee975f119532f31cd25aed97955913 GIT binary patch literal 6080 zcmb_gdpuP6`$zYQN-p2DtxiH@XU>`XC8Ny6r7&)}rftj|OvcPKGcpDxC6`KDQb`wL z!&WNPQs_c=S(PQ)YF$eyDakJ7cg9`qes^E5-}lTPbLKgp&vW~{pXYhcF>z+ups^S- z%A}?Fmj@_300CnE^(aeA&;b?&%7XwLB5?(61VTA11#N^}In082Vm=Hy0eCAbluRy# zxgjV;!;$@A?(TK^ale#?DKqXt4-Aya7$~|M1AIH#WnRG4d3V&xH64ZVIV)J&+Uo2d z(xcTgGwe>q`!6!fSvT8mjrnoRt;uzIa2I#zoAk-JHhJ^f zs1()v8$Q1FW8CXA{jM+7)>S61FL*WEw{nvj?ScjnHZVJ_ZIPNWJ1Y2c*Y)tArtpOS zOm_|0xeJfS?g z8u89_yC>-yEzhl@kIzw`8}9tuhi83lTW3#cO8d_V+BwR{V^co$>*q{g8oM;ZCrA5FecBYi=sd=xYI>0F zp_omvPs^t}#N?jEoznWIT=UV4p6y#3iIN3}r#`>($6Kc&jl8Y9ufBderI!{t&2Y=H z@`C9r;-_o5Fg3NOHpTQV(zg5Vnk@;4wWGSm6#{;Cpme5z^@%-UW}1mH$1^ouE|_uL zrzgg)WQMHJ%UtSW>+(9sum)XYwtnh|8ICp<8Cun(Ah3I>d;v|zFB)S@PJdi|pgOF& z`2~5N=JxIPuX=GUv5f~OSJE7?ZE7d9Jksdc)Pe1w zb^sd}^y%AHZ0nWpJ$`hDBkN_Hw1#kikdZoo$Jd{^vl{J2&;D~KW>whnCHE~}(7O$Y zCPWS~!{@Zm<%W`rNy>QTQRT@$7i+~#WiIx}bjbAO*|@EK=!y3%@P1#WzjjB4-kI~9 zlb*p&zP8I8BGNX-^<*U-PCDR}LYzopb$GG*ItgSbb68`@C+vVbAH}^VL5+!Q+nGKd5%ocl+$=?qfl~K@<6syLTl^3 zR$r0Y`CFUibN}Z2r>!LxO)ndLUNm%?HtRQewD&yndqS@&t&h4>F?>K zzpLxwydSVq)A@a&v))@mH31@@CCAUz)vM9%Hhn}bGVZmG7sW$a%iM7UTp?DDsU)5v z2>B^pKYciv7iY0eR=#ZUS?vsME$xDnPdqyP=!ODq?>W>$n?T3fLnnjvYE4hmbxaJd z@1z;*N}9Dpl=%5dH?I~O$Sd*xi5K97ITdy4xzKi_K|~_&rg^JFMZ@*|H=J(NUw@sD zmKYWf?mpIbQDRXH>R9TmpW8O~)7;(07~@!z^QO&vGm|-8d__XZQQee%r}k}e-&zw> zvxksYSSr9riZ?N7`^rp9-B##*a`-SKG}bpZ)1b#-wSgGV#B&1d1H1D7%>Pgj#^gnC#69W%h^j-=u3{zqv?WFRXkmtEdkJZqZ{crS+>0nR z5w7wqlYTzYf9|xQZ`w>_RPU7X$HJd~721Y87j-`4mhlFXII$hqg4w3*R`$X~@9TAC zxKBSdos2zlZdu=|?^exvbFHK4_56m{XZwP3rZ?9^wfnO79F+jZF=+7{qtK79Y6Fjt|;zJ zt+M7qouDpd;f)1Vl>S1i!m^LSH|ln2p|sdq3wOUw+POf>vf*LSua6#O)wn;OPb<~`?ijuZ@W8<2t;`;Zw&$Gb_zj?2c zUT%_X`1Sf@x;p*SffCTKxMR~F{%71ei!C;KI(>h>Sov~(v(L@YyRTkH=|_bu_v){% z71ux8RQ}TDx#O!eze#teRn4Mlt}SX+zIqpO=5bx;sS-S-i<5^@q>2_y-l^l?qo&8(3$jbMVus{6e`#;)aj{UefZ&OBJ)1~hhY;I5UCgMNu9gsHGHF>@} zlT@;{=VC*pthn`=Vbo1UU7uCQr;5n7X&rHiyOj$sS%q&_7X46i_U$(x zx4rK}!6N=JSw!ws98<+C2fv9_g6gU2p8OU6B>fHl9M3&tcU{sdhcsCcj#p{1jBnYA zhp$XhOucD-_{P(PXZiE&Q(syY#YH&bA1aNj)IYe!7er_q*jzu2dL7(!6qq{aIIOco z(h`u;V^V5(B=25F%%MXbJ4?^m_W!6|Wbq^C!K$D0l#3sSbp=0den0u4j!D4Rv8cRM z`H#hphC&?+g{_d=y2%mhjL>RZHwd7pVzNT6k+8AQ*kZYqE0Mr_vjDD82AhLSgkQ_W zQZqMLDhL3q0|Ephfjk^w!7@Rh2$mxJ9ETxch~}WXKrV#M{JH!<80{a3=91AtVyQqW z7Rk9njD#OBtV$pju@FzpSTr1jBSBOw0gEG0h*S#*w*-Qgn1jwzF+Y?COU;mf210?q zg)_?@z(N@0Bf+8tz#6jBCB*Gf=HRk4Hfv6%=nNX=2@14qo3{e}ZG6Aj<@MXS$$_>}?dq!Y7_Lm4d z6XhC5-u+omIMB9pg=@7>b!K>2oUh;MxI1R z$Wg+Cg9LU;DeR_na_1?7c~rj9aw`;oT$T!&B195`Xa^J_LXnK7pc`?K5`k&Ry-Exk z4J|~LO8EgaSC-B2LgW|SC`c}s&_FOOEDRHd$B3nYAeKs{f)EbG;n2tmv@9IKg#s;- zEgsb~tO-FDPb!ee5ugAn&0K$RsGM$OG~!2y#L;oofJlZJ^a{fhhky#M1jJ$>FeGHm zxuIB8dua9|nVc))!S*bx&`<%NW{t<sxuXexoqU{fe;JQl~c z1d%LE+&h>am0DGj1|PD-ywDH?7$b_=1RTzq4Uy3d2A+(@v)LpxlSGBkIF_{y5l_G| zY;f2S#pCvlDz*ewagWQxNT&aFhW>kg#$|jc2HIee!>YQpQdK1yqN1?`cPx%ZpwI?O zlLkS99*hE|ZVyU}WEVTNEZZS^R@P;pyjo|v<_%vbdsG|R87Lkti*I7g!ASlCs z0Wm~M8|hqDf8Du;8`n_ZGB>vbC+ztj`i+$8aQ#gv55%0}uRT}LhMT_CV2d2|Y)tmQ z@{G?L^-B^e6%KX`;N=x<>*^Z@CLLy8f|k91Tk)L36e zcn94`s_MF5@sq(eKRDD0MC|CK9`}Z9Z~!oo<}VZnB9jW4CBuWt0g2v>52IOZb7U$F z4F~``_$F;^7!ihtkuPY^WHPuim=CCQyZVioQb^$d6a*lQ0vf#l5|M}}0s+9V43CG9 z;itL)(TEI3q9BSU${+}f47Q0f0+oW$mWeVvGBCfC;V2Yj;7(kJBST-=K$!960BHy2s3H0}%o%~dC5-?$+`xcg+KPlD=BsAMggp>)d;}kaWvYlKYKXA{ z|BbRDfe+DN;2-%fYAh!sh4YtnLjw_Wu9? literal 0 HcmV?d00001 diff --git a/src/tests/plugins/badges/assets/bg-rotated/expected.pdf b/src/tests/plugins/badges/assets/bg-rotated/expected.pdf new file mode 100644 index 0000000000..0e8ee99c9d --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-rotated/expected.pdf @@ -0,0 +1,216 @@ +%PDF-1.7 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 210 297.84 ] +/Resources << +/Font 6 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +/ExtGState << +/GS0 8 0 R +>> +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/Type /ExtGState +/OP false +/op false +/OPM 1 +>> +endobj +9 0 obj +<< +/Length 287 +>> +stream +q +0.00000000000000006123234 -1 1 0.00000000000000006123234 0.0 297.84 cm +0.0 0.0 297.84 210 re +W +n +/GS0 gs +0.925811 0.881331 0.538643 rg +0 0.23622 297.638 209.764 re +f* +0.476631 0.756542 0.260899 rg +0 0.23622 297.638 209.764 re +292.638 205 m +5 205 l +5 5.23622 l +292.638 5.23622 l +h +f* +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 210 297.84 ] +/Resources << +/Font 13 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +/ExtGState << +/GS0 8 0 R +>> +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 287 +>> +stream +q +0.00000000000000006123234 -1 1 0.00000000000000006123234 0.0 297.84 cm +0.0 0.0 297.84 210 re +W +n +/GS0 gs +0.925811 0.881331 0.538643 rg +0 0.23622 297.638 209.764 re +f* +0.476631 0.756542 0.260899 rg +0 0.23622 297.638 209.764 re +292.638 205 m +5 205 l +5 5.23622 l +292.638 5.23622 l +h +f* +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000389 00000 n +0000000421 00000 n +0000000452 00000 n +0000000559 00000 n +0000000624 00000 n +0000000962 00000 n +0000001120 00000 n +0000001343 00000 n +0000001377 00000 n +0000001410 00000 n +0000001518 00000 n +0000001857 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +2015 +%%EOF diff --git a/src/tests/plugins/badges/test_pdf.py b/src/tests/plugins/badges/test_pdf.py index 8dcdc85544..c8b9b696ab 100644 --- a/src/tests/plugins/badges/test_pdf.py +++ b/src/tests/plugins/badges/test_pdf.py @@ -32,13 +32,18 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under the License. +import logging from datetime import timedelta from decimal import Decimal from io import BytesIO +from pathlib import Path +import pypdfium2 import pytest +from django.core.files import File from django.utils.timezone import now from django_scopes import scope +from PIL import ImageChops from pypdf import PdfReader from pretix.base.models import ( @@ -118,3 +123,53 @@ def test_generate_pdf_multi(env): assert ftype == 'application/pdf' pdf = PdfReader(BytesIO(buf)) assert len(pdf.pages) == 1 + + +def asset_path(name): + return Path(__file__).parent / "assets" / name + + +def compare_pdfs(pdf_dir: Path, inp_a: Path | bytes, inp_b: Path | bytes): + logging.info(f"Comparing pdfs, writing files to {pdf_dir}") + + pdf_a = pypdfium2.PdfDocument(inp_a) + pdf_b = pypdfium2.PdfDocument(inp_b) + + pdf_a.save(pdf_dir / "a.pdf") + pdf_b.save(pdf_dir / "b.pdf") + + assert len(pdf_a) == len(pdf_b) + + for i, (page_a, page_b) in enumerate(zip(pdf_a, pdf_b)): + render_a = page_a.render() + render_b = page_b.render() + assert render_a.height == render_b.height + assert render_a.width == render_b.width + + diff = ImageChops.difference(render_a.to_pil(), render_b.to_pil()) + if diff.getbbox(): + diff.save(pdf_dir / f"{i}.png") + assert not diff.getbbox(), f"Page {i} differs." + + +@pytest.mark.django_db +@pytest.mark.parametrize("case", [ + "bg-rotated", + "bg-mediabox-offset", + "bg-cropbox" +]) +def test_generate_pdf_weird_bgs(pdf_dir, env, case): + event, order, shirt = env + asset_folder = asset_path(case) + with open(asset_folder / "bg.pdf", 'rb') as fi: + event.badge_layouts.create(name="Default", default=True, background=File(fi, name="test.pdf")) + e = BadgeExporter(event, organizer=event.organizer) + fname, ftype, buf = e.render({ + 'items': [shirt.pk], + 'rendering': 'one', + 'include_pending': True + }) + assert ftype == 'application/pdf' + assert buf + + compare_pdfs(pdf_dir, buf, asset_folder / "expected.pdf")