-
Notifications
You must be signed in to change notification settings - Fork 724
Add docs for testing Redux with hooks (e.g. useSelector, useDispatch, etc) and React Router and ++ #570
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
Comments
I feel like the redux docs are a better place for that. Otherwise we have to maintain these pages regarding testing-library and redux. Since they already have a pretty extensive testing guide I'd recommend opening an issue over there if you have questions. We should probably just remove our example and link to their docs. |
I wrote something here, but it dissapeared... Anyhow, I've read this, and it could turn out to be a case of "not my job" on either side. My hope is to get some docs to work with, either way. |
hello! I'd kindly request to have documentation on how to test properly using React Context with the
|
None of us is getting paid to do this open source work so technically this is just as much your job as it is anyone else's 😉 That's open source for you 😅 @lucasff, googling "Test React Context" turns up this page in the docs: https://testing-library.com/docs/example-react-context |
Hi @kentcdodds, Thanks for chiming in. Your snark is duely noted 🌮. You may have interpreted my use of "not my job" to be that I expect this to be done for me, or that I don't appreciate/understand open source. My apologies, if that was the case. In fact, I meant it to illustrate that--because this project is open source--I am hopeful that someone in the community may have some creative advice and/or ideas toward a solution, which would be helpful toward supplementing the project's docs. Regardless, in my reply that I'd lost and didn't send earlier, I'd intimated that I'd love to help write these docs, but that my understanding--at this time--is such that I can't wrap my head around how to implement a "kitchen sink" testing solution yet. I've been Googling tither and yon, trying this and that, and taking notes as I go. But no luck or lightbulbs as of yet. If I do wind up happening upon a solution or creating one myself, I'll be sure to share it here for consideration. |
@kimfucious Maybe start by sharing what you find lacking in https://redux.js.org/recipes/writing-tests? It seems so much more extensive that I would just drop our guide or upstream some stuff. |
Basically I wrote both of the docs here and there, the problem with dropping our guide is that if for some reason redux will decide to drop RTL explanation, it will leave us with no explanation at all. |
The same applies to any feature we add/drop or they add/drop. But if you think this is a likely scenario then why not just copy it as a whole? Could we establish some communication with redux folks so sync on who should host these guides? Two guides is in my opinion strictly worse since now a reader has to decide which to follow. And if we contradict each other it gets really confusing. |
I agree. |
I mean, we just merged your PR - why would we remove it? :) |
This comment has been minimized.
This comment has been minimized.
@kimfucious I'll address some of your examples here. If you need more guided or in depth help approaching Redux/React/etc. tests, it may help to ask in the
As long as you use the real store (or a similar mock) in your tests this should be fine.
We can update the examples use use hooks, but it still shouldn't affect your test code as long as you use React Redux's
This should not affect your integration tests, only unit tests (which are explained in the Redux docs above Components).
The Redux docs are almost there, we'd just need to replace connect with hooks. Please let us know if you find anything else lacking though. I'd also recommend Testing JavaScript's React course (pro tier) for more in depth examples and integrations. |
I agree, and having to maintain two similar articles isn't ideal. If we update Redux's Writing Tests guide to use hooks (without a separate unconnected component) it should be similar enough to the practices in the Testing Library recipe to replace it. Then Testing Library's recipe can link to Redux's article, which also has more in depth information about unit testing Redux code. Either way we should use hooks in whatever docs we keep to be consistent with Redux's and React's recommendations for new connected components (unless @markerikson is already planning on something similar with the Redux docs rework). |
Hello Gents, I'm impressed by and very appreciative of the positive attention that this thread has received from each of you. My two cents regarding React Testing Library docs is that the docs should focus on how to make the product work in various scenarios, including combined scenarios. Obviously there are a lot of different testing scenarios, so it's a big ask to think that everything would be covered, so focusing on the most common scenarios seems to be the best way forward. I agree that maintaining docs in multiple locations is a bug-bear, so if RTL can point to Redux docs and those docs give a clear picture on how to proceed, that's perfect. In some cases, I can see that Redux docs are mirroring the RTL docs, like here. For me personally, on the current project I'm working on, I think I have a fairly common combination of the following: Redux wrapped around React Router: const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<AppRouter />
</Provider>,
document.getElementById("root")
); AppRouter is using "protected routes" that rely on Redux import React from "react";
import { useSelector } from "react-redux";
import { Route, Redirect, useLocation } from "react-router-dom";
const PrivateRoute = ({ children, ...rest }) => {
const location = useLocation();
const { username } = useSelector((state) => state.auth);
const isAuthenticated = !!username;
return (
<Route
{...rest}
render={({ location }) =>
isAuthenticated ? (
children
) : (
<Redirect
to={{
pathname: "/",
state: { from: location }
}}
/>
)
}
/>
); I use Redux I use React Router Nearly all my action creators are "thunked" with the following pattern: export const doSignOutCognitoUser = () => async (dispatch) => {
dispatch({ type: "SIGN_OUT_START" });
try {
await Auth.signOut();
dispatch({ type: "SIGN_OUT_SUCCESS" });
} catch (e) {
dispatch({ type: "SIGN_OUT_FAIL", payload: e });
console.log(e);
}
}; Some components use all of the above, for example: let Forms = ({ isPortrait }) => {
const dispatch = useDispatch();
const history = useHistory();
const location = useLocation();
const [, width] = useWindowSize();
const {
auth: {
attributes: { "custom:role": role }
},
form: formData,
formality: {
alert,
selectedEvent,
selectedForm,
hasPrintError,
isProcessing,
formToUpload
},
user: { impersonating, cookiesAccepted }
} = useSelector((state) => state);
const [isSpinning, setIsSpinning] = useState(false);
useEffect(() => {
if (alert && alert.message.includes("subscription is not active")) {
history.push("/profile");
}
}, [alert, history]);
// pushes manager back to My Employees page when impersonation alert is dismissed
useEffect(() => {
if (role === "manager" && !impersonating.id) {
history.push("/my-employees");
}
}, [history, impersonating, location, role]);
useEffect(() => {
if (width < 768) {
dispatch({ type: "SET_SELECTED_FORM", payload: "" });
} else {
if (!selectedForm) {
dispatch({ type: "SET_SELECTED_FORM", payload: "appDetails" });
}
}
}, [dispatch, selectedForm, width]);
... I hope that gives you an idea of what I'm working with. I'm not sure, but while it seems like a lot of things are in use here, it's not that uncommon a setup. To be blunt, I've just not been able to find any set of docs that helps me wrap my mind around how to setup testing for this "kitchen sink" type of scenario. If it's out there, I just haven't found it yet. Lastly, I am talking unit tests only, for example:
Integration tests would be Cypress, and that's a whole nuther thing, which is not on topic. Please do ask further question of me if needed, I'm happy to help with this in any way that I can. |
I agree that having integrated docs is important to show more real world usage, but as we mentioned above it's not ideal to maintain two very similar doc pages.
In my opinion the Redux Writing Tests page already does a decent job. If you have any specific issues with that please open an issue on Redux or check out the
Yea, I think the format of the Redux docs provides more useful context in this case though. The Testing Library docs are more focused on API references and general usage.
The Connected Components section covers integration testing with providers. As long as your store has
It sounds like you may be looking for something more like Testing JavaScript as it covers React-related testing topics other than Redux and Testing Library (such as React Router) step-by-step and in more detail. I believe Epic React will have more complex kitchen-sync testing examples as well. I'm still open to suggestions for Redux and Testing Library things missing from the examples though.
I wouldn't recommend unit testing user interfaces, especially with React. Testing Library is specifically designed in favor of integration tests, so I think you'll have the best experience with it if you take more of an integration testing approach.
You can use a query with
Dispatching an event generally updates something in your React app, and you can assert that update happens with Testing Library (using
You generally wouldn't test what functions are doing in an integration test. But if you wanted to unit test it as a separate entity you could, or you could use spies to make sure the internals are working properly if you can't show the result for some reason (like if it's some logging service that the user can't see but your tests can't use the logging service).
Kent and I would generally recommend Testing Library for integration and Cypress for end to end, but you can do what works for you. |
Generally we have included recipes for 3rd party libraries in these scenarios:
The docs look pretty good on the Redux side. I'd say we should just link to them. |
If you haven't seen it yet, that's what I did in #588. Do you think it would also help to do this for other recipes in the long run? |
I've created a repo to gather some examples together with a silly, little app that has (or will have) most of the functionality that I'm looking to test. At present, I've gotten past the hurdle of creating a wrapper, to reduce boilerplate, that gets tests running with both Redux and React Router. This is all obviously incomplete at the onset, and it's evident that I don't really know what I'm doing yet, but it's a starting point that might help both to illustrate what I'm trying to test and others who might find the examples helpful. |
Thanks for this, @nickmccurdy. I misused the term, "unit tests", in the above. I believe that I should have said 'integration tests". You could verify the things I'm trying to test here, if you're at all interested. |
Is your feature request related to a problem? Please describe.
First off, I should say that this is an excellent testing library, and I do appreciate all the work that has gone into it.
That said, I'm always frustrated when I try to use React Testing Library on a project where I'm using the following setup:
useSelector
hook (not using connect anymore)useDispatch
hookI start to try and write tests, and them I'm like, "Oh, yeah... this is why I'm always frustrated."
Then I read this, and try to think, "Ugh, I'm not using a single reducer, and I ain't got no initialState either."
So then I try to jam
rootReducer
in to see what will happen, and then, and then, and then it's a trip down a Google rabbit-hole and a couple hours of frustration, and then I give up.Describe the solution you'd like
I'd love some docs that covered testing an app that implements Redux, using combined reducers and hooks (e.g. useSelector & useDispatch).
🤯 Even better would be a "kitchen sink" example that did everything, including Redux and React Router together with Thunk in Action Creators, and, and, and, ++.
I realize that this probably comes off as a bit whiney, but it's kinda meant to sound like that, because I'm like a kid that wants to play with a toy that's beyond his age range.
The text was updated successfully, but these errors were encountered: