Skip to content

Commit

Permalink
test: playwright tests for genotype presets (#1831)
Browse files Browse the repository at this point in the history
tests are executed within Storybook to re-use the backend mocking
  • Loading branch information
Gregoor authored Jul 23, 2024
1 parent 5a0f325 commit 8d39e44
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 33 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Playwright Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,7 @@ Session.vim
tags

.DS_Store
/test-results/
playwright-report/
/blob-report/
/playwright/.cache/
75 changes: 75 additions & 0 deletions frontend/end-to-end-tests/seqvar-filtration.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { expect, test } from '@playwright/test'

test.beforeEach(async ({ page }) => {
await page.goto(
'http://localhost:6006/iframe.html?globals=backgrounds.grid:!false;backgrounds.value:!hex(F8F8F8)&id=seqvars-seqvars-filtration--example',
)
})

test('modified genotype preset is marked', async ({ page }) => {
page.locator('button[aria-label="Create query based on dominant"]').click()

const selectedGenotypePreset = page.locator(
'[aria-selected="true"]:below(:text("Genotype")):has-text("dominant")',
)
await expect(selectedGenotypePreset.first()).toBeVisible()

const modifiedPreset = selectedGenotypePreset.locator('[data-test-modified]')
await expect(modifiedPreset).toBeHidden()
await page.getByRole('button', { name: '1/0' }).first().click()
await expect(modifiedPreset).toBeVisible()
})

test.describe('genotype', () => {
test.beforeEach(async ({ page }) => {
await page
.locator('button[aria-label="Create query based on de novo"]')
.click()
})

test('any is checked when all types are checked', async ({ page }) => {
const firstAnyButton = page
.getByRole('button', { name: 'any' })
.and(page.locator('[aria-selected]'))
.first()
await expect(firstAnyButton).toHaveAttribute('aria-selected', 'false')
for (const name of ['0/0', '1/0', '1/1']) {
const button = page.getByRole('button', { name }).first()
if ((await button.getAttribute('aria-selected')) === 'false') {
await button.click()
}
}
await expect(firstAnyButton).toHaveAttribute('aria-selected', 'true')
})
})

test.describe('genotype (recessive)', () => {
test.beforeEach(async ({ page }) => {
await page
.locator('button[aria-label="Create query based on recessive"]')
.click()
})

test('index radios are mutually exclusive', async ({ page }) => {
await page
.locator('input[type="radio"][aria-label="Index"]:not(:checked)')
.first()
.click()
await expect(
page.locator('input[type="radio"][aria-label="Index"]:checked'),
).toHaveCount(1)
})

test('only two parent radios can be selected', async ({ page }) => {
const parentRadios = page.locator(
'input[type="radio"][aria-label="Parent"]',
)
expect(await parentRadios.count()).toBe(3)
for (const parent of await parentRadios.all()) {
await parent.click()
}
await expect(await parentRadios.and(page.locator(':checked'))).toHaveCount(
2,
)
})
})
103 changes: 82 additions & 21 deletions frontend/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 frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@iconify-json/medical-icon": "^1.1.8",
"@iconify-json/oi": "^1.1.8",
"@pinia/testing": "0.1.3",
"@playwright/test": "^1.45.1",
"@popperjs/core": "^2.11.8",
"@rushstack/eslint-patch": "^1.10.3",
"@storybook/addon-essentials": "^8.2.2",
Expand All @@ -75,6 +76,7 @@
"@storybook/vue3-vite": "^8.1.5",
"@testing-library/vue": "^8.1.0",
"@types/jquery": "^3.5.29",
"@types/node": "^20.14.10",
"@vitejs/plugin-vue": "^5.0.5",
"@vitest/coverage-istanbul": "^1.4.0",
"@vue/compiler-sfc": "^3.4.33",
Expand Down
36 changes: 36 additions & 0 deletions frontend/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { defineConfig, devices } from '@playwright/test'

export default defineConfig({
testDir: './end-to-end-tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
trace: 'on-first-retry',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],

webServer: {
command: 'npm run storybook',
url: 'http://127.0.0.1:6006',
reuseExistingServer: !process.env.CI,
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,29 @@ const hom = getNumberComputedForKeys('homozygous', 'homoplasmic')
}}<span v-if="size != null" style="color: #808080">{{ size }}k</span>
</label>

<Input v-model="freq" style="grid-column: 2; margin-right: 8px; width: 56px">
<Input
v-model="freq"
:aria-label="'frequency' in model ? 'frequency' : 'carriers'"
style="grid-column: 2; margin-right: 8px; width: 56px"
>
<template v-if="'frequency' in model" #after>%</template></Input
>
<Input v-model="het" type="number" style="width: 40px" />
<Input v-model="hom" type="number" style="width: 40px" />
<Input
v-model="het"
aria-label="heterozygous"
type="number"
style="width: 40px"
/>
<Input
v-model="hom"
aria-label="homozygous"
type="number"
style="width: 40px"
/>
<Input
v-if="'hemizygous' in model"
v-model="model.hemizygous"
aria-label="hemizygous"
type="number"
style="width: 40px"
/>
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/seqvars/components/Input.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
<script setup lang="ts">
import type { CSSProperties } from 'vue'
const props = defineProps<{ style?: CSSProperties; type?: 'text' | 'number' }>()
const props = defineProps<{
style?: CSSProperties
type?: 'text' | 'number'
ariaLabel?: string
}>()
const model = defineModel<string | number>()
</script>

<template>
<div class="root" :style="props.style">
<input v-model="model" :type="props.type ?? 'text'" />
<input
v-model="model"
:aria-label="props.ariaLabel"
:type="props.type ?? 'text'"
/>
<slot name="after"></slot>
</div>
</template>
Expand Down
Loading

0 comments on commit 8d39e44

Please sign in to comment.