diff --git a/static/app/components/onboarding/productSelection.spec.tsx b/static/app/components/onboarding/productSelection.spec.tsx index a4b379cda971ab..a1525d045c9ab5 100644 --- a/static/app/components/onboarding/productSelection.spec.tsx +++ b/static/app/components/onboarding/productSelection.spec.tsx @@ -224,6 +224,58 @@ describe('Onboarding Product Selection', function () { expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeDisabled(); }); + it('selects all products per default', async function () { + const {router} = initializeOrg({ + router: { + location: { + query: {}, + }, + params: {}, + }, + }); + + render(, { + router, + }); + + // router.replace is called to apply default product selection + await waitFor(() => + expect(router.replace).toHaveBeenCalledWith( + expect.objectContaining({ + query: expect.objectContaining({ + product: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], + }), + }) + ) + ); + }); + + it('applies defined default product selection', async function () { + const {router} = initializeOrg({ + router: { + location: { + query: {}, + }, + params: {}, + }, + }); + + render(, { + router, + }); + + // router.replace is called to apply default product selection + await waitFor(() => + expect(router.replace).toHaveBeenCalledWith( + expect.objectContaining({ + query: expect.objectContaining({ + product: [ProductSolution.PERFORMANCE_MONITORING], + }), + }) + ) + ); + }); + it('triggers onChange callback', async function () { const {router} = initializeOrg({ router: { diff --git a/static/app/components/onboarding/productSelection.tsx b/static/app/components/onboarding/productSelection.tsx index 211ca293d09f6f..07f55fff616b64 100644 --- a/static/app/components/onboarding/productSelection.tsx +++ b/static/app/components/onboarding/productSelection.tsx @@ -162,7 +162,7 @@ export const platformProductAvailability = { 'node-nestjs': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], php: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], 'php-laravel': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], - ['php-symfony']: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], + 'php-symfony': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], python: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], 'python-aiohttp': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], 'python-asgi': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], @@ -193,6 +193,16 @@ export const platformProductAvailability = { 'ruby-rails': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING], } as Record; +/** + * Defines which products are selected per default for each platform + * If not defined in here, all products are selected + */ +const platformDefaultProducts: Partial> = { + php: [ProductSolution.PERFORMANCE_MONITORING], + 'php-laravel': [ProductSolution.PERFORMANCE_MONITORING], + 'php-symfony': [ProductSolution.PERFORMANCE_MONITORING], +}; + type ProductProps = { /** * If the product is checked. This information is grabbed from the URL. @@ -296,17 +306,12 @@ export type ProductSelectionProps = { * The platform key of the project (e.g. javascript-react, python-django, etc.) */ platform?: PlatformKey; - /** - * A custom list of products per platform. If not provided, the default list is used. - */ - productsPerPlatform?: Record; }; export function ProductSelection({ disabledProducts: disabledProductsProp, organization, platform, - productsPerPlatform = platformProductAvailability, onChange, onLoad, }: ProductSelectionProps) { @@ -314,16 +319,27 @@ export function ProductSelection({ const urlProducts = useMemo(() => params.product ?? [], [params.product]); const products: ProductSolution[] | undefined = platform - ? productsPerPlatform[platform] + ? platformProductAvailability[platform] : undefined; const disabledProducts = useMemo( () => disabledProductsProp ?? getDisabledProducts(organization), [organization, disabledProductsProp] ); + const defaultProducts = useMemo(() => { - return products?.filter(product => !(product in disabledProducts)) ?? []; - }, [products, disabledProducts]); + const productsArray = products ?? []; + const definedDefaults = platform ? platformDefaultProducts[platform] : undefined; + let selectedDefaults: ProductSolution[] = productsArray; + + if (definedDefaults) { + selectedDefaults = definedDefaults.filter(product => + // Make sure the default product is available for the platform + productsArray.includes(product) + ); + } + return selectedDefaults.filter(product => !(product in disabledProducts)); + }, [products, platform, disabledProducts]); useEffect(() => { onLoad?.(defaultProducts); diff --git a/static/app/types/hooks.tsx b/static/app/types/hooks.tsx index 019ee936ff0e19..5ce77e6e9cdd1c 100644 --- a/static/app/types/hooks.tsx +++ b/static/app/types/hooks.tsx @@ -123,10 +123,7 @@ type OrganizationHeaderProps = { organization: Organization; }; -type ProductSelectionAvailabilityProps = Omit< - ProductSelectionProps, - 'disabledProducts' | 'productsPerPlatform' ->; +type ProductSelectionAvailabilityProps = Omit; type FirstPartyIntegrationAlertProps = { integrations: Integration[];