-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: replace axios with fetch in js client sdk (#739)
- Loading branch information
1 parent
735c575
commit 7d59ff8
Showing
17 changed files
with
372 additions
and
230 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const { Request, Response } = jest.requireActual('cross-fetch') | ||
|
||
const fetch = jest.fn() | ||
|
||
export { Request, Response } | ||
export default fetch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const fetchWithRetry = (_fetch: unknown): unknown => _fetch | ||
export default fetchWithRetry |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,28 @@ | ||
import { DVCPopulatedUser } from '../src/User' | ||
|
||
jest.mock('axios') | ||
import axios, { AxiosInstance } from 'axios' | ||
import { mocked } from 'jest-mock' | ||
|
||
const axiosRequestMock = jest.fn() | ||
const createMock = mocked(axios.create) | ||
|
||
createMock.mockImplementation((): AxiosInstance => { | ||
return { | ||
request: axiosRequestMock, | ||
interceptors: { | ||
request: { use: jest.fn() }, | ||
response: { use: jest.fn() }, | ||
}, | ||
} as unknown as AxiosInstance | ||
}) | ||
jest.mock('cross-fetch') | ||
import fetch, { Response } from 'cross-fetch' | ||
|
||
global.fetch = fetch | ||
import { DVCPopulatedUser } from '../src/User' | ||
import * as Request from '../src/Request' | ||
import { BucketedUserConfig } from '@devcycle/types' | ||
import { dvcDefaultLogger } from '../src/logger' | ||
|
||
const defaultLogger = dvcDefaultLogger({ level: 'debug' }) | ||
const fetchRequestMock = fetch as jest.MockedFn<typeof fetch> | ||
|
||
describe('Request tests', () => { | ||
beforeEach(() => { | ||
axiosRequestMock.mockReset() | ||
}) | ||
|
||
describe('baseRequestParams', () => { | ||
const { baseRequestHeaders } = Request | ||
it('should add sdkKey header if passed in', () => { | ||
const params = baseRequestHeaders('my_sdk_key') | ||
expect(params['Content-Type']).toBe('application/json') | ||
expect(params['Authorization']).toBe('my_sdk_key') | ||
}) | ||
|
||
it('should not add header if no sdkKey passed in', () => { | ||
const params = baseRequestHeaders() | ||
expect(params['Content-Type']).toBe('application/json') | ||
expect(params['Authorization']).toBeUndefined() | ||
}) | ||
fetchRequestMock.mockClear() | ||
fetchRequestMock.mockResolvedValue( | ||
new Response(JSON.stringify({}), { | ||
status: 200, | ||
}), | ||
) | ||
}) | ||
|
||
describe('getConfigJson', () => { | ||
it('should call get with serialized user and SDK key in params', async () => { | ||
const user = { user_id: 'my_user', isAnonymous: false } | ||
const sdkKey = 'my_sdk_key' | ||
axiosRequestMock.mockResolvedValue({ status: 200, data: {} }) | ||
|
||
await Request.getConfigJson( | ||
sdkKey, | ||
user as DVCPopulatedUser, | ||
|
@@ -61,35 +35,35 @@ describe('Request tests', () => { | |
}, | ||
) | ||
|
||
expect(axiosRequestMock).toBeCalledWith({ | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'GET', | ||
url: | ||
'https://sdk-api.devcycle.com/v1/sdkConfig?sdkKey=' + | ||
expect(fetchRequestMock).toBeCalledWith( | ||
'https://sdk-api.devcycle.com/v1/sdkConfig?sdkKey=' + | ||
`${sdkKey}&user_id=${user.user_id}&isAnonymous=false&sse=1&sseLastModified=1234&sseEtag=etag`, | ||
}) | ||
expect.objectContaining({ | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'GET', | ||
}), | ||
) | ||
}) | ||
|
||
it('should call local proxy for apiProxyURL option', async () => { | ||
const user = { user_id: 'my_user', isAnonymous: false } | ||
const sdkKey = 'my_sdk_key' | ||
const dvcOptions = { apiProxyURL: 'http://localhost:4000' } | ||
axiosRequestMock.mockResolvedValue({ status: 200, data: {} }) | ||
|
||
await Request.getConfigJson( | ||
sdkKey, | ||
user as DVCPopulatedUser, | ||
defaultLogger, | ||
dvcOptions, | ||
) | ||
|
||
expect(axiosRequestMock).toBeCalledWith({ | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'GET', | ||
url: | ||
`${dvcOptions.apiProxyURL}/v1/sdkConfig?sdkKey=` + | ||
expect(fetchRequestMock).toBeCalledWith( | ||
`${dvcOptions.apiProxyURL}/v1/sdkConfig?sdkKey=` + | ||
`${sdkKey}&user_id=${user.user_id}&isAnonymous=false`, | ||
}) | ||
expect.objectContaining({ | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'GET', | ||
}), | ||
) | ||
}) | ||
}) | ||
|
||
|
@@ -99,10 +73,11 @@ describe('Request tests', () => { | |
const config = {} as BucketedUserConfig | ||
const sdkKey = 'my_sdk_key' | ||
const events = [{ type: 'event_1_type' }, { type: 'event_2_type' }] | ||
axiosRequestMock.mockResolvedValue({ | ||
status: 200, | ||
data: 'messages', | ||
}) | ||
fetchRequestMock.mockResolvedValue( | ||
new Response('{}', { | ||
status: 200, | ||
}), | ||
) | ||
|
||
await Request.publishEvents( | ||
sdkKey, | ||
|
@@ -112,30 +87,25 @@ describe('Request tests', () => { | |
defaultLogger, | ||
) | ||
|
||
expect(axiosRequestMock).toBeCalledWith({ | ||
headers: { | ||
Authorization: 'my_sdk_key', | ||
'Content-Type': 'application/json', | ||
}, | ||
method: 'POST', | ||
url: 'https://events.devcycle.com/v1/events', | ||
data: { | ||
events: [ | ||
expect.objectContaining({ | ||
customType: 'event_1_type', | ||
type: 'customEvent', | ||
user_id: 'my_user', | ||
clientDate: expect.any(Number), | ||
}), | ||
expect.objectContaining({ | ||
customType: 'event_2_type', | ||
type: 'customEvent', | ||
user_id: 'my_user', | ||
clientDate: expect.any(Number), | ||
}), | ||
], | ||
user, | ||
}, | ||
const call = fetchRequestMock.mock.calls[0] | ||
const requestBody = JSON.parse(call[1]?.body as string) | ||
|
||
expect(requestBody).toEqual({ | ||
events: [ | ||
expect.objectContaining({ | ||
customType: 'event_1_type', | ||
type: 'customEvent', | ||
user_id: 'my_user', | ||
clientDate: expect.any(Number), | ||
}), | ||
expect.objectContaining({ | ||
customType: 'event_2_type', | ||
type: 'customEvent', | ||
user_id: 'my_user', | ||
clientDate: expect.any(Number), | ||
}), | ||
], | ||
user, | ||
}) | ||
}) | ||
}) | ||
|
@@ -144,26 +114,33 @@ describe('Request tests', () => { | |
it('should send user data to edgedb api with url-encoded id', async () => { | ||
const user = { user_id: '[email protected]', isAnonymous: false } | ||
const sdkKey = 'my_sdk_key' | ||
axiosRequestMock.mockResolvedValue({ status: 200, data: {} }) | ||
fetchRequestMock.mockResolvedValue( | ||
new Response('{}', { | ||
status: 200, | ||
}), | ||
) | ||
|
||
await Request.saveEntity( | ||
user as DVCPopulatedUser, | ||
sdkKey, | ||
defaultLogger, | ||
) | ||
|
||
expect(axiosRequestMock).toBeCalledWith({ | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: 'my_sdk_key', | ||
}, | ||
data: { | ||
user_id: '[email protected]', | ||
isAnonymous: false, | ||
}, | ||
method: 'PATCH', | ||
url: 'https://sdk-api.devcycle.com/v1/edgedb/user%40example.com', | ||
const call = fetchRequestMock.mock.calls[0] | ||
const requestBody = JSON.parse(call[1]?.body as string) | ||
expect(requestBody).toEqual({ | ||
user_id: '[email protected]', | ||
isAnonymous: false, | ||
}) | ||
expect(fetchRequestMock).toBeCalledWith( | ||
'https://sdk-api.devcycle.com/v1/edgedb/user%40example.com', | ||
expect.objectContaining({ | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: 'my_sdk_key', | ||
}, | ||
method: 'PATCH', | ||
}), | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.