Skip to content

SetupFix - Improve Testing Infrastructure & Module Structure #6184

@palisadoes

Description

@palisadoes

Problem

The setup.ts script executes immediately when imported (line 102: main()), making it impossible to test without side effects. This violates Node.js best practices where imports should be side-effect free. Additionally, there is inconsistent export strategy - askAndSetRecaptcha is exported but askAndSetLogErrors is not, creating an unclear module API.

Impact:

  • Cannot import the module for unit testing without triggering full setup execution
  • Test file must use extensive mocking to work around immediate execution
  • Inconsistent exports make it unclear which functions are part of the public API
  • Harder for contributors to write tests for setup functionality

Scope

  • src/setup/setup.ts (module execution and exports)
  • src/setup/setup.spec.ts (test improvements)
  • All helper functions that should be testable independently

Approach

  1. Conditional Execution: Wrap module-level execution in require.main === module check
  2. Export Standardization: Make export strategy consistent across all testable functions
  3. Test Improvements: Update tests to import functions directly instead of relying on mocks

This follows Node.js CLI tool patterns where scripts can be both executed directly and imported for testing.

Files to Modify

  • src/setup/setup.ts - Add conditional execution, standardize exports
  • src/setup/setup.spec.ts - Simplify test setup by removing unnecessary mocks

Acceptance Criteria

  • main() is only called when script is executed directly, not on import
  • Both askAndSetRecaptcha and askAndSetLogErrors have consistent export strategy
  • Tests can import functions without triggering setup execution
  • Error handling includes proper process exit codes
  • No breaking changes to existing functionality
  • All existing tests pass

Extensive Starter Code

1. Make module execution conditional

Current code (line 102):

main();  // Executes on import

Updated code:

// Only execute if run directly, not when imported
if (require.main === module) {
  main().catch((error) => {
    console.error("Setup failed:", error);
    process.exit(1);
  });
}

2. Standardize exports

Current code:

export const askAndSetRecaptcha = async (): Promise<void> => { ... }  // Exported

const askAndSetLogErrors = async (): Promise<void> => { ... }  // NOT exported

Updated code:

export const askAndSetRecaptcha = async (): Promise<void> => { ... }

export const askAndSetLogErrors = async (): Promise<void> => { ... }  // Now exported

3. Update test file to use direct imports

Current pattern in setup.spec.ts:

vi.mock("./setup", async () => {
  const actual = await vi.importActual("./setup");
  return {
    ...actual,
    // Extensive mocking due to immediate execution
  };
});

Simplified pattern:

import { main, askAndSetRecaptcha, askAndSetLogErrors } from "./setup";

// Now we can test functions directly without complex mocking
describe("main", () => {
  it("should execute setup flow", async () => {
    // Direct function testing
  });
});

Pattern Reference

This pattern matches standard Node.js CLI tools where the same file can be executed directly or imported for testing. Similar to how tools like eslint, prettier, etc. structure their entry points.

Metadata

Metadata

Labels

Type

No type

Projects

Status

Backlog

Status

Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions