diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ddbade5e..ea5806bff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,16 +6,17 @@ on: name: CI env: SYMFONY_DEPRECATIONS_HELPER: disabled - SIMPLETEST_BASE_URL: http://app:8888 + COMPOSER_DISCARD_CHANGES: true + COMPOSER_MIRROR_PATH_REPOS: 1 jobs: tests: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['8.1', '8.2', '8.3'] + php-versions: ['8.3'] container: - image: ghcr.io/city-of-helsinki/drupal-php-docker:${{ matrix.php-versions }}-alpine - options: --hostname app + image: ghcr.io/city-of-helsinki/drupal-web:${{ matrix.php-versions }}-dev + options: --hostname app --user 1001 services: db: image: mysql:8 @@ -26,6 +27,15 @@ jobs: MYSQL_ROOT_PASSWORD: drupal ports: - 3306:3306 + chromium: + image: selenium/standalone-chromium + env: + SE_NODE_OVERRIDE_MAX_SESSIONS: "true" + SE_NODE_MAX_SESSIONS: "16" + SE_START_XVFB: "false" + SE_START_VNC: "false" + SE_SESSION_RETRY_INTERVAL: "1" + SE_SESSION_REQUEST_TIMEOUT: "10" steps: - uses: actions/checkout@v4 @@ -38,6 +48,13 @@ jobs: - name: Set Drupal root run: echo "DRUPAL_ROOT=$HOME/drupal" >> $GITHUB_ENV + # Actions worker overrides the default entrypoint with "tail -f /dev/null", so + # we have to start services manually. + - name: Start services + env: + WEBROOT: ${{ env.DRUPAL_ROOT }}/public + run: entrypoint & + - name: Set module folder run: | echo "MODULE_FOLDER=$DRUPAL_ROOT/public/modules/contrib/$MODULE_NAME" >> $GITHUB_ENV @@ -48,23 +65,17 @@ jobs: git clone --depth=1 https://github.com/City-of-Helsinki/drupal-helfi-platform.git $DRUPAL_ROOT rm -rf $DRUPAL_ROOT/.git + # We use COMPOSER_MIRROR_PATH_REPOS=1 to mirror local repository + # instead of symlinking it to prevent code coverage issues with + # phpunit. Copy .git folder manually so codecov can generate line by + # line coverage. - name: Install required composer dependencies working-directory: ${{ env.DRUPAL_ROOT }} run: | composer config repositories.5 path $GITHUB_WORKSPACE composer require drupal/$MODULE_NAME -W - # We use COMPOSER_MIRROR_PATH_REPOS=1 to mirror local repository - # instead of symlinking it to prevent code coverage issues with - # phpunit. Copy .git folder manually so codecov can generate line by - # line coverage. cp -r $GITHUB_WORKSPACE/.git $MODULE_FOLDER/ - - name: Install Drupal - working-directory: ${{ env.DRUPAL_ROOT }} - run: | - php -d sendmail_path=$(which true); vendor/bin/drush --yes -v site-install minimal --db-url="$SIMPLETEST_DB" - vendor/bin/drush en $MODULE_NAME helfi_platform_config_base -y - - name: Run PHPCS working-directory: ${{ env.DRUPAL_ROOT }} run: vendor/bin/phpcs $MODULE_FOLDER --standard=$MODULE_FOLDER/phpcs.xml --extensions=php,module,inc,install,test,info @@ -73,9 +84,11 @@ jobs: working-directory: ${{ env.DRUPAL_ROOT }} run: vendor/bin/phpstan analyze -c $MODULE_FOLDER/phpstan.neon $MODULE_FOLDER - - name: Start services + - name: Install Drupal working-directory: ${{ env.DRUPAL_ROOT }} - run: vendor/bin/drush runserver $SIMPLETEST_BASE_URL --dns & + run: | + php -d sendmail_path=$(which true); vendor/bin/drush --yes -v site-install minimal --db-url="$SIMPLETEST_DB" + vendor/bin/drush en $MODULE_NAME helfi_platform_config_base -y - name: Run PHPUnit tests working-directory: ${{ env.DRUPAL_ROOT }} @@ -86,9 +99,12 @@ jobs: --coverage-clover=$MODULE_FOLDER/coverage.xml \ $MODULE_FOLDER - - name: Run codecov - working-directory: ${{ env.MODULE_FOLDER }} - run: codecov + - uses: codecov/codecov-action@v5 + with: + fail_ci_if_error: true + directory: ${{ env.MODULE_FOLDER }} + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true - name: Create an artifact from test report uses: actions/upload-artifact@v4 diff --git a/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.info.yml b/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.info.yml new file mode 100644 index 000000000..7fd1aa085 --- /dev/null +++ b/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.info.yml @@ -0,0 +1,4 @@ +name: 'HDBT cookie banner test module' +type: module +package: Custom +core_version_requirement: ^10 || ^11 diff --git a/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.module b/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.module new file mode 100644 index 000000000..18b44ab4a --- /dev/null +++ b/modules/hdbt_cookie_banner/tests/modules/hdbt_cookie_banner_test/hdbt_cookie_banner_test.module @@ -0,0 +1,18 @@ + 'inline_template', + '#template' => '

Test Content

', + ]; + } + +} diff --git a/modules/hdbt_cookie_banner/tests/src/FunctionalJavascript/CookieBannerTest.php b/modules/hdbt_cookie_banner/tests/src/FunctionalJavascript/CookieBannerTest.php new file mode 100644 index 000000000..da5781cad --- /dev/null +++ b/modules/hdbt_cookie_banner/tests/src/FunctionalJavascript/CookieBannerTest.php @@ -0,0 +1,158 @@ +getPath('hdbt_cookie_banner'); + $json_file_path = $module_path . '/assets/json/siteSettingsTemplate.json'; + + // Assert the file exists. + $this->assertTrue(file_exists($json_file_path)); + + // Load and decode the JSON. + $json_content = file_get_contents($json_file_path); + $this->assertNotEmpty($json_content, 'Decoded JSON data is not empty.'); + + // Get the public base URL (in a FunctionalJavascript test). + // Construct a URL for the hds-cookie-consent.min.js file. + $cookie_js_url = "/$module_path/assets/js/hds-cookie-consent.min.js"; + + // Change configuration value before the test runs. + $config = $this->config('hdbt_cookie_banner.settings'); + $config + ->set('use_custom_settings', TRUE) + ->set('site_settings', $json_content) + ->set('use_internal_hds_cookie_js', FALSE) + ->set('hds_cookie_js_override', $cookie_js_url) + ->save(); + + \Drupal::service('cache.default')->deleteAll(); + } + + /** + * Tests the cookie banner visibility and interaction. + */ + public function testCookieBanner() { + $this->drupalGet('/test-page'); + $this->assertSession()->pageTextContains('Test Content'); + $this->assertSession()->elementExists('css', '.test-footer'); + + // Get the web driver. + $driver = $this->getSession()->getDriver(); + + // Check if the driver is an instance of DrupalSelenium2Driver. + if ($driver instanceof Selenium2Driver) { + // Get all cookies from the browser. + $cookies = $driver->getWebDriverSession()->getCookie(); + + // Extract only the 'name' keys from all the cookies, as we want to check + // if a specific cookie "change-me" exists. + $cookieNames = array_column($cookies, 'name'); + $this->assertNotContains( + 'change-me', + $cookieNames, + 'The cookie "change-me" was found, but it should not exist.', + ); + } + else { + $this->fail('The driver is not an instance of Selenium2Driver.'); + } + + // Assert that the cookie banner is visible and click the accept button. + $this->assertCookieBannerIsVisible(); + + // Get the new cookies from the browser. + $new_cookies = $driver->getWebDriverSession()->getCookie(); + + // There should be a new cookie called "change-me". + $cookieNames = array_column($new_cookies, 'name'); + $this->assertContains( + 'change-me', + $cookieNames, + 'The cookie "change-me" was not found after clicking the button.', + ); + + // Reload the page and assert that the cookie banner is not visible. + $this->drupalGet('/test-page'); + $this->assertSession()->pageTextContains('Test Content'); + $this->assertCookieBannerNotVisible(); + } + + /** + * Asserts that the cookie banner is visible. + */ + protected function assertCookieBannerIsVisible() { + // Get the Shadow DOM host and button selectors. + $shadowHostSelector = '.hds-cc__target'; + $buttonSelector = '.hds-cc__all-cookies-button'; + + // Verify that the cookie banner is visible and click the accept button. + $js = <<getSession()->executeScript($js); + } + + /** + * Asserts that the cookie banner is not visible. + */ + protected function assertCookieBannerNotVisible() { + // Get the Shadow DOM host and button selectors. + $shadowHostSelector = '.hds-cc__target'; + + // Verify that the cookie banner is not visible. + $js = <<getSession()->executeScript($js); + } + +} diff --git a/phpunit.xml b/phpunit.xml index 562c1070b..f888cd7ac 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -17,11 +17,10 @@ - - - + + - +