// @vitest-environment jsdom
/** Settings-navigation icon marker tests (including delayed dialog mount). */
import { afterEach, describe, expect, it } from 'vitest'
import { registerSettingsNavIcon, SETTINGS_NAV_MARKER } from '../src/client/settings-nav-icon.ts'
function navButton(label: string): HTMLButtonElement {
const button = document.createElement('button')
button.innerHTML = `${label}`
return button
}
function dialogWith(...buttons: HTMLButtonElement[]): HTMLElement {
const dialog = document.createElement('div')
dialog.setAttribute('role', 'dialog')
const nav = document.createElement('nav')
nav.append(...buttons)
dialog.append(nav)
return dialog
}
async function mutationTick(): Promise {
await new Promise(resolve => { setTimeout(resolve, 0) })
}
afterEach(() => {
document.body.innerHTML = ''
})
describe('registerSettingsNavIcon', () => {
it('marks only the matching settings row and preserves the shell icon DOM', () => {
const general = navButton('General')
const sideCard = navButton('Side card')
document.body.append(dialogWith(general, sideCard))
const dispose = registerSettingsNavIcon(() => 'Side card')
expect(general.hasAttribute(SETTINGS_NAV_MARKER)).toBe(false)
expect(sideCard.hasAttribute(SETTINGS_NAV_MARKER)).toBe(true)
expect(sideCard.querySelector('[data-fallback="gear"]')).not.toBeNull()
dispose()
expect(sideCard.hasAttribute(SETTINGS_NAV_MARKER)).toBe(false)
})
it('marks a dialog mounted later and follows a localized label change', async () => {
let label = 'Side card'
const dispose = registerSettingsNavIcon(() => label)
const english = navButton('Side card')
const chinese = navButton('侧边卡片')
const dialog = dialogWith(english, chinese)
document.body.append(dialog)
await mutationTick()
expect(english.hasAttribute(SETTINGS_NAV_MARKER)).toBe(true)
expect(chinese.hasAttribute(SETTINGS_NAV_MARKER)).toBe(false)
label = '侧边卡片'
chinese.querySelector('span')!.textContent = '侧边卡片 '
await mutationTick()
expect(english.hasAttribute(SETTINGS_NAV_MARKER)).toBe(false)
expect(chinese.hasAttribute(SETTINGS_NAV_MARKER)).toBe(true)
dispose()
})
})