|
|
|
@ -16,7 +16,7 @@ describe('local search', () => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
await openSearch()
|
|
|
|
|
|
|
|
|
|
|
|
const loading = page.locator('.search-loading')
|
|
|
|
const loading = page.locator('.search-loading')
|
|
|
|
const results = page.locator('.results')
|
|
|
|
const results = page.locator('.results')
|
|
|
|
@ -49,22 +49,10 @@ describe('local search', () => {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
test('exclude content from search results', async () => {
|
|
|
|
test('exclude content from search results', async () => {
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
await searchFor('local')
|
|
|
|
|
|
|
|
await waitForSearchResults({ text: 'Local search included', count: 1 })
|
|
|
|
const input = await page.waitForSelector('input#localsearch-input')
|
|
|
|
|
|
|
|
await input.type('local')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const searchResults = page.locator('#localsearch-list')
|
|
|
|
const searchResults = page.locator('#localsearch-list')
|
|
|
|
await page.waitForFunction(() => {
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
|
|
|
...document.querySelectorAll('#localsearch-list li[role=option]')
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
options.length === 1 &&
|
|
|
|
|
|
|
|
options[0].textContent?.includes('Local search included')
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect(await searchResults.locator('li[role=option]').count()).toBe(1)
|
|
|
|
expect(await searchResults.locator('li[role=option]').count()).toBe(1)
|
|
|
|
|
|
|
|
|
|
|
|
@ -84,21 +72,10 @@ describe('local search', () => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
test('resolves $frontmatter expressions in search results', async () => {
|
|
|
|
test('resolves $frontmatter expressions in search results', async () => {
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
await searchFor('Frontmatter Title Resolved')
|
|
|
|
|
|
|
|
await waitForSearchResults({ text: 'Frontmatter Title Resolved' })
|
|
|
|
const input = await page.waitForSelector('input#localsearch-input')
|
|
|
|
|
|
|
|
await input.fill('Frontmatter Title Resolved')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const searchResults = page.locator('#localsearch-list')
|
|
|
|
const searchResults = page.locator('#localsearch-list')
|
|
|
|
await page.waitForFunction(() => {
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
|
|
|
...document.querySelectorAll('#localsearch-list li[role=option]')
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return options.some((option) =>
|
|
|
|
|
|
|
|
option.textContent?.includes('Frontmatter Title Resolved')
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect(
|
|
|
|
expect(
|
|
|
|
await searchResults
|
|
|
|
await searchResults
|
|
|
|
@ -111,25 +88,11 @@ describe('local search', () => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
test('custom tokenize function reaches the client', async () => {
|
|
|
|
test('custom tokenize function reaches the client', async () => {
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const input = await page.waitForSelector('input#localsearch-input')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// '#hash-probe' survives as one token only under the custom tokenizer —
|
|
|
|
// '#hash-probe' survives as one token only under the custom tokenizer —
|
|
|
|
// MiniSearch's default one would degrade the query to 'hash'/'probe'
|
|
|
|
// MiniSearch's default one would degrade the query to 'hash'/'probe'
|
|
|
|
// and miss the index built with the custom tokenizer
|
|
|
|
// and miss the index built with the custom tokenizer
|
|
|
|
await input.type('#hash-probe')
|
|
|
|
const input = await searchFor('#hash-probe')
|
|
|
|
|
|
|
|
await waitForSearchResults({ text: 'Local search included', count: 1 })
|
|
|
|
await page.waitForFunction(() => {
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
|
|
|
...document.querySelectorAll('#localsearch-list li[role=option]')
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
options.length === 1 &&
|
|
|
|
|
|
|
|
options[0].textContent?.includes('Local search included')
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// a fragment of a kept-whole token must not match anything
|
|
|
|
// a fragment of a kept-whole token must not match anything
|
|
|
|
await input.fill('linked-words')
|
|
|
|
await input.fill('linked-words')
|
|
|
|
@ -145,8 +108,7 @@ describe('local search', () => {
|
|
|
|
]) {
|
|
|
|
]) {
|
|
|
|
await page.setViewportSize({ width, height: 600 })
|
|
|
|
await page.setViewportSize({ width, height: 600 })
|
|
|
|
await goto('/')
|
|
|
|
await goto('/')
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
await openSearch()
|
|
|
|
await page.waitForSelector('input#localsearch-input')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect(await page.locator('.VPNavBarHamburger').isVisible()).toBe(
|
|
|
|
expect(await page.locator('.VPNavBarHamburger').isVisible()).toBe(
|
|
|
|
!isDesktop
|
|
|
|
!isDesktop
|
|
|
|
@ -162,17 +124,9 @@ describe('local search', () => {
|
|
|
|
|
|
|
|
|
|
|
|
test('navigate results with macOS Ctrl shortcuts', async () => {
|
|
|
|
test('navigate results with macOS Ctrl shortcuts', async () => {
|
|
|
|
await page.evaluate(() => document.documentElement.classList.add('mac'))
|
|
|
|
await page.evaluate(() => document.documentElement.classList.add('mac'))
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const input = await page.waitForSelector('input#localsearch-input')
|
|
|
|
const input = await searchFor('lorem')
|
|
|
|
await input.type('lorem')
|
|
|
|
await waitForSearchResults({ minCount: 2 })
|
|
|
|
|
|
|
|
|
|
|
|
await page.waitForFunction(() => {
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
document.querySelectorAll('#localsearch-list li[role=option]').length >
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect(await input.getAttribute('aria-activedescendant')).toBe(
|
|
|
|
expect(await input.getAttribute('aria-activedescendant')).toBe(
|
|
|
|
'localsearch-item-0'
|
|
|
|
'localsearch-item-0'
|
|
|
|
@ -190,6 +144,43 @@ describe('local search', () => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function openSearch() {
|
|
|
|
|
|
|
|
await page.locator('.VPNavBarSearchButton').click()
|
|
|
|
|
|
|
|
return page.waitForSelector('input#localsearch-input')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fills the query in one step, so exactly one search runs and the result
|
|
|
|
|
|
|
|
// list settles into the state for this query and nothing else
|
|
|
|
|
|
|
|
async function searchFor(query: string) {
|
|
|
|
|
|
|
|
const input = await openSearch()
|
|
|
|
|
|
|
|
await input.fill(query)
|
|
|
|
|
|
|
|
return input
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// waits until the result list matches, so assertions never run against the
|
|
|
|
|
|
|
|
// results of an earlier query
|
|
|
|
|
|
|
|
function waitForSearchResults(condition: {
|
|
|
|
|
|
|
|
/** some result must contain this text */
|
|
|
|
|
|
|
|
text?: string
|
|
|
|
|
|
|
|
/** exactly this many results */
|
|
|
|
|
|
|
|
count?: number
|
|
|
|
|
|
|
|
/** at least this many results */
|
|
|
|
|
|
|
|
minCount?: number
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
return page.waitForFunction(({ text, count, minCount }) => {
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
|
|
|
...document.querySelectorAll('#localsearch-list li[role=option]')
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
(count === undefined || options.length === count) &&
|
|
|
|
|
|
|
|
(minCount === undefined || options.length >= minCount) &&
|
|
|
|
|
|
|
|
(text === undefined ||
|
|
|
|
|
|
|
|
options.some((option) => option.textContent?.includes(text)))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}, condition)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function pressMacCtrl(key: string) {
|
|
|
|
function pressMacCtrl(key: string) {
|
|
|
|
return page.evaluate((key) => {
|
|
|
|
return page.evaluate((key) => {
|
|
|
|
window.dispatchEvent(
|
|
|
|
window.dispatchEvent(
|
|
|
|
|