Skip to content

Phase 5: Refactor Tests to Use Test Utilities (IDE Adapter Refactoring) #31

@couimet

Description

@couimet

Goal

Rewrite RangeLinkNavigationHandler tests to use the new test utilities, eliminating 90% of boilerplate.

Context

Part of the IDE Adapter Refactoring initiative. Final phase that delivers clean, maintainable tests.

Parent Issue: Will be linked after parent is created
Depends on: #30


Tasks

Step 5.1: Refactor test setup

Replace current beforeEach with clean helper-based setup:

Before (~60 lines):

let mockLogger: Logger;
let mockDelimiters: DelimiterConfig;
let mockParsed: ParsedLink;
let mockDocument: vscode.TextDocument;
let mockEditor: vscode.TextEditor;

beforeEach(() => {
  mockLogger = {
    debug: jest.fn(),
    info: jest.fn(),
    warn: jest.fn(),
    error: jest.fn(),
  } as unknown as Logger;

  mockDelimiters = { line: 'L', position: 'C', hash: '#', range: '-' };
  mockParsed = { /* ... */ };
  mockDocument = { /* ... */ } as unknown as vscode.TextDocument;
  mockEditor = { /* ... */ } as unknown as vscode.TextEditor;

  (resolveWorkspacePath as jest.Mock).mockResolvedValue(vscode.Uri.file('...'));
  (vscode.workspace.openTextDocument as jest.Mock).mockResolvedValue(mockDocument);
  (vscode.window.showTextDocument as jest.Mock).mockResolvedValue(mockEditor);
  // ... 20 more lines of mock setup ...
});

After (~8 lines):

let handler: RangeLinkNavigationHandler;
let mockIdeAdapter: jest.Mocked<IdeAdapter>;
let mockLogger: jest.Mocked<Logger>;

beforeEach(() => {
  mockIdeAdapter = createMockIdeAdapter();
  mockLogger = createMockLogger();
  const delimiters = createTestDelimiters();

  (buildLinkPattern as jest.Mock).mockReturnValue(/mock-pattern/);
  handler = new RangeLinkNavigationHandler(delimiters, mockLogger, mockIdeAdapter);
});

Step 5.2: Refactor test assertions

Replace brittle vscode API assertions with IdeAdapter assertions:

Before:

expect(vscode.workspace.openTextDocument).toHaveBeenCalledWith(mockUri);
expect(vscode.window.showTextDocument).toHaveBeenCalledWith(mockDocument);
expect(vscode.Position).toHaveBeenCalledWith(9, 4);

After:

expect(mockIdeAdapter.openDocument).toHaveBeenCalledWith(
  expect.objectContaining({ fsPath: 'src/file.ts' })
);
expect(mockIdeAdapter.showDocument).toHaveBeenCalled();
expect(mockIdeAdapter.createPosition).toHaveBeenCalledWith(9, 4);

Step 5.3: Remove vscode mock setup

Delete all jest.mock('vscode', ...) blocks - no longer needed!

Step 5.4: Fix ESLint errors

Remove all any type usages flagged in diagnostics:

  • Line 46:28, 46:38, 47:33, 47:46
  • Line 280:72, 346:29
  • Line 606:18 (unused variable)

Acceptance Criteria

  • All tests refactored to use helper functions
  • Test setup reduced by ~80-90% (measured by LOC)
  • No vscode mocks remaining in test file
  • All ESLint errors fixed (no any types, no unused variables)
  • All tests passing (37+ passing, ideally fix the 4 failing rectangular tests)
  • Code coverage maintained or improved (93.75%+)

Success Metrics

  • Before: ~650 lines of test code with ~200 lines of mock setup
  • After: ~350 lines of test code with ~30 lines of setup
  • Reduction: ~45% fewer lines, ~85% less boilerplate

Effort

Estimated: 3-4 hours
Risk: Low

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions