tool.test.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { afterEach, describe, expect, mock, test } from 'bun:test';
  2. import { createWebfetchTool } from './tool';
  3. function createExecutionContext() {
  4. return {
  5. ask: mock(async () => undefined),
  6. metadata: mock(() => undefined),
  7. abort: new AbortController().signal,
  8. directory: '/tmp/smartfetch-test',
  9. } as any;
  10. }
  11. describe('smartfetch/tool', () => {
  12. const originalFetch = globalThis.fetch;
  13. afterEach(() => {
  14. globalThis.fetch = originalFetch;
  15. mock.restore();
  16. });
  17. test('returns a required llms.txt message when prefer_llms_txt is always and no llms.txt is available', async () => {
  18. const fetchMock = mock(async (input: string | URL | Request) => {
  19. const url = typeof input === 'string' ? input : input.toString();
  20. if (
  21. url === 'https://docs.example.com/llms-full.txt' ||
  22. url === 'https://docs.example.com/llms.txt'
  23. ) {
  24. return new Response('not found', {
  25. status: 404,
  26. headers: { 'content-type': 'text/plain' },
  27. });
  28. }
  29. throw new Error(`Unexpected fetch URL: ${url}`);
  30. });
  31. globalThis.fetch = fetchMock as unknown as typeof fetch;
  32. const webfetch = createWebfetchTool({ client: {} } as any);
  33. const ctx = createExecutionContext();
  34. const result = await webfetch.execute(
  35. {
  36. url: 'https://docs.example.com/page',
  37. format: 'markdown',
  38. extract_main: true,
  39. prefer_llms_txt: 'always',
  40. include_metadata: true,
  41. save_binary: false,
  42. },
  43. ctx,
  44. );
  45. expect(result).toContain('Required llms.txt content was unavailable.');
  46. expect(result).toContain('Original URL: https://docs.example.com/page');
  47. expect(result).toContain('prefer_llms_txt: "always"');
  48. expect(result).toContain('used_llms_txt: false');
  49. expect(ctx.ask).toHaveBeenCalledTimes(1);
  50. expect(ctx.metadata).not.toHaveBeenCalled();
  51. });
  52. });