diff --git a/static/app/views/settings/project/projectKeys/details/keySettings.spec.tsx b/static/app/views/settings/project/projectKeys/details/keySettings.spec.tsx
index c890bb9a659799..3ba98b42c20a56 100644
--- a/static/app/views/settings/project/projectKeys/details/keySettings.spec.tsx
+++ b/static/app/views/settings/project/projectKeys/details/keySettings.spec.tsx
@@ -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'],
@@ -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(
+
+ );
+
+ // 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(
+
+ );
+
+ 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(
+
+ );
+
+ expect(
+ screen.queryByText(
+ 'When using Replay, the loader will load the ES6 bundle instead of the ES5 bundle.'
+ )
+ ).toBeInTheDocument();
+
+ data.dynamicSdkLoaderOptions.hasReplay = false;
+
+ rerender(
+
+ );
+
+ expect(
+ screen.queryByText(
+ 'When using Replay, the loader will load the ES6 bundle instead of the ES5 bundle.'
+ )
+ ).not.toBeInTheDocument();
+ });
});
});
diff --git a/static/app/views/settings/project/projectKeys/details/keySettings.tsx b/static/app/views/settings/project/projectKeys/details/keySettings.tsx
index 151dbf8c48d253..c614fad5d8c29a 100644
--- a/static/app/views/settings/project/projectKeys/details/keySettings.tsx
+++ b/static/app/views/settings/project/projectKeys/details/keySettings.tsx
@@ -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,
},
};
@@ -145,16 +148,40 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
async (newBrowserSDKVersion: typeof browserSdkVersion) => {
addLoadingMessage();
+ const apiData: {
+ browserSdkVersion: typeof browserSdkVersion;
+ dynamicSdkLoaderOptions?: Partial>;
+ } = {
+ 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');
@@ -162,7 +189,14 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
addErrorMessage(message);
}
},
- [api, apiEndpoint, setBrowserSdkVersion]
+ [
+ api,
+ apiEndpoint,
+ setBrowserSdkVersion,
+ setDynamicSDKLoaderOptions,
+ hasJSSDKDynamicLoaderFeatureFlag,
+ dynamicSDKLoaderOptions,
+ ]
);
return (
@@ -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')
@@ -337,3 +391,7 @@ export function KeySettings({onRemove, organization, params, data}: Props) {
);
}
+
+function sdkVersionSupportsPerformanceAndReplay(sdkVersion: string): boolean {
+ return sdkVersion === 'latest' || sdkVersion === '7.x';
+}