From ddb85f56dde0c35f999646081698a1f7ab0d1a46 Mon Sep 17 00:00:00 2001 From: Ali Hamdi Ali Fadel Date: Sat, 27 Jul 2024 09:35:26 +0000 Subject: [PATCH] Add initial end-to-end tests using GitHub Actions --- .github/data/test-case-1-page.pdf | Bin 0 -> 7951 bytes .github/data/test-case-3-pages.pdf | Bin 0 -> 15234 bytes .github/data/test-case-multilines.pdf | Bin 0 -> 14225 bytes .github/workflows/tests.yml | 128 ++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 .github/data/test-case-1-page.pdf create mode 100644 .github/data/test-case-3-pages.pdf create mode 100644 .github/data/test-case-multilines.pdf create mode 100644 .github/workflows/tests.yml diff --git a/.github/data/test-case-1-page.pdf b/.github/data/test-case-1-page.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7a9d8b987c2ae4883a4b69456e0cd8c4bbbb52b7 GIT binary patch literal 7951 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 Rf|yy@SO63hBC?`@{{sU7k$V6D literal 0 HcmV?d00001 diff --git a/.github/data/test-case-multilines.pdf b/.github/data/test-case-multilines.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ea078f70373b535f89a93271d34911d2034a7825 GIT binary patch literal 14225 zcmdVBby!@x*7%RLg@FRarLySoqWPH`*6in|qer?|V6QlPjODDD)O?@Z4* z_nv#t`@HY(-`_m2cJ|8JNp`Z5C&_1rTtP&P9>f3!koRt$ZtfMHefrkh4*&z1fObZf z03IG7qnL%YGsF>kwKjByh(L_(Odvo;8HlZ!vpJB3nG?vz2XJzBgc#ZY+~E_HN91~# zFk5eF-!~wB|4hQ~K_Z~js9Mtt&!GwoqEgyRv)|GYV(ScKhDIv^8I>STb}o*_5GNqZ z9|~bRTW4sz6AE|OxXq@M!9`ydKektbp} zFR0Z_R660sLr9H9aZm#TjAl?yF%|l|6h%Zgmm;iCj>=ijmQ(KsG*{-f8fNCqj=X1@ z;S}xykh+~U;Qd&#HE<61x^%FxM|v+22r%K%HQ+nfOihu*uS5{O-?j0kq!dZ?*Ipbl z_?fgU&~+$KI88tL#*nfLlRbq4h)%Kb_)y?)BE&1#_7O5aA`PD>P&2;=G2>;Uc?YL@Hu4AQ0|nF_agNi{in zl`aFvgp;EGWs4%)I+R%yhww1;6afx7zL&Gr5k35x(>xQ-y})cE3@KF7sNls+vc=~1 zpy|y?t@5=Ih&H}QcI|_^4Af`QJ~H9^RoW$r!jo&-q?pGXl)pSU(478he%&#*^2$f~ zo_Fxwt?CKI{#d49M5gA7^?n&+8y?&RnN}J}ZF_<$T%FBRfz7ot`6D3Q=@YoR<@B>x z@2&M>dw-x&qK5D9TRXvLSuxOVv)^U~*bR5Q=e$fAIlNWlF2Lvae=CU#hKOz!6c$K} zeEEWgo-}51e~J0H-pOe(I@Cj#p4Ewe61=UdxE+rY6l&fQ%;T>S&0qou@|{}qC19g` zM(C4ag=6lb59b}ssn96-Y|xGuPWUY%nJxc21n)g; z9B_<@nO{x)(551uqe~tJU zjxJcgI}TZ35E*e?OaqztL_{cBgAD$~8><-7JcMG=)M)fP;-*N67>5nSry<#f$pm=) zgzF)i5o<rFer z_oeTvm8jSK9hA{1T1Zv_7;h4RWY%OVm_*21$oD}nx>*$ci{zb2-(!08>KIX1f1DL; zm3&Dd7l$MHo(x}!j5?*xUq#ZARF{I6qU}xG5SNL#BY~!Xo_qya7EqrYBbHwwo{9oT zUh1W&(3~8nRFi;*fQN9t((@wQ?;0h^%^6zqZ6e-M-i+dL;H0yp^`Y{((ip3Ry(CX^ z`S_V6w&T>@Ro{<&3Z*Lhs-mPh_mP2PR8x@oxk30J4b<#L$o)k zHeYTMZPpGeJ?&;PxB@E?=10Uuv_wRmvHWZrTOV6stF+L2Y^6@Prm>~*N+3-zO@L2` zDv?pOo5GpOD6uJ#|ITDdVQFYNXL&otP#QT_IOdi)mZ8t`xN#SSpQ|%RrsE7V2jttxc`1&w5M=DTiNFOv!7*IkU?v z4hreV`SO-ZdCQH9YBkJq&7x@vkNxpG$^|X$xAb8FzQz-9%b_>W|e29q_Ny);M49&09U!Q-? zMMc9u#{W)F;5hEE*7(vfhQWj(Lf_p!`@8Bw!n)Sp%@^63$Sv1io8F~a-nsk6TUrch zj2Q9of%w9>Eut}0y$?y1>M`n-4Y8L-N0vv0d|Z5?e35+E?XK;m-i%j<_Xzi{H%n(T z$6GfuxAI6FNM$J7fIK8IB(-OJsLUu>Ph60Cy5PH70$wvt=#%Mu$3qah6Lt;eL19JH z#l3MNV4!0uquBRoRCV`pcSE8#5)~2dZIOr?oEQ`jkHnM4a}yg9?-QL8mlgFCO%jz( z(xB6<-4Kh=iU1by;=Lxu^(1q3EWVsrk`7tl{{dJ(WB}_V*6zq|8LNoa@6vRj zc}4u1WCimv6uY~4Q>NlvzsYSAX(p~E^8eBYHJZceCcU3njL~a;XMXL+urEFvDVaa6@ZXULn zI#k8Z5g3n=p>onRZAt$4AoEKif-H?ZP!qM*vS! FjGx_~pgV^NrLE+YyqXv!Pob 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 AhX4Qo literal 0 HcmV?d00001 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..b746a50 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,128 @@ +name: Tests + +on: + push: + branches: + - main + pull_request: + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + steps: + - name: Install poppler-utils and docx2txt + run: | + sudo apt-get update + sudo apt-get install -y poppler-utils docx2txt + + - name: Checkout code + uses: actions/checkout@v4 + - name: Install Poetry + uses: snok/install-poetry@v1 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version-file: 'pyproject.toml' + cache: 'poetry' + - name: Install Poetry dependencies + run: poetry install + + - name: Write SERVICE_ACCOUNT_CREDENTIALS to service_account_credentials.json + uses: jsdaniell/create-json@v1.2.3 + with: + name: "service_account_credentials.json" + json: ${{ secrets.SERVICE_ACCOUNT_CREDENTIALS }} + + - name: Test Tahweel on 1 page file + run: | + poetry run tahweel ".github/data/test-case-1-page.pdf" --service-account-credentials service_account_credentials.json + test -f ".github/data/test-case-1-page.txt" || exit 1 + test -f ".github/data/test-case-1-page.docx" || exit 1 + grep -q "^بسم الله الرحمن الرحيم$" ".github/data/test-case-1-page.txt" || exit 1 + rm -f ".github/data/test-case-1-page.txt" ".github/data/test-case-1-page.docx" + + - name: Test Tahweel on 3 pages file + run: | + poetry run tahweel ".github/data/test-case-3-pages.pdf" --service-account-credentials service_account_credentials.json + test -f ".github/data/test-case-3-pages.txt" || exit 1 + test -f ".github/data/test-case-3-pages.docx" || exit 1 + grep -o "PAGE_SEPARATOR" ".github/data/test-case-3-pages.txt" | wc -l | grep -q "^2$" || exit 1 + head -n 1 ".github/data/test-case-3-pages.txt" | grep -q "^بسم الله الرحمن الرحيم$" || exit 1 + tail -n 1 ".github/data/test-case-3-pages.txt" | grep -q "^والصلاة والسلام على أشرف الأنبياء والمرسلين$" || exit 1 + rm -f ".github/data/test-case-3-pages.txt" ".github/data/test-case-3-pages.docx" + + - name: Test Tahweel on multiple files + run: | + poetry run tahweel ".github/data/test-case-1-page.pdf" ".github/data/test-case-3-pages.pdf" --service-account-credentials service_account_credentials.json + test -f ".github/data/test-case-1-page.txt" || exit 1 + test -f ".github/data/test-case-1-page.docx" || exit 1 + test -f ".github/data/test-case-3-pages.txt" || exit 1 + test -f ".github/data/test-case-3-pages.docx" || exit 1 + rm -f ".github/data/test-case-1-page.txt" ".github/data/test-case-1-page.docx" ".github/data/test-case-3-pages.txt" ".github/data/test-case-3-pages.docx" + + - name: Test Tahweel on a directory with --dir-output-type tree_to_tree + run: | + poetry run tahweel ".github/data/" --service-account-credentials service_account_credentials.json --dir-output-type tree_to_tree + test -f ".github/data - Tahweel TXT/test-case-1-page.txt" || exit 1 + test -f ".github/data - Tahweel DOCX/test-case-1-page.docx" || exit 1 + test -f ".github/data - Tahweel TXT/test-case-3-pages.txt" || exit 1 + test -f ".github/data - Tahweel DOCX/test-case-3-pages.docx" || exit 1 + rm -rf ".github/data - Tahweel TXT" ".github/data - Tahweel DOCX" + + - name: Test Tahweel on a directory with --dir-output-type side_by_side + run: | + poetry run tahweel ".github/data/" --service-account-credentials service_account_credentials.json --dir-output-type side_by_side + test -f ".github/data/test-case-1-page.txt" || exit 1 + test -f ".github/data/test-case-1-page.docx" || exit 1 + test -f ".github/data/test-case-3-pages.txt" || exit 1 + test -f ".github/data/test-case-3-pages.docx" || exit 1 + rm -rf ".github/data/test-case-1-page.txt" ".github/data/test-case-1-page.docx" ".github/data/test-case-3-pages.txt" ".github/data/test-case-3-pages.docx" + + - name: Test Tahweel on 3 pages file with --txt-page-separator ANYTHING + run: | + poetry run tahweel ".github/data/test-case-3-pages.pdf" --service-account-credentials service_account_credentials.json --txt-page-separator ANYTHING + test -f ".github/data/test-case-3-pages.txt" || exit 1 + test -f ".github/data/test-case-3-pages.docx" || exit 1 + grep -o "ANYTHING" ".github/data/test-case-3-pages.txt" | wc -l | grep -q "^2$" || exit 1 + rm -f ".github/data/test-case-3-pages.txt" ".github/data/test-case-3-pages.docx" + + - name: Test Tahweel on multilines file with --docx-remove-newlines + run: | + poetry run tahweel ".github/data/test-case-multilines.pdf" --service-account-credentials service_account_credentials.json --docx-remove-newlines + test -f ".github/data/test-case-multilines.txt" || exit 1 + test -f ".github/data/test-case-multilines.docx" || exit 1 + docx2txt .github/data/test-case-multilines.docx - | grep -q "^بسم الله الرحمن الرحيم والصلاة والسلام على أشرف الأنبياء والمرسلين$" || exit 1 + rm -f ".github/data/test-case-multilines.txt" ".github/data/test-case-multilines.docx" + + - name: Test Tahweel on 1 page file with --output-formats txt + run: | + poetry run tahweel ".github/data/test-case-1-page.pdf" --service-account-credentials service_account_credentials.json --output-formats txt + test -f ".github/data/test-case-1-page.txt" || exit 1 + test ! -f ".github/data/test-case-1-page.docx" || exit 1 + rm -f ".github/data/test-case-1-page.txt" + + - name: Test Tahweel on 1 page file with --output-dir ".github/custom-output-dir" + run: | + poetry run tahweel ".github/data/test-case-1-page.pdf" --service-account-credentials service_account_credentials.json --output-dir ".github/custom-output-dir" + test -f ".github/custom-output-dir/test-case-1-page.txt" || exit 1 + test -f ".github/custom-output-dir/test-case-1-page.docx" || exit 1 + rm -f ".github/custom-output-dir/test-case-1-page.txt" ".github/custom-output-dir/test-case-1-page.docx" + + - name: Test Tahweel on a directory with --dir-output-type tree_to_tree --output-dir ".github/custom-output-dir" + run: | + poetry run tahweel ".github/data/" --service-account-credentials service_account_credentials.json --dir-output-type tree_to_tree --output-dir ".github/custom-output-dir" + test -f ".github/custom-output-dir/Tahweel TXT/test-case-1-page.txt" || exit 1 + test -f ".github/custom-output-dir/Tahweel DOCX/test-case-1-page.docx" || exit 1 + test -f ".github/custom-output-dir/Tahweel TXT/test-case-3-pages.txt" || exit 1 + test -f ".github/custom-output-dir/Tahweel DOCX/test-case-3-pages.docx" || exit 1 + rm -rf ".github/custom-output-dir" + + - name: Test Tahweel on a directory with --dir-output-type side_by_side --output-dir ".github/custom-output-dir" + run: | + poetry run tahweel ".github/data/" --service-account-credentials service_account_credentials.json --dir-output-type side_by_side --output-dir ".github/custom-output-dir" + test -f ".github/custom-output-dir/test-case-1-page.txt" || exit 1 + test -f ".github/custom-output-dir/test-case-1-page.docx" || exit 1 + test -f ".github/custom-output-dir/test-case-3-pages.txt" || exit 1 + test -f ".github/custom-output-dir/test-case-3-pages.docx" || exit 1 + rm -rf ".github/custom-output-dir"