-
Notifications
You must be signed in to change notification settings - Fork 14
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
Breadcrumbs refactor, testing using jest & storybook #413
base: main
Are you sure you want to change the base?
Conversation
trpc dependency not handled yet
(Reverted changes to package.json for storybook) # Conflicts: # package-lock.json # package.json # src/components/design_system/breadcrumbs/Breadcrumbs.tsx
…r inner display-only component.
@@ -0,0 +1,227 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
|
|||
exports[`BreadcrumbsDesign renders empty for / 1`] = ` |
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 is the "renders empty for / 1`" referring to?
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 file is generated by Jest. Jest will generate these .snap files for test files with tests that use .toMatchSnapshot()
if they don't already exist. If the component code is changed so that it no longer matches the snapshot, the test will fail. To update the snapshot files to match the current version of the component (assuming changes to component are intended), you run jest
with the -u
or --updateSnapshot
option. The way our project is set up in this PR branch, you can update all snapshot files with:
npm run test:frontend -- --updateSnapshot
BreadcrumbsDesign renders empty for /
is the name of the corresponding test in Breadcrumbs.test.tsx
I'm not sure what the "1" refers to. As long as it makes sense to Jest, I guess that's what matters. 😄
See Jest docs for more on Snapshot testing: https://jestjs.io/docs/snapshot-testing
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.
@katconnors once Jest support is merged, would it make sense to document some of this in the README file or compass project wiki? Where do you think would be the best place?
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 just found this comment by doing a search for "readme"... I would definitely advocate for updating the README. My personal best guess would be to go into the h3 "Running Tests", put all the existing content into an h4 for "Backend Tests", add information for "Frontend Tests" as another h4 below it, and then lastly one more h4 for "All Tests". It might be good to also add a link to https://jestjs.io/docs/snapshot-testing, which is where I just went to try to remember how snapshot testing works.
Also, the number seems to refer to the number of the test. Just playing around with it now, I created another test "renders empty for /students/student-id" with different props, and the resulting test generated an additional snapshot, so now there's a
exports[BreadcrumbsDesign renders empty for /students/student-id 2
] = `
snapshot in addition to the first one on my local branch version of the snapshot file.
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.
High level looks good to me, with the caveat that I haven't used jest myself.
Some other comments:
-I really appreciate how thorough the documentation is (both the overview and the file specific comments).
-functionality is good-the tests passed for me (front and backend)
-I would break into multiple PR's in the future (thousands of line changes is a very meaty PR!)
For your questions, I think it would be cool if we integrated some jest into the testing. Leaning towards not completely abolishing ava, but jest is really relevant for the industry and it's a good skill to have.
I don't have strong opinions on the naming, so others can chime in.
.storybook/preview.tsx
Outdated
/* | ||
Attention: We've detected that you're using actions.argTypesRegex together with the visual test addon: | ||
|
||
/Users/mike/Documents/coding/compass/.storybook/preview.tsx | ||
9 | const preview: Preview = { | ||
10 | parameters: { | ||
> 11 | actions: { argTypesRegex: "^on[A-Z].*" }, | ||
| ^^^^^^^^^^^^^ | ||
12 | controls: { | ||
13 | matchers: { | ||
14 | color: /(background|color)$/i, | ||
|
||
We recommend removing the argTypesRegex and assigning explicit action with the fn function from @storybook/test instead: | ||
https://storybook.js.org/docs/essentials/actions#via-storybooktest-fn-spy-function | ||
*/ | ||
// actions: { argTypesRegex: "^on[A-Z].*" }, |
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.
TODO: Take this out of this PR.
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.
@nickvisut is going to take a look at this in a new issue.
jest.setup.ts
Outdated
// eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
jest.mock("next/router", () => require("next-router-mock")); |
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.
TODO: Take this out; no longer mocking the router!
package.json
Outdated
"lint-staged": "^13.1.0", | ||
"next-router-mock": "^0.9.13", |
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.
TODO: Remove this
Still looking at and running the code, but those are some first thoughts. Lastly, and I know a redesign wasn't part of this, but to springboard some discussions - we really need more ui/ux design on the breadcrumb trail to know exactly where the app should go. When I've drilled into a goal:
|
src/components/design_system/breadcrumbs/transformBreadcrumbs.ts
Outdated
Show resolved
Hide resolved
src/components/design_system/breadcrumbs/transformBreadcrumbs.ts
Outdated
Show resolved
Hide resolved
src/components/design_system/breadcrumbs/transformBreadcrumbs.ts
Outdated
Show resolved
Hide resolved
src/components/design_system/breadcrumbs/useBreadcrumbContext.ts
Outdated
Show resolved
Hide resolved
@thomhickey I had filed #396 to address most of these issues. My plan was to first add the ability to test the logic within the breadcrumbs component without changing its functional behavior in this PR, and then fix the functional behavior in another PR and close out #396. |
@thomhickey Hmm...I'm not seeing that. Where do you see that message? |
I have no familiarity with storybook, but when I run it, all the stories are broken. I'm guessing that's not what's supposed to happen...is there anything I should be doing or checking? EDIT: Nvm, for some reason the "transformBreadcrumbs" file was named "transformBreadCrumbs" and that caused storybook to break. Not sure how that happened. |
@thomhickey I think that would make sense if the parent displayed the trail of breadcrumbs and the child displayed a single "crumb," but that's not what's happening. The parent is a stateful component which gets path information from the next router and name data from the backend, and passes it to the child component as props. The stateless child component displays the entire breadcrumb trail based on the props. I like the idea of using "BreadcrumbTrail" rather than "Breadcrumbs" plural though. When @nickvisut and I discussed the PR over a huddle last week, he suggested that:
(@nickvisut , please correct me if I'm misrepresenting your suggestions.) What I'm planning to do now:
I'll work on this now. Thanks for the feedback, @thomhickey and @nickvisut ! |
@KCCPMG, sorry about that. This might have happened because I accidentally named that file with a capital "C"in an earlier commit, and then renamed it with a lower case "c" to match the other files in a later commit. When this PR is eventually squashed and merged, that renaming should be removed from git history, so hopefully no one else will run into this. 🤞 Glad it's working for you now. |
No worries, I felt embarrassed by what a relatively minor issue it was, and I'm surprised it ended up out of sync somehow when it wasn't caught when I started up the the dev server. At any rate, I would have deleted, but I'm leaving it up in case anyone else runs into the same problem and can be spared my embarrassment. |
package-lock.json taken from main branch, then ran `npm install`. # Conflicts: # package-lock.json
Thanks @mrabbitt ... yeah, I suppose I need to be brought up to speed on this whole 'design' and 'design_system' paradigm that's in the codebase. Still scratching my head about why the word 'design' is coming up anywhere in the actual implementations of these components. I understand terms like 'layout' or 'container' in page and component filenames, but 'design' is a head-scratcher for me. |
it went away. that's the second or third time my cursor/vscode has barked about typescript errors that ended up going away. not happy! ... sorry for the confusion @mrabbitt |
I'm getting weird 'cannot find module' errors, even after re-running npm install and even removing my node_modules first and then doing it again. Has anyone else had any issues with this? The first one I had was with esbuild-runner, which I decided to install just to make things work. I got past the postinstall point where it was usually failing, but my backend tests are all exiting and telling me that it cannot find 'nextjs-middleware-wrappers'. This has been the case when I run both 'npm run test:backend', but also if I just do 'npx ava' (though that also gives me grief about finding jest files). |
@KCCPMG , I know this isn't the main problem, but I just pushed a small config change that makes |
@KCCPMG Weird. I haven't seen this. I tried wiping Are there files installed for you under $ ls node_modules/nextjs-middleware-wrappers
README.md dist/ release.config.js tsconfig.json
ava.config.js package.json tests/ wrappers.ts One other idea that might be worth trying is doing a fresh git checkout of compass in another location and seeing if the problem happens there too. |
I just tried the updated branch, then checked out main, all the same thing. I also tried looking for node_modules/nextjs-middleware-wrappers, and the directory isn't there. It looks like it's not supposed to be in package.json, but I do see it in the package-lock.json several times as a peer dependency. The other weird thing is that running tests (or doing a type check) says that now there's no declaration file for the 'pg' library. I'm not sure what's going on, it seems like I might have something pretty deeply screwed up. UPDATE: I tried running this on my other machine and it seems to work fine. More tellingly, running npm install doesn't change my package-lock.json to be out of sync with the git repository, which was happening with both my main branch as well as this one. Seems like the issue is isolated to my MacBook, hopefully the exorcist I called can tell me 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.
I'll approve this because it seems to work, and because the jest testing and storybook stuff look terrific. As far as I'm concerned, this can be merged, but below are my quibbles, which you can feel free to disregard or respond to:
-
I mentioned this before, but it seems to me that useBreadcrumbContext should not be called what it is. There's no call to useContext, nor is there a BreadcrumbContextProvider or something similar, it's effectively just a formatted data object to be passed down. Along similar lines, I don't think that the useBreadcrumbContext needs its own file, but that's an even more nitpicky convention thing, about which I'm probably wrong.
-
I don't think I quite understand why the parent component is referred to as Stateful, there's no actual state and it looks like it's just hooking into useRouter and then passing re-formatted data down.
-
Honestly I get a little bit confused jumping back and forth through the key 4 files involved here, but that's much more on me. I can see how you're splitting up the path and making the "descriptor" part of the benchmark linkable, but not the value that corresponds to a specific identifier. I suppose that makes sense, but it does mean that in students/student_id/goals/goal_id, you wouldn't be able to return to the student, but you would have a link to a goals page that isn't there (I believe @thomhickey mentioned that particular one as well).
Like I said, this works, and hopefully there's some meaningful feedback on the design side of things in terms of if there's something different that they'd like to see. I probably would have used an object that looks at the descriptor which then determined how the descriptor and identifier would be rendered, but that's off the top of my head and there might be very good reasons for not doing that. Sorry for taking so long to get back to you on the review, good job with this, this was clearly a ton of work, and I think that the other infrastructure aspects of this PR will pay big dividends long-term.
@@ -0,0 +1,227 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
|
|||
exports[`BreadcrumbsDesign renders empty for / 1`] = ` |
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 just found this comment by doing a search for "readme"... I would definitely advocate for updating the README. My personal best guess would be to go into the h3 "Running Tests", put all the existing content into an h4 for "Backend Tests", add information for "Frontend Tests" as another h4 below it, and then lastly one more h4 for "All Tests". It might be good to also add a link to https://jestjs.io/docs/snapshot-testing, which is where I just went to try to remember how snapshot testing works.
Also, the number seems to refer to the number of the test. Just playing around with it now, I created another test "renders empty for /students/student-id" with different props, and the resulting test generated an additional snapshot, so now there's a
exports[BreadcrumbsDesign renders empty for /students/student-id 2
] = `
snapshot in addition to the first one on my local branch version of the snapshot file.
src/components/design_system/breadcrumbs/useBreadcrumbContext.ts
Outdated
Show resolved
Hide resolved
|
||
export type Student = SelectableForTable<"student">; | ||
export type Para = SelectableForTable<"user">; | ||
export interface BreadcrumbContext { |
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'm late to the naming things party, but I would caution against using the word context in both this interface and the function. There's no provider for this context as a parent component that deeply nested child components are using, so to my mind this doesn't behave the way that I would expect of something with this name.
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.
following up on this, I agree that we don't want to overload the concept of React "context". perhaps "data" or something similar could work, @mrabbitt?
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 change to-dos from my end, for your commits since my last comment ( Sep 24th onward).
|
||
export type Student = SelectableForTable<"student">; | ||
export type Para = SelectableForTable<"user">; | ||
export interface BreadcrumbContext { |
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.
following up on this, I agree that we don't want to overload the concept of React "context". perhaps "data" or something similar could work, @mrabbitt?
person: Student | Para | undefined; | ||
} | ||
|
||
export const useBreadcrumbContext = ( |
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.
Is this a custom hook?
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.
(if not, can we replace the use
with another word?)
Revisiting this and it's good stuff, @mrabbitt. Looks like there are a handful of unresolved convos (and I just added a couple of my own). They could either be moved out w/"Reference in new issue" to address later or resolved in this PR. |
Included in this PR
Stateful BreadcrumbTrail
: Stateful container component that gets the URL path from and fetches student and para names via router calls. Passes data as props toBreadcrumbTrail
.BreadcrumbTrail
: Stateless component which handles all layout/rendering using given props.test:backend
runs existing tests for backend code with avatest:frontend
runs new frontend tests using jesttest
runs both backend and frontend testsBreadcrumbTrail.test.tsx
tests BreadcrumbTrail component using snapshot testingBreadcrumbTrailUtils.test.ts
contains jest unit tests for a function used by BreadcrumbDesign to transform its input into breadcrumb segments.Not Included in this PR
What input is especially requested from reviewers:
Option 2: Use ava for all teststransformBreadcrumbs.test.ts
will work with ava without further research because they're testing pure TypeScript code without JSX.)Option 3: Use jest for all testsI'd like to rename the component files to match the component names once we're happy with the names, but haven't done that yet.Thank you for reading all this and for your input! 😃