Skip to content

Commit 7997c18

Browse files
committed
Add Calendar component E2E test
1 parent cf753ac commit 7997c18

3 files changed

Lines changed: 152 additions & 31 deletions

File tree

‎src/pages/testing/calendar.astro‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
import BaseLayout from '@layouts/BaseLayout.astro'
3+
import CalendarComponent from '@components/Calendar/index.astro'
4+
5+
export const prerender = true
6+
7+
const pageTitle = 'Calendar Component Test Fixture'
8+
const fixtureDescription =
9+
'Dedicated route reserved for validating the Add to Calendar component with deterministic event metadata.'
10+
const pagePath = '/testing/calendar'
11+
---
12+
13+
<BaseLayout pageTitle={pageTitle} path={pagePath} pageDescription={fixtureDescription} noindex>
14+
<section class="mx-auto flex max-w-4xl flex-col items-center gap-8 px-4 py-10">
15+
<header class="max-w-3xl text-center space-y-4">
16+
<p class="text-xs uppercase tracking-widest text-content-active">Testing Fixture</p>
17+
<h1 class="text-3xl font-semibold leading-tight">{pageTitle}</h1>
18+
<p class="text-content-active">{fixtureDescription}</p>
19+
</header>
20+
21+
<article class="w-full max-w-2xl space-y-6 rounded-lg border border-trim bg-page-offset p-6 shadow-sm">
22+
<div class="space-y-2">
23+
<p class="text-xs uppercase tracking-wider text-content-active">Fixture Event</p>
24+
<h2 class="text-2xl font-semibold">Team sync</h2>
25+
<p class="text-content-active">
26+
Stable event data for validating Google Calendar, Outlook, and `.ics` download actions.
27+
</p>
28+
</div>
29+
30+
<div class="flex justify-center">
31+
<CalendarComponent
32+
name="Team sync"
33+
startDate="2030-01-02"
34+
startTime="13:00"
35+
endDate="2030-01-02"
36+
endTime="14:00"
37+
location="Remote"
38+
description="Weekly team sync"
39+
>
40+
Add to calendar
41+
</CalendarComponent>
42+
</div>
43+
</article>
44+
</section>
45+
</BaseLayout>
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* Calendar component tests
3+
* Covers the dedicated testing fixture for the Add to Calendar menu and download actions.
4+
*/
5+
6+
import { readFile } from 'node:fs/promises'
7+
import { BasePage, expect, test } from '@test/e2e/helpers'
8+
9+
const fixturePath = '/testing/calendar'
10+
const componentSelector = '[data-testid="add-to-calendar"]'
11+
const triggerSelector = `${componentSelector} [data-calendar-trigger]`
12+
const menuSelector = `${componentSelector} [data-calendar-menu]`
13+
const googleLinkSelector = `${componentSelector} [data-calendar-link="google"]`
14+
const outlookLinkSelector = `${componentSelector} [data-calendar-link="outlook"]`
15+
const downloadButtonSelector = `${componentSelector} [data-calendar-download-ics]`
16+
17+
const loadCalendarFixture = async (playwrightPage: Parameters<typeof BasePage.init>[0]) => {
18+
const page = await BasePage.init(playwrightPage)
19+
await page.goto(fixturePath)
20+
await expect(page.locator(componentSelector)).toBeVisible()
21+
return page
22+
}
23+
24+
test.describe('Calendar Component', () => {
25+
test('@ready renders the testing fixture with a collapsed calendar menu', async ({ page: playwrightPage }) => {
26+
const page = await loadCalendarFixture(playwrightPage)
27+
28+
await expect(playwrightPage.getByRole('heading', { name: 'Calendar Component Test Fixture' })).toBeVisible()
29+
await expect(page.locator(triggerSelector)).toHaveText(/Add to calendar/i)
30+
await expect(page.locator(menuSelector)).toHaveClass(/hidden/)
31+
await expect(page.locator(triggerSelector)).toHaveAttribute('aria-expanded', 'false')
32+
})
33+
34+
test('@ready toggles the menu and populates Google and Outlook links from fixture metadata', async ({
35+
page: playwrightPage,
36+
}) => {
37+
const page = await loadCalendarFixture(playwrightPage)
38+
39+
await page.locator(triggerSelector).click()
40+
41+
await expect(page.locator(menuSelector)).not.toHaveClass(/hidden/)
42+
await expect(page.locator(triggerSelector)).toHaveAttribute('aria-expanded', 'true')
43+
44+
const googleHref = await page.locator(googleLinkSelector).getAttribute('href')
45+
expect(googleHref).toBeTruthy()
46+
47+
if (googleHref) {
48+
const googleUrl = new URL(googleHref)
49+
expect(googleUrl.hostname).toContain('calendar.google.com')
50+
expect(googleUrl.pathname).toBe('/calendar/render')
51+
expect(googleUrl.searchParams.get('action')).toBe('TEMPLATE')
52+
expect(googleUrl.searchParams.get('text')).toBe('Team sync')
53+
expect(googleUrl.searchParams.get('dates')).toBe('20300102T130000Z/20300102T140000Z')
54+
expect(googleUrl.searchParams.get('details')).toBe('Weekly team sync')
55+
expect(googleUrl.searchParams.get('location')).toBe('Remote')
56+
}
57+
58+
const outlookHref = await page.locator(outlookLinkSelector).getAttribute('href')
59+
expect(outlookHref).toBeTruthy()
60+
61+
if (outlookHref) {
62+
const outlookUrl = new URL(outlookHref)
63+
expect(outlookUrl.hostname).toContain('outlook.office.com')
64+
expect(outlookUrl.pathname).toBe('/calendar/0/deeplink/compose')
65+
expect(outlookUrl.searchParams.get('path')).toBe('/calendar/action/compose')
66+
expect(outlookUrl.searchParams.get('rru')).toBe('addevent')
67+
expect(outlookUrl.searchParams.get('subject')).toBe('Team sync')
68+
expect(outlookUrl.searchParams.get('startdt')).toBe('2030-01-02T13:00:00.000Z')
69+
expect(outlookUrl.searchParams.get('enddt')).toBe('2030-01-02T14:00:00.000Z')
70+
expect(outlookUrl.searchParams.get('body')).toBe('Weekly team sync')
71+
expect(outlookUrl.searchParams.get('location')).toBe('Remote')
72+
}
73+
74+
await page.locator(triggerSelector).click()
75+
await expect(page.locator(menuSelector)).toHaveClass(/hidden/)
76+
await expect(page.locator(triggerSelector)).toHaveAttribute('aria-expanded', 'false')
77+
})
78+
79+
test('@ready downloads an .ics file with the fixture event details', async ({ page: playwrightPage }) => {
80+
const page = await loadCalendarFixture(playwrightPage)
81+
82+
await page.locator(triggerSelector).click()
83+
const downloadPromise = playwrightPage.waitForEvent('download')
84+
await page.locator(downloadButtonSelector).click()
85+
const download = await downloadPromise
86+
87+
expect(download.suggestedFilename()).toBe('event.ics')
88+
const downloadPath = await download.path()
89+
expect(downloadPath).toBeTruthy()
90+
91+
if (!downloadPath) {
92+
return
93+
}
94+
95+
const icsText = await readFile(downloadPath, 'utf8')
96+
expect(icsText).toContain('BEGIN:VCALENDAR')
97+
expect(icsText).toContain('SUMMARY:Team sync')
98+
expect(icsText).toContain('DESCRIPTION:Weekly team sync')
99+
expect(icsText).toContain('LOCATION:Remote')
100+
expect(icsText).toContain('DTSTART:20300102T130000Z')
101+
expect(icsText).toContain('DTEND:20300102T140000Z')
102+
expect(icsText).toContain('END:VCALENDAR')
103+
104+
await expect(page.locator(menuSelector)).toHaveClass(/hidden/)
105+
await expect(page.locator(triggerSelector)).toHaveAttribute('aria-expanded', 'false')
106+
})
107+
})

‎test/e2e/specs/TROUBLESHOOTING.md‎

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

0 commit comments

Comments
 (0)