diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-pr.yml index f7e06bd39..b7611035c 100644 --- a/.github/workflows/check-pr.yml +++ b/.github/workflows/check-pr.yml @@ -89,3 +89,4 @@ jobs: run-playwright: name: Run Playwright uses: ./.github/workflows/playwright.yml + secrets: inherit diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index a0018936d..7ebf3f398 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -19,6 +19,9 @@ jobs: ref: master path: './api' + - name: Set yarn version + run: yarn set version berry + - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT @@ -35,17 +38,32 @@ jobs: - name: Run db working-directory: ./api run: docker compose up -d pg-db + + - name: Run stripe webhook + working-directory: ./api + env: + STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }} + STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} + run: docker compose up -d stripe-webhook + - uses: actions/setup-node@v3 with: node-version: '18' - - name: Install backend dependencies and seed database + - name: Install backend dependencies + working-directory: ./api + run: yarn + + - name: Seed database working-directory: ./api - run: yarn && yarn prisma generate && yarn prisma migrate deploy && yarn prisma db seed + run: yarn prisma generate && yarn prisma migrate deploy && yarn prisma db seed - name: Run backend working-directory: ./api - run: yarn start & + env: + STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }} + STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} + run: yarn start &> api.log & - name: Install Frontend Dependencies working-directory: ./frontend @@ -71,7 +89,7 @@ jobs: - name: Start frontend working-directory: ./frontend - run: yarn start & + run: yarn start &> frontend.log & - name: Install Playwright Browsers working-directory: ./frontend @@ -93,3 +111,12 @@ jobs: name: playwright-report path: ./frontend/playwright-report/ retention-days: 14 + + - uses: actions/upload-artifact@v3 + if: failure() + with: + name: logs + path: | + ./frontend/frontend.log + ./api/api.log + retention-days: 14 diff --git a/e2e/AuthPage.ts b/e2e/AuthPage.ts new file mode 100644 index 000000000..5bbee26a3 --- /dev/null +++ b/e2e/AuthPage.ts @@ -0,0 +1,31 @@ +import { Page } from '@playwright/test' + +const credentials = { + username: process.env.USERNAME ?? 'admin@podkrepi.bg', + password: process.env.PASSWORD ?? '$ecurePa33', +} + +export class AuthPage { + page: Page + constructor(page: Page) { + this.page = page + } + + async _submitLoginForm() { + await this.page.click('input[type="email"]') + await this.page.fill('input[type="email"]', credentials.username) + await this.page.click('input[type="password"]') + await this.page.fill('input[type="password"]', credentials.password) + await this.page.click('text="Вход"') + await this.page.waitForNavigation({ waitUntil: 'networkidle' }) + } + + async login() { + await Promise.all([ + this.page.goto('http://localhost:3040/login'), + this.page.waitForNavigation(), + ]) + + await this._submitLoginForm() + } +} diff --git a/e2e/local/donation.spec.ts b/e2e/local/donation.spec.ts new file mode 100644 index 000000000..aea2602c3 --- /dev/null +++ b/e2e/local/donation.spec.ts @@ -0,0 +1,88 @@ +import { test, expect } from '@playwright/test' + +test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:3040/', { waitUntil: 'networkidle' }) + await page.locator('text="Подкрепете сега"').first().click() + await page.waitForURL((url) => url.pathname.includes('/campaigns/donation')) +}) + +test.describe('donation page init', () => { + test('test rendering and defaults', async ({ page }) => { + await expect( + page.locator('label', { has: page.locator('text=Карта') }).locator('input[type="radio"]'), + ).toBeChecked() + await expect( + page + .locator('label', { has: page.locator('text=Банков превод') }) + .locator('input[type="radio"]'), + ).not.toBeChecked() + }) +}) + +//This test will not pass since the keycloak is not yet working in the e2e tests + +// test.describe('logged in user donation flow', () => { +// test('choosing a predefined value and donate', async ({ page }) => { +// // Choose a predefined value from the radio buttons +// await page.locator('input[value="card"]').check() +// await page.locator('input[value="500"]').check() + +// // Click checkbox to cover the tax by stripe +// await page.locator('input[name="cardIncludeFees"]').check() +// await page.locator('button:has-text("Напред")').click() + +// await expect(page.locator('text=Вече сте влезли във Вашия профил')).toBeDefined() +// await page.locator('button:has-text("Напред")').click() + +// await page.fill('textarea', 'Test message') +// await page.locator('button:has-text("Премини към плащане")').click() + +// await page.waitForURL((url) => url.host === 'checkout.stripe.com') + +// await expect(page.locator('text=BGN 5.00')).toBeDefined() +// await page.locator('input[name="email"]').fill('admin@podkrepi.bg') +// await page.locator('input[name="cardNumber"]').fill('4242424242424242') +// await page.locator('input[name="cardExpiry"]').fill('0424') +// await page.locator('input[name="cardCvc"]').fill('123') +// await page.locator('input[name="billingName"]').fill('John Doe') +// await page.locator('select[name="billingCountry"]').selectOption('BG') + +// await page.locator('button[data-testid="hosted-payment-submit-button"]').click() + +// await page.waitForURL((url) => url.searchParams.get('success') === 'true') + +// await expect(page.locator('text=Благодарим за доверието и подкрепата!')).toBeDefined() +// }) +// }) + +test.describe('anonymous user donation flow', () => { + test('choosing a custom value and continuing', async ({ page }) => { + // Choose a predefined value from the radio buttons + await page.locator('input[value="card"]').check() + await page.locator('input[value="500"]').check() + + // Click checkbox to cover the tax by stripe + await page.locator('input[name="cardIncludeFees"]').check() + await page.locator('button:has-text("Напред")').click() + + page.locator('text=Дарете анонимно').click() + await page.locator('button:has-text("Напред")').click() + + await page.fill('textarea', 'е2е_tester') + await page.locator('button:has-text("Премини към плащане")').click() + + await expect(page.locator('text=BGN 5.00')).toBeDefined() + await page.locator('input[name="email"]').fill('anon_e2e_tester@podkrepi.bg') + await page.locator('input[name="cardNumber"]').fill('4242424242424242') + await page.locator('input[name="cardExpiry"]').fill('0424') + await page.locator('input[name="cardCvc"]').fill('123') + await page.locator('input[name="billingName"]').fill('John Doe') + await page.locator('select[name="billingCountry"]').selectOption('BG') + + await page.locator('button[data-testid="hosted-payment-submit-button"]').click() + + await page.waitForURL((url) => url.searchParams.get('success') === 'true') + + await expect(page.locator('text=Благодарим за доверието и подкрепата!')).toBeDefined() + }) +}) diff --git a/playwright.config.ts b/playwright.config.ts index 7f7362acd..ac58ae038 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -36,7 +36,7 @@ const config: PlaywrightTestConfig = { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: 'http://localhost:3000', + baseURL: process.env.BASE_URL || 'http://localhost:3040', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry',