#file: noinspection YAMLSchemaValidation
version: '3'
tasks:
  run:
    desc: "Runs playwright functional tests."
    summary: |
      Runs Playwright tests.
        - shard=x/y: Run a fraction of tests. Optional.
    cmds:
      - task: install
      - |
        cd test/playwright
        npx playwright test --shard={{ default "1/1" .shard }}
        STATUS=$?
        echo "System uptime and load average statistics:"; uptime
        echo "If the load average is significantly different than **$(cat /proc/cpuinfo | grep processor | wc -l)** there may be too many or two few Playwright workers assigned. You might want to tweak the number of workers or shards."
        exit $STATUS

  install:
    desc: "Install a base copy of the site for testing."
    summary: |
      This installs Drupal using sqlite. This allows for each test case to
      start with a fixed installation state, with significantly improved
      performance compared to mariadb / mysql. This command should be run
      any time configuration has changed that would change the installed site
      state.
    cmds:
      - |
        # This environment variable tells Drupal to alter the database settings
        # in settings.php.
        export PLAYWRIGHT_SETUP=1
        set +e
        task --dry playwright:install:hook 2>/dev/null 1>/dev/null
        if [[ $? -eq 200 ]]; then
          echo "Task playwright:install:hook does not exist. Running drush site:install --yes demo_umami..."
          drush site:install --yes --site-name Playwright demo_umami
        else
          task playwright:install:hook
        fi

  prepare:
    desc: "Copy a database in preparation for a test run."
    summary: |
      This copies a database created with playwright:install to a now location.

      task playwright:prepare test_id=456

      will import the database into `web/sites/simpletest/456/.ht.sqlite`.
    preconditions:
      - sh: test -f /tmp/sqlite/.ht.sqlite
        msg: 'playwright:install needs to be run before tests can run.'
    cmds:
      - |
        export PLAYWRIGHT_SETUP=1

        # Recreate the sites directory.
        rm -rf web/sites/simpletest/{{ shellQuote .test_id }}/
        mkdir -p web/sites/simpletest/{{ shellQuote .test_id }}/
        mkdir -p /tmp/sqlite/{{ shellQuote .test_id }}/

        # On locals, copying in only the files we need (and not all assets
        # downloaded via stage file proxy) saves several seconds.

        # Copy in settings.php and our services files.
        cp -a web/sites/default/*.php web/sites/simpletest/{{ shellQuote .test_id }}/
        cp -a web/sites/default/*.yml web/sites/simpletest/{{ shellQuote .test_id }}/

        # Copy the database.
        cp -a /tmp/sqlite/.ht.sqlite /tmp/sqlite/{{ shellQuote .test_id }}/

        # Get a user agent based on the test ID. We need to convert colons to
        # URL-escaped characters.
        UA=$(drush ev 'echo drupal_generate_test_ua("test{{ shellQuote .test_id }}");' | sed 's/:/%3A/g')

        # Make sure we can load a page before running any tests.
        # These steps are slow, adding a second or more to each test preparation
        # step. However, these steps would also be run on a first page load by a
        # test, so we may as well add this early check to make sure the test
        # site is working.
        curl -s -k -b SIMPLETEST_USER_AGENT=$UA $DDEV_PRIMARY_URL/core/rebuild.php > /dev/null
        STATUS=$(curl -s -k -b SIMPLETEST_USER_AGENT=$UA -w "%{http_code}\n" -o /dev/null $DDEV_PRIMARY_URL)
        if [[ $STATUS != "200" ]]; then
          (echo "The test site {{ shellQuote .test_id }} is not working as it returned HTTP status $STATUS.";
          echo "Likely your code changes are causing an exception to be thrown.";
          echo "Test by reinstalling the base site and ensuring the home page loads.";) >&2
          exit 1
        fi

        set +e
        task --dry playwright:prepare:hook 2>/dev/null 1>/dev/null
        if [[ $? -ne 200 ]]; then
          set -e
          task playwright:prepare:hook test_id={{ shellQuote .test_id }}
        fi

  ua:
    desc: Return the cookie value for a given test ID.
    summary: |
      Playwright tests need to know the cookie value to use to tell Drupal to
      use a specific test prefix. It turns out this is a single global function
      function, so we haven't gone to the trouble of writing a full Drush
      command for it.

      This command will only ever output the direct cookie value unless there
      is an error. The cookie value will have colons replaced with %3A.
    cmds:
      - PLAYWRIGHT_SETUP=1 drush ev 'echo drupal_generate_test_ua("test{{ shellQuote .test_id }}");' | sed 's/:/%3A/g'

  cleanup:
    desc: Clean up after a test run.
    summary: |
      Deletes databases and simpletest/* files directories after a test successfully completes.
    cmds:
      - |
        # Delete the files and settings directories.
        # Fast tests that do not require a full page render may finish before Drupal
        # has fully written files like aggregated JavaScript to disk.
        while [ -d web/sites/simpletest/{{ shellQuote .test_id }}/ ]; do
          rm -rf web/sites/simpletest/{{ shellQuote .test_id }}/ 2>/dev/null || true
        done;

        # Delete the database.
        rm -rf /tmp/sqlite/{{ shellQuote .test_id }}/

        set +e
        task --dry playwright:cleanup:hook test_id={{ shellQuote .test_id }} 2>/dev/null 1>/dev/null
        # 200 is the exit code when a task doesn't exist.
        if [[ $? -ne 200 ]]; then
          set -e
          task playwright:cleanup:hook test_id={{ shellQuote .test_id }}
        fi;

  visualdiff:
    desc: Runs only visual diff tests
    deps:
      - install
    cmds:
      - |
        cd test/playwright

        # First capture all tests that have snapshots.
        TESTS=$(find . -name '*-snapshots' -type d | sed 's/-snapshots//' | sed 's/\.\///')

        # Run just tests with snapshots.
        echo $TESTS | xargs npx playwright test

  regenerate:
    desc: Regenerates all Playwright snapshots, deleting existing ones by default
    summary: |
      This task deletes all files listed in the -snapshots directories in each
      Playwright test. Then, it reruns tests with the --update-snapshots
      argument.
        - delete=<0,1>: Set to 0 to not delete existing snapshots. Useful
                        when snapshot filenames should not change. Optional.

      Examples:
        Do not delete snapshots when regenerating.
        - task playwright:regenerate delete=0
    deps:
      - playwright:install
    vars:
      delete: '{{ default "1" .delete }}'
    cmds:
      - |
        cd test/playwright
        # First capture all tests that have snapshots.
        TESTS=$(find . -name '*-snapshots' -type d | sed 's/-snapshots//' | sed 's/\.\///')

        # Remove snapshot files, but keep the directories. That way if tests
        # fail and this is rerun, we know what tests should have snapshots.
        if [[ {{ .delete }} -eq 1 ]]; then
          find . -name '*-snapshots' -type d | xargs -I {} -n1 /bin/sh -c 'rm -rf {}/*'
        fi

        # Run just tests with snapshots.
        echo $TESTS | xargs npx playwright test --update-snapshots --retries 3
        echo "From your host, run the following from the project directory to add all changes to commit."
        echo "Be sure to review for unexpected changes, and don't be surprised if modified tests cause"
        echo "files to be renamed."
        echo ""
        echo "find test/playwright -name '*-snapshots' -type d | xargs git add -A"
        echo ""
        echo "Some images may show minor variations, especially with the position of Drupal's admin"
        echo "toolbar. Typically those variations are handled automatically by Playwright's retry"
        echo "settings. Consider reverting those changes to avoid extra repository growth."

