-
Notifications
You must be signed in to change notification settings - Fork 0
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
ERA-7998: List activity for an incident #813
Conversation
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.
Overall, looks amazing and will be very very useful!
I left a few questions/comments/bits of feedback to address.
@@ -0,0 +1,167 @@ | |||
import React, { memo, useCallback, useEffect, useMemo } from 'react'; |
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's already a ReportListItem
component, do we feel like this is going to be confusing?
And/or is this different enough, functionality-wise, to justify its own component as opposed to just reconciling it into the main ReportListItem
instead? Then we could explore fun things like injecting the report preview accordion in other places as well...
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.
Hmmm I would say this is different enough, specially because of the accordion, but Idk, if you think that may be reused I can merge those two components. I fear we will end up with a pretty big ugly file and don't even take advantage of having merged them.
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 personally recommend having the accordion panel content as a separate component, affiliated with the ReportListItem, and reconcile the two together.
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.
Sounds nice, I'm creating a new global ReportFormSummary
that receives report
and schema
as props, so we can reuse this new way of reading the form values 👍 So now this file is only the "reconciliator" that puts the existing ReportListItem within an accordion header and the new ReportFormSummary in its panel content
|
||
.nonSchemaField { | ||
width: 50%; | ||
display: flex; |
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: alphabetical order is neat for CSS properties
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.
Fixing this PR and doing that from now on. I'm really into alphabetical ordering stuff haha
@@ -13,38 +18,55 @@ jest.mock('../../utils/file', () => ({ | |||
fetchImageAsBase64FromUrl: jest.fn(), | |||
})); | |||
|
|||
const server = setupServer( | |||
rest.get( |
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.
How are you feeling about our use of msw
?
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.
100 times better than mocking redux actions. However, Redux is still a pain because in our tests we don't mock our entire redux store, so even though msw mocks the response, we don't have the full store funcitonality of storing the backend data in redux and providing it to the component. This is a limitation to do a full test of certain flows. Anyway, is not a big issue, we can still divide that in two tests: one with the mocked store without data and one with the data preloaded in the test.
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.
Yeah, I'm thinking we'll want to make a slow transition away from mockStore
and to just use our real store instead. We honestly don't even use mockStore
much for its purpose as intended (checking which actions were dispatched etc), just as a bad placeholder for a store.
Once we're using a real store, the full and actual in situ behavior of a live component can be tested in our test suites, which is awesome.
|
||
expect(reportCollapse).toHaveClass('collapse'); | ||
|
||
const expandButton = (await screen.findAllByText('arrow-down-simple.svg'))[2]; |
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.
A couple things:
- This should just be a single arrow, rotated with CSS.
- You'll need to find a different selector for that element once you've done Develop #1. This is a pretty meh selector anyway
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 think you referenced the wrong PR there. Hmm how would you select the icon? I could add a data-testid. That would make it unique, so I won't have an array, but still feels meh to me 😂
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.
lol that was just me typing # 1 and GitHub trying to be smart about it
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 think something more closely following the ARIA guidelines for accordions would yield a number of healthy test selectors.
https://www.w3.org/WAI/ARIA/apg/example-index/accordion/accordion.html
@@ -133,7 +181,7 @@ describe('ReportManager - ActivitySection', () => { | |||
|
|||
expect(noteCollapse).toHaveClass('collapse'); | |||
|
|||
const expandButton = (await screen.findAllByText('arrow-down-simple.svg'))[3]; | |||
const expandButton = (await screen.findAllByText('arrow-down-simple.svg'))[4]; |
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 indexed selectors (findAllByWhatever('hi')[3]
, findAllByWhatever('hi')[4]
etc) have an extremely weak contract as being accurate representations of their elements. We need a better selection pattern.
@@ -127,6 +127,22 @@ | |||
height: 1.375rem; | |||
width: 1.375rem; | |||
} | |||
|
|||
&.priority-300 { |
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.
Any way to steal this from the other places it's defined in the project?
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.
Hmm I could take a look on how to reuse that CSS. Not an expert with SCSS honestly but I see we already have some mixins for buttons and stuff.
schema={reportSchemas?.schema} | ||
showErrorList={false} | ||
templates={{ | ||
ArrayFieldItemTemplate, |
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.
So much of this form definition is recycled from elsewhere. Any way to componentize it for regular reuse?
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.
Do you think it's worth it? We can define a CustomForm that is simply the Form implementing the custom components and spreading the ...rest
props. It won't do a lot, it's another file to mantain, but we will hide this repetitiveness you mention.
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, or capturing the form defaults in a constant which are spread into this form where it's invoked. Or a combination of the two: define the defaults, give them to a component, use that component as the default form component with overrides available.
</div> | ||
</div> | ||
|
||
{reportSchemas?.schema && <Form |
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 tricky. Hiding it through CSS, if possible, would require a lot of rules. Doing it through the custom components, we would need some new flag that tells the custom component if it is a non editable form print like this, so we can decide not to render the field vs the normal form where eve if it is empty we want the field to show up so the user can edit its value.
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.
Hiding it through CSS, if possible, would require a lot of rules
Funny, that seems like the lazy/cheap way to me. Add an "empty" class to field templates with no values, then select and style those specifically in the context of this panel
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 tried this but it's not that simple 😢 I can add the class and try to hide it, display none, etc... But since react-jsonschema-form
injects several divs with different grid classes and other stuff, it's really hard to rearrange the form ignoring the empty fields. There's actually an on-going conversation on their repo about this. It is possible to ui:widget: hidden
but custom components don't override their uiSchema
: rjsf-team/react-jsonschema-form#1236
…omponents, for re-use throughout the new report UI .🤷
…e to refactor them appropriately. minor tweaks to de-anonymize the return values of the useListSortWithButton hook, thus preventing excess renders.
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.
LGTM 🎉
@luixlive just want to call out this ticket comment as something we need to get solid before proceeding |
@luixlive It is sending only the longitude in the location object. I guess this is more of a question as I don't see the issue in develop (2-64-1 right now), nor Stage (2-63-1 right now). In case you can have a look. If it can't be solved in this ticket please let me know so that I can reopen the bug 🙌 |
@Alcoto95 Don't worry about this for now, the hotfix for the |
Ready for new review. But: |
Alright! Thanks! |
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 more feedback about test quality+structure
userEvent.click(expandButton); | ||
|
||
await waitFor(() => { | ||
expect(reportCollapse).toHaveClass('show'); |
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.
Testing this css class has no intrinsic link to testing visibility, you just have to take it on faith that a "show" class means something is visible.
We need to assert something something like expect(whatever).toBeVisible()
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 don't know how toBeVisible
does the validation, but it's not working for this test. Following your suggestions, I should change:
expect(reportCollapse).toHaveClass('collapse');
for expect(reportCollapse).not.toBeVisible();
and
expect(reportCollapse).toHaveClass('show');
for expect(reportCollapse).toBeVisible();
But that doesn't work, even tho I know the test is doing the right thing and the feature works properly 🤔
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 reference (even though we already Slacked about it 🙂 )
Need to add the bootstrap styles to your jsdom
rendering by either importing the stylesheet in your test file or adding a jest css plugin
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.
Thank you for your answer. Actually, there is an open issue in CRA about this exact scenario (test React Bootstrap Accordion with toBeVisible)
: facebook/create-react-app#10483 😞
const reportCollapse = await screen.findByTestId('reportManager-activitySection-collapse-d45cb504-4612-41fe-9ea5-f1b423ac3ba4'); | ||
|
||
await waitFor(() => { | ||
expect(reportCollapse).toHaveClass('collapse'); |
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.
ditto as above
@@ -181,15 +229,17 @@ describe('ReportManager - ActivitySection', () => { | |||
const itemsText = (await screen.findAllByRole('listitem')).map((item) => item.textContent.split(' ')[0]); | |||
|
|||
expect(itemsText).toEqual([ | |||
'note.svgNew', |
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 matchers are not great. Each list item has the text of their icon's name, the name of the file etc, their "new" indicator, etc, all squished together in a weird string. They're also unnecessarily long for showing a basic sort. Can we clean this up to be more legible? Take some known quantities, select for them more cleanly, and assert their position in the list.
src/hooks/useReport/index.test.js
Outdated
@@ -25,6 +25,7 @@ describe('useReport', () => { | |||
</Provider> | |||
); | |||
|
|||
expect((await screen.findByTestId('report-data'))).toHaveTextContent('{"displayTitle":"Light","eventTypeTitle":"Light"}'); | |||
expect((await screen.findByTestId('report-data'))) | |||
.toHaveTextContent('{"coordinates":[-104.19557197413907,20.75709101172957],"displayPriority":300,"displayTitle":"Light","eventTypeTitle":"Light"}'); |
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 test should really be rewritten using renderHook
[ERA-8002] Time Sort Control
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.
Looking good. nice work
|
||
expect((await screen.findByTestId('report-data'))).toHaveTextContent('{"displayTitle":"Light","eventTypeTitle":"Light"}'); | ||
expect(result.current).toEqual({ | ||
coordinates: [-104.19557197413907, 20.75709101172957], |
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.
So much better!
Ticket: https://allenai.atlassian.net/browse/ERA-7998
Env: https://era-7998.pamdas.org/
Figma: https://www.figma.com/file/1u3VbK9kbOEuUg9Wi8AHRW/Patrol-%26-Report-UI-Refresh-FINAL?node-id=1104%3A22978&t=HzjJn1tgySJt8Qbu-0
Evidence

Desktop:
Mobile:
