[READ-ONLY] a fast, modern browser for the npm registry
at main 177 lines 6.7 kB view raw
1import { expect, test } from './test-utils' 2 3test.describe('API Documentation Pages', () => { 4 test('docs page loads and shows content for a package', async ({ page, goto }) => { 5 // Use a small, stable package with TypeScript types 6 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'networkidle' }) 7 8 // Page title should include package name 9 await expect(page).toHaveTitle(/ufo.*docs/i) 10 11 // Header should show package name and version 12 await expect(page.locator('header').getByText('ufo')).toBeVisible() 13 await expect(page.locator('header').getByText('1.6.3')).toBeVisible() 14 15 // API Docs badge should be visible 16 await expect(page.locator('text=API Docs')).toBeVisible() 17 18 // Should have documentation content 19 const docsContent = page.locator('.docs-content') 20 await expect(docsContent).toBeVisible() 21 22 // Should have at least one function documented 23 await expect(page.locator('.docs-badge--function').first()).toBeVisible() 24 }) 25 26 test('docs page shows TOC sidebar on desktop', async ({ page, goto }) => { 27 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'networkidle' }) 28 29 // TOC sidebar should be visible (on desktop viewport) 30 const tocSidebar = page.locator('aside') 31 await expect(tocSidebar).toBeVisible() 32 33 // Should have "Contents" heading 34 await expect(tocSidebar.getByText('Contents')).toBeVisible() 35 36 // Should have section links (Functions, etc.) 37 await expect(tocSidebar.locator('a[href="#section-function"]')).toBeVisible() 38 }) 39 40 test('TOC links navigate to sections', async ({ page, goto }) => { 41 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'networkidle' }) 42 43 // Click on Functions in TOC 44 const functionsLink = page.locator('aside a[href="#section-function"]') 45 await functionsLink.click() 46 47 // URL should have the hash 48 await expect(page).toHaveURL(/#section-function/) 49 50 // Section should be scrolled into view 51 const functionSection = page.locator('#section-function') 52 await expect(functionSection).toBeInViewport() 53 }) 54 55 test('clicking symbol name scrolls to symbol', async ({ page, goto }) => { 56 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'networkidle' }) 57 58 // Find a symbol link in the TOC 59 const symbolLink = page.locator('aside a[href^="#function-"]').first() 60 const href = await symbolLink.getAttribute('href') 61 62 // Click the symbol link 63 await symbolLink.click() 64 65 // URL should have the hash 66 await expect(page).toHaveURL(new RegExp(href!.replace('#', '#'))) 67 }) 68 69 test('docs page without version redirects to latest', async ({ page, goto }) => { 70 await goto('/package-docs/ufo', { waitUntil: 'networkidle' }) 71 72 // Should redirect to include version 73 await expect(page).toHaveURL(/\/package-docs\/ufo\/v\//) 74 }) 75 76 test('package link in header navigates to package page', async ({ page, goto }) => { 77 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'networkidle' }) 78 79 // Click on package name in header 80 const packageLink = page.locator('header a').filter({ hasText: 'ufo' }) 81 await packageLink.click() 82 83 // Should navigate to package page (URL ends with /ufo) 84 await expect(page).toHaveURL(/\/package\/ufo$/) 85 }) 86 87 test('docs page handles package gracefully when types unavailable', async ({ page, goto }) => { 88 // Use a simple JS package - the page should load without crashing 89 // regardless of whether it has types or shows an error state 90 await goto('/package-docs/is-odd/v/3.0.1', { waitUntil: 'networkidle' }) 91 92 // Header should always show the package name 93 await expect(page.locator('header').getByText('is-odd')).toBeVisible() 94 95 // Page should be in one of two states: 96 // 1. Shows "not available" / error message 97 // 2. Shows actual docs content (if types were found) 98 const errorState = page.locator('text=/not available|could not generate/i') 99 const docsContent = page.locator('.docs-content') 100 101 // One of these should be visible 102 await expect(errorState.or(docsContent)).toBeVisible() 103 }) 104}) 105 106test.describe('Version Selector', () => { 107 test('version selector dropdown shows versions', async ({ page, goto }) => { 108 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'hydration' }) 109 110 // Find and click the version selector button (wait for it to be visible) 111 const versionButton = page.locator('header button').filter({ hasText: '1.6.3' }) 112 await expect(versionButton).toBeVisible({ timeout: 10000 }) 113 114 await versionButton.click() 115 116 // Dropdown should appear with version options 117 const dropdown = page.locator('[role="listbox"]') 118 await expect(dropdown).toBeVisible() 119 120 // Should show multiple versions 121 const versionOptions = dropdown.locator('[role="option"]') 122 await expect(versionOptions.first()).toBeVisible() 123 }) 124 125 test('selecting a version navigates to that version', async ({ page, goto }) => { 126 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'hydration' }) 127 128 // Find and click the version selector button (wait for it to be visible) 129 const versionButton = page.locator('header button').filter({ hasText: '1.6.3' }) 130 await expect(versionButton).toBeVisible({ timeout: 10000 }) 131 132 await versionButton.click() 133 134 // Find a version link that's not the current version by checking the href 135 const versionLinks = page.locator('[role="option"] a[href*="/package-docs/ufo/v/"]') 136 const count = await versionLinks.count() 137 138 // Find first link that doesn't point to 1.6.3 139 let targetHref: string | null = null 140 for (let i = 0; i < count; i++) { 141 const href = await versionLinks.nth(i).getAttribute('href') 142 if (href && !href.includes('/v/1.6.3')) { 143 targetHref = href 144 await versionLinks.nth(i).click() 145 break 146 } 147 } 148 149 // Skip if no other versions available 150 if (!targetHref) { 151 test.skip() 152 return 153 } 154 155 // URL should match the href we clicked 156 await expect(page).toHaveURL(new RegExp(targetHref.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))) 157 }) 158 159 test('escape key closes version dropdown', async ({ page, goto }) => { 160 await goto('/package-docs/ufo/v/1.6.3', { waitUntil: 'hydration' }) 161 162 // Wait for version button to be visible 163 const versionButton = page.locator('header button').filter({ hasText: '1.6.3' }) 164 await expect(versionButton).toBeVisible({ timeout: 10000 }) 165 166 await versionButton.click() 167 168 const dropdown = page.locator('[role="listbox"]') 169 await expect(dropdown).toBeVisible() 170 171 // Press escape 172 await page.keyboard.press('Escape') 173 174 // Dropdown should close 175 await expect(dropdown).not.toBeVisible() 176 }) 177})