name: Tests
on: [push, pull_request]
jobs:
  testing:
    name: PHP ${{ matrix.php-versions }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
        extra-tests: ['0']
        # We only need to run PHPStan and Drupal core regression tests once on
        # the latest PHP version.
        include:
          - php-versions: '8.4'
            extra-tests: '1'
    steps:
      - name: Checkout Coder
        uses: actions/checkout@v4

      - name: Setup PHP, with composer and extensions
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-versions }}
          extensions: mbstring
          # Disable Xdebug for better performance.
          coverage: none

      - name: Get composer cache directory
        id: composercache
        run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

      - name: Cache composer dependencies
        uses: actions/cache@v4
        with:
          path: ${{ steps.composercache.outputs.dir }}
          # Use composer.json for key, if composer.lock is not committed.
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
          restore-keys: ${{ runner.os }}-composer-

      - name: Install Composer dependencies
        # Running composer install without a lock file will also update cached
        # dependencies in vendor.
        run: composer install --no-progress --prefer-dist --optimize-autoloader

      - name: Run PHPUnit
        run: ./vendor/bin/phpunit

      - name: Run PHPCS
        run: ./vendor/bin/phpcs

      - name: Check custom standard autoloading
        # Ensure that a custom standard can be invoked and the auto-loading of
        # abstract classes works.
        # Ensure that the DrupalPractice standard can be invoked standalone and the
        # auto-loading of abstract classes works.
        run: |
          ./vendor/bin/phpcs -p --standard=tests/Drupal/phpcs-ruleset.xml tests/Drupal/good/ --ignore=tests/Drupal/good/GoodUnitTest.php
          ./vendor/bin/phpcs -p --standard=coder_sniffer/DrupalPractice tests/DrupalPractice/good/ --ignore=tests/DrupalPractice/good/GoodUnitTest.php

      - name: Run PHPStan
        if: ${{ matrix.extra-tests == '1' }}
        run: ./vendor/bin/phpstan analyse

      - name: Run Cspell
        if: ${{ matrix.extra-tests == '1' }}
        uses: streetsidesoftware/cspell-action@v7
        with:
          incremental_files_only: false

      - name: Checkout Drupal core
        if: ${{ matrix.extra-tests == '1' }}
        uses: actions/checkout@v3
        with:
          repository: drupal/drupal
          ref: "11.x"
          path: drupal

      - name: Run PHPCS on Drupal core for regressions
        if: ${{ matrix.extra-tests == '1' }}
        # In case Drupal core files have known problems that should be
        # ignored temporarily, add them with the --ignore option.
        run: |
          cd drupal/core
          ../../vendor/bin/phpcs -p -s --parallel=$(nproc)
