Skip to content

Commit f88e669

Browse files
committed
fix(tests): exclude Playwright e2e tests from bun test runner
- Rename playwright-runner.test.ts to .e2e.ts to avoid bun test pickup - Add Bun runtime detection to docs.spec.ts and redirects.spec.ts - Update bunfig.toml to exclude e2e directory from bun test Playwright tests now gracefully skip when run under bun test and only execute when run via bunx playwright test.
1 parent c211515 commit f88e669

File tree

4 files changed

+374
-158
lines changed

4 files changed

+374
-158
lines changed

bunfig.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ linker = "hoisted"
55
linkWorkspacePackages = true
66

77
[test]
8-
# Exclude test repositories and integration tests from test execution by default
9-
exclude = ["evals/test-repos/**", "**/*.integration.test.*"]
8+
# Exclude test repositories, integration tests, and Playwright e2e tests from test execution by default
9+
exclude = ["evals/test-repos/**", "**/*.integration.test.*", "web/src/__tests__/e2e/**"]
1010
preload = ["./sdk/test/setup-env.ts", "./test/setup-bigquery-mocks.ts"]

web/src/__tests__/e2e/docs.spec.ts

Lines changed: 168 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -5,194 +5,206 @@
55
* navigation works, and key features like code blocks display properly.
66
*/
77

8-
import { test, expect } from '@playwright/test'
8+
export {}
99

10-
test.describe('Documentation Pages', { tag: '@docs' }, () => {
11-
test.describe('Doc Landing Page', () => {
12-
test('loads the docs index page', async ({ page }) => {
13-
await page.goto('/docs')
10+
const isBun = typeof Bun !== 'undefined'
1411

15-
// Should have documentation content or redirect to first doc
16-
await expect(page).toHaveURL(/\/docs/)
17-
})
18-
19-
test('has working navigation sidebar on desktop', async ({ page }) => {
20-
// Set desktop viewport
21-
await page.setViewportSize({ width: 1280, height: 720 })
22-
await page.goto('/docs/help/quick-start')
12+
if (isBun) {
13+
const { describe, it } = await import('bun:test')
2314

24-
// Sidebar should be visible on desktop
25-
const sidebar = page.locator('[class*="lg:block"]').first()
26-
await expect(sidebar).toBeVisible()
27-
})
15+
describe.skip('playwright-only', () => {
16+
it('skipped under bun test runner', () => {})
2817
})
29-
30-
test.describe('Quick Start Page', () => {
31-
test.beforeEach(async ({ page }) => {
32-
await page.goto('/docs/help/quick-start')
33-
})
34-
35-
test('renders the page title', async ({ page }) => {
36-
// Page should have a heading
37-
const heading = page.locator('h1').first()
38-
await expect(heading).toBeVisible()
39-
await expect(heading).toContainText(/start|codebuff/i)
40-
})
41-
42-
test('renders code blocks with syntax highlighting', async ({ page }) => {
43-
// Should have code blocks
44-
const codeBlocks = page.locator('pre code, [class*="prism"]')
45-
const count = await codeBlocks.count()
46-
expect(count).toBeGreaterThan(0)
47-
})
48-
49-
test('has working internal links', async ({ page }) => {
50-
// Find an internal link
51-
const internalLinks = page.locator('article a[href^="/docs/"]')
52-
const count = await internalLinks.count()
53-
54-
if (count > 0) {
55-
const firstLink = internalLinks.first()
56-
const href = await firstLink.getAttribute('href')
57-
58-
// Click and verify navigation
59-
await firstLink.click()
60-
await expect(page).toHaveURL(
61-
new RegExp(href!.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')),
18+
} else {
19+
const { test, expect } = await import('@playwright/test')
20+
21+
test.describe('Documentation Pages', { tag: '@docs' }, () => {
22+
test.describe('Doc Landing Page', () => {
23+
test('loads the docs index page', async ({ page }) => {
24+
await page.goto('/docs')
25+
26+
// Should have documentation content or redirect to first doc
27+
await expect(page).toHaveURL(/\/docs/)
28+
})
29+
30+
test('has working navigation sidebar on desktop', async ({ page }) => {
31+
// Set desktop viewport
32+
await page.setViewportSize({ width: 1280, height: 720 })
33+
await page.goto('/docs/help/quick-start')
34+
35+
// Sidebar should be visible on desktop
36+
const sidebar = page.locator('[class*="lg:block"]').first()
37+
await expect(sidebar).toBeVisible()
38+
})
39+
})
40+
41+
test.describe('Quick Start Page', () => {
42+
test.beforeEach(async ({ page }) => {
43+
await page.goto('/docs/help/quick-start')
44+
})
45+
46+
test('renders the page title', async ({ page }) => {
47+
// Page should have a heading
48+
const heading = page.locator('h1').first()
49+
await expect(heading).toBeVisible()
50+
await expect(heading).toContainText(/start|codebuff/i)
51+
})
52+
53+
test('renders code blocks with syntax highlighting', async ({ page }) => {
54+
// Should have code blocks
55+
const codeBlocks = page.locator('pre code, [class*="prism"]')
56+
const count = await codeBlocks.count()
57+
expect(count).toBeGreaterThan(0)
58+
})
59+
60+
test('has working internal links', async ({ page }) => {
61+
// Find an internal link
62+
const internalLinks = page.locator('article a[href^="/docs/"]')
63+
const count = await internalLinks.count()
64+
65+
if (count > 0) {
66+
const firstLink = internalLinks.first()
67+
const href = await firstLink.getAttribute('href')
68+
69+
// Click and verify navigation
70+
await firstLink.click()
71+
await expect(page).toHaveURL(
72+
new RegExp(href!.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')),
73+
)
74+
}
75+
})
76+
})
77+
78+
test.describe('Navigation', () => {
79+
test('prev/next navigation works', async ({ page }) => {
80+
await page.goto('/docs/help/quick-start')
81+
82+
// Look for next button
83+
const nextButton = page.locator(
84+
'a:has-text("Next"), a[href*="/docs/"]:has(svg)',
6285
)
63-
}
64-
})
65-
})
86+
const count = await nextButton.count()
6687

67-
test.describe('Navigation', () => {
68-
test('prev/next navigation works', async ({ page }) => {
69-
await page.goto('/docs/help/quick-start')
88+
if (count > 0) {
89+
const initialUrl = page.url()
90+
await nextButton.first().click()
7091

71-
// Look for next button
72-
const nextButton = page.locator(
73-
'a:has-text("Next"), a[href*="/docs/"]:has(svg)',
74-
)
75-
const count = await nextButton.count()
92+
// Should navigate to a different page
93+
await page.waitForURL((url) => url.toString() !== initialUrl)
94+
}
95+
})
7696

77-
if (count > 0) {
78-
const initialUrl = page.url()
79-
await nextButton.first().click()
97+
test('category pages load', async ({ page }) => {
98+
const categories = ['help', 'tips', 'advanced', 'agents']
8099

81-
// Should navigate to a different page
82-
await page.waitForURL((url) => url.toString() !== initialUrl)
83-
}
100+
for (const category of categories) {
101+
const response = await page.goto(`/docs/${category}`)
102+
// Should either load successfully or redirect
103+
expect(response?.status()).toBeLessThan(500)
104+
}
105+
})
84106
})
85107

86-
test('category pages load', async ({ page }) => {
87-
const categories = ['help', 'tips', 'advanced', 'agents']
108+
test.describe('Content Rendering', () => {
109+
test('FAQ page renders correctly', async ({ page }) => {
110+
await page.goto('/docs/help/faq')
88111

89-
for (const category of categories) {
90-
const response = await page.goto(`/docs/${category}`)
91-
// Should either load successfully or redirect
92-
expect(response?.status()).toBeLessThan(500)
93-
}
94-
})
95-
})
112+
// FAQ page should have questions
113+
const heading = page.locator('h1, h2').first()
114+
await expect(heading).toBeVisible()
115+
})
96116

97-
test.describe('Content Rendering', () => {
98-
test('FAQ page renders correctly', async ({ page }) => {
99-
await page.goto('/docs/help/faq')
117+
test('best practices page renders', async ({ page }) => {
118+
await page.goto('/docs/tips/best-practices')
100119

101-
// FAQ page should have questions
102-
const heading = page.locator('h1, h2').first()
103-
await expect(heading).toBeVisible()
104-
})
120+
const heading = page.locator('h1').first()
121+
await expect(heading).toBeVisible()
122+
await expect(heading).toContainText(/best practices/i)
123+
})
105124

106-
test('best practices page renders', async ({ page }) => {
107-
await page.goto('/docs/tips/best-practices')
125+
test('agents overview renders mermaid diagrams or code', async ({
126+
page,
127+
}) => {
128+
await page.goto('/docs/agents/overview')
108129

109-
const heading = page.locator('h1').first()
110-
await expect(heading).toBeVisible()
111-
await expect(heading).toContainText(/best practices/i)
112-
})
130+
// Should have either mermaid diagram or code block for the flowchart
131+
const mermaidOrCode = page.locator(
132+
'.mermaid, pre:has-text("flowchart"), [class*="mermaid"]',
133+
)
134+
const count = await mermaidOrCode.count()
113135

114-
test('agents overview renders mermaid diagrams or code', async ({
115-
page,
116-
}) => {
117-
await page.goto('/docs/agents/overview')
118-
119-
// Should have either mermaid diagram or code block for the flowchart
120-
const mermaidOrCode = page.locator(
121-
'.mermaid, pre:has-text("flowchart"), [class*="mermaid"]',
122-
)
123-
const count = await mermaidOrCode.count()
124-
125-
// Page should at least render without errors - mermaid may or may not render in test env
126-
// We verify the page loaded by checking for the heading instead
127-
const heading = page.locator('h1').first()
128-
await expect(heading).toBeVisible()
136+
// Page should at least render without errors - mermaid may or may not render in test env
137+
// We verify the page loaded by checking for the heading instead
138+
const heading = page.locator('h1').first()
139+
await expect(heading).toBeVisible()
140+
})
129141
})
130-
})
131142

132-
test.describe('Mobile Navigation', () => {
133-
test('mobile menu button appears on small screens', async ({ page }) => {
134-
// Set mobile viewport
135-
await page.setViewportSize({ width: 375, height: 667 })
136-
await page.goto('/docs/help/quick-start')
137-
138-
// Should have a mobile menu trigger (bottom sheet or hamburger)
139-
const mobileMenu = page
140-
.locator('button:has(svg), [class*="lg:hidden"]')
141-
.first()
142-
await expect(mobileMenu).toBeVisible()
143+
test.describe('Mobile Navigation', () => {
144+
test('mobile menu button appears on small screens', async ({ page }) => {
145+
// Set mobile viewport
146+
await page.setViewportSize({ width: 375, height: 667 })
147+
await page.goto('/docs/help/quick-start')
148+
149+
// Should have a mobile menu trigger (bottom sheet or hamburger)
150+
const mobileMenu = page
151+
.locator('button:has(svg), [class*="lg:hidden"]')
152+
.first()
153+
await expect(mobileMenu).toBeVisible()
154+
})
143155
})
144-
})
145156

146-
test.describe('Accessibility', () => {
147-
test('doc pages have proper heading hierarchy', async ({ page }) => {
148-
await page.goto('/docs/help/quick-start')
157+
test.describe('Accessibility', () => {
158+
test('doc pages have proper heading hierarchy', async ({ page }) => {
159+
await page.goto('/docs/help/quick-start')
149160

150-
// Should have an h1
151-
const h1Count = await page.locator('h1').count()
152-
expect(h1Count).toBeGreaterThanOrEqual(1)
161+
// Should have an h1
162+
const h1Count = await page.locator('h1').count()
163+
expect(h1Count).toBeGreaterThanOrEqual(1)
153164

154-
// h1 should come before h2s in the main content
155-
const headings = await page
156-
.locator('article h1, article h2, article h3')
157-
.allTextContents()
158-
expect(headings.length).toBeGreaterThan(0)
159-
})
165+
// h1 should come before h2s in the main content
166+
const headings = await page
167+
.locator('article h1, article h2, article h3')
168+
.allTextContents()
169+
expect(headings.length).toBeGreaterThan(0)
170+
})
160171

161-
test('links have discernible text', async ({ page }) => {
162-
await page.goto('/docs/help/quick-start')
172+
test('links have discernible text', async ({ page }) => {
173+
await page.goto('/docs/help/quick-start')
163174

164-
const links = page.locator('article a')
165-
const count = await links.count()
175+
const links = page.locator('article a')
176+
const count = await links.count()
166177

167-
for (let i = 0; i < Math.min(count, 10); i++) {
168-
const link = links.nth(i)
169-
const text = await link.textContent()
170-
const ariaLabel = await link.getAttribute('aria-label')
178+
for (let i = 0; i < Math.min(count, 10); i++) {
179+
const link = links.nth(i)
180+
const text = await link.textContent()
181+
const ariaLabel = await link.getAttribute('aria-label')
171182

172-
// Link should have either text content or aria-label
173-
const hasDiscernibleText = (text && text.trim().length > 0) || ariaLabel
174-
expect(hasDiscernibleText).toBeTruthy()
175-
}
183+
// Link should have either text content or aria-label
184+
const hasDiscernibleText = (text && text.trim().length > 0) || ariaLabel
185+
expect(hasDiscernibleText).toBeTruthy()
186+
}
187+
})
176188
})
177-
})
178189

179-
test.describe('SEO', () => {
180-
test('doc pages have meta description', async ({ page }) => {
181-
await page.goto('/docs/help/quick-start')
190+
test.describe('SEO', () => {
191+
test('doc pages have meta description', async ({ page }) => {
192+
await page.goto('/docs/help/quick-start')
182193

183-
const metaDescription = page.locator('meta[name="description"]')
184-
const content = await metaDescription.getAttribute('content')
194+
const metaDescription = page.locator('meta[name="description"]')
195+
const content = await metaDescription.getAttribute('content')
185196

186-
// Should have some description
187-
expect(content).toBeTruthy()
188-
})
197+
// Should have some description
198+
expect(content).toBeTruthy()
199+
})
189200

190-
test('doc pages have proper title', async ({ page }) => {
191-
await page.goto('/docs/help/quick-start')
201+
test('doc pages have proper title', async ({ page }) => {
202+
await page.goto('/docs/help/quick-start')
192203

193-
const title = await page.title()
194-
expect(title.length).toBeGreaterThan(0)
195-
expect(title).not.toBe('undefined')
204+
const title = await page.title()
205+
expect(title.length).toBeGreaterThan(0)
206+
expect(title).not.toBe('undefined')
207+
})
196208
})
197209
})
198-
})
210+
}

0 commit comments

Comments
 (0)