Skip to content

Commit

Permalink
Allow the display of messages without failing (#48)
Browse files Browse the repository at this point in the history

Co-authored-by: Valentin Hervieu <[email protected]>
  • Loading branch information
vernak2539 and ValentinH authored Apr 4, 2024
1 parent 3ed9387 commit 8859c1b
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 14 deletions.
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Utility to make jest tests fail when `console.error()`, `console.warn()`, etc. a

[![version][version-badge]][package] [![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs]


## What problem is this solving?

Jest doesn't fail the tests when there is a `console.error`. In large codebase, we can end up with the test output overloaded by a lot of errors, warnings, etc..
Expand Down Expand Up @@ -115,14 +114,41 @@ Use this to make a test fail when a `console.warn()` is logged.
- Type: `boolean`
- Default: `true`
### allowMessage
```ts
// signature
type allowMessage = (
message: string,
methodName: 'assert' | 'debug' | 'error' | 'info' | 'log' | 'warn',
context: { group: string; groups: string[] }
) => boolean
```
This function is called for every console method supported by this utility.
If `true` is returned, the message will show in the console and the test won't fail.
Example:
```ts
failOnConsole({
allowMessage: (errorMessage) => {
if (/An expected error/.test(errorMessage)) {
return true
}
return false
},
})
```
### silenceMessage
```ts
// signature
type silenceMessage = (
message: string,
methodName: 'assert' | 'debug' | 'error' | 'info' | 'log' | 'warn',
context: { group: string, groups: string[] }
context: { group: string; groups: string[] }
) => boolean
```
Expand Down Expand Up @@ -162,7 +188,7 @@ failOnConsole({
if (ignoreNameList.includes(testName)) {
return true
}

return false
},
})
Expand Down
22 changes: 15 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
declare namespace init {
type ConsoleMethodName = 'assert' | 'debug' | 'error' | 'info' | 'log' | 'warn'
type InitOptions = {
/**
* This function lets you define a custom error message. The methodName is the method
* that caused the error, bold is a function that lets you bold subsets of your message.
* example: (methodName, bold) => `console.${methodName} is not ${bold('allowed')}`
*/
errorMessage?: (
methodName: 'assert' | 'debug' | 'error' | 'info' | 'log' | 'warn',
bold: (string: string) => string
) => string
errorMessage?: (methodName: ConsoleMethodName, bold: (string: string) => string) => string

/** @default false */
shouldFailOnAssert?: boolean
Expand All @@ -29,21 +27,31 @@ declare namespace init {
shouldFailOnWarn?: boolean

/**
* This function is called for every console warn/error.
* This function is called for every console methods.
* If true is returned, the message will not show in the console
* and the test won't fail.
*/
silenceMessage?: (
message: string,
methodName: 'assert' | 'debug' | 'error' | 'info' | 'log' | 'warn',
context: { group: string, groups: string[] }
methodName: ConsoleMethodName,
context: { group: string; groups: string[] }
) => boolean

/**
* This function is called for every test setup and teardown to determine if the test should
* skip console checks from this package or not.
*/
skipTest?: (args: { testName: string; testPath: string }) => boolean

/**
* This function is called for every console methods.
* If true is returned, the message will not cause the tests to fail and will be logged to the console.
*/
allowMessage?: (
message: string,
methodName: ConsoleMethodName,
context: { group: string; groups: string[] }
) => boolean
}
}

Expand Down
17 changes: 13 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const init = ({
shouldFailOnWarn = true,
skipTest,
silenceMessage,
allowMessage,
} = {}) => {
const flushUnexpectedConsoleCalls = (methodName, unexpectedConsoleCallStacks) => {
if (unexpectedConsoleCallStacks.length > 0) {
Expand Down Expand Up @@ -50,17 +51,27 @@ const init = ({

const patchConsoleMethod = (methodName) => {
const unexpectedConsoleCallStacks = []
const originalMethod = console[methodName]

const captureMessage = (format, ...args) => {
const message = util.format(format, ...args)
const context = { group: groups[groups.length - 1], groups }

if (
silenceMessage &&
silenceMessage(message, methodName, { group: groups[groups.length - 1], groups })
typeof silenceMessage === 'function' &&
silenceMessage(message, methodName, context)
) {
return
}

if (
typeof allowMessage === 'function' &&
allowMessage(message, methodName, context)
) {
originalMethod(format, ...args)
return
}

// Capture the call stack now so we can warn about it later.
// The call stack has helpful information for the test author.
// Don't throw yet though b'c it might be accidentally caught and suppressed.
Expand Down Expand Up @@ -98,8 +109,6 @@ const init = ({

const newMethod = methods[methodName] || captureMessage

let originalMethod = console[methodName]

const canSkipTest = () => {
const currentTestState = expect.getState()
const testName = currentTestState.currentTestName
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/allow-message/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = () => {
console.error('my error message that I do not control')
}
7 changes: 7 additions & 0 deletions tests/fixtures/allow-message/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const consoleError = require('.')

describe('console.error display message but not fail (allowMessage)', () => {
it('does not throw', () => {
expect(consoleError).not.toThrow()
})
})
3 changes: 3 additions & 0 deletions tests/fixtures/allow-message/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js'],
}
8 changes: 8 additions & 0 deletions tests/fixtures/allow-message/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const failOnConsole = require('../../..')

failOnConsole({
shouldFailOnError: true,
allowMessage: (msg, methodName) => {
return methodName === 'error' && /my error message that I do not control/.test(msg)
},
})
9 changes: 9 additions & 0 deletions tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,13 @@ describe('jest-fail-on-console', () => {

expect(stderr).toEqual(expect.stringContaining(passString('silence-by-nested-group')))
})

it('does not error if message is silenced with `allowMessage`', async () => {
const { stderr, stdout } = await runFixture('allow-message')

expect(stdout).toContain('console.error');
expect(stdout).toContain('my error message that I do not control');

expect(stderr).toEqual(expect.stringContaining(passString('allow-message')))
})
})

0 comments on commit 8859c1b

Please sign in to comment.