Skip to content

Commit b121d0e

Browse files
committed
add site unit tests
1 parent ab1ed8a commit b121d0e

File tree

4 files changed

+154
-2
lines changed

4 files changed

+154
-2
lines changed

.github/workflows/test.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ concurrency:
2121
cancel-in-progress: true
2222

2323
jobs:
24-
tests:
24+
pytest:
2525
strategy:
2626
matrix:
2727
os: [ubuntu-latest, windows-latest]
@@ -31,6 +31,12 @@ jobs:
3131
python-version: "3.11"
3232
install-cmd: pip install -e .[test,symmetry]
3333

34+
vitest:
35+
uses: janosh/workflows/.github/workflows/npm-test.yml@main
36+
with:
37+
working-directory: site
38+
install-e2e: ""
39+
3440
scripts:
3541
runs-on: ubuntu-latest
3642
strategy:

site/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"preview": "vite preview",
1515
"serve": "vite build && vite preview",
1616
"check": "svelte-check",
17+
"test": "vitest",
1718
"changelog": "npx auto-changelog --output ../changelog.md --hide-credit --commit-limit false"
1819
},
1920
"devDependencies": {
@@ -32,6 +33,7 @@
3233
"hastscript": "^9.0.0",
3334
"highlight.js": "^11.10.0",
3435
"js-yaml": "^4.1.0",
36+
"jsdom": "^25.0.1",
3537
"json-schema-to-typescript": "^15.0.3",
3638
"katex": "^0.16.15",
3739
"mdsvex": "^0.12.3",
@@ -55,7 +57,8 @@
5557
"typescript": "5.7.2",
5658
"typescript-eslint": "^8.18.0",
5759
"unified": "^11.0.5",
58-
"vite": "^5.4.10"
60+
"vite": "^5.4.10",
61+
"vitest": "^2.1.8"
5962
},
6063
"prettier": {
6164
"semi": false,

site/tests/landing_page.test.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { tick } from 'svelte'
2+
import { beforeEach, describe, expect, it } from 'vitest'
3+
import Page from '../src/routes/+page.svelte'
4+
5+
describe(`Landing Page`, () => {
6+
beforeEach(() => {
7+
document.body.innerHTML = ``
8+
new Page({ target: document.body })
9+
})
10+
11+
it(`renders discovery set toggle buttons`, () => {
12+
const buttons = document.body.querySelectorAll(`.discovery-set-toggle button`)
13+
expect(buttons).toHaveLength(3)
14+
15+
const button_texts = Array.from(buttons).map((btn) => btn.textContent?.trim())
16+
expect(button_texts).toContain(`Full Test Set`)
17+
expect(button_texts).toContain(`Unique Prototypes`)
18+
expect(button_texts).toContain(`10k Most Stable`)
19+
})
20+
21+
it(`toggles discovery set when clicking buttons`, async () => {
22+
const buttons = document.body.querySelectorAll(`.discovery-set-toggle button`)
23+
const [full_test_btn, unique_protos_btn] = buttons
24+
25+
// Initially Unique Prototypes should be active
26+
expect(unique_protos_btn.classList.contains(`active`)).toBe(true)
27+
expect(full_test_btn.classList.contains(`active`)).toBe(false)
28+
29+
// Click Full Test Set button
30+
full_test_btn.click()
31+
await tick()
32+
33+
expect(unique_protos_btn.classList.contains(`active`)).toBe(false)
34+
expect(full_test_btn.classList.contains(`active`)).toBe(true)
35+
})
36+
37+
it(`toggles column visibility panel`, async () => {
38+
const columns_btn = document.body.querySelector(`details.column-toggles summary`)
39+
const column_menu = document.body.querySelector(`.column-menu`)
40+
41+
// Column menu should be hidden initially
42+
expect(column_menu?.closest(`details`)?.open).toBe(false)
43+
44+
// Click columns button to open menu
45+
columns_btn?.click()
46+
expect(column_menu?.closest(`details`)?.open).toBeTruthy()
47+
48+
// Click outside to close menu
49+
columns_btn?.click()
50+
expect(column_menu?.closest(`details`)?.open).toBe(false)
51+
})
52+
53+
it(`toggles non-compliant models`, async () => {
54+
const toggle = document.body.querySelector(`input[type="checkbox"]`)
55+
expect(toggle).toBeDefined()
56+
57+
// Should be unchecked by default
58+
expect(toggle?.checked).toBe(false)
59+
// get number of table rows
60+
const n_compliant_models = document.body.querySelectorAll(`tbody tr`).length
61+
62+
// Click to show non-compliant models
63+
toggle?.click()
64+
expect(toggle?.checked).toBe(true)
65+
await tick()
66+
const n_all_models = document.body.querySelectorAll(`tbody tr`).length
67+
expect(n_all_models).toBeGreaterThan(n_compliant_models)
68+
})
69+
70+
it(`updates column visibility when toggling checkboxes`, async () => {
71+
const columns_btn = document.body.querySelector(`details.column-toggles summary`)
72+
columns_btn?.click()
73+
await tick()
74+
// Table should reflect column visibility changes
75+
let f1_cells = document.body.querySelectorAll(`th, td`)
76+
let has_f1_column = Array.from(f1_cells).some((cell) =>
77+
cell.textContent?.includes(`F1`),
78+
)
79+
expect(has_f1_column).toBe(true)
80+
81+
const checkboxes = document.body.querySelectorAll(
82+
`.column-menu input[type="checkbox"]`,
83+
)
84+
const f1_checkbox = Array.from(checkboxes).find((cb) =>
85+
cb.parentElement?.textContent?.includes(`F1`),
86+
)
87+
expect(f1_checkbox?.checked).toBe(true)
88+
89+
// Uncheck F1
90+
f1_checkbox?.click()
91+
await tick()
92+
expect(f1_checkbox?.checked).toBe(false)
93+
94+
// Table should reflect column visibility changes
95+
f1_cells = document.body.querySelectorAll(`th, td`)
96+
has_f1_column = Array.from(f1_cells).some((cell) => cell.textContent?.includes(`F1`))
97+
expect(has_f1_column).toBe(false)
98+
})
99+
100+
it(`displays best model information`, () => {
101+
const best_model_info = document.body.querySelector(`[slot="best-report"]`)
102+
expect(best_model_info?.textContent).toMatch(/highest F1 score/)
103+
expect(best_model_info?.textContent).toMatch(/discovery acceleration factor/)
104+
})
105+
106+
it(`renders table downloads section`, () => {
107+
const download_links = document.body.querySelectorAll(`.downloads a`)
108+
expect(download_links).toHaveLength(2)
109+
110+
const [pdf_link, svg_link] = download_links
111+
expect(pdf_link.getAttribute(`href`)).toMatch(/\.pdf$/)
112+
expect(svg_link.getAttribute(`href`)).toMatch(/\.svg$/)
113+
})
114+
115+
it(`displays valid metric values`, () => {
116+
const best_model_info = document.body.querySelector(`[slot="best-report"]`)
117+
const text = best_model_info?.textContent || ``
118+
119+
// Extract F1 and DAF values using regex
120+
const f1_match = text.match(/F1 score of ([\d.]+)/)
121+
const daf_match = text.match(/DAF\) of ([\d.]+)/)
122+
123+
if (f1_match && daf_match) {
124+
const f1_value = parseFloat(f1_match[1])
125+
const daf_value = parseFloat(daf_match[1])
126+
127+
expect(0 < f1_value && f1_value < 1, `F1=${f1_value} is out of range`).toBe(true)
128+
expect(0 < daf_value && daf_value < 10, `DAF=${daf_value} is out of range`).toBe(
129+
true,
130+
)
131+
} else {
132+
throw new Error(`Could not find F1 or DAF values in text: ${text}`)
133+
}
134+
})
135+
})

site/vite.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,12 @@ export default {
1313
preview: {
1414
port: 3000,
1515
},
16+
17+
test: {
18+
environment: `jsdom`,
19+
css: true,
20+
coverage: {
21+
reporter: [`text`, `json-summary`],
22+
},
23+
},
1624
} satisfies UserConfig

0 commit comments

Comments
 (0)