256 lines
7.6 KiB
TypeScript
256 lines
7.6 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { act, render, screen } from '@testing-library/react';
|
|
import { MemoryRouter } from 'react-router-dom';
|
|
import { Today } from '@/pages/Today';
|
|
import { useYinianStore } from '@/stores/yinian';
|
|
import { useYinianSkillsStore } from '@/stores/yinian-skills';
|
|
import { useSkillsStore } from '@/stores/skills';
|
|
import { useChatStore } from '@/stores/chat';
|
|
import { useGatewayStore } from '@/stores/gateway';
|
|
import i18n from '@/i18n';
|
|
import type { YinianConfigSnapshot, YinianLocalSkill } from '../../shared/yinian';
|
|
|
|
const hotelHangzhou = {
|
|
id: 'workspace_hangzhou_ops',
|
|
name: '智念企业组织空间',
|
|
brand: '智念',
|
|
city: '杭州',
|
|
role: 'manager' as const,
|
|
permissions: ['dashboard.read', 'skills.sync'],
|
|
ota: [],
|
|
};
|
|
|
|
const hotelShanghai = {
|
|
id: 'workspace_shanghai_growth',
|
|
name: '智念增长组织空间',
|
|
city: '上海',
|
|
role: 'viewer' as const,
|
|
permissions: ['dashboard.read'],
|
|
ota: [],
|
|
};
|
|
|
|
function createConfig(overrides: Partial<YinianConfigSnapshot> = {}): YinianConfigSnapshot {
|
|
return {
|
|
serverTime: 1,
|
|
user: { id: 'user_1', name: '王管理员' },
|
|
hotel: hotelHangzhou,
|
|
hotels: [hotelHangzhou, hotelShanghai],
|
|
entitlements: [],
|
|
notificationChannels: [],
|
|
featureFlags: {},
|
|
uiPolicy: { defaultPage: 'today', showAdvancedSettings: false },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function createLocalSkill(overrides: Partial<YinianLocalSkill>): YinianLocalSkill {
|
|
return {
|
|
skillId: 'daily-report',
|
|
name: '日报生成助手',
|
|
version: '1.0.0',
|
|
enabled: true,
|
|
installedAt: 1,
|
|
lastSyncedAt: Date.now() - 5 * 60_000,
|
|
status: 'installed',
|
|
source: 'mock',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function renderToday() {
|
|
return render(
|
|
<MemoryRouter>
|
|
<Today />
|
|
</MemoryRouter>,
|
|
);
|
|
}
|
|
|
|
describe('Today page', () => {
|
|
beforeEach(async () => {
|
|
vi.clearAllMocks();
|
|
await i18n.changeLanguage('zh');
|
|
useYinianStore.setState({
|
|
status: 'authenticated',
|
|
session: {
|
|
authenticated: true,
|
|
user: { id: 'user_1', name: '王管理员' },
|
|
hotels: [hotelHangzhou, hotelShanghai],
|
|
currentHotelId: hotelHangzhou.id,
|
|
accessTokenExpiresAt: 100,
|
|
},
|
|
config: createConfig(),
|
|
error: null,
|
|
});
|
|
useYinianSkillsStore.setState({
|
|
localSkills: [],
|
|
lastSync: null,
|
|
loading: false,
|
|
error: null,
|
|
});
|
|
useSkillsStore.setState({
|
|
skills: [],
|
|
loading: false,
|
|
error: null,
|
|
});
|
|
useChatStore.setState({
|
|
sessions: [],
|
|
sessionLabels: {},
|
|
sessionLastActivity: {},
|
|
});
|
|
useGatewayStore.setState({
|
|
status: {
|
|
state: 'stopped',
|
|
port: 18789,
|
|
gatewayReady: false,
|
|
},
|
|
});
|
|
});
|
|
|
|
it('shows work entry, pinned apps, and quick tools when workspace has no entitlements', () => {
|
|
renderToday();
|
|
|
|
expect(screen.getAllByText('智念企业组织空间').length).toBeGreaterThan(0);
|
|
expect(screen.getByText('今天想先做什么?')).toBeInTheDocument();
|
|
expect(screen.getByText('开始工作')).toBeInTheDocument();
|
|
expect(screen.getByText('常用应用')).toBeInTheDocument();
|
|
expect(screen.getByText('智念视频助手')).toBeInTheDocument();
|
|
expect(screen.getByText('定时任务')).toBeInTheDocument();
|
|
expect(screen.getByText('知识库')).toBeInTheDocument();
|
|
expect(screen.queryByText('0/0')).not.toBeInTheDocument();
|
|
expect(screen.queryByText('需要关注')).not.toBeInTheDocument();
|
|
expect(screen.getByText('最近对话')).toBeInTheDocument();
|
|
});
|
|
|
|
it('shows recent conversations before generic empty history', () => {
|
|
useYinianStore.setState({
|
|
config: createConfig({
|
|
entitlements: [
|
|
{
|
|
skillId: 'daily-report',
|
|
name: '日报生成助手',
|
|
version: '1.0.0',
|
|
enabled: true,
|
|
category: 'reporting',
|
|
triggers: ['scheduled', 'manual'],
|
|
lastRunAt: Date.now() - 60 * 60_000,
|
|
},
|
|
{
|
|
skillId: 'data-check',
|
|
name: '数据检查助手',
|
|
version: '1.2.0',
|
|
enabled: true,
|
|
category: 'ota-monitoring',
|
|
triggers: ['scheduled'],
|
|
},
|
|
{
|
|
skillId: 'customer-reply-helper',
|
|
name: '客户回复助手',
|
|
version: '0.9.0',
|
|
enabled: false,
|
|
category: 'guest-comm',
|
|
triggers: ['manual'],
|
|
},
|
|
],
|
|
notificationChannels: [
|
|
{
|
|
id: 'ops',
|
|
kind: 'wecom',
|
|
label: '业务通知群',
|
|
recipient: 'room_1',
|
|
enabled: true,
|
|
source: 'nianxx',
|
|
},
|
|
],
|
|
}),
|
|
});
|
|
useYinianSkillsStore.setState({
|
|
localSkills: [
|
|
createLocalSkill({ skillId: 'daily-report', name: '日报生成助手', version: '1.0.0', status: 'skipped' }),
|
|
createLocalSkill({ skillId: 'data-check', name: '数据检查助手', version: '1.1.0', status: 'installed' }),
|
|
],
|
|
});
|
|
useSkillsStore.setState({
|
|
skills: [
|
|
{
|
|
id: 'daily-report',
|
|
name: '日报生成助手',
|
|
description: '',
|
|
enabled: true,
|
|
isCore: false,
|
|
source: 'openclaw-managed',
|
|
},
|
|
{
|
|
id: 'data-check',
|
|
name: '数据检查助手',
|
|
description: '',
|
|
enabled: true,
|
|
isCore: false,
|
|
source: 'openclaw-managed',
|
|
},
|
|
],
|
|
});
|
|
useChatStore.setState({
|
|
sessions: [
|
|
{ key: 'agent:main:session-a', updatedAt: Date.now() - 2 * 60_000 },
|
|
{ key: 'agent:main:session-b', updatedAt: Date.now() - 60 * 60_000 },
|
|
],
|
|
sessionLabels: {
|
|
'agent:main:session-a': '整理本周门店内容',
|
|
'agent:main:session-b': '又见乌江宣传片',
|
|
},
|
|
sessionLastActivity: {
|
|
'agent:main:session-a': Date.now() - 2 * 60_000,
|
|
'agent:main:session-b': Date.now() - 60 * 60_000,
|
|
},
|
|
});
|
|
|
|
renderToday();
|
|
|
|
expect(screen.queryByText('2/2')).not.toBeInTheDocument();
|
|
expect(screen.queryByText('下发 2 个 · 本地 2 个')).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/待处理 1 个/)).not.toBeInTheDocument();
|
|
expect(screen.getByText('整理本周门店内容')).toBeInTheDocument();
|
|
expect(screen.getByText('又见乌江宣传片')).toBeInTheDocument();
|
|
expect(screen.queryByText('数据检查助手 有新版本')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('updates displayed workspace and counters after hotel switch refreshes config', () => {
|
|
const { rerender } = render(
|
|
<MemoryRouter>
|
|
<Today />
|
|
</MemoryRouter>,
|
|
);
|
|
expect(screen.getAllByText('智念企业组织空间').length).toBeGreaterThan(0);
|
|
|
|
act(() => {
|
|
useYinianStore.setState({
|
|
config: createConfig({
|
|
hotel: hotelShanghai,
|
|
entitlements: [
|
|
{
|
|
skillId: 'customer-reply-helper',
|
|
name: '客户回复助手',
|
|
version: '0.9.0',
|
|
enabled: true,
|
|
category: 'guest-comm',
|
|
triggers: ['manual'],
|
|
},
|
|
],
|
|
}),
|
|
});
|
|
useYinianSkillsStore.setState({ localSkills: [] });
|
|
});
|
|
|
|
rerender(
|
|
<MemoryRouter>
|
|
<Today />
|
|
</MemoryRouter>,
|
|
);
|
|
|
|
expect(screen.getAllByText('智念增长组织空间').length).toBeGreaterThan(0);
|
|
expect(screen.queryByText('1/0')).not.toBeInTheDocument();
|
|
expect(screen.queryByText(/待处理 1 个/)).not.toBeInTheDocument();
|
|
expect(screen.queryByText('智念企业组织空间')).not.toBeInTheDocument();
|
|
});
|
|
});
|