diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..6409ab8 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,45 @@ +name: e2e Tests + +on: + workflow_dispatch: + inputs: + saleorApiUrl: + required: true + type: string + email: + required: true + type: string + password: + required: true + type: string + appManifestUrl: + required: true + type: string + +env: + E2E_TAXES_SALEOR_API_URL: ${{ inputs.saleorApiUrl }} + E2E_TAXES_ADMIN_USER_EMAIL: ${{ inputs.email }} + E2E_TAXES_ADMIN_USER_PASSWORD: ${{ inputs.password }} + E2E_TAXES_TESTED_APP_MANIFEST: ${{ inputs.appManifestUrl }} + +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Install dependencies + run: pnpm install + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + run: pnpm run e2e + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/apps/taxes/.env.example b/apps/taxes/.env.example index c0d1f30..2a74768 100644 --- a/apps/taxes/.env.example +++ b/apps/taxes/.env.example @@ -7,4 +7,11 @@ PORT= VERCEL_URL= REST_APL_ENDPOINT= REST_APL_TOKEN= -ALLOWED_DOMAIN_PATTERN= \ No newline at end of file +ALLOWED_DOMAIN_PATTERN= + +# e2e + +E2E_TAXES_SALEOR_API_URL= +E2E_TAXES_ADMIN_USER_EMAIL= +E2E_TAXES_ADMIN_USER_PASSWORD= +E2E_TAXES_TESTED_APP_MANIFEST= \ No newline at end of file diff --git a/apps/taxes/.gitignore b/apps/taxes/.gitignore index 12a64be..23d8493 100644 --- a/apps/taxes/.gitignore +++ b/apps/taxes/.gitignore @@ -4,3 +4,7 @@ # Sentry next.config.original.js +node_modules/ +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/apps/taxes/e2e/installation.spec.ts b/apps/taxes/e2e/installation.spec.ts new file mode 100644 index 0000000..530e78f --- /dev/null +++ b/apps/taxes/e2e/installation.spec.ts @@ -0,0 +1,64 @@ +require("dotenv").config(); + +import { expect, test } from "@playwright/test"; +import { createClient } from "urql"; +import { AuthorizeDocument, InstallAppDocument, JobStatusEnum } from "../generated/graphql"; + +const saleorUrl = process.env.E2E_TAXES_SALEOR_API_URL!; +const email = process.env.E2E_TAXES_ADMIN_USER_EMAIL!; +const password = process.env.E2E_TAXES_ADMIN_USER_PASSWORD!; +const testedAppManifest = process.env.E2E_TAXES_TESTED_APP_MANIFEST!; + +const client = createClient({ + url: saleorUrl, +}); + +let token = ""; + +test.describe("Taxes Installation @taxes", () => { + test.beforeAll(async () => { + const tokenResp = await client + .mutation(AuthorizeDocument, { + email, + password, + }) + .toPromise(); + + token = tokenResp.data!.tokenCreate!.token as string; + + return expect(token).toBeDefined(); + }); + + /** + * Should it be taxes/e2e or maybe move it to packages/e2e and run all apps installations there? + * Having a package will be hard to orchestrate when tests should run + */ + test("Installs app via Manifest", async () => { + const installationResp = await client + .mutation( + InstallAppDocument, + { manifestUrl: testedAppManifest }, + { + fetchOptions: { + headers: { + Authorization: `Bearer ${token}`, + }, + }, + } + ) + .toPromise(); + + expect(installationResp.data!.appInstall!.appInstallation!.status).toBe(JobStatusEnum.Pending); + expect(installationResp.data!.appInstall!.appInstallation!.id).toEqual(expect.any(String)); + + // todo - fetch installed app after job completed + }); + + test("Fetches manifest", async ({ request }) => { + expect(await request.get(testedAppManifest!).then((r) => r.json())).toMatchObject( + expect.objectContaining({ + name: expect.any(String), + }) + ); + }); +}); diff --git a/apps/taxes/graphql/mutations/Authorize.graphql b/apps/taxes/graphql/mutations/Authorize.graphql new file mode 100644 index 0000000..764cde1 --- /dev/null +++ b/apps/taxes/graphql/mutations/Authorize.graphql @@ -0,0 +1,5 @@ +mutation Authorize($email: String!, $password: String!) { + tokenCreate(email: $email, password: $password) { + token + } +} diff --git a/apps/taxes/graphql/mutations/InstallApp.graphql b/apps/taxes/graphql/mutations/InstallApp.graphql new file mode 100644 index 0000000..a05fa01 --- /dev/null +++ b/apps/taxes/graphql/mutations/InstallApp.graphql @@ -0,0 +1,13 @@ +mutation InstallApp ($manifestUrl: String) { + appInstall( + input: { manifestUrl: $manifestUrl, appName: "E2E TEST APP", activateAfterInstallation: true } + ) { + errors { + code + } + appInstallation { + id + status + } + } +} diff --git a/apps/taxes/package.json b/apps/taxes/package.json index bcd7af4..e7f5d2c 100644 --- a/apps/taxes/package.json +++ b/apps/taxes/package.json @@ -9,7 +9,8 @@ "lint": "next lint", "fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql", "generate": "graphql-codegen", - "test": "vitest" + "test": "vitest", + "e2e": "playwright test" }, "saleor": { "schemaVersion": "3.10" @@ -58,6 +59,7 @@ "@graphql-codegen/typescript-urql": "^3.7.3", "@graphql-codegen/urql-introspection": "2.2.1", "@graphql-typed-document-node/core": "^3.1.2", + "@playwright/test": "^1.32.3", "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "@types/node": "^18.8.1", diff --git a/apps/taxes/playwright.config.ts b/apps/taxes/playwright.config.ts new file mode 100644 index 0000000..b5a3d62 --- /dev/null +++ b/apps/taxes/playwright.config.ts @@ -0,0 +1,85 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./e2e", + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + + /* + * { + * name: 'firefox', + * use: { ...devices['Desktop Firefox'] }, + * }, + * + * { + * name: 'webkit', + * use: { ...devices['Desktop Safari'] }, + * }, + */ + + /* Test against mobile viewports. */ + /* + * { + * name: 'Mobile Chrome', + * use: { ...devices['Pixel 5'] }, + * }, + * { + * name: 'Mobile Safari', + * use: { ...devices['iPhone 12'] }, + * }, + */ + + /* Test against branded browsers. */ + /* + * { + * name: 'Microsoft Edge', + * use: { ...devices['Desktop Edge'], channel: 'msedge' }, + * }, + * { + * name: 'Google Chrome', + * use: { ..devices['Desktop Chrome'], channel: 'chrome' }, + * }, + */ + ], + + /* Run your local dev server before starting the tests */ + /* + * webServer: { + * command: 'npm run start', + * url: 'http://127.0.0.1:3000', + * reuseExistingServer: !process.env.CI, + * }, + */ +}); diff --git a/apps/taxes/turbo.json b/apps/taxes/turbo.json index 03a43c6..df5c4a9 100644 --- a/apps/taxes/turbo.json +++ b/apps/taxes/turbo.json @@ -12,7 +12,12 @@ "VERCEL_URL", "REST_APL_ENDPOINT", "REST_APL_TOKEN", - "ALLOWED_DOMAIN_PATTERN" + "ALLOWED_DOMAIN_PATTERN", + "CI", + "E2E_TAXES_ADMIN_USER_EMAIL", + "E2E_TAXES_ADMIN_USER_PASSWORD", + "E2E_TAXES_TESTED_APP_MANIFEST", + "E2E_TAXES_SALEOR_API_URL" ] } } diff --git a/package.json b/package.json index 15d6a6b..c2c7733 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "test:ci": "turbo run test:ci", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "generate": "turbo run generate", - "prepare": "husky install" + "prepare": "husky install", + "e2e": "turbo run e2e" }, "devDependencies": { "@changesets/cli": "^2.26.0", diff --git a/packages/eslint-config-saleor/index.js b/packages/eslint-config-saleor/index.js index 90eddc4..a84210f 100644 --- a/packages/eslint-config-saleor/index.js +++ b/packages/eslint-config-saleor/index.js @@ -14,7 +14,13 @@ module.exports = { }, overrides: [ { - files: ["src/pages/**/*", "src/pages/api/**/*", "vitest.config.ts", "generated/graphql.ts"], + files: [ + "src/pages/**/*", + "src/pages/api/**/*", + "vitest.config.ts", + "generated/graphql.ts", + "playwright.config.ts", + ], rules: { "import/no-default-export": "off", }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 051b6ad..7c00141 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1575,6 +1575,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.1.2 version: 3.1.2(graphql@16.6.0) + '@playwright/test': + specifier: ^1.32.3 + version: 1.32.3 '@testing-library/react': specifier: ^13.4.0 version: 13.4.0(react-dom@18.2.0)(react@18.2.0) @@ -4647,6 +4650,17 @@ packages: tiny-glob: 0.2.9 tslib: 2.5.0 + /@playwright/test@1.32.3: + resolution: {integrity: sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@types/node': 18.13.0 + playwright-core: 1.32.3 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /@popperjs/core@2.11.6: resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} dev: false @@ -13773,6 +13787,12 @@ packages: mlly: 1.2.0 pathe: 1.1.0 + /playwright-core@1.32.3: + resolution: {integrity: sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==} + engines: {node: '>=14'} + hasBin: true + dev: true + /png-js@1.0.0: resolution: {integrity: sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==} dev: false diff --git a/turbo.json b/turbo.json index a00437b..7ebf131 100644 --- a/turbo.json +++ b/turbo.json @@ -24,6 +24,7 @@ }, "generate": { "outputs": ["generated/"] - } + }, + "e2e": {} } }