README.md in rspec-rails-api-0.3.4 vs README.md in rspec-rails-api-0.4.0
- old
+ new
@@ -46,11 +46,11 @@
renderer.api_tos = 'http://example.com/tos.html'
renderer.api_contact = { name: 'Admin', email: 'admin@example.com', url: 'http://example.com/contact' }
renderer.api_license = { name: 'Apache', url: 'https://opensource.org/licenses/Apache-2.0' }
RSpec.configuration.after(:context, type: :acceptance) do |context|
- renderer.merge_context context.class.metadata[:rrad].to_h
+ renderer.merge_context context.class.metadata[:rra].to_h
end
RSpec.configuration.after(:suite) do
# Default path is 'tmp/rspec_rails_api_output.json/yaml'
renderer.write_files Rails.root.join('public', 'swagger_doc'), only: [:json]
@@ -123,11 +123,11 @@
# In examples
#...
for_code 200, 'Success' do |url|
sing_in #...
- visit url
+ test_response_of url
#...
end
#...
```
@@ -137,18 +137,10 @@
## Usage
Write some spec files and run RSpec as you would usually do.
-If you want to generate the documentation without testing the endpoints
-(and thus, without examples in generated files), use the `DOC_ONLY`
-environment variable:
-
-```sh
-DOC_ONLY=true bundle exec rails spec
-```
-
## Writing specs
There is a [commented example](dummy/spec/acceptance/posts_spec.rb) available in
`dummy/spec/acceptance`.
@@ -169,30 +161,28 @@
created_at: { type: :datetime, description: 'Creation date' },
updated_at: { type: :datetime, description: 'Modification date' },
url: { type: :string, description: 'URL to this category' }
on_get '/api/users/', 'Users list' do
- for_code 200, 'Success response' do |url|
- visit url
- expect(response).to have_many defined :user
+ for_code 200, 'Success response', expect_many: :user do |url|
+ test_response_of url
end
end
on_put '/api/users/:id', 'Users list' do
path_param id: { type: :integer, description: 'User Id' }
request_params user: {
- type: :object, required: true, properties: {
+ type: :object, attributes: {
name: { type: :string, required: false, description: 'New name' },
email: { type: :string, required: false, description: 'New email' },
role: { type: :string, required: false, description: 'New role' },
}
}
- for_code 200, 'Success response' do |url|
- visit url
- expect(response).to have_one defined :user
+ for_code 200, 'Success response', expect_one: :user do |url|
+ test_response_of url
end
end
end
```
@@ -271,29 +261,39 @@
inline.
Both `:of` and `attributes` may be a hash of fields or a symbol. If they
are omitted, they will be documented, but responses won't be validated.
+Arrays of primitives are supported; the type should be prefixed by `type_` to
+avoid collisions with defined entities of the same name:
+
+```rb
+entity :user,
+ surnames: { type: :array, of: :type_int32 }
+```
+
+Check `lib/rspec_rails_api.rb` for the full list.
+
##### `parameters(type, fields)`
Describe path or request parameters. The type is only a reference,
use whatever makes sense. These parameters will be present in
documentation, only if they are referenced by a `request_params` or
`path_params` call.
Fields have the structure of the hash you would give to `request_params`
or `path_params` (see each method later in this documentation).
-##### `on_<xxx>(url, description, &block)`
+##### `on_<xxx>(url, summary = nil, description = nil, &block)`
Defines an URL.
- `url` should be a relative URL to an existing endpoint (i.e.:
`/api/users`)
-- `description` should be some valid
- [CommonMark](https://commonmark.org/)
+- `summary` is a one line description of the endpoint
+- `description` should be some valid [CommonMark](https://commonmark.org/)
-For now, only these methods are available:
+These methods are available:
- `on_get`
- `on_post`
- `on_put`
- `on_patch`
@@ -339,11 +339,11 @@
nested elements can be described:
```ruby
on_post '/api/items' do
request_params attributes: {
- item: { type: :object, required: true, properties: {
+ item: { type: :object, attributes: {
name: { type: integer, description: 'The name of the new item', required: true },
notes: { type: string, description: 'Additional notes' }
} }
}
#...
@@ -351,25 +351,25 @@
```
An attribute should have the following form:
```
-<attr_name>: {type: <type>, desc: <description>, required: <required>, properties: <another_hash>, of: <another_hash> }
+<attr_name>: {type: <type>, desc: <description>, required: <required>, attributes: <another_hash>, of: <another_hash> }
```
- `attr_name` is the attribute name (sic)
- `type` is the field type (check _entity definition_ for a list).
`type` can be `:object` if the attribute contains other attributes.
- `required` is optional an defaults to `false`.
-- `properties` is a hash of params and is only used if `type: :object`
+- `attributes` is a hash of params and is only used if `type: :object`
- `of` is a hash of params and is only used if `type: :array`
Alternative with defined parameters:
```ruby
parameters :item_form_params,
- item: { type: :object, required: true, properties: {
+ item: { type: :object, attributes: {
name: { type: integer, description: 'The name of the new item', required: true },
notes: { type: string, description: 'Additional notes' }
}
}
@@ -378,60 +378,58 @@
#...
end
```
-##### `for_code(http_status, description = nil, doc_only: false, test_only: false &block)`
+##### `for_code(http_status, description = nil, test_only: false &block)`
Describes the desired output for a precedently defined URL.
-Block takes one required argument, that should be passed to `visit`.
-This argument will contain the block context and allow `visit` to access
+Block takes one required argument, that should be passed to `test_response_of`.
+This argument will contain the block context and allow `test_response_of` to access
the metadatas.
You can have only one documented code per action/url, unless you use
`test_only`.
- `http_status` is an integer representing an
[HTTP status](https://httpstat.us/)
- `description` should be some valid
[CommonMark](https://commonmark.org/). If not defined, a human readable
translation of the `http_status` will be used.
-- `doc_only` can be set to true to temporarily disable block execution
- and only create the documentation (without examples).
- `test_only` will omit the test from the documentation. Useful when you
need to test things _around_ the call (response content, db,...)
-- `block` where additional tests can be performed. If `visit()` is
+- `block` where additional tests can be performed. If `test_response_of` is
called within the block, its output will be used in documentation
examples, and the response type and code will actually be tested.
If no block is passed, only the documentation will be generated, without
examples. This can be useful to document endpoints that are impossible
to test.
Once again, you have to pass an argument to the block if you use
-`visit`.
+`test_response_of`.
```ruby
# ...
for_code 200, 'A successful response' do |url|
- visit url
+ test_response_of url
# ...
end
for_code 200, 'Side test', test_only: true do |url|
- visit url
+ test_response_of url
# ...
end
# ...
```
#### Examples
Example methods are available in `for_code` blocks
-##### `visit(example, path_params: {}, payload: {}, headers: {})`
+##### `test_response_of(example, path_params: {}, payload: {}, headers: {})`
Visits the described URL and:
- Expects the response code to match the described one
- Expects the content type to be `application/json`
@@ -444,14 +442,19 @@
requests
- `headers`: a hash of custom headers.
```ruby
for_code 200, 'Success' do |url|
- visit url
+ test_response_of url
end
```
#### Matchers
+
+The matchers _should not_ be used in acceptance specs unless the default DSL is
+not adapted for a particular use case (and I can't imagine one now).
+
+For the sake of comprehension, the two custom matchers still described.
##### `have_one(type)`
Expects the compared content to be a hash with the same keys as a
defined entity.