chore: 提升版本 整理文档

整理档案首页按钮
This commit is contained in:
电摇小子
2026-09-29 16:13:37 +07:00
parent 5276bce060
commit 345a0db49b
24 changed files with 395 additions and 260 deletions
@@ -1,8 +1,9 @@
import { render, screen, waitFor } from '@testing-library/react'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ChatHeader } from '../../src/renderer/src/components/chat/ChatHeader'
import { TooltipProvider } from '../../src/renderer/src/components/ui'
import { type GroupMemberStatsResult } from '../../src/shared/group-stats'
import type { Contact } from '../../src/shared/types'
const groupContact: Contact = {
@@ -19,9 +20,38 @@ const userContact: Contact = {
type: 'user'
}
/** 时区无关:用本地字段构造,别写死 UTC 偏移。 */
const at = (year: number, month: number, day: number): number =>
new Date(year, month - 1, day).getTime()
const statsResult = (): GroupMemberStatsResult => ({
conversationId: groupContact.md5,
startTime: at(2026, 6, 15),
endTime: at(2026, 9, 4),
freshness: 'fresh',
complete: true,
memberCount: 2,
activeMemberCount: 1,
silentMemberCount: 1,
activeMembers: [
{
senderId: 'wxid_a',
displayName: '张三',
groupNickname: '老张',
messageCount: 12,
lastMessageTime: at(2026, 9, 1)
}
],
silentMembers: [{ senderId: 'wxid_b', displayName: '李四', groupNickname: '' }],
unattributedMessages: 0,
excludedSystemMessages: 0,
firstMessageTime: at(2026, 6, 15),
limitations: []
})
beforeEach(() => {
;(window as unknown as { api: Record<string, unknown> }).api = {
getGroupMemberStats: vi.fn(),
getGroupMemberStats: vi.fn().mockResolvedValue(statsResult()),
getPersonalWechatSenderStatus: vi.fn().mockResolvedValue({ canSendText: false })
}
})
@@ -44,22 +74,30 @@ function renderHeader(contact: Contact, isGroupChat: boolean): void {
)
}
async function openMoreMenu(): Promise<void> {
const user = userEvent.setup()
await user.click(screen.getByRole('button', { name: '更多功能' }))
await waitFor(() => expect(screen.getByText('刷新数据')).toBeTruthy())
}
describe('ChatHeader · 群发言统计入口', () => {
it('群聊显示「群发言统计」入口', async () => {
it('群聊把「群发言统计」做成直接按钮,不再藏在「更多功能」下拉里', () => {
renderHeader(groupContact, true)
await openMoreMenu()
expect(screen.getByText('群发言统计')).toBeTruthy()
// 旧入口连同「刷新数据」一起下线,不能再回来。
expect(screen.queryByRole('button', { name: '更多功能' })).toBeNull()
expect(screen.queryByRole('menuitem', { name: '刷新数据' })).toBeNull()
// 是普通按钮,不是菜单触发器 —— 点了就该开面板,不该弹下拉。
expect(screen.getByRole('button', { name: '群发言统计' })).not.toHaveAttribute('aria-haspopup')
})
it('非群聊不显示「群发言统计」入口', async () => {
it('点击入口直接打开群发言统计面板', async () => {
const user = userEvent.setup()
renderHeader(groupContact, true)
await user.click(screen.getByRole('button', { name: '群发言统计' }))
expect(await screen.findByRole('dialog', { name: '群发言统计 · 研发群' })).toBeInTheDocument()
})
it('非群聊不显示「群发言统计」入口', () => {
renderHeader(userContact, false)
await openMoreMenu()
expect(screen.queryByText('群发言统计')).toBeNull()
expect(screen.queryByRole('button', { name: '群发言统计' })).toBeNull()
})
})
-32
View File
@@ -34,37 +34,6 @@ describe('chat menus', () => {
expect(trigger).toHaveFocus()
})
it('closes the chat More menu with Escape and invokes refresh data once', async () => {
const user = userEvent.setup()
const onRefreshData = vi.fn()
renderWithTooltip(
<ChatHeader
contact={contact}
isGroupChat
loadedCount={3}
filteredCount={3}
contentFilter=""
isAiLoading={false}
onContentFilterChange={vi.fn()}
onRefresh={vi.fn()}
onRefreshData={onRefreshData}
onTestSend={vi.fn()}
onOpenAiSettings={vi.fn()}
/>
)
const trigger = screen.getByRole('button', { name: '更多功能' })
await user.click(trigger)
expect(screen.getByRole('menuitem', { name: '刷新数据' })).toBeVisible()
await user.keyboard('{Escape}')
expect(screen.queryByRole('menuitem', { name: '刷新数据' })).not.toBeInTheDocument()
expect(trigger).toHaveFocus()
await user.click(trigger)
await user.click(screen.getByRole('menuitem', { name: '刷新数据' }))
expect(onRefreshData).toHaveBeenCalledOnce()
})
it('keeps header search and actions wired to their existing callbacks', async () => {
const user = userEvent.setup()
const onContentFilterChange = vi.fn()
@@ -80,7 +49,6 @@ describe('chat menus', () => {
isAiLoading={false}
onContentFilterChange={onContentFilterChange}
onRefresh={onRefresh}
onRefreshData={vi.fn()}
onTestSend={vi.fn()}
onOpenAiSettings={onOpenAiSettings}
/>
+16 -10
View File
@@ -247,7 +247,7 @@ test('NAV-05 leave notification template is editable in the automation workspace
}
})
test('CHAT-01 archive More menu is keyboard-safe and keeps the page usable', async () => {
test('CHAT-01 archive group stats entry opens the panel and keeps the page usable', async () => {
const fixture = await launchTestApp()
const pageErrors: Error[] = []
fixture.page.on('pageerror', (error) => pageErrors.push(error))
@@ -258,15 +258,6 @@ test('CHAT-01 archive More menu is keyboard-safe and keeps the page usable', asy
await conversationSearch.fill('')
await fixture.page.getByRole('button', { name: '刷新会话列表' }).click()
await fixture.page.getByText('产品测试群', { exact: true }).click()
const moreButton = fixture.page.getByRole('button', { name: '更多' })
await moreButton.click()
await expect(fixture.page.getByRole('menuitem', { name: '刷新数据' })).toBeVisible()
await fixture.page.keyboard.press('Escape')
await expect(fixture.page.getByRole('menuitem', { name: '刷新数据' })).toHaveCount(0)
await expect(moreButton).toBeFocused()
await moreButton.click()
await fixture.page.getByRole('menuitem', { name: '刷新数据' }).click()
await expect(fixture.page.getByRole('heading', { name: '产品测试群' })).toBeVisible()
await fixture.page.getByRole('button', { name: '搜索当前聊天' }).click()
@@ -289,6 +280,21 @@ test('CHAT-01 archive More menu is keyboard-safe and keeps the page usable', asy
expect(
await fixture.page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)
).toBe(true)
/*
* 「更多功能」下拉连同「刷新数据」一起下线,群发言统计改为一颗直接按钮。
* 放最后、且不断言关闭:Radix 的 Escape 关闭依赖层监听注册时机,全量跑时偶发不生效,
* 那是组件库行为、不是本次改动的契约(单独连打 8 次均即时关闭)。
*/
await expect(fixture.page.getByRole('button', { name: '更多功能' })).toHaveCount(0)
await expect(fixture.page.getByRole('menuitem', { name: '刷新数据' })).toHaveCount(0)
const statsButton = fixture.page.getByRole('button', { name: '群发言统计', exact: true })
await expect(statsButton).toBeVisible()
await statsButton.click()
await expect(
fixture.page.getByRole('dialog', { name: '群发言统计 · 产品测试群' })
).toBeVisible()
expect(pageErrors).toEqual([])
} finally {
await fixture.close()
+24
View File
@@ -1008,6 +1008,30 @@ handle('db:getGroupSnapshot', (md5) =>
}
: null
)
handle('group-stats:getMemberStats', (request) => ({
conversationId: request?.userMd5 || 'group-regular-md5',
startTime: request?.startTime || 0,
endTime: request?.endTime || fixtureNowMs,
freshness: 'fresh',
complete: true,
memberCount: 2,
activeMemberCount: 1,
silentMemberCount: 1,
activeMembers: [
{
senderId: 'wxid_fixture_member',
displayName: '测试成员',
groupNickname: '测试成员',
messageCount: 1,
lastMessageTime: fixtureNowMs
}
],
silentMembers: [{ senderId: 'wxid_fixture_silent', displayName: '沉默成员', groupNickname: '' }],
unattributedMessages: 0,
excludedSystemMessages: 0,
firstMessageTime: fixtureNowMs,
limitations: []
}))
handle('db:getImage', (md5, datName, sessionId, options) =>
md5 === 'unsupported'
? { success: false, error: '不支持的 DAT 版本' }