Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ const dynamicSdkLoaderOptions = {
[DynamicSDKLoaderOption.HAS_DEBUG]: false,
};

const fullDynamicSdkLoaderOptions = {
[DynamicSDKLoaderOption.HAS_PERFORMANCE]: true,
[DynamicSDKLoaderOption.HAS_REPLAY]: true,
[DynamicSDKLoaderOption.HAS_DEBUG]: true,
};

function renderMockRequests(
organizationSlug: Organization['slug'],
projectSlug: Project['slug'],
Expand Down Expand Up @@ -120,5 +126,170 @@ describe('Key Settings', function () {
);
});
});

it('resets performance & replay when selecting SDK version <7', async function () {
const params = {
projectId: '1',
keyId: '1',
};

const {organization} = initializeOrg({
...initializeOrg(),
organization: {
...initializeOrg().organization,
features: ORG_FEATURES,
},
router: {
params,
},
});

const data = {
...(TestStubs.ProjectKeys()[0] as ProjectKey),
dynamicSdkLoaderOptions: fullDynamicSdkLoaderOptions,
} as ProjectKey;

const mockRequests = renderMockRequests(
organization.slug,
params.projectId,
params.keyId
);

render(
<KeySettings
data={data}
onRemove={jest.fn()}
organization={organization}
params={params}
/>
);

// Update SDK version - should reset performance & replay
await selectEvent.select(screen.getByText('latest'), '6.x');

await waitFor(() => {
expect(mockRequests.projectKeys).toHaveBeenCalledWith(
`/projects/${organization.slug}/${params.projectId}/keys/${params.keyId}/`,
expect.objectContaining({
data: {
browserSdkVersion: '6.x',
dynamicSdkLoaderOptions: {
...fullDynamicSdkLoaderOptions,
[DynamicSDKLoaderOption.HAS_PERFORMANCE]: false,
[DynamicSDKLoaderOption.HAS_REPLAY]: false,
[DynamicSDKLoaderOption.HAS_DEBUG]: true,
},
},
})
);
});
});

it('disabled performance & replay when SDK version <7 is selected', function () {
const params = {
projectId: '1',
keyId: '1',
};

const {organization} = initializeOrg({
...initializeOrg(),
organization: {
...initializeOrg().organization,
features: ORG_FEATURES,
},
router: {
params,
},
});

const data = {
...(TestStubs.ProjectKeys()[0] as ProjectKey),
dynamicSdkLoaderOptions: {
[DynamicSDKLoaderOption.HAS_PERFORMANCE]: false,
[DynamicSDKLoaderOption.HAS_REPLAY]: false,
[DynamicSDKLoaderOption.HAS_DEBUG]: true,
},
browserSdkVersion: '6.x',
} as ProjectKey;

render(
<KeySettings
data={data}
onRemove={jest.fn()}
organization={organization}
params={params}
/>
);

for (const key of Object.keys(sdkLoaderOptions)) {
const toggle = screen.getByRole('checkbox', {name: sdkLoaderOptions[key].label});

if (key === DynamicSDKLoaderOption.HAS_DEBUG) {
expect(toggle).toBeEnabled();
expect(toggle).toBeChecked();
} else {
expect(toggle).toBeDisabled();
expect(toggle).not.toBeChecked();
}
}

const infos = screen.getAllByText('Only available in SDK version 7.x and above');
expect(infos.length).toBe(2);
});

it('shows replay message when it is enabled', function () {
const params = {
projectId: '1',
keyId: '1',
};

const {organization} = initializeOrg({
...initializeOrg(),
organization: {
...initializeOrg().organization,
features: ORG_FEATURES,
},
router: {
params,
},
});

const data = {
...(TestStubs.ProjectKeys()[0] as ProjectKey),
dynamicSdkLoaderOptions: fullDynamicSdkLoaderOptions,
} as ProjectKey;

const {rerender} = render(
<KeySettings
data={data}
onRemove={jest.fn()}
organization={organization}
params={params}
/>
);

expect(
screen.queryByText(
'When using Replay, the loader will load the ES6 bundle instead of the ES5 bundle.'
)
).toBeInTheDocument();

data.dynamicSdkLoaderOptions.hasReplay = false;

rerender(
<KeySettings
data={data}
onRemove={jest.fn()}
organization={organization}
params={params}
/>
);

expect(
screen.queryByText(
'When using Replay, the loader will load the ES6 bundle instead of the ES5 bundle.'
)
).not.toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ export enum DynamicSDKLoaderOption {
export const sdkLoaderOptions = {
[DynamicSDKLoaderOption.HAS_PERFORMANCE]: {
label: t('Enable Performance Monitoring'),
requiresV7: true,
},
[DynamicSDKLoaderOption.HAS_REPLAY]: {
label: t('Enable Session Replay'),
requiresV7: true,
},
[DynamicSDKLoaderOption.HAS_DEBUG]: {
label: t('Enable Debug Bundles'),
requiresV7: false,
},
};

Expand Down Expand Up @@ -145,24 +148,55 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
async (newBrowserSDKVersion: typeof browserSdkVersion) => {
addLoadingMessage();

const apiData: {
browserSdkVersion: typeof browserSdkVersion;
dynamicSdkLoaderOptions?: Partial<Record<DynamicSDKLoaderOption, boolean>>;
} = {
browserSdkVersion: newBrowserSDKVersion,
};

const shouldRestrictDynamicSdkLoaderOptions =
hasJSSDKDynamicLoaderFeatureFlag &&
!sdkVersionSupportsPerformanceAndReplay(newBrowserSDKVersion);

if (shouldRestrictDynamicSdkLoaderOptions) {
// Performance & Replay are not supported before 7.x
const newDynamicSdkLoaderOptions = {
...dynamicSDKLoaderOptions,
hasPerformance: false,
hasReplay: false,
};

apiData.dynamicSdkLoaderOptions = newDynamicSdkLoaderOptions;
}

try {
const response = await api.requestPromise(apiEndpoint, {
method: 'PUT',
data: {
browserSdkVersion: newBrowserSDKVersion,
},
data: apiData,
});

setBrowserSdkVersion(response.browserSdkVersion);

if (shouldRestrictDynamicSdkLoaderOptions) {
setDynamicSDKLoaderOptions(response.dynamicSdkLoaderOptions);
}

addSuccessMessage(t('Successfully updated SDK version'));
} catch (error) {
const message = t('Unable to updated SDK version');
handleXhrErrorResponse(message)(error);
addErrorMessage(message);
}
},
[api, apiEndpoint, setBrowserSdkVersion]
[
api,
apiEndpoint,
setBrowserSdkVersion,
setDynamicSDKLoaderOptions,
hasJSSDKDynamicLoaderFeatureFlag,
dynamicSDKLoaderOptions,
]
);

return (
Expand Down Expand Up @@ -267,14 +301,34 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
label={value.label}
key={key}
name={key}
value={dynamicSDKLoaderOptions[sdkLoaderOption]}
value={
value.requiresV7 &&
!sdkVersionSupportsPerformanceAndReplay(browserSdkVersion)
? false
: dynamicSDKLoaderOptions[sdkLoaderOption]
}
onChange={() =>
handleToggleDynamicSDKLoaderOption(
sdkLoaderOption as DynamicSDKLoaderOption,
!dynamicSDKLoaderOptions[sdkLoaderOption]
)
}
disabled={!hasAccess}
disabled={
!hasAccess ||
(value.requiresV7 &&
!sdkVersionSupportsPerformanceAndReplay(browserSdkVersion))
}
help={
value.requiresV7 &&
!sdkVersionSupportsPerformanceAndReplay(browserSdkVersion)
? t('Only available in SDK version 7.x and above')
: key === DynamicSDKLoaderOption.HAS_REPLAY &&
dynamicSDKLoaderOptions[sdkLoaderOption]
? t(
'When using Replay, the loader will load the ES6 bundle instead of the ES5 bundle.'
)
: undefined
}
disabledReason={
!hasAccess
? t('You do not have permission to edit this setting')
Expand Down Expand Up @@ -337,3 +391,7 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
</Access>
);
}

function sdkVersionSupportsPerformanceAndReplay(sdkVersion: string): boolean {
return sdkVersion === 'latest' || sdkVersion === '7.x';
}