Skip to content

Commit

Permalink
test: add more test cases for improving coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
saikumarrs committed Mar 2, 2025
1 parent 46ae303 commit 03e4dba
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 5 deletions.
5 changes: 4 additions & 1 deletion packages/analytics-js-common/__mocks__/StoreManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type { IStoreConfig, IStoreManager } from '../src/types/Store';
import { defaultPluginsManager } from './PluginsManager';
import { defaultCookieStorage, defaultInMemoryStorage, defaultLocalStorage } from './Storage';
import { defaultStore, Store } from './Store';

import { defaultLogger } from './Logger';
import { defaultErrorHandler } from './ErrorHandler';
// Mock all the methods of the StoreManager class

class StoreManager implements IStoreManager {
Expand All @@ -26,6 +27,8 @@ class StoreManager implements IStoreManager {
};
getStore = jest.fn(() => defaultStore);
initializeStorageState = jest.fn();
logger = defaultLogger;
errorHandler = defaultErrorHandler;
}

const defaultStoreManager = new StoreManager();
Expand Down
2 changes: 1 addition & 1 deletion packages/analytics-js-plugins/.size-limit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default [
{
name: 'Plugins - Legacy - CDN',
path: 'dist/cdn/legacy/plugins/rsa-plugins-*.min.js',
limit: '14.1 KiB',
limit: '14.5 KiB',
},
{
name: 'Plugins - Modern - CDN',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { QueueStatuses } from '@rudderstack/analytics-js-common/constants/QueueS
import { defaultStoreManager } from '@rudderstack/analytics-js-common/__mocks__/StoreManager';
import { defaultLocalStorage } from '@rudderstack/analytics-js-common/__mocks__/Storage';
import { Store } from '@rudderstack/analytics-js-common/__mocks__/Store';
import { defaultLogger } from '@rudderstack/analytics-js-common/__mocks__/Logger';
import { Schedule } from '../../../src/utilities/retryQueue/Schedule';
import { RetryQueue } from '../../../src/utilities/retryQueue/RetryQueue';
import type { QueueItem, QueueItemData } from '../../../src/types/plugins';
Expand Down Expand Up @@ -33,6 +34,8 @@ describe('Queue', () => {
},
jest.fn(),
defaultStoreManager,
undefined,
defaultLogger,
);
queue.schedule = schedule;
});
Expand Down Expand Up @@ -247,7 +250,7 @@ describe('Queue', () => {
it('should retry a task if it fails', () => {
queue.start();

// Fail the first time, Succeed the second time
// Fail the first time, succeed the last time
const mockProcessItemCb = jest
.fn()
.mockImplementationOnce((_, cb) => cb(new Error('no')))
Expand Down Expand Up @@ -298,6 +301,86 @@ describe('Queue', () => {
});
});

it('should retry queue item if process function throws an error', () => {
queue.start();

const mockProcessItemCb = jest
.fn()
.mockImplementationOnce(() => {
throw new Error('error 1');
})
.mockImplementationOnce(() => {
throw new Error('error 2');
})
.mockImplementationOnce(() => {
throw new Error('error 3');
});
queue.processQueueCb = mockProcessItemCb;
queue.maxAttempts = 2;

queue.addItem('a');

expect(mockProcessItemCb).toHaveBeenCalledTimes(1);
expect(mockProcessItemCb).toHaveBeenCalledWith('a', expect.any(Function), {
retryAttemptNumber: 0,
maxRetryAttempts: 2,
willBeRetried: true,
timeSinceFirstAttempt: expect.any(Number),
timeSinceLastAttempt: expect.any(Number),
reclaimed: false,
});
expect(defaultLogger.error).toHaveBeenCalledTimes(1);
expect(defaultLogger.error).toHaveBeenCalledWith(
'RetryQueue:: An unknown error occurred while processing the queue item. The item will be requeued.',
new Error('error 1'),
);

// Delay for the first retry
mockProcessItemCb.mockClear();
defaultLogger.error.mockClear();
jest.advanceTimersByTime(queue.getDelay(1));

expect(mockProcessItemCb).toHaveBeenCalledTimes(1);
expect(mockProcessItemCb).toHaveBeenCalledWith('a', expect.any(Function), {
retryAttemptNumber: 1,
maxRetryAttempts: 2,
willBeRetried: true,
timeSinceFirstAttempt: expect.any(Number),
timeSinceLastAttempt: expect.any(Number),
reclaimed: false,
});
expect(defaultLogger.error).toHaveBeenCalledTimes(1);
expect(defaultLogger.error).toHaveBeenCalledWith(
'RetryQueue:: An unknown error occurred while processing the queue item. The item will be requeued. Retry attempt 1 of 2.',
new Error('error 2'),
);

// Delay for the second retry
mockProcessItemCb.mockClear();
defaultLogger.error.mockClear();
jest.advanceTimersByTime(queue.getDelay(2));

expect(mockProcessItemCb).toHaveBeenCalledTimes(1);
expect(mockProcessItemCb).toHaveBeenCalledWith('a', expect.any(Function), {
retryAttemptNumber: 2,
maxRetryAttempts: 2,
willBeRetried: false, // because maxAttempts is 2
timeSinceFirstAttempt: expect.any(Number),
timeSinceLastAttempt: expect.any(Number),
reclaimed: false,
});
expect(defaultLogger.error).toHaveBeenCalledTimes(1);
expect(defaultLogger.error).toHaveBeenCalledWith(
'RetryQueue:: An unknown error occurred while processing the queue item. Retries exhausted (2). The item will be dropped.',
new Error('error 3'),
);

// No retries left as all attempts have been made
expect(queue.getStorageEntry('queue')).toEqual([]);
expect(queue.getStorageEntry('batchQueue')).toEqual([]);
expect(queue.getStorageEntry('inProgress')).toEqual({});
});

it('should delay retries', () => {
const mockProcessItemCb = jest.fn((_, cb) => cb());
queue.processQueueCb = mockProcessItemCb;
Expand Down Expand Up @@ -389,6 +472,19 @@ describe('Queue', () => {
expect(storedQueue[99].item).toEqual(104);
});

it('should respect maxItems configuration value 1', () => {
queue.maxItems = 1;

for (let i = 0; i < 105; i += 1) {
jest.advanceTimersByTime(1);
queue.addItem(i);
}

const storedQueue = queue.store.get(QueueStatuses.QUEUE);
expect(storedQueue.length).toEqual(1);
expect(storedQueue[0].item).toEqual(104);
});

it('should take over a queued task if a queue is abandoned', () => {
// a wild queue of interest appears
const foundQueue = new Store(
Expand Down
4 changes: 2 additions & 2 deletions packages/analytics-js/.size-limit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default [
name: 'Core - Legacy - NPM (CJS)',
path: 'dist/npm/legacy/cjs/index.cjs',
import: '*',
limit: '48 KiB',
limit: '48.2 KiB',
},
{
name: 'Core - Legacy - NPM (UMD)',
Expand Down Expand Up @@ -59,7 +59,7 @@ export default [
name: 'Core (Bundled) - Legacy - NPM (CJS)',
path: 'dist/npm/legacy/bundled/cjs/index.cjs',
import: '*',
limit: '48 KiB',
limit: '48.2 KiB',
},
{
name: 'Core (Bundled) - Legacy - NPM (UMD)',
Expand Down

0 comments on commit 03e4dba

Please sign in to comment.