From 328807afd122c193c2a98cda1247f750ade53bee Mon Sep 17 00:00:00 2001 From: Sem Bauke Date: Fri, 14 Jun 2024 14:20:45 +0200 Subject: [PATCH] feat: convert thirdparty donation tests to Playwright (#55043) --- .github/workflows/e2e-playwright.yml | 2 +- .github/workflows/e2e-third-party.yml | 43 +++++++-------- cypress/e2e/third-party/donate-page.ts | 18 ------- e2e/fixtures/donation/stripe.json | 48 +++++++++++++++++ e2e/third-party-donation.spec.ts | 75 ++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 40 deletions(-) delete mode 100644 cypress/e2e/third-party/donate-page.ts create mode 100644 e2e/fixtures/donation/stripe.json create mode 100644 e2e/third-party-donation.spec.ts diff --git a/.github/workflows/e2e-playwright.yml b/.github/workflows/e2e-playwright.yml index f3564296162..39c2e3e6273 100644 --- a/.github/workflows/e2e-playwright.yml +++ b/.github/workflows/e2e-playwright.yml @@ -142,7 +142,7 @@ jobs: run: | pnpm run start-ci & sleep 10 - npx playwright test --project=${{ matrix.browsers }} + npx playwright test --project=${{ matrix.browsers }} --grep-invert 'third-party-donation.spec.ts' - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} diff --git a/.github/workflows/e2e-third-party.yml b/.github/workflows/e2e-third-party.yml index 0ac0086f637..e7cdf151adc 100644 --- a/.github/workflows/e2e-third-party.yml +++ b/.github/workflows/e2e-third-party.yml @@ -53,17 +53,21 @@ jobs: - name: Set freeCodeCamp Environment Variables run: | - sed '/STRIPE/d; /PAYPAL/d;' sample.env > .env + sed '/STRIPE/d; /PAYPAL/d; /PATREON/d;' sample.env > .env echo 'STRIPE_PUBLIC_KEY=${{ secrets.STRIPE_PUBLIC_KEY }}' >> .env - echo 'STRIPE_SECRET_KEY=${{ secrets.STRIPE_SECRET_KEY }}' >> .env echo 'PAYPAL_CLIENT_ID=${{ secrets.PAYPAL_CLIENT_ID }}' >> .env + echo 'PATREON_CLIENT_ID=${{ secrets.PATREON_CLIENT_ID }}' >> .env - name: Install and Build run: | pnpm install - pnpm run build - - name: Seed Database - run: pnpm run seed + pnpm run create:shared + pnpm run build:curriculum + pnpm run build:server + + - name: Seed Database with Certified User + run: pnpm run seed:certified-user + - name: Move serve.json to Public Folder run: cp client-config/serve.json client/public/serve.json @@ -71,21 +75,18 @@ jobs: - name: Install pm2 run: npm i -g pm2 - # In our cypress config, we default to the cypress/e2e/default directory. - # We need to change this to cypress/e2e/ for the specific tests we are running - # in this workflow. - # - - name: Adjust the Cypress Config - run: | - sed -i 's#cypress/e2e/default/#cypress/e2e/#g' cypress.config.js + - name: Install playwright dependencies + run: npx playwright install --with-deps - - name: Cypress run - uses: cypress-io/github-action@v6 + - name: Run playwright tests + run: | + pnpm run start-ci & + sleep 10 + npx playwright test third-party-donation.spec.ts --project=${{ matrix.browsers }} + + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} with: - record: ${{ env.CYPRESS_RECORD_KEY != 0 }} - start: pnpm run start-ci - wait-on: http://localhost:8000 - wait-on-timeout: 1200 - config: baseUrl=http://localhost:8000 - browser: chrome - spec: 'cypress/e2e/third-party/donate-page.ts' + name: playwright-report-${{ matrix.browsers }} + path: playwright/reporter + retention-days: 30 diff --git a/cypress/e2e/third-party/donate-page.ts b/cypress/e2e/third-party/donate-page.ts deleted file mode 100644 index 69d2dffe951..00000000000 --- a/cypress/e2e/third-party/donate-page.ts +++ /dev/null @@ -1,18 +0,0 @@ -describe('Donate page', () => { - it('Donation ', () => { - cy.task('seed', ['certified-user']); - cy.login('certified-user'); - cy.visit('/donate'); - cy.get("[data-cy='donation-tier-selection-button']").click(); - - cy.get('.donation-elements', { timeout: 10000 }).within(() => { - cy.fillElementsInput('cardNumber', '4242424242424242'); - cy.fillElementsInput('cardExpiry', '1025'); - }); - cy.get("[data-cy='donation-confirmation-button']").click(); - cy.contains('We are processing your donation.').should('be.visible'); - cy.contains('Thank You for Being a Supporter', { timeout: 10000 }).should( - 'be.visible' - ); - }); -}); diff --git a/e2e/fixtures/donation/stripe.json b/e2e/fixtures/donation/stripe.json new file mode 100644 index 00000000000..2fcf5636f4f --- /dev/null +++ b/e2e/fixtures/donation/stripe.json @@ -0,0 +1,48 @@ +{ + "id": "pm_1PRWUAFI1KEgscdTFyjUCbcd", + "object": "payment_method", + "allow_redisplay": "unspecified", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": null + }, + "country": "US", + "display_brand": "visa", + "exp_month": 10, + "exp_year": 2025, + "funding": "credit", + "generated_from": null, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1718357514, + "customer": null, + "livemode": false, + "radar_options": {}, + "type": "card" +} diff --git a/e2e/third-party-donation.spec.ts b/e2e/third-party-donation.spec.ts new file mode 100644 index 00000000000..7167a92fd61 --- /dev/null +++ b/e2e/third-party-donation.spec.ts @@ -0,0 +1,75 @@ +import { test, expect } from '@playwright/test'; + +import stripeJson from './fixtures/donation/stripe.json'; + +test.describe('third-party donation tests', () => { + test.use({ storageState: 'playwright/.auth/certified-user.json' }); + test.beforeEach(async ({ page }) => { + await page.goto('/donate'); + }); + + test('All elements are present in the widget', async ({ page }) => { + await page.getByRole('button', { name: 'Donate', exact: true }).click(); + + // Paypal button should be present + + const paypalButtonIframe = page.frameLocator('.component-frame'); + const paypalButton = paypalButtonIframe.getByRole('link'); + await expect(paypalButton).toBeVisible(); + await expect(paypalButton).toHaveAttribute('aria-label', 'PayPal'); + + // Patreon button should be present + + const patreonButton = page.locator('.patreon-button'); + await expect(patreonButton).toBeVisible(); + + // "Or dontate with card" button should be present + + await expect(page.getByText('Or donate with card')).toBeVisible(); + }); + + test('It is possible to donate with a card', async ({ page }) => { + await page.getByRole('button', { name: 'Donate', exact: true }).click(); + + const cardNumberIframe = page + .frameLocator('iframe[src*="elements-inner-card"]') + .nth(0); + + const cardExpiryIframe = page + .frameLocator('iframe[src*="elements-inner-card"]') + .nth(1); + + await cardNumberIframe + .locator('input[data-elements-stable-field-name="cardNumber"]') + .fill('4242424242424242'); + + await cardExpiryIframe + .locator('input[data-elements-stable-field-name="cardExpiry"]') + .fill('1025'); + + await page.getByRole('button', { name: 'Donate', exact: true }).click(); + + await page.route( + 'https://api.stripe.com/v1/payment_methods', + async route => { + await route.fulfill({ json: stripeJson }); + } + ); + + await page.route( + 'http://localhost:3000/donate/charge-stripe-card', + async route => { + await route.fulfill({ json: { isDonating: true } }); + } + ); + + await expect(page.getByRole('alert')).toBeVisible(); + + await expect(page.getByRole('alert')).toContainText( + 'Your donations will support free technology education for people all over the world.' + ); + await expect(page.getByRole('alert')).toContainText( + 'Visit supporters page to learn about your supporter benefits.' + ); + }); +});