122 lines
6.9 KiB
TypeScript
122 lines
6.9 KiB
TypeScript
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import path from 'node:path';
|
|
import { closeElectronApp, expect, getStableWindow, test } from './fixtures/electron';
|
|
import { createProjectConfig } from '../../shared/project-config';
|
|
|
|
test.describe('Project configuration skills', () => {
|
|
test('does not expose the removed Superpowers feature and supports Skill details', async ({ launchElectronApp }) => {
|
|
const parentPath = await mkdtemp(path.join(tmpdir(), 'niancode-project-configuration-e2e-'));
|
|
const app = await launchElectronApp({ skipSetup: true });
|
|
|
|
try {
|
|
const userDataDir = await app.evaluate(({ app: electronApp }) => electronApp.getPath('userData'));
|
|
const skillDir = path.join(userDataDir, 'opencode', 'niancode-config', 'skills', 'agent-browser');
|
|
await mkdir(path.join(skillDir, 'references'), { recursive: true });
|
|
await writeFile(path.join(skillDir, 'SKILL.md'), '---\nname: agent-browser\ndescription: E2E browser debugging skill.\n---\n\n# Browser debugging\n');
|
|
await writeFile(path.join(skillDir, 'references', 'guide.md'), '# Reference guide\n');
|
|
|
|
await app.evaluate(({ ipcMain }, selectedPath) => {
|
|
ipcMain.removeHandler('dialog:open');
|
|
ipcMain.handle('dialog:open', async () => ({ canceled: false, filePaths: [selectedPath] }));
|
|
}, parentPath);
|
|
|
|
const page = await getStableWindow(app);
|
|
await expect(page.getByTestId('ai-module-selection-page')).toBeVisible();
|
|
await page.getByTestId('ai-module-option-programming').click();
|
|
await expect(page.getByTestId('main-layout')).toBeVisible();
|
|
await page.getByTestId('sidebar-create-project').click();
|
|
await expect(page.getByRole('radio', { name: '小游戏' })).toBeChecked();
|
|
await expect(page.getByRole('radio', { name: '小程序' })).not.toBeChecked();
|
|
await expect(page.getByRole('radio', { name: '自定义项目' })).not.toBeChecked();
|
|
await page.getByRole('radio', { name: '小程序' }).click();
|
|
await expect(page.getByRole('radio', { name: '小程序' })).toBeChecked();
|
|
await page.getByRole('radio', { name: '小游戏' }).click();
|
|
await expect(page.getByRole('radio', { name: '直接使用所选文件夹(默认)' })).toBeChecked();
|
|
await page.getByRole('button', { name: '选择路径' }).click();
|
|
await expect(page.getByLabel('项目路径')).toHaveValue(parentPath);
|
|
await page.getByRole('button', { name: '确认创建' }).click();
|
|
|
|
await expect(page.getByTestId('project-configuration-page')).toBeVisible();
|
|
await expect(page.getByTestId('sidebar-nav-publish')).toHaveCount(0);
|
|
await expect(page.getByText(/新项目还没有伙伴/)).toHaveCount(0);
|
|
await expect(page.getByTestId('project-configuration-actions')).toBeVisible();
|
|
const actionBarBottomGap = await page.getByTestId('project-configuration-actions').evaluate((element) => window.innerHeight - element.getBoundingClientRect().bottom);
|
|
expect(actionBarBottomGap).toBeLessThan(40);
|
|
await expect(page.getByRole('button', { name: '创建伙伴' })).toBeVisible();
|
|
|
|
for (const [resourceId, title] of [
|
|
['resource-card-models', '大脑(大语言模型)'],
|
|
['resource-card-knowledge', '笔记本(知识库)'],
|
|
['resource-card-skills', '工具箱(技能)'],
|
|
] as const) {
|
|
await page.getByTestId(resourceId).click();
|
|
const drawer = page.getByRole('dialog', { name: title });
|
|
await expect(drawer).toBeVisible();
|
|
if (resourceId === 'resource-card-models') {
|
|
await expect(drawer.getByRole('combobox')).toHaveCount(0);
|
|
await expect(drawer.locator('[data-testid="project-model-list"], [data-testid="project-model-empty-state"]')).toHaveCount(1);
|
|
}
|
|
await page.getByRole('button', { name: '关闭' }).click();
|
|
await expect(page.getByRole('dialog', { name: title })).toHaveCount(0);
|
|
}
|
|
|
|
const now = new Date().toISOString();
|
|
await mkdir(path.join(parentPath, '.niancode'), { recursive: true });
|
|
await writeFile(path.join(parentPath, '.niancode', 'project.json'), JSON.stringify({
|
|
...createProjectConfig(undefined, 'mini_game'),
|
|
initialized: true,
|
|
agents: [{
|
|
id: 'e2e-partner',
|
|
avatarId: 'avatar-01',
|
|
roleName: '项目伙伴',
|
|
name: 'E2E伙伴',
|
|
builtIn: false,
|
|
enabled: true,
|
|
model: 'moonshot/kimi-k2.6',
|
|
skillIds: [],
|
|
responsibility: { mission: '验证伙伴维护弹窗。', owns: [], boundaries: [], collaborators: [], principles: [] },
|
|
prompt: '',
|
|
archivedAt: null,
|
|
pinned: false,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
}],
|
|
}, null, 2));
|
|
await page.reload();
|
|
await expect(page.getByTestId('project-configuration-page')).toBeVisible();
|
|
|
|
await page.getByTestId('resource-card-skills').click();
|
|
await expect(page.getByTestId('superpowers-card')).toHaveCount(0);
|
|
await expect(page.getByRole('switch', { name: '启用 Superpowers' })).toHaveCount(0);
|
|
await expect(page.getByTestId('skill-card-agent-browser')).toBeVisible();
|
|
await page.getByTestId('skill-card-agent-browser').click();
|
|
await expect(page.getByTestId('skill-detail-view')).toBeVisible();
|
|
await expect(page.getByTestId('skill-structure')).toContainText('references/guide.md');
|
|
await expect(page.getByTestId('skill-main-file')).toContainText('# Browser debugging');
|
|
await page.getByRole('button', { name: '返回技能列表' }).click();
|
|
await expect(page.getByTestId('skill-card-agent-browser')).toBeVisible();
|
|
await page.getByRole('button', { name: '关闭' }).click();
|
|
await expect(page.getByTestId('resource-card-publish')).toHaveCount(0);
|
|
await expect(page.getByRole('button', { name: '一键提交审核' })).toBeVisible();
|
|
|
|
const agentCard = page.getByTestId('project-agent-e2e-partner');
|
|
await expect(agentCard).toContainText('E2E伙伴');
|
|
await agentCard.click();
|
|
const maintenanceDialog = page.getByRole('dialog', { name: 'E2E伙伴 · 伙伴维护' });
|
|
await expect(maintenanceDialog).toBeVisible();
|
|
await expect(maintenanceDialog.getByLabel(/伙伴名称/)).toHaveValue('E2E伙伴');
|
|
await maintenanceDialog.getByRole('button', { name: '更换头像' }).click();
|
|
const avatarDialog = page.getByRole('dialog', { name: '选择头像' });
|
|
await expect(avatarDialog).toBeVisible();
|
|
await avatarDialog.getByLabel('上传伙伴头像').setInputFiles(path.join(process.cwd(), 'src/assets/agent-avatars/avatar-01.png'));
|
|
await expect(avatarDialog).toHaveCount(0);
|
|
await expect(maintenanceDialog.getByAltText('当前上传头像')).toBeVisible();
|
|
await expect(page.getByText('完成配置')).toHaveCount(0);
|
|
} finally {
|
|
await closeElectronApp(app);
|
|
await rm(parentPath, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|