{"id":20290601,"url":"https://github.com/gocardless/stubby","last_synced_at":"2025-09-02T10:42:47.381Z","repository":{"id":773567,"uuid":"35431318","full_name":"gocardless/stubby","owner":"gocardless","description":"Your favourite pretender stubber","archived":false,"fork":false,"pushed_at":"2023-07-08T13:07:32.000Z","size":1287,"stargazers_count":29,"open_issues_count":31,"forks_count":2,"subscribers_count":90,"default_branch":"master","last_synced_at":"2025-08-20T17:18:49.357Z","etag":null,"topics":["developer-enablement"],"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/gocardless.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-05-11T15:07:52.000Z","updated_at":"2021-08-01T11:49:05.000Z","dependencies_parsed_at":"2024-10-08T08:52:53.582Z","dependency_job_id":"0d1059bf-0255-4258-a821-577e3762c6e8","html_url":"https://github.com/gocardless/stubby","commit_stats":{"total_commits":67,"total_committers":11,"mean_commits":6.090909090909091,"dds":0.7761194029850746,"last_synced_commit":"5964d3b3dc858d7ed47e9d0ee5491e1dbac11338"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/gocardless/stubby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Fstubby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Fstubby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Fstubby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Fstubby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gocardless","download_url":"https://codeload.github.com/gocardless/stubby/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Fstubby/sbom","scorecard":{"id":433130,"data":{"date":"2025-08-11","repo":{"name":"github.com/gocardless/stubby","commit":"5964d3b3dc858d7ed47e9d0ee5491e1dbac11338"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":3,"reason":"Found 2/6 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/gocardless/.github/SECURITY.md:1","Info: Found linked content: github.com/gocardless/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/gocardless/.github/SECURITY.md:1","Info: Found text in security policy: github.com/gocardless/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"71 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-wg6g-ppvx-927h","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-vh7m-p724-62c2","Warn: Project is vulnerable to: GHSA-r9p9-mrjm-926w","Warn: Project is vulnerable to: GHSA-434g-2637-qmqr","Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m","Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw","Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-r628-mhmh-qjhw","Warn: Project is vulnerable to: GHSA-9r2w-394v-53qc","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-qq89-hq3f-393p","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-9m6j-fcg5-2442","Warn: Project is vulnerable to: GHSA-hh27-ffr2-f2jc","Warn: Project is vulnerable to: GHSA-rqff-837h-mm52","Warn: Project is vulnerable to: GHSA-8v38-pw62-9cw2","Warn: Project is vulnerable to: GHSA-hgjh-723h-mx2j","Warn: Project is vulnerable to: GHSA-jf5r-8hm2-f872","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T03:51:41.514Z","repository_id":773567,"created_at":"2025-08-19T03:51:41.514Z","updated_at":"2025-08-19T03:51:41.514Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273272538,"owners_count":25075978,"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","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["developer-enablement"],"created_at":"2024-11-14T15:08:26.378Z","updated_at":"2025-09-02T10:42:47.335Z","avatar_url":"https://github.com/gocardless.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# This library is legacy and will be modified to help us move away from it, and will not be maintained with the plan to deprecate this library later this year (2019).\n## If you require a stubbing library see: [Pretender](https://github.com/trek/pretender)\n\n# Stubby\n\n## Continuous Integration\n Currently this project is tested in Circle CI v1 which is past it's sunset and could be switched off at any time. There are currently no plans to migrate this project as no major changes are being made, and no plans to support this longer term. If you plan on making major changes to this project we recommend you [migrate it to use Circle CI V2](https://circleci.com/docs/2.0/migrating-from-1-2/) first.\n\n### AJAX Testing Stub Library\n\nStubby is a rich API on top of [Pretender](https://github.com/trek/pretender) to allow for browser integration testing and AJAX endpoint mocking.\n\nStubby will also validate any stubs given to it. URL parameters are treated as significant along with request parameters. You can stub request HTTP headers, url parameters, the response code and body. Stubby will match incoming requests against the stubs that have been defined. The library is primarily built for testing JSON APIs; JSON requests and responses are decoded for you.\n\nStubby allows for features to be added as plugins, such as JSON schema validation of requests and mocks, along with potential additional verifications for mocks preventing invalid mocks from being created. The library comes with a module for validating stubs against a [JSON Schema](http://json-schema.org/).\n\n## Installing Stubby\n\nThere are two ways you can use Stubby. The first is to simply add `dist/stubby-bundle.min.js` to your page. This is a Browserify compiled build that includes Stubby and all its dependencies.\n\nIf you'd rather deal with loading the dependencies yourself, you should include `stubby.js` along with its dependencies, which are:\n\n- [RouteRecognizer](https://github.com/tildeio/route-recognizer)\n- [Pretender](https://github.com/trek/pretender)\n- [LoDash](https://github.com/lodash/lodash)\n\nIf you find any bugs or issues with Stubby, please feel free to raise an issue on this repository.\n\n## Usage Examples:\n\nSee the demo in `example/demo.html` by running `npm run demo`.\n\nServer code:\n\n```js\nstubby.stub({\n  url: '/foo',\n  params: { b: 1 },\n}).respondWith(200, { b: 1});\n```\n\nThis code stubs out a server at that responds to `GET /foo?b=1` with `{b:1}`.\n\nClient-side code:\n\n```js\n$.get('/foo?b=1', function(response) {\n\tif (response.body['b'] === 1) {\n\t\talert('ok :)');\n\t} else {\n\t\talert('fail');\n\t}\n})\n```\n\n### Stubbing a URL\n\nGiven an instance of stubby, you can call `stub` to stub a URL. This returns a `Stubby.StubInternal` object, that you can then call `respondWith` to define what Stubby should return:\n\n```js\nstubby.stub(options).respondWith(status, data, responseOptions)\n```\n\nThe allowed options for a stub are:\n\n- `url`: The URL of the request. Can include query params, Stubby will strip them for you and match against them too.\n- `params`: An object of query parameters that should be matched against. If these are given, Stubby will use these over any query parameters in the URL.\n- `headers`: a list of headers for Stubby to match against\n- `data`: an object that should be present in the request data.\n- `method`: the type of request. Defaults to `GET`.\n- `overrideStub`: pass `true` here to state that this stub should override a matching stub if one exists. Defaults to `false`.\n\nIf you try to stub a request that is already stubbed, Stubby will error. You should first call `stubby.remove(options)` to remove the stub, and then restub it.\n\nYou should also [consult the Stubby specs](https://github.com/gocardless/stubby/blob/master/spec/stubby.spec.js) for many examples of how to stub requests.\n\n`respondWith` takes three arguments:\n\n- `status`: the status code that will be returned\n- `data`: the body that will be returned as JSON\n- `responseOptions`: an optional third argument that can set extra options. You can pass in a `headers` object here to set response headers.\n\nAn instance of `Stubby` also has the following methods that can be called:\n\n##### `addModule(module)`\n\nAdds a module to Stubby. See below for what these modules can do and how to write them.\n\n##### `passthrough(url)`\n\nBy default Stubby blocks all requests, and will error if it gets a request that it can't match to a Stub. You can use this method to tell Stubby that it's fine to let requests matching this URL to hit the network. `stubby.passthrough('/foo')` would mean any `GET` request to `/foo` hits the network. It is currently only possible to passthrough on `GET` requests.\n\n##### `verifyNoOutstandingRequests()`\n\nWhen called, Stubby will check that every stub that it has been given has been called at least once, and error if it hasn't. This is useful to perform at the end of a test, to ensure all stubs were matched.\n\n### Modules:\n\nStubby provides an API to add functionality through modules.\n\n#### How to setup a module:\n\nThe included modules in the `modules/` folder are optional, officially supported parts of this project to supplement the functionality of Stubby but also to keep the core lightweight. Modules are registered by passing an instance of a module to `addModule`:\n\n```js\nvar addonModule = new RandomAddonModule();\nvar stubby = new window.Stubby();\nstubby.addModule(addonModule);\n```\n\n#### Modules API:\n\nA module needs to expose an javascript object or function with a prototype or method called register.\nThe register method is passed an object that listeners within that class can be registered with:\n```js\nfunction DemoModule(api_version){\n  // Method to register the module as a handler.\n  this.register = function(handler) {\n    // handler.on(event, callback(request, stub), callback context);\n    // Handler called when the route is setup calling `.stub`.\n    handler.on('setup', function(req, stub) { }, this);\n    // Handler called when a route is being matched (allows for changes or checks before matching routes).\n    handler.on('routesetup', function(req, stub) { }, this);\n    // Handler is called when a request is about to be fuffiled by the passed in matching route\n    handler.on('request', function(req, stub) { this.inject_api_version(stub); }, this);\n  };\n  this.inject_api_version = function(stub) {\n    stub.response.headers['api-version'] = api_version;\n  };\n}\n```\n\n#### Included Modules:\n\n- **schema-validator**:\n\nWhile Stubby doesn't support JSON Schema validation out of the box, the included schema-validator module validates stubs against a JSON hyperschema.\n\nTo setup the validator, add a schema like so:\n\n```js\nvar stubby = new Stubby();\nvar validator = new window.StubbySchemaValidator();\nvalidator.addSchema('/', schemaJSON);\nstubby.addModule(validator);\n```\n\n- **chaos-monkey**:\n\nA demo module that responds with random http status codes instead of the ones specified with the stub with the option `{chaos: true}` set in the stub.\nIt also verifies that the response http status is equal to 42 in order to allow for chaos.\n\nThis module demonstrates how to write a simple module to integrate within the stubby framework, for usage examples, see the definitions file and corresponding spec.\n\n### Development:\n\nWhen you clone the repo, you should ensure all dependencies are installed:\n\n```\nnpm install\nbower install\n```\n\nYou can run `npm test` to run all the tests.\n\nIn order to recompile the browserify modules, run `./script/build` to rebuild. To force a build, run `./script/build -f`.\n\nIf you don't want to use the Browserify build, manually take `stubby.js`, its dependencies and any modules from the `modules` folder.\n\n### Limitations:\n\nSince stubby was created for JSON APIs, it might be better to use the raw pretender API instead of stubby for other types of data.\n\nAdditionally, Pretender doesn't allow for mocking JSONP or cross-origin ajax requests, so stubby only works for the same hostname/protocol/port ajax requests.\n\n\n### Changelog\n\n##### V0.0.6\n- fix schema validation for non-object request payloads\n\n##### V0.0.5\n- print expected stub when no stubs where found\n\n##### V0.0.4\n- allow stubs to have response headers specified\n\n##### V0.0.3\n- allow stubs to override existing match with `overrideStub` option\n\n##### V0.0.2\n- stop skipping data matches in schema validation plugin\n- if a request has data but the stub has none defined, it will now match that request to that stub\n\n##### V0.0.1\n- initial release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgocardless%2Fstubby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgocardless%2Fstubby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgocardless%2Fstubby/lists"}