{"id":13879820,"url":"https://github.com/Betterment/webvalve","last_synced_at":"2025-07-16T15:33:03.162Z","repository":{"id":45380155,"uuid":"82738157","full_name":"Betterment/webvalve","owner":"Betterment","description":"Betterment's framework for locally developing and testing service-oriented apps in isolation with WebMock and Sinatra-based fakes","archived":false,"fork":false,"pushed_at":"2024-10-29T12:47:56.000Z","size":132,"stargazers_count":113,"open_issues_count":6,"forks_count":13,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-11-17T15:03:35.875Z","etag":null,"topics":["fake","fakeweb","http","rails","sinatra","testing"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/webvalve","language":"Ruby","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/Betterment.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-21T23:31:35.000Z","updated_at":"2024-10-29T12:47:58.000Z","dependencies_parsed_at":"2024-01-02T20:29:46.498Z","dependency_job_id":"48555594-6e6c-45dc-b9ab-f1ad92b23258","html_url":"https://github.com/Betterment/webvalve","commit_stats":{"total_commits":90,"total_committers":12,"mean_commits":7.5,"dds":0.4555555555555556,"last_synced_commit":"24bfe9a5a92132c0a89c1fe9bbfbc70e2a214bf3"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Betterment%2Fwebvalve","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Betterment%2Fwebvalve/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Betterment%2Fwebvalve/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Betterment%2Fwebvalve/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Betterment","download_url":"https://codeload.github.com/Betterment/webvalve/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226143895,"owners_count":17580245,"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":["fake","fakeweb","http","rails","sinatra","testing"],"created_at":"2024-08-06T08:02:34.594Z","updated_at":"2024-11-24T08:31:49.546Z","avatar_url":"https://github.com/Betterment.png","language":"Ruby","readme":"WebValve\n========\n\n![Build Status](https://github.com/Betterment/webvalve/workflows/CI/badge.svg)\n[![Gem Status](https://img.shields.io/gem/v/webvalve.svg)](https://rubygems.org/gems/webvalve)\n\nWebValve is a tool for defining and registering fake implementations of\nHTTP services and toggling between the real services and the fake ones\nin non-production environments.\n\nThis library is made possible by the incredible gems\n[WebMock](https://github.com/bblimke/webmock) and\n[Sinatra](https://github.com/sinatra/sinatra).\n\nCheck out [the Rails at Scale talk](https://www.youtube.com/watch?v=Nd9hnffxCP8) for some background on why we built it and some of the key design decisions behind WebValve:\n\n[![Rails @ Scale Talk](https://img.youtube.com/vi/Nd9hnffxCP8/0.jpg)](https://www.youtube.com/watch?v=Nd9hnffxCP8)\n\n## Getting Started\n\nWebValve is designed to work with Rails 4+, but it also should work with\nnon-Rails apps and gems.\n\n### Installation\n\nYou can add WebValve to your Gemfile with:\n```\ngem 'webvalve'\n```\n\nThen run `bundle install`.\n\n### Network connections disabled by default\n\nThe default mode in development and test is to disallow all HTTP network\nconnections. This provides a clean foundation for consuming new\nservices. If you add a new service integration, the first thing that you\nwill be presented with when you attempt to hit it in development or test\nis a warning that the requested URL was not mocked. This behavior comes\nstraight outta WebMock.\n\n```ruby\nirb(main):007:0\u003e Net::HTTP.get(URI('http://bank.test'))\n\nWebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://bank.test/ with headers {'Accept'=\u003e'*/*', 'User-Agent'=\u003e'Ruby'}\n\nYou can stub this request with the following snippet:\n\nstub_request(:get, \"http://bank.test/\").\n  with(:headers =\u003e {'Accept'=\u003e'*/*', 'User-Agent'=\u003e'Ruby'}).\n  to_return(:status =\u003e 200, :body =\u003e \"\", :headers =\u003e {})\n\n============================================================\n```\n\n### Creating a config file\n\nThe first thing to do is run the install generator.\n\n```\n$ rails generate webvalve:install\n```\n\nThis will drop a new file in your config directory.\n\n```ruby\n# config/webvalve.rb\n\n# # register services\n#\n# WebValve.register \"FakeBank\"\n# WebValve.register \"FakeExample\", url: \"https://api.example.org\"\n#\n# # add urls to allowlist\n#\n# WebValve.allow_url \"https://example.com\"\n```\n\nIf you're not using Rails, you can create this file for yourself.\n\n### Registering a service\n\nNext, you will want create a `FakeService` and register\nit with the framework.\n\nThis can be accomplished by running the fake service generator:\n\n```\n$ rails generate webvalve:fake_service Bank\n```\n\nThis will generate a file `fake_bank.rb` in the top-level folder\n`webvalve`. This file will be autoloaded by Rails, so you can\ntweak it as you go without having to restart your application.\n\n```ruby\n# webvalve/fake_bank.rb\n\nclass FakeBank \u003c WebValve::FakeService\n  # # define your routes here\n  #\n  # get '/widgets' do\n  #   json result: 'it works!'\n  # end\n  #\n  # # toggle this service on via ENV\n  #\n  # export BANK_ENABLED=true\nend\n```\n\nAnd it will automatically register it in `config/webvalve.rb`\n\n```ruby\n# config/webvalve.rb\nWebValve.register \"FakeBank\"\n```\n\nAgain, if you're not using Rails, you'll have to create this file\nyourself and update the config file manually.\n\nYou'll also want to define an environment variable for the base url of\nyour service.\n\n```bash\nexport BANK_API_URL='http://bank.test'\n```\n\nThat's it. Now when you hit your service again, it will route your\nrequest into the `FakeBank` instance.\n\nIf you want to connect to the _actual_ service, all you have to do is\nset another environment variable.\n\n```bash\nexport BANK_ENABLED=true\n```\n\nYou will have to restart your application after making this change\nbecause service faking is an initialization time concern and not a\nruntime concern.\n\n## Configuring fakes in tests\n\nIn order to get WebValve fake services working properly in tests, you\nhave to configure WebValve at the beginning of each test. For RSpec, there\nis a configuration provided. \n\n```ruby\n# spec/spec_helper.rb\nrequire 'webvalve/rspec'\n```\n\nIf you are using \n[rspec-retry](https://github.com/NoRedInk/rspec-retry), you'll have to\nmanually register your around hook, instead, to ensure that WebValve\nresets its configuration for each retry, e.g.:\n\n```ruby\n# spec/[rails|spec]_helper.rb\n\n# your require lines omitted ...\nrequire 'webmock/rspec' # set up webmock lifecycle hooks - required\n\nRSpec.configure do |config|\n  # your config lines omitted ...\n\n  config.around :each do |ex|\n    ex.run_with_retry retry: 2\n  end\n  \n  config.around :each do |ex|\n    WebValve.reset!\n    ex.run\n  end\nend\n```\n\nFor any other test framework, you will want to similarly set up webmock\nlifecycle hooks, and add a custom hook that will run `WebValve.setup` before\neach test.\n\n## Setting deterministic fake results in tests\n\nGiven a scenario where we want to mock a specific behavior for an\nendpoint in a test, we can just use WebMock™.\n\n```ruby\n# in an rspec test...\n\nit 'handles 404s by returning nil' do\n  fake_req = stub_request('http://bank.test/some/url/1234')\n    .to_return(status: 404, body: nil)\n\n  response = Faraday.get 'http://bank.test/some/url/1234'\n  expect(response.body).to be_nil\n  expect(fake_req).to have_been_requested\nend\n```\n\nIn other scenarios where we don't care about the specific response from\nthe endpoint, you can just lean into the behavior you've configured for\nthat route in your fake service.\n\n## Overriding conventional defaults\n\nSometimes a service integration may want to use an unconventional name\nfor its environment variables. In that case, you can register the fake\nservice using the optional `url:` argument.\n\n```ruby\n# config/webvalve.rb\n\n# using an ENV variable\nWebValve.register FakeBank, url: ENV.fetch(\"SOME_CUSTOM_API_URL\")\n\n# or with a constant value\nWebValve.register FakeBank, url: \"https://some-service.com\"\n```\n\n## Dynamic URLs\n\nIf the service you are interacting with contains dynamic elements, e.g.\nan instance-specific subdomain, you can specify a wildcard in your url\nwith the `*` character to match a series of zero or more characters\nwithin the same URL segment. For example:\n\n```bash\nexport BANK_API_URL=https://*.mybank.com/\n```\n\nor\n\n```ruby\nWebValve.register FakeBank, url: \"https://*.mybank.com\"\n```\n\nNote: unlike filesystem globbing, `?` isn't respected to mean \"exactly\none character\" because it's a URL delimiter character. Only `*` works\nfor WebValve URL wildcards.\n\nAlternatively you can use `Addressable::Template`s or `Regexp`s to\nspecify dynamic URLs if they for some reason aren't a good fit for the\nwildcard syntax. Note that there is no `ENV` var support for these\nformats because there is no detection logic to determine a URL string is\nactually meant to represent a URL template or regexp. For example:\n\n```ruby\nWebValve.register FakeBank, url: Addressable::Template.new(\"http://mybank.com{/path*}{?query}\")\n```\n\nor\n\n```ruby\nWebValve.register FakeBank, url: %r{\\Ahttp://mybank.com(/.*)?\\z}\n```\n\n## What's in a `FakeService`?\n\nThe definition of `FakeService` is really simple. It's just a\n`Sinatra::Base` class. It is wired up to support returning JSON \nresponses and it will raise when a route is requested but it is \nnot registered.\n\n## Frequently Asked Questions\n\n\u003e Can I use WebValve in environments like staging, demo, and production?\n\nYes! By default WebValve is only enabled in test and development\nenvironments; however, it can be enabled in other environments by\nsetting `WEBVALVE_ENABLED=true` (actually, any of 1/t/true will work).\nThis can be useful for spinning up cheap, one-off environments for\nuser-testing or demos. When WebValve is enabled in any environment other\nthan development/test it will default services to enabled rather than\ndisabled, allowing all traffic to pass-thru. This ensures that\nproduction-like environments are run integrated by default. You can\nchange this behavior by setting `WEBVALVE_SERVICE_ENABLED_DEFAULT=false`\n(any of 0/f/false will work). This will default to the same experience\nas local development, defaulting services to disabled, intercepting all\ntraffic. In either of these modes, you can use the\n`$SERVICE_ENABLED=true/false` to toggle a specific service into the\ndesired state.\n\n\u003e Can I use WebValve without Rails?\n\nYep! If you're not using Rails, you'll have to load the config file\nyourself. You will want to explicitly `require` each of your fake\nservices in your `config/webvalve.rb`, `require` your config file, and\ncall `WebValve.setup`  during your app's boot-up process.\n\n## How to Contribute\n\nWe would love for you to contribute! Anything that benefits the majority\nof `webvalve` users—from a documentation fix to an entirely new\nfeature—is encouraged.\n\nBefore diving in, [check our issue\ntracker](//github.com/Betterment/webvalve/issues) and consider\ncreating a new issue to get early feedback on your proposed change.\n\n### Suggested Workflow\n\n* Fork the project and create a new branch for your contribution.\n* Write your contribution (and any applicable test coverage).\n* Make sure all tests pass (`bundle exec rake`).\n* Submit a pull request.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBetterment%2Fwebvalve","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBetterment%2Fwebvalve","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBetterment%2Fwebvalve/lists"}