Files
listify/listify-client/src/app/assistant/assistant-chat.component.spec.ts
Bastian Wagner cb938d3dc8 Vorschläge
2026-06-15 09:44:59 +02:00

150 lines
4.3 KiB
TypeScript

import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Router, provideRouter } from '@angular/router';
import { of, throwError } from 'rxjs';
import { Mock, vi } from 'vitest';
import { UserList } from '../lists/lists.models';
import { ListsService } from '../lists/lists.service';
import { TemplatesService } from '../templates/templates.service';
import { AssistantChatComponent } from './assistant-chat.component';
import { AssistantService } from './assistant.service';
@Component({
standalone: true,
template: '',
})
class EmptyRouteComponent {}
describe('AssistantChatComponent', () => {
let assistantService: { chat: Mock };
let listsService: { getList: Mock };
let templatesService: { getTemplate: Mock };
let router: Router;
beforeEach(async () => {
assistantService = {
chat: vi.fn().mockReturnValue(
of({
message: { role: 'assistant', content: 'ok' },
actions: [],
}),
),
};
listsService = {
getList: vi.fn(),
};
templatesService = {
getTemplate: vi.fn(),
};
await TestBed.configureTestingModule({
imports: [AssistantChatComponent],
providers: [
provideRouter([
{ path: 'lists', component: EmptyRouteComponent },
{ path: 'lists/:listId', component: EmptyRouteComponent },
{ path: 'templates', component: EmptyRouteComponent },
{ path: 'templates/:templateId', component: EmptyRouteComponent },
]),
{ provide: AssistantService, useValue: assistantService },
{ provide: ListsService, useValue: listsService },
{ provide: TemplatesService, useValue: templatesService },
],
}).compileComponents();
router = TestBed.inject(Router);
});
it('sends list detail context with the current list', async () => {
const list = createList();
listsService.getList.mockReturnValue(of(list));
await router.navigateByUrl('/lists/list-1');
const fixture = TestBed.createComponent(AssistantChatComponent);
const component = fixture.componentInstance as unknown as {
draft: { set(value: string): void };
send(): void;
};
component.draft.set('Was ist hier offen?');
component.send();
expect(listsService.getList).toHaveBeenCalledOnce();
expect(listsService.getList).toHaveBeenCalledWith('list-1');
expect(assistantService.chat).toHaveBeenCalledWith({
messages: [
{
role: 'assistant',
content:
'Hallo, ich bin dein Listify-Assistent. Was soll ich vorbereiten?',
},
{ role: 'user', content: 'Was ist hier offen?' },
],
context: {
page: 'list_detail',
route: '/lists/list-1',
list,
},
});
});
it('falls back to route context when list context loading fails', async () => {
listsService.getList.mockReturnValue(
throwError(() => new Error('not found')),
);
await router.navigateByUrl('/lists/list-1');
const fixture = TestBed.createComponent(AssistantChatComponent);
const component = fixture.componentInstance as unknown as {
draft: { set(value: string): void };
send(): void;
};
component.draft.set('Was ist hier offen?');
component.send();
expect(assistantService.chat).toHaveBeenCalledWith(
expect.objectContaining({
context: {
page: 'unknown',
route: '/lists/list-1',
},
}),
);
});
it('sends overview context without loading a list', async () => {
await router.navigateByUrl('/lists');
const fixture = TestBed.createComponent(AssistantChatComponent);
const component = fixture.componentInstance as unknown as {
draft: { set(value: string): void };
send(): void;
};
component.draft.set('Welche Listen habe ich?');
component.send();
expect(listsService.getList).not.toHaveBeenCalled();
expect(assistantService.chat).toHaveBeenCalledWith(
expect.objectContaining({
context: {
page: 'lists_overview',
route: '/lists',
},
}),
);
});
});
function createList(): UserList {
return {
id: 'list-1',
ownerId: 'user-1',
accessRole: 'owner',
name: 'Einkauf',
kind: 'shopping',
items: [],
collaborators: [],
createdAt: '2026-06-12T00:00:00.000Z',
updatedAt: '2026-06-12T00:00:00.000Z',
};
}