Skip to content

Commit

Permalink
test: add more e2e specs. (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
morganney committed Jan 18, 2024
1 parent 3afba98 commit aac2593
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 65 deletions.
15 changes: 14 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ name: E2E Tests

on:
workflow_dispatch:
inputs:
testPath:
description: 'Files to test.'
required: true
default: 'tests'
type: string

jobs:
test:
Expand Down Expand Up @@ -34,7 +40,7 @@ jobs:
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Tests
run: npm test
run: npm test -- ${{ inputs.testPath }}
env:
CI: true
SERVER_NAME: localhost
Expand All @@ -52,3 +58,10 @@ jobs:
BM_POSTGRES_DB: ${{ secrets.BM_POSTGRES_DB }}
SSO_GOOG_CLIENT_ID: ${{ secrets.SSO_GOOG_CLIENT_ID }}
SSO_GOOG_CLIENT_SECRET: ${{ secrets.SSO_GOOG_CLIENT_SECRET }}
- name: Upload Test Results
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: test-results
retention-days: 15
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,11 @@ COPY packages/web/templates/core/upstreams.conf.template /etc/nginx/templates/co
COPY packages/web/nginx.dev.conf /etc/nginx/nginx.conf
EXPOSE 80 443

FROM builder AS playwright
RUN apt-get update
RUN apt-get install -y vim
RUN npx playwright install
RUN npx playwright install-deps

FROM adminer:4.8.1 as adminer
EXPOSE 8080
24 changes: 24 additions & 0 deletions compose.override.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ services:
- dev
- -w
- ui
playwright:
depends_on:
- api
build:
context: .
target: playwright
container_name: playwright
volumes:
- ./packages/ui:/app/packages/ui
- ./packages/common/dist:/app/packages/common/dist
- ./packages/components/dist:/app/packages/components/dist
- ./tests:/app/tests
- ./playwright.config.ts:/app/playwright.config.ts
- ./.env:/app/.env # used to inject VITE_ env vars
ports:
- '5173:5173'
environment:
API_HOST: ${API_HOST}
command:
- npm
- run
- dev
- -w
- ui
storybook:
build:
context: .
Expand Down
4 changes: 2 additions & 2 deletions copilot/api/addons/bm-cluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ Mappings:
bmclusterEnvScalingConfigurationMap:
test:
'DBMinCapacity': 2 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]
'DBMaxCapacity': 4 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]
'DBMaxCapacity': 2 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]

All:
'DBMinCapacity': 2 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]
'DBMaxCapacity': 4 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]
'DBMaxCapacity': 2 # AllowedValues: [2, 4, 8, 16, 32, 64, 192, 384]

Resources:
bmclusterDBSubnetGroup:
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"clean:all": "npm run clean --workspaces --include-workspace-root",
"cycles": "npm run cycles --workspaces",
"prettier": "prettier . -w",
"lint": "npm run lint --workspaces",
"lint": "npm run lint:tests && npm run lint --workspaces",
"lint:tests": "eslint . tests --ext .ts,.tsx --max-warnings 0",
"build:deps": "npm run build -w @busmap/components && npm run build -w @busmap/common",
"test": "playwright test --reporter=list"
},
Expand Down
101 changes: 46 additions & 55 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
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.
*/
Expand All @@ -16,69 +10,66 @@ export default defineConfig({
/* 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,
retries: process.env.CI ? 1 : 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: 'list',
/* 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: 'https://localhost',
baseURL: process.env.TEST_BASE_URL ?? 'https://localhost',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry'
},

/* Configure projects for major browsers */
projects: process.env.CI
? [
/**
* Ubuntu and mkcert issues with Chrome / Firefox
* @see https://github.com/FiloSottile/mkcert/issues/447
*
* Other option is to use macos GitHub action runner and
* install docker, etc. Could also, use `ignoreHTTPSErrors`
* from playwright in the test specs to cover more browsers.
*/
{
name: 'webkit',
use: { ...devices['Desktop Safari'] }
},

/* Test against mobile viewports. */
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] }
}
]
: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] }
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] }
},
projects: [
/**
* Ubuntu and mkcert issues with Chrome / Firefox
* @see https://github.com/FiloSottile/mkcert/issues/447
*
* Other option is to use macos GitHub action runner and
* install docker, etc. Could also, use `ignoreHTTPSErrors`
* from playwright in the test specs to cover more browsers.
*/
{
name: 'webkit',
use: { ...devices['Desktop Safari'] }
},
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
ignoreHTTPSErrors: Boolean(process.env.CI)
}
},

/* Test against mobile viewports. */
{
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] }
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] }
}
],
/* Test against mobile viewports. */
{
name: 'Mobile Chrome',
use: {
...devices['Pixel 5'],
ignoreHTTPSErrors: Boolean(process.env.CI)
}
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] }
}
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'docker compose -f compose.yaml up --attach-dependencies stage',
ignoreHTTPSErrors: true,
url: 'https://localhost/healthcheck',
reuseExistingServer: !process.env.CI,
timeout: 60_000 * 7
}
webServer: process.env.TEST_BASE_URL
? undefined
: {
command: process.env.CI
? 'docker compose -f compose.yaml up --attach-dependencies stage'
: 'docker compose up --attach-dependencies dev',
ignoreHTTPSErrors: true,
url: 'https://localhost/healthcheck',
reuseExistingServer: !process.env.CI,
timeout: 60_000 * 7
}
})
6 changes: 0 additions & 6 deletions tests/basic.spec.ts

This file was deleted.

20 changes: 20 additions & 0 deletions tests/geolocation/deny.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { test, expect } from '@playwright/test'

test.beforeEach(async ({ context }) => {
await context.clearPermissions()
})

test('Deny geolocation use selector to find stop.', async ({ page }) => {
await page.goto('/')
await expect(
page.getByText('Location permission denied. Check your OS or browser settings.')
).toBeVisible()
await page.getByRole('listitem', { name: 'Selector' }).getByRole('button').click()
await expect(page.getByRole('heading', { name: 'Bus Selector' })).toBeVisible()
await page.getByText('Agency').click()
await page.getByPlaceholder('Agencies ... (64)').fill('toronto')
await page.getByRole('option', { name: 'Toronto Transit Commission' }).click()
await page.getByText('Stop', { exact: true }).click()
await page.getByRole('option', { name: 'Bathurst St At Neptune Dr' }).click()
await expect(page.getByRole('heading', { name: 'Next Arrivals' })).toBeVisible()
})
40 changes: 40 additions & 0 deletions tests/geolocation/omnitrans.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { test, expect } from '@playwright/test'

test.use({
geolocation: {
latitude: 34.10865,
longitude: -117.325531
},
permissions: ['geolocation']
})

test('test', async ({ page, context }) => {
await context.grantPermissions(['geolocation'])
// Navigate to the homepage and select the Nearby stops tab, check for OmniTrans
await page.goto('/')
await page.getByRole('listitem', { name: 'Nearby' }).getByRole('button').click()
await expect(page.getByRole('heading', { name: 'Nearby Stops' })).toBeVisible()
await expect(page.getByRole('heading', { name: 'Omnitrans' })).toBeVisible({
timeout: 10_000
})

// Check that route headings are visible
await expect(page.getByRole('heading', { level: 4 }).first()).toBeVisible()

// Get the stop title link and save the innerText
const link = page.getByRole('heading', { level: 5 }).first().getByRole('link')
const linkText = await link.innerText()

// Click the stop link and check that predictions are rendered with users distance from stop
await link.click()
await expect(page.getByRole('heading', { name: 'Next Arrivals' })).toBeVisible({
timeout: 7_000
})
await expect(page.getByText(/You are .+ miles away/)).toBeVisible()

// Close the flyout menu and check the map for user and stop markers
await page.locator('button').filter({ hasText: 'Close' }).click()
await page.getByRole('button', { name: 'Marker' }).click()
await expect(page.locator('.leaflet-marker-icon').first()).toBeVisible()
await expect(page.locator('#map').getByText(linkText)).toBeVisible()
})
39 changes: 39 additions & 0 deletions tests/geolocation/ttc.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { test, expect } from '@playwright/test'

test.use({
geolocation: {
latitude: 43.69786,
longitude: -79.39712
},
permissions: ['geolocation']
})

test('Nearby stops for Toronto Transit Commission.', async ({ page }) => {
await page.goto('/')
await page.getByRole('listitem', { name: 'Nearby' }).getByRole('button').click()
await expect(page.getByRole('heading', { name: 'Nearby Stops' })).toBeVisible()
await expect(page.getByText('Monitoring your location.')).toBeVisible()
await expect(page.getByRole('heading', { name: 'Toronto TTC' })).toBeVisible({
timeout: 10_000
})

// Check that route headings are visible
await expect(page.getByRole('heading', { level: 4 }).first()).toBeVisible()

// Get the stop title link and save the innerText
const link = page.getByRole('heading', { level: 5 }).first().getByRole('link')
const linkText = await link.innerText()

// Click the stop link and check that predictions are rendered with users distance from stop
await link.click()
await expect(page.getByRole('heading', { name: 'Next Departures' })).toBeVisible({
timeout: 7_000
})
await expect(page.getByText(/You are .+ miles away/)).toBeVisible()

// Close the flyout menu and check the map for user and stop markers
await page.locator('button').filter({ hasText: 'Close' }).click()
await page.getByRole('button', { name: 'Marker' }).click()
await expect(page.locator('.leaflet-marker-icon').first()).toBeVisible()
await expect(page.locator('#map').getByText(linkText)).toBeVisible()
})
15 changes: 15 additions & 0 deletions tests/selector/agencyStop.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { test, expect } from '@playwright/test'

test('Select an agency and stop to see arrivals.', async ({ page }) => {
await page.goto('/')
await page.getByRole('listitem', { name: 'Selector' }).getByRole('button').click()
await expect(page.getByRole('heading', { name: 'Bus Selector' })).toBeVisible()
await page.getByText('Agency').click()
await page.getByRole('option', { name: 'Toronto Transit Commission' }).click()
await page.getByText('Stop', { exact: true }).click()
await page.getByRole('option', { name: 'Bathurst St At Neptune Dr' }).click()
await expect(page.getByRole('heading', { name: 'Next Arrivals' })).toBeVisible()
await page.locator('button').filter({ hasText: 'Close' }).click()
await page.getByRole('button', { name: 'Marker' }).click()
await page.locator('#map').getByText('Bathurst St At Neptune Dr').click()
})

0 comments on commit aac2593

Please sign in to comment.