feat: add plugin marketplace renderer
This commit is contained in:
1 parent
8b6824a8ba
commit
97c9ad1aad
27 files changed
+1585
-23
No files matched your search
@@ -0,0 +1,59 @@
|
||||
import { closeElectronApp, expect, getStableWindow, test } from './fixtures/electron';
|
||||
|
||||
test.describe('Plugin Marketplace', () => {
|
||||
test('opens the global catalog, searches, and reads detail through fixed Main routes', async ({ launchElectronApp }) => {
|
||||
const app = await launchElectronApp({ skipSetup: true });
|
||||
try {
|
||||
const page = await getStableWindow(app);
|
||||
await page.getByTestId('ai-module-option-programming').click();
|
||||
await app.evaluate(({ ipcMain }) => {
|
||||
const requests: string[] = [];
|
||||
(globalThis as typeof globalThis & { __marketplaceE2E?: { requests: string[] } }).__marketplaceE2E = { requests };
|
||||
ipcMain.removeHandler('hostapi:fetch');
|
||||
ipcMain.handle('hostapi:fetch', async (_event, request: { path?: string }) => {
|
||||
const requestPath = request.path ?? '';
|
||||
requests.push(requestPath);
|
||||
const item = {
|
||||
pluginId: 'makelore.notes', title: '灵感笔记', summary: '整理项目灵感。', category: '效率', tags: ['笔记'],
|
||||
providerDisplayName: 'MakeLore', runtimeKind: 'skill_only', runtimeStatus: 'enabled', acquisition: 'free',
|
||||
usageBilling: 'included', includedOperationCount: 1, meteredOperationCount: 0, stableVersion: '1.0.0', betaVersion: null,
|
||||
};
|
||||
if (requestPath.startsWith('/api/coding/plugin-marketplace/catalog')) {
|
||||
return { ok: true, data: { status: 200, ok: true, json: {
|
||||
items: [item], nextCursor: null, total: 1, catalogGeneration: 1,
|
||||
etag: '"plugins-1-tp-none"', pricingVersionId: null, stale: false, fetchedAt: 1,
|
||||
} } };
|
||||
}
|
||||
if (requestPath === '/api/coding/plugin-marketplace/plugins/makelore.notes') {
|
||||
return { ok: true, data: { status: 200, ok: true, json: {
|
||||
...item, descriptionMarkdown: '详细介绍', permissions: ['读取项目名称'], operations: [],
|
||||
stableRelease: { releaseId: 'release-1', pluginId: 'makelore.notes', version: '1.0.0' }, betaRelease: null,
|
||||
etag: '"plugins-1-tp-none"', pricingVersionId: null, stale: false, fetchedAt: 1,
|
||||
} } };
|
||||
}
|
||||
return { ok: false, error: { message: `Unexpected Host API request: ${requestPath}` } };
|
||||
});
|
||||
});
|
||||
|
||||
await page.getByTestId('sidebar-nav-plugin-marketplace').click();
|
||||
await expect(page.getByTestId('plugin-marketplace-page')).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: '灵感笔记' })).toBeVisible();
|
||||
await page.getByRole('searchbox', { name: '搜索插件' }).fill('笔记');
|
||||
await page.getByRole('button', { name: '搜索', exact: true }).click();
|
||||
await page.getByRole('button', { name: '查看详情' }).click();
|
||||
await expect(page.getByRole('heading', { name: '灵感笔记' }).last()).toBeVisible();
|
||||
await expect(page.getByText('详细介绍')).toBeVisible();
|
||||
|
||||
const requests = await app.evaluate(() => (
|
||||
(globalThis as typeof globalThis & { __marketplaceE2E?: { requests: string[] } }).__marketplaceE2E?.requests ?? []
|
||||
));
|
||||
expect(requests).toContain('/api/coding/plugin-marketplace/catalog?limit=24');
|
||||
expect(requests).toContain('/api/coding/plugin-marketplace/catalog?query=%E7%AC%94%E8%AE%B0&limit=24');
|
||||
expect(requests).toContain('/api/coding/plugin-marketplace/plugins/makelore.notes');
|
||||
const marketplaceRequests = requests.filter((requestPath) => requestPath.startsWith('/api/coding/plugin-marketplace/'));
|
||||
expect(JSON.stringify(marketplaceRequests)).not.toMatch(/account|admission|release_id|path=/i);
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -36,11 +36,13 @@ test.describe('Project Plugin Center', () => {
|
||||
schemaVersion: 1,
|
||||
project: { localProjectId: state.localProjectId, durableProjectId: '11111111-1111-4111-8111-111111111111' },
|
||||
policyStatus: 'current',
|
||||
unknownPluginIds: [],
|
||||
items: [{
|
||||
id: 'makelore.data-service', version: '1.0.0', displayName: '开发数据服务', description: '为当前项目提供数据。',
|
||||
contractVersion: 1, requiresBackend: true,
|
||||
enabled: state.enabled, state: state.enabled ? 'configuration_required' : 'disabled', backend: { status: 'unconfigured' },
|
||||
skills: [{ id: 'data-service', assignedAgentIds: [] }],
|
||||
capabilities: [{ id: 'data-service.control', operations: [{ id: 'inspect', billing: { mode: 'included', availability: 'available', notice: 'Fixed quotas apply' } }] }],
|
||||
capabilities: [{ id: 'data-service.control', operations: [{ id: 'inspect', billing: { mode: 'included', availability: 'available', notice: 'Fixed quotas apply' }, tool: null }] }],
|
||||
settingsSurface: 'data-service',
|
||||
}],
|
||||
} } };
|
||||
@@ -58,7 +60,7 @@ test.describe('Project Plugin Center', () => {
|
||||
expect(localProjectId).toBeTruthy();
|
||||
await expect(page.getByText(localProjectId as string)).toHaveCount(0);
|
||||
await expect(page.getByText('11111111-1111-4111-8111-111111111111')).toHaveCount(0);
|
||||
await page.getByRole('button', { name: '启用开发数据服务' }).click();
|
||||
await page.getByRole('button', { name: '启用到项目开发数据服务' }).click();
|
||||
await expect(page.getByRole('article').getByText('待配置')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: '创建开发数据空间' })).toBeDisabled();
|
||||
const dataServiceCalls = await app.evaluate(() => (
|
||||
|
||||
Reference in new issue
Block a user