Skip to content

Commit bc48f92

Browse files
authored
fix: address timeout issue with mocked timers (Revert #2880) (#2902)
This reverts commit fb112f3.
1 parent e4390b8 commit bc48f92

File tree

7 files changed

+20
-345
lines changed

7 files changed

+20
-345
lines changed

.eslintrc.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ overrides:
2222
mocha: true
2323
rules:
2424
mocha/no-exclusive-tests: 'error'
25-
- files:
26-
- 'tests_jest/**/*.js'
27-
globals:
28-
jest: true
2925

3026
rules:
3127
# TODO These are included in standard and should be cleaned up and turned on.

README.md

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ For instance, if a module performs HTTP requests to a CouchDB server or makes HT
9191
- [Requests made by ES Modules are not intercepted](#requests-made-by-es-modules-are-not-intercepted)
9292
- [Axios](#axios)
9393
- [Memory issues with Jest](#memory-issues-with-jest)
94-
- [Fake timers](#fake-timers)
9594
- [Debugging](#debugging)
9695
- [Contributing](#contributing)
9796
- [Contributors](#contributors)
@@ -1614,86 +1613,6 @@ One of the core principles of [Jest](https://jestjs.io/) is that it runs tests i
16141613
It does this by manipulating the modules cache of Node in a way that conflicts with how Nock monkey patches the builtin `http` and `https` modules.
16151614
[Related issue with more details](https://github.com/nock/nock/issues/1817).
16161615

1617-
### Fake timers
1618-
1619-
### Jest
1620-
1621-
To use `nock` in conjunction with `jest` fake timers, make sure you're using the "async" functions when advancing the
1622-
timers, such as `jest.advanceTimersByTimeAsync()` or `jest.runAllTimersAsync()`. Otherwise, the timers will not be
1623-
advanced correctly and you'll experience a timeout in your tests.
1624-
1625-
```js
1626-
test('should mock a request with fake timers', async () => {
1627-
jest.useFakeTimers()
1628-
1629-
const scope = nock('https://example.com')
1630-
.get('/path')
1631-
.delay(1000)
1632-
.reply(200, 'response')
1633-
1634-
// Simulate a request
1635-
const request = got('https://example.com/path')
1636-
1637-
// Fast-forward time
1638-
await jest.advanceTimersByTimeAsync(1000)
1639-
1640-
// Or advance all timers
1641-
await jest.runAllTimersAsync()
1642-
1643-
// Wait for the request to complete
1644-
const response = await request
1645-
1646-
expect(response.body).toBe('response')
1647-
jest.useRealTimers() // Restore real timers after the test
1648-
scope.done()
1649-
})
1650-
```
1651-
1652-
In case you don't need testing delays, you can instruct `jest` to advance the timers automatically using the
1653-
`advanceTimers` option
1654-
1655-
```js
1656-
jest.useFakeTimers({ advanceTimers: true })
1657-
```
1658-
1659-
### Sinon
1660-
1661-
In a similar way to `jest`, if you are using `sinon` fake timers, you should use the `clock.tickAsync()` or
1662-
`clock.runAllAsync()` methods to advance the timers correctly.
1663-
1664-
```js
1665-
it('should us sinon timers', async () => {
1666-
clock = sinon.useFakeTimers()
1667-
const scope = nock('https://example.com')
1668-
.get('/path')
1669-
.delay(1000)
1670-
.reply(200, 'response')
1671-
1672-
// Simulate a request
1673-
const request = got('https://example.com/path')
1674-
1675-
// Fast-forward time
1676-
await clock.tickAsync(1000)
1677-
1678-
// Or run all timers
1679-
await clock.runAllAsync()
1680-
1681-
// Wait for the request to complete
1682-
const response = await request
1683-
1684-
expect(response.body).toBe('response')
1685-
clock.restore()
1686-
scope.done()
1687-
})
1688-
```
1689-
1690-
Same applies for `sinon`, if you don't need testing delays, you can instruct `sinon` to advance the timers automatically
1691-
using the `shouldAdvanceTime` option
1692-
1693-
```js
1694-
clock = sinon.useFakeTimers({ shouldAdvanceTime: true })
1695-
```
1696-
16971616
## Debugging
16981617

16991618
Nock uses node internals [`debuglog`](https://nodejs.org/api/util.html#utildebuglogsection-callbackg), so just run with environmental variable `NODE_DEBUG` set to `nock:*`.

lib/common.js

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const { common: debug } = require('./debug')
4+
const timers = require('timers')
45
const url = require('url')
56
const util = require('util')
67
const http = require('http')
@@ -520,36 +521,24 @@ function deepEqual(expected, actual) {
520521
const timeouts = new Set()
521522
const immediates = new Set()
522523

523-
const _setImmediate = (callback, ...timerArgs) => {
524-
const cb = (...callbackArgs) => {
525-
try {
526-
// eslint-disable-next-line n/no-callback-literal
527-
callback(...callbackArgs)
528-
} finally {
529-
immediates.delete(id)
530-
}
531-
}
532-
533-
const id = setImmediate(cb, 0, ...timerArgs)
534-
535-
immediates.add(id)
536-
return id
537-
}
538-
539-
const _setTimeout = (callback, ...timerArgs) => {
540-
const cb = (...callbackArgs) => {
541-
try {
542-
// eslint-disable-next-line n/no-callback-literal
543-
callback(...callbackArgs)
544-
} finally {
545-
timeouts.delete(id)
524+
const wrapTimer =
525+
(timer, ids) =>
526+
(callback, ...timerArgs) => {
527+
const cb = (...callbackArgs) => {
528+
try {
529+
// eslint-disable-next-line n/no-callback-literal
530+
callback(...callbackArgs)
531+
} finally {
532+
ids.delete(id)
533+
}
546534
}
535+
const id = timer(cb, ...timerArgs)
536+
ids.add(id)
537+
return id
547538
}
548539

549-
const id = setTimeout(cb, ...timerArgs)
550-
timeouts.add(id)
551-
return id
552-
}
540+
const setTimeout = wrapTimer(timers.setTimeout, timeouts)
541+
const setImmediate = wrapTimer(timers.setImmediate, immediates)
553542

554543
function clearTimer(clear, ids) {
555544
ids.forEach(clear)
@@ -725,8 +714,8 @@ module.exports = {
725714
percentDecode,
726715
percentEncode,
727716
removeAllTimers,
728-
setImmediate: _setImmediate,
729-
setTimeout: _setTimeout,
717+
setImmediate,
718+
setTimeout,
730719
stringifyRequest,
731720
convertFetchRequestToClientRequest,
732721
}

tests/got/test_fake_timer.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ it('should still return successfully when fake timer is enabled', async () => {
99
const clock = fakeTimers.install()
1010
const scope = nock('http://example.test').get('/').reply()
1111

12-
const promise = got('http://example.test')
13-
14-
await clock.runAllAsync() // Run all fake timers to ensure all scheduled tasks are executed
15-
16-
await promise
12+
await got('http://example.test')
1713

1814
clock.uninstall()
1915
scope.done()

tests/got/test_reply_headers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ describe('`replyDate()`', () => {
427427
const scope = nock('http://example.test').replyDate().get('/').reply()
428428

429429
const req = got('http://example.test/')
430-
await clock.runAllAsync()
430+
clock.tick()
431431
const { headers } = await req
432432
const date = new Date()
433433
expect(headers).to.include({ date: date.toUTCString() })

tests/test_fake_timers.js

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)