diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 5f41fb5..842aeda 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,6 +18,9 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Install poppler-utils + run: sudo apt-get install -y poppler-utils + - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 84c683a..29440ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 4.3.0 - 2024-08-22 + +### What's Changed + +* Fix empty PDF issue with Puppeteer ^23.0.0 by @JeppeKnockaert in https://github.com/spatie/browsershot/pull/876 + +**Full Changelog**: https://github.com/spatie/browsershot/compare/4.2.1...4.3.0 + ## 4.2.1 - 2024-08-20 Revert changes of 4.2.1 because PDFs do not render correctly anymore (see https://github.com/spatie/laravel-pdf/issues/175) diff --git a/README.md b/README.md index 24cb1ff..04c048d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,18 @@ We highly appreciate you sending us a postcard from your hometown, mentioning wh All documentation is available [on our documentation site](https://spatie.be/docs/browsershot). +## Testing + +For running the testsuite, you'll need to have Puppeteer installed. Pleaser refer to the Browsershot requirements [here](https://spatie.be/docs/browsershot/v4/requirements). Usually `npm -g i puppeteer` will do the trick. + +Additionally, you'll need the `pdftotext` CLI which is part of the poppler-utils package. More info can be found in in the [spatie/pdf-to-text readme](https://github.com/spatie/pdf-to-text?tab=readme-ov-file#requirements). Usually `brew install poppler-utils` will suffice. + +Finally run the tests with: + +```bash +composer test +``` + ## Contributing Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. diff --git a/bin/browser.cjs b/bin/browser.cjs index a648123..532bb3c 100644 --- a/bin/browser.cjs +++ b/bin/browser.cjs @@ -49,7 +49,9 @@ const getOutput = async (request, page = null) => { const result = await page[request.action](request.options); // Ignore output result when saving to a file - output.result = request.options.path ? '' : result.toString('base64'); + output.result = request.options.path + ? '' + : (result instanceof Uint8Array ? Buffer.from(result) : result).toString('base64'); } } @@ -99,6 +101,7 @@ const callChrome = async pup => { ...(request.options.env || {}), ...process.env }, + protocolTimeout: request.options.protocolTimeout ?? 30000, }); } @@ -158,7 +161,7 @@ const callChrome = async pup => { page.on('request', interceptedRequest => { var headers = interceptedRequest.headers(); - if (request.options && request.options.disableCaptureURLS) { + if (!request.options || !request.options.disableCaptureURLS) { requestsList.push({ url: interceptedRequest.url(), }); @@ -384,7 +387,7 @@ const callChrome = async pup => { if (request.options.waitForSelector) { await page.waitForSelector(request.options.waitForSelector, (request.options.waitForSelectorOptions ? request.options.waitForSelectorOptions : undefined)); } - + console.log(await getOutput(request, page)); if (remoteInstance && page) { diff --git a/composer.json b/composer.json index 735ddb9..56355e9 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ "require-dev": { "pestphp/pest": "^1.20", "spatie/image": "^3.6", + "spatie/pdf-to-text": "^1.52", "spatie/phpunit-snapshot-assertions": "^4.2.3" }, "autoload": { diff --git a/src/Browsershot.php b/src/Browsershot.php index 3838ba7..d50ee04 100644 --- a/src/Browsershot.php +++ b/src/Browsershot.php @@ -504,6 +504,11 @@ public function timeout(int $timeout): static return $this->setOption('timeout', $timeout * 1000); } + public function protocolTimeout(int $protocolTimeout): static + { + return $this->setOption('protocolTimeout', $protocolTimeout * 1000); + } + public function userAgent(string $userAgent): static { return $this->setOption('userAgent', $userAgent); diff --git a/tests/BrowsershotTest.php b/tests/BrowsershotTest.php index cbcae72..baf6df2 100644 --- a/tests/BrowsershotTest.php +++ b/tests/BrowsershotTest.php @@ -1004,7 +1004,9 @@ $this->expectException(ProcessFailedException::class); - $instance = Browsershot::url('https://example.com'); + // Block the favicon request to prevent randomness in the output. + $instance = Browsershot::url('https://example.com') + ->blockUrls(['https://example.com/favicon.ico']); try { $instance->save($targetPath); @@ -1014,7 +1016,14 @@ expect($output)->not()->toBeNull(); expect($output)->toBeInstanceOf(ChromiumResult::class); expect($output->getException())->not()->toBeEmpty(); - expect($output->getConsoleMessages())->toBe([]); + expect($output->getConsoleMessages())->toBe([ + [ + 'type' => 'error', + 'message' => 'Failed to load resource: net::ERR_FAILED', + 'location' => ['url' => 'https://example.com/favicon.ico'], + 'stackTrace' => [['url' => 'https://example.com/favicon.ico']], + ], + ]); expect($output->getRequestsList())->toMatchArray([[ 'url' => 'https://example.com/', ]]); diff --git a/tests/PdfTest.php b/tests/PdfTest.php index 03c06b6..ca6ac3b 100644 --- a/tests/PdfTest.php +++ b/tests/PdfTest.php @@ -1,6 +1,7 @@ toBeTrue(); }); +it('can return a pdf', function () { + $binPath = PHP_OS === 'Linux' ? '/usr/bin/pdftotext' : '/opt/homebrew/bin/pdftotext'; + $targetPath = __DIR__.'/temp/testPdf.pdf'; + + $pdf = Browsershot::url('https://example.com') + ->pdf(); + file_put_contents($targetPath, $pdf); + + expect(Pdf::getText($targetPath, $binPath))->toContain('Example Domain'); +}); + it('can write options to a file and generate a pdf', function () { $targetPath = __DIR__.'/temp/testPdf.pdf';