From 1b74e71fdd1c30fa1de45465bacc1cf5dc852881 Mon Sep 17 00:00:00 2001
From: Melek REBAI <melek.rebai89@gmail.com>
Date: Wed, 8 Mar 2023 10:42:02 +0100
Subject: [PATCH] Add waitForSelector()

---
 bin/browser.cjs               |  4 ++++
 docs/usage/creating-images.md | 11 +++++++++
 src/Browsershot.php           | 11 +++++++++
 tests/BrowsershotTest.php     | 43 +++++++++++++++++++++++++++++++++++
 4 files changed, 69 insertions(+)

diff --git a/bin/browser.cjs b/bin/browser.cjs
index 9ce571ff..4d0566cf 100644
--- a/bin/browser.cjs
+++ b/bin/browser.cjs
@@ -369,6 +369,10 @@ const callChrome = async pup => {
             await page.waitForFunction(request.options.function, functionOptions);
         }
 
+        if (request.options.waitForSelector) {
+            await page.waitForSelector(request.options.waitForSelector, request.options.waitForSelectorOptions ?? undefined);
+        }
+
         output = await getOutput(page, request);
 
         if (!request.options.path) {
diff --git a/docs/usage/creating-images.md b/docs/usage/creating-images.md
index f2decce5..475a4735 100644
--- a/docs/usage/creating-images.md
+++ b/docs/usage/creating-images.md
@@ -230,6 +230,17 @@ Browsershot::url('https://example.com')
     ->waitForFunction('window.innerWidth < 100', $pollingInMilliseconds, $timeoutInMilliseconds)
     ->save($pathToImage);
 ```
+
+## Waiting for a selector
+
+You can also wait for a selector by using `waitForSelector()`. This is useful if you need to wait for the selector to appear in page.
+
+```php
+Browsershot::url('https://example.com')
+    ->waitForSelector('#my_selector')
+    ->save($pathToImage);
+```
+
 ## Adding JS
 
 You can add javascript prior to your screenshot or output using the syntax for [Puppeteer's addScriptTag](https://github.com/puppeteer/puppeteer/blob/v1.9.0/docs/api.md#pageaddscripttagoptions).
diff --git a/src/Browsershot.php b/src/Browsershot.php
index 7f303a14..9f6c1cec 100644
--- a/src/Browsershot.php
+++ b/src/Browsershot.php
@@ -231,6 +231,17 @@ public function waitForFunction(string $function, $polling = self::POLLING_REQUE
         return $this->setOption('function', $function);
     }
 
+    public function waitForSelector(string $selector, array $options = [])
+    {
+        $this->setOption('waitForSelector', $selector);
+
+        if (! empty($options)) {
+            $this->setOption('waitForSelectorOptions', $options);
+        }
+
+        return $this;
+    }
+
     public function setUrl(string $url)
     {
         if (Helpers::stringStartsWith(strtolower($url), 'file://')) {
diff --git a/tests/BrowsershotTest.php b/tests/BrowsershotTest.php
index 14c16502..0feec8bd 100644
--- a/tests/BrowsershotTest.php
+++ b/tests/BrowsershotTest.php
@@ -1127,6 +1127,49 @@
     ], $command);
 });
 
+it('can add a wait for selector', function () {
+    $command = Browsershot::url('https://example.com')
+        ->waitForSelector('.wait_for_me')
+        ->createScreenshotCommand('screenshot.png');
+
+    $this->assertEquals([
+        'url' => 'https://example.com',
+        'action' => 'screenshot',
+        'options' => [
+            'waitForSelector' => '.wait_for_me',
+            'path' => 'screenshot.png',
+            'viewport' => [
+                'width' => 800,
+                'height' => 600,
+            ],
+            'args' => [],
+            'type' => 'png',
+        ],
+    ], $command);
+});
+
+it('can add a wait for selector and provide options', function () {
+    $command = Browsershot::url('https://example.com')
+        ->waitForSelector('.wait_for_me', ['visibile' => true])
+        ->createScreenshotCommand('screenshot.png');
+
+    $this->assertEquals([
+        'url' => 'https://example.com',
+        'action' => 'screenshot',
+        'options' => [
+            'waitForSelector' => '.wait_for_me',
+            'waitForSelectorOptions' => ['visibile' => true],
+            'path' => 'screenshot.png',
+            'viewport' => [
+                'width' => 800,
+                'height' => 600,
+            ],
+            'args' => [],
+            'type' => 'png',
+        ],
+    ], $command);
+});
+
 it('can input form fields and post and get the body html', function () {
     $delay = 2000;