mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
Warn that default signOut scope revokes all sessions. Motivation: https://github.com/supabase/ssr/issues/68 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified that signing out without a specified scope ends all sessions by default. * Added guidance for using a local sign-out scope to preserve sessions on other devices and browsers. * Documented the invalid refresh token errors that may occur when other sessions are revoked. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
142 lines
4.4 KiB
TypeScript
142 lines
4.4 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
import type { TestInfo } from '@playwright/test'
|
|
|
|
import { parsePagePaths } from '../../shared/paths.ts'
|
|
import {
|
|
attachScanReport,
|
|
blockingViolations,
|
|
ENFORCED_RULES,
|
|
formatViolations,
|
|
scanArticle,
|
|
scanLooksEmpty,
|
|
settleForAxe,
|
|
shouldEnforceAll,
|
|
unloadedResult,
|
|
violationIds,
|
|
} from '../utils/axe-helpers.js'
|
|
import {
|
|
articleSelectorForPagePath,
|
|
checkLinkFromBrowser,
|
|
collectDocsOwnedLinks,
|
|
} from '../utils/docs-links.js'
|
|
|
|
const pagePaths = parsePagePaths(process.env.DOCS_E2E_PAGE_PATHS)
|
|
|
|
function annotate(testInfo: TestInfo, description: string) {
|
|
testInfo.annotations.push({ type: 'warning', description })
|
|
console.warn(`::warning title=Accessibility::${description}`)
|
|
}
|
|
|
|
test.describe('Docs owned pages', () => {
|
|
// Without this, every test in this file runs on one worker.
|
|
test.describe.configure({ mode: 'parallel' })
|
|
|
|
test('resolved page list must not be empty', () => {
|
|
expect(
|
|
pagePaths.length,
|
|
'No pages to test. `pnpm e2e:docs` resolves pages from git changes by default, ' +
|
|
'or set DOCS_E2E_PAGE_PATHS explicitly.'
|
|
).toBeGreaterThan(0)
|
|
})
|
|
|
|
for (const pagePath of pagePaths) {
|
|
test(`${pagePath} loads and docs-owned article links resolve`, async ({ page }, testInfo) => {
|
|
const baseURL = testInfo.project.use.baseURL
|
|
expect(baseURL, 'A Playwright base URL should be configured').toBeTruthy()
|
|
|
|
const articleSelector = articleSelectorForPagePath(pagePath)
|
|
const response = await page.goto(pagePath)
|
|
expect(response, `Expected a response for ${pagePath}`).not.toBeNull()
|
|
expect(
|
|
response!.ok(),
|
|
`Page should return a successful status, got ${response!.status()}`
|
|
).toBeTruthy()
|
|
|
|
const article = page.locator(articleSelector)
|
|
await expect(article, 'Page article should be present').toBeVisible()
|
|
|
|
const links = await collectDocsOwnedLinks(page, baseURL!, articleSelector)
|
|
|
|
for (const url of links) {
|
|
const result = await checkLinkFromBrowser(page, url)
|
|
expect
|
|
.soft(
|
|
result.ok,
|
|
result.error
|
|
? `${url} should be reachable (${result.error})`
|
|
: `${url} should resolve (status ${result.status})`
|
|
)
|
|
.toBeTruthy()
|
|
}
|
|
})
|
|
}
|
|
|
|
for (const pagePath of pagePaths) {
|
|
test(`${pagePath} has no blocking accessibility violations @a11y`, async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.setTimeout(120_000)
|
|
|
|
const include = articleSelectorForPagePath(pagePath)
|
|
|
|
let response
|
|
try {
|
|
response = await page.goto(pagePath)
|
|
} catch (error) {
|
|
await attachScanReport(testInfo, unloadedResult(pagePath, pagePath, null, include))
|
|
throw error
|
|
}
|
|
|
|
const status = response?.status() ?? null
|
|
|
|
if (!response?.ok()) {
|
|
await attachScanReport(testInfo, unloadedResult(pagePath, page.url(), status, include))
|
|
expect(
|
|
response?.ok(),
|
|
`Expected a successful response for ${pagePath}, got ${status}`
|
|
).toBeTruthy()
|
|
return
|
|
}
|
|
|
|
await settleForAxe(page)
|
|
|
|
await expect(
|
|
page.locator(include),
|
|
`No article matching "${include}" on ${pagePath}. This suite covers guides and ` +
|
|
'troubleshooting entries; other routes have no article element to scan.'
|
|
).toBeVisible()
|
|
|
|
const result = await scanArticle(page, pagePath, include)
|
|
result.status = status
|
|
|
|
await attachScanReport(testInfo, result)
|
|
|
|
if (scanLooksEmpty(result)) {
|
|
annotate(
|
|
testInfo,
|
|
`${pagePath} scanned only ${result.elementCount} element(s) in ${include}, so a clean ` +
|
|
'result here proves nothing. Most likely the page had not finished rendering.'
|
|
)
|
|
}
|
|
|
|
const blocking = blockingViolations(result)
|
|
|
|
const reported = result.violations.filter((violation) => !blocking.includes(violation))
|
|
if (reported.length) {
|
|
annotate(
|
|
testInfo,
|
|
`${pagePath} has ${reported.length} non-blocking accessibility finding(s): ` +
|
|
reported.map((v) => `${v.id} (${v.nodes.length})`).join(', ')
|
|
)
|
|
}
|
|
|
|
const enforced = shouldEnforceAll() ? 'all WCAG 2.1 A/AA rules' : ENFORCED_RULES.join(', ')
|
|
|
|
expect(
|
|
violationIds(blocking),
|
|
`${pagePath} has blocking a11y violations (${enforced}):\n${formatViolations(blocking)}`
|
|
).toEqual([])
|
|
})
|
|
}
|
|
})
|