← Corpus / lost-in-public / exploration
Using Test Coverage to Constrain AI Code Assistants
- Path
- explorations/Using-Test-Coverage-to-Constrain-AI.md
- Authors
- Michael Staton
- Tags
- Explorations · Fine-Tuners
Context
This document demonstrates how comprehensive test coverage can be used to effectively constrain and guide AI code assistants, using the ModeSwitcher class as an example.
Test File Overview
We have a test file at src/utils/__tests__/mode-switcher.test.js that tests the ModeSwitcher class. The tests are organized using describe blocks to group related functionality.
1. Setup and Mocks
First, we set up our test environment with mocks in setup.js:
// Mock localStorage
const localStorageMock = {
getItem: vi.fn(),
setItem: vi.fn(),
clear: vi.fn(),
removeItem: vi.fn(),
};
// Mock window object
global.window = {
matchMedia: () => ({
matches: false,
addListener: vi.fn(),
removeListener: vi.fn(),
}),
localStorage: localStorageMock,
dispatchEvent: vi.fn(),
CustomEvent: class {}
};
// Mock document
global.document = {
documentElement: {
setAttribute: vi.fn(),
removeAttribute: vi.fn(),
hasAttribute: vi.fn().mockReturnValue(false),
getAttribute: vi.fn().mockReturnValue(null)
},
addEventListener: vi.fn(),
removeEventListener: vi.fn()
};
2. Test Cases
2.1 Constructor Test
it('should initialize with light mode by default', () => {
expect(switcher.getCurrentMode()).toBe('light');
});
Verifies that a new ModeSwitcher instance defaults to ‘light’ mode.
2.2 setMode Tests
2.2.1 Setting Dark Mode
it('should set and apply dark mode', () => {
const result = switcher.setMode('dark');
expect(result).toBe('dark');
expect(switcher.getCurrentMode()).toBe('dark');
expect(window.localStorage.setItem).toHaveBeenCalledWith('mode', 'dark');
expect(document.documentElement.setAttribute).toHaveBeenCalledWith('data-mode', 'dark');
});
Tests that setting dark mode:
- Returns ‘dark’
- Updates the current mode
- Saves to localStorage
- Sets the correct data attribute on the document
2.2.2 Setting Light Mode
it('should set and apply light mode', () => {
// First set to dark to test the transition
switcher.setMode('dark');
vi.clearAllMocks();
const result = switcher.setMode('light');
expect(result).toBe('light');
expect(switcher.getCurrentMode()).toBe('light');
expect(window.localStorage.setItem).toHaveBeenCalledWith('mode', 'light');
expect(document.documentElement.removeAttribute).toHaveBeenCalledWith('data-mode');
});
Tests:
- Transitioning from dark to light mode
- Verifies the data attribute is removed for light mode
2.2.3 Invalid Mode
it('should warn and return current mode for invalid mode', () => {
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const result = switcher.setMode('invalid-mode');
expect(result).toBe('light'); // Should remain at default
expect(consoleWarnSpy).toHaveBeenCalledWith("Invalid mode: invalid-mode. Valid modes are 'light' and 'dark'.");
consoleWarnSpy.mockRestore();
});
Tests:
- Invalid modes are rejected
- Warning is logged
- Current mode remains unchanged
2.3 toggleMode Tests
2.3.1 Toggle from Light to Dark
it('should toggle from light to dark mode', () => {
switcher.toggleMode();
expect(switcher.getCurrentMode()).toBe('dark');
expect(window.localStorage.setItem).toHaveBeenCalledWith('mode', 'dark');
expect(document.documentElement.setAttribute).toHaveBeenCalledWith('data-mode', 'dark');
});
Tests:
- Toggling from light to dark
- Mode is saved and applied
2.3.2 Toggle from Dark to Light
it('should toggle from dark to light mode', () => {
// First set to dark
switcher.setMode('dark');
vi.clearAllMocks();
switcher.toggleMode();
expect(switcher.getCurrentMode()).toBe('light');
expect(window.localStorage.setItem).toHaveBeenCalledWith('mode', 'light');
expect(document.documentElement.removeAttribute).toHaveBeenCalledWith('data-mode');
});
Tests:
- Toggling from dark to light
- Data attribute is removed
2.4 getCurrentMode Test
it('should return the current mode', () => {
expect(switcher.getCurrentMode()).toBe('light');
switcher.setMode('dark');
expect(switcher.getCurrentMode()).toBe('dark');
});
Verifies:
- Getter returns the current mode
- Updates correctly after mode changes
3. Test Isolation
Each test is isolated because:
- We create a fresh
ModeSwitcherinstance inbeforeEach - We clear all mocks between tests
- We restore any spied functions after use
4. What These Tests Ensure
- State Management: The mode is correctly tracked and updated
- Persistence: Modes are properly saved to localStorage
- DOM Updates: The correct data attributes are set/removed
- Error Handling: Invalid inputs are handled gracefully
- API Contract: The public interface behaves as expected
5. Potential Additional Tests
While we have good coverage, we could add tests for:
- System preference detection
- Initializing with a stored preference
- Edge cases like localStorage being unavailable
- Integration with the actual UI components
Conclusion
This comprehensive test suite effectively constrains the behavior of the ModeSwitcher class, ensuring that any modifications or refactoring maintain the expected functionality. By testing all public methods and edge cases, we create a safety net that helps prevent regressions and guides future development.