Skip to content

Commit

Permalink
feat: read snapshot configuration from jest config in package.json
Browse files Browse the repository at this point in the history
  • Loading branch information
ChALkeR committed Jul 12, 2024
1 parent 9cdb5d4 commit 66f315e
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"bin/jest.js",
"src/dark.cjs",
"src/jest.js",
"src/jest.config.js",
"src/jest.fn.js",
"src/jest.mock.js",
"src/jest.snapshot.js",
Expand Down
41 changes: 41 additions & 0 deletions src/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import path from 'node:path'

const files = process.argv.slice(1)
const baseDir = files.length === 1 ? path.dirname(path.resolve(files[0])) : undefined

async function getJestConfig(dir) {
if (!dir) return

try {
const pkg = JSON.parse(await readFile(path.resolve(dir, 'package.json'), 'utf8'))
if (pkg.jest) return pkg.jest
} catch {}

const parent = path.dirname(dir)
return parent === dir ? undefined : getJestConfig(parent)
}

const normalizeJestConfig = (config) => ({
testEnvironment: 'node',
snapshotSerializers: [],
...config,
snapshotFormat: {
// jest-snapshot defaults
indent: 2,
escapeRegex: true,
printFunctionName: false,
// defaults from https://jestjs.io/docs/configuration#snapshotformat-object
escapeString: false,
printBasicPrototype: false,
// user config
...config?.snapshotFormat,
// not overridable per doc
compareKeys: undefined,
},
})

export const config = normalizeJestConfig(await getJestConfig(baseDir))

assert.equal(config.testEnvironment, 'node', 'Only "node" testEnvironment is supported')
5 changes: 4 additions & 1 deletion src/jest.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import { jestfn } from './jest.fn.js'

const files = process.argv.slice(1)
const baseUrl = files.length === 1 && existsSync(files[0]) ? normalize(files[0]) : undefined
const require = createRequire(baseUrl || import.meta.url)
const mapMocks = new Map()
const mapActual = new Map()

const require = createRequire(baseUrl || import.meta.url)

export const relativeRequire = require

export function resolveModule(name) {
assert(baseUrl || /^[@a-zA-Z]/u.test(name), 'Mocking relative paths is not possible')
return require.resolve(name)
Expand Down
16 changes: 14 additions & 2 deletions src/jest.snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,27 @@ import { expect } from 'expect'
import { format } from 'pretty-format'
import assert from 'node:assert/strict'
import { basename, dirname, join } from 'node:path'
import { config } from './jest.config.js'
import { relativeRequire } from './jest.mock.js'

const { snapshotFormat, snapshotSerializers } = config
const plugins = []
const opts = { indent: 2, escapeRegex: true, printFunctionName: false, printBasicPrototype: false }
const serialize = (val) => format(val, { ...opts, plugins }).replaceAll(/\r\n|\r/gu, '\n')
const serialize = (val) => format(val, { ...snapshotFormat, plugins }).replaceAll(/\r\n|\r/gu, '\n')

let serializersAreSetup = false
let snapshotsAreJest = false

function maybeSetupSerializers() {
if (serializersAreSetup) return
// empty require and serializers should not let this fail, non-empty serializers and empty require should
if (snapshotSerializers.length > 0) plugins.push(...snapshotSerializers.map(relativeRequire))
serializersAreSetup = true
}

// We want to setup snapshots to behave like jest only when first used from jest API
function maybeSetupJestSnapshots() {
if (snapshotsAreJest) return
maybeSetupSerializers()
const require = createRequire(import.meta.url)
const { snapshot } = require('node:test') // attempt to load them, and we need to do that synchronously
assert(snapshot, 'snapshots require Node.js >=22.3.0')
Expand Down Expand Up @@ -68,6 +79,7 @@ const throws = (fn, check) =>
const snapInline = (obj, inline) => {
assert(inline !== undefined, 'Inline Snapshots generation is not supported')
assert(typeof inline === 'string')
maybeSetupSerializers()
getAssert().strictEqual(serialize(obj).trim(), inline.trim())
}

Expand Down

0 comments on commit 66f315e

Please sign in to comment.