mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
fix(frontend): complete i18n coverage and responsive layouts
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createApp, h, nextTick, ref, type App } from 'vue'
|
||||
|
||||
import Pagination from '../pagination.vue'
|
||||
import { setI18nLocale } from '@/i18n'
|
||||
|
||||
const mountedApps: Array<{ app: App, root: HTMLElement }> = []
|
||||
|
||||
afterEach(() => {
|
||||
for (const { app, root } of mountedApps.splice(0)) {
|
||||
app.unmount()
|
||||
root.remove()
|
||||
}
|
||||
})
|
||||
|
||||
describe('Pagination', () => {
|
||||
it('updates the summary and accessible page controls when the locale changes', async () => {
|
||||
const root = document.createElement('div')
|
||||
document.body.appendChild(root)
|
||||
const updateCurrent = vi.fn()
|
||||
const app = createApp({
|
||||
render: () => h(Pagination, {
|
||||
current: 1,
|
||||
total: 1250,
|
||||
pageSize: 20,
|
||||
showPageSizeSelector: false,
|
||||
'onUpdate:current': updateCurrent,
|
||||
}),
|
||||
})
|
||||
app.mount(root)
|
||||
mountedApps.push({ app, root })
|
||||
|
||||
expect(root.querySelector('[aria-live]')?.textContent).toContain('共 1,250 条')
|
||||
expect(root.querySelector('[aria-current="page"]')?.getAttribute('aria-label')).toBe('第 1 页')
|
||||
|
||||
setI18nLocale('en-US')
|
||||
await nextTick()
|
||||
|
||||
expect(root.querySelector('[aria-live]')?.textContent).toContain('Showing 1-20 of 1,250 items')
|
||||
expect(root.querySelector('[aria-current="page"]')?.getAttribute('aria-label')).toBe('Page 1')
|
||||
expect(root.querySelector('input')?.getAttribute('aria-label')).toBe('Go to page')
|
||||
|
||||
root.querySelector<HTMLButtonElement>('[aria-label="Page 2"]')?.click()
|
||||
expect(updateCurrent).toHaveBeenCalledWith(2)
|
||||
})
|
||||
|
||||
it('shows a zero-based empty range after the final record is removed', async () => {
|
||||
const total = ref(1)
|
||||
const root = document.createElement('div')
|
||||
document.body.appendChild(root)
|
||||
const app = createApp({
|
||||
render: () => h(Pagination, {
|
||||
current: 1,
|
||||
total: total.value,
|
||||
showPageSizeSelector: false,
|
||||
}),
|
||||
})
|
||||
app.mount(root)
|
||||
mountedApps.push({ app, root })
|
||||
|
||||
total.value = 0
|
||||
setI18nLocale('en-US')
|
||||
await nextTick()
|
||||
|
||||
expect(root.querySelector('[aria-live]')?.textContent).toContain('Showing 0-0 of 0 items')
|
||||
expect(root.querySelectorAll('button')).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,55 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createApp, h, nextTick, type App } from 'vue'
|
||||
|
||||
import Tabs from '../tabs.vue'
|
||||
import TabsList from '../tabs-list.vue'
|
||||
import TabsTrigger from '../tabs-trigger.vue'
|
||||
import { setI18nLocale, useI18n } from '@/i18n'
|
||||
|
||||
const mountedApps: Array<{ app: App, root: HTMLElement }> = []
|
||||
|
||||
afterEach(() => {
|
||||
for (const { app, root } of mountedApps.splice(0)) {
|
||||
app.unmount()
|
||||
root.remove()
|
||||
}
|
||||
vi.restoreAllMocks()
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
describe('TabsList', () => {
|
||||
it('repositions the indicator after translated labels change width', async () => {
|
||||
vi.useFakeTimers()
|
||||
vi.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function (this: HTMLElement) {
|
||||
return { width: this.textContent === '个人设置' ? 80 : 140 } as DOMRect
|
||||
})
|
||||
vi.spyOn(HTMLElement.prototype, 'offsetLeft', 'get').mockReturnValue(4)
|
||||
|
||||
const root = document.createElement('div')
|
||||
document.body.appendChild(root)
|
||||
const app = createApp({
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return () => h(Tabs, { modelValue: 'settings' }, {
|
||||
default: () => h(TabsList, {}, {
|
||||
default: () => h(TabsTrigger, { value: 'settings' }, () => t('common.settings')),
|
||||
}),
|
||||
})
|
||||
},
|
||||
})
|
||||
app.mount(root)
|
||||
mountedApps.push({ app, root })
|
||||
await nextTick()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
const indicator = root.querySelector<HTMLElement>('.tabs-indicator')
|
||||
expect(indicator?.style.width).toBe('80px')
|
||||
expect(indicator?.style.transform).toBe('translateX(4px)')
|
||||
|
||||
setI18nLocale('en-US')
|
||||
await nextTick()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
expect(indicator?.style.width).toBe('140px')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user