@lwc/state-test-utils
v0.29.0
Published
Test Utilities for @lwc/state
Downloads
22,669
Maintainers
Keywords
Readme
@lwc/state-test-utils
Test utilities for @lwc/state that help you create mock state managers for testing purposes.
Overview
@lwc/state-test-utils provides utilities for creating mock implementations of state managers in your test suites. This package is particularly useful when you need to test components or functions that depend on state manager behavior without requiring a full implementation.
The main utility, stateManagerInstanceMock, creates a mock state manager instance that:
- Mimics the interface of a real state manager
- Allows direct manipulation of its value via the
updateValuemethod - Properly triggers notifications when values change
- Supports TypeScript generics for type-safe testing
API
stateManagerInstanceMock<T>(initialValue?: T): StateManagerMock<T>
Creates a mock implementation of a state manager instance for testing purposes.
Type Parameters:
T- The type of the state manager's value (defaults toRecord<string, unknown>)
Parameters:
initialValue(optional) - The initial value for the state manager mock. Defaults to an empty object{}.
Returns:
A StateManagerMock<T> object that:
- Has a
valueproperty getter that returns the current value - Has an
updateValue(newValue: T)method to update the value and trigger notifications.updateValue()returns aPromise<void>that resolves once all consumers of the state manager have been informed of the update. A test should wait for thisPromiseto resolve before checking that consumers of the state manager have reacted to the new value as expected. - Is compatible with code that consumes state managers from
@lwc/state
Type Definition:
type StateManagerMock<T> = {
value: T;
updateValue: (newValue: T) => Promise<void>;
// ... additional properties for compatibility with state manager consumers
};Usage
Basic Example
import { fromContext } from '@lwc/state';
import { stateManagerInstanceMock } from '@lwc/state-test-utils';
import CounterDisplay from 'c/counterDisplay';
jest.mock('@lwc/state', () => {
const actual = jest.requireActual('@lwc/state');
return {
...actual,
fromContext: jest.fn()
};
});
describe('MyComponent', () => {
afterEach(() => {
// Clear mocks after each test
jest.clearAllMocks();
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
});
it('should display counter value from state manager', () => {
const mockState = stateManagerInstanceMock({ counter: 5, increment: jest.fn(), });
fromContext.mockReturnValue(mockState);
const element = createElement('c-counter-display', {
is: CounterDisplay
});
document.body.appendChild(element);
// Wait for DOM to update
return Promise.resolve().then(() => {
expect(getCounterFromDOM(element)).toBe(5);
});
});
it('should call increment on state manager', () => {
const mockedStateValue = { counter: 0, increment: jest.fn(), };
const mockState = stateManagerInstanceMock(mockedStateValue);
fromContext.mockReturnValue(mockState);
const element = createElement('c-counter-display', {
is: CounterDisplay
});
document.body.appendChild(element);
// Wait for initial render
return Promise.resolve()
.then(() => {
// Verify initial state in DOM
expect(getCounterFromDOM(element)).toBe(0);
// Click increment button
const incrementButton = getIncrementButton(element);
incrementButton.click();
// Verify state manager was updated
expect(mockState.value.increment).toHaveBeenCalled();
// Increment the value, returned Promise will resolve once consumers
// of the state manager have been informed of the update
retutrn mockState.updateValue({ ...mockedStateValue, counter: 1, });
})
.then(() => {
// Verify it reflects the updated value
expect(getCounterFromDOM(element)).toBe(1);
});
});
});Typed State Manager Mock
interface UserState {
name: string;
email: string;
age: number;
}
const mockUserState = stateManagerInstanceMock<UserState>({
name: 'John Doe',
email: '[email protected]',
age: 30
});
// TypeScript will enforce the correct shape
mockUserState.updateValue({
name: 'Jane Doe',
email: '[email protected]',
age: 28
});Testing with Complex State Shapes
interface AppState {
user: {
id: string;
preferences: Record<string, unknown>;
};
settings: {
theme: 'light' | 'dark';
notifications: boolean;
};
}
const mockAppState = stateManagerInstanceMock<AppState>({
user: {
id: '123',
preferences: {}
},
settings: {
theme: 'light',
notifications: true
}
});
// Update nested properties
mockAppState.updateValue({
...mockAppState.value,
settings: {
...mockAppState.value.settings,
theme: 'dark'
}
});