From 7be9efbcd2e8e61b60432bfff2d824a4bf80b07c Mon Sep 17 00:00:00 2001 From: Artem Yarylchenko Date: Wed, 13 Apr 2022 17:17:48 +0300 Subject: [PATCH 1/2] add interceptors usage --- lib/mock-axios-types.ts | 7 ++++++- lib/mock-axios.ts | 30 ++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/mock-axios-types.ts b/lib/mock-axios-types.ts index 6d4b572..984ce97 100644 --- a/lib/mock-axios-types.ts +++ b/lib/mock-axios-types.ts @@ -9,7 +9,7 @@ export interface HttpResponse { } interface Interceptor { - use: jest.Mock; + use: jest.Mock any | Promise, onRejected?: (error: any) => any]>; eject: jest.Mock; } @@ -18,6 +18,11 @@ interface Interceptors { response: Interceptor; } +export interface InterceptorsStack { + onFulfilled?(value: any): any | Promise; + onRejected?(error: any): any; +} + interface AxiosDefaults { headers: any; } diff --git a/lib/mock-axios.ts b/lib/mock-axios.ts index e4efb80..6800adc 100644 --- a/lib/mock-axios.ts +++ b/lib/mock-axios.ts @@ -7,8 +7,8 @@ */ import {jest} from '@jest/globals'; - - import { SynchronousPromise, UnresolvedSynchronousPromise } from "synchronous-promise"; + +import { SynchronousPromise, UnresolvedSynchronousPromise } from "synchronous-promise"; import Cancel from "./cancel/Cancel"; import CancelToken from "./cancel/CancelToken"; import { @@ -16,10 +16,12 @@ import { AxiosMockRequestCriteria, AxiosMockType, HttpResponse, + InterceptorsStack, } from "./mock-axios-types"; /** a FIFO queue of pending request */ const _pending_requests: AxiosMockQueueItem[] = []; +const _responseInterceptors: InterceptorsStack[] = []; const _newReq: (config?: any) => UnresolvedSynchronousPromise = (config: any = {}, actualConfig: any = {}) => { if(typeof config === 'string') { @@ -99,9 +101,13 @@ MockAxios.interceptors = { }, response: { // @ts-ignore - use: jest.fn(), + use: jest.fn((onFulfilled, onRejected) => { + return _responseInterceptors.push({onFulfilled, onRejected}); + }), // @ts-ignore - eject: jest.fn(), + eject: jest.fn((position: number) => { + _responseInterceptors.splice(position - 1, 1); + }), }, }; @@ -163,6 +169,14 @@ const popQueueItem = (queueItem: SynchronousPromise | AxiosMockQueueItem = } }; +const processInterceptors = (data: any, type: keyof InterceptorsStack) => { + return _responseInterceptors.map(({[type]: interceptor}) => interceptor) + .filter((interceptor) => !!interceptor) + .reduce((_result, next) => { + return next(_result); + }, data); +} + MockAxios.mockResponse = ( response?: HttpResponse, queueItem: SynchronousPromise | AxiosMockQueueItem = null, @@ -188,8 +202,10 @@ MockAxios.mockResponse = ( return; } + const result = processInterceptors(response, 'onFulfilled'); + // resolving the Promise with the given response data - promise.resolve(response); + promise.resolve(result); }; MockAxios.mockResponseFor = ( @@ -228,8 +244,10 @@ MockAxios.mockError = ( error.isAxiosError = true; } + const result = processInterceptors(error, 'onRejected'); + // resolving the Promise with the given error - promise.reject(error); + promise.reject(result); }; MockAxios.isAxiosError = (payload) => (typeof payload === 'object') && (payload.isAxiosError === true); From 4d44dd7404a8817116a4a8e9664dbf2946a07c2c Mon Sep 17 00:00:00 2001 From: Artem Yarylchenko Date: Wed, 13 Apr 2022 20:05:23 +0300 Subject: [PATCH 2/2] added request interceptor --- lib/mock-axios.ts | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/lib/mock-axios.ts b/lib/mock-axios.ts index 6800adc..86dd713 100644 --- a/lib/mock-axios.ts +++ b/lib/mock-axios.ts @@ -22,6 +22,15 @@ import { /** a FIFO queue of pending request */ const _pending_requests: AxiosMockQueueItem[] = []; const _responseInterceptors: InterceptorsStack[] = []; +const _requestInterceptors: InterceptorsStack[] = []; + +const processInterceptors = (data: any, stack: InterceptorsStack[], type: keyof InterceptorsStack) => { + return stack.map(({[type]: interceptor}) => interceptor) + .filter((interceptor) => !!interceptor) + .reduce((_result, next) => { + return next(_result); + }, data); +} const _newReq: (config?: any) => UnresolvedSynchronousPromise = (config: any = {}, actualConfig: any = {}) => { if(typeof config === 'string') { @@ -44,13 +53,15 @@ const _newReq: (config?: any) => UnresolvedSynchronousPromise = (config: an }) } - _pending_requests.push({ + const requestConfig = processInterceptors({ config, data, method, promise, url - }); + }, _requestInterceptors, 'onFulfilled'); + + _pending_requests.push(requestConfig); return promise; }; @@ -95,9 +106,13 @@ MockAxios.create = jest.fn(() => MockAxios); MockAxios.interceptors = { request: { // @ts-ignore - use: jest.fn(), + use: jest.fn((onFulfilled, onRejected) => { + return _requestInterceptors.push({ onFulfilled, onRejected }) + }), // @ts-ignore - eject: jest.fn(), + eject: jest.fn((position: number) => { + _requestInterceptors.splice(position - 1, 1); + }), }, response: { // @ts-ignore @@ -169,14 +184,6 @@ const popQueueItem = (queueItem: SynchronousPromise | AxiosMockQueueItem = } }; -const processInterceptors = (data: any, type: keyof InterceptorsStack) => { - return _responseInterceptors.map(({[type]: interceptor}) => interceptor) - .filter((interceptor) => !!interceptor) - .reduce((_result, next) => { - return next(_result); - }, data); -} - MockAxios.mockResponse = ( response?: HttpResponse, queueItem: SynchronousPromise | AxiosMockQueueItem = null, @@ -202,7 +209,7 @@ MockAxios.mockResponse = ( return; } - const result = processInterceptors(response, 'onFulfilled'); + const result = processInterceptors(response, _responseInterceptors, 'onFulfilled'); // resolving the Promise with the given response data promise.resolve(result); @@ -244,7 +251,7 @@ MockAxios.mockError = ( error.isAxiosError = true; } - const result = processInterceptors(error, 'onRejected'); + const result = processInterceptors(error, _responseInterceptors, 'onRejected'); // resolving the Promise with the given error promise.reject(result);