From ec2bb9c7f8d85bdcb8252d48c3e243b23b29e7a7 Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 13:01:35 +0300 Subject: [PATCH 1/6] images waiting and timeout / ref #5 --- src/hotrush/Webshotter/Webshot.php | 43 ++++++++++++++++++++++++ src/views/webshotter.php | 53 ++++++++++++++++++++++++++---- tests/PropertiesTest.php | 31 +++++++++++++++++ tests/TimeoutTest.php | 14 ++++++++ tests/data/template.php | 14 +++++--- tests/data/template_images.php | 53 ++++++++++++++++++++++++++++++ tests/template/webshotter.php | 8 ++--- 7 files changed, 201 insertions(+), 15 deletions(-) create mode 100644 tests/data/template_images.php diff --git a/src/hotrush/Webshotter/Webshot.php b/src/hotrush/Webshotter/Webshot.php index 2c1072a..af4cd80 100644 --- a/src/hotrush/Webshotter/Webshot.php +++ b/src/hotrush/Webshotter/Webshot.php @@ -56,6 +56,20 @@ class Webshot */ private $timeout; + /** + * Wait while all page images will be loaded + * + * @var bool + */ + private $waitForImages; + + /** + * Images waiting timeout + * + * @var int + */ + private $imagesLoadingTimeout; + /** * Webshot constructor. * @@ -78,6 +92,8 @@ public function __construct($binPath = null, $templatePath = null) } $this->fullPage = false; $this->timeout = 30; + $this->waitForImages = false; + $this->imagesLoadingTimeout = 30; return $this; } @@ -166,6 +182,31 @@ public function setTimeout($timeout) return $this; } + /** + * Let webshotter wait while images will load + * + * @return $this + */ + public function waitForImages() + { + $this->waitForImages = true; + + return $this; + } + + /** + * Set images loading timeout + * + * @param $timeout + * @return $this + */ + public function setImagesLoadingTimeout($timeout) + { + $this->imagesLoadingTimeout = (int) $timeout; + + return $this; + } + /** * Render PhantomJS script template * @@ -180,6 +221,8 @@ private function renderTemplate($filePath) 'height' => $this->height, 'fullPage' => $this->fullPage, 'timeout' => $this->timeout * 1000, // convert into milliseconds + 'waitForImages' => $this->waitForImages, + 'imagesLoadingTimeout' => $this->imagesLoadingTimeout * 1000, // convert into milliseconds ), $filePath); } diff --git a/src/views/webshotter.php b/src/views/webshotter.php index 0c4f96d..d923b67 100644 --- a/src/views/webshotter.php +++ b/src/views/webshotter.php @@ -6,17 +6,58 @@ page.settings.resourceTimeout = ; page.open('', function () { + + waitFor(function() { + return page.evaluate(function() { + for(var i = 0; i < document.images.length; i++) { + if (!document.images[i].complete) { + return false; + } + } + return true; + }); + }, function() { + savePage(); + phantom.exit(); + }, ); + + savePage(); + phantom.exit(); + +}); + +function savePage() { page.viewportSize = { width: , height: }; - page.clipRect = { - width: , - height: - } + page.clipRect = { + width: , + height: + } page.render(''); - phantom.exit(); -}); +} + +function waitFor(testFx, onReady, timeOutMillis) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, + start = new Date().getTime(), + condition = false, + interval = setInterval(function() { + if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code + } else { + if (!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + phantom.exit(1); + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval); //< Stop this interval + } + } + }, 250); +}; diff --git a/tests/PropertiesTest.php b/tests/PropertiesTest.php index f6b0ae1..70fd10f 100644 --- a/tests/PropertiesTest.php +++ b/tests/PropertiesTest.php @@ -63,6 +63,22 @@ public function testTimeoutProperty() $this->assertEquals(10, PHPUnit_Framework_Assert::readAttribute($webshot, 'timeout')); } + public function testImagesWaitProperty() + { + $webshot = new Webshot(); + $this->assertEquals(false, PHPUnit_Framework_Assert::readAttribute($webshot, 'waitForImages')); + $webshot->waitForImages(); + $this->assertEquals(true, PHPUnit_Framework_Assert::readAttribute($webshot, 'waitForImages')); + } + + public function testImagesTimeoutProperty() + { + $webshot = new Webshot(); + $this->assertEquals(30, PHPUnit_Framework_Assert::readAttribute($webshot, 'imagesLoadingTimeout')); + $webshot->setImagesLoadingTimeout(10); + $this->assertEquals(10, PHPUnit_Framework_Assert::readAttribute($webshot, 'imagesLoadingTimeout')); + } + public function testTemplateRendering() { $webshot = new Webshot(); @@ -77,6 +93,21 @@ public function testTemplateRendering() $this->assertEquals($mock, $method->invokeArgs($webshot, array('tests/tmp/github.png'))); } + public function testTemplateRenderingWithImagesWait() + { + $webshot = new Webshot(); + $webshot + ->setUrl('https://github.com') + ->setWidth(1200) + ->setHeight(800) + ->waitForImages(); + $mock = file_get_contents(realpath(dirname(__FILE__).'/../tests/data/template_images.php')); + $reflection = new ReflectionClass('hotrush\Webshotter\Webshot'); + $method = $reflection->getMethod('renderTemplate'); + $method->setAccessible(true); + $this->assertEquals($mock, $method->invokeArgs($webshot, array('tests/tmp/github.png'))); + } + public function testTemplateProperty() { $path = realpath(dirname(__FILE__)); diff --git a/tests/TimeoutTest.php b/tests/TimeoutTest.php index de0a36d..edb4785 100644 --- a/tests/TimeoutTest.php +++ b/tests/TimeoutTest.php @@ -18,4 +18,18 @@ public function testTimeout() ->setTimeout(5) ->saveToPng('delay', $path); } + + public function testImagesTimeout() + { + $path = realpath(dirname(__FILE__).'/../tests/tmp/'); + $webshot = new Webshot(); + $webshot + ->setUrl('https://github.com') + ->setWidth(1200) + ->setHeight(800) + ->setTimeout(5) + ->waitForImages() + ->setImagesLoadingTimeout(10) + ->saveToPng('imagestimeout', $path); + } } diff --git a/tests/data/template.php b/tests/data/template.php index 0d9a7df..495e496 100644 --- a/tests/data/template.php +++ b/tests/data/template.php @@ -6,13 +6,17 @@ page.settings.resourceTimeout = 30000; page.open('https://github.com', function () { + savePage(); + phantom.exit(); + }); + +function savePage() { page.viewportSize = { width: 1200, height: 800 }; - page.clipRect = { - width: 1200, - height: 800 } + page.clipRect = { + width: 1200, + height: 800 } page.render('tests/tmp/github.png'); - phantom.exit(); -}); +} diff --git a/tests/data/template_images.php b/tests/data/template_images.php new file mode 100644 index 0000000..31b9dc9 --- /dev/null +++ b/tests/data/template_images.php @@ -0,0 +1,53 @@ +var page = new WebPage(); +page.settings.javascriptEnabled = true; +page.onResourceTimeout = function(request) { + phantom.exit(); +}; +page.settings.resourceTimeout = 30000; + +page.open('https://github.com', function () { + waitFor(function() { + return page.evaluate(function() { + for(var i = 0; i < document.images.length; i++) { + if (!document.images[i].complete) { + return false; + } + } + return true; + }); + }, function() { + savePage(); + phantom.exit(); + }, 30000); + }); + +function savePage() { + page.viewportSize = { + width: 1200, + height: 800 }; + page.clipRect = { + width: 1200, + height: 800 } + page.render('tests/tmp/github.png'); +} + +function waitFor(testFx, onReady, timeOutMillis) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, + start = new Date().getTime(), + condition = false, + interval = setInterval(function() { + if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code + } else { + if (!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + phantom.exit(1); + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval); //< Stop this interval + } + } + }, 250); +}; \ No newline at end of file diff --git a/tests/template/webshotter.php b/tests/template/webshotter.php index 0c4f96d..4abbf8b 100644 --- a/tests/template/webshotter.php +++ b/tests/template/webshotter.php @@ -11,10 +11,10 @@ height: }; - page.clipRect = { - width: , - height: - } + page.clipRect = { + width: , + height: + } page.render(''); phantom.exit(); From b38e1758b190ad4ac9bdd0f12ac8c6ff150cbc7d Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 13:18:11 +0300 Subject: [PATCH 2/6] update readme / ci fixes --- .travis.yml | 3 +-- README.md | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7561d7..61a80ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,12 +10,11 @@ php: matrix: allow_failures: - - php: 7.0 - php: nightly - php: hhvm before_install: - - wget http://security.ubuntu.com/ubuntu/pool/main/i/icu/libicu52_52.1-3ubuntu0.4_amd64.deb + - wget http://security.ubuntu.com/ubuntu/pool/main/i/icu/libicu52_52.1-3ubuntu0.7_amd64.deb - sudo dpkg -i libicu52_52.1-3ubuntu0.4_amd64.deb before_script: diff --git a/README.md b/README.md index 88846a4..556183a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Take website's screenshots with PHP/PhantomJS and save them to PNG, JPG or PDF. Also you can take a look at simple microservice with lumen and this package - [hotrush/Webshotter-microservice](https://github.com/hotrush/Webshotter-microservice). ## Changelog +***0.1.6*** - added ```waitForImages()``` and ```imagesLoadingTimeout``` + ***0.1.5*** - custom ```$templatePath``` fixed, thanks to [mizansyed](https://github.com/mizansyed) ***0.1.3*** - added ```timeout``` property that allow to limit page load timeout (using [onResourceTimeout](http://phantomjs.org/api/webpage/handler/on-resource-timeout.html) phantomjs feature). If timeout reached ```TimeoutException``` will be thrown. @@ -42,6 +44,8 @@ $jpg = $webshot ->setHeight(800) ->setTimeout(5) // set timeout in seconds, 30 seconds default ->setFullPage(true) // set to true to get full page screenshot (width/height will be used for viewport only) + ->waitForImages() // wait when all images will load + ->setImagesLoadingTimeout() // images loading timeout, will failt if not loaded ->saveToPng('github', $path); ``` From 5f760c144e8565712df3889ad538a4fefb81e4fb Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 13:31:17 +0300 Subject: [PATCH 3/6] update readme / ci fixes --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 61a80ba..50322fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: before_install: - wget http://security.ubuntu.com/ubuntu/pool/main/i/icu/libicu52_52.1-3ubuntu0.7_amd64.deb - - sudo dpkg -i libicu52_52.1-3ubuntu0.4_amd64.deb + - sudo dpkg -i libicu52_52.1-3ubuntu0.7_amd64.deb before_script: - composer self-update From 4f6807c30c983e64b70c9bef18d0e4d2253a5fba Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 13:51:13 +0300 Subject: [PATCH 4/6] ci for php 7.1/7.1 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 50322fc..bb38772 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ php: - 5.5 - 5.6 - 7.0 + - 7.1 + - 7.2 - nightly - hhvm From 376f622a1b457ab9039786985f5e8a91c85e5e4a Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 13:53:35 +0300 Subject: [PATCH 5/6] remove hhvm --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb38772..f68cc3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,12 +8,10 @@ php: - 7.1 - 7.2 - nightly - - hhvm matrix: allow_failures: - php: nightly - - php: hhvm before_install: - wget http://security.ubuntu.com/ubuntu/pool/main/i/icu/libicu52_52.1-3ubuntu0.7_amd64.deb From 05c7d206841f47d48257bd56dc5b3c7439eabea5 Mon Sep 17 00:00:00 2001 From: rush Date: Wed, 27 Dec 2017 14:25:14 +0300 Subject: [PATCH 6/6] ci fixes --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f68cc3f..016b505 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,4 +21,4 @@ before_script: - composer self-update - composer install --prefer-source --no-interaction --dev -script: phpunit +script: vendor/bin/phpunit