-
Notifications
You must be signed in to change notification settings - Fork 7
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
ENH Display toast notifications #39
ENH Display toast notifications #39
Conversation
d539204
to
62479be
Compare
b660a0e
to
92ee1fe
Compare
112bfe2
to
e7d869b
Compare
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.
Just going back to what I said on the original PR. The Login component is mixing concerns. It should be split in two:
- one part that handles the UI (That's what should be in the pattern library)
- one part that handles the communication with the backend, the displaying of toasts, etc
The pattern library is still broken for me. You need to update that to use disconnected Component as well.
1059772
to
a4ac5e9
Compare
3af340e
to
fa6edd3
Compare
@maxime-rainville I've split the components and responded to all the other feedback, good for peer review again |
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.
Some things that ought to be in the LoginSessionCantianer is still in the LoginSession component.
I haven't reviewed the fine print of the JS tests because the final shape of the JSX components is still fluid.
@@ -10,6 +10,14 @@ const props = { | |||
Created: '2021-01-20 00:33:41', | |||
LastAccessed: '2021-03-11 03:47:22', | |||
LogOutEndpoint: 'admin/loginsession/remove', | |||
logout: (beforeRequest, receivedResponse, caughtException) => { |
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.
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.
It's not a mock event handler. The logout() function needs to call beforeRequest() and receivedResponse() in order for the LoginSession state and thus text to update
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.
No longer required, can use logout: () => 1
just to satisfy the func.required propType
fa6edd3
to
5183610
Compare
592f4ec
to
a621235
Compare
a621235
to
a3ae336
Compare
a3ae336
to
b749681
Compare
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 took some extra time to refactor <LoginSessionContainer />
to be a functional and update its matching tests. What you did wasn't horrible or anything, but since you struggled with this part, I thought it would be a good learning experience to illustrate how to write test for a functional component following best practices.
I left lots of detailed comments on the commit to explain why I did it that way.
Have a read and let me know if you have any further questions.
Otherwise, the rest of the PR is great. I left some suggestion here and there but nothing that absolutely needs to be addressed.
if (!await confirm(confirmMessage, { title: confirmTitle, confirmLabel: buttonLabel })) { | ||
return; | ||
} | ||
|
||
logOut(); | ||
} | ||
|
||
if (loading.fadeOutComplete) { | ||
return null; | ||
props.logout(); |
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.
To my eye this looks better, but the current code is fine.
if (await confirm(confirmMessage, { title: confirmTitle, confirmLabel: buttonLabel })) {
props.logout();
}
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.
logout
is not define in your propTypes.
{!props.IsCurrent && <Button | ||
color="link" | ||
className="login-session__logout" | ||
onClick={() => attemptLogOut()} |
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.
That's a bit more succinct.
onClick={() => attemptLogOut()} | |
onClick={attemptLogOut} |
</li>) | ||
)} | ||
<ul className="session-manager-field list-unstyled"> | ||
{props.loginSessions.map((loginSession) => ( |
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.
{props.loginSessions.map((loginSession) => ( | |
{props.loginSessions.map(loginSession => ( |
@@ -1,22 +1,22 @@ | |||
/* global window */ | |||
import React from 'react'; | |||
import LoginSession from '../LoginSession/LoginSession'; | |||
import LoginSessionContainer from '../LoginSession/LoginSessionContainer'; |
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.
import LoginSessionContainer from '../LoginSession/LoginSessionContainer'; | |
import LoginSessionContainer from 'components/LoginSession/LoginSessionContainer'; |
@@ -111,39 +52,37 @@ function LoginSession(props) { | |||
); | |||
|
|||
return ( | |||
<div className={`login-session ${(loading.complete && !loading.failed) ? 'hidden' : ''}`}> | |||
<div className={`login-session ${(props.complete && !props.failed) ? 'hidden' : ''}`}> |
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.
It would be clearer if you use the classnames lib for this kind of string building.
httpResolve({ | ||
error: false, | ||
success: global.success, | ||
message: 'amazing success' | ||
}); | ||
await logoutRequest; |
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 fake our HTTP response.
expect(loginSession.props()).toMatchObject({ | ||
...sessionData, | ||
complete: true, | ||
failed: false, | ||
submitting: false | ||
}); |
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 test the end state of our component, once the session has been invalidated.
expect(props.displayToastSuccess).toBeCalledWith('amazing success'); | ||
expect(props.displayToastFailure).not.toBeCalled(); |
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.
These mock calls are a bit smarter. We're not only testing the that our mocks have been called, but that they've been called with the expected success message.
expect(props.displayToastSuccess).not.toBeCalled(); | ||
}); | ||
|
||
it('Handles HTTP Request failure', async () => { |
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.
Our initial test was only testing a regular failure. We were not testing a scenario where we had an actual HTTP failure.
submitting: true | ||
}); | ||
|
||
httpReject(); |
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.
Calling the Promise's reject
method will cause our catch
block to run.
1306663
to
b749681
Compare
@emteknetnz Reverted my commits and split them off into a separate PR creative-commoners#4 |
Issue #13