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
52 changes: 52 additions & 0 deletions static/app/components/onboarding/productSelection.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(<ProductSelection organization={organization} platform="python" />, {
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(<ProductSelection organization={organization} platform="php" />, {
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: {
Expand Down
34 changes: 25 additions & 9 deletions static/app/components/onboarding/productSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -193,6 +193,16 @@ export const platformProductAvailability = {
'ruby-rails': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
} as Record<PlatformKey, ProductSolution[]>;

/**
* Defines which products are selected per default for each platform
* If not defined in here, all products are selected
*/
const platformDefaultProducts: Partial<Record<PlatformKey, ProductSolution[]>> = {
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.
Expand Down Expand Up @@ -296,34 +306,40 @@ 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<PlatformKey, ProductSolution[]>;
};

export function ProductSelection({
disabledProducts: disabledProductsProp,
organization,
platform,
productsPerPlatform = platformProductAvailability,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found out that this prop is not used anymore and removed it.
Will also clean it up in getsentry once this is merged.

onChange,
onLoad,
}: ProductSelectionProps) {
const [params, setParams] = useOnboardingQueryParams();
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);
Expand Down
5 changes: 1 addition & 4 deletions static/app/types/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,7 @@ type OrganizationHeaderProps = {
organization: Organization;
};

type ProductSelectionAvailabilityProps = Omit<
ProductSelectionProps,
'disabledProducts' | 'productsPerPlatform'
>;
type ProductSelectionAvailabilityProps = Omit<ProductSelectionProps, 'disabledProducts'>;

type FirstPartyIntegrationAlertProps = {
integrations: Integration[];
Expand Down
Loading