/**
* Tests for get_company tool exploration features
*
* Tests the optional include_* parameters for fetching related data
* (notes, tasks, threads, meetings, list entries)
*/
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { handleGetCompany } from '../../../src/tools/get-company.js';
import { createMockAttioClient } from '../../helpers/mock-attio-client.js';
import * as attioClientModule from '../../../src/attio-client.js';
vi.mock('../../../src/attio-client.js', () => ({
createAttioClient: vi.fn(),
}));
describe('get_company exploration features', () => {
let mockClient: ReturnType<typeof createMockAttioClient>;
let originalApiKey: string | undefined;
const mockCompanyResponse = {
data: {
id: {
workspace_id: 'ws-123',
object_id: 'obj-123',
record_id: 'company-123',
},
values: {
name: [{ value: 'Acme Corp' }],
domains: [{ domain: 'acme.com' }],
description: [{ value: 'A great company' }],
},
},
};
beforeEach(() => {
originalApiKey = process.env.ATTIO_API_KEY;
process.env.ATTIO_API_KEY = 'test-api-key';
mockClient = createMockAttioClient();
vi.mocked(attioClientModule.createAttioClient).mockReturnValue(
mockClient as any
);
});
afterEach(() => {
if (originalApiKey) {
process.env.ATTIO_API_KEY = originalApiKey;
} else {
delete process.env.ATTIO_API_KEY;
}
mockClient.reset();
vi.clearAllMocks();
});
describe('Backward compatibility', () => {
it('should work without any include_* parameters', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
const result = await handleGetCompany({ record_id: 'company-123' });
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.record_id).toBe('company-123');
expect(parsed.data.name).toBe('Acme Corp');
expect(parsed.data.notes).toBeUndefined();
expect(parsed.data.tasks).toBeUndefined();
});
});
describe('include_notes', () => {
it('should fetch notes when include_notes=true', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
mockClient.mockResponse('GET', '/notes?parent_object=companies&parent_record_id=company-123', {
data: {
data: [
{
id: { note_id: 'note-1' },
title: 'Partnership Discussion',
content_plaintext: 'Discussed potential partnership',
content_markdown: '# Partnership Discussion',
created_at: '2024-11-15T10:00:00Z',
created_by_actor: { type: 'user', id: 'user-1' },
},
],
},
});
const result = await handleGetCompany({
record_id: 'company-123',
include_notes: true,
});
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.notes).toHaveLength(1);
expect(parsed.data.notes[0].id).toBe('note-1');
expect(parsed.data.notes[0].title).toBe('Partnership Discussion');
});
it('should return empty array if notes fetch fails', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
mockClient.mockResponse('GET', '/notes?parent_object=companies&parent_record_id=company-123', {
error: 'API error',
status: 500,
});
const result = await handleGetCompany({
record_id: 'company-123',
include_notes: true,
});
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.notes).toEqual([]);
});
});
describe('include_all', () => {
it('should fetch all related data when include_all=true', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
mockClient.mockResponse('GET', '/notes?parent_object=companies&parent_record_id=company-123', {
data: { data: [{ id: { note_id: 'note-1' }, title: 'Note', content_plaintext: '', content_markdown: '', created_at: '2024-11-15T10:00:00Z', created_by_actor: {} }] },
});
mockClient.mockResponse('GET', '/tasks?linked_object=companies&linked_record_id=company-123', {
data: { data: [{ id: { task_id: 'task-1' }, content_plaintext: 'Task', deadline_at: null, is_completed: false, assignees: [], linked_records: [], created_at: '2024-11-15T10:00:00Z' }] },
});
mockClient.mockResponse('GET', '/threads?record_id=company-123&object=companies', {
data: { data: [{ id: { thread_id: 'thread-1' }, comments: [], created_at: '2024-11-15T10:00:00Z' }] },
});
mockClient.mockResponse('GET', '/meetings?linked_object=companies&linked_record_id=company-123', {
data: { data: [{ id: { meeting_id: 'meeting-1' }, title: 'Meeting', description: '', start: {}, end: {}, participants: [], linked_records: [], created_at: '2024-11-15T10:00:00Z' }] },
});
mockClient.mockResponse('GET', '/objects/companies/records/company-123/entries', {
data: { data: [{ id: { list_id: 'list-1', entry_id: 'entry-1' }, created_at: '2024-11-15T10:00:00Z', entry_values: {} }] },
});
const result = await handleGetCompany({
record_id: 'company-123',
include_all: true,
});
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.notes).toHaveLength(1);
expect(parsed.data.tasks).toHaveLength(1);
expect(parsed.data.comment_threads).toHaveLength(1);
expect(parsed.data.meetings).toHaveLength(1);
expect(parsed.data.list_entries).toHaveLength(1);
});
it('should continue even if some fetches fail', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
mockClient.mockResponse('GET', '/notes?parent_object=companies&parent_record_id=company-123', {
data: { data: [{ id: { note_id: 'note-1' }, title: 'Note', content_plaintext: '', content_markdown: '', created_at: '2024-11-15T10:00:00Z', created_by_actor: {} }] },
});
mockClient.mockResponse('GET', '/tasks?linked_object=companies&linked_record_id=company-123', {
error: 'Failed',
status: 500,
});
mockClient.mockResponse('GET', '/threads?record_id=company-123&object=companies', {
data: { data: [{ id: { thread_id: 'thread-1' }, comments: [], created_at: '2024-11-15T10:00:00Z' }] },
});
mockClient.mockResponse('GET', '/meetings?linked_object=companies&linked_record_id=company-123', {
error: 'Failed',
status: 500,
});
mockClient.mockResponse('GET', '/objects/companies/records/company-123/entries', {
data: { data: [] },
});
const result = await handleGetCompany({
record_id: 'company-123',
include_all: true,
});
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.notes).toHaveLength(1);
expect(parsed.data.tasks).toEqual([]); // Failed fetch
expect(parsed.data.comment_threads).toHaveLength(1);
expect(parsed.data.meetings).toEqual([]); // Failed fetch
expect(parsed.data.list_entries).toEqual([]);
});
});
describe('Multiple include flags', () => {
it('should fetch only requested data when multiple flags are set', async () => {
mockClient.mockResponse('GET', '/objects/companies/records/company-123', {
data: mockCompanyResponse,
});
mockClient.mockResponse('GET', '/notes?parent_object=companies&parent_record_id=company-123', {
data: { data: [{ id: { note_id: 'note-1' }, title: 'Note', content_plaintext: '', content_markdown: '', created_at: '2024-11-15T10:00:00Z', created_by_actor: {} }] },
});
mockClient.mockResponse('GET', '/tasks?linked_object=companies&linked_record_id=company-123', {
data: { data: [{ id: { task_id: 'task-1' }, content_plaintext: 'Task', deadline_at: null, is_completed: false, assignees: [], linked_records: [], created_at: '2024-11-15T10:00:00Z' }] },
});
const result = await handleGetCompany({
record_id: 'company-123',
include_notes: true,
include_tasks: true,
});
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.data.notes).toHaveLength(1);
expect(parsed.data.tasks).toHaveLength(1);
expect(parsed.data.comment_threads).toBeUndefined();
expect(parsed.data.meetings).toBeUndefined();
expect(parsed.data.list_entries).toBeUndefined();
});
});
});