-
Notifications
You must be signed in to change notification settings - Fork 124
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
Test Thoughts & Subthoughts #312
Conversation
Only first test is passing, no matter which test it is. I'm suspecting I need to clean up something or reinit firebase or something, so I'm closing this PR for now. |
Everything works if we have one |
I am unfortunately getting the following error when I try to run the tests:
|
Looking into a solution, as it may be OSX specific. |
Sweet, installing watchman was all it took to fix that. |
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 still have not figured out how to run more than one it
block in the same file. It seems to not be properly cleaning up/unmounting, because the wrappers are returning nodes from the previous it
. It's good that it is not cleaned up automatically, as we want the same component to be used across multiple it
blocks when we are testing various properties without having to recreate the DOM each time, but I am not sure why unmount
is not working. It would be nice to be able to reset for each describe
block in some cases.
I have yet to test this potential solution out: enzymejs/enzyme#911
Another approach: uyhcire/tabliner@3e4c7d3
For now, we can do each full test scenario in a separate file.
Do you want me to add it as dev dependency? |
35fad43
to
8d80593
Compare
No, too heavy. Developers can install it if needed for now. |
2e66407
to
88cfaca
Compare
I left
|
wrapper = null | ||
}) | ||
|
||
it('create and edit empty thought', async () => { |
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.
Create and edit should be separate tests.
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.
Think about it, it's useless. In order to edit the thought, you need to create it, so why not test it? Same for delete.
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 disagree. If there is one test for creating a thought and for editing a thought, and the test fails after some changes are made in the future, we won't know whether there was a regression in creating a thought or editing a thought. While editing a thought will never work if creating a thought is broken, the inverse is not true. Having separate tests isolates these test cases and prevents this ambiguity from arising.
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.
But failing test tells you exact line where it broke, so we will know what exactly failed. If you still want me to have create and edit, no problem.
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.
Good point. Either one is a reasonable approach. Let's go with separate tests since that is my preference.
a80dfe4
to
dd15d4b
Compare
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, thanks!
Could you find a way to get rid of the render
warning that appears in the tests?
Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.
I will fix the Failed prop type
warning.
We should investigate why restoreSelection
is failing as well.
src/setupTests.js
Outdated
const skipTutorial = wrapper.find('div.modal-actions div a') | ||
skipTutorial.simulate('click') | ||
const keyboardResponder = wrapper.find('#keyboard') | ||
await keyboardResponder.simulate('keydown', { key: 'Enter' }) |
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.
Can we put the Enter event in the tests? I'm okay with the skipTutorial click happening here, but the new thought should go in each test. If a regression is introduced to creating a new thought, we want the newThought test to fail, not setupTests.
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.
Still waiting on this
src/setupTests.js
Outdated
} | ||
|
||
await act(async () => { | ||
// eslint-disable-next-line no-undef |
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 believe you can remove the eslint-disable lines related to jest now that we have jest
specified as an eslint env.
@@ -0,0 +1,6 @@ | |||
it('create thought', async () => { | |||
const thought = document.wrapper.find( | |||
'li.leaf div.thought-container div.thought div.editable', |
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.
Based on my tests, document.wrapper.find('div.editable')
works fine.
.editable
does not work because there is both a <ContentEditable className='editable'>
and a <div className='editable'>
await thought.update() | ||
expect(thought.text()).toBe('c') | ||
// eslint-disable-next-line fp/no-let | ||
const subthoughtsData = getThoughtsRanked(['c']) |
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 variables are short enough that they can be inlined in the expect
.
await thought.update() | ||
expect(thought.text()).toBe('c') | ||
// eslint-disable-next-line fp/no-let | ||
let subthoughtsData = getThoughtsRanked(['c']) |
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.
Let's avoid let
here, and simply inline these short statements as needed.
jest.runAllTimers() | ||
await thought.update() | ||
expect(thought.text()).toBe('c') | ||
// eslint-disable-next-line fp/no-let |
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.
Similar
jest.runAllTimers() | ||
await thought.update() | ||
expect(thought.text()).toBe('c') | ||
// eslint-disable-next-line fp/no-let |
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.
Also here
071f35e
to
0e7f5db
Compare
Also let's move the |
I tried moving tests one directory up, but this is what I end up with:
|
c6e3dd5
to
700d892
Compare
Okay, that's too bad. |
Thank you, those are perfectly sized and named commits. |
700d892
to
facb4d6
Compare
Well, after a couple hours of trying different things myself, I was also unable to get the Editable element to update in the unit test. None of the tips in enzymejs/enzyme#76 seemed to work. That said, the import { ROOT_TOKEN } from '../../constants.js'
import { getThoughts } from '../../util.js'
it('edit thought', async () => {
const thought = document.wrapper.find('div.editable')
expect(thought.text()).toBe('')
await thought.simulate('change', { target: { value: 'c' } })
jest.runAllTimers()
// for some reason the text of the Editable element is not updated
// await document.wrapper.update()
// expect(document.wrapper.find('div.editable').text()).toBe('c')
const children = getThoughts([ROOT_TOKEN])
expect(children).toHaveLength(1)
expect(children[0]).toMatchObject({ value: 'c', rank: 0 })
}) |
These changes are important to set |
e1484cc
to
12f5dd4
Compare
src/setupTests.js
Outdated
|
||
await act(async () => { | ||
jest.useFakeTimers() | ||
const originalError = console.error |
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.
Hey, I'm not really comfortable with disabling console.error
to hide the error. It seems like it's just a workaround. Let's try to get to the source of the problem. If it is impossible to remove, it deserves a clear comment explaining why.
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 https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOMLegacy.js#L81 is where we get that error from. As I don't see any way to go around it except creating new console.error
which filters what it outputs by content (we can output only if first argument to console.error
is not the one from the link).
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.
New console.error
mock is more precise in what it silences. Good enough?
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.
Mounting to a child of document.body
will fix the error without the workaround:
// mount to child to avoid warning about rendering directly to document.body
const root = document.body.appendChild(document.createElement('div'))
const wrapper = await mount(
<div
id="keyboard"
onKeyDown={keyDown}
tabIndex="0"
>
{app}
</div>,
{ attachTo: root },
)
e61fe08
to
ccf085f
Compare
I was going to try this solution, but this branch is crashing as-is when I run ● Console
console.warn src/reducers/settings.js:25
Missing oldThoughtRanked in Settings update: Tutorial Off
RUNS src/components/__tests__/SubThoughtCreate.js
/Users/raine/projects/em/node_modules/react-scripts/scripts/test.js:20
throw err;
^
TypeError: Cannot read property '_location' of null
at Window.get location [as location] (/Users/raine/projects/em/node_modules/jsdom/lib/jsdom/browser/Window.js:148:79)
at Object.<anonymous>.exports.loadLocalState (/Users/raine/projects/em/src/util/loadLocalState.js:56:32)
npm ERR! Test failed. See above for more details. |
I do see it in the log, but it doesn't break. This is the whole log on my machine http://dpaste.com/27JD3PE |
d5f8716
to
2d1b58f
Compare
Great! The |
src/setupTests.js
Outdated
const skipTutorial = wrapper.find('div.modal-actions div a') | ||
skipTutorial.simulate('click') | ||
const keyboardResponder = wrapper.find('#keyboard') | ||
await keyboardResponder.simulate('keydown', { key: 'Enter' }) |
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.
Still waiting on this
src/setupTests.js
Outdated
|
||
await act(async () => { | ||
jest.useFakeTimers() | ||
const originalError = console.error |
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.
Mounting to a child of document.body
will fix the error without the workaround:
// mount to child to avoid warning about rendering directly to document.body
const root = document.body.appendChild(document.createElement('div'))
const wrapper = await mount(
<div
id="keyboard"
onKeyDown={keyDown}
tabIndex="0"
>
{app}
</div>,
{ attachTo: root },
)
Github doesn't let me reply on last two comments.
|
That's a fair argument I suppose. To me it seems clear that creating a thought is a testable action, not part of setup. It is also more future-proof, as there will likely be tests that do not begin by creating a new thought. |
86dc39d
to
b0be19c
Compare
Refers to #244