Skip to content

ref(product-selection): Update code to not strip url #86582

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

Merged
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
114 changes: 34 additions & 80 deletions static/app/components/onboarding/productSelection.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('Onboarding Product Selection', function () {

// Try to uncheck error monitoring
await userEvent.click(screen.getByRole('checkbox', {name: 'Error Monitoring'}));
await waitFor(() => expect(router.push).not.toHaveBeenCalled());
expect(router.push).not.toHaveBeenCalled();

// Tracing shall be checked and enabled by default
expect(screen.getByRole('checkbox', {name: 'Tracing'})).toBeChecked();
Expand All @@ -63,25 +63,21 @@ describe('Onboarding Product Selection', function () {

// Uncheck tracing
await userEvent.click(screen.getByRole('checkbox', {name: 'Tracing'}));
await waitFor(() =>
expect(router.replace).toHaveBeenCalledWith({
pathname: undefined,
query: {product: [ProductSolution.SESSION_REPLAY]},
})
);
expect(router.replace).toHaveBeenCalledWith({
pathname: undefined,
query: {product: [ProductSolution.SESSION_REPLAY]},
});

// Session replay shall be checked and enabled by default
expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeChecked();
expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeEnabled();

// Uncheck sesseion replay
await userEvent.click(screen.getByRole('checkbox', {name: 'Session Replay'}));
await waitFor(() =>
expect(router.replace).toHaveBeenCalledWith({
pathname: undefined,
query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
})
);
expect(router.replace).toHaveBeenCalledWith({
pathname: undefined,
query: {product: [ProductSolution.PERFORMANCE_MONITORING]},
});

// Tooltip with explanation shall be displayed on hover
await userEvent.hover(screen.getByRole('checkbox', {name: 'Session Replay'}));
Expand Down Expand Up @@ -134,9 +130,7 @@ describe('Onboarding Product Selection', function () {
await waitFor(() => expect(router.push).not.toHaveBeenCalled());
});

// TODO: This test does not play well with deselected products by default
// eslint-disable-next-line jest/no-disabled-tests
it.skip('does not render Session Replay', async function () {
it('does not render Session Replay if not available for the platform', function () {
platformProductAvailability['javascript-react'] = [
ProductSolution.PERFORMANCE_MONITORING,
];
Expand All @@ -158,21 +152,10 @@ describe('Onboarding Product Selection', function () {
screen.queryByRole('checkbox', {name: 'Session Replay'})
).not.toBeInTheDocument();

// router.replace is called to remove session-replay from query
await waitFor(() =>
expect(router.replace).toHaveBeenCalledWith(
expect.objectContaining({
query: expect.objectContaining({
product: [ProductSolution.PERFORMANCE_MONITORING],
}),
})
)
);
expect(router.replace).not.toHaveBeenCalled();
});

// TODO: This test does not play well with deselected products by default
// eslint-disable-next-line jest/no-disabled-tests
it.skip('render Profiling', async function () {
it('does render Profiling if available for the platform', function () {
const {router} = initializeOrg({
router: {
location: {
Expand All @@ -188,16 +171,7 @@ describe('Onboarding Product Selection', function () {

expect(screen.getByRole('checkbox', {name: 'Profiling'})).toBeInTheDocument();

// router.replace is called to add profiling from query
await waitFor(() =>
expect(router.replace).toHaveBeenCalledWith(
expect.objectContaining({
query: expect.objectContaining({
product: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
}),
})
)
);
expect(router.replace).not.toHaveBeenCalled();
});

it('renders with non-errors features disabled for errors only self-hosted', function () {
Expand Down Expand Up @@ -228,9 +202,7 @@ describe('Onboarding Product Selection', function () {
expect(screen.getByRole('checkbox', {name: 'Session Replay'})).toBeDisabled();
});

// TODO: This test does not play well with deselected products by default
// eslint-disable-next-line jest/no-disabled-tests
it.skip('selects all products per default', async function () {
it('does not select any products by default', function () {
const {router} = initializeOrg({
router: {
location: {
Expand All @@ -244,44 +216,7 @@ describe('Onboarding Product Selection', function () {
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],
}),
})
)
);
});

// TODO: This test does not play well with deselected products by default
// eslint-disable-next-line jest/no-disabled-tests
it.skip('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],
}),
})
)
);
expect(router.replace).not.toHaveBeenCalled();
});

it('triggers onChange callback', async function () {
Expand Down Expand Up @@ -310,4 +245,23 @@ describe('Onboarding Product Selection', function () {
await userEvent.click(screen.getByRole('checkbox', {name: 'Profiling'}));
expect(handleChange).toHaveBeenCalledWith(['performance-monitoring', 'profiling']);
});

it('does not overwrite URL products if others are present', function () {
const {router} = initializeOrg({
router: {
location: {
query: {product: ['invalid-product', ProductSolution.PERFORMANCE_MONITORING]},
},
params: {},
},
});

render(<ProductSelection organization={organization} platform="javascript-react" />, {
router,
});

expect(screen.getByRole('checkbox', {name: 'Tracing'})).toBeChecked();

expect(router.replace).not.toHaveBeenCalled();
});
});
17 changes: 10 additions & 7 deletions static/app/components/onboarding/productSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {ReactNode} from 'react';
import {useCallback, useEffect, useMemo} from 'react';
import {useCallback, useEffect, useMemo, useRef} from 'react';
import {css} from '@emotion/react';
import styled from '@emotion/styled';

Expand Down Expand Up @@ -345,13 +345,16 @@ export function ProductSelection({
return selectedDefaults.filter(product => !(product in disabledProducts));
}, [products, platform, disabledProducts]);

const safeDependencies = useRef({onLoad, urlProducts});

useEffect(() => {
safeDependencies.current = {onLoad, urlProducts};
});

useEffect(() => {
onLoad?.(defaultProducts);
setParams({
product: defaultProducts,
});
// Adding defaultProducts to the dependency array causes an max-depth error
// eslint-disable-next-line react-hooks/exhaustive-deps
safeDependencies.current.onLoad?.(
safeDependencies.current.urlProducts as ProductSolution[]
);
}, []);

const handleClickProduct = useCallback(
Expand Down
Loading