-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
feat(guided-steps): Update logic to render steps based on url param #88779
feat(guided-steps): Update logic to render steps based on url param #88779
Conversation
priscilawebdev
commented
Apr 4, 2025
- closes [Onboarding/React] Track progress (next-buttons) in getting started flow #79346
Codecov ReportAll modified and coverable lines are covered by tests ✅ ✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## master #88779 +/- ##
==========================================
+ Coverage 87.71% 87.77% +0.05%
==========================================
Files 10064 10033 -31
Lines 569158 567320 -1838
Branches 22352 22186 -166
==========================================
- Hits 499264 497966 -1298
+ Misses 69498 68931 -567
- Partials 396 423 +27 |
}, | ||
}); | ||
}, | ||
[navigate, currentStep, location] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The location is memorized, the currentStep is a number
, and navigate uses useCallback
, therefore, no rerenders are happening. Tested everything locally too
expect( | ||
await screen.findByText( | ||
textWithMarkupMatcher( | ||
"Configuration should happen as early as possible in your application's lifecycle." | ||
) | ||
) | ||
).toBeInTheDocument(); | ||
|
||
await userEvent.click(screen.getByRole('button', {name: 'Next'})); | ||
|
||
expect(await screen.findByText(/Add Distributed Tracing/)).toBeInTheDocument(); | ||
|
||
await userEvent.click(screen.getByRole('button', {name: 'Next'})); | ||
|
||
expect( | ||
await screen.findByText(/Verify that performance monitoring is working correctly/) | ||
).toBeInTheDocument(); | ||
|
||
expect( | ||
await screen.findByText("Waiting for this project's first trace") | ||
).toBeInTheDocument(); | ||
|
||
expect( | ||
screen.getByRole('button', {name: 'Take me to an example'}) | ||
).toBeInTheDocument(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are testing these things in the guidedSteps.spec.tsx
but I am removing these checks here because we no longer render the content based on the component internal state. Now we are using URL query
…am' of github.com:getsentry/sentry into priscila/ref/guided-steps/render-steps-based-on-url-param
const navigate = useNavigate(); | ||
const location = useLocation(); | ||
|
||
const currentStep = decodeInteger(location.query.guidedStep); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@priscilawebdev this component was built to be unopinionated and flexible, so I disagree with coupling it to a specific query param.
I'd suggest adding an initialStepId
prop, which you can provide location.query.guidedStep
for in the onboarding
component. There should already be an onStepChange()
callback that you could use to update the query param when the steps change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@malwilley I completely understand and can definitely decouple this. However, considering that this component will be used throughout our product, it could lead to a frustrating user experience if the step state is lost every time the URL is refreshed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, it seems that in most places where we're using this feature, we'll need to include something like:
initialStep={decodeInteger(location.query.guidedStep)}
onStepChange={step => {
navigate({
pathname: location.pathname,
query: {
...location.query,
guidedStep: step,
},
});
}}
Are there any scenarios you can think of where this wouldn’t be the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I like about the initialStep
approach is that we could use other ways of saving the current step, like localStorage or an API response depending on the need. In the future if it looks like we are copying this code a bunch perhaps we can create a more opinionated <OnboardingSteps />
component or something like that that uses GuidedSteps internally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see... that makes sense! We'll probably have to create another component, since we're copying and pasting in at least 3x different places. We'll see :)
</GuidedSteps> | ||
it('update url query param when navigating through steps', async function () { | ||
render(<Component />, { | ||
router, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, also! There's a new option that I haven't documented yet (so no need to make the change, just letting you know), that makes testing location changes easier: #83400
Note that I recently changed the option from disableRouterMocks: true
to enableRouterMocks: false
since I'm in the process of making it the default behavior, but otherwise it should be the same as described in the PR
</GuidedSteps.Step> | ||
</GuidedSteps> | ||
); | ||
jest.mock('sentry/utils/useNavigate'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scttcper is actually in the process of banning hook mocks in tests, I'd suggest using enableRouterMocks: false
instead
closing this in favour of #88877 |