diff --git a/.github/workflows/tests.yml b/.github/workflows/test.yml similarity index 88% rename from .github/workflows/tests.yml rename to .github/workflows/test.yml index 8d96243..3a8f4f1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,8 @@ env: DRUPAL_TESTING_DATABASE_USER: root DRUPAL_TESTING_DATABASE_PASSWORD: root DRUPAL_TESTING_DATABASE_ENGINE: mysql - DRUPAL_TESTING_SELENIUM_CHROME_VERSION: '105.0' + DRUPAL_TESTING_SELENIUM_CHROME_VERSION: 'latest' + DRUPAL_TESTING_USE_SELENIUM: 'false' jobs: test-projects: @@ -24,11 +25,8 @@ jobs: RUN: [1, 2] include: - RUN: 1 - DRUPAL_TESTING_DRUPAL_VERSION: '~10.0' - PHP_VERSION: '8.1' - - RUN: 2 - DRUPAL_TESTING_DRUPAL_VERSION: '~10.0' - PHP_VERSION: '8.2' + DRUPAL_TESTING_DRUPAL_VERSION: '~11.3' + PHP_VERSION: '8.4' steps: - uses: actions/checkout@v1 @@ -44,7 +42,7 @@ jobs: sudo /etc/init.d/mysql start - name: Cache composer dependencies - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.composer/cache key: ${{ runner.os }}-composer-cache-${{ hashFiles('**/composer.json') }} @@ -74,7 +72,7 @@ jobs: - uses: shivammathur/setup-php@v2 with: coverage: none - php-version: '8.1' + php-version: '8.3' extensions: gd, pdo_mysql - name: Start MySql service @@ -82,7 +80,7 @@ jobs: sudo /etc/init.d/mysql start - name: Cache composer dependencies - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.composer/cache key: ${{ runner.os }}-composer-cache-${{ hashFiles('**/composer.json') }} @@ -90,7 +88,7 @@ jobs: - name: Cache NPM dependencies id: npm-cache - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-npm-cache @@ -110,7 +108,7 @@ jobs: run: cd /tmp; tar cfz build.tgz test; mv build.tgz ${GITHUB_WORKSPACE} - name: Upload build - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: build path: build.tgz @@ -126,7 +124,7 @@ jobs: - uses: shivammathur/setup-php@v2 with: coverage: none - php-version: '8.1' + php-version: '8.3' extensions: gd, pdo_mysql - name: Start MySql service @@ -139,9 +137,10 @@ jobs: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH - name: Download build - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v4 with: name: build + path: build - name: Unzip build artifact run: tar xCfz /tmp build/build.tgz test; rm -rf build diff --git a/composer.json b/composer.json index f3dbcda..d06c23a 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,7 @@ ], "require": { "php": ">=7.2", - "drupal/coder": "^8.3", - "symfony/yaml": "^3.4" + "drupal/coder": "^8.3" }, "config": { "allow-plugins": { diff --git a/configuration.sh b/configuration.sh index fb1c52d..1f00641 100644 --- a/configuration.sh +++ b/configuration.sh @@ -13,7 +13,8 @@ DRUPAL_TESTING_COMPOSER_PROJECT=${DRUPAL_TESTING_COMPOSER_PROJECT:-"drupal/recom # The drupal version to test against. This can be any valid composer version string, but only drupal versions greater 8.6 # are supported. By default, we use the most recent stable version. -DRUPAL_TESTING_DRUPAL_VERSION=${DRUPAL_TESTING_DRUPAL_VERSION:-$(git ls-remote --tags --sort=-version:refname https://github.com/drupal/core.git | grep -E -o '[0-9]+\.[0-9]\.[0-9]+$' | head -n1)} +_drupal_latest_core=$(git ls-remote --tags --sort=-version:refname https://github.com/drupal/core.git | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+$' | head -n1) +DRUPAL_TESTING_DRUPAL_VERSION=${DRUPAL_TESTING_DRUPAL_VERSION:-"~${_drupal_latest_core%.*}"} # The version of the composer project to use. DRUPAL_TESTING_COMPOSER_PROJECT_VERSION=${DRUPAL_TESTING_COMPOSER_PROJECT_VERSION:-${DRUPAL_TESTING_DRUPAL_VERSION}} @@ -190,7 +191,7 @@ export SYMFONY_DEPRECATIONS_HELPER=${SYMFONY_DEPRECATIONS_HELPER-weak} export SIMPLETEST_BASE_URL=${SIMPLETEST_BASE_URL:-http://${DRUPAL_TESTING_HTTP_HOST}:${DRUPAL_TESTING_HTTP_PORT}} # The driver args for webdriver. -export MINK_DRIVER_ARGS_WEBDRIVER=${MINK_DRIVER_ARGS_WEBDRIVER-"[\"chrome\", {\"chromeOptions\": {\"w3c\": false } }, \"http://${DRUPAL_TESTING_SELENIUM_HOST}:${DRUPAL_TESTING_SELENIUM_PORT}/wd/hub\"]"} +export MINK_DRIVER_ARGS_WEBDRIVER=${MINK_DRIVER_ARGS_WEBDRIVER-"[\"chrome\", {\"goog:chromeOptions\": {\"args\": [\"--headless\", \"--disable-gpu\", \"--no-sandbox\", \"--disable-dev-shm-usage\"]}}, \"http://${DRUPAL_TESTING_SELENIUM_HOST}:${DRUPAL_TESTING_SELENIUM_PORT}/wd/hub\"]"} # Increase composer memory limit. export COMPOSER_MEMORY_LIMIT=${COMPOSER_MEMORY_LIMIT:-"-1"} diff --git a/lib/stages/prepare_build.sh b/lib/stages/prepare_build.sh index efe902e..ab6bf34 100644 --- a/lib/stages/prepare_build.sh +++ b/lib/stages/prepare_build.sh @@ -15,6 +15,8 @@ _stage_prepare_build() { # Build is based on drupal project composer create-project "${DRUPAL_TESTING_COMPOSER_PROJECT}":"${DRUPAL_TESTING_COMPOSER_PROJECT_VERSION}" "${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" --no-interaction --no-install + # Disable blocking on security advisories — this is a CI test environment, not production. + composer config audit.block-insecure false --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" composer config "prefer-stable" true --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" if [[ ${DRUPAL_TESTING_PROJECT_TYPE} != "drupal-profile" ]]; then @@ -61,7 +63,7 @@ _stage_prepare_build() { composer config extra.enable-patching true --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" # Use jq to find all dev dependencies of the project and add them to root composer file. - for dev_dependency in $(jq -r '.["require-dev"?] | keys[] as $k | "\($k):\(.[$k])"' "${DRUPAL_TESTING_PROJECT_BASEDIR}"/composer.json); do + for dev_dependency in $(jq -r '(.["require-dev"?] // {}) | keys[] as $k | "\($k):\(.[$k])"' "${DRUPAL_TESTING_PROJECT_BASEDIR}"/composer.json); do composer require "${dev_dependency}" --dev --no-update --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" done diff --git a/lib/stages/prepare_old_install.sh b/lib/stages/prepare_old_install.sh index 3d7bfce..b8d57a7 100644 --- a/lib/stages/prepare_old_install.sh +++ b/lib/stages/prepare_old_install.sh @@ -23,6 +23,8 @@ _stage_prepare_old_install() { # Build is based on drupal project composer create-project "${DRUPAL_TESTING_COMPOSER_PROJECT}":"${DRUPAL_TESTING_UPGRADE_COMPOSER_PROJECT_VERSION}" "${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" --no-interaction --no-install + # Disable blocking on security advisories — this is a CI test environment, not production. + composer config audit.block-insecure false --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" composer config "prefer-stable" true --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" # Reorder repositories, to make sure, local path is first. diff --git a/lib/stages/prepare_upgrade.sh b/lib/stages/prepare_upgrade.sh index 2534210..860d91b 100644 --- a/lib/stages/prepare_upgrade.sh +++ b/lib/stages/prepare_upgrade.sh @@ -39,7 +39,7 @@ _stage_prepare_upgrade() { # Set the path repository back to the project under test. composer config repositories.0 --json "{\"type\":\"path\", \"url\":\"${DRUPAL_TESTING_PROJECT_BASEDIR}\", \"options\":{\"symlink\": false}}" --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" # Use jq to find all dev dependencies of the project and add them to root composer file. - for dev_dependency in $(jq -r '.["require-dev"?] | keys[] as $k | "\($k):\(.[$k])"' "${DRUPAL_TESTING_PROJECT_BASEDIR}"/composer.json); do + for dev_dependency in $(jq -r '(.["require-dev"?] // {}) | keys[] as $k | "\($k):\(.[$k])"' "${DRUPAL_TESTING_PROJECT_BASEDIR}"/composer.json); do composer require "${dev_dependency}" --dev --no-update --working-dir="${DRUPAL_TESTING_DRUPAL_INSTALLATION_DIRECTORY}" done diff --git a/lib/stages/start_services.sh b/lib/stages/start_services.sh index c454add..996bb2b 100644 --- a/lib/stages/start_services.sh +++ b/lib/stages/start_services.sh @@ -28,12 +28,27 @@ _stage_start_services() { if [ "${DRUPAL_TESTING_USE_SELENIUM}" = true ]; then docker run --detach --net host --name "${DRUPAL_TESTING_SELENIUM_DOCKER_NAME}" --volume "${DRUPAL_TESTING_PROJECT_BASEDIR}":/project --volume /dev/shm:/dev/shm selenium/standalone-chrome:"${DRUPAL_TESTING_SELENIUM_CHROME_VERSION}" + wait_for_port "${DRUPAL_TESTING_SELENIUM_HOST}" "${DRUPAL_TESTING_SELENIUM_PORT}" + # Wait for Selenium node to register — port open ≠ Chrome node ready. + local selenium_status_url="http://${DRUPAL_TESTING_SELENIUM_HOST}:${DRUPAL_TESTING_SELENIUM_PORT}/status" + local ready_count=0 + until curl -sf "${selenium_status_url}" | grep -q '"ready":true'; do + sleep 2 + ready_count=$((ready_count + 1)) + if [[ ${ready_count} -gt 15 ]]; then + printf "Error: Selenium node did not become ready in time.\n" 1>&2 + exit 1 + fi + done + elif command -v chromedriver > /dev/null 2>&1; then + # Use system ChromeDriver (pre-installed on GitHub Actions runners). + chromedriver --port="${DRUPAL_TESTING_SELENIUM_PORT}" --url-base=/wd/hub & + wait_for_port "${DRUPAL_TESTING_SELENIUM_HOST}" "${DRUPAL_TESTING_SELENIUM_PORT}" else download_chromedriver "${DRUPAL_TESTING_TEST_BASE_DIRECTORY}"/chromedriver --port="${DRUPAL_TESTING_SELENIUM_PORT}" --url-base=/wd/hub & + wait_for_port "${DRUPAL_TESTING_SELENIUM_HOST}" "${DRUPAL_TESTING_SELENIUM_PORT}" fi - - wait_for_port "${DRUPAL_TESTING_SELENIUM_HOST}" "${DRUPAL_TESTING_SELENIUM_PORT}" fi if ! port_is_open "${DRUPAL_TESTING_HTTP_HOST}" "${DRUPAL_TESTING_HTTP_PORT}"; then diff --git a/tests/module/module.info.yml b/tests/module/module.info.yml index 883a6f1..932ebf7 100644 --- a/tests/module/module.info.yml +++ b/tests/module/module.info.yml @@ -2,4 +2,4 @@ name: Module type: module description: Drupal module with all sorts of tests, to test capabilities of the drupal-testing package. package: Drupal Testing -core_version_requirement: ^9 || ^10 +core_version_requirement: ^9 || ^10 || ^11 diff --git a/tests/module/tests/FunctionalJavascript/ModuleControllerTest.php b/tests/module/tests/FunctionalJavascript/ModuleControllerTest.php index 982965d..cf7f5ba 100644 --- a/tests/module/tests/FunctionalJavascript/ModuleControllerTest.php +++ b/tests/module/tests/FunctionalJavascript/ModuleControllerTest.php @@ -3,14 +3,16 @@ namespace Drupal\Tests\module\FunctionalJavascript; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses; /** * Class ModuleControllerTest. * * Javascript tests. - * - * @group module */ +#[Group('module')] +#[RunTestsInSeparateProcesses] class ModuleControllerTest extends WebDriverTestBase { /** diff --git a/tests/module/tests/Unit/ModuleServiceTest.php b/tests/module/tests/Unit/ModuleServiceTest.php index 03b6b08..73ff5c3 100644 --- a/tests/module/tests/Unit/ModuleServiceTest.php +++ b/tests/module/tests/Unit/ModuleServiceTest.php @@ -4,11 +4,15 @@ use Drupal\module\Service; use Drupal\Tests\UnitTestCase; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; /** - * @coversDefaultClass \Drupal\module\Service - * @group module + * Tests for the Service class. */ +#[CoversClass(\Drupal\module\Service::class)] +#[Group('module')] class ModuleServiceTest extends UnitTestCase { /** * The entity permission provider. @@ -27,10 +31,9 @@ protected function setUp(): void { } /** - * @covers ::serve - * - * @dataProvider numberProvider + * Tests the serve method. */ + #[DataProvider('numberProvider')] public function testServe($number, $serving): void { $this->assertEquals($serving, $this->service->serve($number)); } @@ -41,7 +44,7 @@ public function testServe($number, $serving): void { * @return array * A list of number and the servings they generate. */ - public function numberProvider(): array { + public static function numberProvider(): array { return [ [1, 'You have been served a 1'], ];