Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby): Support user integrations as a function #4050

Merged
merged 3 commits into from
Oct 11, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/gatsby/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from '@sentry/react';
export { Integrations } from '@sentry/tracing';

export { init } from './sdk';
47 changes: 41 additions & 6 deletions packages/gatsby/src/utils/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,54 @@ import { Integration } from '@sentry/types';

import { GatsbyOptions } from './types';

type UserFnIntegrations = (integrations: Integration[]) => Integration[];
export type UserIntegrations = Integration[] | UserFnIntegrations;

/**
* Returns the integrations to add to the SDK.
* If tracing is enabled, `BrowserTracing` is always present.
*
* @param options The options users have defined.
*/
export function getIntegrationsFromOptions(options: GatsbyOptions): Integration[] {
const integrations = [...(options.integrations || [])];
export function getIntegrationsFromOptions(options: GatsbyOptions): UserIntegrations {
const isTracingEnabled = Tracing.hasTracingEnabled(options);
if (options.integrations === undefined) {
return getIntegrationsFromArray([], isTracingEnabled);
} else if (Array.isArray(options.integrations)) {
return getIntegrationsFromArray(options.integrations, isTracingEnabled);
} else {
return getIntegrationsFromFunction(options.integrations, isTracingEnabled);
}
}

/**
* Returns the integrations to add to the SDK, from the given integrations array.
*
* @param userIntegrations Array of user's integrations.
* @param isTracingEnabled Whether the user has enabled tracing.
*/
function getIntegrationsFromArray(userIntegrations: Integration[], isTracingEnabled: boolean): Integration[] {
if (
Tracing.hasTracingEnabled(options) &&
!integrations.some(integration => integration.name === Tracing.Integrations.BrowserTracing.name)
isTracingEnabled &&
!userIntegrations.some(integration => integration.name === Tracing.Integrations.BrowserTracing.name)
) {
integrations.push(new Tracing.Integrations.BrowserTracing());
userIntegrations.push(new Tracing.Integrations.BrowserTracing());
}
return integrations;
return userIntegrations;
}

/**
* Returns the integrations to add to the SDK, from the given function.
*
* @param userIntegrations Function returning the user's integrations.
* @param isTracingEnabled Whether the user has enabled tracing.
*/
function getIntegrationsFromFunction(
userIntegrations: UserFnIntegrations,
isTracingEnabled: boolean,
): UserFnIntegrations {
const wrapper: UserFnIntegrations = (defaultIntegrations: Integration[]) => {
return getIntegrationsFromArray(userIntegrations(defaultIntegrations), isTracingEnabled);
};
return wrapper;
}
68 changes: 58 additions & 10 deletions packages/gatsby/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Integrations } from '@sentry/tracing';
import { Integration, Package } from '@sentry/types';

import { defaultOptions, init as gatsbyInit } from '../src/sdk';
import { UserIntegrations } from '../src/utils/integrations';
import { GatsbyOptions } from '../src/utils/types';

const reactInit = reactInitRaw as jest.Mock;
Expand Down Expand Up @@ -65,28 +66,75 @@ describe('Integrations from options', () => {
afterEach(() => reactInit.mockClear());

test.each([
['tracing disabled, no integrations', {}, []],
['tracing enabled, no integrations', { tracesSampleRate: 1 }, ['BrowserTracing']],
['tracing disabled, no integrations', [], {}, []],
['tracing enabled, no integrations', [], { tracesSampleRate: 1 }, ['BrowserTracing']],
[
'tracing disabled, with Integrations.BrowserTracing',
'tracing disabled, with Integrations.BrowserTracing as an array',
[],
{ integrations: [new Integrations.BrowserTracing()] },
['BrowserTracing'],
],
[
'tracing enabled, with Integrations.BrowserTracing',
'tracing disabled, with Integrations.BrowserTracing as a function',
[],
{
integrations: () => [new Integrations.BrowserTracing()],
},
['BrowserTracing'],
],
[
'tracing enabled, with Integrations.BrowserTracing as an array',
[],
{ tracesSampleRate: 1, integrations: [new Integrations.BrowserTracing()] },
['BrowserTracing'],
],
[
'tracing enabled, with another integration',
'tracing enabled, with Integrations.BrowserTracing as a function',
[],
{ tracesSampleRate: 1, integrations: () => [new Integrations.BrowserTracing()] },
['BrowserTracing'],
],
[
'tracing enabled, with another integration as an array',
[],
{ tracesSampleRate: 1, integrations: [new Integrations.Express()] },
['Express', 'BrowserTracing'],
],
['tracing disabled, with another integration', { integrations: [new Integrations.Express()] }, ['Express']],
])('%s', (_testName, options: GatsbyOptions, expectedIntNames: string[]) => {
[
'tracing enabled, with another integration as a function',
[],
{ tracesSampleRate: 1, integrations: () => [new Integrations.Express()] },
['Express', 'BrowserTracing'],
],
[
'tracing disabled, with another integration as an array',
[],
{ integrations: [new Integrations.Express()] },
['Express'],
],
[
'tracing disabled, with another integration as a function',
[],
{ integrations: () => [new Integrations.Express()] },
['Express'],
],
[
'merges integrations with user integrations as a function',
[new Integrations.Mongo()],
{
tracesSampleRate: 1,
integrations: (defaultIntegrations: Integration[]): Integration[] => [
...defaultIntegrations,
new Integrations.Express(),
],
},
['Mongo', 'Express', 'BrowserTracing'],
],
])('%s', (_testName, defaultIntegrations: Integration[], options: GatsbyOptions, expectedIntNames: string[]) => {
gatsbyInit(options);
const integrations: Integration[] = reactInit.mock.calls[0][0].integrations;
expect(integrations).toHaveLength(expectedIntNames.length);
integrations.map((integration, idx) => expect(integration.name).toStrictEqual(expectedIntNames[idx]));
const integrations: UserIntegrations = reactInit.mock.calls[0][0].integrations;
const arrIntegrations = Array.isArray(integrations) ? integrations : integrations(defaultIntegrations);
expect(arrIntegrations).toHaveLength(expectedIntNames.length);
arrIntegrations.map((integration, idx) => expect(integration.name).toStrictEqual(expectedIntNames[idx]));
});
});