import { describe, it, expect } from 'vitest'; import { InMemoryGmailClient } from '../src/dev-client.js'; describe('InMemoryGmailClient', () => { describe('searchInbox', () => { it('matches a case-insensitive substring against subject/snippet', async () => { const client = new InMemoryGmailClient(); const results = await client.searchInbox({ userSub: 'lauren@seahavenind.com', query: 'INVOICE', maxResults: 10, }); expect(results.map((m) => m.id)).toEqual(['msg-l-1']); }); it('matches against the snippet body too', async () => { const client = new InMemoryGmailClient(); const results = await client.searchInbox({ userSub: 'lauren@seahavenind.com', query: 'walkthrough', maxResults: 10, }); expect(results.map((m) => m.id)).toEqual(['msg-l-2']); }); it('caps results at maxResults', async () => { const client = new InMemoryGmailClient(); const results = await client.searchInbox({ userSub: 'lauren@seahavenind.com', query: '', maxResults: 1, }); expect(results).toHaveLength(1); }); it("is partitioned by userSub — lauren cannot see adam's mail", async () => { const client = new InMemoryGmailClient(); const results = await client.searchInbox({ userSub: 'lauren@seahavenind.com', query: 'check #2087', maxResults: 10, }); expect(results).toEqual([]); const adamResults = await client.searchInbox({ userSub: 'adam@seahavenind.com', query: 'check #2087', maxResults: 10, }); expect(adamResults.map((m) => m.id)).toEqual(['msg-a-1']); }); it('returns an empty list for an unknown sub', async () => { const client = new InMemoryGmailClient(); const results = await client.searchInbox({ userSub: 'nobody@example.com', query: 'invoice', maxResults: 10, }); expect(results).toEqual([]); }); }); describe('getThreadDetail', () => { it('returns an owned thread', async () => { const client = new InMemoryGmailClient(); const thread = await client.getThreadDetail({ userSub: 'lauren@seahavenind.com', threadId: 'thr-l-1', }); expect(thread.threadId).toBe('thr-l-1'); expect(thread.subject).toBe('Invoice #4821 from Coastal Supply'); expect(thread.messages).toHaveLength(1); }); it('throws for an unknown threadId', async () => { const client = new InMemoryGmailClient(); await expect( client.getThreadDetail({ userSub: 'lauren@seahavenind.com', threadId: 'thr-missing' }), ).rejects.toThrow(/not found/); }); it('throws when the thread is not owned by the caller', async () => { const client = new InMemoryGmailClient(); await expect( client.getThreadDetail({ userSub: 'lauren@seahavenind.com', threadId: 'thr-a-1' }), ).rejects.toThrow(/not found/); }); it('throws for an unknown user', async () => { const client = new InMemoryGmailClient(); await expect( client.getThreadDetail({ userSub: 'nobody@example.com', threadId: 'thr-l-1' }), ).rejects.toThrow(/not found/); }); }); });