npm package diff
Package: @forge/events
Versions: 2.0.1-next.0 - 2.0.1-next.1
File: package/src/__test__/queue.test.ts
Index: package/src/__test__/queue.test.ts
===================================================================
--- package/src/__test__/queue.test.ts
+++ package/src/__test__/queue.test.ts
@@ -1,306 +0,0 @@
-import {
- InternalServerError,
- InvalidQueueNameError,
- InvalidPayloadError,
- NoEventsToPushError,
- PartialSuccessError,
- PayloadTooBigError,
- RateLimitError,
- TooManyEventsError,
- InvalidPushSettingsError,
- InvocationLimitReachedError
-} from '../errors';
-import { getMockFetchMethod, getApiClientMockWithoutResponseBody, verifyApiClientCalledPushPathWith } from './utils';
-import { Queue } from '../queue';
-import { JobProgress } from '../jobProgress';
-import { __requestAtlassianAsApp } from '@forge/api';
-
-jest.mock('@forge/api', () => ({
- __requestAtlassianAsApp: getMockFetchMethod('done', 201)
-}));
-
-const getQueue = (queueName: string, apiClientMock?: any) => new Queue({ key: queueName }, apiClientMock);
-
-describe('Queue methods', () => {
- describe('constructor', () => {
- it('should throw InvalidQueueNameError', async () => {
- const apiClientMock = getMockFetchMethod();
- expect(() => getQueue('invalid name', apiClientMock)).toThrowError(
- new InvalidQueueNameError('Queue names can only contain alphanumeric characters, dashes and underscores.')
- );
- });
- });
-
- const PAYLOAD = { body: { page: 1 } } as const;
-
- describe('push', () => {
- it.each([
- ['single payload', PAYLOAD, [PAYLOAD]],
- ['payload array', [PAYLOAD, PAYLOAD], [PAYLOAD, PAYLOAD]]
- ])('should call the queue/publish endpoint when given %s', async (_, payload, expectedPayload) => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- await queue.push(payload);
- verifyApiClientCalledPushPathWith(apiClientMock, expectedPayload, 'name');
- });
-
- it.each([
- ['number', 1],
- ['string', 'test'],
- ['boolean', true],
- ['array', [1, 2, 3]],
- ['null', null],
- ['undefined', undefined],
- ['array with non-object', [1]],
- ['array with an array', [[2, 3]]]
- ])('rejects non-object (%s) event', async (_, payload) => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- // @ts-expect-error Testing invalid payload type on purpose
- await expect(queue.push(payload)).rejects.toThrow(new InvalidPayloadError(`Event must be an object.`));
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it.each([
- ['number', 1],
- ['string', 'test'],
- ['boolean', true],
- ['array', [1, 2, 3]],
- ['null', null],
- ['undefined', undefined],
- ['array with non-object', [1]],
- ['array with an array', [[2, 3]]]
- ])('rejects non-object (%s) event body', async (_, body) => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- // @ts-expect-error Testing invalid payload type on purpose
- await expect(queue.push({ body })).rejects.toThrow(new InvalidPayloadError(`Event body must be an object.`));
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it('should throw InvalidPushSettingsError for delay', async () => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push({ ...PAYLOAD, delayInSeconds: 901 })).rejects.toThrow(
- new InvalidPushSettingsError(`The delayInSeconds setting must be between 0 and 900.`)
- );
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it('should throw NoEventsToPushError', async () => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push([])).rejects.toThrow(new NoEventsToPushError(`No events pushed.`));
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it('should throw TooManyEventsError', async () => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push(Array(51).fill(PAYLOAD))).rejects.toThrow(
- new TooManyEventsError(`This push contains more than the 50 events allowed.`)
- );
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it('should throw PayloadTooBigError', async () => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push({ body: { content: 'x'.repeat(201 * 1024) } })).rejects.toThrow(
- new PayloadTooBigError(`The maximum payload size is 200KB.`)
- );
- expect(apiClientMock).toHaveBeenCalledTimes(0);
- });
-
- it('should throw RateLimitError', async () => {
- const apiClientMock = getMockFetchMethod({}, 429);
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push(PAYLOAD)).rejects.toThrow(new RateLimitError(`Too many requests.`));
- verifyApiClientCalledPushPathWith(apiClientMock, [PAYLOAD], 'name');
- });
-
- it('should throw InvocationLimitReachedError', async () => {
- const apiClientMock = getMockFetchMethod({}, 405);
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push(PAYLOAD)).rejects.toThrow(
- new InvocationLimitReachedError(`The limit on cyclic invocation has been reached.`)
- );
- verifyApiClientCalledPushPathWith(apiClientMock, [PAYLOAD], 'name');
- });
-
- it('should throw PartialSuccessError when there are failed events', async () => {
- const apiClientMock = getMockFetchMethod(
- {
- failedEvents: [
- {
- index: '0',
- errorMessage: 'failed-1'
- },
- {
- index: 2,
- errorMessage: 'failed-3'
- }
- ]
- },
- 202
- );
- const queue = getQueue('name', apiClientMock);
- const payload = [
- {
- body: {
- content: 'payload-1'
- }
- },
- {
- body: {
- content: 'payload-2'
- }
- },
- {
- body: {
- content: 'payload-3'
- }
- }
- ];
- await expect(queue.push(payload)).rejects.toThrow(
- new PartialSuccessError(`Failed to process 2 event(s).`, { jobId: 'some-job-id' }, [
- {
- errorMessage: 'failed-1',
- event: {
- body: {
- content: 'payload-1'
- }
- }
- },
- {
- errorMessage: 'failed-3',
- event: {
- body: {
- content: 'payload-3'
- }
- }
- }
- ])
- );
- verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
- });
-
- it('should throw PartialSuccessError when backend failed to create job stats', async () => {
- const apiClientMock = getMockFetchMethod(
- {
- errorMessage: 'Failed to create stats for job name#12345'
- },
- 202
- );
- const queue = getQueue('name', apiClientMock);
- const payload = [
- {
- body: {
- content: 'payload-1'
- }
- },
- {
- body: {
- content: 'payload-2'
- }
- },
- {
- body: {
- content: 'payload-3'
- }
- }
- ];
- await expect(queue.push(payload)).rejects.toThrow(
- new PartialSuccessError(`Failed to create stats for job name#12345`, { jobId: 'some-job-id' }, [])
- );
- verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
- });
-
- it('should throw PartialSuccessError when there are failed events and backend failed to create job stats', async () => {
- const apiClientMock = getMockFetchMethod(
- {
- errorMessage: 'Failed to create stats for job name#12345',
- failedEvents: [
- {
- index: '0',
- errorMessage: 'failed-1'
- }
- ]
- },
- 202
- );
- const queue = getQueue('name', apiClientMock);
- const payload = [
- {
- body: {
- content: 'payload-1'
- }
- },
- {
- body: {
- content: 'payload-2'
- }
- }
- ];
- await expect(queue.push(payload)).rejects.toThrow(
- new PartialSuccessError(
- `Failed to process 1 event(s). Failed to create stats for job name#12345`,
- { jobId: 'some-job-id' },
- [
- {
- errorMessage: 'failed-1',
- event: {
- body: {
- content: 'payload-1'
- }
- }
- }
- ]
- )
- );
- verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
- });
-
- it('should throw InternalServerError', async () => {
- const apiClientMock = getMockFetchMethod(
- {
- message: 'AWS SQS timed out',
- code: 500,
- details: 'The request processing has failed because of an unknown error, exception or failure'
- },
- 500
- );
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push(PAYLOAD)).rejects.toThrow(
- new InternalServerError(
- `500 Status Text: AWS SQS timed out`,
- 500,
- 'The request processing has failed because of an unknown error, exception or failure'
- )
- );
- verifyApiClientCalledPushPathWith(apiClientMock, [PAYLOAD], 'name');
- });
-
- it('should throw InternalServerError for error response without response body', async () => {
- const apiClientMock = getApiClientMockWithoutResponseBody(504, 'Gateway Timeout');
- const queue = getQueue('name', apiClientMock);
- await expect(queue.push(PAYLOAD)).rejects.toThrow(new InternalServerError(`504 Gateway Timeout`, 504));
- verifyApiClientCalledPushPathWith(apiClientMock, [PAYLOAD], 'name');
- });
-
- it('requests stargate if no api client is provided', async () => {
- const queue = getQueue('queue');
- await queue.push({ body: { test: 'stargate' } });
- expect(__requestAtlassianAsApp).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('getJob', () => {
- it('should create a JobProgress by jobId', async () => {
- const apiClientMock = getMockFetchMethod();
- const queue = getQueue('name', apiClientMock);
- const jobProgress = queue.getJob('test-job-id');
- expect(jobProgress).toEqual(new JobProgress({ key: 'name' }, 'test-job-id', apiClientMock));
- });
- });
-});