Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add more e2e specs. #179

Merged
merged 6 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
})