@msflib/testing¶
Shared testing utilities for msflib modules - focus on eliminating repeated mock definitions.
Install¶
pnpm add -D @msflib/testing
Peer Dependencies¶
- vitest >= 4
Main Feature: Hoisted Mocks¶
The core feature is createHoisedMocks() - a factory function that generates reusable mock objects for tests.
Problem It Solves¶
Before, every test file had to define the same mocks repeatedly:
const mocks = vi.hoisted(() => {
return {
storage: {
setItem: vi.fn(),
getItem: vi.fn(),
removeItem: vi.fn(),
},
coreConfig: {
baseURL: 'https://api.example.com',
accessTokenKey: 'access_token',
endpoints: {
profile: { profile: '/profile' },
},
},
api: {
get: vi.fn(),
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
},
};
});
Solution: Shared Factory¶
Now use the shared factory in your test files:
import { createHoisedMocks } from '@msflib/testing';
const mocks = vi.hoisted(() =>
createHoisedMocks({
apiMethods: ['get', 'create', 'update', 'delete'],
coreConfig: {
endpoints: {
profile: {
profile: '/profile',
},
},
},
}),
);
vi.mock('@msflib/core', () => ({
storage: mocks.storage,
getApplicationConfig: () => mocks.coreConfig,
}));
vi.mock('../api/profile.api', () => ({
createProfileApi: () => mocks.api,
}));
API¶
createHoisedMocks(options?)¶
Creates a complete mock object for use in vi.hoisted().
Parameters:
{
apiMethods?: string[]; // API method names to mock (e.g., ['get', 'create'])
coreConfig?: {
baseURL?: string; // Defaults to 'https://api.example.com'
accessTokenKey?: string; // Defaults to 'access_token'
endpoints?: Record<string, any>; // Custom endpoint overrides
}
}
Returns:
{
storage: {
(setItem, getItem, removeItem);
} // Mock storage (vi.fn)
coreConfig: {
(baseURL, accessTokenKey, endpoints);
} // Mock config
api: Record<string, Mock>; // API methods specified in apiMethods
}
Example:
const mocks = vi.hoisted(() =>
createHoisedMocks({
apiMethods: ['get', 'create', 'update', 'delete', 'uploadAvatar'],
coreConfig: {
baseURL: 'https://custom.api.com',
endpoints: {
profile: { profile: '/profile', avatar: '/profile/avatar' },
},
},
}),
);
mocks.api.get; // vi.fn
mocks.api.create; // vi.fn
mocks.api.uploadAvatar; // vi.fn
mocks.storage.getItem; // vi.fn
mocks.coreConfig.baseURL; // 'https://custom.api.com'
createMockStorage()¶
Creates just the storage mock independently.
import { createMockStorage } from '@msflib/testing';
const storage = createMockStorage();
storage.getItem('access_token');
storage.setItem('access_token', 'token123');
createMockCoreConfig(config?)¶
Creates just the core config mock independently.
import { createMockCoreConfig } from '@msflib/testing';
const config = createMockCoreConfig({
endpoints: { auth: { login: '/login' } },
});
Vitest Configurations¶
Pre-configured Vitest setups are also available:
// For React component testing (jsdom)
import { createJsdomConfig } from '@msflib/testing';
export default createJsdomConfig();
// For Node/utility testing
import { createNodeConfig } from '@msflib/testing';
export default createNodeConfig();
Benefits¶
- ✅ Single source of truth for mock definitions
- ✅ Less boilerplate in test files
- ✅ Consistent mocking patterns across modules
- ✅ Type-safe with TypeScript
- ✅ Easy to extend for new modules