-
Notifications
You must be signed in to change notification settings - Fork 481
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
Break apart workshop.jsx #31990
Break apart workshop.jsx #31990
Conversation
.attr('first_name', 'George') | ||
.attr('last_name', 'Dragon') | ||
.attr('school', 'Academy') | ||
.attr('attended', 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.
@madelynkasula I ❤️ rosie
so far. Thank you for adding this!
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.
yayy -- thank you for recommending it!
@@ -9,37 +9,15 @@ import _ from 'lodash'; | |||
import PropTypes from 'prop-types'; |
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.
GitHub wants to hide this diff because it's too large, but please take a look - simplifying this component is why I think this change is worthwhile.
/** | ||
* View and manage the list of teachers enrolled in a workshop. | ||
*/ | ||
export default class EnrollmentsPanel extends React.Component { |
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.
Note: I'm especially excited about extracting EnrollmentsPanel
because this is where we'll give admins the ability to change enrollment details in the near future. There's definitely some further simplification that could happen in this component but I picked this as a stopping point since we'll be coming back to it soon anyway.
Note to reviewers: There's no timeline on this and it's a large review, so don't feel a need to look at this right away. |
const {view, workshop, isWorkshopAdmin, onWorkshopSaved} = this.props; | ||
|
||
if (view === 'edit') { | ||
const header = <EditHeader handleSave={this.handleSaveClick} />; |
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.
Not a blocker. These headers, EditHeader
, NotStartedHeader
, AdminHeader
, DetailsPanelHeader
, have multiple nested layers to display a simple text + a button. And what really changes is the button name and its callback function. In this case, I would prefer a flatter component structure (maybe more verbose code) but easier to reason.
/** | ||
* Provides controls for taking attendance in a workshop session. | ||
*/ | ||
export default class AttendancePanel extends React.Component { |
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 we change file name style, for example AttendancePanel.jsx (new) vs. workshop_enrollment.jsx (old). What is the convention to follow?
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'd like us to move to PascalCase
instead of snake_case
for JavaScript filenames, as this is the convention other cabals are using.
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've just reviewed half of the changes, so far so good :)
* Simple wrapper component for a chunk of related content when | ||
* viewing a workshop. | ||
*/ | ||
export default class WorkshopPanel extends React.Component { |
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.
This is a great UI abstraction!
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.
Phew, done, this PR is a good read. I learn a lot more about workshop page now.
server = null; | ||
}); | ||
|
||
it('when ready to close', () => { |
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 are the purpose of this test and the one below it? Do they test if a component can mount or if a component can be rendered?
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 a quick check that the component renders without errors when given a certain set of props. (By default, our tests fail when console.warn
or console.error
is called. One common way this happens for React components is PropType failures.) While these definitely are not robust in terms of checking a behavior for the component, I wanted to make sure all possible render paths were covered.
loadEnrollments={loadEnrollments} | ||
/> | ||
); | ||
assert( |
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.
Nit: To be symmetrical to the test above, you can assert that spinner is not rendered here.
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.
Great point! I'll do that.
@@ -385,3 +385,45 @@ export function enforceDocumentBodyCleanup( | |||
describe('', runTestCases); | |||
}); | |||
} | |||
|
|||
/** | |||
* Call in the `describe` block for a group of tests to stub the value of window.dashboard safely. |
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.
🥇 for the comments!
8919629
to
9d647cb
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.
🎉
Restores behavior introduced in #32453 and regressed during a complicated rebase in #31990. Most of the change was preserved, but the JSX that actually renders the new component was accidentally dropped. I mentioned in the previous PR that I wasn't adding a test for the UI because I was adding so many tests in the other PR (that regressed this!) and it would be covered. Turns out I was wrong! So now I'm adding a unit test for the Workshop component that verifies that we show the created_at date as expected.
Break the large and fairly entangled Workshop component in workshop.jsx out into many small components. I'm doing this cleanup work in preparation for a behavior change that we haven't scheduled yet but is certainly badly needed: Letting workshop admins change names on enrollments (Jira). We're up to at least five requests for engineers to do this manually, so it's time to make some progress on it.
This change should be a pure refactor.
One benefit of breaking the components apart this way is that they show up with useful names in the React devtools for Chrome:
Testing story
There was very little existing coverage of this code. I only found the eyes test workshop_dashboard.feature.
I've added enough unit tests to achieve at least 70% coverage for every extracted component, which should be a big improvement since this is all code that had zero coverage before. Here's unit test coverage for this directory before (Notice that workshop.jsx isn't even on the list):
And here's coverage after:
I've also been doing manual testing of key behaviors on the workshop view throughout the process.
Reviewer Checklist: