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

Create first e2e tests for cert creation #28

Merged
merged 22 commits into from Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Expand Up @@ -3,7 +3,7 @@ DATABASE_URL=postgresql://im-app:empty@127.0.0.1:54321/im-app

NEXT_APP_URL=

NEXTAUTH_URL=http://localhost:3000
FRONTEND_URL=http://localhost:3000

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
Expand Down
6 changes: 3 additions & 3 deletions .env.test
@@ -1,11 +1,11 @@
# Nonstandard port to avoid clashes with other local DB servers.
# Also a unique port for testing, so users can run automated tests locally without clashing with
# their local manual testing.
DATABASE_URL=postgresql://im-app:empty@127.0.0.1:54322/im-app
DATABASE_URL=postgresql://im-app:empty@127.0.0.1:54322/im-app-test

NEXT_APP_URL=
NEXT_APP_URL=http://localhost:3001

NEXTAUTH_URL=http://localhost:3000
FRONTEND_URL=http://localhost:3001

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/node.js.yml
Expand Up @@ -5,9 +5,9 @@ name: Tests, style checks, and type checks

on:
push:
branches: ['main', 'beta', 'development', 'test-system']
branches: '**'
pull_request:
branches: ['main', 'beta', 'development', 'test-system']
branches: '**'

jobs:
test-unit:
Expand Down Expand Up @@ -63,12 +63,10 @@ jobs:
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Set up environment variables for the test env
run: cp .env.test .env
- name: Start the test database
run: docker-compose -f docker-compose.test.yaml up -d
- name: Create the database schema
run: npx prisma migrate deploy
run: npx dotenv -e .env.test -- npx prisma migrate deploy
- name: Run Playwright tests
run: npm run test:e2e
- uses: actions/upload-artifact@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -31,6 +31,7 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local
.env.backup

# vercel
.vercel
Expand Down
8 changes: 7 additions & 1 deletion docker-compose.test.yaml
@@ -1,7 +1,7 @@
version: '3.5'

services:
postgres:
postgres-test:
image: 'postgres:14-alpine'
volumes:
- postgres-data:/var/lib/postgresql/data/
Expand All @@ -10,6 +10,12 @@ services:
- POSTGRES_PASSWORD=empty
ports:
- '127.0.0.1:54322:5432'
networks:
- test

networks:
test:
name: test

volumes:
postgres-data:
1 change: 1 addition & 0 deletions env/server.ts
Expand Up @@ -58,6 +58,7 @@ export const serverEnv = {
allowEmpty: true,
devDefault: 'http://localhost:3000',
}),
FRONTEND_URL: str(),
NEXTAUTH_SECRET: str({
devDefault: 'xxx',
}),
Expand Down
2 changes: 1 addition & 1 deletion lib/auth.ts
Expand Up @@ -53,7 +53,7 @@ if (serverEnv.MOCK_LOGIN) {
authOptions.callbacks!.jwt = async ({ token }) => {
const email = 'mock.user@example.com'
const name = 'Mock User'
const image = 'http://localhost:3000/images/logo-min-light.png'
const image = serverEnv.FRONTEND_URL + '/images/logo-min-light.png'
const role = Role.USER
const user = await prisma.user.upsert({
select: { id: true, name: true, role: true, image: true, email: true },
Expand Down
73 changes: 57 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -41,6 +41,8 @@
"csstype": "^3.1.0",
"cuid": "^2.1.8",
"date-fns": "^2.29.1",
"dotenv": "^16.0.3",
"dotenv-cli": "^6.0.0",
"envsafe": "^2.0.3",
"gemoji": "^7.1.0",
"isomorphic-dompurify": "^0.20.0",
Expand Down
14 changes: 8 additions & 6 deletions playwright.config.ts
Expand Up @@ -5,7 +5,7 @@ import { devices } from '@playwright/test'
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
require('dotenv').config({ path: '.env.test' })

/**
* See https://playwright.dev/docs/test-configuration.
Expand All @@ -25,8 +25,8 @@ const config: PlaywrightTestConfig = {
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,
/* Retry on both CI and local dev */
retries: 2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you already notice brittleness or is this just in case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed, pretty frequently, the Chromium browser will just sit and timeout after 30 seconds waiting for the first page to load. Retries have made it work.

Not sure why; Firefox and Webkit have not experienced this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, weird. Thanks!

/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
Expand All @@ -36,10 +36,12 @@ 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: 'http://localhost:3001',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
/* Switch to false to see the browser */
headless: true,
},

/* Configure projects for major browsers */
Expand Down Expand Up @@ -99,8 +101,8 @@ const config: PlaywrightTestConfig = {

/* Run your local dev server before starting the tests */
webServer: {
command: 'npm run dev',
port: 3000,
command: 'PORT=3001 npm run dev',
url: 'http://localhost:3001',
},
}

Expand Down
70 changes: 70 additions & 0 deletions tests/e2e/create-cert.test.ts
@@ -0,0 +1,70 @@
import { type Page, expect, test } from '@playwright/test'

const proofText = 'https://forum.effectivealtruism.org'
const counterfactualText = 'I would be sitting around doing nothing.'
const descriptionText = 'Just a random description.'

test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3001/')
await page.click('text=Log in')
await page.click('text=Sign in with Mock Login')
})

test.describe('Create Certificate', () => {
test('should allow creating new certificate', async ({ page }) => {
const titleText = 'My test project 0001'

await page.click('text=New project')
await fillInDefaultValues(page, titleText)
await page.locator('button:has-text("Submit")').click()

// Check we've landed on the cert page.
await expect(page).toHaveTitle(new RegExp('.*' + titleText + '.*'))
})

test('should fill in all certificate values', async ({ page }) => {
const titleText = 'My test project 0002'

await page.click('text=New project')
await fillInDefaultValues(page, titleText)
await page.locator('button:has-text("Submit")').click()

// Check we've landed on the cert page.
await expect(page).toHaveTitle(new RegExp('.*' + titleText + '.*'))

// Verify certificate values.
await expect(page.getByRole('heading', { level: 1 })).toContainText(
titleText
)
await expect(page.locator('text=Proof of ownership')).toHaveAttribute(
'href',
proofText
)
await page.locator('text=' + descriptionText).click() // Just clicking to verify it's there.
})
})

async function fillInDefaultValues(page: Page, titleText: string) {
await page.getByRole('textbox', { name: 'title' }).fill(titleText)
await page.getByRole('textbox', { name: 'proof' }).fill(proofText)

// TODO: start + end dates
//await page.getByRole('textbox', { name: 'actionStart' }).fill(actionStartText)
//await page.getByRole('textbox', { name: 'actionEnd' }).fill(actionEndText)

await page
.getByRole('textbox', { name: 'counterfactual' })
.fill(counterfactualText)

// TODO: Tags
//await page.selectOption('#tags', [{label: tagLabel}])

await page.locator(':nth-match(textarea, 1)').fill(descriptionText)

// TODO: Advanced options

await page.click('text=I will never sell these rights more than once')
await page.click(
'text=I am happy for this record to be publicly accessible forever'
)
}