← back to Designer Wallcoverings
DW-Agents/__tests__/unit/test-utils.test.ts
208 lines
/**
* Unit Tests for Test Utilities
* Tests for helper functions and utilities used across the test suite
*/
describe('Test Utilities', () => {
describe('waitFor utility', () => {
it('should wait for condition to become true', async () => {
let counter = 0;
const condition = () => {
counter++;
return counter >= 3;
};
await global.testUtils.waitFor(condition, 5000);
expect(counter).toBeGreaterThanOrEqual(3);
});
it('should timeout if condition never becomes true', async () => {
const condition = () => false;
await expect(
global.testUtils.waitFor(condition, 500)
).rejects.toThrow(/Timeout waiting for condition/);
});
it('should resolve immediately if condition is already true', async () => {
const startTime = Date.now();
await global.testUtils.waitFor(() => true, 5000);
const duration = Date.now() - startTime;
expect(duration).toBeLessThan(500);
});
it('should handle async conditions', async () => {
let counter = 0;
const asyncCondition = async () => {
counter++;
await new Promise(resolve => setTimeout(resolve, 50));
return counter >= 2;
};
await global.testUtils.waitFor(asyncCondition, 5000);
expect(counter).toBeGreaterThanOrEqual(2);
});
});
describe('retry utility', () => {
it('should succeed on first try if operation succeeds', async () => {
let attempts = 0;
const operation = async () => {
attempts++;
return 'success';
};
const result = await global.testUtils.retry(operation, 3, 100);
expect(result).toBe('success');
expect(attempts).toBe(1);
});
it('should retry on failure and eventually succeed', async () => {
let attempts = 0;
const operation = async () => {
attempts++;
if (attempts < 3) {
throw new Error('Not yet');
}
return 'success';
};
const result = await global.testUtils.retry(operation, 5, 50);
expect(result).toBe('success');
expect(attempts).toBe(3);
});
it('should fail after max retries', async () => {
const operation = async () => {
throw new Error('Always fails');
};
await expect(
global.testUtils.retry(operation, 3, 50)
).rejects.toThrow('Always fails');
});
it('should wait specified delay between retries', async () => {
let attempts = 0;
const timestamps: number[] = [];
const operation = async () => {
attempts++;
timestamps.push(Date.now());
if (attempts < 3) {
throw new Error('Not yet');
}
return 'success';
};
await global.testUtils.retry(operation, 5, 200);
// Check delays between attempts
for (let i = 1; i < timestamps.length; i++) {
const delay = timestamps[i] - timestamps[i - 1];
expect(delay).toBeGreaterThanOrEqual(180); // Allow some variance
}
});
});
describe('Global test configuration', () => {
it('should have baseURL configured', () => {
expect(global.testConfig.baseURL).toBeDefined();
expect(typeof global.testConfig.baseURL).toBe('string');
});
it('should have masterHubPort configured', () => {
expect(global.testConfig.masterHubPort).toBeDefined();
expect(typeof global.testConfig.masterHubPort).toBe('string');
});
it('should have testTimeout configured', () => {
expect(global.testConfig.testTimeout).toBeDefined();
expect(typeof global.testConfig.testTimeout).toBe('number');
expect(global.testConfig.testTimeout).toBeGreaterThan(0);
});
});
});
describe('Environment Configuration', () => {
it('should respect environment variables', () => {
// Test that env vars are properly loaded
expect(process.env.NODE_ENV).toBeDefined();
});
it('should use default values when env vars not set', () => {
const baseURL = process.env.BASE_URL || 'http://localhost';
expect(baseURL).toBeDefined();
expect(typeof baseURL).toBe('string');
});
});
describe('Mock and Stub Utilities', () => {
describe('Jest mock functions', () => {
it('should create and track mock function calls', () => {
const mockFn = jest.fn();
mockFn('arg1', 'arg2');
mockFn('arg3');
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
expect(mockFn).toHaveBeenCalledWith('arg3');
});
it('should allow mock return values', () => {
const mockFn = jest.fn()
.mockReturnValueOnce('first')
.mockReturnValueOnce('second')
.mockReturnValue('default');
expect(mockFn()).toBe('first');
expect(mockFn()).toBe('second');
expect(mockFn()).toBe('default');
expect(mockFn()).toBe('default');
});
it('should allow mock implementations', () => {
const mockFn = jest.fn((x: number) => x * 2);
expect(mockFn(5)).toBe(10);
expect(mockFn(10)).toBe(20);
});
it('should track call arguments', () => {
const mockFn = jest.fn();
mockFn('a', 1);
mockFn('b', 2);
expect(mockFn.mock.calls[0]).toEqual(['a', 1]);
expect(mockFn.mock.calls[1]).toEqual(['b', 2]);
});
});
describe('Async mock functions', () => {
it('should handle async mock functions', async () => {
const mockAsyncFn = jest.fn().mockResolvedValue('async result');
const result = await mockAsyncFn();
expect(result).toBe('async result');
expect(mockAsyncFn).toHaveBeenCalled();
});
it('should handle rejected promises', async () => {
const mockAsyncFn = jest.fn().mockRejectedValue(new Error('async error'));
await expect(mockAsyncFn()).rejects.toThrow('async error');
});
});
});