mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-12-22 04:50:09 +00:00
merge
This commit is contained in:
commit
1807b73524
18
.travis.yml
18
.travis.yml
@ -1,18 +1,32 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
sauce_connect: true
|
||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository ppa:fontforge/fontforge --yes
|
- sudo add-apt-repository ppa:fontforge/fontforge --yes
|
||||||
- sudo add-apt-repository ppa:coolwanglu/pdf2htmlex --yes
|
- sudo add-apt-repository ppa:coolwanglu/pdf2htmlex --yes
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -qq libpoppler-dev libpoppler-private-dev libspiro-dev libcairo-dev libpango1.0-dev libfreetype6-dev libltdl-dev libfontforge-dev python-imaging wkhtmltopdf
|
- sudo apt-get install -qq libpoppler-dev libpoppler-private-dev libspiro-dev libcairo-dev libpango1.0-dev libfreetype6-dev libltdl-dev libfontforge-dev python-imaging python-pip firefox xvfb
|
||||||
|
- sudo pip install selenium sauceclient
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- test/start_xvfb.sh
|
||||||
|
- pushd test/browser_tests
|
||||||
|
- python -m SimpleHTTPServer 8000 &
|
||||||
|
- popd
|
||||||
|
- sleep 5
|
||||||
before_script:
|
before_script:
|
||||||
- cmake -DENABLE_SVG=ON .
|
- cmake -DENABLE_SVG=ON .
|
||||||
script:
|
script:
|
||||||
- make
|
- make
|
||||||
- make test
|
- P2H_TEST_REMOTE=1 ctest --output-on-failure
|
||||||
- sudo make install
|
- sudo make install
|
||||||
- /usr/local/bin/pdf2htmlEX -v
|
- /usr/local/bin/pdf2htmlEX -v
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- incoming
|
- incoming
|
||||||
|
- wl
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- secure: V0yGXROTAsRc3ExcECj7X/CrJLbodUeqZyfQGkA6x0iLV7Lh8/hgTjSsvuj7ef/DIWMqJ5cAIzZuXiF0KIxiVllF1v0I3w+LScxynT7B1NsyH16hvGIc7EvrsRmGVeTv8n9I+cCIwQxjtliNKfeZjV4Rk2+u6LioUzTszmW2etc=
|
||||||
|
- secure: Q5ZSrdFEgN0JvUp90nY5Wh58iukmGZQ2EW7crOibWH2yuUsxAnMELxpY+9yV3+eA7kbjJf/I0NCa5ZY1gkxK60ugUj+zuUDTL+BV1XCbO37e0uwh3ae99iyQWpXc8e8wBp10sthoX7U6Hvypa5tD9r1JJib8jxJV/MzIFpb7H9s=
|
||||||
|
@ -1 +0,0 @@
|
|||||||
SET(CTEST_CUSTOM_POST_TEST "cat Testing/Temporary/LastTest.log")
|
|
@ -3,7 +3,7 @@
|
|||||||
<!--
|
<!--
|
||||||
[![Build Status](https://travis-ci.org/coolwanglu/pdf2htmlEX.png?branch=master)](https://travis-ci.org/coolwanglu/pdf2htmlEX)
|
[![Build Status](https://travis-ci.org/coolwanglu/pdf2htmlEX.png?branch=master)](https://travis-ci.org/coolwanglu/pdf2htmlEX)
|
||||||
-->
|
-->
|
||||||
>一图胜千言<br>A beautiful demo is worth a thousand words:
|
>一图胜千言<br>A beautiful demo is worth a thousand words
|
||||||
|
|
||||||
- **Bible de Genève, 1564** (fonts and typography): [HTML](http://coolwanglu.github.com/pdf2htmlEX/demo/geneve.html) / [PDF](https://github.com/raphink/geneve_1564/raw/master/geneve_1564.pdf)
|
- **Bible de Genève, 1564** (fonts and typography): [HTML](http://coolwanglu.github.com/pdf2htmlEX/demo/geneve.html) / [PDF](https://github.com/raphink/geneve_1564/raw/master/geneve_1564.pdf)
|
||||||
- **Cheat Sheet** (math formulas): [HTML](http://coolwanglu.github.com/pdf2htmlEX/demo/cheat.html) / [PDF](http://www.tug.org/texshowcase/cheat.pdf)
|
- **Cheat Sheet** (math formulas): [HTML](http://coolwanglu.github.com/pdf2htmlEX/demo/cheat.html) / [PDF](http://www.tug.org/texshowcase/cheat.pdf)
|
||||||
|
4
debian/control
vendored
4
debian/control
vendored
@ -6,11 +6,11 @@ Build-Depends: cmake (>= 2.6.0),
|
|||||||
debhelper (>= 8),
|
debhelper (>= 8),
|
||||||
default-jre-headless (>= 1.6),
|
default-jre-headless (>= 1.6),
|
||||||
libcairo2-dev,
|
libcairo2-dev,
|
||||||
libfontforge-dev,
|
libfontforge-dev (>= 20140000),
|
||||||
libjpeg-dev,
|
libjpeg-dev,
|
||||||
libpango1.0-dev,
|
libpango1.0-dev,
|
||||||
libpng12-dev,
|
libpng12-dev,
|
||||||
libpoppler-dev (>= 0.20.3),
|
libpoppler-dev (>= 0.25.0),
|
||||||
libspiro-dev,
|
libspiro-dev,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
python-dev
|
python-dev
|
||||||
|
1
test/.gitattributes
vendored
1
test/.gitattributes
vendored
@ -1 +1,2 @@
|
|||||||
*.pdf binary
|
*.pdf binary
|
||||||
|
*.woff binary
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- wkhtmltoimage
|
- python2 and packages
|
||||||
- python2
|
- Python Imaging Library
|
||||||
- Python Imaging Library
|
- Selenium
|
||||||
|
- unittest
|
||||||
|
- Firefox
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
- Run all tests:
|
- Run all tests:
|
||||||
- `./test.py`
|
- `./test.py`
|
||||||
- Run selected tests:
|
- Run selected test suites:
|
||||||
- `./test.py test_A test_B ...`
|
- `./test.py test_local_browser`
|
||||||
|
- Run selected test case:
|
||||||
|
- `./test.py test_local_browser.test_basic_text`
|
||||||
|
- Or `./test.py test_basic_text
|
||||||
- Environment variables:
|
- Environment variables:
|
||||||
- set `P2H_TEST_SAVE_TMP=1` to keep the temporary files
|
- set `P2H_TEST_SAVE_TMP=1` to keep the temporary files in `/tmp/pdf2htmlEX_test`
|
||||||
- set `P2H_TEST_GEN=1` to generate new reference images instead of comparing with old ones
|
- set `P2H_TEST_GEN=1` to generate new reference files
|
||||||
|
|
||||||
### Guidelines for test cases
|
### Guidelines for test cases
|
||||||
|
|
||||||
@ -21,6 +26,5 @@
|
|||||||
- One page only, unless the test case is about multiple pages.
|
- One page only, unless the test case is about multiple pages.
|
||||||
- Grayscale only, unless the test case is about colors.
|
- Grayscale only, unless the test case is about colors.
|
||||||
- Remove unnecessary elements.
|
- Remove unnecessary elements.
|
||||||
- Set proper parameters for cropping in `wkhtml2image_args`.
|
|
||||||
- [Optional] Include the source files that the PDF file is generated from.
|
- [Optional] Include the source files that the PDF file is generated from.
|
||||||
|
|
||||||
|
84
test/browser_tests.py
Normal file
84
test/browser_tests.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from PIL import Image, ImageChops
|
||||||
|
from test import Common
|
||||||
|
|
||||||
|
class BrowserTests(Common):
|
||||||
|
TEST_DATA_DIR = os.path.join(Common.TEST_DIR, 'browser_tests')
|
||||||
|
|
||||||
|
DEFAULT_PDF2HTMLEX_ARGS = [
|
||||||
|
'--fit-width', 800,
|
||||||
|
'--last-page', 1,
|
||||||
|
'--embed', 'fi', # avoid base64 to make it faster
|
||||||
|
]
|
||||||
|
|
||||||
|
BROWSER_WIDTH=800
|
||||||
|
BROWSER_HEIGHT=1200
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run_test_case(self, filename, pdf2htmlEX_args=[]):
|
||||||
|
basefilename, extension = os.path.splitext(filename)
|
||||||
|
htmlfilename = basefilename + '.html'
|
||||||
|
|
||||||
|
ref_htmlfolder = os.path.join(self.TEST_DATA_DIR, basefilename)
|
||||||
|
ref_htmlfilename = os.path.join(ref_htmlfolder, htmlfilename)
|
||||||
|
|
||||||
|
out_htmlfilename = os.path.join(self.cur_output_dir, htmlfilename)
|
||||||
|
|
||||||
|
self.assertEquals(extension.lower(), '.pdf', 'Input file is not PDF')
|
||||||
|
|
||||||
|
pdf2htmlEX_args = self.DEFAULT_PDF2HTMLEX_ARGS \
|
||||||
|
+ list(pdf2htmlEX_args) + [
|
||||||
|
os.path.join(self.TEST_DATA_DIR, filename),
|
||||||
|
htmlfilename
|
||||||
|
]
|
||||||
|
|
||||||
|
result = self.run_pdf2htmlEX(pdf2htmlEX_args)
|
||||||
|
self.assertIn(htmlfilename, result['output_files'], 'HTML file is not generated')
|
||||||
|
|
||||||
|
if self.GENERATING_MODE:
|
||||||
|
# copy generated html files
|
||||||
|
shutil.rmtree(ref_htmlfolder, True)
|
||||||
|
shutil.copytree(self.cur_output_dir, ref_htmlfolder)
|
||||||
|
return
|
||||||
|
|
||||||
|
png_out_dir = os.path.join(self.cur_temp_dir, 'png_out')
|
||||||
|
os.mkdir(png_out_dir)
|
||||||
|
|
||||||
|
pngfilename_out_fullpath = os.path.join(png_out_dir, basefilename + '.out.png')
|
||||||
|
self.generate_image(out_htmlfilename, pngfilename_out_fullpath)
|
||||||
|
out_img = Image.open(pngfilename_out_fullpath)
|
||||||
|
|
||||||
|
pngfilename_ref_fullpath = os.path.join(png_out_dir, basefilename + '.ref.png')
|
||||||
|
self.generate_image(ref_htmlfilename, pngfilename_ref_fullpath)
|
||||||
|
ref_img = Image.open(pngfilename_ref_fullpath)
|
||||||
|
|
||||||
|
diff_img = ImageChops.difference(ref_img, out_img);
|
||||||
|
|
||||||
|
if diff_img.getbbox() is not None:
|
||||||
|
if self.SAVE_TMP:
|
||||||
|
# save the diff image
|
||||||
|
# http://stackoverflow.com/questions/15721484/saving-in-png-using-pil-library-after-taking-imagechops-difference-of-two-png
|
||||||
|
diff_img.crop(diff_img.getbbox()).convert('RGB').save(os.path.join(png_out_dir, basefilename + '.diff.png'))
|
||||||
|
self.fail('PNG files differ')
|
||||||
|
|
||||||
|
def test_basic_text(self):
|
||||||
|
self.run_test_case('basic_text.pdf')
|
||||||
|
|
||||||
|
def test_geneve_1564(self):
|
||||||
|
self.run_test_case('geneve_1564.pdf')
|
||||||
|
|
||||||
|
def test_text_visibility(self):
|
||||||
|
self.run_test_case('text_visibility.pdf', ['--correct-text-visibility', 1])
|
||||||
|
|
107
test/browser_tests/basic_text/basic_text.html
Normal file
107
test/browser_tests/basic_text/basic_text.html
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Created by pdf2htmlEX (https://github.com/coolwanglu/pdf2htmlex) -->
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="generator" content="pdf2htmlEX"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||||
|
<style type="text/css">
|
||||||
|
/*!
|
||||||
|
* Base CSS for pdf2htmlEX
|
||||||
|
* Copyright 2012,2013 Lu Wang <coolwanglu@gmail.com>
|
||||||
|
* https://github.com/coolwanglu/pdf2htmlEX/blob/master/share/LICENSE
|
||||||
|
*/#sidebar{position:absolute;top:0;left:0;bottom:0;width:250px;padding:0;margin:0;overflow:auto}#page-container{position:absolute;top:0;left:0;margin:0;padding:0;border:0}@media screen{#sidebar.opened+#page-container{left:250px}#page-container{bottom:0;right:0;overflow:auto}.loading-indicator{display:none}.loading-indicator.active{display:block;position:absolute;width:64px;height:64px;top:50%;left:50%;margin-top:-32px;margin-left:-32px}.loading-indicator img{position:absolute;top:0;left:0;bottom:0;right:0}}@media print{@page{margin:0}html{margin:0}body{margin:0;-webkit-print-color-adjust:exact}#sidebar{display:none}#page-container{width:auto;height:auto;overflow:visible;background-color:transparent}.d{display:none}}.pf{position:relative;background-color:white;overflow:hidden;margin:0;border:0}.pc{position:absolute;border:0;padding:0;margin:0;top:0;left:0;width:100%;height:100%;overflow:hidden;display:block;transform-origin:0 0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0}.pc.opened{display:block}.bf{position:absolute;border:0;margin:0;top:0;bottom:0;width:100%;height:100%;-ms-user-select:none;-moz-user-select:none;-webkit-user-select:none;user-select:none}.bi{position:absolute;border:0;margin:0;-ms-user-select:none;-moz-user-select:none;-webkit-user-select:none;user-select:none}@media print{.pf{margin:0;box-shadow:none;page-break-after:always;page-break-inside:avoid}@-moz-document url-prefix(){.pf{overflow:visible;border:1px solid #fff}.pc{overflow:visible}}}.c{position:absolute;border:0;padding:0;margin:0;overflow:hidden;display:block}.t{position:absolute;white-space:pre;font-size:1px;transform-origin:0 100%;-ms-transform-origin:0 100%;-webkit-transform-origin:0 100%;unicode-bidi:bidi-override;-moz-font-feature-settings:"liga" 0}.t:after{content:''}.t span{position:relative;display:inline-block;unicode-bidi:bidi-override}._{color:transparent;z-index:-1}::selection{background:rgba(127,255,255,0.4)}::-moz-selection{background:rgba(127,255,255,0.4)}.pi{display:none}.d{position:absolute;transform-origin:0 100%;-ms-transform-origin:0 100%;-webkit-transform-origin:0 100%}</style>
|
||||||
|
<style type="text/css">
|
||||||
|
/* CSS for test cases */
|
||||||
|
#page-container {
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
.ff0{font-family:sans-serif;visibility:hidden;}
|
||||||
|
@font-face{font-family:ff1;src:url(f1.woff)format("woff");}.ff1{font-family:ff1;line-height:0.899000;font-style:normal;font-weight:normal;visibility:visible;}
|
||||||
|
@font-face{font-family:ff2;src:url(f2.woff)format("woff");}.ff2{font-family:ff2;line-height:0.882000;font-style:normal;font-weight:normal;visibility:visible;}
|
||||||
|
.m2{transform:matrix(0.231081,-0.231081,0.231081,0.231081,0,0);-ms-transform:matrix(0.231081,-0.231081,0.231081,0.231081,0,0);-webkit-transform:matrix(0.231081,-0.231081,0.231081,0.231081,0,0);}
|
||||||
|
.m0{transform:matrix(0.326797,0.000000,0.000000,0.326797,0,0);-ms-transform:matrix(0.326797,0.000000,0.000000,0.326797,0,0);-webkit-transform:matrix(0.326797,0.000000,0.000000,0.326797,0,0);}
|
||||||
|
.m3{transform:matrix(0.462161,-0.462161,0.231081,0.231081,0,0);-ms-transform:matrix(0.462161,-0.462161,0.231081,0.231081,0,0);-webkit-transform:matrix(0.462161,-0.462161,0.231081,0.231081,0,0);}
|
||||||
|
.m1{transform:matrix(0.653595,0.000000,0.000000,0.326797,0,0);-ms-transform:matrix(0.653595,0.000000,0.000000,0.326797,0,0);-webkit-transform:matrix(0.653595,0.000000,0.000000,0.326797,0,0);}
|
||||||
|
.v0{vertical-align:0.000000px;}
|
||||||
|
.ls0{letter-spacing:0.000000px;}
|
||||||
|
.ls1{letter-spacing:20.000000px;}
|
||||||
|
.ls2{letter-spacing:20.081833px;}
|
||||||
|
.sc_{text-shadow:none;}
|
||||||
|
.sc0{text-shadow:-0.015em 0 transparent,0 0.015em transparent,0.015em 0 transparent,0 -0.015em transparent;}
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0){
|
||||||
|
.sc_{-webkit-text-stroke:0px transparent;}
|
||||||
|
.sc0{-webkit-text-stroke:0.015em transparent;text-shadow:none;}
|
||||||
|
}
|
||||||
|
.ws0{word-spacing:0.000000px;}
|
||||||
|
._1{display:inline;margin-left:-3.997949px;}
|
||||||
|
._2{display:inline;margin-left:-1.115811px;}
|
||||||
|
._0{display:inline-block;width:39.850619px;}
|
||||||
|
.fc0{color:rgb(0,0,0);}
|
||||||
|
.fs1{font-size:19.925200px;}
|
||||||
|
.fs0{font-size:39.850400px;}
|
||||||
|
.fs2{font-size:40.013453px;}
|
||||||
|
.y8{bottom:210.583007px;}
|
||||||
|
.y7{bottom:628.221281px;}
|
||||||
|
.y6{bottom:650.413190px;}
|
||||||
|
.y4{bottom:672.604170px;}
|
||||||
|
.y5{bottom:715.900248px;}
|
||||||
|
.y3{bottom:796.620915px;}
|
||||||
|
.y2{bottom:827.875817px;}
|
||||||
|
.y0{bottom:859.130719px;}
|
||||||
|
.y1{bottom:865.666667px;}
|
||||||
|
.h1{height:28.094532px;}
|
||||||
|
.h2{height:28.209484px;}
|
||||||
|
.h0{height:1035.294118px;}
|
||||||
|
.w0{width:800.000000px;}
|
||||||
|
.x0{left:194.394771px;}
|
||||||
|
.x2{left:199.825216px;}
|
||||||
|
.x4{left:222.016196px;}
|
||||||
|
.x3{left:233.840248px;}
|
||||||
|
.x5{left:244.208105px;}
|
||||||
|
.x1{left:312.996078px;}
|
||||||
|
.x6{left:396.252288px;}
|
||||||
|
@media print{
|
||||||
|
.v0{vertical-align:0.000000pt;}
|
||||||
|
.ls0{letter-spacing:0.000000pt;}
|
||||||
|
.ls1{letter-spacing:20.400000pt;}
|
||||||
|
.ls2{letter-spacing:20.483469pt;}
|
||||||
|
.ws0{word-spacing:0.000000pt;}
|
||||||
|
._1{display:inline;margin-left:-4.077908pt;}
|
||||||
|
._2{display:inline;margin-left:-1.138127pt;}
|
||||||
|
._0{display:inline-block;width:40.647631pt;}
|
||||||
|
.fs1{font-size:20.323704pt;}
|
||||||
|
.fs0{font-size:40.647408pt;}
|
||||||
|
.fs2{font-size:40.813722pt;}
|
||||||
|
.y8{bottom:214.794667pt;}
|
||||||
|
.y7{bottom:640.785707pt;}
|
||||||
|
.y6{bottom:663.421453pt;}
|
||||||
|
.y4{bottom:686.056253pt;}
|
||||||
|
.y5{bottom:730.218253pt;}
|
||||||
|
.y3{bottom:812.553333pt;}
|
||||||
|
.y2{bottom:844.433333pt;}
|
||||||
|
.y0{bottom:876.313333pt;}
|
||||||
|
.y1{bottom:882.980000pt;}
|
||||||
|
.h1{height:28.656423pt;}
|
||||||
|
.h2{height:28.773674pt;}
|
||||||
|
.h0{height:1056.000000pt;}
|
||||||
|
.w0{width:816.000000pt;}
|
||||||
|
.x0{left:198.282667pt;}
|
||||||
|
.x2{left:203.821720pt;}
|
||||||
|
.x4{left:226.456520pt;}
|
||||||
|
.x3{left:238.517053pt;}
|
||||||
|
.x5{left:249.092267pt;}
|
||||||
|
.x1{left:319.256000pt;}
|
||||||
|
.x6{left:404.177333pt;}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="page-container">
|
||||||
|
<div id="pf1" class="pf w0 h0" data-page-no="1"><div class="pc pc1 w0 h0"><div class="t m0 x0 h1 y0 ff1 fs0 fc0 sc0 ls0 ws0">Normal<span class="_ _0"> </span><span class="ff2 fs1">tiny<span class="_ _0"> </span></span>T<span class="_ _1"></span>ext</div><div class="t m0 x1 h1 y1 ff1 fs0 fc0 sc0 ls0 ws0">Rise</div><div class="t m0 x0 h1 y2 ff1 fs0 fc0 sc0 ls1 ws0">CharSpace</div><div class="t m1 x0 h1 y3 ff1 fs0 fc0 sc0 ls0 ws0">Horizon<span class="_ _2"></span>tal<span class="_ _0"> </span>Scale</div><div class="t m2 x2 h2 y4 ff1 fs2 fc0 sc0 ls0 ws0">Rotated</div><div class="t m2 x3 h2 y5 ff1 fs2 fc0 sc0 ls0 ws0">Rise</div><div class="t m2 x4 h2 y6 ff1 fs2 fc0 sc0 ls2 ws0">CharSpace</div><div class="t m3 x5 h2 y7 ff1 fs2 fc0 sc0 ls0 ws0">Horizon<span class="_ _2"></span>tal<span class="_ _0"> </span>Scale</div><div class="t m0 x6 h1 y8 ff1 fs0 fc0 sc0 ls0 ws0">1</div></div><div class="pi" data-data='{"ctm":[1.307190,0.000000,0.000000,1.307190,0.000000,0.000000]}'></div></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
test/browser_tests/basic_text/f1.woff
Normal file
BIN
test/browser_tests/basic_text/f1.woff
Normal file
Binary file not shown.
BIN
test/browser_tests/basic_text/f2.woff
Normal file
BIN
test/browser_tests/basic_text/f2.woff
Normal file
Binary file not shown.
BIN
test/browser_tests/geneve_1564/bg1.png
Normal file
BIN
test/browser_tests/geneve_1564/bg1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
BIN
test/browser_tests/geneve_1564/f1.woff
Normal file
BIN
test/browser_tests/geneve_1564/f1.woff
Normal file
Binary file not shown.
BIN
test/browser_tests/geneve_1564/f2.woff
Normal file
BIN
test/browser_tests/geneve_1564/f2.woff
Normal file
Binary file not shown.
738
test/browser_tests/geneve_1564/geneve_1564.html
Normal file
738
test/browser_tests/geneve_1564/geneve_1564.html
Normal file
File diff suppressed because one or more lines are too long
BIN
test/browser_tests/text_visibility/bg1.png
Normal file
BIN
test/browser_tests/text_visibility/bg1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 109 KiB |
BIN
test/browser_tests/text_visibility/f1.woff
Normal file
BIN
test/browser_tests/text_visibility/f1.woff
Normal file
Binary file not shown.
BIN
test/browser_tests/text_visibility/f2.woff
Normal file
BIN
test/browser_tests/text_visibility/f2.woff
Normal file
Binary file not shown.
153
test/browser_tests/text_visibility/text_visibility.html
Normal file
153
test/browser_tests/text_visibility/text_visibility.html
Normal file
File diff suppressed because one or more lines are too long
2
test/start_xvfb.sh
Executable file
2
test/start_xvfb.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1920x16
|
38
test/test.py
38
test/test.py
@ -14,6 +14,8 @@ class Common(object):
|
|||||||
PDF2HTMLEX_PATH = os.path.join(SRC_DIR, 'pdf2htmlEX')
|
PDF2HTMLEX_PATH = os.path.join(SRC_DIR, 'pdf2htmlEX')
|
||||||
|
|
||||||
SAVE_TMP = os.environ.get('P2H_TEST_SAVE_TMP')
|
SAVE_TMP = os.environ.get('P2H_TEST_SAVE_TMP')
|
||||||
|
GENERATING_MODE = os.environ.get('P2H_TEST_GEN')
|
||||||
|
|
||||||
CANONICAL_TEMPDIR = '/tmp/pdf2htmlEX_test'
|
CANONICAL_TEMPDIR = '/tmp/pdf2htmlEX_test'
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -83,16 +85,34 @@ if __name__ == '__main__':
|
|||||||
exit(1)
|
exit(1)
|
||||||
suites = []
|
suites = []
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
test_names = list(map(lambda x: 'T.'+x, sys.argv[1:]))
|
|
||||||
for module_name in ['test_naming', 'test_conversion']:
|
all_modules = []
|
||||||
__import__(module_name)
|
all_modules.append(__import__('test_output'))
|
||||||
if len(test_names) > 0:
|
all_modules.append(__import__('test_local_browser'))
|
||||||
try:
|
all_classes = ['test_output', 'test_local_browser']
|
||||||
suites.append(loader.loadTestsFromNames(test_names, sys.modules[module_name]))
|
|
||||||
except:
|
if os.environ.get('P2H_TEST_REMOTE'):
|
||||||
pass
|
m = __import__('test_remote_browser')
|
||||||
|
all_modules.append(m)
|
||||||
|
all_classes += m.test_classnames
|
||||||
|
|
||||||
|
test_names = []
|
||||||
|
for name in sys.argv[1:]:
|
||||||
|
if name.find('.') != -1:
|
||||||
|
test_names.append(name)
|
||||||
else:
|
else:
|
||||||
suites.append(loader.loadTestsFromModule(sys.modules[module_name]))
|
for m in all_classes:
|
||||||
|
test_names.append(m + '.' + name)
|
||||||
|
|
||||||
|
for module in all_modules:
|
||||||
|
if len(test_names) > 0:
|
||||||
|
for n in test_names:
|
||||||
|
try:
|
||||||
|
suites.append(loader.loadTestsFromName(n, module))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
suites.append(loader.loadTestsFromModule(module))
|
||||||
|
|
||||||
if len(suites) == 0:
|
if len(suites) == 0:
|
||||||
print >>sys.stderr, 'No test found'
|
print >>sys.stderr, 'No test found'
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from PIL import Image, ImageChops
|
|
||||||
from test import Common
|
|
||||||
|
|
||||||
class T(Common, unittest.TestCase):
|
|
||||||
GENERATING_MODE = os.environ.get('P2H_TEST_GEN')
|
|
||||||
|
|
||||||
WKHTML2IMAGE = 'wkhtmltoimage'
|
|
||||||
TTFAUTOHINT = 'ttfautohint'
|
|
||||||
TEST_DATA_DIR = os.path.join(Common.TEST_DIR, 'test_conversion')
|
|
||||||
|
|
||||||
DEFAULT_PDF2HTMLEX_ARGS = [
|
|
||||||
'--external-hint-tool', 'ttfautohint',
|
|
||||||
'--fit-width', 800,
|
|
||||||
'--last-page', 1,
|
|
||||||
'--correct-text-visibility', 1,
|
|
||||||
]
|
|
||||||
|
|
||||||
DEFAULT_WKHTML2IMAGE_ARGS = [
|
|
||||||
'-f', 'png',
|
|
||||||
'--height', 600,
|
|
||||||
'--width', 800,
|
|
||||||
'--quality', 0,
|
|
||||||
'--quiet'
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
subprocess.check_call([cls.WKHTML2IMAGE, '--version'])
|
|
||||||
subprocess.check_call([cls.TTFAUTOHINT, '--version'])
|
|
||||||
|
|
||||||
def run_test_case(self, filename, pdf2htmlEX_args=[], wkhtml2image_args=[]):
|
|
||||||
basefilename, extension = os.path.splitext(filename)
|
|
||||||
htmlfilename = basefilename + '.html'
|
|
||||||
pngfilename = basefilename + '.png'
|
|
||||||
|
|
||||||
self.assertEquals(extension.lower(), '.pdf', 'Input file is not PDF')
|
|
||||||
|
|
||||||
pdf2htmlEX_args = self.DEFAULT_PDF2HTMLEX_ARGS \
|
|
||||||
+ list(pdf2htmlEX_args) + [
|
|
||||||
os.path.join(self.TEST_DATA_DIR, filename),
|
|
||||||
htmlfilename
|
|
||||||
]
|
|
||||||
|
|
||||||
result = self.run_pdf2htmlEX(pdf2htmlEX_args)
|
|
||||||
self.assertIn(htmlfilename, result['output_files'], 'HTML file is not generated')
|
|
||||||
|
|
||||||
png_out_dir = os.path.join(self.cur_temp_dir, 'png_out')
|
|
||||||
os.mkdir(png_out_dir)
|
|
||||||
|
|
||||||
pngfilename_out_fullpath = os.path.join(png_out_dir, pngfilename)
|
|
||||||
pngfilename_raw_fullpath = os.path.join(self.TEST_DATA_DIR, pngfilename)
|
|
||||||
|
|
||||||
wkhtml2image_args = [self.WKHTML2IMAGE] \
|
|
||||||
+ self.DEFAULT_WKHTML2IMAGE_ARGS \
|
|
||||||
+ list(wkhtml2image_args) + [
|
|
||||||
os.path.join(self.cur_output_dir, htmlfilename),
|
|
||||||
pngfilename_out_fullpath
|
|
||||||
]
|
|
||||||
|
|
||||||
return_code = subprocess.call(list(map(str, wkhtml2image_args)))
|
|
||||||
self.assertEquals(return_code, 0, 'cannot execute ' + self.WKHTML2IMAGE)
|
|
||||||
|
|
||||||
if self.GENERATING_MODE:
|
|
||||||
shutil.copy(pngfilename_out_fullpath, pngfilename_raw_fullpath)
|
|
||||||
else:
|
|
||||||
original_img = Image.open(pngfilename_raw_fullpath)
|
|
||||||
new_img = Image.open(pngfilename_out_fullpath)
|
|
||||||
|
|
||||||
diff_img = ImageChops.difference(original_img, new_img);
|
|
||||||
|
|
||||||
if diff_img.getbbox() is not None:
|
|
||||||
if self.SAVE_TMP:
|
|
||||||
# save the diff image
|
|
||||||
# http://stackoverflow.com/questions/15721484/saving-in-png-using-pil-library-after-taking-imagechops-difference-of-two-png
|
|
||||||
diff_img.convert('RGB').save(os.path.join(png_out_dir, basefilename + '.diff.png'))
|
|
||||||
self.fail('PNG files differ')
|
|
||||||
|
|
||||||
def test_basic_text(self):
|
|
||||||
self.run_test_case('basic_text.pdf',
|
|
||||||
wkhtml2image_args=[
|
|
||||||
'--crop-x', 180,
|
|
||||||
'--crop-y', 150,
|
|
||||||
'--crop-w', 220,
|
|
||||||
'--crop-h', 260
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_geneve_1564(self):
|
|
||||||
self.run_test_case('geneve_1564.pdf', wkhtml2image_args=['--height', 1100])
|
|
||||||
|
|
||||||
def test_text_visibility(self):
|
|
||||||
self.run_test_case('text_visibility.pdf', wkhtml2image_args=['--height', 1200])
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.4 MiB |
Binary file not shown.
Before Width: | Height: | Size: 127 KiB |
29
test/test_local_browser.py
Executable file
29
test/test_local_browser.py
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Run browsers tests with a local Firefox
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from selenium import webdriver
|
||||||
|
from browser_tests import BrowserTests
|
||||||
|
|
||||||
|
class test_local_browser(BrowserTests, unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(test_local_browser, cls).setUpClass()
|
||||||
|
if not cls.GENERATING_MODE:
|
||||||
|
cls.browser = webdriver.Firefox()
|
||||||
|
cls.browser.maximize_window()
|
||||||
|
size = cls.browser.get_window_size()
|
||||||
|
assert ((size['width'] >= cls.BROWSER_WIDTH) and (size['height'] >= cls.BROWSER_HEIGHT)), 'Screen is not large enough'
|
||||||
|
cls.browser.set_window_size(cls.BROWSER_WIDTH, cls.BROWSER_HEIGHT)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
if not cls.GENERATING_MODE:
|
||||||
|
cls.browser.quit()
|
||||||
|
super(test_local_browser, cls).tearDownClass()
|
||||||
|
|
||||||
|
def generate_image(self, html_file, png_file):
|
||||||
|
self.browser.get('file://' + html_file)
|
||||||
|
self.browser.save_screenshot(png_file)
|
@ -1,16 +1,18 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# Test --split-page and --page-filename
|
# Test output files
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from test import Common
|
from test import Common
|
||||||
|
|
||||||
class T(Common, unittest.TestCase):
|
class test_output(Common, unittest.TestCase):
|
||||||
def run_test_case(self, input_file, expected_output_files, args=[]):
|
def run_test_case(self, input_file, expected_output_files, args=[]):
|
||||||
|
if self.GENERATING_MODE:
|
||||||
|
self.skipTest("Skipping test_output test cases in generating mode")
|
||||||
args = list(args)
|
args = list(args)
|
||||||
args.insert(0, os.path.join(self.TEST_DIR, 'test_naming', input_file))
|
args.insert(0, os.path.join(self.TEST_DIR, 'test_output', input_file))
|
||||||
self.assertItemsEqual(self.run_pdf2htmlEX(args)['output_files'], expected_output_files)
|
self.assertItemsEqual(self.run_pdf2htmlEX(args)['output_files'], expected_output_files)
|
||||||
|
|
||||||
def test_generate_single_html_default_name_single_page_pdf(self):
|
def test_generate_single_html_default_name_single_page_pdf(self):
|
131
test/test_remote_browser.py
Executable file
131
test/test_remote_browser.py
Executable file
@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Run browser tests through Sauce Labs
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from selenium import webdriver
|
||||||
|
from sauceclient import SauceClient
|
||||||
|
from browser_tests import BrowserTests
|
||||||
|
|
||||||
|
# Set your own environment variables
|
||||||
|
USERNAME = os.environ.get('SAUCE_USERNAME')
|
||||||
|
ACCESS_KEY = os.environ.get('SAUCE_ACCESS_KEY')
|
||||||
|
|
||||||
|
# The base url that remote browser will access
|
||||||
|
# Usually a HTTP server should be set up in the folder containing the test cases
|
||||||
|
# Also Sauce Connect should be enabled
|
||||||
|
BASEURL='http://localhost:8000/'
|
||||||
|
|
||||||
|
SAUCE_OPTIONS = {
|
||||||
|
'record-video': False,
|
||||||
|
'record-screenshots': False,
|
||||||
|
'record-logs': False,
|
||||||
|
'sauce-advisor': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
# we want to test the latest stable version
|
||||||
|
# and 'beta' is usually the best estimation
|
||||||
|
BROWSER_MATRIX = [
|
||||||
|
('win_ie', {
|
||||||
|
'platform': 'Windows 8.1',
|
||||||
|
'browserName': 'internet explorer',
|
||||||
|
'version': '11',
|
||||||
|
}),
|
||||||
|
('win_firefox', {
|
||||||
|
'platform': 'Windows 8.1',
|
||||||
|
'browserName': 'firefox',
|
||||||
|
'version': 'beta',
|
||||||
|
}),
|
||||||
|
('win_chrome', {
|
||||||
|
'platform': 'Windows 8.1',
|
||||||
|
'browserName': 'chrome',
|
||||||
|
'version': 'beta',
|
||||||
|
}),
|
||||||
|
('mac_firefox', {
|
||||||
|
'platform': 'OS X 10.9',
|
||||||
|
'browserName': 'firefox',
|
||||||
|
'version': 'beta',
|
||||||
|
}),
|
||||||
|
('mac_chrome', {
|
||||||
|
'platform': 'OS X 10.9',
|
||||||
|
'browserName': 'chrome',
|
||||||
|
'version': '38', # beta is not supported
|
||||||
|
}),
|
||||||
|
('linux_firefox', {
|
||||||
|
'platform': 'Linux',
|
||||||
|
'browserName': 'firefox',
|
||||||
|
'version': 'beta',
|
||||||
|
}),
|
||||||
|
('linux_chrome', {
|
||||||
|
'platform': 'Linux',
|
||||||
|
'browserName': 'chrome',
|
||||||
|
'version': 'beta',
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
class test_remote_browser_base(BrowserTests):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(test_remote_browser_base, cls).setUpClass()
|
||||||
|
if not cls.GENERATING_MODE:
|
||||||
|
cls.sauce = SauceClient(USERNAME, ACCESS_KEY)
|
||||||
|
cls.sauce_url = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (USERNAME, ACCESS_KEY)
|
||||||
|
|
||||||
|
cls.browser = webdriver.Remote(
|
||||||
|
desired_capabilities=cls.desired_capabilities,
|
||||||
|
command_executor=cls.sauce_url
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.browser.implicitly_wait(30)
|
||||||
|
# remote screen may not be large enough for the whole page
|
||||||
|
cls.browser.set_window_size(cls.BROWSER_WIDTH, cls.BROWSER_HEIGHT)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
if not cls.GENERATING_MODE:
|
||||||
|
cls.browser.quit()
|
||||||
|
super(test_remote_browser_base, cls).tearDownClass()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(test_remote_browser_base, self).setUp()
|
||||||
|
sys.exc_clear()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
passed = (sys.exc_info() == (None, None, None))
|
||||||
|
branch = os.environ.get('TRAVIS_BRANCH', 'manual')
|
||||||
|
pull_request = os.environ.get('TRAVIS_PULL_REQUEST')
|
||||||
|
self.sauce.jobs.update_job(self.browser.session_id,
|
||||||
|
build_num=os.environ.get('TRAVIS_BUILD_NUMBER', 0),
|
||||||
|
name='pdf2htmlEX',
|
||||||
|
passed=passed,
|
||||||
|
public='public restricted',
|
||||||
|
tags = [pull_request] if pull_request != 'false' else [branch]
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def generate_image(self, html_file, png_file):
|
||||||
|
self.browser.get(BASEURL + html_file)
|
||||||
|
self.browser.save_screenshot(png_file)
|
||||||
|
|
||||||
|
test_classnames = []
|
||||||
|
|
||||||
|
def generate_classes():
|
||||||
|
module = globals()
|
||||||
|
for browser in BROWSER_MATRIX:
|
||||||
|
d = dict(test_remote_browser_base.__dict__)
|
||||||
|
caps = SAUCE_OPTIONS.copy()
|
||||||
|
caps.update(browser[1])
|
||||||
|
tunnel_identifier = os.environ.get('TRAVIS_JOB_NUMBER')
|
||||||
|
if tunnel_identifier:
|
||||||
|
caps['tunnel-identifier'] = tunnel_identifier
|
||||||
|
d['desired_capabilities'] = caps
|
||||||
|
name = "test_remote_%s" % (browser[0], )
|
||||||
|
module[name] = type(name, (test_remote_browser_base, unittest.TestCase), d)
|
||||||
|
test_classnames.append(name)
|
||||||
|
|
||||||
|
generate_classes()
|
Loading…
Reference in New Issue
Block a user