{"id":15240481,"url":"https://github.com/skryukov/openapi_rspec","last_synced_at":"2026-01-25T15:00:44.144Z","repository":{"id":51392614,"uuid":"176805972","full_name":"skryukov/openapi_rspec","owner":"skryukov","description":"Test your API against OpenApi v3 documentation","archived":false,"fork":false,"pushed_at":"2022-11-16T17:34:01.000Z","size":71,"stargazers_count":13,"open_issues_count":4,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-13T23:52:29.575Z","etag":null,"topics":["api","openapi","rspec","ruby"],"latest_commit_sha":null,"homepage":"","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/skryukov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-20T19:47:40.000Z","updated_at":"2025-12-27T01:53:10.000Z","dependencies_parsed_at":"2023-01-22T07:02:31.355Z","dependency_job_id":null,"html_url":"https://github.com/skryukov/openapi_rspec","commit_stats":null,"previous_names":["medsolutions/openapi_rspec"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/skryukov/openapi_rspec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fopenapi_rspec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fopenapi_rspec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fopenapi_rspec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fopenapi_rspec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skryukov","download_url":"https://codeload.github.com/skryukov/openapi_rspec/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skryukov%2Fopenapi_rspec/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28754807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T13:59:49.818Z","status":"ssl_error","status_checked_at":"2026-01-25T13:59:33.728Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","openapi","rspec","ruby"],"created_at":"2024-09-29T11:05:12.464Z","updated_at":"2026-01-25T15:00:43.905Z","avatar_url":"https://github.com/skryukov.png","language":"Ruby","readme":"[gem]: https://rubygems.org/gems/openapi_rspec\n[codeclimate]: https://codeclimate.com/github/skryukov/openapi_rspec\n\n# openapi_rspec\n[![Gem Version](https://badge.fury.io/rb/openapi_rspec.svg)][gem]\n[![Build](https://github.com/skryukov/openapi_rspec/workflows/Build/badge.svg)](https://github.com/skryukov/openapi_rspec/actions)\n[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)\n\nTest your API against OpenApi v3 documentation\n\nInspired by [Apivore](https://github.com/westfieldlabs/apivore)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'openapi_rspec'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install openapi_rspec\n\n## Usage\n\nAdd `spec/openapi_helper.rb` and set `OpenapiRspec.config.app`:\n\n```ruby\n# spec/openapi_helper.rb\n\nrequire \"rails_helper\"\n\nOpenapiRspec.config.app = Rails.application # or any other Rack app, thanks to rack-test gem\n```\n\nThen configure path to your documentation. You can use documentation defined as:\n- static file with `.yaml`/`.yml` or `.json` extension\n- uri to OpenAPI schema in your application\n\n```ruby\n# spec/openapi_helper.rb\n\n#...\n\n# static file\nAPI_V1 = OpenapiRspec.api(\"./spec/data/openapi.yml\")\n\n# application path\nAPI_V2 = OpenapiRspec.api_by_path(\"/openapi.json\")\n```\n\n\n### Validate documentation against the OpenAPI 3.0 Specification:\n\n```ruby\nRSpec.describe \"API v1\" do\n  subject { API_V1 }\n\n  it \"is valid OpenAPI spec\" do\n    expect(subject).to validate_documentation\n  end\nend\n```\n\n#### Validate documentation against custom schema\n\nYou can validate documentation against additional custom schemata, for example, to enforce organization documentation standards:\n\n```ruby\n# spec/openapi_helper.rb\n\n#...\n\nAPI_V1 = OpenapiRspec.api(\"./spec/data/openapi.yml\", additional_schemas: [\"./spec/data/acme_schema.yml\"])\n```\n\n```ruby\n# openapi_v1_spec.rb\n\nRSpec.describe \"API v1\" do\n  subject { API_V1 }\n\n  it \"is valid OpenAPI and ACME spec\" do\n    expect(subject).to validate_documentation\n  end\nend\n```\n\n### Validate endpoints\n\nGeneral example:\n\n```ruby\nrequire \"openapi_rspec\"\n\nRSpec.describe \"API v1 /pets\" do\n\n  subject { API_V1 }\n\n  get \"/pets\" do\n    headers { { \"X-Client-Device\" =\u003e \"ios\" } }\n    query { { tags: [\"lucky\"] } }\n\n    validate_code(200) do |validator|\n      result = JSON.parse(validator.response.body)\n      expect(result.first[\"name\"]).to eq(\"Lucky\")\n    end\n  end\n\n  post \"/pets\" do\n    params { { name: \"Lucky\" } }\n\n    validate_code(201)\n  end\n\n  get \"/pets/{id}\" do\n    let(:id) { 23 }\n\n    validate_code(200)\n\n    context \"when pet not found\" do\n      let(:id) { \"bad_id\" }\n\n      validate_code(404)\n    end\n  end\n```\n\n#### Helper methods\n\nTo validate response use:\n- `get`, `post`, `put`, `patch`, `delete` and `head` methods to describe operation with the path\n- `validate_code` method with passed expected code\n\n```ruby\n# ...\n  get \"/pets\" do\n    validate_code(200)\n  end\n# ...\n```\n\nTo set **request body** (as form data) use `params` helper method and provide a `Hash`:\n\n```ruby\n# ...\n  post \"/pets\" do\n    params { { name: \"Lucky\" } }\n\n    validate_code(201)\n  end\n# ...\n```\n\nTo set **raw request body** use the `params` helper method and provide a `String`:\n\n```ruby\n# ...\n  post \"/pets\" do\n    params { JSON.dump(name: \"Lucky\") }\n\n    validate_code(201)\n  end\n# ...\n```\n\n\nTo set **path parameter** use `let` helper method:\n\n```ruby\n# ...\n  get \"/pets/{id}\" do\n    let(:id) { 23 }\n\n    validate_code(200)\n  end\n# ...\n```\n\nTo set **query parameters** use `query` helper method:\n\n```ruby\n# ...\n  get \"/pets\" do\n    query { { name: \"lucky\" } }\n\n    validate_code(200)\n  end\n# ...\n```\n\nTo set **header parameters** use `headers` helper method:\n\n```ruby\n# ...\n  get \"/pets\" do\n    headers { { \"X-User-Token\" =\u003e \"bad_token\" } }\n\n    validate_code(401)\n  end\n# ...\n```\n\n#### Custom response validation\n\nYou can access response to add custom validation like this:\n\n```ruby\n# ...\n  get \"/pets\" do\n    validate_code(200) do |validator|\n      result = JSON.parse(validator.response.body)\n      expect(result).not_to be_empty\n    end\n  end\n# ...\n```\n\n#### Prefix API requests\n\nTo prefix each request with `\"/some_path\"` use `:api_base_path` option:\n\n```ruby\n# spec/openapi_helper.rb\n\n#...\n\nAPI_V1 = OpenapiRspec.api(\"./spec/data/openapi.yml\", api_base_path: \"/some_path\")\n```\n\n#### Validate that all documented routes are tested\n\nTo validate this we will use a small hack:\n\n```ruby\n# spec/openapi_helper.rb\n\n# ...\n\nAPI_V1_DOC = OpenapiRspec.api(\"./openapi/openapi.yml\", api_base_path: \"/api/v1\")\n\nRSpec.configure do |config|\n  config.after(:suite) do\n    unvalidated_requests = API_V1_DOC.unvalidated_requests\n\n    if unvalidated_requests.any? \u0026\u0026 ENV[\"TEST_COVERAGE\"]\n      raise unvalidated_requests.map { |path| \"Path #{path.join(' ')} not tested\" }.join(\"\\n\")\n    end\n  end\nend\n```\n\nThen run your specs:\n\n    $ TEST_COVERAGE=1 rspec\n\nThis will raise an error if any of the documented paths are not validated.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/skryukov/openapi_rspec.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskryukov%2Fopenapi_rspec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskryukov%2Fopenapi_rspec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskryukov%2Fopenapi_rspec/lists"}