Skip to content

Commit 9100958

Browse files
committed
Updating tests and removing test results
1 parent be24dac commit 9100958

File tree

7 files changed

+393
-18
lines changed

7 files changed

+393
-18
lines changed

.github/workflows/svelte_integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches: [ main, master ]
66
pull_request:
77
branches: [ main, master ]
8-
8+
99

1010
workflow_dispatch:
1111

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"bits-ui": "2.9.4",
6161
"flexsearch": "^0.8.205",
6262
"ioredis": "^5.7.0",
63-
"lucide-svelte": "^0.541.0",
63+
"lucide-svelte": "^0.542.0",
6464
"scrape-it": "^6.1.11",
6565
"sharp": "^0.34.3",
6666
"svelte-local-storage-store": "^0.6.4"

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-results/.last-run.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

tests/home.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ test.describe('Home page', () => {
3131
await expect(link).toBeVisible();
3232

3333
const before = await link.evaluate((el) => {
34-
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
34+
const cs = getComputedStyle(el);
3535
return { color: cs.color };
3636
});
3737
await link.hover();
3838
const after = await link.evaluate((el) => {
39-
const cs = getComputedStyle(el as Element) as CSSStyleDeclaration;
39+
const cs = getComputedStyle(el);
4040
return { color: cs.color };
4141
});
4242

@@ -55,7 +55,7 @@ test.describe('Home page', () => {
5555
const nav = page.locator(area);
5656
const link = nav.getByRole('link', { name: 'Home', exact: true });
5757
await expect(link).toBeVisible();
58-
const isActive = await link.evaluate((el) => (el as Element).classList.contains('active'));
58+
const isActive = await link.evaluate((el) => el.classList.contains('active'));
5959
expect(isActive).toBeTruthy();
6060
}
6161
});
@@ -193,9 +193,9 @@ test.describe('Home page', () => {
193193

194194
// Layout: single column and scrollable vertically
195195
const scrollInfo = await albumsGrid.evaluate((el) => ({
196-
overflowY: getComputedStyle(el as HTMLElement).overflowY,
197-
scrollHeight: (el as HTMLElement).scrollHeight,
198-
clientHeight: (el as HTMLElement).clientHeight,
196+
overflowY: getComputedStyle(el).overflowY,
197+
scrollHeight: el.scrollHeight,
198+
clientHeight: el.clientHeight,
199199
}));
200200
expect(scrollInfo.clientHeight).toBeLessThan(scrollInfo.scrollHeight);
201201
expect(['auto', 'scroll']).toContain(scrollInfo.overflowY);
@@ -216,7 +216,7 @@ test.describe('Home page', () => {
216216

217217
// Articles are a vertical list (same x, increasing y)
218218
const boxes = await page.locator('section.articles article.card').evaluateAll((els) =>
219-
(els as HTMLElement[]).slice(0, Math.min(4, els.length)).map((el) => el.getBoundingClientRect())
219+
els.slice(0, Math.min(4, els.length)).map((el) => el.getBoundingClientRect())
220220
);
221221
expect(boxes.length).toBeGreaterThan(0);
222222
const x0 = boxes[0].left;

tests/portfolio.test.ts

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test.describe('Portfolio page', () => {
4+
test('has expected main heading', async ({ page }) => {
5+
await page.goto('/portfolio');
6+
await expect(page.getByRole('heading', { level: 1, name: 'Portfolio!' })).toBeVisible();
7+
});
8+
9+
test('header/footer links hover: color becomes shellYellow', async ({ page }) => {
10+
await page.goto('/portfolio');
11+
12+
const shellYellow = await page.evaluate(() => {
13+
const probe = document.createElement('div');
14+
probe.style.color = 'var(--shellYellow)';
15+
document.body.appendChild(probe);
16+
const color = getComputedStyle(probe).color;
17+
probe.remove();
18+
return color;
19+
});
20+
21+
const areas = [
22+
'header[aria-label="header navigation"]',
23+
'footer nav[aria-label="footer navigation"]',
24+
];
25+
26+
for (const area of areas) {
27+
const nav = page.locator(area);
28+
await expect(nav).toBeVisible();
29+
30+
const link = nav.getByRole('link', { name: 'Portfolio', exact: true });
31+
await expect(link).toBeVisible();
32+
33+
const before = await link.evaluate((el) => getComputedStyle(el as Element).color);
34+
await link.hover();
35+
const after = await link.evaluate((el) => getComputedStyle(el as Element).color);
36+
37+
expect(after).toBe(shellYellow);
38+
expect(after).not.toBe(before);
39+
}
40+
});
41+
42+
test('current page (Portfolio) link is active in header and footer', async ({ page }) => {
43+
await page.goto('/portfolio');
44+
const areas = [
45+
'header[aria-label="header navigation"]',
46+
'footer nav[aria-label="footer navigation"]',
47+
];
48+
for (const area of areas) {
49+
const nav = page.locator(area);
50+
const portfolioLink = nav.getByRole('link', { name: 'Portfolio', exact: true });
51+
await expect(portfolioLink).toBeVisible();
52+
const isActive = await portfolioLink.evaluate((el) => (el as Element).classList.contains('active'));
53+
expect(isActive).toBeTruthy();
54+
}
55+
});
56+
57+
test('tabs render and can switch between Personal and Professional', async ({ page }) => {
58+
await page.goto('/portfolio');
59+
60+
// Prefer role-based tab selection; fall back to data attribute if role is not present
61+
const personalTab = page.getByRole('tab', { name: 'Personal' }).or(page.locator('[data-tabs-trigger]', { hasText: 'Personal' }));
62+
const professionalTab = page.getByRole('tab', { name: 'Professional' }).or(page.locator('[data-tabs-trigger]', { hasText: 'Professional' }));
63+
64+
await expect(personalTab).toBeVisible();
65+
await expect(professionalTab).toBeVisible();
66+
67+
// Personal content visible by default (card heading exists)
68+
const personalCardHeading = page.locator('.portfolio-picture h2', { hasText: 'Personal Website' }).first();
69+
await expect(personalCardHeading).toBeVisible();
70+
71+
// Switch to Professional
72+
await professionalTab.click();
73+
74+
// Professional content appears, personal may hide
75+
const professionalCardHeading = page.locator('.portfolio-picture h2', { hasText: 'Mark Shellnut Architect' }).first();
76+
await expect(professionalCardHeading).toBeVisible();
77+
});
78+
79+
test('personal tab: key cards, images, and external links are accessible', async ({ page }) => {
80+
await page.goto('/portfolio');
81+
82+
// Ensure on Personal tab
83+
const personalTab = page.getByRole('tab', { name: 'Personal' }).or(page.locator('[data-tabs-trigger]', { hasText: 'Personal' }));
84+
await personalTab.click();
85+
86+
// Headings (scoped to portfolio cards to avoid strict-mode conflicts)
87+
await expect(page.locator('.portfolio-picture h2', { hasText: 'Personal Website' }).first()).toBeVisible();
88+
await expect(page.locator('.portfolio-picture h2', { hasText: 'Wedding Website' }).first()).toBeVisible();
89+
await expect(page.locator('.portfolio-picture h2', { hasText: 'Old Personal Website' }).first()).toBeVisible();
90+
91+
// Images by alt text
92+
await expect(page.getByAltText("Picture of Bradley Shellnut's Personal Website")).toBeVisible();
93+
await expect(page.getByAltText('Picture of NextJS Wedding Website')).toBeVisible();
94+
await expect(page.getByAltText('Home Page of the old bradleyshellnut.com website')).toBeVisible();
95+
96+
// External links (use visible link names)
97+
await expect(page.getByRole('link', { name: /GitHub repository/i }).first()).toBeVisible();
98+
});
99+
100+
test('professional tab: card renders with external link', async ({ page }) => {
101+
await page.goto('/portfolio');
102+
103+
const professionalTab = page.getByRole('tab', { name: 'Professional' }).or(page.locator('[data-tabs-trigger]', { hasText: 'Professional' }));
104+
await professionalTab.click();
105+
106+
const professionalCard = page
107+
.locator('.portfolio')
108+
.filter({ has: page.locator('.portfolio-picture h2', { hasText: 'Mark Shellnut Architect' }) })
109+
.first();
110+
111+
await expect(professionalCard).toBeVisible();
112+
// Accessible name derived from aria-label in ExternalLink.svelte
113+
await expect(
114+
professionalCard.getByRole('link', { name: /Open\s+View Mark Shellnut Architect\s+externally/i })
115+
).toBeVisible();
116+
});
117+
118+
// Mirror header link presence from other pages
119+
test('header navigation shows expected links', async ({ page }) => {
120+
await page.goto('/portfolio');
121+
const headerNav = page.locator('header[aria-label="header navigation"]');
122+
await expect(headerNav).toBeVisible();
123+
await expect(headerNav.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
124+
await expect(headerNav.getByRole('link', { name: 'About', exact: true })).toBeVisible();
125+
await expect(headerNav.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
126+
await expect(headerNav.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
127+
});
128+
129+
// Mirror navigation flow via header (starting on /portfolio)
130+
test('header navigation links go to correct routes (from /portfolio)', async ({ page }) => {
131+
await page.goto('/portfolio');
132+
const headerNav = page.locator('header[aria-label="header navigation"]');
133+
134+
await headerNav.getByRole('link', { name: 'About', exact: true }).click();
135+
await expect(page).toHaveURL(/\/about\/?$/);
136+
137+
await headerNav.getByRole('link', { name: 'Uses', exact: true }).click();
138+
await expect(page).toHaveURL(/\/uses\/?$/);
139+
140+
await headerNav.getByRole('link', { name: 'Home', exact: true }).click();
141+
await expect(page).toHaveURL(/\/?$/);
142+
143+
await headerNav.getByRole('link', { name: 'Portfolio', exact: true }).click();
144+
await expect(page).toHaveURL(/\/portfolio\/?$/);
145+
});
146+
147+
// Mirror footer link presence from other pages
148+
test('footer shows expected links', async ({ page }) => {
149+
await page.goto('/portfolio');
150+
const footerNav = page.getByRole('navigation', { name: 'footer navigation' });
151+
await expect(footerNav).toBeVisible();
152+
await expect(footerNav.getByRole('link', { name: 'Home', exact: true })).toBeVisible();
153+
await expect(footerNav.getByRole('link', { name: 'About', exact: true })).toBeVisible();
154+
await expect(footerNav.getByRole('link', { name: 'Portfolio', exact: true })).toBeVisible();
155+
await expect(footerNav.getByRole('link', { name: 'Uses', exact: true })).toBeVisible();
156+
await expect(footerNav.getByRole('link', { name: 'Privacy', exact: true })).toBeVisible();
157+
await expect(footerNav.getByRole('link', { name: 'Favorite Articles', exact: true })).toBeVisible();
158+
});
159+
160+
// Mirror navigation via footer (starting on /portfolio)
161+
test('footer navigation links go to correct routes (from /portfolio)', async ({ page }) => {
162+
await page.goto('/portfolio');
163+
const footerNav = page.getByRole('navigation', { name: 'footer navigation' });
164+
165+
await footerNav.getByRole('link', { name: 'Privacy', exact: true }).scrollIntoViewIfNeeded();
166+
await footerNav.getByRole('link', { name: 'Privacy', exact: true }).click();
167+
await expect(page).toHaveURL(/\/privacy\/?$/);
168+
169+
// Favorite Articles may route to /articles or /articles/1
170+
const fav = footerNav.getByRole('link', { name: 'Favorite Articles', exact: true });
171+
await fav.scrollIntoViewIfNeeded();
172+
const href = await fav.getAttribute('href');
173+
expect(href).toBeTruthy();
174+
if (href) {
175+
expect(href).toMatch(/\/articles(\/\d+)?\/?$/);
176+
await page.goto(href);
177+
await expect(page).toHaveURL(/\/articles(\/\d+)?\/?$/, { timeout: 15000 });
178+
}
179+
180+
await footerNav.getByRole('link', { name: 'About', exact: true }).scrollIntoViewIfNeeded();
181+
await footerNav.getByRole('link', { name: 'About', exact: true }).click();
182+
await expect(page).toHaveURL(/\/about\/?$/);
183+
184+
await footerNav.getByRole('link', { name: 'Home', exact: true }).scrollIntoViewIfNeeded();
185+
await footerNav.getByRole('link', { name: 'Home', exact: true }).click();
186+
await expect(page).toHaveURL(/\/?$/);
187+
});
188+
});

0 commit comments

Comments
 (0)