/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/** @vitest-environment jsdom */

import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import type { Mocked } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { useCompletion } from './useCompletion.js';
import * as fs from 'fs/promises';
import { glob } from 'glob';
import { CommandContext, SlashCommand } from '../commands/types.js';
import { Config, FileDiscoveryService } from '@google/gemini-cli-core';

// Mock dependencies
vi.mock('fs/promises');
vi.mock('glob');
vi.mock('@google/gemini-cli-core', async () => {
  const actual = await vi.importActual('@google/gemini-cli-core');
  return {
    ...actual,
    FileDiscoveryService: vi.fn(),
    isNodeError: vi.fn((error) => error.code === 'ENOENT'),
    escapePath: vi.fn((path) => path),
    unescapePath: vi.fn((path) => path),
    getErrorMessage: vi.fn((error) => error.message),
  };
});
vi.mock('glob');

describe('useCompletion', () => {
  let mockFileDiscoveryService: Mocked<FileDiscoveryService>;
  let mockConfig: Mocked<Config>;
  let mockCommandContext: CommandContext;
  let mockSlashCommands: SlashCommand[];

  const testCwd = '/test/project';

  beforeEach(() => {
    mockFileDiscoveryService = {
      shouldGitIgnoreFile: vi.fn(),
      shouldGeminiIgnoreFile: vi.fn(),
      shouldIgnoreFile: vi.fn(),
      filterFiles: vi.fn(),
      getGeminiIgnorePatterns: vi.fn(),
      projectRoot: '',
      gitIgnoreFilter: null,
      geminiIgnoreFilter: null,
    } as unknown as Mocked<FileDiscoveryService>;

    mockConfig = {
      getFileFilteringRespectGitIgnore: vi.fn(() => true),
      getFileService: vi.fn().mockReturnValue(mockFileDiscoveryService),
      getEnableRecursiveFileSearch: vi.fn(() => true),
      getFileFilteringOptions: vi.fn(() => ({
        respectGitIgnore: true,
        respectGeminiIgnore: true,
      })),
    } as unknown as Mocked<Config>;

    mockCommandContext = {} as CommandContext;

    mockSlashCommands = [
      {
        name: 'help',
        altNames: ['?'],
        description: 'Show help',
        action: vi.fn(),
      },
      {
        name: 'stats',
        altNames: ['usage'],
        description: 'check session stats. Usage: /stats [model|tools]',
        action: vi.fn(),
      },
      {
        name: 'clear',
        description: 'Clear the screen',
        action: vi.fn(),
      },
      {
        name: 'memory',
        description: 'Manage memory',
        subCommands: [
          {
            name: 'show',
            description: 'Show memory',
            action: vi.fn(),
          },
          {
            name: 'add',
            description: 'Add to memory',
            action: vi.fn(),
          },
        ],
      },
      {
        name: 'chat',
        description: 'Manage chat history',
        subCommands: [
          {
            name: 'save',
            description: 'Save chat',
            action: vi.fn(),
          },
          {
            name: 'resume',
            description: 'Resume a saved chat',
            action: vi.fn(),
            completion: vi.fn().mockResolvedValue(['chat1', 'chat2']),
          },
        ],
      },
    ];

    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  describe('Hook initialization and state', () => {
    it('should initialize with default state', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '',
          testCwd,
          false,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toEqual([]);
      expect(result.current.activeSuggestionIndex).toBe(-1);
      expect(result.current.visibleStartIndex).toBe(0);
      expect(result.current.showSuggestions).toBe(false);
      expect(result.current.isLoadingSuggestions).toBe(false);
    });

    it('should reset state when isActive becomes false', () => {
      const { result, rerender } = renderHook(
        ({ isActive }) =>
          useCompletion(
            '/help',
            testCwd,
            isActive,
            mockSlashCommands,
            mockCommandContext,
            mockConfig,
          ),
        { initialProps: { isActive: true } },
      );

      rerender({ isActive: false });

      expect(result.current.suggestions).toEqual([]);
      expect(result.current.activeSuggestionIndex).toBe(-1);
      expect(result.current.visibleStartIndex).toBe(0);
      expect(result.current.showSuggestions).toBe(false);
      expect(result.current.isLoadingSuggestions).toBe(false);
    });

    it('should provide required functions', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(typeof result.current.setActiveSuggestionIndex).toBe('function');
      expect(typeof result.current.setShowSuggestions).toBe('function');
      expect(typeof result.current.resetCompletionState).toBe('function');
      expect(typeof result.current.navigateUp).toBe('function');
      expect(typeof result.current.navigateDown).toBe('function');
    });
  });

  describe('resetCompletionState', () => {
    it('should reset all state to default values', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/help',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      act(() => {
        result.current.setActiveSuggestionIndex(5);
        result.current.setShowSuggestions(true);
      });

      act(() => {
        result.current.resetCompletionState();
      });

      expect(result.current.suggestions).toEqual([]);
      expect(result.current.activeSuggestionIndex).toBe(-1);
      expect(result.current.visibleStartIndex).toBe(0);
      expect(result.current.showSuggestions).toBe(false);
      expect(result.current.isLoadingSuggestions).toBe(false);
    });
  });

  describe('Navigation functions', () => {
    it('should handle navigateUp with no suggestions', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      act(() => {
        result.current.navigateUp();
      });

      expect(result.current.activeSuggestionIndex).toBe(-1);
    });

    it('should handle navigateDown with no suggestions', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      act(() => {
        result.current.navigateDown();
      });

      expect(result.current.activeSuggestionIndex).toBe(-1);
    });

    it('should navigate up through suggestions with wrap-around', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/h',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions.length).toBe(1);
      expect(result.current.activeSuggestionIndex).toBe(0);

      act(() => {
        result.current.navigateUp();
      });

      expect(result.current.activeSuggestionIndex).toBe(0);
    });

    it('should navigate down through suggestions with wrap-around', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/h',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions.length).toBe(1);
      expect(result.current.activeSuggestionIndex).toBe(0);

      act(() => {
        result.current.navigateDown();
      });

      expect(result.current.activeSuggestionIndex).toBe(0);
    });

    it('should handle navigation with multiple suggestions', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions.length).toBe(5);
      expect(result.current.activeSuggestionIndex).toBe(0);

      act(() => {
        result.current.navigateDown();
      });
      expect(result.current.activeSuggestionIndex).toBe(1);

      act(() => {
        result.current.navigateDown();
      });
      expect(result.current.activeSuggestionIndex).toBe(2);

      act(() => {
        result.current.navigateUp();
      });
      expect(result.current.activeSuggestionIndex).toBe(1);

      act(() => {
        result.current.navigateUp();
      });
      expect(result.current.activeSuggestionIndex).toBe(0);

      act(() => {
        result.current.navigateUp();
      });
      expect(result.current.activeSuggestionIndex).toBe(4);
    });

    it('should handle navigation with large suggestion lists and scrolling', () => {
      const largeMockCommands = Array.from({ length: 15 }, (_, i) => ({
        name: `command${i}`,
        description: `Command ${i}`,
        action: vi.fn(),
      }));

      const { result } = renderHook(() =>
        useCompletion(
          '/command',
          testCwd,
          true,
          largeMockCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions.length).toBe(15);
      expect(result.current.activeSuggestionIndex).toBe(0);
      expect(result.current.visibleStartIndex).toBe(0);

      act(() => {
        result.current.navigateUp();
      });

      expect(result.current.activeSuggestionIndex).toBe(14);
      expect(result.current.visibleStartIndex).toBe(Math.max(0, 15 - 8));
    });
  });

  describe('Slash command completion', () => {
    it('should show all commands for root slash', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(5);
      expect(result.current.suggestions.map((s) => s.label)).toEqual(
        expect.arrayContaining(['help', 'clear', 'memory', 'chat', 'stats']),
      );
      expect(result.current.showSuggestions).toBe(true);
      expect(result.current.activeSuggestionIndex).toBe(0);
    });

    it('should filter commands by prefix', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/h',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('help');
      expect(result.current.suggestions[0].description).toBe('Show help');
    });

    it.each([['/?'], ['/usage']])(
      'should not suggest commands when altNames is fully typed',
      (altName) => {
        const { result } = renderHook(() =>
          useCompletion(
            altName,
            testCwd,
            true,
            mockSlashCommands,
            mockCommandContext,
            mockConfig,
          ),
        );

        expect(result.current.suggestions).toHaveLength(0);
      },
    );

    it('should suggest commands based on partial altNames matches', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/usag', // part of the word "usage"
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('stats');
    });

    it('should not show suggestions for exact leaf command match', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/clear',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });

    it('should show sub-commands for parent commands', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/memory',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(2);
      expect(result.current.suggestions.map((s) => s.label)).toEqual(
        expect.arrayContaining(['show', 'add']),
      );
    });

    it('should show all sub-commands after parent command with space', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/memory ',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(2);
      expect(result.current.suggestions.map((s) => s.label)).toEqual(
        expect.arrayContaining(['show', 'add']),
      );
    });

    it('should filter sub-commands by prefix', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/memory a',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('add');
    });

    it('should handle unknown command gracefully', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '/unknown',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });
  });

  describe('Command argument completion', () => {
    it('should call completion function for command arguments', async () => {
      const completionFn = vi.fn().mockResolvedValue(['arg1', 'arg2']);
      const commandsWithCompletion = [...mockSlashCommands];
      const chatCommand = commandsWithCompletion.find(
        (cmd) => cmd.name === 'chat',
      );
      const resumeCommand = chatCommand?.subCommands?.find(
        (cmd) => cmd.name === 'resume',
      );
      if (resumeCommand) {
        resumeCommand.completion = completionFn;
      }

      const { result } = renderHook(() =>
        useCompletion(
          '/chat resume ',
          testCwd,
          true,
          commandsWithCompletion,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(completionFn).toHaveBeenCalledWith(mockCommandContext, '');
      expect(result.current.suggestions).toHaveLength(2);
      expect(result.current.suggestions.map((s) => s.label)).toEqual([
        'arg1',
        'arg2',
      ]);
    });

    it('should call completion function with partial argument', async () => {
      const completionFn = vi.fn().mockResolvedValue(['arg1', 'arg2']);
      const commandsWithCompletion = [...mockSlashCommands];
      const chatCommand = commandsWithCompletion.find(
        (cmd) => cmd.name === 'chat',
      );
      const resumeCommand = chatCommand?.subCommands?.find(
        (cmd) => cmd.name === 'resume',
      );
      if (resumeCommand) {
        resumeCommand.completion = completionFn;
      }

      renderHook(() =>
        useCompletion(
          '/chat resume ar',
          testCwd,
          true,
          commandsWithCompletion,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(completionFn).toHaveBeenCalledWith(mockCommandContext, 'ar');
    });

    it('should handle completion function that returns null', async () => {
      const completionFn = vi.fn().mockResolvedValue(null);
      const commandsWithCompletion = [...mockSlashCommands];
      const chatCommand = commandsWithCompletion.find(
        (cmd) => cmd.name === 'chat',
      );
      const resumeCommand = chatCommand?.subCommands?.find(
        (cmd) => cmd.name === 'resume',
      );
      if (resumeCommand) {
        resumeCommand.completion = completionFn;
      }

      const { result } = renderHook(() =>
        useCompletion(
          '/chat resume ',
          testCwd,
          true,
          commandsWithCompletion,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });
  });

  describe('File path completion (@-syntax)', () => {
    beforeEach(() => {
      vi.mocked(fs.readdir).mockResolvedValue([
        { name: 'file1.txt', isDirectory: () => false },
        { name: 'file2.js', isDirectory: () => false },
        { name: 'folder1', isDirectory: () => true },
        { name: '.hidden', isDirectory: () => false },
      ] as unknown as Awaited<ReturnType<typeof fs.readdir>>);
    });

    it('should show file completions for @ prefix', async () => {
      const { result } = renderHook(() =>
        useCompletion(
          '@',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(3);
      expect(result.current.suggestions.map((s) => s.label)).toEqual(
        expect.arrayContaining(['file1.txt', 'file2.js', 'folder1/']),
      );
    });

    it('should filter files by prefix', async () => {
      // Mock for recursive search since enableRecursiveFileSearch is true
      vi.mocked(glob).mockResolvedValue([
        `${testCwd}/file1.txt`,
        `${testCwd}/file2.js`,
      ]);

      const { result } = renderHook(() =>
        useCompletion(
          '@file',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(2);
      expect(result.current.suggestions.map((s) => s.label)).toEqual(
        expect.arrayContaining(['file1.txt', 'file2.js']),
      );
    });

    it('should include hidden files when prefix starts with dot', async () => {
      // Mock for recursive search since enableRecursiveFileSearch is true
      vi.mocked(glob).mockResolvedValue([`${testCwd}/.hidden`]);

      const { result } = renderHook(() =>
        useCompletion(
          '@.',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('.hidden');
    });

    it('should handle ENOENT error gracefully', async () => {
      const enoentError = new Error('No such file or directory');
      (enoentError as Error & { code: string }).code = 'ENOENT';
      vi.mocked(fs.readdir).mockRejectedValue(enoentError);

      const { result } = renderHook(() =>
        useCompletion(
          '@nonexistent',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });

    it('should handle other errors by resetting state', async () => {
      const consoleErrorSpy = vi
        .spyOn(console, 'error')
        .mockImplementation(() => {});
      vi.mocked(fs.readdir).mockRejectedValue(new Error('Permission denied'));

      const { result } = renderHook(() =>
        useCompletion(
          '@',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(consoleErrorSpy).toHaveBeenCalled();
      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
      expect(result.current.isLoadingSuggestions).toBe(false);

      consoleErrorSpy.mockRestore();
    });
  });

  describe('Debouncing', () => {
    it('should debounce file completion requests', async () => {
      // Mock for recursive search since enableRecursiveFileSearch is true
      vi.mocked(glob).mockResolvedValue([`${testCwd}/file1.txt`]);

      const { rerender } = renderHook(
        ({ query }) =>
          useCompletion(
            query,
            testCwd,
            true,
            mockSlashCommands,
            mockCommandContext,
            mockConfig,
          ),
        { initialProps: { query: '@f' } },
      );

      rerender({ query: '@fi' });
      rerender({ query: '@fil' });
      rerender({ query: '@file' });

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(glob).toHaveBeenCalledTimes(1);
    });
  });

  describe('Query handling edge cases', () => {
    it('should handle empty query', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });

    it('should handle query without slash or @', () => {
      const { result } = renderHook(() =>
        useCompletion(
          'regular text',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(0);
      expect(result.current.showSuggestions).toBe(false);
    });

    it('should handle query with whitespace', () => {
      const { result } = renderHook(() =>
        useCompletion(
          '   /hel',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('help');
    });

    it('should handle @ at the end of query', async () => {
      // Mock for recursive search since enableRecursiveFileSearch is true
      vi.mocked(glob).mockResolvedValue([`${testCwd}/file1.txt`]);

      const { result } = renderHook(() =>
        useCompletion(
          'some text @',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      // Wait for completion
      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      // Should process the @ query and get suggestions
      expect(result.current.isLoadingSuggestions).toBe(false);
      expect(result.current.suggestions.length).toBeGreaterThanOrEqual(0);
    });
  });

  describe('File sorting behavior', () => {
    it('should prioritize source files over test files with same base name', async () => {
      // Mock glob to return files with same base name but different extensions
      vi.mocked(glob).mockResolvedValue([
        `${testCwd}/component.test.ts`,
        `${testCwd}/component.ts`,
        `${testCwd}/utils.spec.js`,
        `${testCwd}/utils.js`,
        `${testCwd}/api.test.tsx`,
        `${testCwd}/api.tsx`,
      ]);

      mockFileDiscoveryService.shouldIgnoreFile.mockReturnValue(false);

      const { result } = renderHook(() =>
        useCompletion(
          '@comp',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(6);

      // Extract labels for easier testing
      const labels = result.current.suggestions.map((s) => s.label);

      // Verify the exact sorted order: source files should come before their test counterparts
      expect(labels).toEqual([
        'api.tsx',
        'api.test.tsx',
        'component.ts',
        'component.test.ts',
        'utils.js',
        'utils.spec.js',
      ]);
    });
  });

  describe('Config and FileDiscoveryService integration', () => {
    it('should work without config', async () => {
      vi.mocked(fs.readdir).mockResolvedValue([
        { name: 'file1.txt', isDirectory: () => false },
      ] as unknown as Awaited<ReturnType<typeof fs.readdir>>);

      const { result } = renderHook(() =>
        useCompletion(
          '@',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          undefined,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('file1.txt');
    });

    it('should respect file filtering when config is provided', async () => {
      vi.mocked(fs.readdir).mockResolvedValue([
        { name: 'file1.txt', isDirectory: () => false },
        { name: 'ignored.log', isDirectory: () => false },
      ] as unknown as Awaited<ReturnType<typeof fs.readdir>>);

      mockFileDiscoveryService.shouldIgnoreFile.mockImplementation(
        (path: string) => path.includes('.log'),
      );

      const { result } = renderHook(() =>
        useCompletion(
          '@',
          testCwd,
          true,
          mockSlashCommands,
          mockCommandContext,
          mockConfig,
        ),
      );

      await act(async () => {
        await new Promise((resolve) => setTimeout(resolve, 150));
      });

      expect(result.current.suggestions).toHaveLength(1);
      expect(result.current.suggestions[0].label).toBe('file1.txt');
    });
  });
});
