wip: agui integration
This commit is contained in:
195
tests/renderer/navigation/assistantPanelSpec.test.ts
Normal file
195
tests/renderer/navigation/assistantPanelSpec.test.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { extractAssistantPanelSpec, extractAssistantResponseContent } from '../../../src/renderer/navigation/assistantPanelSpec';
|
||||
|
||||
describe('assistantPanelSpec', () => {
|
||||
it('extracts valid spec from fenced json block', () => {
|
||||
const raw = [
|
||||
'Here is the analysis summary.',
|
||||
'```json',
|
||||
'{"specVersion":"1","elements":[{"type":"metric","label":"Drafts","value":"12"}]}',
|
||||
'```',
|
||||
].join('\n');
|
||||
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.specVersion).toBe('1');
|
||||
expect(result?.elements).toHaveLength(1);
|
||||
expect(result?.elements[0]).toEqual({ type: 'metric', label: 'Drafts', value: '12' });
|
||||
});
|
||||
|
||||
it('returns null for invalid schema payload', () => {
|
||||
const raw = '{"specVersion":"1","elements":[{"type":"table","columns":[]}]}';
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('ignores yaml payloads to keep the protocol JSON-only', () => {
|
||||
const raw = [
|
||||
'Here is your chart.',
|
||||
'```yaml',
|
||||
'specVersion: "1"',
|
||||
'elements:',
|
||||
' - type: chart',
|
||||
' chartType: bar',
|
||||
' title: Posts by Month',
|
||||
' series:',
|
||||
' - label: Jan',
|
||||
' value: 10',
|
||||
' - label: Feb',
|
||||
' value: 20',
|
||||
'```',
|
||||
].join('\n');
|
||||
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('extracts text plus ui payload from mixed assistant response', () => {
|
||||
const raw = [
|
||||
'I found two weak months. Please confirm how to proceed.',
|
||||
'```json',
|
||||
'{"specVersion":"1","elements":[{"type":"chart","chartType":"bar","title":"Posts by Month","series":[{"label":"Jan","value":10},{"label":"Feb","value":20}]}]}',
|
||||
'```',
|
||||
].join('\n\n');
|
||||
|
||||
const result = extractAssistantResponseContent(raw);
|
||||
|
||||
expect(result.displayText).toContain('I found two weak months');
|
||||
expect(result.panelSpec).not.toBeNull();
|
||||
expect(result.panelSpec?.elements[0]).toMatchObject({ type: 'chart', chartType: 'bar' });
|
||||
});
|
||||
|
||||
it('normalizes tab-channel envelope payloads into canonical panel spec', () => {
|
||||
const raw = JSON.stringify({
|
||||
type: 'tab',
|
||||
title: 'Posts mit Tag spielen',
|
||||
id: 'spielen-tag-analysis',
|
||||
content: {
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
id: 'yearly-chart',
|
||||
title: 'Jahresübersicht',
|
||||
content: {
|
||||
type: 'chart',
|
||||
chartType: 'bar',
|
||||
data: {
|
||||
labels: ['2011', '2013'],
|
||||
datasets: [{ data: [2, 8] }],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.specVersion).toBe('1');
|
||||
expect(result?.elements[0]).toMatchObject({ type: 'tabs' });
|
||||
});
|
||||
|
||||
it('normalizes chartjs-like chart payloads to series format', () => {
|
||||
const raw = JSON.stringify({
|
||||
specVersion: '1',
|
||||
elements: [
|
||||
{
|
||||
type: 'chart',
|
||||
chartType: 'bar',
|
||||
data: {
|
||||
labels: ['Jan', 'Feb', 'Mar'],
|
||||
datasets: [{ data: [23, 10, 14] }],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.elements[0]).toMatchObject({
|
||||
type: 'chart',
|
||||
chartType: 'bar',
|
||||
series: [
|
||||
{ label: 'Jan', value: 23 },
|
||||
{ label: 'Feb', value: 10 },
|
||||
{ label: 'Mar', value: 14 },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('parses extended widgets including chart, form, datePicker, card, image, input and tabs', () => {
|
||||
const raw = JSON.stringify({
|
||||
specVersion: '1',
|
||||
elements: [
|
||||
{
|
||||
type: 'chart',
|
||||
chartType: 'bar',
|
||||
title: 'Posts by Month',
|
||||
series: [
|
||||
{ label: 'Jan', value: 10 },
|
||||
{ label: 'Feb', value: 20 },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
key: 'query',
|
||||
label: 'Search Query',
|
||||
inputType: 'text',
|
||||
placeholder: 'Find post',
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
key: 'publishDate',
|
||||
label: 'Publish Date',
|
||||
},
|
||||
{
|
||||
type: 'form',
|
||||
formId: 'meta-form',
|
||||
title: 'Update Metadata',
|
||||
submitLabel: 'Apply',
|
||||
action: 'updatePostMetadata',
|
||||
fields: [
|
||||
{ key: 'title', label: 'Title', inputType: 'text' },
|
||||
{ key: 'isDraft', label: 'Draft', inputType: 'checkbox' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'card',
|
||||
title: 'Suggestion',
|
||||
body: 'Consider adding tags.',
|
||||
actions: [
|
||||
{ label: 'Open Tags', action: 'switchView', payload: { view: 'tags' } },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'image',
|
||||
src: 'https://example.com/image.png',
|
||||
alt: 'Preview',
|
||||
caption: 'Generated preview',
|
||||
},
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
id: 'summary',
|
||||
label: 'Summary',
|
||||
elements: [{ type: 'text', text: 'Summary text' }],
|
||||
},
|
||||
{
|
||||
id: 'details',
|
||||
label: 'Details',
|
||||
elements: [{ type: 'metric', label: 'Count', value: '42' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const result = extractAssistantPanelSpec(raw);
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.elements).toHaveLength(7);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user