Skip to content

Feature/separate locale format #744

Feature/separate locale format

Feature/separate locale format #744

name: Playwright tests
concurrency:
group: wf-${{github.event.pull_request.number || github.sha}}-${{github.workflow}}
cancel-in-progress: true
on:
pull_request:
paths-ignore:
- 'apps/**/*.md'
merge_group:
workflow_dispatch:
env:
NX_SKIP_NX_CACHE: ${{ contains(github.event.pull_request.labels.*.name, 'skip-cache') && 'true' || 'false' }}
RUN_TESTS: true
jobs:
check-should-run:
name: Check if tests should run
runs-on: ubuntu-latest
outputs:
should-run: ${{ steps.check.outputs.should-run }}
styles-changed: ${{ steps.changes.outputs.styles }}
steps:
- uses: actions/checkout@v6
- name: Check RUN_TESTS flag
id: check
run: echo "should-run=${{ env.RUN_TESTS }}" >> $GITHUB_OUTPUT
- uses: dorny/paths-filter@v4
id: changes
with:
filters: |
styles:
- 'packages/devextreme-scss/scss/**'
- 'packages/devextreme-scss/icons/**'
- 'packages/devextreme-scss/images/**'
- 'packages/devextreme-scss/fonts/**'
- 'packages/devextreme/js/**/themes/**'
- 'e2e/playwright/helpers/accessibility/**'
build:
name: Build DevExtreme
needs: check-should-run
if: needs.check-should-run.outputs.should-run == 'true'
runs-on: devextreme-shr2
timeout-minutes: 15
steps:
- name: Get sources
uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version-file: '.node-version'
- uses: pnpm/action-setup@v6
with:
run_install: false
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-cache
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: actions/cache@v5
name: Setup nx cache
with:
path: |
.nx/cache
.nx/workspace-data/*.db
.nx/workspace-data/*.db-wal
.nx/workspace-data/*.db-shm
key: ${{ runner.os }}-nx-v2-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-nx-v2-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}-
${{ runner.os }}-nx-v2-${{ github.workflow }}-${{ github.job }}-
${{ runner.os }}-nx-v2-
- name: Build
shell: bash
env:
NODE_OPTIONS: --max-old-space-size=8192
run: |
pnpm exec nx build devextreme-scss
pnpm exec nx build devextreme -c testing
- name: Zip artifacts
working-directory: ./packages/devextreme
run: |
7z a -tzip -mx3 -mmt2 artifacts.zip artifacts ../devextreme-scss/scss/bundles
- name: Upload build artifacts
uses: actions/upload-artifact@v7
with:
name: devextreme-artifacts-playwright
path: ./packages/devextreme/artifacts.zip
retention-days: 1
determine-playwright-matrix:
runs-on: ubuntu-latest
name: Determine Playwright matrix
needs: check-should-run
if: needs.check-should-run.outputs.should-run == 'true'
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- name: Build matrix
id: matrix
run: |
base_matrix_start=$(cat <<'JSON'
[
{ "componentFolder": "accessibility", "name": "accessibility", "concurrency": 6 }
]
JSON
)
base_matrix_end=$(cat <<'JSON'
[
{ "componentFolder": "common", "name": "common", "concurrency": 3 },
{ "name": "generic", "theme": "generic.light", "concurrency": 2 },
{ "name": "material", "theme": "material.blue.light", "concurrency": 2 },
{ "name": "material - compact", "theme": "material.blue.light.compact", "concurrency": 2 },
{ "componentFolder": "cardView", "name": "cardView" },
{ "componentFolder": "dataGrid", "name": "dataGrid (1/4)", "indices": "1/4", "concurrency": 5 },
{ "componentFolder": "dataGrid", "name": "dataGrid (2/4)", "indices": "2/4", "concurrency": 5 },
{ "componentFolder": "dataGrid", "name": "dataGrid (3/4)", "indices": "3/4", "concurrency": 5 },
{ "componentFolder": "dataGrid", "name": "dataGrid (4/4)", "indices": "4/4", "concurrency": 5 },
{ "componentFolder": "editors", "name": "editors" },
{ "componentFolder": "navigation", "name": "navigation", "concurrency": 6 },
{ "componentFolder": "scheduler/common", "name": "scheduler / common (1/3)", "indices": "1/3", "concurrency": 6 },
{ "componentFolder": "scheduler/common", "name": "scheduler / common (2/3)", "indices": "2/3", "concurrency": 6 },
{ "componentFolder": "scheduler/common", "name": "scheduler / common (3/3)", "indices": "3/3", "concurrency": 6 },
{ "componentFolder": "scheduler/viewOffset", "name": "scheduler / viewOffset (1/2)", "indices": "1/2", "concurrency": 4 },
{ "componentFolder": "scheduler/viewOffset", "name": "scheduler / viewOffset (2/2)", "indices": "2/2", "concurrency": 4 },
{ "componentFolder": "scheduler/timezones", "name": "scheduler / timezones (Europe/Berlin)", "timezone": "Europe/Berlin" },
{ "componentFolder": "scheduler/timezones", "name": "scheduler / timezones (America/Los_Angeles)", "timezone": "America/Los_Angeles" }
]
JSON
)
style_dependent_matrix=$(cat <<'JSON'
[
{ "componentFolder": "accessibility", "name": "accessibility - fluent.dark", "theme": "fluent.blue.dark", "concurrency": 6 },
{ "componentFolder": "accessibility", "name": "accessibility - material.light", "theme": "material.blue.light", "concurrency": 6 },
{ "componentFolder": "accessibility", "name": "accessibility - material.dark", "theme": "material.blue.dark", "concurrency": 6 }
]
JSON
)
matrix=$(jq -c -n \
--argjson baseStart "$base_matrix_start" \
--argjson baseEnd "$base_matrix_end" \
--argjson styleDependent "$style_dependent_matrix" \
--arg stylesChanged "${{ needs.check-should-run.outputs.styles-changed }}" \
'{ include: ($baseStart + (if $stylesChanged == "true" then $styleDependent else [] end) + $baseEnd) }')
echo "matrix=$matrix" >> $GITHUB_OUTPUT
playwright:
name: ${{ matrix.name }}${{ !matrix.theme && ' - fluent' || '' }}
if: |
needs.check-should-run.outputs.should-run == 'true' &&
needs.determine-playwright-matrix.result == 'success' &&
needs.build.result == 'success'
needs: [check-should-run, build, determine-playwright-matrix]
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.determine-playwright-matrix.outputs.matrix) }}
runs-on: devextreme-shr2
timeout-minutes: 45
steps:
- name: Get sources
uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v8
with:
name: devextreme-artifacts-playwright
path: ./packages/devextreme
- name: Unpack artifacts
working-directory: ./packages/devextreme
run: 7z x artifacts.zip -aoa
- name: Setup Chrome
uses: ./.github/actions/setup-chrome
with:
chrome-version: '150.0.7871.181'
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version-file: '.node-version'
- uses: pnpm/action-setup@v6
with:
run_install: false
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache/restore@v5
name: Restore pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-cache
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Sanitize job name
if: ${{ always() }}
run: echo "JOB_NAME=$(echo "${{ matrix.name }}" | tr -c 'A-Za-z0-9._-' '-')" >> $GITHUB_ENV
- name: Run Playwright tests
working-directory: ./e2e/playwright
env:
NODE_OPTIONS: --max-old-space-size=8192
# The browser context takes the timezone, so the agent clock is left alone.
TIMEZONE: ${{ matrix.timezone }}
# The default blob name is built from the test paths only, so jobs that differ by theme or
# timezone alone would write the same zip and overwrite each other once merged.
PLAYWRIGHT_BLOB_OUTPUT_NAME: report-${{ env.JOB_NAME }}.zip
run: |
THEME="--theme ${{ matrix.theme || 'fluent.blue.light' }}"
[ "${{ matrix.componentFolder }}" != "" ] && COMPONENT_FOLDER="--componentFolder ${{ matrix.componentFolder }}"
[ "${{ matrix.indices }}" != "" ] && INDICES="--indices ${{ matrix.indices }}"
[ "${{ matrix.concurrency }}" != "" ] && CONCURRENCY="--concurrency ${{ matrix.concurrency }}"
all_args="$COMPONENT_FOLDER $CONCURRENCY $INDICES $THEME"
echo "$all_args"
pnpm run test $all_args
- name: Upload blob report
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: playwright-blob-${{ env.JOB_NAME }}
path: ${{ github.workspace }}/e2e/playwright/artifacts/blob-report
if-no-files-found: ignore
- name: Upload test traces and screenshot diffs
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: playwright-traces-${{ env.JOB_NAME }}
path: ${{ github.workspace }}/e2e/playwright/artifacts/test-results
if-no-files-found: ignore
merge-artifacts:
runs-on: ubuntu-latest
needs: [playwright]
if: ${{ always() }}
steps:
- name: Detect mergeable artifacts
id: mergeable-artifacts
uses: actions/github-script@v9
with:
script: |
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId,
per_page: 100,
});
const artifactGroups = {
blobs: /^playwright-blob-/,
traces: /^playwright-traces-/,
};
for (const [outputName, pattern] of Object.entries(artifactGroups)) {
const names = artifacts
.map((artifact) => artifact.name)
.filter((name) => pattern.test(name));
core.setOutput(outputName, names.length > 0 ? 'true' : 'false');
core.info(`${outputName}: ${names.length ? names.join(', ') : '(none)'}`);
}
- name: Get sources
if: steps.mergeable-artifacts.outputs.blobs == 'true'
uses: actions/checkout@v6
- name: Use Node.js
if: steps.mergeable-artifacts.outputs.blobs == 'true'
uses: actions/setup-node@v6
with:
node-version-file: '.node-version'
- uses: pnpm/action-setup@v6
if: steps.mergeable-artifacts.outputs.blobs == 'true'
with:
run_install: false
- name: Install dependencies
if: steps.mergeable-artifacts.outputs.blobs == 'true'
run: pnpm install --frozen-lockfile
- name: Download blob reports
if: steps.mergeable-artifacts.outputs.blobs == 'true'
uses: actions/download-artifact@v7
with:
pattern: playwright-blob-*
path: ${{ github.workspace }}/blob-reports
merge-multiple: true
- name: Merge blob reports into one report
if: steps.mergeable-artifacts.outputs.blobs == 'true'
working-directory: ./e2e/playwright
env:
PLAYWRIGHT_HTML_OUTPUT_DIR: ${{ github.workspace }}/playwright-report
run: pnpm exec playwright merge-reports --reporter html ${{ github.workspace }}/blob-reports
- name: Upload merged report
if: steps.mergeable-artifacts.outputs.blobs == 'true'
uses: actions/upload-artifact@v7
with:
name: playwright-report
path: ${{ github.workspace }}/playwright-report
if-no-files-found: error
- name: Merge test traces
if: steps.mergeable-artifacts.outputs.traces == 'true'
uses: actions/upload-artifact/merge@v7
continue-on-error: true
with:
name: playwright-traces
pattern: playwright-traces-*
separate-directories: true
delete-merged: true