-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref(node): Small
RequestData
integration tweaks (#5979)
This makes a few small revisions to the new `RequestData` integration: - Switch to using booleans rather than an array of keys when specifying what user data to include. This makes it match all of the other options, and is something I should have just done from the get-go. Given that the integration is new and thus far entirely undocumented, IMHO it feels safe to make what is technically a breaking change here. - Rename the integration's internal `RequestDataOptions` type to `RequestDataIntegrationOptions`, to help distinguish it from the many other flavors of request data functions and types floating around. - Make all properties in `RequestDataIntegrationOptions` optional, rather than using the `Partial` helper type. - Switch the callback which actually does the data adding from being an option to being a protected property, in order to make it less public but still leave open the option of subclassing and setting it to a different value if we ever get around to using this in browser-based SDKs. Because I also made the property's type slightly more generic and used an index signature to do it, I also had to switch `AddRequestDataToEventOptions` from being an interface to being a type. See microsoft/TypeScript#15300. - Rename the helper function which formats the `include` option for use in `addRequestDataToEvent` to more specifically indicate that it's converting from integration-style options to `addRequestDataToEvent`-style options. - Refactor the aforementioned helper function to act upon and return an entire options object rather than just the `include` property, in order to have access to the `transactionNamingScheme` option. - Add missing `transaction` property in helper function's output. - Add tests for the helper function.
- Loading branch information
1 parent
95f6030
commit c1d9c66
Showing
3 changed files
with
173 additions
and
35 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { getCurrentHub, Hub, makeMain } from '@sentry/core'; | ||
import { Event, EventProcessor } from '@sentry/types'; | ||
import * as http from 'http'; | ||
|
||
import { NodeClient } from '../../src/client'; | ||
import { RequestData, RequestDataIntegrationOptions } from '../../src/integrations/requestdata'; | ||
import * as requestDataModule from '../../src/requestdata'; | ||
import { getDefaultNodeClientOptions } from '../helper/node-client-options'; | ||
|
||
const addRequestDataToEventSpy = jest.spyOn(requestDataModule, 'addRequestDataToEvent'); | ||
const requestDataEventProcessor = jest.fn(); | ||
|
||
const headers = { ears: 'furry', nose: 'wet', tongue: 'spotted', cookie: 'favorite=zukes' }; | ||
const method = 'wagging'; | ||
const protocol = 'mutualsniffing'; | ||
const hostname = 'the.dog.park'; | ||
const path = '/by/the/trees/'; | ||
const queryString = 'chase=me&please=thankyou'; | ||
|
||
function initWithRequestDataIntegrationOptions(integrationOptions: RequestDataIntegrationOptions): void { | ||
const setMockEventProcessor = (eventProcessor: EventProcessor) => | ||
requestDataEventProcessor.mockImplementationOnce(eventProcessor); | ||
|
||
const requestDataIntegration = new RequestData({ | ||
...integrationOptions, | ||
}); | ||
|
||
const client = new NodeClient( | ||
getDefaultNodeClientOptions({ | ||
dsn: 'https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012', | ||
integrations: [requestDataIntegration], | ||
}), | ||
); | ||
client.setupIntegrations = () => requestDataIntegration.setupOnce(setMockEventProcessor, getCurrentHub); | ||
client.getIntegration = () => requestDataIntegration as any; | ||
|
||
const hub = new Hub(client); | ||
|
||
makeMain(hub); | ||
} | ||
|
||
describe('`RequestData` integration', () => { | ||
let req: http.IncomingMessage, event: Event; | ||
|
||
beforeEach(() => { | ||
req = { | ||
headers, | ||
method, | ||
protocol, | ||
hostname, | ||
originalUrl: `${path}?${queryString}`, | ||
} as unknown as http.IncomingMessage; | ||
event = { sdkProcessingMetadata: { request: req } }; | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe('option conversion', () => { | ||
it('leaves `ip` and `user` at top level of `include`', () => { | ||
initWithRequestDataIntegrationOptions({ include: { ip: false, user: true } }); | ||
|
||
requestDataEventProcessor(event); | ||
|
||
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2]; | ||
|
||
expect(passedOptions?.include).toEqual(expect.objectContaining({ ip: false, user: true })); | ||
}); | ||
|
||
it('moves `transactionNamingScheme` to `transaction` include', () => { | ||
initWithRequestDataIntegrationOptions({ transactionNamingScheme: 'path' }); | ||
|
||
requestDataEventProcessor(event); | ||
|
||
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2]; | ||
|
||
expect(passedOptions?.include).toEqual(expect.objectContaining({ transaction: 'path' })); | ||
}); | ||
|
||
it('moves `true` request keys into `request` include, but omits `false` ones', async () => { | ||
initWithRequestDataIntegrationOptions({ include: { data: true, cookies: false } }); | ||
|
||
requestDataEventProcessor(event); | ||
|
||
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2]; | ||
|
||
expect(passedOptions?.include?.request).toEqual(expect.arrayContaining(['data'])); | ||
expect(passedOptions?.include?.request).not.toEqual(expect.arrayContaining(['cookies'])); | ||
}); | ||
|
||
it('moves `true` user keys into `user` include, but omits `false` ones', async () => { | ||
initWithRequestDataIntegrationOptions({ include: { user: { id: true, email: false } } }); | ||
|
||
requestDataEventProcessor(event); | ||
|
||
const passedOptions = addRequestDataToEventSpy.mock.calls[0][2]; | ||
|
||
expect(passedOptions?.include?.user).toEqual(expect.arrayContaining(['id'])); | ||
expect(passedOptions?.include?.user).not.toEqual(expect.arrayContaining(['email'])); | ||
}); | ||
}); | ||
}); |