Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Api/Concerns/MakesConsoleAssertions.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,29 @@ public function assertNoConsoleLogs(): Webpage
return $this;
}

/**
* Asserts there are no console messages at given levels on the page.
*
* @param array<int, string>|string $levels Console message level(s) to check for (debug, info, error, warning).
*/
public function assertNoConsoleMessages(array|string $levels = ['info', 'error', 'warning']): Webpage
{
if (is_string($levels)) {
$levels = [$levels];
}
$messages = $this->page->consoleMessages($levels);

expect($messages)->toBeEmpty(sprintf(
'Expected no console messages at levels [%s] on the page initially with the url [%s], but found %d: %s',
implode(', ', $levels),
$this->initialUrl,
count($messages),
implode(', ', array_map(fn (array $log): string => "{$log['level']}: {$log['message']}", $messages)),
));

return $this;
}

/**
* Asserts there are no JavaScript errors on the page.
*/
Expand Down
9 changes: 9 additions & 0 deletions src/Exceptions/BrowserExpectationFailedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ public static function from(Page $page, ExpectationFailedException $e): Expectat
));
}

$consoleMessages = $page->consoleMessages();

if (count($consoleMessages) > 0) {
$message .= "\n\nThe following console messages were found:\n".implode("\n", array_map(
fn (array $error): string => $error['level'] . ': ' . $error['message'],
$consoleMessages,
));
}

$javaScriptErrors = $page->javaScriptErrors();

if (count($javaScriptErrors) > 0) {
Expand Down
16 changes: 15 additions & 1 deletion src/Playwright/InitScript.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public static function get(): string

window.__pestBrowser = {
jsErrors: [],
consoleLogs: []
consoleLogs: [],
consoleMessages: []
};

const originalConsoleLog = console.log;
Expand All @@ -35,6 +36,19 @@ public static function get(): string
originalConsoleLog.apply(console, args);
};

['debug', 'error', 'info', 'warning'].forEach(function (level) {
const methodName = level === 'warning' ? 'warn' : level;
const originalConsoleMethod = console[methodName];
console[methodName] = function(...args) {
window.__pestBrowser.consoleMessages.push({
timestamp: new Date().getTime(),
level: level,
message: args.map(arg => String(arg)).join(' ')
});
originalConsoleMethod.apply(console, args);
};
});

window.addEventListener('error', (e) => {
window.__pestBrowser.jsErrors.push({
message: e.message,
Expand Down
26 changes: 26 additions & 0 deletions src/Playwright/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,32 @@ public function consoleLogs(): array
return $consoleLogs;
}

/**
* Get the console messages at given levels from the page, if any.
*
* @param array<int, string>|string $levels Message levels to filter for ('debug', 'info', 'error', 'warning')
* @return array<int, array{level: string, message: string}>
*/
public function consoleMessages(array|string $levels = ['info', 'error', 'warning']): array
{
$consoleMessages = $this->evaluate('window.__pestBrowser.consoleMessages || []');

/** @var array<int, array{level: string, message: string}> $consoleMessages */
if (is_string($levels)) {
$checkLevels = [$levels => true];
} else {
$checkLevels = array_flip($levels);
if (array_key_exists('warn', $checkLevels)) {
$checkLevels['warning'] = true;
}
}

return array_filter(
$consoleMessages,
fn (array $log): bool => array_key_exists($log['level'], $checkLevels)
);
}

/**
* Get the broken images from the page, if any.
*
Expand Down
107 changes: 107 additions & 0 deletions tests/Browser/Webpage/AssertNoConsoleMessagesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare(strict_types=1);

use Illuminate\Support\Facades\Route;
use PHPUnit\Framework\ExpectationFailedException;

it('asserts that there are no console messages', function (): void {
Route::get('/', fn (): string => '
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages();
});

it('ignores debug messages by default', function (): void {
Route::get('/', fn (): string => '
<script>
console.debug("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages();
});

it('asserts that there are console messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.error("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages();
})->throws(ExpectationFailedException::class, 'but found 1: error: Hello, World!');

it('asserts that there are console debug messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.debug("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages('debug');
})->throws(ExpectationFailedException::class, 'but found 1: debug: Hello, World!');

it('asserts that there are console error messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.error("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages('error');
})->throws(ExpectationFailedException::class, 'but found 1: error: Hello, World!');

it('asserts that there are console info messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.info("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages('info');
})->throws(ExpectationFailedException::class, 'but found 1: info: Hello, World!');

it('asserts that there are console warning messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.warn("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages('warning');
})->throws(ExpectationFailedException::class, 'but found 1: warning: Hello, World!');

it('allows alias warn for console warning messages', function (): void {
Route::get('/', fn (): string => '
<script>
console.warn("Hello, World!");
</script>
<div></div>
');

$page = visit('/');

$page->assertNoConsoleMessages('warn');
})->throws(ExpectationFailedException::class, 'but found 1: warning: Hello, World!');
Loading