import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import {
DEFAULT_SKILLS,
DEFAULT_TOOLS,
AGENTS,
loadStoredSkills,
saveStoredSkills,
loadStoredTools,
loadActiveAgentId,
saveActiveAgentId,
} from '@/pages/doormile/settings/agentStudio/agentRegistryData';
// Stub lucide-react ESM exports for Jest
jest.mock('lucide-react', () => {
return new Proxy(
{},
{
get: (target, prop) => {
if (prop === '__esModule') return true;
return (props) => ;
},
}
);
});
// Stub framer-motion layout animations for jsdom
jest.mock('framer-motion', () => ({
motion: {
div: ({ children, ...rest }) =>
{children}
,
span: ({ children, ...rest }) => {children},
},
AnimatePresence: ({ children }) => <>{children}>,
}));
import SkillCard from '@/pages/doormile/settings/agentStudio/SkillCard';
import SkillCardsGrid from '@/pages/doormile/settings/agentStudio/SkillCardsGrid';
import ToolRegistryView from '@/pages/doormile/settings/agentStudio/ToolRegistryView';
describe('Agent Studio — Data Layer & Persistence', () => {
beforeEach(() => {
localStorage.clear();
});
it('pre-seeds default agents and surfaces correctly', () => {
expect(AGENTS.length).toBeGreaterThanOrEqual(2);
expect(AGENTS.some((a) => a.name === 'MileTruth AI Agent')).toBe(true);
expect(AGENTS.some((a) => a.name === 'MileTruth AI Dispatcher')).toBe(true);
});
it('pre-seeds default skills matching reference image', () => {
expect(DEFAULT_SKILLS.some((s) => s.title === 'MileTruth Skill Management')).toBe(true);
expect(DEFAULT_SKILLS.some((s) => s.title === 'Learning Analysis')).toBe(true);
const learningSkill = DEFAULT_SKILLS.find((s) => s.title === 'Learning Analysis');
expect(learningSkill.prompt).toBe('How is training progressing?');
expect(learningSkill.category).toBe('WORKFORCE');
});
it('persists modified skills to localStorage and restores them', () => {
const customSkill = {
id: 'custom-skill-1',
title: 'Custom Automation Skill',
category: 'LOGISTICS',
scope: 'agent',
enabled: true,
description: 'Test custom capability',
tools: ['create_single_order'],
};
saveStoredSkills([customSkill]);
const restored = loadStoredSkills();
expect(restored.length).toBe(1);
expect(restored[0].title).toBe('Custom Automation Skill');
});
it('saves and loads active agent id', () => {
saveActiveAgentId('miletruth-agent');
expect(loadActiveAgentId()).toBe('miletruth-agent');
});
});
describe('Agent Studio — SkillCard Component', () => {
const sampleSkill = {
id: 'test-skill-1',
title: 'MileTruth Skill Management',
category: 'AUTHORING',
scope: 'agent',
integration: 'MileTruth AI',
enabled: true,
description: 'Create workforce skills, training and verification in MileTruth AI.',
prompt: 'How is training progressing?',
tools: ['open_add_training'],
};
it('renders title, description, category, and prompt trigger bubble', () => {
render( {}} onDetails={() => {}} />);
expect(screen.getByText('MileTruth Skill Management')).toBeInTheDocument();
expect(
screen.getByText('Create workforce skills, training and verification in MileTruth AI.')
).toBeInTheDocument();
expect(screen.getByText('AUTHORING')).toBeInTheDocument();
expect(screen.getByText('"How is training progressing?"')).toBeInTheDocument();
expect(screen.getByText('MileTruth AI')).toBeInTheDocument();
});
it('fires onTest when Test in Playground is clicked', () => {
const handleTest = jest.fn();
render( {}} />);
const testBtn = screen.getByText('Test in Playground');
fireEvent.click(testBtn);
expect(handleTest).toHaveBeenCalledWith(sampleSkill);
});
it('fires onDetails when Details button is clicked', () => {
const handleDetails = jest.fn();
render( {}} onDetails={handleDetails} />);
const detailsBtn = screen.getByText('Details');
fireEvent.click(detailsBtn);
expect(handleDetails).toHaveBeenCalledWith(sampleSkill);
});
});
describe('Agent Studio — SkillCardsGrid Component', () => {
it('renders skill cards and filters by search query', () => {
render(
{}}
onOpenDetails={() => {}}
onNewSkill={() => {}}
/>
);
expect(screen.getByText('MileTruth Skill Management')).toBeInTheDocument();
expect(screen.getByText('Learning Analysis')).toBeInTheDocument();
const searchInput = screen.getByPlaceholderText('Search skills, capabilities or pages...');
fireEvent.change(searchInput, { target: { value: 'Learning' } });
expect(screen.queryByText('MileTruth Skill Management')).not.toBeInTheDocument();
expect(screen.getByText('Learning Analysis')).toBeInTheDocument();
});
it('filters by category pill selection', () => {
render(
{}}
onOpenDetails={() => {}}
onNewSkill={() => {}}
/>
);
// Click 'Authoring' category pill
const authoringPill = screen.getByText('Authoring');
fireEvent.click(authoringPill);
expect(screen.getByText('MileTruth Skill Management')).toBeInTheDocument();
expect(screen.queryByText('Learning Analysis')).not.toBeInTheDocument();
});
it('triggers onNewSkill when clicking New skill button', () => {
const handleNewSkill = jest.fn();
render(
{}}
onOpenDetails={() => {}}
onNewSkill={handleNewSkill}
/>
);
const newSkillBtn = screen.getByText('New skill');
fireEvent.click(newSkillBtn);
expect(handleNewSkill).toHaveBeenCalled();
});
});
describe('Agent Studio — ToolRegistryView Component', () => {
it('renders tool registry table and displays argument schemas', () => {
render();
expect(screen.getByText('open_add_skill_training')).toBeInTheDocument();
expect(screen.getByText('create_single_order')).toBeInTheDocument();
expect(screen.getByText('rebalance_riders')).toBeInTheDocument();
});
it('filters tool list by search input', () => {
render();
const searchInput = screen.getByPlaceholderText(
'Filter tools by function name, category or description...'
);
fireEvent.change(searchInput, { target: { value: 'rebalance' } });
expect(screen.getByText('rebalance_riders')).toBeInTheDocument();
expect(screen.queryByText('open_add_skill_training')).not.toBeInTheDocument();
});
});