You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/__tests__/base/not-found.test.ts

153 lines
5.8 KiB

import { SUB_PREFIX } from './constants'
import { newPage, realErrors, waitForHydration, type TestPage } from './helpers'
// the cdn build, served at the root by a host that picks the nearest 404.html
const nearest = () => `http://localhost:${process.env['PAGES_PORT']}`
// the plain build, served by a host that only knows the root 404.html
const rootOnly = () => `http://localhost:${process.env['PLAIN_PORT']}`
// the relative build, mounted under a prefix
const sub = () => `http://localhost:${process.env['SUB_PORT']}${SUB_PREFIX}`
let t: TestPage
beforeAll(async () => {
t = await newPage()
})
afterAll(async () => {
await t.page.close()
await t.browser.close()
})
beforeEach(() => {
t.errors.length = 0
})
const h1 = () => t.page.textContent('h1')
// the document of a miss is a 404 by design; anything else is a real error
const errors = () => realErrors(t.errors, [t.page.url()])
const lang = () => t.page.evaluate(() => document.documentElement.lang)
const mark = () => t.page.evaluate(() => ((window as any).__spa_marker = 1))
const marked = () => t.page.evaluate(() => (window as any).__spa_marker === 1)
describe('not-found page on a host serving the nearest 404.html', () => {
test('a miss shows the theme page when the site has no 404.md', async () => {
const res = await t.page.goto(`${nearest()}/nowhere.html`)
expect(res?.status()).toBe(404)
await waitForHydration(t.page)
expect(await t.page.textContent('.NotFound .title')).toBe('PAGE NOT FOUND')
expect(await t.page.title()).toBe('404 | Base Fixture')
expect(await t.page.getAttribute('.NotFound .link', 'href')).toBe('/')
expect(new URL(t.page.url()).pathname).toBe('/nowhere.html')
expect(errors()).toEqual([])
})
test("a miss under a locale shows that locale's 404.md", async () => {
const res = await t.page.goto(`${nearest()}/zh/guide/nowhere.html`)
expect(res?.status()).toBe(404)
await waitForHydration(t.page)
expect(await h1()).toContain('页面未找到')
expect(await lang()).toBe('zh-CN')
expect(await t.page.title()).toBe('页面未找到 | Base Fixture')
expect(errors()).toEqual([])
})
test('the theme page uses the locale text of the miss', async () => {
// the root build has no zh text of its own: only the client knows the
// locale, from the url
await t.page.goto(`${nearest()}/nowhere.html`)
await waitForHydration(t.page)
expect(await t.page.textContent('.NotFound .title')).toBe('PAGE NOT FOUND')
expect(await lang()).toBe('en')
})
test('a 404 served for a url that has a page renders that page', async () => {
// the static host has no `index` -> `index.html` rule, so this is a miss
// for the server and a real page for the client
const res = await t.page.goto(`${nearest()}/sub/index`)
expect(res?.status()).toBe(404)
await waitForHydration(t.page)
expect(await h1()).toContain('Sub index')
expect(errors()).toEqual([])
})
test('the not-found page renders at its own url', async () => {
const res = await t.page.goto(`${nearest()}/zh/404.html`)
expect(res?.status()).toBe(200)
await waitForHydration(t.page)
expect(await h1()).toContain('页面未找到')
expect(errors()).toEqual([])
})
test('client-side navigation to a miss keeps the url and recovers', async () => {
await t.page.goto(`${nearest()}/`)
await waitForHydration(t.page)
await mark()
await t.page.evaluate(() => {
const a = document.createElement('a')
a.href = '/zh/nowhere.html'
a.id = 'to-nowhere'
a.textContent = 'nowhere'
// above the fixed nav and sidebar, so the click reaches it
a.style.cssText = 'position:fixed;right:0;bottom:0;z-index:1000'
document.body.appendChild(a)
})
await t.page.click('#to-nowhere')
await t.page.waitForFunction(() =>
document.querySelector('h1')?.textContent?.includes('页面未找到')
)
expect(new URL(t.page.url()).pathname).toBe('/zh/nowhere.html')
expect(await lang()).toBe('zh-CN')
expect(await marked()).toBe(true)
await t.page.click('.vp-doc a[href="/zh/"]')
await t.page.waitForFunction(() =>
document.querySelector('h1')?.textContent?.includes('首页')
)
expect(await marked()).toBe(true)
expect(errors()).toEqual([])
})
})
describe('not-found page on a host serving only the root 404.html', () => {
test("a miss under a locale still shows that locale's page", async () => {
const res = await t.page.goto(`${rootOnly()}/zh/nowhere.html`)
expect(res?.status()).toBe(404)
await waitForHydration(t.page)
expect(await h1()).toContain('页面未找到')
expect(await lang()).toBe('zh-CN')
expect(await t.page.title()).toBe('页面未找到 | Base Fixture')
expect(errors()).toEqual([])
})
test('a miss outside any locale shows the theme page', async () => {
await t.page.goto(`${rootOnly()}/deep/nowhere.html`)
await waitForHydration(t.page)
expect(await t.page.textContent('.NotFound .title')).toBe('PAGE NOT FOUND')
expect(errors()).toEqual([])
})
})
describe('not-found page with a relative base', () => {
test('a miss under a locale is styled and localized', async () => {
const res = await t.page.goto(`${sub()}zh/nowhere.html`)
expect(res?.status()).toBe(404)
await waitForHydration(t.page)
expect(await h1()).toContain('页面未找到')
expect(await t.page.evaluate(() => (window as any).__VP_SITE_ROOT__)).toBe(
sub()
)
expect(errors()).toEqual([])
})
test('a root-level miss shows the theme page', async () => {
await t.page.goto(`${sub()}nowhere.html`)
await waitForHydration(t.page)
expect(await t.page.textContent('.NotFound .title')).toBe('PAGE NOT FOUND')
expect(await t.page.getAttribute('.NotFound .link', 'href')).toBe(
SUB_PREFIX
)
expect(errors()).toEqual([])
})
})