Skip to content

Commit

Permalink
feat(waitForElementToBeRemoved): add the new utility function (#218)
Browse files Browse the repository at this point in the history
* Add tests and snapshots

* Implement waitForElementToBeRemoved method

* Export waitForElementToBeRemoved

* Add as contributor

* Update README.md after rebase

* Throw error is the element is not present in the first place

* Add test for full coverage

* User jest time faker

* Add typings

* Cleanup

* Update snapshot

* Get rid of iife

* Cleanup from review

* Check for empty array as well

* Check for error, falsy and empty to check whether the element is removed

* error not defined error fix

* Change snapshot to inline snapshot

* Update snapshot

* Only observe mutations if synchronous test passes

* only observer if synchronous test passes fix

* Await for the respective promise to resolve in test

* Snapshot test to normal toHaveBeenCalledWith assertions

* Update comment

* Remove comment

* test: improve tests for wait-for-element-to-be-removed

* test: fix everything

* test: do not test unstable node versions
  • Loading branch information
Tolsee authored and Kent C. Dodds committed Mar 9, 2019
1 parent ca7db36 commit 1727a49
Show file tree
Hide file tree
Showing 24 changed files with 186 additions and 104 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,15 @@
"code",
"test"
]
},
{
"login": "Tolsee",
"name": "Tulsi Sapkota",
"avatar_url": "https://avatars0.githubusercontent.com/u/16590492?v=4",
"profile": "https://github.com/Tolsee",
"contributions": [
"code"
]
}
]
}
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ cache:
notifications:
email: false
node_js:
- 'node'
- '10'
- '8'
install: npm install
Expand Down
15 changes: 0 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@ Thanks for being willing to contribute!
> branch. Whenever you want to update your version of `master`, do a regular
> `git pull`.
## Add yourself as a contributor
This project follows the [all contributors][all-contributors] specification.
To add yourself to the table of contributors on the `README.md`, please use the
automated script as part of your PR:
```console
npm run add-contributor
```
Follow the prompt and commit `.all-contributorsrc` and `README.md` in the PR.
If you've already added yourself to the list and are making
a new type of contribution, you can run it again and select the added
contribution type.

## Committing and Pushing changes
Please make sure to run the tests before you commit your changes. You can run
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
[![downloads][downloads-badge]][npmtrends]
[![MIT License][license-badge]][license]

[![All Contributors](https://img.shields.io/badge/all_contributors-50-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-51-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Code of Conduct][coc-badge]][coc]

Expand Down Expand Up @@ -138,7 +138,7 @@ Thanks goes to these people ([emoji key][emojis]):
| [<img src="https://avatars3.githubusercontent.com/u/881986?v=4" width="100px;" alt="dadamssg"/><br /><sub><b>dadamssg</b></sub>](https://github.com/dadamssg)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=dadamssg "Code") | [<img src="https://avatars1.githubusercontent.com/u/186971?v=4" width="100px;" alt="Neil Kistner"/><br /><sub><b>Neil Kistner</b></sub>](https://neilkistner.com/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=wyze "Code") | [<img src="https://avatars3.githubusercontent.com/u/1448597?v=4" width="100px;" alt="Ben Chauvette"/><br /><sub><b>Ben Chauvette</b></sub>](http://bdchauvette.net/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=bdchauvette "Code") | [<img src="https://avatars2.githubusercontent.com/u/777527?v=4" width="100px;" alt="Jeff Baumgardt"/><br /><sub><b>Jeff Baumgardt</b></sub>](https://github.com/JeffBaumgardt)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/4658208?v=4" width="100px;" alt="Matan Kushner"/><br /><sub><b>Matan Kushner</b></sub>](http://matchai.me)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Documentation") [🤔](#ideas-matchai "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Tests") | [<img src="https://avatars2.githubusercontent.com/u/5779538?v=4" width="100px;" alt="Alex Wendte"/><br /><sub><b>Alex Wendte</b></sub>](http://www.wendtedesigns.com/)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=themostcolm "Tests") | [<img src="https://avatars0.githubusercontent.com/u/2196208?v=4" width="100px;" alt="Tamas Fodor"/><br /><sub><b>Tamas Fodor</b></sub>](https://github.com/ruffle1986)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=ruffle1986 "Documentation") |
| [<img src="https://avatars3.githubusercontent.com/u/14793495?v=4" width="100px;" alt="Benjamin Eckardt"/><br /><sub><b>Benjamin Eckardt</b></sub>](https://github.com/BenjaminEckardt)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=BenjaminEckardt "Code") | [<img src="https://avatars3.githubusercontent.com/u/205752?v=4" width="100px;" alt="Ryan Campbell"/><br /><sub><b>Ryan Campbell</b></sub>](https://github.com/campbellr)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=campbellr "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/1335519?v=4" width="100px;" alt="Taylor Briggs"/><br /><sub><b>Taylor Briggs</b></sub>](https://taylor-briggs.com)<br />[⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=TaylorBriggs "Tests") | [<img src="https://avatars2.githubusercontent.com/u/132233?v=4" width="100px;" alt="John Gozde"/><br /><sub><b>John Gozde</b></sub>](https://github.com/jgoz)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=jgoz "Code") | [<img src="https://avatars2.githubusercontent.com/u/3382565?v=4" width="100px;" alt="C. T. Lin"/><br /><sub><b>C. T. Lin</b></sub>](https://github.com/chentsulin)<br />[📖](https://github.com/kentcdodds/dom-testing-library/commits?author=chentsulin "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/5312329?v=4" width="100px;" alt="Terrence Wong"/><br /><sub><b>Terrence Wong</b></sub>](http://terrencewwong.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=terrencewwong "Code") | [<img src="https://avatars0.githubusercontent.com/u/12230408?v=4" width="100px;" alt="Soo Jae Hwang"/><br /><sub><b>Soo Jae Hwang</b></sub>](https://www.ossfinder.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=misoguy "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/19773?v=4" width="100px;" alt="Royston Shufflebotham"/><br /><sub><b>Royston Shufflebotham</b></sub>](https://github.com/RoystonS)<br />[🐛](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3ARoystonS "Bug reports") [💻](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=RoystonS "Tests") | [<img src="https://avatars0.githubusercontent.com/u/591673?v=4" width="100px;" alt="Vadim Brodsky"/><br /><sub><b>Vadim Brodsky</b></sub>](http://www.vadimbrodsky.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=VadimBrodsky "Code") | [<img src="https://avatars3.githubusercontent.com/u/499898?v=4" width="100px;" alt="Eunjae Lee"/><br /><sub><b>Eunjae Lee</b></sub>](https://twitter.com/eunjae_lee)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=eunjae-lee "Code") | [<img src="https://avatars2.githubusercontent.com/u/167743?v=4" width="100px;" alt="David Peter"/><br /><sub><b>David Peter</b></sub>](http://davidpeter.me)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=sarenji "Code") | [<img src="https://avatars0.githubusercontent.com/u/13174025?v=4" width="100px;" alt="Shy Alter"/><br /><sub><b>Shy Alter</b></sub>](https://twitter.com/@puemos)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=puemos "Code") [📖](https://github.com/kentcdodds/dom-testing-library/commits?author=puemos "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/11966621?v=4" width="100px;" alt="Łukasz Makuch"/><br /><sub><b>Łukasz Makuch</b></sub>](https://lukaszmakuch.pl)<br />[📦](#platform-lukaszmakuch "Packaging/porting to new platform") | [<img src="https://avatars1.githubusercontent.com/u/11150235?v=4" width="100px;" alt="Tyler Haas"/><br /><sub><b>Tyler Haas</b></sub>](https://github.com/tylerthehaas)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=tylerthehaas "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=tylerthehaas "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/482561?v=4" width="100px;" alt="Vesa Laakso"/><br /><sub><b>Vesa Laakso</b></sub>](http://vesalaakso.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=valscion "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=valscion "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/482561?v=4" width="100px;" alt="Vesa Laakso"/><br /><sub><b>Vesa Laakso</b></sub>](http://vesalaakso.com)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=valscion "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=valscion "Tests") | [<img src="https://avatars0.githubusercontent.com/u/16590492?v=4" width="100px;" alt="Tulsi Sapkota"/><br /><sub><b>Tulsi Sapkota</b></sub>](https://github.com/Tolsee)<br />[💻](https://github.com/kentcdodds/dom-testing-library/commits?author=Tolsee "Code") |

<!-- ALL-CONTRIBUTORS-LIST:END -->

Expand Down
18 changes: 2 additions & 16 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
const baseConfig = require('kcd-scripts/jest')

module.exports = {
collectCoverageFrom: baseConfig.collectCoverageFrom,
coverageThreshold: baseConfig.coverageThreshold,
projects: [
{
...baseConfig,
displayName: 'jsdom',
testEnvironment: 'jest-environment-jsdom',
},
{
...baseConfig,
displayName: 'node',
testEnvironment: 'jest-environment-node',
},
],
// this is for eslint
modulePaths: baseConfig.modulePaths,
...baseConfig,
testEnvironment: 'jest-environment-jsdom',
}
18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,36 @@
"node": ">=8"
},
"scripts": {
"add-contributor": "kcd-scripts contributors add",
"build": "kcd-scripts build && kcd-scripts build --bundle --no-clean",
"lint": "kcd-scripts lint",
"test": "kcd-scripts test",
"test:update": "npm test -- --updateSnapshot --coverage",
"validate": "kcd-scripts validate",
"setup": "npm install && npm run validate -s",
"precommit": "kcd-scripts precommit",
"dtslint": "dtslint typings"
},
"husky": {
"hooks": {
"pre-commit": "kcd-scripts pre-commit"
}
},
"files": [
"dist",
"typings"
],
"dependencies": {
"@babel/runtime": "^7.1.5",
"@babel/runtime": "^7.3.4",
"@sheerun/mutationobserver-shim": "^0.3.2",
"pretty-format": "^24.0.0",
"wait-for-expect": "^1.1.0"
},
"devDependencies": {
"dtslint": "^0.3.0",
"jest-dom": "^2.1.1",
"dtslint": "^0.5.3",
"jest-dom": "^3.1.2",
"jest-in-case": "^1.0.2",
"jsdom": "^13.0.0",
"kcd-scripts": "^0.46.0"
"jest-watch-select-projects": "^0.1.1",
"jsdom": "^13.2.0",
"kcd-scripts": "^1.1.0"
},
"eslintConfig": {
"extends": "./node_modules/kcd-scripts/eslint.js",
Expand Down
1 change: 0 additions & 1 deletion src/__tests__/element-queries.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'jest-dom/extend-expect'
import {configure} from '../config'
import {render, renderIntoDocument} from './helpers/test-utils'
import document from './helpers/document'

beforeEach(() => {
document.defaultView.Cypress = null
Expand Down
2 changes: 0 additions & 2 deletions src/__tests__/events.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import {fireEvent} from '..'
import document from './helpers/document'
import window from './helpers/window'

const eventTypes = [
{
Expand Down
1 change: 0 additions & 1 deletion src/__tests__/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import {getByLabelText, getByText, getByTestId, queryByTestId, wait} from '../'
// adds special assertions like toHaveTextContent
import 'jest-dom/extend-expect'
import document from './helpers/document'

function getExampleDOM() {
// This is just a raw example of setting up some DOM
Expand Down
1 change: 0 additions & 1 deletion src/__tests__/get-queries-for-element.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {getQueriesForElement} from '../get-queries-for-element'
import {queries} from '..'
import document from './helpers/document'

test('uses default queries', () => {
const container = document.createElement('div')
Expand Down
14 changes: 2 additions & 12 deletions src/__tests__/helpers.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import {getDocument, newMutationObserver} from '../helpers'

describe('getDocument', () => {
if (typeof document === 'undefined') {
test('throws an error if window does not exist', () => {
expect(() => getDocument()).toThrowError(
/Could not find default container/,
)
})
} else {
test('returns global document if exists', () => {
expect(getDocument()).toBe(document)
})
}
test('returns global document if exists', () => {
expect(getDocument()).toBe(document)
})

class DummyClass {
Expand Down
9 changes: 0 additions & 9 deletions src/__tests__/helpers/document.js

This file was deleted.

1 change: 0 additions & 1 deletion src/__tests__/helpers/test-utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {getQueriesForElement} from '../../get-queries-for-element'
import document from './document'

function render(html) {
const container = document.createElement('div')
Expand Down
9 changes: 0 additions & 9 deletions src/__tests__/helpers/window.js

This file was deleted.

1 change: 0 additions & 1 deletion src/__tests__/pretty-dom.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {prettyDOM} from '../pretty-dom'
import {render} from './helpers/test-utils'
import document from './helpers/document'

test('it prints out the given DOM element tree', () => {
const {container} = render('<div>Hello World!</div>')
Expand Down
16 changes: 2 additions & 14 deletions src/__tests__/wait-for-dom-change.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {waitForDomChange} from '../'
// adds special assertions like toBeTruthy
import 'jest-dom/extend-expect'
import {render} from './helpers/test-utils'
import document from './helpers/document'

const skipSomeTime = delayMs =>
new Promise(resolve => setTimeout(resolve, delayMs))
Expand All @@ -16,11 +15,7 @@ test('it waits for the next DOM mutation', async () => {
const successHandler = jest.fn().mockName('successHandler')
const errorHandler = jest.fn().mockName('errorHandler')

if (typeof window === 'undefined') {
waitForDomChange({container: document}).then(successHandler, errorHandler)
} else {
waitForDomChange().then(successHandler, errorHandler)
}
waitForDomChange().then(successHandler, errorHandler)

// Promise callbacks are always asynchronous.
expect(successHandler).toHaveBeenCalledTimes(0)
Expand Down Expand Up @@ -88,14 +83,7 @@ test('it throws if timeout is exceeded', async () => {
const successHandler = jest.fn().mockName('successHandler')
const errorHandler = jest.fn().mockName('errorHandler')

if (typeof window === 'undefined') {
waitForDomChange({container: document, timeout: 70}).then(
successHandler,
errorHandler,
)
} else {
waitForDomChange({timeout: 70}).then(successHandler, errorHandler)
}
waitForDomChange({timeout: 70}).then(successHandler, errorHandler)

await skipSomeTimeForMutationObserver(100)

Expand Down
40 changes: 40 additions & 0 deletions src/__tests__/wait-for-element-to-be-removed.fake-timers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'jest-dom/extend-expect'
import {waitForElementToBeRemoved} from '../'
import {render} from './helpers/test-utils'

jest.useFakeTimers()

test('requires a function as the first parameter', () => {
return expect(
waitForElementToBeRemoved(),
).rejects.toThrowErrorMatchingInlineSnapshot(
`"waitForElementToBeRemoved requires a function as the first parameter"`,
)
})

test('requires an element to exist first', () => {
return expect(
waitForElementToBeRemoved(() => null),
).rejects.toThrowErrorMatchingInlineSnapshot(
`"The callback function which was passed did not return an element or non-empty array of elements. waitForElementToBeRemoved requires that the element(s) exist before waiting for removal."`,
)
})

test('requires an unempty array of elements to exist first', () => {
return expect(
waitForElementToBeRemoved(() => []),
).rejects.toThrowErrorMatchingInlineSnapshot(
`"The callback function which was passed did not return an element or non-empty array of elements. waitForElementToBeRemoved requires that the element(s) exist before waiting for removal."`,
)
})

test('times out after 4500ms by default', () => {
const {container} = render(`<div></div>`)
const promise = expect(
waitForElementToBeRemoved(() => container),
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Timed out in waitForElementToBeRemoved."`,
)
jest.advanceTimersByTime(4501)
return promise
})
36 changes: 36 additions & 0 deletions src/__tests__/wait-for-element-to-be-removed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'jest-dom/extend-expect'
import {waitForElementToBeRemoved} from '../'
import {renderIntoDocument} from './helpers/test-utils'

test('resolves on mutation only when the element is removed', async () => {
const {queryAllByTestId} = renderIntoDocument(`
<div data-testid="div"></div>
<div data-testid="div"></div>
`)
const divs = queryAllByTestId('div')
// first mutation
setTimeout(() => {
divs.forEach(d => d.setAttribute('id', 'mutated'))
})
// removal
setTimeout(() => {
divs.forEach(div => div.parentElement.removeChild(div))
}, 100)
// the timeout is here for two reasons:
// 1. It helps test the timeout config
// 2. The element should be removed immediately
// so if it doesn't in the first 100ms then we know something's wrong
// so we'll fail early and not wait the full timeout
await waitForElementToBeRemoved(() => queryAllByTestId('div'), {timeout: 200})
})

test('resolves on mutation if callback throws an error', async () => {
const {getByTestId} = renderIntoDocument(`
<div data-testid="div"></div>
`)
const div = getByTestId('div')
setTimeout(() => {
div.parentElement.removeChild(div)
})
await waitForElementToBeRemoved(() => getByTestId('div'), {timeout: 100})
})
1 change: 0 additions & 1 deletion src/__tests__/wait-for-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {waitForElement, wait} from '../'
// adds special assertions like toBeTruthy
import 'jest-dom/extend-expect'
import {render} from './helpers/test-utils'
import document from './helpers/document'

const skipSomeTime = delayMs =>
new Promise(resolve => setTimeout(resolve, delayMs))
Expand Down
11 changes: 0 additions & 11 deletions src/__tests__/wait.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,3 @@ test('it waits for the data to be loaded', async () => {
await wait(() => expect(spy).toHaveBeenCalledTimes(1))
expect(spy).toHaveBeenCalledWith()
})

test('can just be used for a next tick thing', async () => {
jest.useFakeTimers()
const spy = jest.fn()
Promise.resolve().then(spy)
expect(spy).toHaveBeenCalledTimes(0) // promises are always async
await wait() // wait for next tick
jest.advanceTimersByTime(60)
expect(spy).toHaveBeenCalledTimes(1)
jest.clearAllTimers()
})
1 change: 1 addition & 0 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function newMutationObserver(onMutation) {
}

function getDocument() {
/* istanbul ignore if */
if (typeof window === 'undefined') {
throw new Error('Could not find default container')
}
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as queryHelpers from './query-helpers'
export * from './queries'
export * from './wait'
export * from './wait-for-element'
export * from './wait-for-element-to-be-removed'
export * from './wait-for-dom-change'
export {getDefaultNormalizer} from './matches'
export * from './get-node-text'
Expand Down
Loading

0 comments on commit 1727a49

Please sign in to comment.