Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ fileignoreconfig:
checksum: 34d28e7736ffac2b27d3708b6bca28591f3a930292433001d2397bfdf2d2fd0f
- filename: .husky/pre-commit
checksum: 5baabd7d2c391648163f9371f0e5e9484f8fb90fa2284cfc378732ec3192c193
- filename: test/request.spec.ts
checksum: 87afd3bb570fd52437404cbe69a39311ad8a8c73bca9d075ecf88652fd3e13f6
version: ""
17 changes: 3 additions & 14 deletions src/lib/retryPolicy/delivery-sdk-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const retry = (error: any, config: any, retryCount: number, retryDelay: number,
* @param headers - Response headers from the API
* @returns Delay time in milliseconds
*/
const calculateRateLimitDelay = (headers: any): number => {
export const calculateRateLimitDelay = (headers: any): number => {
// Check for retry-after header (in seconds)
const retryAfter = headers['retry-after'];
if (retryAfter) {
Expand Down Expand Up @@ -156,17 +156,6 @@ const calculateRateLimitDelay = (headers: any): number => {
return Math.max(delay + 1000, 1000); // At least 1 second delay
}

// Default fallback delay (60 seconds) if no rate limit reset info is available
return 60000;
};

/**
* Retry request after specified delay
* @param error - The original error object
* @param delay - Delay time in milliseconds
* @param axiosInstance - Axios instance to retry with
* @returns Promise that resolves after the delay and retry
*/
const retryWithDelay = async (error: any, delay: number, axiosInstance: AxiosInstance) => {
return
// Default fallback delay (1 second) if no rate limit reset info is available
return 1000;
};
209 changes: 209 additions & 0 deletions test/request.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,213 @@ describe('Request tests', () => {
expect(mock.history.get[0].url).toBe(livePreviewURL);
expect(result).toEqual(mockResponse);
});

it('should throw error when response has no data property', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const responseWithoutData = { status: 200, headers: {} }; // Response without data property

// Mock response that returns undefined/empty data
mock.onGet(url).reply(() => [200, undefined, {}]);

await expect(getData(client, url)).rejects.toThrowError();
});

it('should throw error when response is null', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';

// Mock response that returns null
mock.onGet(url).reply(() => [200, null]);

await expect(getData(client, url)).rejects.toThrowError();
});

it('should handle live_preview when enable is false', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

client.stackConfig = {
live_preview: {
enable: false, // Disabled
preview_token: 'someToken',
live_preview: 'someHash',
host: 'rest-preview.com',
},
};

mock.onGet(url).reply(200, mockResponse);

const result = await getData(client, url, {});

// Should not modify URL when live preview is disabled
expect(mock.history.get[0].url).toBe(url);
expect(result).toEqual(mockResponse);
});

it('should handle request when stackConfig is undefined', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

// No stackConfig set
client.stackConfig = undefined;

mock.onGet(url).reply(200, mockResponse);

const result = await getData(client, url, {});
expect(result).toEqual(mockResponse);
});

it('should handle request when stackConfig exists but live_preview is undefined', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

client.stackConfig = {
// live_preview not defined
apiKey: 'test-key',
};

mock.onGet(url).reply(200, mockResponse);

const result = await getData(client, url, {});
expect(result).toEqual(mockResponse);
});

it('should set live_preview to "init" when enable is true and no live_preview provided', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

client.stackConfig = {
live_preview: {
enable: true,
preview_token: 'someToken',
// live_preview not provided
},
};

mock.onGet(url).reply(200, mockResponse);

const data: any = {};
const result = await getData(client, url, data);

// Should set live_preview to 'init'
expect(data.live_preview).toBe('init');
expect(result).toEqual(mockResponse);
});

it('should set headers when preview_token is provided', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

client.stackConfig = {
live_preview: {
enable: true,
preview_token: 'test-preview-token',
live_preview: 'init',
},
};

mock.onGet(url).reply(200, mockResponse);

const result = await getData(client, url, {});

// Should set headers
expect(client.defaults.headers.preview_token).toBe('test-preview-token');
expect(client.defaults.headers.live_preview).toBe('init');
expect(result).toEqual(mockResponse);
});

it('should handle live_preview when enable is true but no preview_token', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };

client.stackConfig = {
live_preview: {
enable: true,
live_preview: 'init',
// preview_token not provided
},
};

mock.onGet(url).reply(200, mockResponse);

const data: any = {};
const result = await getData(client, url, data);

// Should still set live_preview in data
expect(data.live_preview).toBe('init');
expect(result).toEqual(mockResponse);
});

it('should handle custom error messages when request fails', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const customError = new Error('Custom network error');

mock.onGet(url).reply(() => {
throw customError;
});

await expect(getData(client, url)).rejects.toThrowError('Custom network error');
});

it('should handle non-Error objects as errors when they have message property', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const errorObject = { status: 500, message: 'Internal Server Error' };

mock.onGet(url).reply(() => {
throw errorObject;
});

// When error has message property, it uses the message
await expect(getData(client, url)).rejects.toThrowError('Internal Server Error');
});

it('should handle non-Error objects as errors when they have no message property', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const errorObject = { status: 500, code: 'SERVER_ERROR' };

mock.onGet(url).reply(() => {
throw errorObject;
});

// When error has no message property, it stringifies the object
await expect(getData(client, url)).rejects.toThrowError(JSON.stringify(errorObject));
});

it('should pass data parameter to axios get request', async () => {
const client = httpClient({});
const mock = new MockAdapter(client as any);
const url = '/your-api-endpoint';
const mockResponse = { data: 'mocked' };
const requestData = { params: { limit: 10, skip: 0 } };

mock.onGet(url).reply((config) => {
// Verify that data was passed correctly
expect(config.params).toEqual(requestData.params);
return [200, mockResponse];
});

const result = await getData(client, url, requestData);
expect(result).toEqual(mockResponse);
});
});
Loading
Loading