Skip to content

Commit

Permalink
feat: actually working polly env
Browse files Browse the repository at this point in the history
  • Loading branch information
ChALkeR committed Jul 13, 2024
1 parent 34d852b commit 3594583
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 24 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"src/dark.cjs",
"src/jest.js",
"src/jest.config.js",
"src/jest.environment.js",
"src/jest.fn.js",
"src/jest.mock.js",
"src/jest.snapshot.js",
Expand Down
30 changes: 6 additions & 24 deletions src/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import path from 'node:path'
import { createRequire } from 'node:module'
import { specialEnvironments } from './jest.environment.js'

const files = process.argv.slice(1)
const baseDir = files.length === 1 ? path.dirname(path.resolve(files[0])) : undefined
Expand Down Expand Up @@ -69,32 +70,10 @@ const normalizeJestConfig = (config) => ({
},
})

const specialEnvs = {
__proto__: null,

'setup-polly-jest/jest-environment-node': (require) => {
const { Polly } = require('@pollyjs/core')
const { JestPollyGlobals } = require('setup-polly-jest/lib/common')
const pollyGlobals = new JestPollyGlobals(globalThis)
pollyGlobals.isJestPollyEnvironment = true

beforeEach((t) => {
if (!pollyGlobals.isPollyActive) return
pollyGlobals.pollyContext.polly = new Polly(t.fullName, pollyGlobals.pollyContext.options)
})

afterEach(async () => {
if (!pollyGlobals.pollyContext.polly) return
await pollyGlobals.pollyContext.polly.stop()
pollyGlobals.pollyContext.polly = null
})
},
}

function verifyJestConfig(c) {
assert(!configUsed, 'Can not apply new config as the current one was already used')

if (!Object.hasOwn(specialEnvs, c.testEnvironment)) {
if (!Object.hasOwn(specialEnvironments, c.testEnvironment)) {
assert.equal(c.testEnvironment, 'node', 'Only "node" testEnvironment is supported')
}

Expand Down Expand Up @@ -147,7 +126,10 @@ export async function installJestEnvironment(jestGlobals) {

const require = createRequire(config.rootDir)

if (Object.hasOwn(specialEnvs, c.testEnvironment)) specialEnvs[c.testEnvironment](require)
if (Object.hasOwn(specialEnvironments, c.testEnvironment)) {
specialEnvironments[c.testEnvironment](require, jestGlobals, c.testEnvironmentOptions)
}

for (const file of c.setupFiles || []) require(file)
for (const file of c.setupFilesAfterEnv || []) require(file)

Expand Down
93 changes: 93 additions & 0 deletions src/jest.environment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Shoult not import src/ stuff here, as this goes into runner too (to check config)

function getTestNamePath(t, { require }) {
// No implementation in Node.js yet, will have to PR
if (t.fullName) return t.fullName.split(' > ')

// We are on Node.js < 22.3.0 where even t.fullName doesn't exist yet, polyfill
const namePath = Symbol('namePath')
try {
if (t[namePath]) return t[namePath]

// Sigh, ok, whatever
const { Test } = require('node:internal/test_runner/test')

const usePathName = Symbol('usePathName')
const restoreName = Symbol('restoreName')
Test.prototype.getNamePath = function () {
if (this === this.root) return []
return [...(this.parent?.getNamePath() || []), this.name]
}

const diagnostic = Test.prototype.diagnostic
Test.prototype.diagnostic = function (...args) {
if (args[0] === usePathName) {
this[restoreName] = this.name
this.name = this.getNamePath()
return
}

if (args[0] === restoreName) {
this.name = this[restoreName]
delete this[restoreName]
return
}

return diagnostic.apply(this, args)
}

const TestContextProto = Object.getPrototypeOf(t)
Object.defineProperty(TestContextProto, namePath, {
get() {
this.diagnostic(usePathName)
const result = this.name
this.diagnostic(restoreName)
return result
},
})

return t[namePath]
} catch {}

return [t.name] // last resort
}

export const specialEnvironments = {
__proto__: null,

// Reproduces setup-polly-jest/jest-environment-node ad hacks into 'setup-polly-jest'.pollyJest
'setup-polly-jest/jest-environment-node': (require, jestGlobals) => {
const { Polly } = require('@pollyjs/core')
const pollyJest = require('setup-polly-jest')
const { JestPollyGlobals, createPollyContextAccessor } = require('setup-polly-jest/lib/common')
const pollyGlobals = new JestPollyGlobals(globalThis)
pollyGlobals.isJestPollyEnvironment = true
pollyJest.setupPolly = (options) => {
if (!pollyGlobals.isJestPollyEnvironment) return

jestGlobals.beforeAll(() => {
pollyGlobals.isPollyActive = true
pollyGlobals.pollyContext.options = options
})

jestGlobals.afterAll(() => {
pollyGlobals.isPollyActive = false
pollyGlobals.pollyContext.options = null
})

return createPollyContextAccessor(pollyGlobals)
}

jestGlobals.beforeEach((t) => {
if (!pollyGlobals.isPollyActive) return
const name = getTestNamePath(t, { require }).join('/')
pollyGlobals.pollyContext.polly = new Polly(name, pollyGlobals.pollyContext.options)
})

jestGlobals.afterEach(async () => {
if (!pollyGlobals.pollyContext.polly) return
await pollyGlobals.pollyContext.polly.stop()
pollyGlobals.pollyContext.polly = null
})
},
}

0 comments on commit 3594583

Please sign in to comment.