Attempt My Gameboards VRT fix - #2346
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2346 +/- ##
==========================================
- Coverage 43.57% 43.55% -0.03%
==========================================
Files 601 601
Lines 25811 25856 +45
Branches 8610 8588 -22
==========================================
+ Hits 11248 11262 +14
- Misses 14506 14537 +31
Partials 57 57 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I've gotten as far as your first fix, but gave up when I saw the second problem! (Here's the PR I ultimately gave up on: #2300). Very excited to see this potentially getting fixed! |
There was a problem hiding this comment.
I'd by lying if I said I understood everything that's happening, but if I correctly understood you:
- you're now waiting for the window object to become available, and explicitly passing this to
createBrowserRouter - you're now passing a unique uuid to the
mountcommand, so react doesn't treat our components as the same. This is because you suspect some react state is seeping through these test cases.
The first change is specific to createBrowserRouter, and the second is about isolating our test cases. I'd just like to note here for our later reference that even with the (hopefully) improved isolation here, we have a lot of state bleeding through these test cases. For an example, I've worked up this proof to show that they use the same store:
import React from "react";
import { selectors, sidebarSlice, useAppDispatch, useAppSelector } from "../../app/state";
const SetStore = () => {
const isSidebarOpen = useAppSelector(selectors.sidebar.open);
const dispatch = useAppDispatch();
dispatch(sidebarSlice.actions.setOpen(true));
return <p data-testId="testPar">The sidebar is {isSidebarOpen ? "open" : "closed"}</p>;
};
const ReadStore = () => {
const isSidebarOpen = useAppSelector(selectors.sidebar.open);
return <p data-testId="testPar">The sidebar is {isSidebarOpen ? "open" : "closed"}</p>;
};
it('sets something on the store', () => {
cy.mountWithStoreAndRouter(<SetStore />);
cy.get('[data-testId=testPar]').should('have.text', "The sidebar is open");
});
it('then reads that from the store', () => {
cy.mountWithStoreAndRouter(<ReadStore />);
cy.get('[data-testId=testPar]').should('have.text', "The sidebar is open");
});
|
Yes, indeed – you can see this quite clearly from |
There are two fixes here that work together and do seem to be working consistently. There are 5 successful consecutive runs here.
First, this wraps the
mountWithStoreAndRoutercommand with acy.window().then(window => ...);. This ensures a global window is necessarily defined beforecreateBrowserRoutergets called; this was causing theCannot read properties of null (reading 'history')error we love. The reason the window was not defined in the first place is slightly more tricky, and indeed this fix alone does not solve the issue.If we fix the window issue, the next error seen (from this run) helps find the root cause – this reads
queue.insert must be called with a valid index - the index (1) is out of bounds. Similar stack traces occur when Cypress commands occur outside of the standard test lifecycle order. In this case, my presumption is that:<MyGameboards user={mockUser} />wrapped in a store<Provider />and a<RouterProvider />;The fix is therefore to ensure that the component passed into the tests cannot be recognised as the same by React. We solve this with
keys; my first attempt at doing this manually did not seem to work, but themountfunction takes an explicitrerenderKeythat seems to be for precisely this purpose, so I'm using a random string unique to a given test.These two things together seem to fix things!