/* eslint-env jest */ import type { ICopilotMessage, ICopilotStep, } from '../../../service/copilot/copilot.interface'; import { generationCard, isActionDisabled, pageTurnTitle, startedGeneration, startedScan, } from '../thread-turns'; const step = ( id: string, state: ICopilotStep['state'] = 'done' ): ICopilotStep => ({ id, label: id, state }); const reply = (steps: ICopilotStep[]): ICopilotMessage => ({ role: 'assistant', content: 'Sure.', steps, }); describe('what a turn started', () => { it('sees a scan only when the tool went through', () => { expect(startedScan(reply([step('start_visibility_scan')]))).toBe(true); expect(startedScan(reply([step('start_visibility_scan', 'running')]))).toBe( true ); expect(startedScan(reply([step('start_visibility_scan', 'held')]))).toBe( false ); expect(startedScan(reply([step('start_visibility_scan', 'failed')]))).toBe( false ); expect(startedScan(reply([step('get_catalog_quality')]))).toBe(false); }); it('does not count a scan as a generation, it has its own card', () => { expect(startedGeneration(reply([step('start_visibility_scan')]))).toBe( false ); expect(startedGeneration(reply([step('generate_article')]))).toBe(true); }); it('shows a card for a job reported only by a directive', () => { expect( startedGeneration({ role: 'assistant', content: '', generationStatus: 'generating', }) ).toBe(true); }); }); describe('the card a turn earns', () => { it('has nothing to say about a turn that started nothing', () => { expect(generationCard(reply([step('get_catalog_quality')]))).toBeNull(); }); it('reads an emailed product-content job', () => { expect( generationCard({ ...reply([step('generate_product_content')]), generationKind: 'content', }) ).toEqual({ kind: 'content', status: 'working' }); }); it('reads a Company ID push that gave up', () => { expect( generationCard({ ...reply([step('push_company_id_to_visibility')]), generationKind: 'company_id_engines', generationWatch: 'push', generationStatus: 'stalled', }) ).toEqual({ kind: 'company_id', status: 'stalled', watch: 'push' }); }); it('carries the article id so the card can open it', () => { expect( generationCard({ ...reply([step('generate_article')]), generationArticleId: 'art-1', generationStatus: 'ready', }) ).toEqual({ kind: 'article', status: 'ready', articleId: 'art-1' }); }); }); describe('a quick-action chip', () => { it('cannot ask a question while one is being answered', () => { const chip = { label: 'Fix it', kind: 'primary' as const, action: 'prompt' as const, prompt: 'Fix it', }; expect(isActionDisabled(chip, true)).toBe(true); expect(isActionDisabled(chip, false)).toBe(false); }); it('is dead when the agent sent it without a target', () => { expect( isActionDisabled( { label: 'Open', kind: 'secondary', action: 'navigate' }, false ) ).toBe(true); expect( isActionDisabled( { label: 'Ask', kind: 'secondary', action: 'prompt' }, false ) ).toBe(true); }); }); describe('the title of a conversation a page opened', () => { it('is the first line of what the page asked, cut at a word', () => { expect( pageTurnTitle( 'Write a meta description (up to 155 characters) for each of these published pages without one, then save it with the SEO tools:\n- Contact (http://localhost:8080/contact/)' ) ).toBe('Write a meta description (up to 155 characters) for each…'); expect(pageTurnTitle('Help me: Connect your store')).toBe( 'Help me: Connect your store' ); expect(pageTurnTitle('Fix these pages:\n- One')).toBe('Fix these pages'); }); });