diff options
Diffstat (limited to 'test/lib/fixtures/mock-globals.js')
-rw-r--r-- | test/lib/fixtures/mock-globals.js | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/test/lib/fixtures/mock-globals.js b/test/lib/fixtures/mock-globals.js new file mode 100644 index 000000000..02566e575 --- /dev/null +++ b/test/lib/fixtures/mock-globals.js @@ -0,0 +1,321 @@ +const t = require('tap') +const mockGlobals = require('../../fixtures/mock-globals') + +const originals = { + platform: process.platform, + error: console.error, + stderrOn: process.stderr.on, + stderrWrite: process.stderr.write, + shell: process.env.SHELL, + home: process.env.HOME, + argv: process.argv, + env: process.env, + setInterval, +} + +t.test('console', async t => { + await t.test('mocks', async (t) => { + const errors = [] + mockGlobals(t, { + 'console.error': (...args) => errors.push(...args), + }) + + console.error(1) + console.error(2) + console.error(3) + t.strictSame(errors, [1, 2, 3], 'i got my errors') + }) + + t.equal(console.error, originals.error) +}) + +t.test('platform', async (t) => { + t.equal(process.platform, originals.platform) + + await t.test('posix', async (t) => { + mockGlobals(t, { 'process.platform': 'posix' }) + t.equal(process.platform, 'posix') + + await t.test('win32 --> woo', async (t) => { + mockGlobals(t, { 'process.platform': 'win32' }) + t.equal(process.platform, 'win32') + + mockGlobals(t, { 'process.platform': 'woo' }) + t.equal(process.platform, 'woo') + }) + + t.equal(process.platform, 'posix') + }) + + t.equal(process.platform, originals.platform) +}) + +t.test('manual reset', async t => { + let errorHandler, data + + const { reset } = mockGlobals(t, { + 'process.stderr.on': (__, handler) => { + errorHandler = handler + reset['process.stderr.on']() + }, + 'process.stderr.write': (chunk, callback) => { + data = chunk + process.nextTick(() => { + errorHandler({ errno: 'EPIPE' }) + callback() + }) + reset['process.stderr.write']() + }, + }) + + await new Promise((res, rej) => { + process.stderr.on('error', er => er.errno === 'EPIPE' ? res() : rej(er)) + process.stderr.write('hey', res) + }) + + t.equal(process.stderr.on, originals.stderrOn) + t.equal(process.stderr.write, originals.stderrWrite) + t.equal(data, 'hey', 'handles EPIPE errors') + t.ok(errorHandler) +}) + +t.test('reset called multiple times', async (t) => { + await t.test('single reset', async t => { + const { reset } = mockGlobals(t, { 'process.platform': 'z' }) + t.equal(process.platform, 'z') + + reset['process.platform']() + t.equal(process.platform, originals.platform) + + reset['process.platform']() + reset['process.platform']() + reset['process.platform']() + t.equal(process.platform, originals.platform) + }) + + t.equal(process.platform, originals.platform) +}) + +t.test('object mode', async t => { + await t.test('mocks', async t => { + const home = t.testdir() + + mockGlobals(t, { + process: { + stderr: { + on: '1', + }, + env: { + HOME: home, + }, + }, + }) + + t.equal(process.stderr.on, '1') + t.equal(process.env.HOME, home) + }) + + t.equal(process.env.HOME, originals.home) + t.equal(process.stderr.write, originals.stderrWrite) +}) + +t.test('mixed object/string mode', async t => { + await t.test('mocks', async t => { + const home = t.testdir() + + mockGlobals(t, { + 'process.env': { + HOME: home, + TEST: '1', + }, + }) + + t.equal(process.env.HOME, home) + t.equal(process.env.TEST, '1') + }) + + t.equal(process.env.HOME, originals.home) + t.equal(process.env.TEST, undefined) +}) + +t.test('conflicting mixed object/string mode', async t => { + await t.test('same key', async t => { + t.throws( + () => mockGlobals(t, { + process: { + env: { + HOME: '1', + TEST: '1', + NODE_ENV: '1', + }, + stderr: { + write: '1', + }, + }, + 'process.env.HOME': '1', + 'process.stderr.write': '1', + }), + /process.env.HOME,process.stderr.write/ + ) + }) + + await t.test('partial overwrite with replace', async t => { + t.throws( + () => mockGlobals(t, { + process: { + env: { + HOME: '1', + TEST: '1', + NODE_ENV: '1', + }, + stderr: { + write: '1', + }, + }, + 'process.env.HOME': '1', + 'process.stderr.write': '1', + }, { replace: true }), + /process -> process.env.HOME,process.stderr.write/ + ) + }) +}) + +t.test('falsy values', async t => { + await t.test('undefined deletes', async t => { + mockGlobals(t, { 'process.platform': undefined }) + t.notOk(Object.prototype.hasOwnProperty.call(process, 'platform')) + t.equal(process.platform, undefined) + }) + + await t.test('null', async t => { + mockGlobals(t, { 'process.platform': null }) + t.ok(Object.prototype.hasOwnProperty.call(process, 'platform')) + t.equal(process.platform, null) + }) + + t.equal(process.platform, originals.platform) +}) + +t.test('date', async t => { + await t.test('mocks', async t => { + mockGlobals(t, { + 'Date.now': () => 100, + 'Date.prototype.toISOString': () => 'DDD', + }) + t.equal(Date.now(), 100) + t.equal(new Date().toISOString(), 'DDD') + }) + + t.ok(Date.now() > 100) + t.ok(new Date().toISOString().includes('T')) +}) + +t.test('argv', async t => { + await t.test('argv', async t => { + mockGlobals(t, { 'process.argv': ['node', 'woo'] }) + t.strictSame(process.argv, ['node', 'woo']) + }) + + t.strictSame(process.argv, originals.argv) +}) + +t.test('replace', async (t) => { + await t.test('env', async t => { + mockGlobals(t, { 'process.env': { HOME: '1' } }, { replace: true }) + t.strictSame(process.env, { HOME: '1' }) + t.equal(Object.keys(process.env).length, 1) + }) + + await t.test('setInterval', async t => { + mockGlobals(t, { setInterval: 0 }, { replace: true }) + t.strictSame(setInterval, 0) + }) + + t.strictSame(setInterval, originals.setInterval) + t.strictSame(process.env, originals.env) +}) + +t.test('multiple mocks and resets', async (t) => { + const initial = 'a' + const platforms = ['b', 'c', 'd', 'e', 'f', 'g'] + + await t.test('first in, first out', async t => { + mockGlobals(t, { 'process.platform': initial }) + t.equal(process.platform, initial) + + await t.test('platforms', async (t) => { + const resets = platforms.map((platform) => { + const { reset } = mockGlobals(t, { 'process.platform': platform }) + t.equal(process.platform, platform) + return reset['process.platform'] + }).reverse() + + ;[...platforms.reverse()].forEach((platform, index) => { + const reset = resets[index] + const nextPlatform = index === platforms.length - 1 ? initial : platforms[index + 1] + t.equal(process.platform, platform) + reset() + t.equal(process.platform, nextPlatform, 'first reset') + reset() + reset() + t.equal(process.platform, nextPlatform, 'multiple resets are indempotent') + }) + }) + + t.equal(process.platform, initial) + }) + + await t.test('last in,first out', async t => { + mockGlobals(t, { 'process.platform': initial }) + t.equal(process.platform, initial) + + await t.test('platforms', async (t) => { + const resets = platforms.map((platform) => { + const { reset } = mockGlobals(t, { 'process.platform': platform }) + t.equal(process.platform, platform) + return reset['process.platform'] + }) + + resets.forEach((reset, index) => { + // Calling a reset out of order removes it from the stack + // but does not change the descriptor so it should still be the + // last in descriptor until there are none left + const lastPlatform = platforms[platforms.length - 1] + const nextPlatform = index === platforms.length - 1 ? initial : lastPlatform + t.equal(process.platform, lastPlatform) + reset() + t.equal(process.platform, nextPlatform, 'multiple resets are indempotent') + reset() + reset() + t.equal(process.platform, nextPlatform, 'multiple resets are indempotent') + }) + }) + + t.equal(process.platform, initial) + }) + + t.test('reset all', async (t) => { + const { teardown } = mockGlobals(t, { 'process.platform': initial }) + + await t.test('platforms', async (t) => { + const resets = platforms.map((p) => { + const { teardown, reset } = mockGlobals(t, { 'process.platform': p }) + t.equal(process.platform, p) + return [ + reset['process.platform'], + teardown, + ] + }) + + resets.forEach(r => r[1]()) + t.equal(process.platform, initial, 'teardown goes to initial value') + + resets.forEach((r) => r[0]()) + t.equal(process.platform, initial, 'calling resets after teardown does nothing') + }) + + t.equal(process.platform, initial) + teardown() + t.equal(process.platform, originals.platform) + }) +}) |