Skip to content

Fix CLI auth tests localStorage issue (#135)#137

Merged
alexinslc merged 1 commit intomainfrom
fix/cli-auth-tests
Jan 10, 2026
Merged

Fix CLI auth tests localStorage issue (#135)#137
alexinslc merged 1 commit intomainfrom
fix/cli-auth-tests

Conversation

@alexinslc
Copy link
Copy Markdown
Owner

Description

Fixes #135 - CLI authentication tests were failing with a localStorage initialization error in Node.js v20+.

Changes Made

Fixed localStorage Issue

  • Created custom Jest environment (jest-environment-node-no-storage.js) that patches Node.js global localStorage before Jest initializes
  • This prevents the "Cannot initialize local storage without a --localstorage-file path" error that occurs with jest-environment-node in Node.js v20+

Implemented Comprehensive Auth Tests

  • Replaced placeholder tests with 10 real, meaningful tests
  • Login command tests (5):
    • Successful login with credential storage
    • 401 authentication failure handling
    • 400 bad request error handling
    • Network error handling
    • Config directory creation when it doesn't exist
  • Logout command tests (2):
    • Clear stored credentials
    • Handle logout when not authenticated
  • getConfig function tests (3):
    • Return config when file exists
    • Return null when file doesn't exist
    • Return null when file is corrupted (invalid JSON)

Test Implementation Details

  • Properly mocked all dependencies: axios, fs, os, readline
  • Fixed mock initialization order (mocks before imports)
  • Tests verify both success and error paths
  • Tests check console output and file operations
  • All tests passing (10/10) ✅

Root Cause

The CLI doesn't actually use localStorage - it uses file-based storage (fs.readFileSync/fs.writeFileSync). The error was coming from Jest's Node environment trying to initialize Node.js's experimental localStorage API in v20+, which requires a file path.

Solution

Created a custom Jest environment that:

  1. Patches global.localStorage before Jest environment initialization
  2. Prevents the localStorage API from initializing
  3. Removes localStorage from the test global scope (since our CLI doesn't need it)

Testing

$ npx nx test cli
 PASS   cli  src/__tests__/commands/auth.test.ts
  CLI Auth Commands
    login command
      ✓ should store credentials on successful login (2 ms)
      ✓ should display error message on 401 authentication failure
      ✓ should display error message on 400 bad request (2 ms)
      ✓ should handle network errors
      ✓ should create config directory if it does not exist
    logout command
      ✓ should clear stored credentials
      ✓ should display message when not logged in
    getConfig function
      ✓ should return config when file exists
      ✓ should return null when file does not exist
      ✓ should return null when file is corrupted

Test Suites: 1 passed, 1 total
Tests:       10 passed, 10 total

Related Issues

Checklist

- Fixed 'Cannot initialize local storage' error in Node.js v20+
- Created custom Jest environment to disable localStorage initialization
- Implemented comprehensive auth command tests (10 tests, all passing)
- Tests cover login, logout, and getConfig functionality
- Tests include success cases, error handling, and edge cases
- Properly mock axios, fs, os, and readline modules

Fixes #135
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the localStorage initialization error that occurs with Jest in Node.js v20+ for CLI authentication tests. The error was caused by Jest's Node environment attempting to initialize Node.js's experimental localStorage API, which the CLI doesn't actually use (it uses file-based storage instead).

Changes:

  • Created a custom Jest environment that patches global localStorage/sessionStorage to prevent initialization errors
  • Replaced placeholder tests in auth.test.ts.skip with 10 comprehensive tests covering login, logout, and getConfig functions
  • Added proper mocking for dependencies (axios, fs, os, readline) with correct initialization order

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
apps/cli/src/tests/commands/auth.test.ts.skip Removed placeholder/skipped tests that were waiting for localStorage fix
apps/cli/src/tests/commands/auth.test.ts Added comprehensive auth tests with proper mocking and error handling coverage
apps/cli/jest-environment-node-no-storage.js Custom Jest environment that prevents localStorage initialization by patching global object
apps/cli/jest.env.setup.js Setup file that deletes localStorage/sessionStorage from global scope
apps/cli/jest.config.ts Updated to use custom environment and setup file

Comment on lines +10 to +12
// Prevent Node.js from initializing localStorage
delete global.localStorage;
delete global.sessionStorage;
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jest.env.setup.js file appears to be redundant. The custom Jest environment jest-environment-node-no-storage.js already handles removing localStorage and sessionStorage from the test global in its constructor (lines 34-35). Since setupFilesAfterEnv runs after the environment is initialized, this file is performing the same deletion operation a second time, which is unnecessary and could cause confusion about which mechanism is actually solving the localStorage issue.

Suggested change
// Prevent Node.js from initializing localStorage
delete global.localStorage;
delete global.sessionStorage;
// Note: The custom Jest environment `jest-environment-node-no-storage.js`
// is responsible for removing `localStorage` and `sessionStorage` from the
// global object. This file is intentionally left without side effects to
// avoid duplicating that logic.

Copilot uses AI. Check for mistakes.
Comment thread apps/cli/jest.config.ts
preset: '../../jest.preset.js',
testEnvironment: 'node',
testEnvironment: '<rootDir>/jest-environment-node-no-storage.js',
setupFilesAfterEnv: ['<rootDir>/jest.env.setup.js'],
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setupFilesAfterEnv configuration is redundant since the custom environment jest-environment-node-no-storage.js already handles removing localStorage and sessionStorage. The setup file performs the same deletion that's already done in the custom environment's constructor.

Suggested change
setupFilesAfterEnv: ['<rootDir>/jest.env.setup.js'],

Copilot uses AI. Check for mistakes.
Comment on lines +182 to +188
mockedFs.readFileSync.mockReturnValue(
JSON.stringify({
accessToken: 'token',
refreshToken: 'refresh',
user: mockUser,
})
);
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mockUser object includes accessToken and refreshToken at the top level, but when used as the user property in the config object, these tokens should not be included. According to the AuthConfig interface in auth.ts, the user property should only contain userId, email, firstName, lastName, and role fields. The tokens should be at the top level of the config alongside the user object, not inside it.

This causes the test to verify against an incorrect data structure. The logout function reads the config to get the user's first name, and while this test may pass, it's testing against the wrong shape of data.

Copilot uses AI. Check for mistakes.
Comment on lines +209 to +213
const mockConfig = {
accessToken: 'token',
refreshToken: 'refresh',
user: mockUser,
};
Copy link

Copilot AI Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mockUser object includes accessToken and refreshToken fields, but when used as the user property in the config object, these tokens should not be included. According to the AuthConfig interface, the user property should only contain userId, email, firstName, lastName, and role. The tokens belong at the top level of the config object, not nested inside the user object.

This causes the test to verify against an incorrect data structure.

Copilot uses AI. Check for mistakes.
@alexinslc alexinslc merged commit 3e44d9f into main Jan 10, 2026
22 of 23 checks passed
@alexinslc alexinslc deleted the fix/cli-auth-tests branch January 10, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CLI] Fix Jest Environment localStorage Issue in Auth Tests

2 participants