178 lines
5.9 KiB
JavaScript
178 lines
5.9 KiB
JavaScript
// The tab title names the record, and the two writers do not fight.
|
|
//
|
|
// The router can only name the KIND of page - it runs before the view has
|
|
// fetched anything - so a detail view names the record itself once it loads.
|
|
// That leaves two writers for one string, and the router's is asynchronous
|
|
// (it awaits the site settings), so on a cold load it can finish LAST and
|
|
// overwrite a good title with the generic one. These pin that ordering.
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
|
|
// The real getFacilityName caches, so only the first call is slow and every
|
|
// later one is instant. Mirror that: pending calls are held until the test
|
|
// releases them, and the value is served synchronously from then on. A mock
|
|
// that hands out a fresh unresolved promise per call hangs the moment a test
|
|
// navigates twice.
|
|
let pending = []
|
|
let settled = null
|
|
|
|
function resolveFacility(value) {
|
|
settled = value
|
|
const waiting = pending
|
|
pending = []
|
|
waiting.forEach((resolve) => resolve(value))
|
|
}
|
|
|
|
vi.mock('@/utils/siteSettings', () => ({
|
|
getFacilityName: () => (settled !== null
|
|
? Promise.resolve(settled)
|
|
: new Promise((resolve) => { pending.push(resolve) })),
|
|
}))
|
|
|
|
import {
|
|
beginNavigation, applyGenericTitle, setRecordTitle, _reset,
|
|
} from './pageTitle'
|
|
|
|
beforeEach(() => {
|
|
_reset()
|
|
document.title = ''
|
|
pending = []
|
|
settled = null
|
|
})
|
|
|
|
describe('the generic title', () => {
|
|
it('names the section when no record has been set', async () => {
|
|
beginNavigation('/machines')
|
|
const done = applyGenericTitle('/machines', 'Machines')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - Machines')
|
|
})
|
|
|
|
it('falls back to plain ShopDB when the facility is unset', async () => {
|
|
beginNavigation('/machines')
|
|
const done = applyGenericTitle('/machines', 'Machines')
|
|
resolveFacility('ShopDB')
|
|
await done
|
|
|
|
expect(document.title).toBe('ShopDB - Machines')
|
|
})
|
|
|
|
it('drops the site name entirely on the dashboard', async () => {
|
|
beginNavigation('/')
|
|
const done = applyGenericTitle('/', 'Home')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB')
|
|
})
|
|
})
|
|
|
|
describe('a record title', () => {
|
|
it('names the record once the view has loaded it', async () => {
|
|
beginNavigation('/machines/12')
|
|
const done = applyGenericTitle('/machines/12', 'Machines')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
setRecordTitle('CSF16')
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - CSF16')
|
|
})
|
|
|
|
it('SURVIVES a slow router that resolves afterwards', async () => {
|
|
// The regression this file exists for. The view wins the race, the
|
|
// settings fetch lands second, and the generic write must stand down.
|
|
beginNavigation('/machines/12')
|
|
const done = applyGenericTitle('/machines/12', 'Machines')
|
|
|
|
setRecordTitle('CSF16') // view got there first
|
|
resolveFacility('West Jefferson')
|
|
await done // router finishes last
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - CSF16')
|
|
})
|
|
|
|
it('is ignored when the record has no usable name', async () => {
|
|
beginNavigation('/machines/12')
|
|
const done = applyGenericTitle('/machines/12', 'Machines')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
setRecordTitle('')
|
|
setRecordTitle(null)
|
|
setRecordTitle(undefined)
|
|
setRecordTitle(' ')
|
|
|
|
// the section name is a better tab than a blank or a bare id
|
|
expect(document.title).toBe('West Jefferson ShopDB - Machines')
|
|
})
|
|
|
|
it('shortens a name too long for a tab, at a word boundary', async () => {
|
|
// Knowledge base articles are named with a sentence of description, and a
|
|
// browser truncates those mid-word wherever it happens to run out.
|
|
beginNavigation('/knowledgebase/2')
|
|
const done = applyGenericTitle('/knowledgebase/2', 'Knowledge Base')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
const full = 'Documentation on how to image a Standard or Business PC '
|
|
+ 'in GCC High using MediaCreator Lite'
|
|
setRecordTitle(full)
|
|
|
|
expect(document.title.length).toBeLessThan(90)
|
|
expect(document.title.startsWith('West Jefferson ShopDB - ')).toBe(true)
|
|
expect(document.title.endsWith('...')).toBe(true)
|
|
|
|
// what survives is a whole-word prefix of the original: the character
|
|
// following the cut in the source is a space, so no word was split
|
|
const kept = document.title
|
|
.replace('West Jefferson ShopDB - ', '')
|
|
.replace(/\.\.\.$/, '')
|
|
expect(full.startsWith(kept)).toBe(true)
|
|
expect(full[kept.length]).toBe(' ')
|
|
})
|
|
|
|
it('leaves a name that already fits alone', async () => {
|
|
beginNavigation('/machines/14')
|
|
const done = applyGenericTitle('/machines/14', 'Machines')
|
|
resolveFacility('West Jefferson')
|
|
await done
|
|
|
|
setRecordTitle('0600')
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - 0600')
|
|
})
|
|
|
|
it('does not leak onto the next page', async () => {
|
|
beginNavigation('/machines/12')
|
|
const first = applyGenericTitle('/machines/12', 'Machines')
|
|
resolveFacility('West Jefferson')
|
|
await first
|
|
setRecordTitle('CSF16')
|
|
|
|
beginNavigation('/printers')
|
|
const second = applyGenericTitle('/printers', 'Printers')
|
|
await second
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - Printers')
|
|
})
|
|
|
|
it('is discarded when the user navigates away mid-flight', async () => {
|
|
// Two navigations overlap; the first one's late generic write must not
|
|
// land on the second page.
|
|
beginNavigation('/machines/12')
|
|
const stale = applyGenericTitle('/machines/12', 'Machines')
|
|
|
|
beginNavigation('/printers/3')
|
|
const fresh = applyGenericTitle('/printers/3', 'Printers')
|
|
setRecordTitle('WJPRT04')
|
|
|
|
resolveFacility('West Jefferson')
|
|
await Promise.all([stale, fresh])
|
|
|
|
expect(document.title).toBe('West Jefferson ShopDB - WJPRT04')
|
|
})
|
|
})
|