e2e/test/scenarios/joins/reproductions/18512-cannot-join-two-saved-questions-with-same-implicit-explicit-grouped-field.cy.spec.js
Replay of localhost
https://app.replay.io/recording/e2etestscenariosjoinsreproductions18512-cannot-join-two-saved-questions-with-same-implicit-explicit-grouped-fieldcyspecjs--4278ec85-6d28-4d07-ab29-45330ac6e016?point=39915782121745558809872149013078687&time=18597&focusWindow=eyJiZWdpbiI6eyJwb2ludCI6IjMxNDc4Mjk5NzE4NjQxMTIzMTk5NjUzNzQ1Njk2NzAyNDY0IiwidGltZSI6MTQ5Njl9LCJlbmQiOnsicG9pbnQiOiI1NTQ5MjY3MjcwMTcyNDQ1NTMxNTMyMTQzMjE5MDIyMjMzNiIsInRpbWUiOjIzODA5fX0%3D
What is the test trying to do?
The test creates two questions and then tries to join them with the same implicit/explicit grouped field.
Procedurally, the test performs these steps
- two questions are created via the API
- the test clicks on
Saved Questions
and then selects question18512#1
- clicks the join button
- clicks on
Saved Questions
a second time and then selects question18512#2
- visits the visualize page and waits for
Products \u2192 Created At
to appear.
What goes wrong?
When the test fails, the test is not able to select the second question.
What is the observable difference?
When the test fails, the “Saved Questions” button is missing so there’s nothing to click. This happens because the render function has a case statement that renders the
TablePicker
when the test fails and the DatabaseSchemaPicker
when the test passes. Why does the test fail?
The
DatabaseSchemaPicker
is rendered because the active step is a SCHEMA_STEP. And when the test fails, onChangeSchema
is called with 1:PUBLIC
. When the test passes, onChangeSchema
is not called!- Why is
onChangeSchema
called when the test fails?
onChangeSchema
is called from skipTests when the DataSelector is mounted and when the test fails, the component has 1:PUBLIC
schema set in its state. When the test passes, the component does not have any schemas set.- Why is the schema not set when the test passes?
When the test passes, the schema is fetched when the DataSelector is mounted. Here’s what the console logs look like. Here’s the point where the fetch is returned.
When the test fails, the schema is fetched earlier which causes it to finish before the DataSelector even tries to fetch the schema. Here’s the point where the fetch is returned.
- Why is the schema fetched when the test fails
- An earlier step triggers the DataSelector
handleSavedQuestionSelect
callback - Which calls updateQuestion
- Which calls
loadMetadataForCard
- Which calls
entity.api.list
- Which calls
MetabaseApi.db_schemas
- Which makes an api call
When the test fails, the schema is fetched by an earlier test step. Here’s what we know:
How do you fix the test?
This test failure is a example of how coupling React component rendering and state management can lead to unpredictable behavior.
There are two ways to fix this issue
- Add guards in the test to wait for the API calls to complete
- Add guards in the application so that the React component can re-render when the api call resolves
In this case, improving the application is the better option because this issue could just as easily effect users in production.