{"id":13580961,"url":"https://github.com/Tabueeee/puppeteer-request-spy","last_synced_at":"2025-04-06T06:32:21.495Z","repository":{"id":65411535,"uuid":"113701684","full_name":"Tabueeee/puppeteer-request-spy","owner":"Tabueeee","description":"Watch, fake or block requests from puppeteer matching patterns","archived":false,"fork":false,"pushed_at":"2020-10-10T18:05:42.000Z","size":366,"stargazers_count":49,"open_issues_count":0,"forks_count":8,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-03T04:34:25.174Z","etag":null,"topics":["puppeteer","puppeteer-request-spy","request-interceptors"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/Tabueeee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-09T21:14:05.000Z","updated_at":"2022-03-17T08:54:52.000Z","dependencies_parsed_at":"2023-01-23T10:54:59.726Z","dependency_job_id":null,"html_url":"https://github.com/Tabueeee/puppeteer-request-spy","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tabueeee%2Fpuppeteer-request-spy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tabueeee%2Fpuppeteer-request-spy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tabueeee%2Fpuppeteer-request-spy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tabueeee%2Fpuppeteer-request-spy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tabueeee","download_url":"https://codeload.github.com/Tabueeee/puppeteer-request-spy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445652,"owners_count":20939952,"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":["puppeteer","puppeteer-request-spy","request-interceptors"],"created_at":"2024-08-01T15:01:56.796Z","updated_at":"2025-04-06T06:32:21.165Z","avatar_url":"https://github.com/Tabueeee.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# puppeteer-request-spy\n[![Build Status](https://travis-ci.org/Tabueeee/puppeteer-request-spy.svg?branch=master)](https://travis-ci.org/Tabueeee/puppeteer-request-spy)\n[![Coverage Status](https://coveralls.io/repos/github/Tabueeee/puppeteer-request-spy/badge.svg?branch=master)](https://coveralls.io/github/Tabueeee/puppeteer-request-spy?branch=master)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTabueeee%2Fpuppeteer-request-spy.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FTabueeee%2Fpuppeteer-request-spy?ref=badge_shield)\n\u003e With puppeteer-request-spy you can easily watch, fake, modify or block requests from puppeteer matching patterns. \n\n- allows you to write tests verifying specific resources are loaded as expected\n- allows you to exclude unneeded requests from tests, speeding them up significantly\n- allows you to alter requests and responses with custom content and http status\n- avoids conflicts resulting from already aborted / continued or responded requests\n\n## Install\n\n```bash\nnpm install puppeteer-request-spy --save-dev\n```\n\n## Table Of Content\n\n- [Spying On Requests](#usage)\n- [Altering Requests](#altering-requests)\n    - [Modifying Requests](#modifying-requests)\n    - [Redirecting Requests](#redirecting-requests)\n    - [Blocking Requests](#blocking-requests)\n- [Altering Responses](#altering-responses)\n    - [Faking Responses](#faking-responses)\n    - [Modifying Responses](#modifying-responses)\n- [Asynchronous Options](#asynchronous-options)\n- [Interception Order](#requestinterceptor-request-interception-order)\n- [Advanced Usage](#advanced-usage)\n- [Full API](./documentation/API.md)\n\n## Usage\n\n### Spying On Requests With A KeywordMatcher \nFirst create a new `RequestInterceptor` with a `matcher` function and an optional logger. \n```js\nfunction KeywordMatcher(testee, keyword) {\n    return testee.indexOf(keyword) \u003e -1; \n}\n\nlet requestInterceptor = new RequestInterceptor(KeywordMatcher, console);\n```\nNext create a new `RequestSpy` with a `pattern` to be matched against all requests.\n```js\nlet imageSpy = new RequestSpy('/pictures');\n```\nThe `RequestSpy` needs to be registered with the `RequestInterceptor`.\n```js\nrequestInterceptor.addSpy(imageSpy);\n```\nTo use the puppeteer's request event the RequestInterception flag on the page object has to be set to true. \n```js\nawait page.setRequestInterception(true);\n```\nThe `RequestInterceptor` must be registered with puppeteer.\n```js\npage.on('request', requestInterceptor.intercept.bind(requestInterceptor));\n```\nAfter puppeteer's page object finished navigating to any page, you can query the `RequestSpy`.\n ```js\nawait page.goto('https://www.example.com');\n\nassert.ok(!imageSpy.getMatchedRequests()[0].failure());\nassert.ok(imageSpy.hasMatch() \u0026\u0026 imageSpy.getMatchCount() \u003e 0);\n``` \nWhen all responses have been loaded you can also query the response of any matched Request. You can ensure all responses have been loaded by using the networkidle0 option. For further information check the official [puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagegotourl-options). \n```js\nfor (let match of imagesSpy.getMatchedRequests()) {\n    assert.ok(match.response().ok());\n}\n``` \nNote\n\u003e Since unhandled Promise rejections causes the node process to keep running after test failure, the `RequestInterceptor` will catch and log puppeteer's exception, if the `requestInterception` flag is not set.\n\n\n### Altering Requests\n\n#### Modifying Requests\nIntercepted requests can be modified by passing an overrides object to the RequestModifier. The response overrides have to match the Overrides object as specified in the official [puppeteer API](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#httprequestcontinueoverrides).\n\n```js\nlet requestModifier = new RequestModifier('/ajax/some-post-request', {\n  url: '/ajax/some-get-request',\n  method: 'GET',\n  postData: '',\n  headers: {}\n});                  \n\nrequestInterceptor.addRequestModifier(requestModifier);\n```\n\n#### Redirecting Requests\nIf you just want to replace the url of an intercepted request, you can use the RequestRedirector.\n\n```js\nlet requestRedirector = new RequestRedirector('/ajax/some-request', 'some/new/url');                  \n\nrequestInterceptor.addRequestModifier(requestRedirector);\n```\n\nThe RequestRedirector uses the IRequestModifier interface.\n\n#### Blocking Requests    \nOptionally you can add `patterns` to block requests. Blocking requests speeds up page load since no data is loaded. Blocking requests takes precedence over overriding requests or faking responses, so any request blocked will not be replaced even when matching a `ResponseFaker`. Blocked or faked requests will still be counted by a `RequestSpy` with a matching pattern.  \n\n```js\nrequestInterceptor.block(['scripts', 'track', '.png']);      \n```\n\n### Altering Responses\n\n#### Faking Responses\nThe response of intercepted requests can be replaced by adding a ResponseFaker to the RequestInterceptor. The fake response has to match the Response object as specified in the official [puppeteer API](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#httprequestrespondresponse).\n```js\nlet responseFaker = new ResponseFaker('/ajax/some-request', {\n    status: 200,\n    contentType: 'application/json',\n    body: JSON.stringify({successful: false, payload: []})\n});\n\nrequestInterceptor.addFaker(responseFaker);\n```\nFor further details on how to replace different formats of data like images, text or html, please refer to the examples provided in the [github repository](./examples/fake-test.spec.js).\n\n#### Modifying Responses\nIt's also possible to replace the content of a response instead of replacing it:\n\n```js\nlet responseModifier = new ResponseModifier('/ajax/some-request', (response, request) =\u003e {\n    return response.replace('\u003c/head\u003e', '\u003cscript\u003e\u003c/script\u003e\u003c/head\u003e');\n});\n\nrequestInterceptor.addFaker(responseModifier);\n```                   \n\nNote:\n\u003e The request is currently loaded in the node environment, not the browser environment.\n\nThe ResponseModifier uses the IResponseFaker interface.\n\n### Asynchronous Options\n\nAll ResponseFakers and ResponseModifiers now accept a callback for resolving the passed options. This callback can also be async or return a promise. \n\n```js\n// static options\nlet requestRedirector = new RequestRedirector(\n    '/ajax/some-request',\n    'some/other/url'\n);                  \n\n// callback options\nlet requestModifier = new RequestModifier(\n    '/ajax/some-request',\n    (matchedRequest) =\u003e ({url: '/ajax/some-different-request'})\n);  \n  \n// async callback options\nlet requestRedirector = new RequestRedirector(\n    '/ajax/some-request',\n     async (matchedRequest) =\u003e 'some/new/url'\n);   \n               \n// promise callback options\nlet responseFaker = new ResponseFaker(\n    '/ajax/some-request',\n    (matchedRequest) =\u003e Promise.resolve(({\n        status: 200, \n        contentType: 'application/json',\n        body: JSON.stringify({successful: false, payload: []})\n    }))\n);                                                        \n```\n\n## RequestInterceptor Request Interception Order:\n\n![image](./documentation/activity.png)\n\n## Advanced Usage\n\nAs long as you follow the interfaces provided in the [github repository](./src/interface) you can create your own Spies, Fakers, Modifiers or Blocker.\n\n````js\nlet interceptor = new RequestInterceptor(\n    (testee, pattern) =\u003e testee.indexOf(pattern) \u003e -1\n);\n\nlet count = 0;\ninterceptor.addSpy({\n    isMatchingRequest: (_request, _matcher) =\u003e true,\n    addMatch: (_request) =\u003e count++\n});\n\ninterceptor.addFaker({\n    isMatchingRequest: (_request, _matcher) =\u003e true,\n    getResponseFake: (request) =\u003e ({body: ''})\n});\n\ninterceptor.addRequestModifier({\n    isMatchingRequest: (_request, _matcher) =\u003e true,\n    getOverride: (interceptedRequest) =\u003e ({url: ''})\n});\n\ninterceptor.setRequestBlocker({\n    shouldBlockRequest: (_request, _matcher) =\u003e true,\n    clearUrlsToBlock: () =\u003e undefined,\n    addUrlsToBlock: (urlsToBlock) =\u003e undefined\n});\n````\n\n### Minimatch\npuppeteer-request-spy works great with [minimatch](https://github.com/isaacs/minimatch), it can be passed as the `matcher` function.\n```js\nconst minimatch = require('minimatch');\n\nlet cssSpy = new RequestSpy('**/*.css');\nlet responseFaker = new ResponseFaker('**/*.jpg', someFakeResponse);\n                                                        \nlet requestInterceptor = new RequestInterceptor(minimatch);  \nrequestInterceptor.addFaker(responseFaker);\nrequestInterceptor.addSpy(cssSpy);   \nrequestInterceptor.block('**/*.js');\n\nawait page.setRequestInterception(true);\npage.on('request', requestInterceptor.intercept.bind(requestInterceptor));  \nawait page.goto('https://www.example.com');\n                                                 \nassert.ok(cssSpy.hasMatch() \u0026\u0026 cssSpy.getMatchCount() \u003e 0);\nfor (let matchedRequest of cssSpy.getMatchedRequests()) {\n    assert.ok(matchedRequest.response().status() === 200);\n}\n```\n# API\n\nFull API can be found [here](./documentation/API.md).\n\n# Examples\n\nThere are some usage examples included in the [github repository](./examples). Check them out to get started with writing a simple test with puppeteer and puppeteer-request-spy.\n\n# Related\n - [minimatch](https://github.com/isaacs/minimatch) - For easily matching path-like strings to patterns.\n - [puppeteer](https://github.com/GoogleChrome/puppeteer) - Control chrome in headless mode with puppeteer for automated testing.\n\n# License\nMIT\n\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTabueeee%2Fpuppeteer-request-spy.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FTabueeee%2Fpuppeteer-request-spy?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTabueeee%2Fpuppeteer-request-spy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTabueeee%2Fpuppeteer-request-spy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTabueeee%2Fpuppeteer-request-spy/lists"}