rspec-rails-api 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0c5ddec517d805e43305c00f7b7baa19373acb3d8fe55bca724e521e57cc8e3
4
- data.tar.gz: 9f1ed792f16c075e140610902f8d7671d13d03483115066e55ca48c43b42f8d7
3
+ metadata.gz: '0861008371cafa6cab0cda5c165acda54b5a3047f152713bb684ae0c7c7be0ff'
4
+ data.tar.gz: d3c8877c5ef1e43c902010b68b9e483feefa6e57251d67aba325394a9682aee7
5
5
  SHA512:
6
- metadata.gz: 501da0c03e7375b0097e95d951b1db831743564abd88dd4d28e719be5ee84701daaa9583160a0610dcd3cde35b143b8199b07e6bf684e0261fd26afca5b67d23
7
- data.tar.gz: 5eaf88f5467cb5d5a12ca311e53778507534ff5090e85647581899bc5c4b7ab1f9914aea97f663bc7474faaede720fe66ff3d350ff0ba12982361b0772a00ae2
6
+ metadata.gz: e1009f40d78187888e546c74e62e88d7557f45a4a3cfed78a27785d63b401f673ed1796928f1d32823a665694b86761653bb87edc68522418d6117c4b576e362
7
+ data.tar.gz: 10ffebb4902456c4671b39b7dd707ea8ca870b9a27054c3139cae94bb3dcebfc3f88abd41a298ed870f98d7953c1195171cbf8f077db2dcd6530fe761e354a5a
data/.gitignore CHANGED
@@ -12,5 +12,7 @@
12
12
 
13
13
  # Ignore lockfile for Gemfile
14
14
  Gemfile.lock
15
+ # Keep the dummy one
16
+ !dummy/Gemfile.lock
15
17
 
16
18
  .byebug_history
data/.gitlab-ci.yml CHANGED
@@ -34,3 +34,10 @@ rspec:
34
34
  - bundle exec rspec
35
35
  dependencies:
36
36
  - bundle
37
+
38
+ rspec-dummy:
39
+ stage: test
40
+ script:
41
+ - cd dummy
42
+ - bundle install --path='vendor/bundle'
43
+ - bundle exec rspec
data/.rubocop.yml CHANGED
@@ -2,9 +2,13 @@
2
2
  require:
3
3
  - rubocop-performance
4
4
 
5
+ AllCops:
6
+ Exclude:
7
+ - dummy/**/*
8
+ - vendor/bundle/**/*
9
+
5
10
  Metrics/BlockLength:
6
11
  Exclude:
7
- - examples/**/*.rb
8
12
  - rspec-rails-api.gemspec
9
13
  - spec/**/*_spec.rb
10
14
 
data/CHANGELOG.md CHANGED
@@ -1,6 +1,27 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## Not released
5
+
6
+ ## 0.2.0 - 2019-11-02
7
+
8
+ ### Added
9
+
10
+ - `parameters` method to define path or requests params for the whole file.
11
+ - A simple Rails application now acts as example and is used to generate some
12
+ of the fixtures.
13
+
14
+ ### Changed
15
+
16
+ - method `path_params` can now use a reference to a previously defined parameters
17
+ set. The method has a new signature: `path_params(fields: nil, defined: nil)`. Update
18
+ the existing calls accordingly. To use params defined with `parameters`, use the
19
+ `defined` option: `path_params defined: :common_path_params`
20
+ - method `request_params` can now use a reference to a previously defined parameters
21
+ set. The method has a new signature: `request_params(attributes: nil, defined: nil)`. Update
22
+ the existing calls accordingly. To use params defined with `parameters`, use the
23
+ `defined` option: `request_params defined: :common_form_params`
24
+
4
25
  ## 0.1.5 - 2019-10-31
5
26
 
6
27
  ### Fixed
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RSpecRailsApiDoc
1
+ # RSpec-rails-api
2
2
 
3
3
  > An RSpec plugin to test Rails api responses and generate swagger
4
4
  > documentation
@@ -13,7 +13,7 @@ in order to test it.
13
13
 
14
14
  Add this line to your application's Gemfile:
15
15
 
16
- ```rb
16
+ ```ruby
17
17
  gem 'rspec-rails-api'
18
18
  ```
19
19
 
@@ -29,7 +29,7 @@ Configuration should be made manually for now:
29
29
 
30
30
  **spec/acceptance_helper.rb**
31
31
 
32
- ```rb
32
+ ```ruby
33
33
  require 'rails_helper'
34
34
  require 'rspec_rails_api'
35
35
 
@@ -38,13 +38,15 @@ RSpec.configure do |config|
38
38
  end
39
39
 
40
40
  renderer = RSpec::Rails::Api::OpenApiRenderer.new
41
- renderer.api_servers = [{ url: 'https://example.com' }]
42
- renderer.api_title = 'A nice API for a nice application'
41
+ # Options here should be customized
42
+ renderer.api_title = 'YourProject API'
43
43
  renderer.api_version = '1'
44
- renderer.api_description = 'Access update data in this project'
45
- # renderer.api_tos = 'http://example.com/tos.html'
46
- # renderer.api_contact = { name: 'Admin', email: 'admin@example.com', 'http://example.com/contact' }
47
- # renderer.api_license = { name: 'Apache', url: 'https://opensource.org/licenses/Apache-2.0' }
44
+ renderer.api_description = 'Manage data on YourProject'
45
+ # Options below are optional
46
+ renderer.api_servers = [{ url: 'https://example.com' }]
47
+ renderer.api_tos = 'http://example.com/tos.html'
48
+ renderer.api_contact = { name: 'Admin', email: 'admin@example.com', url: 'http://example.com/contact' }
49
+ renderer.api_license = { name: 'Apache', url: 'https://opensource.org/licenses/Apache-2.0' }
48
50
 
49
51
  RSpec.configuration.after(:context, type: :acceptance) do |context|
50
52
  renderer.merge_context context.class.metadata[:rrad].to_h
@@ -58,14 +60,14 @@ end
58
60
 
59
61
  **spec/rails_helper.rb**
60
62
 
61
- ```rb
63
+ ```ruby
62
64
  # ...
63
65
 
64
66
  RSpec::Rails::DIRECTORY_MAPPINGS[:acceptance] = %w[spec acceptance]
65
67
 
66
68
  RSpec.configure do |config|
67
69
  # ...
68
- config.include RSpec::Rails::RequestExampleGroup, :type => :acceptance
70
+ config.include RSpec::Rails::RequestExampleGroup, type: :acceptance
69
71
  end
70
72
  ```
71
73
 
@@ -77,7 +79,7 @@ end
77
79
 
78
80
  To use `sign_in` and `sign_out` from Devise in the acceptance tests, create a Devise support file:
79
81
 
80
- ```rb
82
+ ```ruby
81
83
  # spec/support/devise.rb
82
84
  module DeviseAcceptanceSpecHelpers
83
85
  include Warden::Test::Helpers
@@ -97,7 +99,7 @@ end
97
99
 
98
100
  Load this file in `rails_helper.rb`:
99
101
 
100
- ```rb
102
+ ```ruby
101
103
  #...
102
104
  # Add additional requires below this line. Rails is not loaded until this point!
103
105
  require 'support/devise'
@@ -106,7 +108,7 @@ require 'support/devise'
106
108
 
107
109
  Include the helper for acceptance specs:
108
110
 
109
- ```rb
111
+ ```ruby
110
112
  RSpec.configure do |config|
111
113
  config.include DeviseAcceptanceSpecHelpers, type: :acceptance
112
114
  end
@@ -114,7 +116,7 @@ end
114
116
 
115
117
  You can now use the methods as usual:
116
118
 
117
- ```rb
119
+ ```ruby
118
120
  # In a before block
119
121
  before do
120
122
  sign_in #...
@@ -122,9 +124,9 @@ end
122
124
 
123
125
  # In examples
124
126
  #...
125
- for_code 200, 'Success' do |example|
127
+ for_code 200, 'Success' do |url|
126
128
  sing_in #...
127
- visit example
129
+ visit url
128
130
 
129
131
  #...
130
132
  end
@@ -142,24 +144,20 @@ If you want to generate the documentation without testing the endpoints
142
144
  (and thus, without examples in generated files), use the `DOC_ONLY`
143
145
  environment variable:
144
146
 
145
- ```rb
147
+ ```sh
146
148
  DOC_ONLY=true bundle exec rails spec
147
149
  ```
148
150
 
149
- For now, files are saved as `tmp/out.json` and `tmp/out.yml`.
150
-
151
- There is nothing to customize the file headers (info, license, ...) yet.
152
-
153
151
  ## Writing specs
154
152
 
155
- There is a [commented example](examples/commented.rb) available in
156
- `doc/`.
153
+ There is a [commented example](dummy/spec/acceptance/posts_spec.rb) available in
154
+ `dummy/spec/acceptance`.
157
155
 
158
156
  The idea is to have a simple DSL, and declare things like:
159
157
 
160
158
  **spec/acceptance/users_spec.rb**
161
159
 
162
- ```rb
160
+ ```ruby
163
161
  require 'acceptance_helper'
164
162
 
165
163
  RSpec.describe 'Users', type: :acceptance do
@@ -174,8 +172,8 @@ RSpec.describe 'Users', type: :acceptance do
174
172
  url: { type: :string, description: 'URL to this category' }
175
173
 
176
174
  on_get '/api/users/', 'Users list' do
177
- for_code 200, 'Success response' do |example|
178
- visit example
175
+ for_code 200, 'Success response' do |url|
176
+ visit url
179
177
  expect(response).to have_many defined :user
180
178
  end
181
179
  end
@@ -191,8 +189,8 @@ RSpec.describe 'Users', type: :acceptance do
191
189
  }
192
190
  }
193
191
 
194
- for_code 200, 'Success response' do |example|
195
- visit example
192
+ for_code 200, 'Success response' do |url|
193
+ visit url
196
194
  expect(response).to have_one defined :user
197
195
  end
198
196
  end
@@ -203,25 +201,24 @@ end
203
201
 
204
202
  #### Example groups
205
203
 
206
- ##### `resource(name, description)`
204
+ ##### `resource(type, description)`
207
205
 
208
206
  Starts a resource description.
209
207
 
210
208
  - It must be called before any other documentation calls.
211
209
  - It should be in the first `describe block`
212
210
 
213
- ##### `entity(name, fields)`
211
+ ##### `entity(type, fields)`
214
212
 
215
- Describes an entity for the documentation. The name is not visible, so
216
- you can put whatever fits (i.e: `:account`, `:user` if the content
217
- differs)
213
+ Describes an entity for the documentation. The type is only a reference,
214
+ you can put whatever fits (i.e: `:account`, `:user`, ...).
218
215
 
219
- They are ideally in the main `describe` block.
216
+ They should be in the main `describe` block.
220
217
 
221
- - `name` is a symbol
218
+ - `type` is a symbol
222
219
  - `description` is a hash of attributes
223
220
 
224
- ```rb
221
+ ```ruby
225
222
  {
226
223
  id: { type: :integer, desc: 'The resource identifier' },
227
224
  name: { type: :string, desc: 'The resource name' },
@@ -253,7 +250,7 @@ An attribute should have the following form:
253
250
  To describe complex structures, use `:object` with `:attributes` and
254
251
  `:array` `:of` something:
255
252
 
256
- ```rb
253
+ ```ruby
257
254
  entity :friend,
258
255
  name: { type: :string, required: false, description: 'Friend name' }
259
256
 
@@ -277,6 +274,15 @@ inline.
277
274
  Both `:of` and `attributes` may be a hash of fields or a symbol. If they
278
275
  are omitted, they will be documented, but responses won't be validated.
279
276
 
277
+ ##### `parameters(type, fields)`
278
+ Describe path or request parameters. The type is only a reference,
279
+ use whatever makes sense. These parameters will be present in
280
+ documentation, only if they are referenced by a `request_params` or
281
+ `path_params` call.
282
+
283
+ Fields have the structure of the hash you would give to `request_params`
284
+ or `path_params` (see each method later in this documentation).
285
+
280
286
  ##### `on_<xxx>(url, description, &block)`
281
287
 
282
288
  Defines an URL.
@@ -294,15 +300,16 @@ For now, only these methods are available:
294
300
  - `on_patch`
295
301
  - `on_delete`
296
302
 
297
- ##### `path_params(<hash_of_attributes>)`
303
+ ##### `path_params(fields: nil, defined: nil)`
298
304
 
299
305
  Defines the path parameters that are used in the URL.
300
306
 
301
- ```rb
307
+ ```ruby
302
308
  on_get '/api/users/:id/posts/:post_slug?full=:full_post' do
303
- path_params id: type: :integer, description: 'The user ID',
304
- post_slug: type: :string, description: 'The post slug',
305
- full_post: type: :boolean, required: false, description: 'Returns the full post if `true`, or only an excerpt'
309
+ path_params fields: {
310
+ id: { type: :integer, description: 'The user ID' },
311
+ post_slug: { type: :string, description: 'The post slug' },
312
+ full_post: { type: :boolean, required: false, description: 'Returns the full post if `true`, or only an excerpt' } }
306
313
 
307
314
  # ...
308
315
  end
@@ -313,18 +320,33 @@ end
313
320
  [CommonMark](https://commonmark.org/)
314
321
  - `required` is optional an defaults to `true`.
315
322
 
316
- ##### `request_params(<hash_of_attributes>)`
323
+ Alternative with defined parameters:
324
+
325
+ ```ruby
326
+ parameters :users_post_path_params,
327
+ id: { type: :integer, description: 'The user ID' },
328
+ post_slug: { type: :string, description: 'The post slug' }
329
+
330
+ on_get '/api/users/:id/posts/:post_slug' do
331
+ path_params defined: :users_post_path_params
332
+
333
+ #...
334
+ end
335
+ ```
336
+
337
+ ##### `request_params(attributes: nil, defined: nil)`
317
338
 
318
339
  Defines the format of the JSON payload. Type `object` is supported, so
319
340
  nested elements can be described:
320
341
 
321
- ```rb
342
+ ```ruby
322
343
  on_post '/api/items' do
323
- request_params item: { type: :object, required: true, properties: {
324
- name: { type: integer, description: 'The name of the new item', required: true },
325
- notes: { type: string, description: 'Additional notes' }
326
- },
327
- }
344
+ request_params attributes: {
345
+ item: { type: :object, required: true, properties: {
346
+ name: { type: integer, description: 'The name of the new item', required: true },
347
+ notes: { type: string, description: 'Additional notes' }
348
+ } }
349
+ }
328
350
  #...
329
351
  end
330
352
  ```
@@ -342,6 +364,23 @@ An attribute should have the following form:
342
364
  - `properties` is a hash of params and is only used if `type: :object`
343
365
  - `of` is a hash of params and is only used if `type: :array`
344
366
 
367
+ Alternative with defined parameters:
368
+
369
+ ```ruby
370
+ parameters :item_form_params,
371
+ item: { type: :object, required: true, properties: {
372
+ name: { type: integer, description: 'The name of the new item', required: true },
373
+ notes: { type: string, description: 'Additional notes' }
374
+ }
375
+ }
376
+
377
+ on_post '/api/items' do
378
+ request_params defined: :item_form_params
379
+
380
+ #...
381
+ end
382
+ ```
383
+
345
384
  ##### `for_code(http_status, description, doc_only: false &block)`
346
385
 
347
386
  Describes the desired output for a precedently defined URL.
@@ -367,10 +406,10 @@ to test.
367
406
  Once again, you have to pass an argument to the block if you use
368
407
  `visit`.
369
408
 
370
- ```rb
409
+ ```ruby
371
410
  # ...
372
- for_code 200 'A successful response' do |example|
373
- visit example
411
+ for_code 200, 'A successful response' do |url|
412
+ visit url
374
413
  # ...
375
414
  end
376
415
  # ...
@@ -395,9 +434,9 @@ Visits the described URL and:
395
434
  requests
396
435
  - `headers`: a hash of custom headers.
397
436
 
398
- ```rb
399
- for_code 200, 'Success' do |example|
400
- visit example
437
+ ```ruby
438
+ for_code 200, 'Success' do |url|
439
+ visit url
401
440
  end
402
441
  ```
403
442
 
@@ -410,9 +449,9 @@ defined entity.
410
449
 
411
450
  It should be compared against a hash or a `response` object:
412
451
 
413
- ```rb
452
+ ```ruby
414
453
  #...
415
- entity user:
454
+ entity :user,
416
455
  id: { type: :integer, desc: 'The id' },
417
456
  name: { type: :string, desc: 'The name' }
418
457
 
@@ -433,11 +472,11 @@ as a defined entity.
433
472
 
434
473
  It should be compared against an array or a `response` object:
435
474
 
436
- ```rb
475
+ ```ruby
437
476
  #...
438
- entity user:
477
+ entity :user,
439
478
  id: { type: :integer, desc: 'The id' },
440
- name: { type: :string, desc: 'The name }'
479
+ name: { type: :string, desc: 'The name' }
441
480
 
442
481
  #...
443
482
 
@@ -456,7 +495,7 @@ expect(response).to have_many defined :user
456
495
  Contexts will break the thing. This is due to how the gem builds its
457
496
  metadata, relying on the parents metadata. You have to stick to the DSL.
458
497
 
459
- ```rb
498
+ ```ruby
460
499
  RSpec.describe 'Categories', type: :request do
461
500
  describe 'Categories'
462
501
 
@@ -494,14 +533,38 @@ There is no support for file fields yet.
494
533
  ## Development
495
534
 
496
535
  After checking out the repo, run `bin/setup` to install dependencies.
497
- Then, run `rake spec` to run the tests. You can also run `bin/console`
536
+ Then, run `bundle exec rspec` to run the tests. You can also run `bin/console`
498
537
  for an interactive prompt that will allow you to experiment.
499
538
 
500
- To install this gem onto your local machine, run `bundle exec rake
501
- install`. To release a new version, update the version number in
502
- `version.rb`, and then run `bundle exec rake release`, which will create
503
- a git tag for the version, push git commits and tags, and push the
504
- `.gem` file to [rubygems.org](https://rubygems.org).
539
+ ### Testing
540
+
541
+ #### Dummy application
542
+
543
+ A small Rails application is available as an example, in the `dummy` directory.
544
+ If you write new features in the library, you'll have to update the examples to
545
+ make them pass their tests:
546
+
547
+ ```shell
548
+ cd dummy
549
+ bundle exec rspec
550
+ ```
551
+
552
+ Doing so will also update the fixtures used by some of the library tests.
553
+
554
+ Please don't commit the fixtures unless the changes in them are directly related
555
+ to the changes in the library.
556
+
557
+ #### Code linting
558
+
559
+ We use Rubocop here, with a releset for the library, and another for the dummy
560
+ application:
561
+
562
+ ```shell
563
+ bundle exec rubocop
564
+
565
+ cd dummy
566
+ bundle exec rubocop
567
+ ```
505
568
 
506
569
  ## Contributing
507
570
 
data/bin/setup CHANGED
@@ -6,3 +6,5 @@ set -vx
6
6
  bundle install
7
7
 
8
8
  # Do any other automated setup that you need to do here
9
+ cd dummy
10
+ bundle install
@@ -21,13 +21,30 @@ module RSpec
21
21
  metadata[:rrad].add_entity type, fields
22
22
  end
23
23
 
24
+ # Used to describe a request or path param which will be available as reference
25
+ def parameters(type, fields)
26
+ metadata[:rrad].add_parameter type, fields
27
+ end
28
+
24
29
  # Used to describe query parameters
25
- def path_params(fields)
30
+ def path_params(fields: nil, defined: nil)
31
+ if defined && !metadata[:rrad].parameters[defined]
32
+ raise "Parameter #{defined} was not defined with the 'parameters' method"
33
+ end
34
+
35
+ fields ||= metadata[:rrad].parameters[defined]
36
+
26
37
  metadata[:rrad].add_path_params fields
27
38
  end
28
39
 
29
- def request_params(fields)
30
- metadata[:rrad].add_request_params fields
40
+ def request_params(attributes: nil, defined: nil)
41
+ if defined && !metadata[:rrad].parameters[defined]
42
+ raise "Parameter #{defined} was not defined with the 'parameters' method"
43
+ end
44
+
45
+ attributes ||= metadata[:rrad].parameters[defined]
46
+
47
+ metadata[:rrad].add_request_params attributes
31
48
  end
32
49
 
33
50
  def on_get(url, description = nil, &block)
@@ -9,11 +9,12 @@ module RSpec
9
9
  module Api
10
10
  # Handles contexts and examples metadatas.
11
11
  class Metadata # rubocop:disable Metrics/ClassLength
12
- attr_reader :entities, :resources, :current_resource
12
+ attr_reader :entities, :resources, :current_resource, :parameters
13
13
 
14
14
  def initialize
15
- @resources = {}
16
- @entities = {}
15
+ @resources = {}
16
+ @entities = {}
17
+ @parameters = {}
17
18
  # Only used when building metadata during RSpec boot
18
19
  @current_resource = nil
19
20
  @current_method = nil
@@ -32,6 +33,12 @@ module RSpec
32
33
  EntityConfig.new(fields))
33
34
  end
34
35
 
36
+ def add_parameter(type, fields)
37
+ raise "Parameter #{type} is already defined" if @parameters[type]
38
+
39
+ @parameters[type] = fields
40
+ end
41
+
35
42
  def add_path_params(fields) # rubocop:disable Metrics/MethodLength
36
43
  check_current_context :resource, :url
37
44
 
@@ -138,7 +145,7 @@ module RSpec
138
145
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Style/GuardClause
139
146
 
140
147
  def path_param_scope(url_chunks, name)
141
- if /:#{name}/ =~ url_chunks[0]
148
+ if /:#{name}/.match?(url_chunks[0])
142
149
  :path
143
150
  elsif url_chunks[1] && /:#{name}/ =~ url_chunks[1]
144
151
  :query
@@ -19,7 +19,7 @@ module RSpec
19
19
  def initialize
20
20
  @metadata = { resources: {}, entities: {} }
21
21
  @api_infos = {}
22
- @api_servers = {}
22
+ @api_servers = []
23
23
  @api_paths = {}
24
24
  @api_components = {}
25
25
  @api_tags = []
@@ -27,11 +27,12 @@ module RSpec
27
27
  @api_license = {}
28
28
  end
29
29
 
30
- def merge_context(context)
30
+ def merge_context(context, dump_metadata: false)
31
31
  @metadata[:resources].deep_merge! context[:resources]
32
32
  @metadata[:entities].deep_merge! context[:entities]
33
- # Save context to make the fixture (will be saved in the reference project)
34
- # File.write ::Rails.root.join('tmp', 'meta.yaml'), context.to_yaml
33
+
34
+ # Save context for debug and fixtures
35
+ File.write ::Rails.root.join('tmp', 'rra_metadata.yaml'), context.to_yaml if dump_metadata
35
36
  end
36
37
 
37
38
  def write_files(path = nil, only: %i[yaml json])
@@ -3,7 +3,7 @@
3
3
  module RSpec
4
4
  module Rails
5
5
  module Api
6
- VERSION = '0.1.5'
6
+ VERSION = '0.2.0'
7
7
  end
8
8
  end
9
9
  end
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  # Specify which files should be added to the gem when it is released.
27
27
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
28
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
29
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|dummy)/}) }
30
30
  end
31
31
  spec.bindir = 'exe'
32
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-rails-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Tancoigne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-30 00:00:00.000000000 Z
11
+ date: 2019-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -144,7 +144,6 @@ files:
144
144
  - Rakefile
145
145
  - bin/console
146
146
  - bin/setup
147
- - examples/commented.rb
148
147
  - lib/rspec/rails/api/dsl/example.rb
149
148
  - lib/rspec/rails/api/dsl/example_group.rb
150
149
  - lib/rspec/rails/api/entity_config.rb
@@ -1,167 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'acceptance_helper'
4
-
5
- RSpec.describe 'Categories', type: :acceptance do
6
- # Needed to initialize documentation for this type of request.
7
- # It should come before all the other calls (it will let the metadata
8
- # class know which resource we're dealing with)
9
- resource 'Categories', 'Manage categories in a group'
10
-
11
- # Define an entity that can be returned by an URL.
12
- entity :category,
13
- id: { type: :integer, description: 'The id' },
14
- name: { type: :string, description: 'The name' },
15
- group_id: { type: :number, description: 'Concerned group' },
16
- created_at: { type: :datetime, description: 'Creation date' },
17
- updated_at: { type: :datetime, description: 'Modification date' },
18
- url: { type: :string, description: 'URL to this category' }
19
-
20
- entity :error,
21
- error: { type: :string, description: 'The error' }
22
-
23
- entity :form_error,
24
- errors: {
25
- type: :object, description: 'Form errors', attributes: {
26
- name: { type: :array, description: 'Name errors' },
27
- group: { type: :array, description: 'Group errors' },
28
- }
29
- }
30
-
31
- # Some vars to use in the tests
32
- let(:current_user) { FactoryBot.create :user_active }
33
-
34
- let(:group) { current_user.groups.first }
35
- let(:group_id) { group.id }
36
- let(:category) { FactoryBot.create :category, user: current_user, group: group }
37
-
38
- # Declare a path accessed with a given method
39
- # Their values can be declared with a "let(:var){ value }" statement,
40
- # or passed to "visit" method (see "for_code 404")
41
- on_get '/api/groups/:group_id/categories', 'Categories defined in the given group' do
42
- # Declare path parameters for documentation
43
- path_params group_id: { type: :integer, description: 'Target group identifier' }
44
-
45
- # Expectations for the given HTTP status
46
- for_code 200, 'Success' do |example|
47
- FactoryBot.create_list :category, 2, user: current_user, group: group
48
-
49
- # This method is not built-in; check: ../README.md
50
- sign_in current_user
51
-
52
- # Actually visit the path. It will expect the given code and a
53
- # content of type "application/JSON" (except for 204: no content
54
- # statuses)
55
- visit example
56
-
57
- # Custom matcher: have_many will expect a body with an array of
58
- # the given entity. All entries in the response will have its keys
59
- # checked (not the content type).
60
- # The `defined` method will get the correct entity for comparison
61
- expect(response).to have_many defined :category
62
-
63
- # Other expectations
64
- expect(JSON.parse(response.body).count).to eq 2
65
- end
66
-
67
- for_code 404, 'Not found (not owned)' do |example|
68
- sign_in current_user
69
-
70
- group_id = FactoryBot.create(:user_active).groups.first.id
71
-
72
- visit example, path_params: { group_id: group_id }
73
- expect(response).to have_one defined :error
74
- end
75
-
76
- for_code 401, 'Not authorized' do |example|
77
- visit example
78
- expect(response).to have_one defined :error
79
- end
80
- end
81
-
82
- on_get '/api/groups/:group_id/categories/:id', 'Get category' do
83
- path_params group_id: { type: :integer, description: 'Target group identifier' },
84
- id: { type: :integer, description: 'Category id' }
85
-
86
- let(:id) { category.id }
87
-
88
- for_code 200, 'Success' do |example|
89
- sign_in current_user
90
-
91
- visit example
92
- expect(response).to have_one defined :category
93
- end
94
-
95
- for_code 401, 'Not authorized' do |example|
96
- visit example
97
- expect(response).to have_one defined :error
98
- end
99
-
100
- for_code 404, 'Not found' do |example|
101
- sign_in current_user
102
-
103
- visit example, path_params: { id: 0 }
104
- expect(response).to have_one defined :error
105
- end
106
- end
107
-
108
- on_post '/api/groups/:group_id/categories', 'Creates a category' do
109
- path_params group_id: { type: :integer, description: 'Target group identifier' }
110
-
111
- request_params category: {
112
- type: :object, required: true, attributes: {
113
- name: { type: :string, required: true, description: 'The name' },
114
- }
115
- }
116
-
117
- let(:id) { category.id }
118
-
119
- for_code 201, 'Success' do |example|
120
- sign_in current_user
121
-
122
- visit example, payload: { category: { name: 'New category' } }
123
- expect(response).to have_one defined :category
124
- end
125
-
126
- for_code 422, 'Form error' do |example|
127
- sign_in current_user
128
-
129
- visit example, payload: { category: {} }
130
- expect(response).to have_one defined :form_error
131
- end
132
- end
133
-
134
- on_put '/api/groups/:group_id/categories/:id', 'Updates a category' do
135
- path_params group_id: { type: :integer, description: 'Target group identifier' },
136
- id: { type: :integer, description: 'Category id' }
137
-
138
- let(:id) { category.id }
139
-
140
- request_params category: {
141
- type: :object, required: true, description: 'New category attributes', attributes: {
142
- name: { type: :string, required: false, description: 'The new name' },
143
- }
144
- }
145
-
146
- for_code 200, 'Success' do |example|
147
- sign_in current_user
148
-
149
- visit example, payload: { category: { name: 'New name' } }
150
- expect(response).to have_one defined :category
151
- end
152
- end
153
-
154
- on_delete '/api/groups/:group_id/categories/:id', 'Deletes a category' do
155
- path_params group_id: { type: :integer, description: 'Target group identifier' },
156
- id: { type: :integer, description: 'Category id' }
157
-
158
- let(:id) { category.id }
159
-
160
- for_code 204, 'Success' do |example|
161
- sign_in current_user
162
-
163
- visit example
164
- # Not checking content for 204 responses
165
- end
166
- end
167
- end