{"id":13846952,"url":"https://github.com/tkrotoff/throw-on","last_synced_at":"2026-02-26T17:03:03.955Z","repository":{"id":43743774,"uuid":"440266442","full_name":"tkrotoff/throw-on","owner":"tkrotoff","description":"Throw on console.error/warn \u0026 fetch","archived":false,"fork":false,"pushed_at":"2023-03-11T14:19:26.000Z","size":1428,"stargazers_count":24,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-15T18:59:35.519Z","etag":null,"topics":["console","fetch","react","throw","xmlhttprequest"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tkrotoff.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-12-20T18:17:45.000Z","updated_at":"2023-10-02T14:09:51.000Z","dependencies_parsed_at":"2024-01-15T20:47:35.146Z","dependency_job_id":"5a488bf7-555b-4680-8a0a-eda413f57c67","html_url":"https://github.com/tkrotoff/throw-on","commit_stats":{"total_commits":104,"total_committers":1,"mean_commits":104.0,"dds":0.0,"last_synced_commit":"13c5c86a8309391b93d49026da2084c7b75ff9ce"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/tkrotoff/throw-on","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrotoff%2Fthrow-on","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrotoff%2Fthrow-on/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrotoff%2Fthrow-on/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrotoff%2Fthrow-on/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkrotoff","download_url":"https://codeload.github.com/tkrotoff/throw-on/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkrotoff%2Fthrow-on/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261325194,"owners_count":23141861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console","fetch","react","throw","xmlhttprequest"],"created_at":"2024-08-04T18:00:50.956Z","updated_at":"2026-02-26T17:02:58.898Z","avatar_url":"https://github.com/tkrotoff.png","language":"JavaScript","readme":"# throw-on\n\n[![npm version](https://badge.fury.io/js/throw-on.svg)](https://www.npmjs.com/package/throw-on)\n[![Node.js CI](https://github.com/tkrotoff/throw-on/workflows/Node.js%20CI/badge.svg?branch=master)](https://github.com/tkrotoff/throw-on/actions)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/a1d8efe9ec84a918822d/test_coverage)](https://codeclimate.com/github/tkrotoff/throw-on/test_coverage)\n[![Bundle size](https://badgen.net/bundlephobia/minzip/throw-on)](https://bundlephobia.com/result?p=throw-on)\n[![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![Airbnb Code Style](https://badgen.net/badge/code%20style/airbnb/ff5a5f?icon=airbnb)](https://github.com/airbnb/javascript)\n\nForce console.error/warn and network requests to fail.\n\n- Tiny: less than 100 lines of code\n- No dependencies\n- Fully tested\n- Written in TypeScript\n- Works with Node.js and browsers\n- Generic: not specific to React or Jest\n\nThis is an alternative to https://github.com/ValentinH/jest-fail-on-console\n\n## Why?\n\nDo you have warnings like _\"An update inside a test was not wrapped in act\"_ or _\"Can't perform a React state update on an unmounted component\"_ when running or testing your React app? Are your tests performing network requests when they shouldn't?\n\nSolution: throw whenever there is a warning (e.g. console.error/warn) or a network request that isn't mocked\n\n- The sooner a test fails, the easier it is to fix\n- Improve code quality (like an ESLint rule but at run/test time)\n\nthrow-on still displays the original console message before throwing an exception with the message `throw-on console.[METHOD]: [ORIGINAL_MESSAGE_SHORTEN]`\n\nResult:\n\n- before (test passes)\n\n  ![before](doc/was-not-wrapped-in-act-original.png)\n\n- after (test fails)\n\n  ![after](doc/was-not-wrapped-in-act-throwOnConsoleError.png)\n\n## Usage\n\n### In your tests\n\n`npm install --save-dev throw-on`\n\n```TypeScript\n// Inside jest.setup.js (Jest setupFilesAfterEnv option) for example\n\nimport {\n  throwOnConsole,\n  throwOnFetch,\n  throwOnXMLHttpRequestOpen\n} from 'throw-on';\n\nthrowOnConsole('assert');\nthrowOnConsole('error');\nthrowOnConsole('warn');\nthrowOnFetch();\nthrowOnXMLHttpRequestOpen();\n```\n\n### In the browser\n\n`npm install throw-on`\n\n```TypeScript\n// Inside your entry file (something like index.js, app.js, pages/_app.js)\n\nif (process.env.NODE_ENV !== 'production') { // You probably don't want this in production\n  const { throwOnConsole } = await import('throw-on');\n  throwOnConsole('assert');\n  throwOnConsole('error');\n  throwOnConsole('warn');\n}\n\nrender(\u003cMyApp /\u003e, document.getElementById('app'));\n```\n\n### Make it your own\n\nCopy-paste [throwOnConsole.ts](src/throwOnConsole.ts) and/or [throwOnFetch.ts](src/throwOnFetch.ts) and/or [throwOnXMLHttpRequestOpen.ts](src/throwOnXMLHttpRequestOpen.ts) into your source code.\n\n### Platform support\n\nTested with Node.js \u003e= 14, might work with Node.js 12.\n\nTranspilation to ES5 (via Babel for example) is needed for non-modern browsers.\n\n## API\n\n```TypeScript\ntype Options = {\n  /**\n   * Messages to ignore (won't throw), each message to ignore can be a substring or a regex.\n   *\n   * Empty list by default.\n   */\n  ignore?: (string | RegExp)[];\n};\n\ntype ConsoleMethodName = 'assert' | 'error' | 'warn' | 'info' | 'log' | 'dir' | 'debug';\n\n/**\n * Makes console method to throw if called.\n */\nfunction throwOnConsole(methodName: ConsoleMethodName, options: Options = {}): void;\n\n/**\n * Restores the original console method implementation.\n */\nfunction restoreConsole(methodName: ConsoleMethodName): void;\n\n/**\n * Makes fetch to throw if called.\n */\nfunction throwOnFetch(): void;\n\n/**\n * Restores the original fetch implementation.\n */\nfunction restoreFetch(): void;\n\n/**\n * Makes XMLHttpRequest.open to throw if called.\n */\nfunction throwOnXMLHttpRequestOpen(): void;\n\n/**\n * Restores the original XMLHttpRequest.open implementation.\n */\nfunction restoreXMLHttpRequestOpen(): void;\n```\n\n## What about valid console messages?\n\nIf a `console.error()` is expected, then you should assert for it:\n\n```TypeScript\ntest('should log an error', () =\u003e {\n  const spy = jest.spyOn(console, 'error').mockImplementation();\n\n  // ...\n\n  expect(spy).toHaveBeenCalledTimes(1);\n  expect(spy).toHaveBeenCalledWith('your error message');\n\n  spy.mockRestore();\n});\n```\n\n## Limitations\n\n- Be careful: it adds a line to Jest stack trace, messing up the [codeframe](https://github.com/facebook/jest/issues/8819):\n\n  ```\n  at console.\u003ccomputed\u003e (src/throwOnConsole.ts:69:7) \u003c===\n  at console.error (node_modules/@testing-library/react-hooks/lib/core/console.js:19:7)\n  at printWarning (node_modules/react-dom/cjs/react-dom.development.js:67:30)\n  at error (node_modules/react-dom/cjs/react-dom.development.js:43:5)\n  ...\n  ```\n\n  Use `restoreConsole()` to get the original codeframe\n\n- Be careful: the shorten exception message does not always match the original console message (because of [React error boundary](https://reactjs.org/docs/error-boundaries.html)?)\n\n- Libraries that console.\\* exceptions \u003csup\u003e[1](https://github.com/expressjs/express/blob/4.17.3/lib/application.js#L630)\u003c/sup\u003e \u003csup\u003e[2](https://github.com/expressjs/api-error-handler/blob/1.0.0/index.js#L22)\u003c/sup\u003e introduce an infinite loop:\n  throw-on intercepts the console.\\* call and throws an exception =\u003e the library catches the exception and console.\\* it, ect.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkrotoff%2Fthrow-on","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkrotoff%2Fthrow-on","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkrotoff%2Fthrow-on/lists"}