@dbs-portal/core-api
Version:
HTTP client and API utilities for DBS Portal
279 lines • 9.17 kB
JavaScript
/**
* MSW integration with TanStack Query
*/
import { createQueryClient as originalCreateQueryClient } from '../../query/query-client';
import { setupMocks, isMswSetup } from '../setup';
import { getMockConfig } from '../config';
/**
* Create query client with MSW integration
*/
export async function createMockAwareQueryClient(config = {}) {
// Initialize MSW if configured
if (config.autoSetupMocks && config.mocking?.enabled) {
await setupMocks({
config: config.mocking,
handlers: config.mockHandlers || [],
start: true,
});
}
// Create query client with mock-aware defaults
const queryClientConfig = {
...config,
defaultOptions: {
...config.defaultOptions,
queries: {
...config.defaultOptions?.queries,
// Adjust retry behavior for mocked responses
retry: config.mocking?.enabled ? 1 : (config.defaultOptions?.queries?.retry ?? 3),
// Reduce stale time for development with mocks
staleTime: config.mocking?.enabled && config.mocking.mode === 'development'
? 0
: (config.defaultOptions?.queries?.staleTime ?? 5 * 60 * 1000),
},
mutations: {
...config.defaultOptions?.mutations,
// Reduce retry for mutations with mocks
retry: config.mocking?.enabled ? 0 : (config.defaultOptions?.mutations?.retry ?? 0),
},
},
};
return originalCreateQueryClient(queryClientConfig);
}
/**
* Query client wrapper with MSW utilities
*/
export class MockAwareQueryClient {
queryClient;
mockConfig;
constructor(queryClient, mockConfig) {
this.queryClient = queryClient;
this.mockConfig = mockConfig || {};
}
/**
* Get the underlying query client
*/
getClient() {
return this.queryClient;
}
/**
* Check if mocking is enabled
*/
isMocking() {
return this.mockConfig?.enabled ?? false;
}
/**
* Invalidate queries (useful after adding/removing mock handlers)
*/
async invalidateAll() {
await this.queryClient.invalidateQueries();
}
/**
* Clear all queries (useful when switching between mock/real APIs)
*/
clear() {
this.queryClient.clear();
}
/**
* Reset queries to initial state
*/
async resetQueries() {
await this.queryClient.resetQueries();
}
/**
* Refetch all queries (useful after mock data changes)
*/
async refetchAll() {
await this.queryClient.refetchQueries();
}
}
/**
* Testing utilities for MSW + React Query
*/
export const mockQueryUtils = {
/**
* Create a query client optimized for testing
*/
createTestQueryClient(mockHandlers = []) {
return createMockAwareQueryClient({
mocking: {
enabled: true,
mode: 'testing',
logging: false,
delay: 0, // No delay in tests
},
mockHandlers,
autoSetupMocks: true,
defaultOptions: {
queries: {
retry: false,
staleTime: 0,
gcTime: 0,
},
mutations: {
retry: false,
},
},
});
},
/**
* Create a query client for Storybook
*/
createStorybookQueryClient(mockHandlers = []) {
return createMockAwareQueryClient({
mocking: {
enabled: true,
mode: 'storybook',
logging: true,
delay: [100, 300],
},
mockHandlers,
autoSetupMocks: true,
defaultOptions: {
queries: {
retry: 1,
staleTime: 5 * 60 * 1000,
},
mutations: {
retry: 0,
},
},
});
},
/**
* Wait for queries to settle (useful in tests)
*/
async waitForQueries(queryClient, timeout = 5000) {
const start = Date.now();
while (Date.now() - start < timeout) {
const queries = queryClient.getQueryCache().getAll();
const isSettled = queries.every(query => query.state.status === 'success' ||
query.state.status === 'error' ||
query.state.status === 'pending');
if (isSettled) {
return;
}
await new Promise(resolve => setTimeout(resolve, 10));
}
throw new Error(`Queries did not settle within ${timeout}ms`);
},
/**
* Mock query data directly in cache
*/
setQueryData(queryClient, queryKey, data) {
queryClient.setQueryData(queryKey, data);
},
/**
* Get query data from cache
*/
getQueryData(queryClient, queryKey) {
return queryClient.getQueryData(queryKey);
},
};
/**
* Hook utilities for MSW + React Query integration
*/
export const mockHookUtils = {
/**
* Create mock-aware query options
*/
createMockQueryOptions(queryKey, mockData, options = {}) {
const mockConfig = getMockConfig();
return {
queryKey,
queryFn: async () => {
// If mocking is enabled, return mock data
if (mockConfig.enabled) {
// Simulate network delay if configured
if (mockConfig.delay) {
const delay = Array.isArray(mockConfig.delay)
? Math.floor(Math.random() * (mockConfig.delay[1] - mockConfig.delay[0] + 1)) + mockConfig.delay[0]
: mockConfig.delay;
await new Promise(resolve => setTimeout(resolve, delay));
}
return mockData;
}
// This should not be reached if MSW is properly set up
throw new Error('Mock data requested but MSW is not enabled');
},
enabled: options.enabled ?? true,
staleTime: options.staleTime ?? (mockConfig.enabled ? 0 : 5 * 60 * 1000),
gcTime: options.gcTime ?? (mockConfig.enabled ? 0 : 5 * 60 * 1000),
};
},
/**
* Create mock-aware mutation options
*/
createMockMutationOptions(mockMutationFn, options = {}) {
const mockConfig = getMockConfig();
return {
mutationFn: async (variables) => {
// If mocking is enabled, use mock function
if (mockConfig.enabled) {
// Simulate network delay if configured
if (mockConfig.delay) {
const delay = Array.isArray(mockConfig.delay)
? Math.floor(Math.random() * (mockConfig.delay[1] - mockConfig.delay[0] + 1)) + mockConfig.delay[0]
: mockConfig.delay;
await new Promise(resolve => setTimeout(resolve, delay));
}
return await Promise.resolve(mockMutationFn(variables));
}
// This should not be reached if MSW is properly set up
throw new Error('Mock mutation requested but MSW is not enabled');
},
onSuccess: options.onSuccess,
onError: options.onError,
retry: mockConfig.enabled ? 0 : 3,
};
},
};
/**
* Development utilities for MSW + React Query
*/
export const mockDevUtils = {
/**
* Log query cache state (useful for debugging)
*/
logQueryCache(queryClient) {
const queries = queryClient.getQueryCache().getAll();
console.group('Query Cache State');
queries.forEach(query => {
console.log({
queryKey: query.queryKey,
status: query.state.status,
data: query.state.data,
error: query.state.error,
lastUpdated: query.state.dataUpdatedAt,
});
});
console.groupEnd();
},
/**
* Log mutation cache state
*/
logMutationCache(queryClient) {
const mutations = queryClient.getMutationCache().getAll();
console.group('Mutation Cache State');
mutations.forEach(mutation => {
console.log({
mutationKey: mutation.options.mutationKey,
status: mutation.state.status,
data: mutation.state.data,
error: mutation.state.error,
variables: mutation.state.variables,
});
});
console.groupEnd();
},
/**
* Check if MSW is properly set up for queries
*/
checkMswSetup() {
return {
isMswSetup: isMswSetup(),
isMockingEnabled: getMockConfig().enabled,
mockConfig: getMockConfig(),
};
},
};
//# sourceMappingURL=query-integration.js.map