Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .ahoy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ commands:
test-functional:
usage: Run PHPUnit functional tests.
cmd: ahoy cli vendor/bin/phpunit --testsuite=functional "$@"

test-functional-javascript:
aliases: [test-js]
usage: Run PHPUnit functional JavaScript tests.
cmd: ahoy cli vendor/bin/phpunit --testsuite=functional-javascript "$@"
#;> TOOL_PHPUNIT

#;< TOOL_BEHAT
Expand Down
5 changes: 1 addition & 4 deletions .docker/cli.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ ARG VORTEX_FRONTEND_BUILD_SKIP="0"
ENV VORTEX_FRONTEND_BUILD_SKIP=${VORTEX_FRONTEND_BUILD_SKIP}

ENV COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_CACHE_DIR=/tmp/.composer/cache \
SIMPLETEST_DB=mysql://drupal:drupal@database/drupal \
SIMPLETEST_BASE_URL=http://nginx:8080 \
SYMFONY_DEPRECATIONS_HELPER=disabled
COMPOSER_CACHE_DIR=/tmp/.composer/cache

# Allow custom PHP runtime configuration for Drush CLI commands.
# The leading colon appends to the default scan directories.
Expand Down
2 changes: 2 additions & 0 deletions .vortex/.ahoy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@ commands:

# If there are changes to the snapshots - this command will re-run twice reporting error the first time.
update-snapshots:
aliases: [us]
cmd: |
export XDEBUG_MODE=off
composer --working-dir=tests update-snapshots
composer --working-dir=installer update-snapshots

update-snapshots-install:
aliases: [usi]
cmd: |
ahoy install
ahoy update-snapshots
Expand Down
8 changes: 7 additions & 1 deletion .vortex/docs/content/development/phpunit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Test types supported:
1. **Unit tests** - Test isolated PHP classes without Drupal bootstrap
2. **Kernel tests** - Test with partial Drupal bootstrap (database, services)
3. **Functional tests** - Test with full Drupal bootstrap including browser simulation
4. **Functional JavaScript tests** - Test with full Drupal bootstrap and a real browser (Chrome via Selenium) for JavaScript interactions

## Running tests

Expand All @@ -35,6 +36,8 @@ import TabItem from '@theme/TabItem';
ahoy test-kernel
# Run only Functional tests
ahoy test-functional
# Run only Functional JavaScript tests
ahoy test-functional-javascript
# Run specific test file
ahoy test tests/phpunit/ExampleTest.php
# Run tests with filter
Expand All @@ -51,6 +54,8 @@ import TabItem from '@theme/TabItem';
docker compose exec cli vendor/bin/phpunit --testsuite=kernel
# Run only Functional tests
docker compose exec cli vendor/bin/phpunit --testsuite=functional
# Run only Functional JavaScript tests
docker compose exec cli vendor/bin/phpunit --testsuite=functional-javascript
# Run specific test file
docker compose exec cli vendor/bin/phpunit tests/phpunit/ExampleTest.php
# Run tests with filter
Expand All @@ -66,6 +71,7 @@ PHPUnit tests are organized into test suites defined in `phpunit.xml`:
- **unit** - Fast tests that don't require Drupal bootstrap
- **kernel** - Tests that need database and core services
- **functional** - Full browser simulation tests
- **functional-javascript** - Tests requiring a real browser with JavaScript support (Chrome via Selenium)

## Configuration

Expand Down Expand Up @@ -97,7 +103,7 @@ continuous integration to track test performance and stability.

## Boilerplate

**Vortex** provides Unit, Kernel and Functional tests boilerplate for custom [modules](https://github.com/drevops/vortex/blob/main/web/modules/custom/ys_base/tests/src),
**Vortex** provides Unit, Kernel, Functional and Functional JavaScript tests boilerplate for custom [modules](https://github.com/drevops/vortex/blob/main/web/modules/custom/ys_base/tests/src),
[themes](https://github.com/drevops/vortex/blob/main/web/themes/custom/your_site_theme/tests/src) and
[scripts](https://github.com/drevops/vortex/blob/main/tests/phpunit).

Expand Down
13 changes: 13 additions & 0 deletions .vortex/docs/content/tools/behat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ default:
- '%paths.base%/web/modules/custom/mymodule/tests/behat/features'
```

### Chrome session flags

The [`behat.yml`](https://github.com/drevops/vortex/blob/main/behat.yml)
configuration passes the following flags to Chrome via `goog:chromeOptions`
to ensure stable and deterministic test execution in the container environment:

| Flag | Purpose |
|----------------------------------|------------------------------------------------------------------|
| `--disable-extensions` | Prevents interference from browser extensions |
| `--disable-translate` | Prevents the translation bar from appearing on non-English pages |
| `--force-prefers-reduced-motion` | Disables CSS animations and transitions for test stability |
| `--test-type` | Suppresses error dialogs and crash recovery prompts |

### Contexts and extensions

The configuration uses the following contexts and extensions:
Expand Down
38 changes: 34 additions & 4 deletions .vortex/docs/content/tools/phpunit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ import TabItem from '@theme/TabItem';
ahoy test-unit # Run Unit tests.
ahoy test-kernel # Run Kernel tests.
ahoy test-functional # Run Functional tests.
ahoy test-functional-javascript # Run Functional JavaScript tests.
```
</TabItem>
<TabItem value="docker-compose" label="Docker Compose">
```shell
docker compose exec cli vendor/bin/phpunit # Run all tests.
docker compose exec cli vendor/bin/phpunit --testsuite=unit # Run Unit tests.
docker compose exec cli vendor/bin/phpunit --testsuite=kernel # Run Kernel tests.
docker compose exec cli vendor/bin/phpunit --testsuite=functional # Run Functional tests.
docker compose exec cli vendor/bin/phpunit # Run all tests.
docker compose exec cli vendor/bin/phpunit --testsuite=unit # Run Unit tests.
docker compose exec cli vendor/bin/phpunit --testsuite=kernel # Run Kernel tests.
docker compose exec cli vendor/bin/phpunit --testsuite=functional # Run Functional tests.
docker compose exec cli vendor/bin/phpunit --testsuite=functional-javascript # Run Functional JavaScript tests.
```
</TabItem>
</Tabs>
Expand Down Expand Up @@ -102,6 +104,34 @@ Run checks against platform version specified in `composer.json` key `config.pla
<config name="testVersion" value="8.1"/>
```

### Chrome session flags

Functional JavaScript tests use a Chrome browser running in the
[`selenium/standalone-chromium`](https://hub.docker.com/r/selenium/standalone-chromium)
container. The following flags are passed via `MINK_DRIVER_ARGS_WEBDRIVER`
in `phpunit.xml` to ensure stable and deterministic test execution:

| Flag | Purpose |
|----------------------------------|------------------------------------------------------------------|
| `--disable-extensions` | Prevents interference from browser extensions |
| `--disable-translate` | Prevents the translation bar from appearing on non-English pages |
| `--force-prefers-reduced-motion` | Disables CSS animations and transitions for test stability |
| `--test-type` | Suppresses error dialogs and crash recovery prompts |
| `--window-size=1920,1080` | Sets a deterministic viewport size for consistent screenshots |

The `w3c: true` option is required for compatibility with Selenium 4.

### Bootstrap

The custom [`tests/phpunit/bootstrap.php`](https://github.com/drevops/vortex/blob/main/tests/phpunit/bootstrap.php)
file runs before tests to:

1. Set `BROWSERTEST_OUTPUT_BASE_URL` from the `VORTEX_LOCALDEV_URL` environment
variable so that HTML output links are accessible from the host machine.
2. Create the `web/sites/simpletest/browser_output` directory required by the
`HtmlOutputLogger` extension before it initializes
(see [Drupal core issue #2992069](https://www.drupal.org/project/drupal/issues/2992069)).

## Coverage

PHPUnit is configured to generate code coverage reports. The reports are stored
Expand Down
4 changes: 3 additions & 1 deletion .vortex/docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
],
"words": [
"Asciinema",
"BROWSERTEST",
"Buildx",
"Diffy",
"GHSA",
Expand All @@ -19,8 +20,8 @@
"acquia",
"amazee",
"amazeeio",
"automations",
"apikey",
"automations",
"behat",
"bootstrappable",
"calver",
Expand Down Expand Up @@ -73,6 +74,7 @@
"runsheets",
"seckit",
"shellvar",
"simpletest",
"standardise",
"updatedb",
"uselagoon",
Expand Down
2 changes: 2 additions & 0 deletions .vortex/installer/src/Prompts/Handlers/Theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ protected function removeThemeConfigLines(string $tmpDir): void {
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/**/tests/src/Kernel</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/*/tests/src/Functional</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/**/tests/src/Functional</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/*/tests/src/FunctionalJavascript</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/**/tests/src/FunctionalJavascript</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory suffix="Test.php">web/themes/custom</directory>');
File::removeLineInFile($tmpDir . '/phpunit.xml', '<directory>web/themes/custom/*/node_modules</directory>');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ commands:
usage: Run PHPUnit functional tests.
cmd: ahoy cli vendor/bin/phpunit --testsuite=functional "$@"

test-functional-javascript:
aliases: [test-js]
usage: Run PHPUnit functional JavaScript tests.
cmd: ahoy cli vendor/bin/phpunit --testsuite=functional-javascript "$@"

test-bdd:
usage: Run BDD tests.
aliases: [test-behat]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ ARG VORTEX_FRONTEND_BUILD_SKIP="0"
ENV VORTEX_FRONTEND_BUILD_SKIP=${VORTEX_FRONTEND_BUILD_SKIP}

ENV COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_CACHE_DIR=/tmp/.composer/cache \
SIMPLETEST_DB=mysql://drupal:drupal@database/drupal \
SIMPLETEST_BASE_URL=http://nginx:8080 \
SYMFONY_DEPRECATIONS_HELPER=disabled
COMPOSER_CACHE_DIR=/tmp/.composer/cache

# Allow custom PHP runtime configuration for Drush CLI commands.
# The leading colon appends to the default scan directories.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,10 @@ default:
extra_capabilities:
'goog:chromeOptions':
args:
# Options to increase stability and speed.
- '--disable-extensions' # Disables all installed Chrome extensions. Useful in testing environments to avoid interference from extensions.
- '--disable-gpu' # Disables hardware acceleration required in containers and cloud-based instances (like CI runners) where GPU is not available.
- '--disable-infobars' # Hides the infobar that Chrome displays for various notifications, like warnings when opening multiple tabs.
- '--disable-popup-blocking' # Disables the popup blocker, allowing all popups to appear. Useful in testing scenarios where popups are expected.
- '--disable-translate' # Disables the built-in translation feature, preventing Chrome from offering to translate pages.
- '--force-prefers-reduced-motion' # Forces Chrome to respect prefers-reduced-motion CSS media query, disabling animations and transitions.
- '--no-first-run' # Skips the initial setup screen that Chrome typically shows when running for the first time.
- '--test-type' # Disables certain security features and UI components that are unnecessary for automated testing, making Chrome more suitable for test environments.
- '--disable-extensions' # Prevents interference from browser extensions.
- '--disable-translate' # Prevents the translation bar from appearing on non-English pages.
- '--force-prefers-reduced-motion' # Disables CSS animations and transitions for test stability.
- '--test-type' # Suppresses error dialogs and crash recovery prompts.

# Provides integration with Drupal APIs.
Drupal\DrupalExtension:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class MyClassTest extends UnitTestCase {
- **Unit** - `Drupal\Tests\UnitTestCase` - Testing isolated PHP classes
- **Kernel** - `Drupal\KernelTests\KernelTestBase` - Testing with database/services
- **Functional** - `Drupal\Tests\BrowserTestBase` - Testing with full browser
- **FunctionalJavascript** - `Drupal\FunctionalJavascriptTests\WebDriverTestBase` - Testing browser interaction with JavaScript

### Test data conventions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
bootstrap="web/core/tests/bootstrap.php"
bootstrap="tests/phpunit/bootstrap.php"
cacheResult="false"
colors="true"
displayDetailsOnPhpunitDeprecations="true"
Expand All @@ -31,38 +31,37 @@
<ini name="error_reporting" value="32767"/>
<!-- Do not limit the amount of memory tests take to run. -->
<ini name="memory_limit" value="-1"/>
<!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
<env name="SIMPLETEST_BASE_URL" value=""/>
<!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/database_name#table_prefix -->
<env name="SIMPLETEST_DB" value=""/>
<env name="SIMPLETEST_BASE_URL" value="http://nginx:8080"/>
<env name="SIMPLETEST_DB" value="mysql://drupal:drupal@database/drupal"/>
<!-- By default, browser tests will output links that use the base URL set
in SIMPLETEST_BASE_URL. However, if your SIMPLETEST_BASE_URL is an internal
path (such as may be the case in a virtual or Docker-based environment),
you can set the base URL used in the browser test output links to something
reachable from your host machine here. This will allow you to follow them
directly and view the output. -->
<env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/>
<!-- This is populated dynamically in tests/phpunit/bootstrap.php -->
<!-- <env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/> -->
<!-- The environment variable SYMFONY_DEPRECATIONS_HELPER is used to configure
the behavior of the deprecation tests.
Drupal core's testing framework is setting this variable to its defaults.
Projects with their own requirements need to manage this variable
explicitly.
the behavior of the deprecation tests.
Drupal core's testing framework is setting this variable to its defaults.
Projects with their own requirements need to manage this variable
explicitly.
-->
<!-- To disable deprecation testing completely uncomment the next line. -->
<!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/> -->
<!-- Deprecation errors can be selectively ignored by specifying a file of
regular expression patterns for exclusion.
Uncomment the line below to specify a custom deprecations ignore file.
NOTE: it may be required to specify the full path to the file to run tests
correctly.
regular expression patterns for exclusion.
Uncomment the line below to specify a custom deprecations ignore file.
NOTE: it may be required to specify the full path to the file to run tests
correctly.
-->
<!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="ignoreFile=.deprecation-ignore.txt"/> -->
<!-- Example for changing the driver class for mink tests MINK_DRIVER_CLASS value: 'Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver' -->
<env name="MINK_DRIVER_CLASS" value=""/>
<!-- Example for changing the driver args to mink tests MINK_DRIVER_ARGS value: '["http://127.0.0.1:8510"]' -->
<env name="MINK_DRIVER_ARGS" value=""/>
<!-- Example for changing the driver args to webdriver tests MINK_DRIVER_ARGS_WEBDRIVER value: '["chrome", { "goog:chromeOptions": { "w3c": false } }, "http://localhost:4444/wd/hub"]' For using the Firefox browser, replace "chrome" with "firefox" -->
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value=""/>
<!-- Driver args for webdriver tests. -->
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value='["chrome", {"goog:chromeOptions": {"w3c": true, "args": ["--disable-extensions", "--disable-translate", "--force-prefers-reduced-motion", "--test-type", "--window-size=1920,1080"]}}, "http://chrome:4444/wd/hub"]'/>
</php>
<testsuites>
<testsuite name="unit">
Expand All @@ -79,13 +78,10 @@
<directory>web/themes/custom/**/tests/src/Functional</directory>
</testsuite>

<!-- Not implemented. -->
<!-- See https://github.com/drevops/vortex/issues/820 -->
<!--
<testsuite name="functional-javascript">
<file>./tests/TestSuites/FunctionalJavascriptTestSuite.php</file>
<directory>web/modules/custom/**/tests/src/FunctionalJavascript</directory>
<directory>web/themes/custom/**/tests/src/FunctionalJavascript</directory>
</testsuite>
-->
</testsuites>

<logging>
Expand Down Expand Up @@ -124,4 +120,14 @@
<group>skipped</group>
</exclude>
</groups>
<extensions>
<!-- Functional tests HTML output logging.
Output directory is hardcoded in Drupal core's BrowserHtmlDebugTrait
to DRUPAL_ROOT/sites/simpletest/browser_output.
@see https://www.drupal.org/project/drupal/issues/2992069 -->
<bootstrap class="Drupal\TestTools\Extension\HtmlLogging\HtmlOutputLogger">
<parameter name="outputDirectory" value="web/sites/simpletest/browser_output"/>
<parameter name="verbose" value="true"/>
</bootstrap>
</extensions>
</phpunit>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/**
* @file
* PHPUnit bootstrap file.
*
* Prepares the environment for running PHPUnit tests.
*/

declare(strict_types=1);

// Set the browser test output base URL from the local development URL.
$localdev_url = getenv('VORTEX_LOCALDEV_URL');
if ($localdev_url) {
$base_url = str_starts_with($localdev_url, 'http') ? $localdev_url : 'http://' . $localdev_url;
putenv('BROWSERTEST_OUTPUT_BASE_URL=' . $base_url);
$_SERVER['BROWSERTEST_OUTPUT_BASE_URL'] = $base_url;
$_ENV['BROWSERTEST_OUTPUT_BASE_URL'] = $base_url;
}

// @see https://www.drupal.org/project/drupal/issues/2992069
$browser_output_dir = dirname(__DIR__, 2) . '/web/sites/simpletest/browser_output';
if (!is_dir($browser_output_dir)) {
mkdir($browser_output_dir, 0775, TRUE);
}

// Load the Drupal core test bootstrap.
require dirname(__DIR__, 2) . '/web/core/tests/bootstrap.php';
Loading