parent
b69df8d8e7
commit
ace9f5bdbf
@ -0,0 +1,39 @@
|
|||||||
|
import angular from 'angular'
|
||||||
|
import 'angular-mocks'
|
||||||
|
import {render, fireEvent} from '../'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.module('atl', [])
|
||||||
|
angular.mock.module('atl')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('`fireEvent` triggers a digest', () => {
|
||||||
|
angular.module('atl').component('atlDigest', {
|
||||||
|
template: `
|
||||||
|
<button ng-ref="$ctrl.btn">
|
||||||
|
Click Me
|
||||||
|
</button>
|
||||||
|
<div ng-if="$ctrl.wasClicked">
|
||||||
|
Clicked!
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
controller: class {
|
||||||
|
wasClicked = false
|
||||||
|
btn = null
|
||||||
|
$postLink() {
|
||||||
|
this.btn.on('click', this.handleClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.wasClicked = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const {getByRole, queryByText} = render(`<atl-digest></atl-digest>`)
|
||||||
|
|
||||||
|
const button = getByRole('button')
|
||||||
|
expect(queryByText('Clicked!')).toBeNull()
|
||||||
|
fireEvent.click(button)
|
||||||
|
expect(queryByText('Clicked!')).not.toBeNull()
|
||||||
|
})
|
@ -1,135 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
import * as testUtils from 'react-dom/test-utils'
|
|
||||||
|
|
||||||
const reactAct = testUtils.act
|
|
||||||
const actSupported = reactAct !== undefined
|
|
||||||
|
|
||||||
// act is supported react-dom@16.8.0
|
|
||||||
// so for versions that don't have act from test utils
|
|
||||||
// we do this little polyfill. No warnings, but it's
|
|
||||||
// better than nothing.
|
|
||||||
function actPolyfill(cb) {
|
|
||||||
ReactDOM.unstable_batchedUpdates(cb)
|
|
||||||
ReactDOM.render(<div />, document.createElement('div'))
|
|
||||||
}
|
|
||||||
|
|
||||||
const act = reactAct || actPolyfill
|
|
||||||
|
|
||||||
let youHaveBeenWarned = false
|
|
||||||
let isAsyncActSupported = null
|
|
||||||
|
|
||||||
function asyncAct(cb) {
|
|
||||||
if (actSupported === true) {
|
|
||||||
if (isAsyncActSupported === null) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// patch console.error here
|
|
||||||
const originalConsoleError = console.error
|
|
||||||
console.error = function error(...args) {
|
|
||||||
/* if console.error fired *with that specific message* */
|
|
||||||
/* istanbul ignore next */
|
|
||||||
const firstArgIsString = typeof args[0] === 'string'
|
|
||||||
if (
|
|
||||||
firstArgIsString &&
|
|
||||||
args[0].indexOf(
|
|
||||||
'Warning: Do not await the result of calling ReactTestUtils.act',
|
|
||||||
) === 0
|
|
||||||
) {
|
|
||||||
// v16.8.6
|
|
||||||
isAsyncActSupported = false
|
|
||||||
} else if (
|
|
||||||
firstArgIsString &&
|
|
||||||
args[0].indexOf(
|
|
||||||
'Warning: The callback passed to ReactTestUtils.act(...) function must not return anything',
|
|
||||||
) === 0
|
|
||||||
) {
|
|
||||||
// no-op
|
|
||||||
} else {
|
|
||||||
originalConsoleError.apply(console, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let cbReturn, result
|
|
||||||
try {
|
|
||||||
result = reactAct(() => {
|
|
||||||
cbReturn = cb()
|
|
||||||
return cbReturn
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
console.error = originalConsoleError
|
|
||||||
reject(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result.then(
|
|
||||||
() => {
|
|
||||||
console.error = originalConsoleError
|
|
||||||
// if it got here, it means async act is supported
|
|
||||||
isAsyncActSupported = true
|
|
||||||
resolve()
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
console.error = originalConsoleError
|
|
||||||
isAsyncActSupported = true
|
|
||||||
reject(err)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// 16.8.6's act().then() doesn't call a resolve handler, so we need to manually flush here, sigh
|
|
||||||
|
|
||||||
if (isAsyncActSupported === false) {
|
|
||||||
console.error = originalConsoleError
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (!youHaveBeenWarned) {
|
|
||||||
// if act is supported and async act isn't and they're trying to use async
|
|
||||||
// act, then they need to upgrade from 16.8 to 16.9.
|
|
||||||
// This is a seemless upgrade, so we'll add a warning
|
|
||||||
console.error(
|
|
||||||
`It looks like you're using a version of react-dom that supports the "act" function, but not an awaitable version of "act" which you will need. Please upgrade to at least react-dom@16.9.0 to remove this warning.`,
|
|
||||||
)
|
|
||||||
youHaveBeenWarned = true
|
|
||||||
}
|
|
||||||
|
|
||||||
cbReturn.then(() => {
|
|
||||||
// a faux-version.
|
|
||||||
// todo - copy https://github.com/facebook/react/blob/master/packages/shared/enqueueTask.js
|
|
||||||
Promise.resolve().then(() => {
|
|
||||||
// use sync act to flush effects
|
|
||||||
act(() => {})
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
}, reject)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (isAsyncActSupported === false) {
|
|
||||||
// use the polyfill directly
|
|
||||||
let result
|
|
||||||
act(() => {
|
|
||||||
result = cb()
|
|
||||||
})
|
|
||||||
return result.then(() => {
|
|
||||||
return Promise.resolve().then(() => {
|
|
||||||
// use sync act to flush effects
|
|
||||||
act(() => {})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// all good! regular act
|
|
||||||
return act(cb)
|
|
||||||
}
|
|
||||||
// use the polyfill
|
|
||||||
let result
|
|
||||||
act(() => {
|
|
||||||
result = cb()
|
|
||||||
})
|
|
||||||
return result.then(() => {
|
|
||||||
return Promise.resolve().then(() => {
|
|
||||||
// use sync act to flush effects
|
|
||||||
act(() => {})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default act
|
|
||||||
export {asyncAct}
|
|
||||||
|
|
||||||
/* eslint no-console:0 */
|
|
Loading…
Reference in new issue