Skip to content

Commit

Permalink
Set up playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
minkyngkm committed Dec 8, 2023
1 parent d92de19 commit 8a8673d
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ CONFIDENTIALITY_AGREEMENT_WEBHOOK_USERNAME="local"
CONFIDENTIALITY_AGREEMENT_WEBHOOK_PASSWORD="password"

# This is a test api key https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
CAPTCHA_TESTING_API_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
CAPTCHA_TESTING_API_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
42 changes: 0 additions & 42 deletions .github/workflows/cypress-pr.yaml

This file was deleted.

65 changes: 65 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Playwright Tests
env:
SECRET_KEY: insecure_test_key
PORT: 8001
CONTRACTS_API_URL: https://contracts.staging.canonical.com
STRIPE_PUBLISHABLE_KEY: pk_test_yndN9H0GcJffPe0W58Nm64cM00riYG4N46
CAPTCHA_TESTING_API_KEY: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
MARKETO_API_CLIENT: ${{secrets.MARKETO_API_CLIENT}}
MARKETO_API_SECRET: ${{secrets.MARKETO_API_SECRET}}
PLAYWRIGHT_USER_ID: ${{secrets.PLAYWRIGHT_USER_ID}}
PLAYWRIGHT_USER_PASSWORD : ${{secrets.PLAYWRIGHT_USER_PASSWORD}}
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
if: github.repository == 'canonical/ubuntu.com'
runs-on: ubuntu-latest
steps:
- name: Echo GitHub Secret
run: echo ${{ secrets.PLAYWRIGHT_USER_ID }} ${{ secrets.PLAYWRIGHT_USER_PASSWORD }}
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install python dependencies
run: pip3 install -r requirements.txt
- name: Install dependencies
run: npm install -g yarn && yarn
- name: Install dotrun
uses: canonical/install-dotrun@main

- name: Install dependencies
run: /snap/bin/dotrun install

- name: Build assets
run: /snap/bin/dotrun build

- name: Run dotrun
run: |
/snap/bin/dotrun &
curl --head --fail --retry-delay 1 --retry 30 --retry-connrefused http://localhost:8001
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run Playwright tests
run: yarn playwright test
env:
PLAYWRIGHT_USER_ID: ${{secrets.PLAYWRIGHT_USER_ID}}
PLAYWRIGHT_USER_PASSWORD : ${{secrets.PLAYWRIGHT_USER_PASSWORD}}
- uses: actions/upload-artifact@v3
if: always()
with:
build: yarn run build
start: yarn run serve
name: playwright-report
path: playwright-report/
retention-days: 30
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ webapp/snapcraft_api/
.login
static/js/build/
tests/cassettes/TestRoutes.test_ceph_docs.yaml
/test-results/
/playwright-report/
/playwright/
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@babel/preset-env": "7.16.7",
"@babel/preset-react": "7.14.5",
"@babel/preset-typescript": "7.16.7",
"@playwright/test": "^1.40.0",
"@testing-library/cypress": "8.0.0",
"@testing-library/dom": "8.13.0",
"@testing-library/jest-dom": "5.14.1",
Expand All @@ -52,6 +53,7 @@
"@types/enzyme": "3.10.11",
"@types/jest": "26.0.24",
"@types/lodash": "4.14.175",
"@types/node": "^20.9.3",
"@types/react-google-recaptcha": "2.1.2",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
Expand Down Expand Up @@ -97,6 +99,7 @@
"autoprefixer": "10.4.1",
"date-fns": "2.28.0",
"date-fns-tz": "1.3.4",
"dotenv": "^16.3.1",
"esbuild": "0.14.10",
"flickity": "^3.0.0",
"formik": "2.2.9",
Expand Down Expand Up @@ -127,6 +130,9 @@
"node_modules",
"src"
],
"testPathIgnorePatterns": [
"<rootDir>/tests/playwright/"
],
"setupFilesAfterEnv": [
"<rootDir>/tests/setupTests.ts"
],
Expand Down
42 changes: 42 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { defineConfig, devices } from '@playwright/test';
import * as dotenv from 'dotenv';
import * as path from "path";

dotenv.config({
path: path.join(__dirname, ".env.local")
});

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: path.join(__dirname, "tests/playwright/tests"),
/* 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. */
timeout: 30000,
use: {
baseURL: "http://0.0.0.0:8001",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
ignoreHTTPSErrors: true,
headless: true,
},

/* Configure projects for major browsers */
projects: [
{
name: 'checkout',
testMatch: "*.spec.ts",
use: { ...devices['Desktop Chrome']},
},
],
});
42 changes: 42 additions & 0 deletions tests/playwright/helplers/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Page } from "@playwright/test";

export const login = async (page: Page) => {
// TODO: mocking Login (To intercept "https://login.ubuntu.com/*/+login", proper mock responses are needed)

await acceptCookiePolicy(page);
await page.fill('input[name="email"]', process.env.PLAYWRIGHT_USER_ID as string) ;
await page.fill('input[name="password"]', process.env.PLAYWRIGHT_USER_PASSWORD as string);
await page.click('button[type="submit"]') // Click "Login"
await page.click('button[type="submit"]') // Click "Yes, log me in"
}

export const selectProducts = async (
page: Page,
productUser = "organisation",
quantity = 2,
machineType = "physical",
version = "20.04",
support = "none"
) => {
await page.locator(`[value='${productUser}']`).check();
await page.locator("#quantity-input").fill(`${quantity}`);
await page.locator(`[value='${machineType}']`).check();
await page.getByRole('tab', { name: `${version} LTS`}).click();
await page.getByRole('radio', { name: 'Ubuntu Pro (Infra-only)', exact: true }).check();
await page.$(`#${support}-label`)
};

export const acceptCookiePolicy = async (
page: Page,
) => {
await page.locator('#cookie-policy-button-accept').click();
};

export const acceptTerms = async (page: Page) => {
await page.getByText(/I agree to the Ubuntu Pro service terms/).click();
await page.getByText(/I agree to the Ubuntu Pro description/).click();
}

export const clickRecaptcha = async (page: Page) => {
await page.frameLocator('[title="reCAPTCHA"]').getByRole('checkbox', { name: 'I\'m not a robot' }).click({force: true});
}
59 changes: 59 additions & 0 deletions tests/playwright/helplers/mockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// post /pro/purchase/preview${window.location.search}
export const previewResponse = {
"currency": "usd",
"end_of_cycle": "",
"id": "",
"items": null,
"payment_status": null,
"reason": "subscription_create",
"start_of_cycle": "",
"status": "draft",
"tax_amount": null,
"total": 45000,
"url": null
}

// post /account/customer-info/${accountId}${queryString}
export const customerInfoResponse = {
"accountInfo": {
"createdAt": "2023-06-21T10:19:18Z",
"externalAccountIDs": [
{
"IDs": [
"cus_OAc0ko9kKLLpn2"
],
"origin": "Stripe"
},
{
"IDs": [
"0013M00001QN0K4QAL"
],
"origin": "Salesforce"
}
],
"id": "aACd-Dgydz9UmVpft445tErM1NIVHbVhX-G7bbxzAWgQ",
"lastModifiedAt": "2023-08-08T11:04:08Z",
"name": "Canonical",
"type": "paid"
},
"customerInfo": {
"address": {
"city": "test",
"country": "JP",
"line1": "test 2",
"line2": "",
"postal_code": "test",
"state": ""
},
"defaultPaymentMethod": {
"brand": "visa",
"country": "US",
"expMonth": 4,
"expYear": 2024,
"id": "pm_1OJqfSCzjFajHovdEN8RvPf8",
"last4": "4242"
},
"email": "[email protected]",
"name": "MIn Kim"
}
}
4 changes: 4 additions & 0 deletions tests/playwright/helplers/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ENDPOINTS = {
customerInfo: "/account/customer-info*",
preview: "/pro/purchase/preview*"
};
44 changes: 44 additions & 0 deletions tests/playwright/tests/checkout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { test, expect } from "@playwright/test";
import { selectProducts, acceptCookiePolicy, login } from "../helplers/commands";
import { customerInfoResponse, previewResponse } from "../helplers/mockData";
import { ENDPOINTS } from "../helplers/utils";

test.describe("Checkout - Region and taxes", () => {
test("It should show correct non-VAT price", async ({page}) => {
await page.goto("/pro/subscribe")
await acceptCookiePolicy(page)
await selectProducts(page);
await page.getByRole("button", { name: "Buy now" }).click();

await login(page);

await page.route(ENDPOINTS.customerInfo, async (route) => {
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({...customerInfoResponse, "customerInfo": {...customerInfoResponse.customerInfo, "address": {...customerInfoResponse.customerInfo.address, "country": "AF" }}})
});
});

await page.route(ENDPOINTS.preview, async (route) => {
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(previewResponse)
});
});

await page.locator(
":nth-child(1) > .p-stepped-list__content > .row > .u-align--right > .p-action-button"
).click(); // Click "Edit" button
await page.getByLabel("Country/Region:").selectOption({ label: 'Afghanistan' })
await page.locator(".u-align--right > :nth-child(2)").click(); // Click "Save" button

const country = await page.$('[data-testid="country"]')
const countryText = await country?.innerText();

expect(countryText).toBe("Afghanistan")
expect(await page.$('[data-testid="total"]')).toBeNull();
expect(await page.$('[data-testid="tax"]')).toBeNull();
})
})
Loading

0 comments on commit 8a8673d

Please sign in to comment.