feat: prepare Zhinian desktop pilot
This commit is contained in:
@@ -4,6 +4,8 @@ import { YinianSkills } from '@/pages/YinianSkills';
|
||||
import { useYinianStore } from '@/stores/yinian';
|
||||
import { useYinianSkillsStore } from '@/stores/yinian-skills';
|
||||
import { useSkillsStore } from '@/stores/skills';
|
||||
import { useQuickTasksStore } from '@/stores/quick-tasks';
|
||||
import i18n from '@/i18n';
|
||||
import type { YinianConfigSnapshot, YinianLocalSkill } from '../../shared/yinian';
|
||||
|
||||
const toastSuccessMock = vi.fn();
|
||||
@@ -62,9 +64,14 @@ function createLocalSkill(overrides: Partial<YinianLocalSkill>): YinianLocalSkil
|
||||
};
|
||||
}
|
||||
|
||||
function clickCapabilityTab(label: '服务下发' | '本地安装') {
|
||||
fireEvent.click(screen.getByRole('button', { name: new RegExp(`^${label}\\s+\\d+$`) }));
|
||||
}
|
||||
|
||||
describe('YinianSkills page', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
await i18n.changeLanguage('zh');
|
||||
useYinianStore.setState({
|
||||
status: 'authenticated',
|
||||
session: {
|
||||
@@ -89,6 +96,7 @@ describe('YinianSkills page', () => {
|
||||
error: null,
|
||||
fetchSkills: vi.fn().mockResolvedValue(undefined),
|
||||
});
|
||||
useQuickTasksStore.setState({ tasks: [] });
|
||||
vi.mocked(window.yinian.skills.getRegistry).mockReset();
|
||||
vi.mocked(window.yinian.skills.getRegistry).mockResolvedValue(undefined);
|
||||
vi.mocked(window.yinian.skills.sync).mockReset();
|
||||
@@ -97,8 +105,9 @@ describe('YinianSkills page', () => {
|
||||
it('shows empty entitlement state', () => {
|
||||
render(<YinianSkills />);
|
||||
|
||||
expect(screen.getByText('智念企业组织空间')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('yinian-skills-empty-entitlements')).toHaveTextContent('当前组织空间尚未开通应用');
|
||||
expect(screen.getByText('业务能力包')).toBeInTheDocument();
|
||||
clickCapabilityTab('服务下发');
|
||||
expect(screen.getByTestId('yinian-skills-empty-entitlements')).toHaveTextContent('当前组织空间尚未开通能力包');
|
||||
});
|
||||
|
||||
it('maps entitlement and registry states for installed, update, disabled, and failed skills', () => {
|
||||
@@ -149,6 +158,7 @@ describe('YinianSkills page', () => {
|
||||
});
|
||||
|
||||
render(<YinianSkills />);
|
||||
clickCapabilityTab('服务下发');
|
||||
|
||||
expect(screen.getByTestId('yinian-skill-state-daily-report')).toHaveTextContent('已是最新');
|
||||
expect(screen.getByTestId('yinian-skill-state-data-check')).toHaveTextContent('有更新');
|
||||
@@ -179,7 +189,7 @@ describe('YinianSkills page', () => {
|
||||
});
|
||||
|
||||
render(<YinianSkills />);
|
||||
fireEvent.click(screen.getByRole('button', { name: /本地安装/ }));
|
||||
clickCapabilityTab('本地安装');
|
||||
|
||||
expect(screen.getByText('本地总结助手')).toBeInTheDocument();
|
||||
expect(screen.getByText('整理本地会话内容')).toBeInTheDocument();
|
||||
@@ -187,6 +197,52 @@ describe('YinianSkills page', () => {
|
||||
expect(screen.getByText('/tmp/openclaw/skills/local-summary')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides OpenClaw built-in skills from local capability packs by default', () => {
|
||||
useSkillsStore.setState({
|
||||
skills: [
|
||||
{
|
||||
id: 'builtin-search',
|
||||
slug: 'builtin-search',
|
||||
name: 'OpenClaw 内置搜索',
|
||||
description: 'OpenClaw 自带能力',
|
||||
enabled: true,
|
||||
version: '1.0.0',
|
||||
isBundled: true,
|
||||
source: 'openclaw-bundled',
|
||||
},
|
||||
{
|
||||
id: 'extra-helper',
|
||||
slug: 'extra-helper',
|
||||
name: 'OpenClaw 扩展目录助手',
|
||||
description: 'OpenClaw 扩展目录能力',
|
||||
enabled: true,
|
||||
version: '1.0.0',
|
||||
source: 'openclaw-extra',
|
||||
},
|
||||
{
|
||||
id: 'local-summary',
|
||||
slug: 'local-summary',
|
||||
name: '本地总结助手',
|
||||
description: '整理本地会话内容',
|
||||
enabled: true,
|
||||
version: '0.2.0',
|
||||
source: 'openclaw-managed',
|
||||
baseDir: '/tmp/openclaw/skills/local-summary',
|
||||
},
|
||||
],
|
||||
loading: false,
|
||||
error: null,
|
||||
fetchSkills: vi.fn().mockResolvedValue(undefined),
|
||||
});
|
||||
|
||||
render(<YinianSkills />);
|
||||
clickCapabilityTab('本地安装');
|
||||
|
||||
expect(screen.queryByText('OpenClaw 内置搜索')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('OpenClaw 扩展目录助手')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('本地总结助手')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows empty registry warning when entitlements exist but no local skills are installed', () => {
|
||||
useYinianStore.setState({
|
||||
config: createConfig({
|
||||
@@ -204,9 +260,10 @@ describe('YinianSkills page', () => {
|
||||
});
|
||||
|
||||
render(<YinianSkills />);
|
||||
clickCapabilityTab('服务下发');
|
||||
|
||||
expect(screen.getByTestId('yinian-skill-state-daily-report')).toHaveTextContent('已开通未同步');
|
||||
expect(screen.getByTestId('yinian-skills-empty-registry')).toHaveTextContent('这台电脑还没有准备好应用');
|
||||
expect(screen.getByTestId('yinian-skills-empty-registry')).toHaveTextContent('这台电脑还没有准备好能力包');
|
||||
});
|
||||
|
||||
it('sync button stores result and shows success toast', async () => {
|
||||
@@ -231,7 +288,7 @@ describe('YinianSkills page', () => {
|
||||
});
|
||||
|
||||
render(<YinianSkills />);
|
||||
const syncButton = screen.getByRole('button', { name: '同步应用' });
|
||||
const syncButton = screen.getByRole('button', { name: '同步能力包' });
|
||||
await waitFor(() => {
|
||||
expect(syncButton).not.toBeDisabled();
|
||||
});
|
||||
@@ -239,7 +296,7 @@ describe('YinianSkills page', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
expect(window.yinian.skills.sync).toHaveBeenCalled();
|
||||
expect(toastSuccessMock).toHaveBeenCalledWith('应用已同步');
|
||||
expect(toastSuccessMock).toHaveBeenCalledWith('能力包已同步');
|
||||
});
|
||||
expect(useYinianSkillsStore.getState().localSkills).toHaveLength(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user