diff --git a/.changeset/poor-ducks-mate.md b/.changeset/poor-ducks-mate.md new file mode 100644 index 00000000000..38e55a6d52c --- /dev/null +++ b/.changeset/poor-ducks-mate.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Add manual test run for e2e diff --git a/.github/actions/merge-pw-reports/action.yml b/.github/actions/merge-pw-reports/action.yml new file mode 100644 index 00000000000..73c621820e5 --- /dev/null +++ b/.github/actions/merge-pw-reports/action.yml @@ -0,0 +1,30 @@ +name: Merge playwright reports +description: Merge reports from all shards + +runs: + using: "composite" + steps: + - uses: actions/setup-node@v3 + with: + node-version-file: ".nvmrc" + + - name: Install dependencies + shell: bash + run: npm ci + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v3 + with: + name: all-blob-reports + path: all-blob-reports + + - name: Merge into HTML Report + shell: bash + run: npx playwright merge-reports --reporter html ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v3 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 \ No newline at end of file diff --git a/.github/actions/prepare-api-variables/action.yml b/.github/actions/prepare-api-variables/action.yml new file mode 100644 index 00000000000..9516b09bdfb --- /dev/null +++ b/.github/actions/prepare-api-variables/action.yml @@ -0,0 +1,77 @@ +name: Prepare api variables +description: Prepare env config for cloud + +inputs: + MODE: + description: "The mode of running tests (pull-request, release, main)" + required: true + +outputs: + BASE_URL: + description: "Dashboard base url" + value: ${{ steps.generate.outputs.BASE_URL }} + API_URL: + description: "API url" + value: ${{ steps.generate.outputs.API_URL }} + BASE_URL_DOMAIN: + description: "Dashboard domain" + value: ${{ steps.generate.outputs.BASE_URL_DOMAIN }} + POOL_NAME: + description: "The name of the instance" + value: ${{ steps.generate.outputs.POOL_NAME }} + POOL_INSTANCE: + description: "The full URL of the instance" + value: ${{ steps.generate.outputs.POOL_INSTANCE }} + BACKUP_NAMESPACE: + description: "The backup namespace" + value: ${{ steps.generate.outputs.BACKUP_NAMESPACE }} + +runs: + using: "composite" + steps: + - name: Generate + id: generate + shell: bash + env: + MODE: ${{ inputs.MODE }} + PULL_REQUEST_NUMBER: ${{ github.event.number }} + PREFIX: pr- + run: | + if [[ "$MODE" == 'pull-request' ]]; then + echo "BASE_URL=https://${PREFIX}${PULL_REQUEST_NUMBER}.dashboard.saleor.rocks" >> $GITHUB_OUTPUT + echo "API_URL=https://${PREFIX}${PULL_REQUEST_NUMBER}.staging.saleor.cloud/graphql/" >> $GITHUB_OUTPUT + echo "BASE_URL_DOMAIN=${PREFIX}${PULL_REQUEST_NUMBER}.dashboard.saleor.rocks" >> $GITHUB_OUTPUT + echo "POOL_NAME=${PREFIX}${PULL_REQUEST_NUMBER}" >> $GITHUB_OUTPUT + echo "POOL_INSTANCE=https://${PREFIX}${PULL_REQUEST_NUMBER}.staging.saleor.cloud" >> $GITHUB_OUTPUT + echo "BACKUP_NAMESPACE=snapshot-automation-tests" >> $GITHUB_OUTPUT + + exit 0 + fi + + if [[ "$MODE" == 'release' ]]; then + CURRENT_BRANCH=$(echo "${GITHUB_REF}" | sed "s/refs\/heads\///") + VERSION_SLUG=$(echo "${CURRENT_BRANCH}" | sed "s/\.//") + + echo "BASE_URL=https://v${VERSION_SLUG}.staging.saleor.cloud/dashboard/" >> $GITHUB_OUTPUT + echo "API_URL=https://v${VERSION_SLUG}.staging.saleor.cloud/graphql/" >> $GITHUB_OUTPUT + echo "BASE_URL_DOMAIN=v${VERSION_SLUG}.staging.saleor.cloud" >> $GITHUB_OUTPUT + echo "POOL_NAME=${CURRENT_BRANCH} Staging" >> $GITHUB_OUTPUT + echo "POOL_INSTANCE=https://v${VERSION_SLUG}.staging.saleor.cloud/" >> $GITHUB_OUTPUT + echo "BACKUP_NAMESPACE=snapshot-automation-tests-${CURRENT_BRANCH}" >> $GITHUB_OUTPUT + + exit 0 + fi + + if [[ "$MODE" == 'main' ]]; then + echo "BASE_URL=https://automation-dashboard.staging.saleor.cloud/dashboard/" >> $GITHUB_OUTPUT + echo "API_URL=https://automation-dashboard.staging.saleor.cloud/graphql/" >> $GITHUB_OUTPUT + echo "BASE_URL_DOMAIN=automation-dashboard.staging.saleor.cloud" >> $GITHUB_OUTPUT + echo "POOL_NAME=automation-dashboard" >> $GITHUB_OUTPUT + echo "POOL_INSTANCE=https://automation-dashboard.staging.saleor.cloud" >> $GITHUB_OUTPUT + echo "BACKUP_NAMESPACE=snapshot-automation-tests" >> $GITHUB_OUTPUT + + exit 0 + fi + + echo "Unknown mode: $MODE" >&2 + exit 1 diff --git a/.github/actions/prepare-backups-variables/action.yml b/.github/actions/prepare-backups-variables/action.yml new file mode 100644 index 00000000000..9ef536dc497 --- /dev/null +++ b/.github/actions/prepare-backups-variables/action.yml @@ -0,0 +1,41 @@ +name: Prepare backup variables +description: Prepare database snapshots +inputs: + CLI_TOKEN: + description: "Saleor cli token" + required: true + BACKUP_NAMESPACE: + description: "The backups namespace" + required: true +outputs: + BACKUP_ID: + description: "The ID of backup" + value: ${{ steps.backup.outputs.BACKUP_ID }} + BACKUP_VER: + description: "The version of backup" + value: ${{ steps.backup.outputs.BACKUP_VER }} + BACKUP_NAME: + description: "The name of backup" + value: ${{ steps.backup.outputs.BACKUP_NAME }} +runs: + using: "composite" + steps: + - name: Saleor login + uses: ./.github/actions/cli-login + with: + token: ${{ inputs.CLI_TOKEN }} + + - name: Obtain backup id + id: backup + shell: bash + env: + BACKUP_NAME: ${{ inputs.BACKUP_NAMESPACE }} + run: | + BACKUPS=$(npx saleor backup list --name="$BACKUP_NAME" --latest --json) + BACKUP_ID=$(echo "$BACKUPS" | jq -r '.[0].key') + BACKUP_VER=$(echo "$BACKUPS" | jq -r '.[0].saleor_version') + BACKUP_NAME=$(echo "$BACKUPS" | jq -r '.[0].name') + + echo "BACKUP_ID=$BACKUP_ID" >> $GITHUB_OUTPUT + echo "BACKUP_VER=$BACKUP_VER" >> $GITHUB_OUTPUT + echo "BACKUP_NAME=$BACKUP_NAME" >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/actions/prepare-instance/action.yml b/.github/actions/prepare-instance/action.yml new file mode 100644 index 00000000000..0c26e3d9c44 --- /dev/null +++ b/.github/actions/prepare-instance/action.yml @@ -0,0 +1,70 @@ +name: Prepare instance +description: Prepare cloud instance for testing +inputs: + STRATEGY: + description: "How to create the new instance (create|reload)" + required: false + default: "create" + CLI_TOKEN: + description: "Saleor cli token" + required: true + BASE_URL: + description: "Dashboard base url" + required: true + API_URL: + description: "API url" + required: true + POOL_NAME: + description: "The name of the instance" + required: true + POOL_INSTANCE: + description: "The full URL of the instance" + required: true + BACKUP_ID: + description: "The id of backup" + required: true +runs: + using: "composite" + steps: + - name: Saleor login + uses: ./.github/actions/cli-login + with: + token: ${{ inputs.CLI_TOKEN }} + + - name: Instance check + if: ${{ inputs.STRATEGY == 'reload' }} + shell: bash + id: instance_check + env: + INSTANCE_NAME: ${{ inputs.POOL_NAME }} + run: | + set +o pipefail + INSTANCE_KEY=$(npx saleor env show "$INSTANCE_NAME" --json | jq .key) + echo "INSTANCE_KEY=$INSTANCE_KEY" >> $GITHUB_OUTPUT + + - name: Reload snapshot + shell: bash + if: ${{ steps.instance_check.outputs.INSTANCE_KEY }} + env: + BACKUP_ID: ${{ inputs.BACKUP_ID }} + INSTANCE_NAME: ${{ inputs.POOL_NAME }} + run: | + npx saleor backup restore "$BACKUP_ID" \ + --environment="$INSTANCE_NAME" \ + --skip-webhooks-update + + - name: Create new instance + shell: bash + if: ${{ !steps.instance_check.outputs.INSTANCE_KEY }} + env: + BACKUP_ID: ${{ inputs.BACKUP_ID }} + INSTANCE_NAME: ${{ inputs.POOL_NAME }} + run: | + npx saleor env create "$INSTANCE_NAME" \ + --project=project-for-pr-testing \ + --database=snapshot \ + --restore-from="$BACKUP_ID" \ + --saleor=saleor-master-staging \ + --domain="$INSTANCE_NAME" \ + --skip-restrict \ + --skip-webhooks-update \ No newline at end of file diff --git a/.github/actions/prepare-tests-variables/action.yml b/.github/actions/prepare-tests-variables/action.yml new file mode 100644 index 00000000000..a997a3c07ad --- /dev/null +++ b/.github/actions/prepare-tests-variables/action.yml @@ -0,0 +1,71 @@ +name: Prepare tests variables +description: Prepare database snapshots +inputs: + MODE: + description: "The mode of running tests (pull-request, release, main)" + required: true + CLI_TOKEN: + description: "Saleor cli token" + required: true +outputs: + BASE_URL: + description: "Dashboard base url" + value: ${{ steps.api.outputs.BASE_URL }} + BASE_URL_DOMAIN: + description: "Dashboard domain" + value: ${{ steps.api.outputs.BASE_URL_DOMAIN }} + API_URL: + description: "API url" + value: ${{ steps.api.outputs.API_URL }} + POOL_NAME: + description: "The name of the instance" + value: ${{ steps.api.outputs.POOL_NAME }} + POOL_INSTANCE: + description: "The full URL of the instance" + value: ${{ steps.api.outputs.POOL_INSTANCE }} + BACKUP_ID: + description: "The ID of backup" + value: ${{ steps.backup.outputs.BACKUP_ID }} + BACKUP_VER: + description: "The version of backup" + value: ${{ steps.backup.outputs.BACKUP_VER }} + BACKUP_NAME: + description: "The name of backup" + value: ${{ steps.backup.outputs.BACKUP_NAME }} + BACKUP_NAMESPACE: + description: "The name of backup" + value: ${{ steps.api.outputs.BACKUP_NAMESPACE }} +runs: + using: "composite" + steps: + - name: Generate api + id: api + uses: ./.github/actions/prepare-api-variables + with: + MODE: ${{ inputs.MODE }} + + - name: Generate backup + id: backup + uses: ./.github/actions/prepare-backups-variables + with: + CLI_TOKEN: ${{ inputs.CLI_TOKEN }} + BACKUP_NAMESPACE: ${{ steps.api.outputs.BACKUP_NAMESPACE }} + + - name: Print annotations + shell: bash + env: + BASE_URL: ${{ steps.api.outputs.BASE_URL }} + API_URL: ${{ steps.api.outputs.API_URL }} + POOL_NAME: ${{ steps.api.outputs.POOL_NAME }} + POOL_INSTANCE: ${{ steps.api.outputs.POOL_INSTANCE }} + BACKUP_ID: ${{ steps.backup.outputs.BACKUP_ID }} + BACKUP_VER: ${{ steps.backup.outputs.BACKUP_VER }} + BACKUP_NAME: ${{ steps.backup.outputs.BACKUP_NAME }} + BACKUP_NAMESPACE: ${{ steps.api.outputs.BACKUP_NAMESPACE }} + run: | + echo "::notice title=BASE_URL::${BASE_URL}" + echo "::notice title=API_URL::${API_URL}" + echo "::notice title=POOL_NAME::${POOL_NAME}" + echo "::notice title=POOL_INSTANCE::${POOL_INSTANCE}" + echo "::notice title=BACKUP_NAMESPACE::${BACKUP_NAMESPACE}" + echo "::notice title=SNAPSHOT::backup_id=${BACKUP_ID}, version=${BACKUP_VER}, name=${BACKUP_NAME}" \ No newline at end of file diff --git a/.github/workflows/run-test-manual.yml b/.github/workflows/run-test-manual.yml index 0c2f3c81137..09b7af4f4cb 100644 --- a/.github/workflows/run-test-manual.yml +++ b/.github/workflows/run-test-manual.yml @@ -25,12 +25,15 @@ jobs: - name: Set variables mode id: set_variables_mode shell: bash + # run: | + # if [[ "$GITHUB_REF" == "refs/heads/main" ]]; then + # echo "MODE=main" >> $GITHUB_OUTPUT + # else + # echo "MODE=release" >> $GITHUB_OUTPUT + # fi run: | - if [[ "$GITHUB_REF" == "refs/heads/main" ]]; then echo "MODE=main" >> $GITHUB_OUTPUT - else - echo "MODE=release" >> $GITHUB_OUTPUT - fi + - name: Generate variables id: cloud_variables @@ -129,4 +132,4 @@ jobs: --slack_webhook_url "$slack_webhook_url" \ --environment "$environment" \ --url_to_action "$url_to_action" \ - --ref_name "$ref_name" + --ref_name "$ref_name" \ No newline at end of file diff --git a/package.json b/package.json index 4160a5876b0..5ce1c0af4f4 100644 --- a/package.json +++ b/package.json @@ -366,7 +366,9 @@ "qa:artifact-move-screenshots": "find cypress/reports/*/mochareports -type d -name \"*.js\" -exec mv {} cypress/reports/mochareports \\;", "qa:artifact-move-videos": "find cypress/reports/*/mochareports/videos -type f -name \"*.js.mp4\" -exec mv {} cypress/reports/mochareports/videos \\;", "qa:basic-regression": "npx playwright test --grep @basic-regression", - "qa:full-regression": "npx playwright test" + "qa:full-regression": "npx playwright test", + "qa:pw-e2e": "npx playwright test --grep @e2e", + "qa:pw-ui": "npx playwright test --ui" }, "description": "![Saleor Dashboard](https://user-images.githubusercontent.com/44495184/185379472-2a204c0b-9b7a-4a3e-93c0-2cb85205ed5e.png)" } diff --git a/playwright/data/url.ts b/playwright/data/url.ts index 8ae9bb38e0c..1e142b57c05 100644 --- a/playwright/data/url.ts +++ b/playwright/data/url.ts @@ -22,12 +22,12 @@ export const URL_LIST = { plugins: "/plugins/", products: "/products/", productsAdd: "add?product-type-id=", - productTypes: "/product-types/", - productTypesAdd: "/product-types/add", - sales: "/discounts/sales/", - shippingMethods: "/shipping/", - siteSettings: "/site-settings/", - staffMembers: "/staff/", + productTypes: "product-types/", + productTypesAdd: "product-types/add", + sales: "discounts/sales/", + shippingMethods: "shipping/", + siteSettings: "site-settings/", + staffMembers: "staff/", stripeApiPaymentMethods: "https://api.stripe.com/v1/payment_methods", translations: "/translations/", variants: "/variant/", diff --git a/playwright/pages/homePage.ts b/playwright/pages/homePage.ts index 32f08cd65af..ce75d3e27e9 100644 --- a/playwright/pages/homePage.ts +++ b/playwright/pages/homePage.ts @@ -1,3 +1,4 @@ +import { URL_LIST } from "@data/url"; import { expect, Locator, Page } from "@playwright/test"; export class HomePage { @@ -27,7 +28,7 @@ export class HomePage { this.productsOutOfStock = page.getByTestId("products-out-of-stock"); } async goto() { - await this.page.goto("/"); + await this.page.goto(URL_LIST.homePage); } async clickChannelSelectButton() { diff --git a/playwright/tests/auth.setup.ts b/playwright/tests/auth.setup.ts index 60f0ffed6bc..afadb3fd4f5 100644 --- a/playwright/tests/auth.setup.ts +++ b/playwright/tests/auth.setup.ts @@ -1,3 +1,4 @@ +import { URL_LIST } from "@data/url"; import { USER_PERMISSION } from "@data/userPermissions"; import { LoginPage } from "@pages/loginPage"; import { test as setup } from "@playwright/test"; diff --git a/playwright/tests/home.spec.ts b/playwright/tests/home.spec.ts index 58480572938..8346843f869 100644 --- a/playwright/tests/home.spec.ts +++ b/playwright/tests/home.spec.ts @@ -1,3 +1,4 @@ +import { URL_LIST } from "@data/url"; import { HomePage } from "@pages/homePage"; import { expect, test } from "@playwright/test"; @@ -8,7 +9,7 @@ test("TC: SALEOR_29 Correct information on dashboard home page @basic-regression }) => { const homePage = new HomePage(page); - await page.goto("/"); + await page.goto(URL_LIST.homePage); await expect(homePage.channelSelect).toBeVisible({ timeout: 10000 }); await homePage.expectHomePageElementsToBeVisible();