From 7de82ef80e9843a988d3d537b27d8d3d45212d00 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Thu, 11 Sep 2025 23:31:06 +0530 Subject: [PATCH 1/9] document details add --- browser-testing.md | 347 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 312 insertions(+), 35 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 7a72a47..4a75859 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -1,17 +1,50 @@ --- title: Browser Testing -description: +description: Browser testing capabilities in Pest PHP --- # Browser Testing -Browser testing is an essential part of modern web development, allowing you to ensure that your application works correctly across different browsers and devices. Pest provides a simple and elegant way to write browser tests. Here is an example of how to write a browser test using Pest: +Browser testing is an essential part of modern web development, allowing you to ensure that your application works correctly across different browsers and devices. Pest provides a comprehensive browser testing API through its browser plugin. This documentation covers all available features based on the official API implementation. + +## Table of Contents + +- [Getting Started](#getting-started) + + - [Installation](#getting-started) + - [Running Tests and Configuration](#running-tests-and-configuration) + - [Multiple Page Testing](#multiple-page-testing) + - [Configuration Options](#configuration-options) + +- [Core Features](#core-features) + + - [Navigation and Page Interaction](#navigation-and-page-interaction) + - [Screen Interactions](#screen-interactions) + - [Frame Handling](#frame-handling) + - [Tab Management](#tab-management) + - [Viewport Control](#viewport-control) + +- [Assertions and Testing](#assertions-and-testing) + + - [Console and Error Handling](#console-and-error-handling) + - [Element Assertions](#element-assertions) + - [URL Assertions](#url-assertions) + +- [Advanced Features](#advanced-features) + - [Location Simulation](#location-simulation) + - [Livewire Support](#livewire-support) + +## Basic Example + +Here's a simple example of a browser test using Pest: ```php -it('may welcome the user', function () { +test('homepage shows welcome message', function () { $page = visit('/'); - $page->assertSee('Welcome'); + $page->assertSee('Welcome') + ->assertTitle('Home') + ->assertNoConsoleErrors(); }); ``` @@ -59,38 +92,102 @@ npx playwright install Finally, add `tests/Browser/Screenshots` to your `.gitignore` file to avoid committing screenshots taken during browser tests. -### Running Browser Tests - -Running browser tests is similar to running regular Pest tests: +### Running Tests and Configuration ```bash +# Run all tests ./vendor/bin/pest -``` - -We recommend running tests in parallel using the `--parallel` option to speed up the execution: -```bash +# Run tests in parallel ./vendor/bin/pest --parallel -``` -For debugging purposes, you can run the tests in a headed mode and pause the execution at the end of the failed test run: - -```bash +# Run in debug mode (headed browser) ./vendor/bin/pest --debug + +# Run with specific browser +./vendor/bin/pest --browser firefox +./vendor/bin/pest --browser safari ``` -### Navigation +### Multiple Page Testing -The `visit()` method is used to navigate to a specific URL in your browser test. It provides various methods to interact with the page: +You can test multiple pages simultaneously using array capabilities: ```php -test('example', function () { - $page = visit('/'); +test('multiple pages', function () { + // Visit multiple pages at once + $pages = visit(['/', '/about', '/contact']); + + // Run assertions on all pages + $pages->assertNoConsoleErrors() + ->assertNoJavaScriptErrors(); - $page->assertSee('Welcome'); + // Access individual pages + [$home, $about, $contact] = $pages; + + $home->assertSee('Welcome'); + $about->assertPathIs('/about'); + $contact->assertTitle('Contact Us'); }); ``` +### Configuration Options + +You can configure the browser behavior in your `Pest.php` file: + +```php +use Pest\Plugin\Browser\Configuration; + +pest()->browser() + // Browser selection + ->inChrome() + ->inFirefox() + ->inSafari() + + // Display modes + ->headed() // Show browser window + ->headless() // Hide browser window + ->inDarkMode() // Enable dark mode + + // Timing and behavior + ->timeout(10000) // Set timeout in milliseconds + ->userAgent('Custom/1.0') // Set custom user agent + + // Screenshot configuration + ->screenshotsPath('tests/Browser/screenshots') + ->failedScreenshotsPath('tests/Browser/screenshots/failures'); +``` + +## Core Features + +### Navigation and Page Interaction + +The browser plugin provides various methods to interact with web pages: + +````php +test('page navigation and interaction', function () { + $page = visit('/') + // Basic navigation + ->navigate('/about') + ->back() + ->forward() + ->refresh() + + // Waiting capabilities (HasWaitCapabilities) + ->waitForNavigation() + ->waitFor('.element') + ->waitForText('Loading completed') + + // Element interaction (InteractsWithElements) + ->click('.button') + ->type('email', 'test@example.com') + ->fill('message', 'Hello') + ->select('country', 'USA') + ->check('terms') + ->uncheck('newsletter') + ->press('Submit'); +}); + ### Using Other Browsers By default, the `visit()` method uses Chrome as the browser. However, if you want to use a different browser, you can specify it using the `--browser` option when running the tests: @@ -98,7 +195,7 @@ By default, the `visit()` method uses Chrome as the browser. However, if you wan ```bash ./vendor/bin/pest --browser firefox ./vendor/bin/pest --browser safari -``` +```` If you wish to use a different browser by default without specifying it in the command line, you can set it in your `Pest.php` configuration file: @@ -121,15 +218,112 @@ If you wish to use a specific device, you can use the `on()` method and chain it $page = visit('/')->on()->iPhone14Pro(); ``` -### Using Dark Mode +### Screen Interactions (InteractsWithScreen) -Pest enforces a light color scheme by default. However, you can specify a dark color scheme using the `inDarkMode()` method: +```php +$page = visit('/') + // Taking screenshots + ->screenshot('homepage.png') + ->screenshotElement('#header', 'header.png') + + // Assertions + ->assertScreenshotMatches('expected.png') + ->assertElementScreenshotMatches('#element', 'element.png'); +``` + +### Frame Handling (InteractsWithFrames) + +```php +$page = visit('/') + ->withinFrame('#iframe', function ($frame) { + $frame->click('.button') + ->assertSee('Frame Content') + ->type('email', 'test@example.com'); + }); +``` + +### Tab Management (InteractsWithTab) + +```php +$page = visit('/') + ->openNewTab() + ->switchToTab(1) + ->assertUrlIs('/new-page') + ->closeTab() + ->switchToTab(0); +``` + +### Viewport Control (InteractsWithViewPort) + +```php +$page = visit('/') + // Set specific dimensions + ->resize(1920, 1080) + + // Use predefined device settings + ->on()->iPhone14() + ->on()->macbook16() + ->on()->mobile() + ->on()->desktop(); +``` + +### Console and Error Handling (MakesConsoleAssertions) ```php -$page = visit('/')->inDarkMode(); +$page = visit('/') + ->assertNoConsoleErrors() + ->assertNoJavaScriptErrors() + ->assertConsoleLogContains('Debug message') + ->assertConsoleWarningContains('Warning'); +``` + +### Element Assertions (MakesElementAssertions) + +```php +$page = visit('/') + ->assertVisible('.element') + ->assertHidden('.hidden-element') + ->assertExists('#id') + ->assertMissing('.not-found') + ->assertValue('input[name="email"]', 'test@example.com') + ->assertSelected('select[name="country"]', 'USA') + ->assertChecked('#terms') + ->assertNotChecked('#newsletter'); +``` + +### URL Assertions (MakesUrlAssertions) + +```php +$page = visit('/') + ->assertUrlIs('https://example.com') + ->assertPathIs('/home') + ->assertSchemeIs('https') + ->assertHostIs('example.com') + ->assertQueryStringHas('page', '1') + ->assertQueryStringMissing('debug') + ->assertFragmentIs('section-1'); ``` -### Visiting Multiple Pages +### Location Simulation (From) + +```php +$page = visit('/')->from() + ->amsterdam() // Simulate being in Amsterdam + ->london() // Simulate being in London + ->withLocale('nl-NL') + ->withTimezone('Europe/Amsterdam'); +``` + +### Livewire Support + +```php +$page = visit('/') + ->livewire() + ->assertSeeText('Component content') + ->assertSet('property', 'value') + ->call('method') + ->assertEmitted('event'); +``` You can visit multiple pages simultaneously by passing an array of URLs to the `visit()` method. This is useful for testing scenarios where you need to interact with multiple pages at once: @@ -188,7 +382,7 @@ pest()->browser()->timeout(10000); ### Configuring User Agent -By default, the User Agent will default to the Browser you're running for tests such as: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/133.0.6943.16 Safari/537.36` +By default, the User Agent will default to the Browser you're running for tests such as: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/133.0.6943.16 Safari/537.36` You may wish to override the User Agent of the browser for all of your tests, you can configure this in the `Pest.php` configuration file: @@ -198,7 +392,7 @@ pest()->browser()->userAgent('CustomUserAgent'); ### Geolocation -Sometimes, you need to define where the browser believes it is physically on the earth. This method takes a latitude and longitude and will set the `geolocation` permission in the browser and then make the coordinates available via Javascript's getCurrentPosition API: +Sometimes, you need to define where the browser believes it is physically on the earth. This method takes a latitude and longitude and will set the `geolocation` permission in the browser and then make the coordinates available via Javascript's getCurrentPosition API: ```php $page = visit('/') @@ -214,6 +408,7 @@ $page = visit('/')->withLocale('fr-FR'); $page->assertSee('Bienvenue'); ``` + ### Configuring Timezone You can set the timezone for your test requests using the `withTimezone` method. This is useful for testing date and time displays in different time zones. @@ -351,6 +546,7 @@ $page->assertSee('Welcome, bot!'); ## Element Assertions + ### assertTitle The `assertTitle` method asserts that the page title matches the given text: @@ -360,6 +556,7 @@ $page->assertTitle('Home Page'); ``` + ### assertTitleContains The `assertTitleContains` method asserts that the page title contains the given text: @@ -369,6 +566,7 @@ $page->assertTitleContains('Home'); ``` + ### assertSee The `assertSee` method asserts that the given text is present on the page: @@ -378,6 +576,7 @@ $page->assertSee('Welcome to our website'); ``` + ### assertDontSee The `assertDontSee` method asserts that the given text is not present on the page: @@ -387,6 +586,7 @@ $page->assertDontSee('Error occurred'); ``` + ### assertSeeIn The `assertSeeIn` method asserts that the given text is present within the selector: @@ -396,6 +596,7 @@ $page->assertSeeIn('.header', 'Welcome'); ``` + ### assertDontSeeIn The `assertDontSeeIn` method asserts that the given text is not present within the selector: @@ -405,6 +606,7 @@ $page->assertDontSeeIn('.error-container', 'Error occurred'); ``` + ### assertSeeAnythingIn The `assertSeeAnythingIn` method asserts that any text is present within the selector: @@ -414,6 +616,7 @@ $page->assertSeeAnythingIn('.content'); ``` + ### assertSeeNothingIn The `assertSeeNothingIn` method asserts that no text is present within the selector: @@ -423,6 +626,7 @@ $page->assertSeeNothingIn('.empty-container'); ``` + ### assertCount The `assertCount` method asserts that a given element is present a given amount of times: @@ -432,6 +636,7 @@ $page->assertCount('.item', 5); ``` + ### assertScript The `assertScript` method asserts that the given JavaScript expression evaluates to the given value: @@ -442,6 +647,7 @@ $page->assertScript('document.querySelector(".btn").disabled', true); ``` + ### assertSourceHas The `assertSourceHas` method asserts that the given source code is present on the page: @@ -451,6 +657,7 @@ $page->assertSourceHas('

Welcome

'); ``` + ### assertSourceMissing The `assertSourceMissing` method asserts that the given source code is not present on the page: @@ -460,6 +667,7 @@ $page->assertSourceMissing('
'); ``` + ### assertSeeLink The `assertSeeLink` method asserts that the given link is present on the page: @@ -469,6 +677,7 @@ $page->assertSeeLink('About Us'); ``` + ### assertDontSeeLink The `assertDontSeeLink` method asserts that the given link is not present on the page: @@ -478,6 +687,7 @@ $page->assertDontSeeLink('Admin Panel'); ``` + ### assertChecked The `assertChecked` method asserts that the given checkbox is checked: @@ -488,6 +698,7 @@ $page->assertChecked('color', 'blue'); // For checkbox with specific value ``` + ### assertNotChecked The `assertNotChecked` method asserts that the given checkbox is not checked: @@ -498,6 +709,7 @@ $page->assertNotChecked('color', 'red'); // For checkbox with specific value ``` + ### assertIndeterminate The `assertIndeterminate` method asserts that the given checkbox is in an indeterminate state: @@ -507,6 +719,7 @@ $page->assertIndeterminate('partial-selection'); ``` + ### assertRadioSelected The `assertRadioSelected` method asserts that the given radio field is selected: @@ -516,6 +729,7 @@ $page->assertRadioSelected('size', 'large'); ``` + ### assertRadioNotSelected The `assertRadioNotSelected` method asserts that the given radio field is not selected: @@ -525,6 +739,7 @@ $page->assertRadioNotSelected('size', 'small'); ``` + ### assertSelected The `assertSelected` method asserts that the given dropdown has the given value selected: @@ -534,6 +749,7 @@ $page->assertSelected('country', 'US'); ``` + ### assertNotSelected The `assertNotSelected` method asserts that the given dropdown does not have the given value selected: @@ -543,6 +759,7 @@ $page->assertNotSelected('country', 'UK'); ``` + ### assertValue The `assertValue` method asserts that the element matching the given selector has the given value: @@ -552,6 +769,7 @@ $page->assertValue('input[name=email]', 'test@example.com'); ``` + ### assertValueIsNot The `assertValueIsNot` method asserts that the element matching the given selector does not have the given value: @@ -561,6 +779,7 @@ $page->assertValueIsNot('input[name=email]', 'invalid@example.com'); ``` + ### assertAttribute The `assertAttribute` method asserts that the element matching the given selector has the given value in the provided attribute: @@ -570,6 +789,7 @@ $page->assertAttribute('img', 'alt', 'Profile Picture'); ``` + ### assertAttributeMissing The `assertAttributeMissing` method asserts that the element matching the given selector is missing the provided attribute: @@ -579,6 +799,7 @@ $page->assertAttributeMissing('button', 'disabled'); ``` + ### assertAttributeContains The `assertAttributeContains` method asserts that the element matching the given selector contains the given value in the provided attribute: @@ -588,6 +809,7 @@ $page->assertAttributeContains('div', 'class', 'container'); ``` + ### assertAttributeDoesntContain The `assertAttributeDoesntContain` method asserts that the element matching the given selector does not contain the given value in the provided attribute: @@ -597,6 +819,7 @@ $page->assertAttributeDoesntContain('div', 'class', 'hidden'); ``` + ### assertAriaAttribute The `assertAriaAttribute` method asserts that the element matching the given selector has the given value in the provided aria attribute: @@ -606,6 +829,7 @@ $page->assertAriaAttribute('button', 'label', 'Close'); ``` + ### assertDataAttribute The `assertDataAttribute` method asserts that the element matching the given selector has the given value in the provided data attribute: @@ -615,6 +839,7 @@ $page->assertDataAttribute('div', 'id', '123'); ``` + ### assertVisible The `assertVisible` method asserts that the element matching the given selector is visible: @@ -624,6 +849,7 @@ $page->assertVisible('.alert'); ``` + ### assertPresent The `assertPresent` method asserts that the element matching the given selector is present in the DOM: @@ -633,6 +859,7 @@ $page->assertPresent('form'); ``` + ### assertNotPresent The `assertNotPresent` method asserts that the element matching the given selector is not present in the DOM: @@ -642,6 +869,7 @@ $page->assertNotPresent('.error-message'); ``` + ### assertMissing The `assertMissing` method asserts that the element matching the given selector is not visible: @@ -651,6 +879,7 @@ $page->assertMissing('.hidden-element'); ``` + ### assertEnabled The `assertEnabled` method asserts that the given field is enabled: @@ -660,6 +889,7 @@ $page->assertEnabled('email'); ``` + ### assertDisabled The `assertDisabled` method asserts that the given field is disabled: @@ -669,6 +899,7 @@ $page->assertDisabled('submit'); ``` + ### assertButtonEnabled The `assertButtonEnabled` method asserts that the given button is enabled: @@ -678,6 +909,7 @@ $page->assertButtonEnabled('Save'); ``` + ### assertButtonDisabled The `assertButtonDisabled` method asserts that the given button is disabled: @@ -689,6 +921,7 @@ $page->assertButtonDisabled('Submit'); ## URL Assertions + ### assertUrlIs The `assertUrlIs` method asserts that the current URL matches the given string: @@ -698,6 +931,7 @@ $page->assertUrlIs('https://example.com/home'); ``` + ### assertSchemeIs The `assertSchemeIs` method asserts that the current URL scheme matches the given scheme: @@ -707,6 +941,7 @@ $page->assertSchemeIs('https'); ``` + ### assertSchemeIsNot The `assertSchemeIsNot` method asserts that the current URL scheme does not match the given scheme: @@ -716,6 +951,7 @@ $page->assertSchemeIsNot('http'); ``` + ### assertHostIs The `assertHostIs` method asserts that the current URL host matches the given host: @@ -725,6 +961,7 @@ $page->assertHostIs('example.com'); ``` + ### assertHostIsNot The `assertHostIsNot` method asserts that the current URL host does not match the given host: @@ -734,6 +971,7 @@ $page->assertHostIsNot('wrong-domain.com'); ``` + ### assertPortIs The `assertPortIs` method asserts that the current URL port matches the given port: @@ -743,6 +981,7 @@ $page->assertPortIs('443'); ``` + ### assertPortIsNot The `assertPortIsNot` method asserts that the current URL port does not match the given port: @@ -752,6 +991,7 @@ $page->assertPortIsNot('8080'); ``` + ### assertPathBeginsWith The `assertPathBeginsWith` method asserts that the current URL path begins with the given path: @@ -761,6 +1001,7 @@ $page->assertPathBeginsWith('/users'); ``` + ### assertPathEndsWith The `assertPathEndsWith` method asserts that the current URL path ends with the given path: @@ -770,6 +1011,7 @@ $page->assertPathEndsWith('/profile'); ``` + ### assertPathContains The `assertPathContains` method asserts that the current URL path contains the given path: @@ -779,6 +1021,7 @@ $page->assertPathContains('settings'); ``` + ### assertPathIs The `assertPathIs` method asserts that the current path matches the given path: @@ -788,6 +1031,7 @@ $page->assertPathIs('/dashboard'); ``` + ### assertPathIsNot The `assertPathIsNot` method asserts that the current path does not match the given path: @@ -797,6 +1041,7 @@ $page->assertPathIsNot('/login'); ``` + ### assertQueryStringHas The `assertQueryStringHas` method asserts that the given query string parameter is present and has a given value: @@ -807,6 +1052,7 @@ $page->assertQueryStringHas('page', '2'); ``` + ### assertQueryStringMissing The `assertQueryStringMissing` method asserts that the given query string parameter is missing: @@ -816,6 +1062,7 @@ $page->assertQueryStringMissing('page'); ``` + ### assertFragmentIs The `assertFragmentIs` method asserts that the URL's current hash fragment matches the given fragment: @@ -825,6 +1072,7 @@ $page->assertFragmentIs('section-2'); ``` + ### assertFragmentBeginsWith The `assertFragmentBeginsWith` method asserts that the URL's current hash fragment begins with the given fragment: @@ -834,6 +1082,7 @@ $page->assertFragmentBeginsWith('section'); ``` + ### assertFragmentIsNot The `assertFragmentIsNot` method asserts that the URL's current hash fragment does not match the given fragment: @@ -845,6 +1094,7 @@ $page->assertFragmentIsNot('wrong-section'); ## Console Assertions + ### assertNoSmoke The `assertNoSmoke` method asserts there are no console logs or JavaScript errors on the page: @@ -854,6 +1104,7 @@ $page->assertNoSmoke(); ``` + ### assertNoConsoleLogs The `assertNoConsoleLogs` method asserts there are no console logs on the page: @@ -863,6 +1114,7 @@ $page->assertNoConsoleLogs(); ``` + ### assertNoJavaScriptErrors The `assertNoJavaScriptErrors` method asserts there are no JavaScript errors on the page: @@ -872,6 +1124,7 @@ $page->assertNoJavaScriptErrors(); ``` + ### assertNoAccessibilityIssues The `assertNoAccessibilityIssues` method asserts there are no "serious" accessibility issues on the page: @@ -897,6 +1150,7 @@ By default, the level is 1 (serious). You can change to one of the following lev ## Screenshot Assertions + ### assertScreenshotMatches The `assertScreenshotMatches` method asserts that the screenshot matches the expected image: @@ -909,6 +1163,7 @@ $page->assertScreenshotMatches(true, true); // Full page, show diff ## Element Interactions + ### click The `click` method clicks the link with the given text: @@ -924,6 +1179,7 @@ $page->click('#button', options: ['clickCount' => 2]); ``` + ### text The `text` method gets the text of the element matching the given selector: @@ -933,6 +1189,7 @@ $text = $page->text('.header'); ``` + ### attribute The `attribute` method gets the given attribute from the element matching the given selector: @@ -942,6 +1199,7 @@ $alt = $page->attribute('img', 'alt'); ``` + ### keys The `keys` method sends the given keys to the element matching the given selector: @@ -952,6 +1210,7 @@ $page->keys('input[name=password]', ['{Control}', 'a']); // Keyboard shortcuts ``` + ### withKeyDown The `withKeyDown` method executes the given callback while a key is held down: @@ -966,6 +1225,7 @@ $page->withKeyDown('Shift', function () use ($page): void { > 'a' always types a lowercase “a” and 'A' always types an uppercase “A”, regardless of modifiers. + ### type The `type` method types the given value in the given field: @@ -985,6 +1245,7 @@ $page->typeSlowly('email', 'test@example.com'); ``` + ### select The `select` method selects the given value in the given field: @@ -995,6 +1256,7 @@ $page->select('interests', ['music', 'sports']); // Multiple select ``` + ### append The `append` method types the given value in the given field without clearing it: @@ -1004,6 +1266,7 @@ $page->append('description', ' Additional information.'); ``` + ### clear The `clear` method clears the given field: @@ -1013,6 +1276,7 @@ $page->clear('search'); ``` + ### radio The `radio` method selects the given value of a radio button field: @@ -1022,6 +1286,7 @@ $page->radio('size', 'large'); ``` + ### check The `check` method checks the given checkbox: @@ -1032,6 +1297,7 @@ $page->check('color', 'blue'); // For checkbox with specific value ``` + ### uncheck The `uncheck` method unchecks the given checkbox: @@ -1042,6 +1308,7 @@ $page->uncheck('color', 'red'); // For checkbox with specific value ``` + ### attach The `attach` method attaches the given file to the field: @@ -1051,6 +1318,7 @@ $page->attach('avatar', '/path/to/image.jpg'); ``` + ### press The `press` method presses the button with the given text or name: @@ -1060,6 +1328,7 @@ $page->press('Submit'); ``` + ### pressAndWaitFor The `pressAndWaitFor` method presses the button with the given text or name and waits for a specified amount of time: @@ -1069,6 +1338,7 @@ $page->pressAndWaitFor('Submit', 2); // Wait for 2 seconds ``` + ### drag The `drag` method drags an element to another element using selectors: @@ -1078,6 +1348,7 @@ $page->drag('#item', '#target'); ``` + ### hover The `hover` method hovers over the given element: @@ -1087,6 +1358,7 @@ $page->hover('#item'); ``` + ### submit The `submit` method submits the first form found on the page: @@ -1096,6 +1368,7 @@ $page->submit(); ``` + ### value The `value` method gets the value of the element matching the given selector: @@ -1130,6 +1403,7 @@ $page->resize(1280, 720); ``` + ### script The `script` method executes a script in the context of the page: @@ -1139,6 +1413,7 @@ $result = $page->script('document.title'); ``` + ### content The `content` method gets the page's content: @@ -1148,6 +1423,7 @@ $html = $page->content(); ``` + ### url The `url` method gets the page's URL: @@ -1157,6 +1433,7 @@ $currentUrl = $page->url(); ``` + ### wait The `wait` method pauses for the given number of seconds: @@ -1166,6 +1443,7 @@ $page->wait(2); // Wait for 2 seconds ``` + ### waitForKey The `waitForKey` method opens the current page URL in the default web browser and waits for a key press: @@ -1189,7 +1467,6 @@ Optionally, you can also use the `debug()` method in your test. It will limit ex $page->debug(); ``` - You can also take a screenshot of the current page using the `screenshot()` method. This is useful for visual debugging: @@ -1235,15 +1512,15 @@ You may refer to Pest's [Continuous Integration](https://pestphp.com/docs/contin However, if you are using GitHub Actions, you need to add the following steps to your workflow file: ```yaml - - uses: actions/setup-node@v4 - with: - node-version: lts/* +- uses: actions/setup-node@v4 + with: + node-version: lts/* - - name: Install dependencies - run: npm ci +- name: Install dependencies + run: npm ci - - name: Install Playwright Browsers - run: npx playwright install --with-deps +- name: Install Playwright Browsers + run: npx playwright install --with-deps ``` --- From a8890bd8a6a8ca7968f6f4e97e8d468b0df7df47 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Thu, 11 Sep 2025 23:38:59 +0530 Subject: [PATCH 2/9] update documentation --- browser-testing.md | 306 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 290 insertions(+), 16 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 4a75859..665f3f8 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -220,54 +220,328 @@ $page = visit('/')->on()->iPhone14Pro(); ### Screen Interactions (InteractsWithScreen) +Screen Interactions provide powerful capabilities for capturing and validating visual aspects of your application, including screenshots and visual regression testing. + ```php $page = visit('/') - // Taking screenshots + // Basic Screenshot ->screenshot('homepage.png') + + // Full Page Screenshot + ->screenshot('full-page.png', fullPage: true) + + // Screenshot with Specific Dimensions + ->screenshot('custom-size.png', clip: [ + 'x' => 0, + 'y' => 0, + 'width' => 1920, + 'height' => 1080 + ]) + + // Element Screenshots ->screenshotElement('#header', 'header.png') + ->screenshotElement('.product-card', 'product.png') + + // Screenshot with Options + ->screenshot('homepage-dark.png', options: [ + 'omitBackground' => true, + 'quality' => 80, + 'timeout' => 5000 + ]) + + // Visual Regression Testing + ->assertScreenshotMatches() // Uses test name as baseline + ->assertScreenshotMatches('custom-baseline.png') + ->assertScreenshotMatches(fullPage: true) + ->assertElementScreenshotMatches('#element', 'element-baseline.png') + + // Mobile/Responsive Screenshots + ->on()->iPhone14() + ->screenshot('mobile-view.png') + ->on()->desktop() + ->screenshot('desktop-view.png'); - // Assertions - ->assertScreenshotMatches('expected.png') - ->assertElementScreenshotMatches('#element', 'element.png'); +// Advanced Screenshot Testing +$page->visit('/products') + // Take screenshots in different states + ->screenshot('products-initial.png') + ->click('#filter-button') + ->waitForText('Filtered Results') + ->screenshot('products-filtered.png') + ->hover('.product-card') + ->screenshot('product-hover.png'); ``` -### Frame Handling (InteractsWithFrames) +Screenshot Options: + +- `fullPage`: Capture entire scrollable page +- `clip`: Capture specific area +- `omitBackground`: Make background transparent +- `quality`: JPEG quality (0-100) +- `timeout`: Maximum time to wait for screenshot +- `type`: Image format (png/jpeg) + +Visual Regression Features: + +1. Automatic baseline creation +2. Pixel-by-pixel comparison +3. Tolerance settings for minor differences +4. Diff image generation +5. Multiple comparison strategies + +Common Use Cases: + +- Visual regression testing +- Documentation generation +- Bug reporting +- State verification +- Responsive design testing +- Cross-browser testing +- Animation testing (with multiple screenshots) + +Best Practices: + +1. Use consistent viewport sizes +2. Consider dynamic content +3. Handle loading states +4. Set appropriate tolerances +5. Organize screenshots by feature +6. Version control baselines +7. Regular baseline updates### Frame Handling (InteractsWithFrames) + +The Frame Handling feature allows you to interact with content inside iframes. This is particularly useful when testing applications that embed third-party content or use frame-based layouts. ```php $page = visit('/') + // Basic frame interaction ->withinFrame('#iframe', function ($frame) { $frame->click('.button') ->assertSee('Frame Content') ->type('email', 'test@example.com'); + }) + + // Multiple frames handling + ->withinFrame(['#parent-frame', '#child-frame'], function ($frame) { + // Interact with nested frames + $frame->click('.nested-button'); + }) + + // Frame by name or selector + ->withinFrame('frame-name', function ($frame) { + $frame->assertVisible('.frame-content'); + }) + + // Wait for frame to be available + ->waitForFrame('#loading-frame') + + // Assertions within frames + ->withinFrame('#payment-frame', function ($frame) { + $frame->assertVisible('#card-number') + ->type('#card-number', '4242424242424242') + ->assertValue('#card-number', '4242424242424242'); }); -``` + +// Example with complex frame interactions +$page->visit('/checkout') + ->withinFrame('#payment-widget', function ($frame) { + // Fill payment form in iframe + $frame->type('cardNumber', '4242424242424242') + ->type('expiryDate', '12/25') + ->type('cvv', '123') + ->press('Pay Now') + ->waitForText('Payment Successful'); + }) + ->assertPathIs('/confirmation'); +``` + +Frame Handling Features: + +- Support for single and nested iframes +- Frame selection by CSS selector or name +- Automatic waiting for frame availability +- Full access to page interaction methods within frames +- Support for assertions within frames +- Ability to chain frame interactions +- Automatic frame context switching +- Error handling for missing frames + +Common Use Cases: + +1. Testing embedded payment forms +2. Interacting with rich text editors +3. Testing embedded maps or media players +4. Working with third-party widgets +5. Testing administrative dashboards with frame-based layouts ### Tab Management (InteractsWithTab) +Tab Management allows you to work with multiple browser tabs/windows, essential for testing scenarios that involve pop-ups, new window interactions, or multi-window workflows. + ```php $page = visit('/') - ->openNewTab() - ->switchToTab(1) + // Basic Tab Operations + ->openNewTab() // Opens a new empty tab + ->switchToTab(1) // Switch to tab by index + ->visit('/new-page') // Navigate in new tab ->assertUrlIs('/new-page') - ->closeTab() - ->switchToTab(0); -``` + ->closeTab() // Close current tab + ->switchToTab(0) // Return to first tab + + // Advanced Tab Management + ->openNewTab(url: '/direct-page') // Open with specific URL + ->waitForTab(2) // Wait for specific number of tabs + ->getAllTabs() // Get all open tabs + ->switchToLastTab() // Switch to most recent tab + ->switchToFirstTab() // Switch to first tab + + // Working with Multiple Tabs + ->openNewTab() + ->within(1, function ($tab) { // Work in specific tab + $tab->assertSee('New Tab Content'); + }) + + // Handling Popup Windows + ->click('#open-popup') + ->waitForNewTab() + ->switchToLastTab() + ->assertSee('Popup Content') + + // Tab Context Preservation + ->switchToTab(0) + ->assertSee('Original Content'); + +// Complex Multi-tab Scenario +$page->visit('/products') + // Open product in new tab + ->click('#view-in-new-tab', modifiers: ['Control']) + ->waitForNewTab() + ->switchToLastTab() + ->assertUrlContains('/product/') + ->assertSee('Product Details') + + // Compare in multiple tabs + ->switchToFirstTab() + ->assertSee('Product List') + + // Clean up + ->closeAllOtherTabs() // Close all except current + ->assertTabCount(1); // Verify cleanup +``` + +Tab Management Features: + +1. Create new tabs with or without URLs +2. Switch between tabs by index +3. Close individual or multiple tabs +4. Wait for tab operations +5. Handle popup windows +6. Preserve context across tabs +7. Access all open tabs +8. Tab count assertions + +Common Use Cases: + +- Testing "Open in New Tab" functionality +- Handling popup windows +- Multi-window workflows +- Compare views across tabs +- Testing tab-specific behavior +- Social media authentication flows +- Document preview features + +Best Practices: + +1. Always clean up tabs after tests +2. Use explicit waits for new tabs +3. Handle tab indices carefully +4. Verify correct context after switching +5. Consider tab lifecycle management +6. Handle unexpected popups +7. Test tab-specific keyboard shortcuts ### Viewport Control (InteractsWithViewPort) +The viewport control allows you to manipulate the browser's viewport size and emulate different devices. This is particularly useful for testing responsive designs and mobile-specific features. + ```php $page = visit('/') // Set specific dimensions ->resize(1920, 1080) - - // Use predefined device settings + ->setViewport([ + 'width' => 1280, + 'height' => 720, + 'deviceScaleFactor' => 1, + 'isMobile' => false, + 'hasTouch' => false, + 'isLandscape' => false + ]) + + // Predefined device settings ->on()->iPhone14() + ->on()->iPhone14Pro() + ->on()->iPhone14ProMax() + ->on()->macbook14() ->on()->macbook16() + + // Generic device types ->on()->mobile() - ->on()->desktop(); + ->on()->tablet() + ->on()->desktop() + + // Orientation control + ->on()->landscape() + ->on()->portrait(); + +// Chain with other assertions +$page->assertVisible('.mobile-menu') // On mobile view + ->on()->desktop() // Switch to desktop + ->assertMissing('.mobile-menu'); // Verify responsive behavior ``` -### Console and Error Handling (MakesConsoleAssertions) +Available Device Presets: + +- Mobile Devices + + - `iPhone14()` + - `iPhone14Plus()` + - `iPhone14Pro()` + - `iPhone14ProMax()` + - `iPhone13()` + - `iPhone13Pro()` + - `iPhone13ProMax()` + - `iPadAir()` + - `iPadMini()` + - `pixel7()` + - `galaxyS23()` + +- Desktop Devices + - `macbook13()` + - `macbook14()` + - `macbook16()` + - `desktop4K()` + - `desktopHD()` + +Each device preset automatically configures: + +- Viewport dimensions +- Device scale factor +- User agent string +- Touch capability +- Mobile mode +- Default orientation + +You can also create custom viewport settings: + +````php +$page->setViewport([ + 'width' => 1024, + 'height' => 768, + 'deviceScaleFactor' => 2, // For retina/high-DPI displays + 'isMobile' => true, // Enable mobile mode + 'hasTouch' => true, // Enable touch events + 'isLandscape' => true // Set landscape orientation +]); +```### Console and Error Handling (MakesConsoleAssertions) ```php $page = visit('/') @@ -275,7 +549,7 @@ $page = visit('/') ->assertNoJavaScriptErrors() ->assertConsoleLogContains('Debug message') ->assertConsoleWarningContains('Warning'); -``` +```` ### Element Assertions (MakesElementAssertions) From e89d8b263dc49b108b87ae9f16e323c81748a239 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Fri, 12 Sep 2025 00:03:17 +0530 Subject: [PATCH 3/9] fix the format --- browser-testing.md | 393 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 325 insertions(+), 68 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 665f3f8..f642b69 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -164,7 +164,7 @@ pest()->browser() The browser plugin provides various methods to interact with web pages: -````php +`````php test('page navigation and interaction', function () { $page = visit('/') // Basic navigation @@ -195,7 +195,67 @@ By default, the `visit()` method uses Chrome as the browser. However, if you wan ```bash ./vendor/bin/pest --browser firefox ./vendor/bin/pest --browser safari -```` +``` + +### Toolbar Operations (InteractsWithToolbar) + +The Toolbar Operations feature provides methods to interact with browser's DevTools and various browser controls. + +```php +$page = visit('/') + // DevTools Operations + ->openDevTools() // Open Chrome DevTools + ->closeDevTools() // Close DevTools + + // Navigation Controls + ->reload() // Reload the current page + ->reloadWithCache() // Force reload with cache + ->reloadWithoutCache() // Force reload bypassing cache + + // Browser Controls + ->maximize() // Maximize browser window + ->minimize() // Minimize browser window + ->fullScreen() // Enter full screen mode + ->exitFullScreen() // Exit full screen mode + + // Network Operations + ->setOffline(true) // Enable offline mode + ->setOffline(false) // Disable offline mode + + // Performance + ->emulateCPUThrottling(4) // Simulate slower CPU + ->emulateNetworkConditions([ // Simulate network conditions + 'offline' => false, + 'latency' => 100, + 'downloadThroughput' => 1024 * 1024, + 'uploadThroughput' => 1024 * 1024 + ]); + +// Example with debugging workflow +$page->visit('/complex-page') + ->openDevTools() + ->assertSee('Loading...') + ->waitForText('Loaded') + ->screenshot('debug-view.png') + ->closeDevTools(); +``` + +Toolbar Features: +1. DevTools management +2. Page reload controls +3. Window state management +4. Network condition simulation +5. Performance throttling +6. Cache control +7. Full screen handling + +Common Use Cases: +- Debugging complex interactions +- Testing offline behavior +- Performance testing +- Network condition testing +- Cache-related testing +- Responsive design testing` If you wish to use a different browser by default without specifying it in the command line, you can set it in your `Pest.php` configuration file: @@ -274,12 +334,12 @@ $page->visit('/products') Screenshot Options: -- `fullPage`: Capture entire scrollable page -- `clip`: Capture specific area -- `omitBackground`: Make background transparent -- `quality`: JPEG quality (0-100) -- `timeout`: Maximum time to wait for screenshot -- `type`: Image format (png/jpeg) +- `fullPage`: Capture entire scrollable page +- `clip`: Capture specific area +- `omitBackground`: Make background transparent +- `quality`: JPEG quality (0-100) +- `timeout`: Maximum time to wait for screenshot +- `type`: Image format (png/jpeg) Visual Regression Features: @@ -291,13 +351,13 @@ Visual Regression Features: Common Use Cases: -- Visual regression testing -- Documentation generation -- Bug reporting -- State verification -- Responsive design testing -- Cross-browser testing -- Animation testing (with multiple screenshots) +- Visual regression testing +- Documentation generation +- Bug reporting +- State verification +- Responsive design testing +- Cross-browser testing +- Animation testing (with multiple screenshots) Best Practices: @@ -356,14 +416,14 @@ $page->visit('/checkout') Frame Handling Features: -- Support for single and nested iframes -- Frame selection by CSS selector or name -- Automatic waiting for frame availability -- Full access to page interaction methods within frames -- Support for assertions within frames -- Ability to chain frame interactions -- Automatic frame context switching -- Error handling for missing frames +- Support for single and nested iframes +- Frame selection by CSS selector or name +- Automatic waiting for frame availability +- Full access to page interaction methods within frames +- Support for assertions within frames +- Ability to chain frame interactions +- Automatic frame context switching +- Error handling for missing frames Common Use Cases: @@ -441,13 +501,13 @@ Tab Management Features: Common Use Cases: -- Testing "Open in New Tab" functionality -- Handling popup windows -- Multi-window workflows -- Compare views across tabs -- Testing tab-specific behavior -- Social media authentication flows -- Document preview features +- Testing "Open in New Tab" functionality +- Handling popup windows +- Multi-window workflows +- Compare views across tabs +- Testing tab-specific behavior +- Social media authentication flows +- Document preview features Best Practices: @@ -500,35 +560,35 @@ $page->assertVisible('.mobile-menu') // On mobile view Available Device Presets: -- Mobile Devices - - - `iPhone14()` - - `iPhone14Plus()` - - `iPhone14Pro()` - - `iPhone14ProMax()` - - `iPhone13()` - - `iPhone13Pro()` - - `iPhone13ProMax()` - - `iPadAir()` - - `iPadMini()` - - `pixel7()` - - `galaxyS23()` - -- Desktop Devices - - `macbook13()` - - `macbook14()` - - `macbook16()` - - `desktop4K()` - - `desktopHD()` +- Mobile Devices + + - `iPhone14()` + - `iPhone14Plus()` + - `iPhone14Pro()` + - `iPhone14ProMax()` + - `iPhone13()` + - `iPhone13Pro()` + - `iPhone13ProMax()` + - `iPadAir()` + - `iPadMini()` + - `pixel7()` + - `galaxyS23()` + +- Desktop Devices + - `macbook13()` + - `macbook14()` + - `macbook16()` + - `desktop4K()` + - `desktopHD()` Each device preset automatically configures: -- Viewport dimensions -- Device scale factor -- User agent string -- Touch capability -- Mobile mode -- Default orientation +- Viewport dimensions +- Device scale factor +- User agent string +- Touch capability +- Mobile mode +- Default orientation You can also create custom viewport settings: @@ -541,15 +601,82 @@ $page->setViewport([ 'hasTouch' => true, // Enable touch events 'isLandscape' => true // Set landscape orientation ]); -```### Console and Error Handling (MakesConsoleAssertions) +``` + +### Console and Error Handling (MakesConsoleAssertions) + +The Console and Error Handling feature allows you to monitor and assert browser console output, JavaScript errors, and other browser-level messages. This is crucial for detecting client-side issues and debugging JavaScript applications. ```php $page = visit('/') - ->assertNoConsoleErrors() - ->assertNoJavaScriptErrors() + // Basic Console Assertions + ->assertNoConsoleErrors() // No error-level messages + ->assertNoJavaScriptErrors() // No JavaScript exceptions + ->assertNoConsoleLogs() // No console messages at all + + // Console Message Type Assertions ->assertConsoleLogContains('Debug message') - ->assertConsoleWarningContains('Warning'); -```` + ->assertConsoleWarningContains('Warning') + ->assertConsoleErrorContains('Error') + + // Multiple Message Assertions + ->assertConsoleLogContains([ + 'First message', + 'Second message' + ]) + + // Regex Pattern Matching + ->assertConsoleLogMatches('/API response: .*/') + + // Combined Assertions + ->assertNoSmoke() // No errors/warnings/logs + + // Timing and Performance + ->assertNoSlowResources() // Check for slow loading resources + ->assertNoNetworkErrors() // Check for failed network requests + + // Custom Console Handling + ->tap(function ($page) { + $consoleLogs = $page->getConsoleLogs(); + // Custom log processing + }); + +// Example with error tracking +$page->visit('/js-heavy-page') + ->waitForText('Loaded') + ->tap(function ($page) { + $errors = $page->getJavaScriptErrors(); + expect($errors)->toBeEmpty(); + }); +``` + +Console Message Types: +1. `log` - General logging messages +2. `info` - Informational messages +3. `warning` - Warning messages +4. `error` - Error messages +5. `debug` - Debug messages + +Available Assertions: +- `assertNoConsoleErrors()` - No error messages +- `assertNoJavaScriptErrors()` - No JS exceptions +- `assertNoConsoleLogs()` - No console messages +- `assertConsoleLogContains()` - Check log content +- `assertConsoleWarningContains()` - Check warning content +- `assertConsoleErrorContains()` - Check error content +- `assertNoSmoke()` - No issues of any kind +- `assertNoSlowResources()` - Performance check +- `assertNoNetworkErrors()` - Network check + +Best Practices: +1. Clear console before critical assertions +2. Handle asynchronous console messages +3. Use specific assertions for message types +4. Consider environment-specific logging +5. Monitor resource loading errors +6. Track performance issues +7. Handle expected console output +````` ### Element Assertions (MakesElementAssertions) @@ -580,24 +707,154 @@ $page = visit('/') ### Location Simulation (From) +The Location Simulation feature allows you to test location-specific behavior by simulating different geographical locations and related settings. + ```php $page = visit('/')->from() - ->amsterdam() // Simulate being in Amsterdam - ->london() // Simulate being in London - ->withLocale('nl-NL') - ->withTimezone('Europe/Amsterdam'); -``` + // Predefined Locations + ->amsterdam() // Simulate being in Amsterdam + ->london() // Simulate being in London + ->newYork() // Simulate being in New York + ->tokyo() // Simulate being in Tokyo + + // Locale and Timezone + ->withLocale('nl-NL') // Set Dutch locale + ->withTimezone('Europe/Amsterdam') // Set Amsterdam timezone + + // Custom Location + ->location(52.3676, 4.9041) // Custom coordinates + + // Combined Settings + ->from() + ->paris() + ->withLocale('fr-FR') + ->withTimezone('Europe/Paris') + ->withCurrency('EUR'); + +// Example with location-based testing +$page->visit('/weather') + ->from()->tokyo() + ->assertSee('°C') // Metric units + ->assertSee('JST') // Japan timezone + + ->from()->newYork() + ->assertSee('°F') // Imperial units + ->assertSee('EST'); // US timezone +``` + +Available Features: + +1. Predefined city locations +2. Custom GPS coordinates +3. Locale settings +4. Timezone configuration +5. Currency formatting +6. Language preferences +7. Regional settings + +Predefined Locations: + +- `amsterdam()` - Amsterdam, Netherlands +- `london()` - London, UK +- `newYork()` - New York, USA +- `tokyo()` - Tokyo, Japan +- `paris()` - Paris, France +- `berlin()` - Berlin, Germany +- And more... + +Common Use Cases: + +- Testing geo-restricted content +- Language/locale testing +- Timezone-specific features +- Currency formatting +- Regional pricing +- Content localization +- Weather applications +- Maps and navigation ### Livewire Support +The Livewire Support feature provides comprehensive testing capabilities for Laravel Livewire components, allowing you to interact with and assert against Livewire-specific functionality. + ```php $page = visit('/') + // Basic Livewire Testing ->livewire() ->assertSeeText('Component content') ->assertSet('property', 'value') ->call('method') - ->assertEmitted('event'); -``` + ->assertEmitted('event') + + // Component State + ->assertSet('counter', 0) + ->call('increment') + ->assertSet('counter', 1) + + // Event Testing + ->assertEmitted('counter-updated') + ->assertEmittedUp('parent-notified') + ->assertNotEmitted('unused-event') + + // Property Updates + ->updateProperty('name', 'Test') + ->assertSet('name', 'Test') + + // Form Interaction + ->fillForm([ + 'email' => 'test@example.com', + 'password' => 'secret' + ]) + ->call('submit') + + // File Uploads + ->upload('avatar', '/path/to/image.jpg') + ->assertSet('hasAvatar', true) + + // Validation + ->assertHasErrors(['email']) + ->assertHasNoErrors(['name']); + +// Example with complex Livewire interaction +$page->visit('/todos') + ->livewire() + ->assertSet('todos', []) + ->updateProperty('newTodo', 'Buy groceries') + ->call('addTodo') + ->assertSet('todos', ['Buy groceries']) + ->assertEmitted('todo-added') + ->assertSeeText('Buy groceries'); +``` + +Available Features: + +1. Component state assertions +2. Method calling +3. Event handling +4. Property manipulation +5. Form interaction +6. File upload testing +7. Validation testing +8. Real-time updates + +Common Assertions: + +- `assertSet()` - Check property values +- `assertEmitted()` - Verify events +- `assertHasErrors()` - Validate form errors +- `assertSeeHtml()` - Check rendered HTML +- `assertDispatched()` - Verify dispatched events +- `assertRedirect()` - Check redirects + +Best Practices: + +1. Test component isolation +2. Verify state changes +3. Test event propagation +4. Validate form submission +5. Check error handling +6. Test real-time updates +7. Verify component mounting You can visit multiple pages simultaneously by passing an array of URLs to the `visit()` method. This is useful for testing scenarios where you need to interact with multiple pages at once: From 7cff4fd0b95bbf6060adcbee0dee9fa804108ba0 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Mon, 15 Sep 2025 21:59:05 +0530 Subject: [PATCH 4/9] format fix --- browser-testing.md | 94 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index f642b69..1eb81c6 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -11,10 +11,9 @@ Browser testing is an essential part of modern web development, allowing you to - [Getting Started](#getting-started) - - [Installation](#getting-started) - - [Running Tests and Configuration](#running-tests-and-configuration) - - [Multiple Page Testing](#multiple-page-testing) - - [Configuration Options](#configuration-options) + - [Installation](#installation) + - [Basic Configuration](#basic-configuration) + - [Running Tests](#running-tests) - [Core Features](#core-features) @@ -23,18 +22,66 @@ Browser testing is an essential part of modern web development, allowing you to - [Frame Handling](#frame-handling) - [Tab Management](#tab-management) - [Viewport Control](#viewport-control) + - [Toolbar Operations](#toolbar-operations) + +- [Testing Capabilities](#testing-capabilities) + + - [Element Interactions](#element-interactions) + - [Form Handling](#form-handling) + - [Mouse and Keyboard](#mouse-and-keyboard) + - [Screenshots](#screenshots) + - [Console and Network](#console-and-network) -- [Assertions and Testing](#assertions-and-testing) +- [Assertions](#assertions) - - [Console and Error Handling](#console-and-error-handling) - [Element Assertions](#element-assertions) - [URL Assertions](#url-assertions) + - [Console Assertions](#console-assertions) + - [Screenshot Assertions](#screenshot-assertions) - [Advanced Features](#advanced-features) + + - [Multiple Page Testing](#multiple-page-testing) - [Location Simulation](#location-simulation) + - [Device Emulation](#device-emulation) - [Livewire Support](#livewire-support) -## Basic Example +- [Configuration](#configuration) + + - [Browser Options](#browser-options) + - [Viewport Settings](#viewport-settings) + - [Network Conditions](#network-conditions) + - [Screenshot Settings](#screenshot-settings) + +- [Debugging](#debugging) + - [Visual Debugging](#visual-debugging) + - [Console Debugging](#console-debugging) + - [Network Debugging](#network-debugging) + +## Getting Started + +### Installation + +To get started with browser testing in Pest, follow these steps: + +```bash +# Install the browser plugin +composer require pestphp/pest-plugin-browser --dev + +# Install Playwright +npm install playwright@latest + +# Install browser drivers +npx playwright install +``` + +Add the following to your `.gitignore` file: + +``` +tests/Browser/screenshots/ +``` + +### Basic Example Here's a simple example of a browser test using Pest: @@ -48,34 +95,33 @@ test('homepage shows welcome message', function () { }); ``` -This is a basic example of a browser test that checks if the homepage contains the text "Welcome". However, Pest's browser testing capabilities go beyond this simple example. You can use various methods to interact with the page, such as clicking buttons, filling out forms, and navigating between pages. - -Here is an example of a more complex browser test, on Laravel, that checks if a user can sign in: - -```php -it('may sign in the user', function () { - Event::fake(); - - User::factory()->create([ // assumes RefreshDatabase trait is used on Pest.php... - 'email' => 'nuno@laravel.com', - 'password' => 'password', - ]); +For a more complex example, here's a Laravel authentication test:```php +test('user can sign in', function () { +// Setup +Event::fake(); +User::factory()->create([ +'email' => 'test@example.com', +'password' => 'password', +]); + // Test $page = visit('/')->on()->mobile()->firefox(); $page->click('Sign In') ->assertUrlIs('/login') ->assertSee('Sign In to Your Account') - ->fill('email', 'nuno@laravel.com') + ->fill('email', 'test@example.com') ->fill('password', 'password') ->click('Submit') ->assertSee('Dashboard'); - $this->assertAuthenticated(); - + // Assertions + expect()->toBeAuthenticated(); Event::assertDispatched(UserLoggedIn::class); + }); -``` + +```` Note that, you are leveraging the full power of Laravel's testing capabilities, such as refresh database, event faking, and authentication assertions, while also actually doing browser testing. @@ -88,7 +134,7 @@ composer require pestphp/pest-plugin-browser --dev npm install playwright@latest npx playwright install -``` +```` Finally, add `tests/Browser/Screenshots` to your `.gitignore` file to avoid committing screenshots taken during browser tests. From 52e1c8e4255cedebc5bdecbbf9b9293d9e33eff0 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Mon, 15 Sep 2025 22:19:30 +0530 Subject: [PATCH 5/9] format changes --- browser-testing.md | 166 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 4 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 1eb81c6..378b400 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -1,11 +1,167 @@ --- title: Browser Testing -description: Browser testing capabilities in Pest PHP +description: Browser testing enables you to automate web application interactions in real browsers, helping you validate functionality across different browsers and devices. --- # Browser Testing -Browser testing is an essential part of modern web development, allowing you to ensure that your application works correctly across different browsers and devices. Pest provides a comprehensive browser testing API through its browser plugin. This documentation covers all available features based on the official API implementation. +Pest's browser testing plugin provides a powerful API for automating browser interactions. Here's everything you need to know to get started: + +```bash +# Installation +composer require pestphp/pest-plugin-browser --dev +npm install playwright@latest +npx playwright install +``` + +## Basic Usage + +```php +test('user can log in', function () { + visit('/login') + ->type('email', 'test@example.com') + ->type('password', 'password') + ->click('Login') + ->assertPathIs('/dashboard'); +}); +``` + +## Available Methods + +
+ +### Navigation + +[visit()](#visit) - Visit a URL +[navigate()](#navigate) - Navigate to another URL +[back()](#back) - Go back +[forward()](#forward) - Go forward +[refresh()](#refresh) - Refresh page + +### Interactions + +[click()](#click) - Click element +[type()](#type) - Type text +[select()](#select) - Select option +[check()](#check) - Check checkbox +[uncheck()](#uncheck) - Uncheck checkbox +[attach()](#attach) - Attach file +[press()](#press) - Press key +[hover()](#hover) - Hover over element +[drag()](#drag) - Drag element + +### Assertions + +[assertSee()](#assert-see) - Assert text visible +[assertDontSee()](#assert-dont-see) - Assert text not visible +[assertTitle()](#assert-title) - Assert page title +[assertUrlIs()](#assert-url-is) - Assert current URL +[assertPathIs()](#assert-path-is) - Assert current path +[assertVisible()](#assert-visible) - Assert element visible +[assertMissing()](#assert-missing) - Assert element not visible +[assertValue()](#assert-value) - Assert input value + +### Device & Network + +[mobile()](#mobile) - Mobile viewport +[tablet()](#tablet) - Tablet viewport +[desktop()](#desktop) - Desktop viewport +[setNetwork()](#set-network) - Set network conditions +[setGeolocation()](#set-geolocation) - Set location + +### Debug & Screenshots + +[screenshot()](#screenshot) - Take screenshot +[debug()](#debug) - Start debugging +[pause()](#pause) - Pause execution + +
+ +## Common Examples + +### Form Testing + +```php +test('contact form submission', function () { + visit('/contact') + ->type('name', 'John Doe') + ->type('email', 'john@example.com') + ->type('message', 'Hello') + ->attach('attachment', '/path/to/file.pdf') + ->click('Submit') + ->assertSee('Message sent successfully'); +}); +``` + +### Responsive Testing + +```php +test('menu is responsive', function () { + visit('/') + ->desktop() + ->assertVisible('#desktop-menu') + ->assertMissing('#mobile-menu') + ->mobile() + ->assertVisible('#mobile-menu') + ->assertMissing('#desktop-menu'); +}); +``` + +### Multi-page Testing + +```php +test('multiple pages', function () { + $pages = visit(['/', '/about']); + [$home, $about] = $pages; + + $home->assertSee('Welcome'); + $about->assertSee('About Us'); +}); +``` + +### Error Handling + +```php +test('form validation', function () { + visit('/register') + ->click('Register') + ->assertSee('Email is required') + ->type('email', 'invalid') + ->click('Register') + ->assertSee('Valid email required') + ->assertPathIs('/register'); +}); +``` + +## Configuration + +Configure browser testing in your `Pest.php`: + +```php +pest()->browser() + ->inChrome() // Use Chrome (default) + ->inFirefox() // Use Firefox + ->timeout(10000) // Set timeout (ms) + ->headed() // Show browser + ->headless(); // Hide browser (default) +``` + +
+ +[Installation](#installation) +[Basic Usage](#basic-usage) +[Navigation](#navigation) +[Element Interactions](#element-interactions) +[Assertions](#assertions) +[Screenshots](#screenshots) +[Device Emulation](#device-emulation) +[Network Conditions](#network-conditions) +[Console and Errors](#console-and-errors) +[Frames and Windows](#frames-and-windows) +[Geolocation](#geolocation) +[Accessibility Testing](#accessibility-testing) + +
## Table of Contents @@ -60,9 +216,11 @@ Browser testing is an essential part of modern web development, allowing you to ## Getting Started + + ### Installation -To get started with browser testing in Pest, follow these steps: +Browser testing in Pest requires both the Pest Browser plugin and Playwright. You can install them using the following commands: ```bash # Install the browser plugin @@ -75,7 +233,7 @@ npm install playwright@latest npx playwright install ``` -Add the following to your `.gitignore` file: +After installation, add the following path to your `.gitignore` file to exclude browser test screenshots: ``` tests/Browser/screenshots/ From 91362d9ce020e312f100feedbcccf86d0cd97aa1 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Tue, 16 Sep 2025 23:26:35 +0530 Subject: [PATCH 6/9] md file format fix --- browser-testing.md | 685 +++++++++++++++++++++++++++------------------ 1 file changed, 419 insertions(+), 266 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 378b400..14d9c8e 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -32,48 +32,48 @@ test('user can log in', function () { ### Navigation -[visit()](#visit) - Visit a URL -[navigate()](#navigate) - Navigate to another URL -[back()](#back) - Go back -[forward()](#forward) - Go forward -[refresh()](#refresh) - Refresh page +- [visit()](#visit) - Visit a URL +- [navigate()](#navigate) - Navigate to another URL +- [back()](#back) - Go back +- [forward()](#forward) - Go forward +- [refresh()](#refresh) - Refresh page ### Interactions -[click()](#click) - Click element -[type()](#type) - Type text -[select()](#select) - Select option -[check()](#check) - Check checkbox -[uncheck()](#uncheck) - Uncheck checkbox -[attach()](#attach) - Attach file -[press()](#press) - Press key -[hover()](#hover) - Hover over element -[drag()](#drag) - Drag element +- [click()](#click) - Click element +- [type()](#type) - Type text +- [select()](#select) - Select option +- [check()](#check) - Check checkbox +- [uncheck()](#uncheck) - Uncheck checkbox +- [attach()](#attach) - Attach file +- [press()](#press) - Press key +- [hover()](#hover) - Hover over element +- [drag()](#drag) - Drag element ### Assertions -[assertSee()](#assert-see) - Assert text visible -[assertDontSee()](#assert-dont-see) - Assert text not visible -[assertTitle()](#assert-title) - Assert page title -[assertUrlIs()](#assert-url-is) - Assert current URL -[assertPathIs()](#assert-path-is) - Assert current path -[assertVisible()](#assert-visible) - Assert element visible -[assertMissing()](#assert-missing) - Assert element not visible -[assertValue()](#assert-value) - Assert input value +- [assertSee()](#assert-see) - Assert text visible +- [assertDontSee()](#assert-dont-see) - Assert text not visible +- [assertTitle()](#assert-title) - Assert page title +- [assertUrlIs()](#assert-url-is) - Assert current URL +- [assertPathIs()](#assert-path-is) - Assert current path +- [assertVisible()](#assert-visible) - Assert element visible +- [assertMissing()](#assert-missing) - Assert element not visible +- [assertValue()](#assert-value) - Assert input value ### Device & Network -[mobile()](#mobile) - Mobile viewport -[tablet()](#tablet) - Tablet viewport -[desktop()](#desktop) - Desktop viewport -[setNetwork()](#set-network) - Set network conditions -[setGeolocation()](#set-geolocation) - Set location +- [mobile()](#mobile) - Mobile viewport +- [tablet()](#tablet) - Tablet viewport +- [desktop()](#desktop) - Desktop viewport +- [setNetwork()](#set-network) - Set network conditions +- [setGeolocation()](#set-geolocation) - Set location ### Debug & Screenshots -[screenshot()](#screenshot) - Take screenshot -[debug()](#debug) - Start debugging -[pause()](#pause) - Pause execution +- [screenshot()](#screenshot) - Take screenshot +- [debug()](#debug) - Start debugging +- [pause()](#pause) - Pause execution
@@ -137,13 +137,19 @@ test('form validation', function () { Configure browser testing in your `Pest.php`: +- `inChrome()` - Use Chrome (default) +- `inFirefox()` - Use Firefox +- `timeout(10000)` - Set timeout (ms) +- `headed()` - Show browser +- `headless()` - Hide browser (default) + ```php pest()->browser() - ->inChrome() // Use Chrome (default) - ->inFirefox() // Use Firefox - ->timeout(10000) // Set timeout (ms) - ->headed() // Show browser - ->headless(); // Hide browser (default) + ->inChrome() + ->inFirefox() + ->timeout(10000) + ->headed() + ->headless(); ```
@@ -253,7 +259,9 @@ test('homepage shows welcome message', function () { }); ``` -For a more complex example, here's a Laravel authentication test:```php +For a more complex example, here's a Laravel authentication test: + +```php test('user can sign in', function () { // Setup Event::fake(); @@ -278,8 +286,7 @@ User::factory()->create([ Event::assertDispatched(UserLoggedIn::class); }); - -```` +``` Note that, you are leveraging the full power of Laravel's testing capabilities, such as refresh database, event faking, and authentication assertions, while also actually doing browser testing. @@ -292,26 +299,19 @@ composer require pestphp/pest-plugin-browser --dev npm install playwright@latest npx playwright install -```` +``` Finally, add `tests/Browser/Screenshots` to your `.gitignore` file to avoid committing screenshots taken during browser tests. ### Running Tests and Configuration -```bash -# Run all tests -./vendor/bin/pest - -# Run tests in parallel -./vendor/bin/pest --parallel +Available test running options: -# Run in debug mode (headed browser) -./vendor/bin/pest --debug - -# Run with specific browser -./vendor/bin/pest --browser firefox -./vendor/bin/pest --browser safari -``` +- `./vendor/bin/pest` - Run all tests +- `./vendor/bin/pest --parallel` - Run tests in parallel +- `./vendor/bin/pest --debug` - Run in debug mode (headed browser) +- `./vendor/bin/pest --browser firefox` - Run with Firefox browser +- `./vendor/bin/pest --browser safari` - Run with Safari browser ### Multiple Page Testing @@ -339,6 +339,28 @@ test('multiple pages', function () { You can configure the browser behavior in your `Pest.php` file: +Browser selection: + +- `inChrome()` - Use Chrome browser +- `inFirefox()` - Use Firefox browser +- `inSafari()` - Use Safari browser + +Display modes: + +- `headed()` - Show browser window +- `headless()` - Hide browser window +- `inDarkMode()` - Enable dark mode + +Timing and behavior: + +- `timeout(10000)` - Set timeout in milliseconds +- `userAgent('Custom/1.0')` - Set custom user agent + +Screenshot configuration: + +- `screenshotsPath('tests/Browser/screenshots')` - Set screenshots path +- `failedScreenshotsPath('tests/Browser/screenshots/failures')` - Set failed screenshots path + ```php use Pest\Plugin\Browser\Configuration; @@ -349,13 +371,13 @@ pest()->browser() ->inSafari() // Display modes - ->headed() // Show browser window - ->headless() // Hide browser window - ->inDarkMode() // Enable dark mode + ->headed() + ->headless() + ->inDarkMode() // Timing and behavior - ->timeout(10000) // Set timeout in milliseconds - ->userAgent('Custom/1.0') // Set custom user agent + ->timeout(10000) + ->userAgent('Custom/1.0') // Screenshot configuration ->screenshotsPath('tests/Browser/screenshots') @@ -368,7 +390,32 @@ pest()->browser() The browser plugin provides various methods to interact with web pages: -`````php +``Browser navigation and interaction methods: + +Navigation methods: + +- `navigate('/about')` - Navigate to another URL +- `back()` - Go back one page +- `forward()` - Go forward one page +- `refresh()` - Refresh current page + +Waiting methods: + +- `waitForNavigation()` - Wait for page navigation +- `waitFor('.element')` - Wait for element +- `waitForText('Loading completed')` - Wait for text + +Element interaction methods: + +- `click('.button')` - Click an element +- `type('email', 'value')` - Type into input +- `fill('message', 'text')` - Fill form field +- `select('country', 'USA')` - Select dropdown option +- `check('terms')` - Check checkbox +- `uncheck('newsletter')` - Uncheck checkbox +- `press('Submit')` - Press button + +```php test('page navigation and interaction', function () { $page = visit('/') // Basic navigation @@ -377,12 +424,12 @@ test('page navigation and interaction', function () { ->forward() ->refresh() - // Waiting capabilities (HasWaitCapabilities) + // Waiting capabilities ->waitForNavigation() ->waitFor('.element') ->waitForText('Loading completed') - // Element interaction (InteractsWithElements) + // Element interaction ->click('.button') ->type('email', 'test@example.com') ->fill('message', 'Hello') @@ -391,44 +438,71 @@ test('page navigation and interaction', function () { ->uncheck('newsletter') ->press('Submit'); }); +``` ### Using Other Browsers -By default, the `visit()` method uses Chrome as the browser. However, if you want to use a different browser, you can specify it using the `--browser` option when running the tests: +By default, the `visit()` method uses Chrome as the browser. Available browser options: -```bash -./vendor/bin/pest --browser firefox -./vendor/bin/pest --browser safari -``` +- `./vendor/bin/pest --browser firefox` - Run tests in Firefox +- `./vendor/bin/pest --browser safari` - Run tests in Safari ### Toolbar Operations (InteractsWithToolbar) The Toolbar Operations feature provides methods to interact with browser's DevTools and various browser controls. +DevTools Operations: + +- `openDevTools()` - Open Chrome DevTools +- `closeDevTools()` - Close DevTools + +Navigation Controls: + +- `reload()` - Reload the current page +- `reloadWithCache()` - Force reload with cache +- `reloadWithoutCache()` - Force reload bypassing cache + +Browser Controls: + +- `maximize()` - Maximize browser window +- `minimize()` - Minimize browser window +- `fullScreen()` - Enter full screen mode +- `exitFullScreen()` - Exit full screen mode + +Network Operations: + +- `setOffline(true)` - Enable offline mode +- `setOffline(false)` - Disable offline mode + +Performance Controls: + +- `emulateCPUThrottling(4)` - Simulate slower CPU +- `emulateNetworkConditions()` - Simulate network conditions + ```php $page = visit('/') // DevTools Operations - ->openDevTools() // Open Chrome DevTools - ->closeDevTools() // Close DevTools + ->openDevTools() + ->closeDevTools() // Navigation Controls - ->reload() // Reload the current page - ->reloadWithCache() // Force reload with cache - ->reloadWithoutCache() // Force reload bypassing cache + ->reload() + ->reloadWithCache() + ->reloadWithoutCache() // Browser Controls - ->maximize() // Maximize browser window - ->minimize() // Minimize browser window - ->fullScreen() // Enter full screen mode - ->exitFullScreen() // Exit full screen mode + ->maximize() + ->minimize() + ->fullScreen() + ->exitFullScreen() // Network Operations - ->setOffline(true) // Enable offline mode - ->setOffline(false) // Disable offline mode + ->setOffline(true) + ->setOffline(false) // Performance - ->emulateCPUThrottling(4) // Simulate slower CPU - ->emulateNetworkConditions([ // Simulate network conditions + ->emulateCPUThrottling(4) + ->emulateNetworkConditions([ 'offline' => false, 'latency' => 100, 'downloadThroughput' => 1024 * 1024, @@ -444,22 +518,14 @@ $page->visit('/complex-page') ->closeDevTools(); ``` -Toolbar Features: -1. DevTools management -2. Page reload controls -3. Window state management -4. Network condition simulation -5. Performance throttling -6. Cache control -7. Full screen handling - Common Use Cases: + - Debugging complex interactions - Testing offline behavior - Performance testing - Network condition testing - Cache-related testing -- Responsive design testing` +- Responsive design testing If you wish to use a different browser by default without specifying it in the command line, you can set it in your `Pest.php` configuration file: @@ -538,12 +604,12 @@ $page->visit('/products') Screenshot Options: -- `fullPage`: Capture entire scrollable page -- `clip`: Capture specific area -- `omitBackground`: Make background transparent -- `quality`: JPEG quality (0-100) -- `timeout`: Maximum time to wait for screenshot -- `type`: Image format (png/jpeg) +- `fullPage`: Capture entire scrollable page +- `clip`: Capture specific area +- `omitBackground`: Make background transparent +- `quality`: JPEG quality (0-100) +- `timeout`: Maximum time to wait for screenshot +- `type`: Image format (png/jpeg) Visual Regression Features: @@ -555,13 +621,13 @@ Visual Regression Features: Common Use Cases: -- Visual regression testing -- Documentation generation -- Bug reporting -- State verification -- Responsive design testing -- Cross-browser testing -- Animation testing (with multiple screenshots) +- Visual regression testing +- Documentation generation +- Bug reporting +- State verification +- Responsive design testing +- Cross-browser testing +- Animation testing (with multiple screenshots) Best Practices: @@ -620,14 +686,14 @@ $page->visit('/checkout') Frame Handling Features: -- Support for single and nested iframes -- Frame selection by CSS selector or name -- Automatic waiting for frame availability -- Full access to page interaction methods within frames -- Support for assertions within frames -- Ability to chain frame interactions -- Automatic frame context switching -- Error handling for missing frames +- Support for single and nested iframes +- Frame selection by CSS selector or name +- Automatic waiting for frame availability +- Full access to page interaction methods within frames +- Support for assertions within frames +- Ability to chain frame interactions +- Automatic frame context switching +- Error handling for missing frames Common Use Cases: @@ -705,13 +771,13 @@ Tab Management Features: Common Use Cases: -- Testing "Open in New Tab" functionality -- Handling popup windows -- Multi-window workflows -- Compare views across tabs -- Testing tab-specific behavior -- Social media authentication flows -- Document preview features +- Testing "Open in New Tab" functionality +- Handling popup windows +- Multi-window workflows +- Compare views across tabs +- Testing tab-specific behavior +- Social media authentication flows +- Document preview features Best Practices: @@ -764,46 +830,55 @@ $page->assertVisible('.mobile-menu') // On mobile view Available Device Presets: -- Mobile Devices - - - `iPhone14()` - - `iPhone14Plus()` - - `iPhone14Pro()` - - `iPhone14ProMax()` - - `iPhone13()` - - `iPhone13Pro()` - - `iPhone13ProMax()` - - `iPadAir()` - - `iPadMini()` - - `pixel7()` - - `galaxyS23()` - -- Desktop Devices - - `macbook13()` - - `macbook14()` - - `macbook16()` - - `desktop4K()` - - `desktopHD()` +- Mobile Devices + + - `iPhone14()` + - `iPhone14Plus()` + - `iPhone14Pro()` + - `iPhone14ProMax()` + - `iPhone13()` + - `iPhone13Pro()` + - `iPhone13ProMax()` + - `iPadAir()` + - `iPadMini()` + - `pixel7()` + - `galaxyS23()` + +- Desktop Devices + - `macbook13()` + - `macbook14()` + - `macbook16()` + - `desktop4K()` + - `desktopHD()` Each device preset automatically configures: -- Viewport dimensions -- Device scale factor -- User agent string -- Touch capability -- Mobile mode -- Default orientation +- Viewport dimensions +- Device scale factor +- User agent string +- Touch capability +- Mobile mode +- Default orientation + +### Custom Viewport Settings + +You can configure custom viewport settings using these options: -You can also create custom viewport settings: +- `width` - Viewport width in pixels +- `height` - Viewport height in pixels +- `deviceScaleFactor` - Screen density (e.g., 2 for Retina displays) +- `isMobile` - Enable mobile device mode +- `hasTouch` - Enable touch screen capabilities +- `isLandscape` - Set landscape orientation -````php +```php $page->setViewport([ 'width' => 1024, 'height' => 768, - 'deviceScaleFactor' => 2, // For retina/high-DPI displays - 'isMobile' => true, // Enable mobile mode - 'hasTouch' => true, // Enable touch events - 'isLandscape' => true // Set landscape orientation + 'deviceScaleFactor' => 2, + 'isMobile' => true, + 'hasTouch' => true, + 'isLandscape' => true ]); ``` @@ -811,6 +886,28 @@ $page->setViewport([ The Console and Error Handling feature allows you to monitor and assert browser console output, JavaScript errors, and other browser-level messages. This is crucial for detecting client-side issues and debugging JavaScript applications. +Available Console Message Types: + +1. `log` - General logging messages +2. `info` - Informational messages +3. `warning` - Warning messages +4. `error` - Error messages +5. `debug` - Debug messages + +Available Assertions: + +- `assertNoConsoleErrors()` - No error messages +- `assertNoJavaScriptErrors()` - No JS exceptions +- `assertNoConsoleLogs()` - No console messages +- `assertConsoleLogContains()` - Check log content +- `assertConsoleWarningContains()` - Check warning content +- `assertConsoleErrorContains()` - Check error content +- `assertNoSmoke()` - No issues of any kind +- `assertNoSlowResources()` - Performance check +- `assertNoNetworkErrors()` - Network check + +Example usage: + ```php $page = visit('/') // Basic Console Assertions @@ -854,25 +951,8 @@ $page->visit('/js-heavy-page') }); ``` -Console Message Types: -1. `log` - General logging messages -2. `info` - Informational messages -3. `warning` - Warning messages -4. `error` - Error messages -5. `debug` - Debug messages - -Available Assertions: -- `assertNoConsoleErrors()` - No error messages -- `assertNoJavaScriptErrors()` - No JS exceptions -- `assertNoConsoleLogs()` - No console messages -- `assertConsoleLogContains()` - Check log content -- `assertConsoleWarningContains()` - Check warning content -- `assertConsoleErrorContains()` - Check error content -- `assertNoSmoke()` - No issues of any kind -- `assertNoSlowResources()` - Performance check -- `assertNoNetworkErrors()` - Network check - Best Practices: + 1. Clear console before critical assertions 2. Handle asynchronous console messages 3. Use specific assertions for message types @@ -880,22 +960,49 @@ Best Practices: 5. Monitor resource loading errors 6. Track performance issues 7. Handle expected console output -````` ### Element Assertions (MakesElementAssertions) +Element assertions allow you to verify the presence, visibility, and state of elements on the page. These assertions help ensure your page structure and content are correct. + +Available Element Assertions: + +- `assertVisible()` - Assert element is visible +- `assertHidden()` - Assert element is hidden +- `assertExists()` - Assert element exists in DOM +- `assertMissing()` - Assert element doesn't exist +- `assertValue()` - Assert input value matches +- `assertSelected()` - Assert option is selected +- `assertChecked()` - Assert checkbox is checked +- `assertNotChecked()` - Assert checkbox is not checked + +Example usage: + ```php $page = visit('/') - ->assertVisible('.element') - ->assertHidden('.hidden-element') - ->assertExists('#id') - ->assertMissing('.not-found') - ->assertValue('input[name="email"]', 'test@example.com') - ->assertSelected('select[name="country"]', 'USA') - ->assertChecked('#terms') - ->assertNotChecked('#newsletter'); + // Visibility assertions + ->assertVisible('.element') // Check if element is visible + ->assertHidden('.hidden-element') // Check if element is hidden + + // Existence assertions + ->assertExists('#id') // Check if element exists in DOM + ->assertMissing('.not-found') // Check if element doesn't exist + + // Form element assertions + ->assertValue('input[name="email"]', 'test@example.com') // Check input value + ->assertSelected('select[name="country"]', 'USA') // Check selected option + ->assertChecked('#terms') // Check if checked + ->assertNotChecked('#newsletter'); // Check if unchecked ``` +Best Practices: + +1. Use specific selectors to avoid ambiguity +2. Check both positive and negative cases +3. Verify form states after interactions +4. Consider async behavior when checking visibility +5. Test both initial and changed states + ### URL Assertions (MakesUrlAssertions) ```php @@ -1170,65 +1277,85 @@ $page->assertSee('Welcome, bot!');
-[assertTitle](#assert-title) -[assertTitleContains](#assert-title-contains) -[assertSee](#assert-see) -[assertDontSee](#assert-dont-see) -[assertSeeIn](#assert-see-in) -[assertDontSeeIn](#assert-dont-see-in) -[assertSeeAnythingIn](#assert-see-anything-in) -[assertSeeNothingIn](#assert-see-nothing-in) -[assertCount](#assert-count) -[assertScript](#assert-script) -[assertSourceHas](#assert-source-has) -[assertSourceMissing](#assert-source-missing) -[assertSeeLink](#assert-see-link) -[assertDontSeeLink](#assert-dont-see-link) -[assertChecked](#assert-checked) -[assertNotChecked](#assert-not-checked) -[assertIndeterminate](#assert-indeterminate) -[assertRadioSelected](#assert-radio-selected) -[assertRadioNotSelected](#assert-radio-not-selected) -[assertSelected](#assert-selected) -[assertNotSelected](#assert-not-selected) -[assertValue](#assert-value) -[assertValueIsNot](#assert-value-is-not) -[assertAttribute](#assert-attribute) -[assertAttributeMissing](#assert-attribute-missing) -[assertAttributeContains](#assert-attribute-contains) -[assertAttributeDoesntContain](#assert-attribute-doesnt-contain) -[assertAriaAttribute](#assert-aria-attribute) -[assertDataAttribute](#assert-data-attribute) -[assertVisible](#assert-visible) -[assertPresent](#assert-present) -[assertNotPresent](#assert-not-present) -[assertMissing](#assert-missing) -[assertEnabled](#assert-enabled) -[assertDisabled](#assert-disabled) -[assertButtonEnabled](#assert-button-enabled) -[assertButtonDisabled](#assert-button-disabled) -[assertUrlIs](#assert-url-is) -[assertSchemeIs](#assert-scheme-is) -[assertSchemeIsNot](#assert-scheme-is-not) -[assertHostIs](#assert-host-is) -[assertHostIsNot](#assert-host-is-not) -[assertPortIs](#assert-port-is) -[assertPortIsNot](#assert-port-is-not) -[assertPathBeginsWith](#assert-path-begins-with) -[assertPathEndsWith](#assert-path-ends-with) -[assertPathContains](#assert-path-contains) -[assertPathIs](#assert-path-is) -[assertPathIsNot](#assert-path-is-not) -[assertQueryStringHas](#assert-query-string-has) -[assertQueryStringMissing](#assert-query-string-missing) -[assertFragmentIs](#assert-fragment-is) -[assertFragmentBeginsWith](#assert-fragment-begins-with) -[assertFragmentIsNot](#assert-fragment-is-not) -[assertNoSmoke](#assert-no-smoke) -[assertNoConsoleLogs](#assert-no-console-logs) -[assertNoJavaScriptErrors](#assert-no-javascript-errors) -[assertNoAccessibilityIssues](#assert-no-accessibility-issues) -[assertScreenshotMatches](#assert-screenshot-matches) +Content Assertions: + +- [assertSee](#assert-see) - Assert text is visible on page +- [assertDontSee](#assert-dont-see) - Assert text is not visible on page +- [assertSeeIn](#assert-see-in) - Assert text is visible in selector +- [assertDontSeeIn](#assert-dont-see-in) - Assert text is not visible in selector +- [assertSeeAnythingIn](#assert-see-anything-in) - Assert any content in selector +- [assertSeeNothingIn](#assert-see-nothing-in) - Assert no content in selector +- [assertCount](#assert-count) - Assert element count matches + +Element Assertions: + +- [assertTitle](#assert-title) - Assert page title matches +- [assertTitleContains](#assert-title-contains) - Assert page title contains text +- [assertVisible](#assert-visible) - Assert element is visible +- [assertPresent](#assert-present) - Assert element exists in DOM +- [assertNotPresent](#assert-not-present) - Assert element doesn't exist +- [assertMissing](#assert-missing) - Assert element is not visible + +Form Assertions: + +- [assertValue](#assert-value) - Assert input value matches +- [assertValueIsNot](#assert-value-is-not) - Assert input value doesn't match +- [assertChecked](#assert-checked) - Assert checkbox is checked +- [assertNotChecked](#assert-not-checked) - Assert checkbox is not checked +- [assertIndeterminate](#assert-indeterminate) - Assert checkbox is indeterminate +- [assertRadioSelected](#assert-radio-selected) - Assert radio is selected +- [assertRadioNotSelected](#assert-radio-not-selected) - Assert radio not selected +- [assertSelected](#assert-selected) - Assert dropdown option selected +- [assertNotSelected](#assert-not-selected) - Assert option not selected +- [assertEnabled](#assert-enabled) - Assert field is enabled +- [assertDisabled](#assert-disabled) - Assert field is disabled +- [assertButtonEnabled](#assert-button-enabled) - Assert button enabled +- [assertButtonDisabled](#assert-button-disabled) - Assert button disabled + +URL Assertions: + +- [assertUrlIs](#assert-url-is) - Assert full URL matches +- [assertSchemeIs](#assert-scheme-is) - Assert URL scheme matches +- [assertSchemeIsNot](#assert-scheme-is-not) - Assert scheme doesn't match +- [assertHostIs](#assert-host-is) - Assert URL host matches +- [assertHostIsNot](#assert-host-is-not) - Assert host doesn't match +- [assertPortIs](#assert-port-is) - Assert URL port matches +- [assertPortIsNot](#assert-port-is-not) - Assert port doesn't match +- [assertPathIs](#assert-path-is) - Assert URL path matches +- [assertPathIsNot](#assert-path-is-not) - Assert path doesn't match +- [assertPathBeginsWith](#assert-path-begins-with) - Assert path starts with +- [assertPathEndsWith](#assert-path-ends-with) - Assert path ends with +- [assertPathContains](#assert-path-contains) - Assert path contains +- [assertQueryStringHas](#assert-query-string-has) - Assert query param exists +- [assertQueryStringMissing](#assert-query-string-missing) - Assert no query param +- [assertFragmentIs](#assert-fragment-is) - Assert URL fragment matches +- [assertFragmentBeginsWith](#assert-fragment-begins-with) - Assert fragment starts +- [assertFragmentIsNot](#assert-fragment-is-not) - Assert fragment doesn't match + +Source Assertions: + +- [assertScript](#assert-script) - Assert JS expression result +- [assertSourceHas](#assert-source-has) - Assert source contains code +- [assertSourceMissing](#assert-source-missing) - Assert source lacks code +- [assertSeeLink](#assert-see-link) - Assert link exists +- [assertDontSeeLink](#assert-dont-see-link) - Assert link doesn't exist + +Attribute Assertions: + +- [assertAttribute](#assert-attribute) - Assert attribute value matches +- [assertAttributeMissing](#assert-attribute-missing) - Assert no attribute +- [assertAttributeContains](#assert-attribute-contains) - Assert attribute contains +- [assertAttributeDoesntContain](#assert-attribute-doesnt-contain) - Assert not in attribute +- [assertAriaAttribute](#assert-aria-attribute) - Assert ARIA attribute +- [assertDataAttribute](#assert-data-attribute) - Assert data attribute + +Debug Assertions: + +- [assertNoSmoke](#assert-no-smoke) - Assert no console errors +- [assertNoConsoleLogs](#assert-no-console-logs) - Assert no console logs +- [assertNoJavaScriptErrors](#assert-no-javascript-errors) - Assert no JS errors +- [assertNoAccessibilityIssues](#assert-no-accessibility-issues) - Assert accessible +- [assertScreenshotMatches](#assert-screenshot-matches) - Assert visual match
@@ -1236,33 +1363,47 @@ $page->assertSee('Welcome, bot!');
-[click](#click) -[text](#text) -[attribute](#attribute) -[keys](#keys) -[withKeyDown](#withKeyDown) -[type](#type) -[typeSlowly](#type-slowly) -[select](#select) -[append](#append) -[clear](#clear) -[radio](#radio) -[check](#check) -[uncheck](#uncheck) -[attach](#attach) -[press](#press) -[pressAndWaitFor](#press-and-wait-for) -[drag](#drag) -[hover](#hover) -[submit](#submit) -[value](#value) -[withinIframe](#within-iframe) -[resize](#resize) -[script](#script) -[content](#content) -[url](#url) -[wait](#wait) -[waitForKey](#wait-for-key) +Mouse Interactions: + +- [click](#click) - Click an element +- [hover](#hover) - Hover over element +- [drag](#drag) - Drag and drop elements + +Form Interactions: + +- [type](#type) - Type text into input +- [typeSlowly](#type-slowly) - Type text with delay +- [select](#select) - Select dropdown option +- [append](#append) - Add text to existing input +- [clear](#clear) - Clear input field +- [radio](#radio) - Select radio button +- [check](#check) - Check checkbox +- [uncheck](#uncheck) - Uncheck checkbox +- [attach](#attach) - Upload file +- [submit](#submit) - Submit form + +Button/Key Interactions: + +- [press](#press) - Press a button +- [pressAndWaitFor](#press-and-wait-for) - Press and wait +- [keys](#keys) - Send keyboard input +- [withKeyDown](#withKeyDown) - Hold key while executing + +Element State: + +- [text](#text) - Get element text +- [attribute](#attribute) - Get element attribute +- [value](#value) - Get input value +- [withinIframe](#within-iframe) - Work with iframes + +Page Control: + +- [resize](#resize) - Resize browser window +- [script](#script) - Execute JavaScript +- [content](#content) - Get page content +- [url](#url) - Get current URL +- [wait](#wait) - Wait for duration +- [waitForKey](#wait-for-key) - Wait for keypress
@@ -1270,11 +1411,19 @@ $page->assertSee('Welcome, bot!');
-[debug](#debug) -[screenshot](#screenshot) -[screenshotElement](#screenshot-element) -[tinker](#tinker) -[headed](#headed) +Debugging Tools: + +- [debug](#debug) - Enable debugging mode +- [tinker](#tinker) - Interactive debugging session + +Screenshot Tools: + +- [screenshot](#screenshot) - Capture page screenshot +- [screenshotElement](#screenshot-element) - Capture element screenshot + +Browser Display: + +- [headed](#headed) - Show browser window while testing
@@ -2261,3 +2410,7 @@ However, if you are using GitHub Actions, you need to add the following steps to --- Now, let's dive into architectural testing and how it can benefit your development process. By performing architectural testing, you can evaluate the overall design of your application and identify potential flaws before they become significant issues: [Arch Testing](/docs/arch-testing) + +``` + +``` From 39d4362603dc8291657e2ce8c41bb329706e99b2 Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Fri, 24 Oct 2025 15:53:03 +0530 Subject: [PATCH 7/9] arch testing code block add --- browser-testing.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 14d9c8e..2d8a777 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -2409,8 +2409,13 @@ However, if you are using GitHub Actions, you need to add the following steps to --- -Now, let's dive into architectural testing and how it can benefit your development process. By performing architectural testing, you can evaluate the overall design of your application and identify potential flaws before they become significant issues: [Arch Testing](/docs/arch-testing) +Now, let's dive into architectural testing and how it can benefit your development process. By performing architectural testing, you can evaluate the overall design of your application and identify potential flaws before they become significant issues. -``` +See the full guide: [Arch Testing](/docs/arch-testing) + +Try it locally (macOS): +```bash +# Open the Arch Testing guide in your default editor / browser +open docs/arch-testing.md ``` From dba1f97714ff5fa23af22a30a73525ae2d29a1bd Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Fri, 24 Oct 2025 16:00:35 +0530 Subject: [PATCH 8/9] fix the instruction for next chapter --- browser-testing.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 2d8a777..89ffbb7 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -2409,13 +2409,8 @@ However, if you are using GitHub Actions, you need to add the following steps to --- -Now, let's dive into architectural testing and how it can benefit your development process. By performing architectural testing, you can evaluate the overall design of your application and identify potential flaws before they become significant issues. - -See the full guide: [Arch Testing](/docs/arch-testing) +--- -Try it locally (macOS): +In this section, you have learned how to perform browser testing with Pest, enabling you to verify your application's behavior in real browsers. From form interactions to network conditions, you now have the tools to ensure your web application works correctly across different browsers and devices. -```bash -# Open the Arch Testing guide in your default editor / browser -open docs/arch-testing.md -``` +Next, let's explore how you can ensure your application's architecture remains clean and maintainable through [Arch Testing](/docs/arch-testing). From 54ec24c3d92559a5f7d09597cdbac5a6456d867b Mon Sep 17 00:00:00 2001 From: sonali-dudhia Date: Fri, 24 Oct 2025 16:01:50 +0530 Subject: [PATCH 9/9] remove double line --- browser-testing.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/browser-testing.md b/browser-testing.md index 89ffbb7..1a00ff1 100644 --- a/browser-testing.md +++ b/browser-testing.md @@ -2409,8 +2409,6 @@ However, if you are using GitHub Actions, you need to add the following steps to --- ---- - In this section, you have learned how to perform browser testing with Pest, enabling you to verify your application's behavior in real browsers. From form interactions to network conditions, you now have the tools to ensure your web application works correctly across different browsers and devices. Next, let's explore how you can ensure your application's architecture remains clean and maintainable through [Arch Testing](/docs/arch-testing).