stub_requests 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -2
  3. data/.reek.yml +1 -0
  4. data/.rubocop.yml +33 -35
  5. data/.simplecov +14 -8
  6. data/.yardopts +1 -1
  7. data/CHANGELOG.md +4 -1
  8. data/README.md +19 -11
  9. data/Rakefile +1 -3
  10. data/bin/update_docs.sh +16 -0
  11. data/gemfiles/webmock_2.3.gemfile.lock +1 -1
  12. data/gemfiles/webmock_3.5.gemfile.lock +1 -1
  13. data/gemfiles/webmock_develop.gemfile.lock +1 -1
  14. data/lib/rspec/subject_as_lambda.rb +138 -0
  15. data/lib/stub_requests/api.rb +42 -8
  16. data/lib/stub_requests/argument_validation.rb +17 -6
  17. data/lib/stub_requests/configuration.rb +21 -0
  18. data/lib/stub_requests/core_ext/all.rb +4 -0
  19. data/lib/stub_requests/core_ext/array/extract_options.rb +32 -0
  20. data/lib/stub_requests/core_ext/class/attribute.rb +61 -0
  21. data/lib/stub_requests/core_ext/kernel/singleton_class.rb +12 -0
  22. data/lib/stub_requests/core_ext/module/redefine_method.rb +44 -0
  23. data/lib/stub_requests/core_ext/object/blank.rb +99 -155
  24. data/lib/stub_requests/endpoint.rb +28 -30
  25. data/lib/stub_requests/endpoint_registry.rb +18 -16
  26. data/lib/stub_requests/exceptions.rb +84 -0
  27. data/lib/stub_requests/hash_util.rb +2 -0
  28. data/lib/stub_requests/metrics/endpoint_stat.rb +97 -0
  29. data/lib/stub_requests/metrics/registry.rb +132 -0
  30. data/lib/stub_requests/metrics/stub_stat.rb +80 -0
  31. data/lib/stub_requests/metrics.rb +32 -0
  32. data/lib/stub_requests/property/validator.rb +136 -0
  33. data/lib/stub_requests/property.rb +99 -0
  34. data/lib/stub_requests/service.rb +12 -53
  35. data/lib/stub_requests/service_registry.rb +8 -9
  36. data/lib/stub_requests/stub_requests.rb +23 -51
  37. data/lib/stub_requests/uri/builder.rb +5 -1
  38. data/lib/stub_requests/uri/scheme.rb +3 -1
  39. data/lib/stub_requests/uri/suffix.rb +5 -0
  40. data/lib/stub_requests/uri/validator.rb +3 -1
  41. data/lib/stub_requests/uri.rb +34 -0
  42. data/lib/stub_requests/version.rb +1 -1
  43. data/lib/stub_requests/webmock/builder.rb +116 -0
  44. data/lib/stub_requests/webmock/stub_registry_extension.rb +46 -0
  45. data/lib/stub_requests.rb +21 -3
  46. metadata +19 -49
  47. data/docs/.gitkeep +0 -0
  48. data/docs/Array.html +0 -137
  49. data/docs/FalseClass.html +0 -232
  50. data/docs/Hash.html +0 -137
  51. data/docs/NilClass.html +0 -232
  52. data/docs/Numeric.html +0 -233
  53. data/docs/Object.html +0 -396
  54. data/docs/String.html +0 -298
  55. data/docs/StubRequests/API.html +0 -651
  56. data/docs/StubRequests/ArgumentValidation.html +0 -309
  57. data/docs/StubRequests/Endpoint.html +0 -1187
  58. data/docs/StubRequests/EndpointNotFound.html +0 -157
  59. data/docs/StubRequests/EndpointRegistry.html +0 -1527
  60. data/docs/StubRequests/Error.html +0 -153
  61. data/docs/StubRequests/HashUtil.html +0 -304
  62. data/docs/StubRequests/InvalidType.html +0 -252
  63. data/docs/StubRequests/InvalidUri.html +0 -252
  64. data/docs/StubRequests/Service.html +0 -1307
  65. data/docs/StubRequests/ServiceHaveEndpoints.html +0 -244
  66. data/docs/StubRequests/ServiceNotFound.html +0 -252
  67. data/docs/StubRequests/ServiceRegistry.html +0 -1031
  68. data/docs/StubRequests/URI/Builder.html +0 -1194
  69. data/docs/StubRequests/URI/Scheme.html +0 -315
  70. data/docs/StubRequests/URI/Suffix.html +0 -315
  71. data/docs/StubRequests/URI/Validator.html +0 -770
  72. data/docs/StubRequests/URI.html +0 -144
  73. data/docs/StubRequests/UriSegmentMismatch.html +0 -157
  74. data/docs/StubRequests/WebMockBuilder.html +0 -887
  75. data/docs/StubRequests.html +0 -452
  76. data/docs/Time.html +0 -232
  77. data/docs/TrueClass.html +0 -232
  78. data/docs/_config.yml +0 -1
  79. data/docs/_index.html +0 -391
  80. data/docs/class_list.html +0 -51
  81. data/docs/css/common.css +0 -1
  82. data/docs/css/full_list.css +0 -58
  83. data/docs/css/style.css +0 -496
  84. data/docs/file.README.html +0 -225
  85. data/docs/file_list.html +0 -56
  86. data/docs/frames.html +0 -17
  87. data/docs/index.html +0 -225
  88. data/docs/js/app.js +0 -292
  89. data/docs/js/full_list.js +0 -216
  90. data/docs/js/jquery.js +0 -4
  91. data/docs/method_list.html +0 -707
  92. data/docs/top-level-namespace.html +0 -112
  93. data/lib/stub_requests/webmock_builder.rb +0 -108
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc8e6e325329977ce50cecf33f1261c7194afdfa9dd63f2d18627fd9228aaf2b
4
- data.tar.gz: d581dbdc2d0c56d55e634754876b62a2ee38cad988c1b9474971308bf51c08e5
3
+ metadata.gz: 521fcf52479aee73bde3bacc79d67c6d4a45032000b5db6c52aa74d11f96135b
4
+ data.tar.gz: a762b8db4bda856bf186c50974c16f2ca0668d9e3fe5dc77c84d6e096de938f6
5
5
  SHA512:
6
- metadata.gz: 516de1eae065073fb7e97d73793283943e22d2b328de5d1cd870aefbb068e3f8b3d7c149280a186c3c19ae9d84d2aaa6cdb7dc3a53532f5dec3776225804a102
7
- data.tar.gz: 0bae1c15d8fa2101f1c205d0424524d626ea0599cfe07e15da374bdee39891759a57f53b379459e7e97d7b583430a9cde2d5ad15b8a3f9ec3d67b6b9b854f47f
6
+ metadata.gz: 94eaf0edd7a35e83f6321189e775e6e90290ddfac63117e60f07b86aea9b84fffa6b363f8014e6629ff6214324c99d8b1686a113cd5f3a89ed8199191a200a18
7
+ data.tar.gz: 10084a0c36f0e7c857f19615312fe018fab42272468a72a74e62747113b15953e2706f25965d81f80f50a7d21f56b339d2c37d58b696ad41c274eb63cefbccce
data/.gitignore CHANGED
@@ -1,10 +1,13 @@
1
1
  /.bundle/
2
+ /.rspec_status
2
3
  /.yardoc
3
4
  /_yardoc/
4
5
  /coverage/
5
6
  /doc/
7
+ /docs
6
8
  /pkg/
7
9
  /spec/reports/
8
10
  /tmp/
9
- /Gemfile.lock
10
- .rspec_status
11
+
12
+ Gemfile.lock
13
+ .DS_store
data/.reek.yml CHANGED
@@ -11,3 +11,4 @@ detectors:
11
11
  exclude_paths:
12
12
  - vendor/bundle
13
13
  - gemfiles
14
+ - lib/stub_requests/core_ext/
data/.rubocop.yml CHANGED
@@ -12,17 +12,15 @@ AllCops:
12
12
  - "lib/**/*"
13
13
  - "bin/**/*"
14
14
  - "spec/**/*"
15
+ - ".simplecov"
15
16
  Exclude:
16
17
  - "lib/stub_requests/core_ext/**/*"
17
18
  - "Gemfile.lock"
18
19
  - "bin/setup"
19
20
  - "gemfiles/**/*"
20
21
 
21
- Lint/HandleExceptions:
22
- Enabled: true
23
-
24
- Lint/UselessAssignment:
25
- Enabled: true
22
+ Layout/IndentArray:
23
+ EnforcedStyle: consistent
26
24
 
27
25
  Metrics/AbcSize:
28
26
  Max: 38
@@ -37,7 +35,6 @@ Metrics/MethodLength:
37
35
  Max: 13
38
36
 
39
37
  Metrics/BlockLength:
40
- Enabled: true
41
38
  Exclude:
42
39
  - '**/spec/**/*.rb'
43
40
  - '**/*.rake'
@@ -45,14 +42,7 @@ Metrics/BlockLength:
45
42
  Metrics/PerceivedComplexity:
46
43
  Max: 8
47
44
 
48
- Naming/AccessorMethodName:
49
- Enabled: true
50
-
51
- Naming/ConstantName:
52
- Enabled: true
53
-
54
45
  Naming/FileName:
55
- Enabled: true
56
46
  Exclude:
57
47
  - '**/Gemfile'
58
48
 
@@ -60,55 +50,63 @@ Naming/UncommunicativeMethodParamName:
60
50
  AllowedNames:
61
51
  - ex
62
52
 
63
- RSpec/AlignLeftLetBrace:
53
+ AlignLeftLetBrace:
64
54
  Enabled: true
65
55
 
56
+ RSpec/ContextWording:
57
+ Prefixes:
58
+ - when
59
+ - with
60
+ - without
61
+ - if
62
+ - given
63
+ - for
64
+ - and
65
+
66
+ RSpec/EmptyExampleGroup:
67
+ Enabled: false
68
+ CustomIncludeMethods:
69
+ - let!
70
+ - specfify!
71
+
66
72
  RSpec/FilePath:
67
- Enabled: true
68
73
  Exclude:
69
- - 'spec/stub_requests/webmock_builder_spec.rb'
74
+ - spec/stub_requests/webmock/builder_spec.rb
70
75
 
71
- RSpec/NestedGroups:
72
- Max: 4
73
- Enabled: true
76
+ RSpec/ImplicitSubject:
77
+ Enabled: false
78
+ EnforcedStyle: single_statement_only
74
79
 
75
- Style/FrozenStringLiteralComment:
76
- Enabled: true
80
+ RSpec/MultipleDescribes:
81
+ Exclude:
82
+ - spec/stub_requests/core_ext/object/blank_spec.rb
77
83
 
78
- Style/Documentation:
79
- Enabled: true
84
+ RSpec/NamedSubject:
85
+ Exclude:
86
+ - spec/stub_requests/core_ext/object/blank_spec.rb
80
87
 
81
- Style/GlobalVars:
82
- Enabled: true
88
+ RSpec/NestedGroups:
89
+ Max: 4
83
90
 
84
91
  Style/ModuleFunction:
85
- Enabled: false
92
+ EnforcedStyle: extend_self
86
93
 
87
94
  Style/StringLiterals:
88
- Enabled: true
89
95
  EnforcedStyle: double_quotes
90
96
  ConsistentQuotesInMultiline: true
91
97
 
92
- Style/StringLiteralsInInterpolation:
93
- Enabled: true
94
-
95
98
  Style/SymbolArray:
96
- Enabled: true
97
99
  EnforcedStyle: brackets
98
100
 
99
101
  Style/TernaryParentheses:
100
- Enabled: true
101
102
  EnforcedStyle: require_parentheses_when_complex
102
103
  AllowSafeAssignment: true
103
104
 
104
105
  Style/TrailingCommaInArguments:
105
- Enabled: true
106
106
  EnforcedStyleForMultiline: comma
107
107
 
108
108
  Style/TrailingCommaInArrayLiteral:
109
- Enabled: true
110
109
  EnforcedStyleForMultiline: comma
111
110
 
112
111
  Style/TrailingCommaInHashLiteral:
113
- Enabled: true
114
112
  EnforcedStyleForMultiline: comma
data/.simplecov CHANGED
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "simplecov-json"
2
4
 
3
- SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
4
- SimpleCov::Formatter::HTMLFormatter,
5
- SimpleCov::Formatter::JSONFormatter,
6
- ])
5
+ SimpleCov.formatters =
6
+ SimpleCov::Formatter::MultiFormatter.new([
7
+ SimpleCov::Formatter::HTMLFormatter,
8
+ SimpleCov::Formatter::JSONFormatter,
9
+ ])
7
10
 
8
11
  SimpleCov.configure do
9
12
  command_name "RSpec"
@@ -16,8 +19,11 @@ SimpleCov.configure do
16
19
  end
17
20
 
18
21
  SimpleCov.start do
19
- add_filter '/spec/'
20
- add_filter '/bin/'
21
- add_filter '/gemfiles/'
22
- add_filter '/examples/'
22
+ add_filter "/spec/"
23
+ add_filter "/bin/"
24
+ add_filter "/gemfiles/"
25
+ add_filter "/lib/stub_requests/core_ext/array/extract_options.rb"
26
+ add_filter "/lib/stub_requests/core_ext/class/attribute.rb"
27
+ add_filter "/lib/stub_requests/core_ext/kernel/singleton_class.rb"
28
+ add_filter "/lib/stub_requests/core_ext/module/redefine_method.rb"
23
29
  end
data/.yardopts CHANGED
@@ -1 +1 @@
1
- --no-private --output-dir docs lib/stub_requests/**/*.rb --markup-provider=redcarpet --markup=markdown - README.md
1
+ --no-private --markup-provider=redcarpet --markup=markdown lib/stub_requests/**/*.rb - README.md
data/CHANGELOG.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  **Merged pull requests:**
8
8
 
9
+ - Allow older webmock versions [\#4](https://github.com/mhenrixon/stub_requests/pull/4) ([mhenrixon](https://github.com/mhenrixon))
10
+ - Add docs folder [\#3](https://github.com/mhenrixon/stub_requests/pull/3) ([mhenrixon](https://github.com/mhenrixon))
9
11
  - Add docs folder and CHANGELOG.md [\#2](https://github.com/mhenrixon/stub_requests/pull/2) ([mhenrixon](https://github.com/mhenrixon))
10
12
 
11
13
  ## [v0.1.0](https://github.com/mhenrixon/stub_requests/tree/v0.1.0) (2019-02-01)
@@ -14,4 +16,5 @@
14
16
  - Add rough initial implementation [\#1](https://github.com/mhenrixon/stub_requests/pull/1) ([mhenrixon](https://github.com/mhenrixon))
15
17
 
16
18
 
17
- \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
19
+
20
+ \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
data/README.md CHANGED
@@ -16,9 +16,11 @@ This is achieve by keeping a registry over the service endpoints.
16
16
 
17
17
  - [Installation](#installation)
18
18
  - [Usage](#usage)
19
+ - [Register service endpoints](#register-service-endpoints)
20
+ - [Stubbing service endpoints](#stubbing-service-endpoints)
21
+ - [Metrics](#metrics)
19
22
  - [Future Improvements](#future-improvements)
20
23
  - [API Client Gem](#api-client-gem)
21
- - [Debugging](#debugging)
22
24
  - [Development](#development)
23
25
  - [Contributing](#contributing)
24
26
  - [License](#license)
@@ -54,6 +56,9 @@ To use the gem we need to register some service endpoints. In the following exam
54
56
 
55
57
  The naming of the `service_id` and `endpoint_id`'s is irrelevant. This is just how we look things up in the registry.
56
58
 
59
+ <a id="register-service-endpoints"></a>
60
+ ### Register service endpoints
61
+
57
62
  ```ruby
58
63
  StubRequests.register_service(:google_ads, "https://api.google.com/v5") do
59
64
  register(:index, :get, "ads")
@@ -66,6 +71,9 @@ end
66
71
 
67
72
  Now we have a list of endpoints we can stub.
68
73
 
74
+ <a id="stubbing-service-endpoints"></a>
75
+ ### Stubbing service endpoints
76
+
69
77
  ```ruby
70
78
  StubRequests.stub_endpoint(:google_ads, :index)
71
79
  .to_return(code: 204, body: "")
@@ -77,8 +85,6 @@ WebMock.stub_request(:get, "#{Settings.google_ads_base_uri}/ads")
77
85
  .to_return(status: 204, body: "")
78
86
  ```
79
87
 
80
- So far so good but not much of a gain yet. The real power comes when we don't have to interpolate a bunch of URLs all the time.
81
-
82
88
  ```ruby
83
89
  StubRequests.stub_endpoint(:google_ads, :update, id: 1) do
84
90
  with(body: request_body.to_json)
@@ -93,11 +99,18 @@ WebMock.stub_request(:patch, "#{Settings.google_ads_base_uri}/ads/#{id}")
93
99
  .to_return(status: 200, body: response_body.to_json)
94
100
  ```
95
101
 
96
- First of all we reduce a lot of duplication.
102
+ This reduces the need to spread out URI's in the test suite without having to resort to shared examples.
97
103
 
98
- Imagine a code base with thousands of stubbed request. You always have to look at the defined URL to understand which request is actually being called.
104
+ <a id="metrics"></a>
105
+ ### Metrics
99
106
 
100
- Madness!!
107
+ Metrics collection are by default turned off. It can be turned on by the following code.
108
+
109
+ ```ruby
110
+ StubRequests.configure do |config|
111
+ config.record_metrics = true
112
+ end
113
+ ```
101
114
 
102
115
  <a id="future-improvements"></a>
103
116
  ## Future Improvements
@@ -111,11 +124,6 @@ sense to make this into an API client. Not sure yet, maybe this will become mult
111
124
  Anyway, the idea was to provide endpoint calls in production and stubbed
112
125
  requests in tests using the same registry.
113
126
 
114
- <a id="debugging"></a>
115
- ### Debugging
116
-
117
- I want to provide information about where a request stub was created from. In the project I am currently working this would have saved me a days work already.
118
-
119
127
  <a id="development"></a>
120
128
  ## Development
121
129
 
data/Rakefile CHANGED
@@ -12,11 +12,9 @@ YARD::Rake::YardocTask.new do |t|
12
12
  t.files = %w[lib/stub_requests/**/*.rb"]
13
13
  t.options = %w[
14
14
  --no-private
15
- --output-dir docs
16
- --readme README.md
17
- --output-dir docs
18
15
  --markup=markdown
19
16
  --markup-provider=redcarpet
17
+ --readme README.md
20
18
  ]
21
19
  end
22
20
 
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+
3
+ git checkout master
4
+ git pull --rebase
5
+
6
+ rake yard
7
+
8
+ git checkout gh-pages
9
+
10
+ shopt -s extglob
11
+ rm -rf "$(echo ./!(bin|_config.yml|_index.html))"
12
+
13
+ mv doc/* ./
14
+ git commit -a -m 'Update documentation'
15
+ git push
16
+
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- stub_requests (0.1.0)
4
+ stub_requests (0.1.1)
5
5
  concurrent-ruby (~> 1.0, < 2)
6
6
  docile (~> 1.0, < 2)
7
7
  public_suffix (~> 3.0, < 4)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- stub_requests (0.1.0)
4
+ stub_requests (0.1.1)
5
5
  concurrent-ruby (~> 1.0, < 2)
6
6
  docile (~> 1.0, < 2)
7
7
  public_suffix (~> 3.0, < 4)
@@ -10,7 +10,7 @@ GIT
10
10
  PATH
11
11
  remote: ..
12
12
  specs:
13
- stub_requests (0.1.0)
13
+ stub_requests (0.1.1)
14
14
  concurrent-ruby (~> 1.0, < 2)
15
15
  docile (~> 1.0, < 2)
16
16
  public_suffix (~> 3.0, < 4)
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec/core"
4
+
5
+ module RSpec
6
+ #
7
+ # SubjectAsLambda provides a convenient way of turning a regular subject into a proc
8
+ #
9
+ # @author Mikael Henriksson <mikael@zoolutions.se>
10
+ #
11
+ module SubjectAsLambda
12
+ # Creates a nested example group named by the submitted `attribute`,
13
+ # and then generates an example using the submitted block.
14
+ #
15
+ # @example
16
+ #
17
+ # # This ...
18
+ # describe Array do
19
+ # its(:size) { should eq(0) }
20
+ # end
21
+ #
22
+ # # ... generates the same runtime structure as this:
23
+ # describe Array do
24
+ # describe "size" do
25
+ # it "should eq(0)" do
26
+ # subject.size.should eq(0)
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # The attribute can be a `Symbol` or a `String`. Given a `String`
32
+ # with dots, the result is as though you concatenated that `String`
33
+ # onto the subject in an expression.
34
+ #
35
+ # @example
36
+ #
37
+ # describe Person do
38
+ # subject do
39
+ # Person.new.tap do |person|
40
+ # person.phone_numbers << "555-1212"
41
+ # end
42
+ # end
43
+ #
44
+ # its("phone_numbers.first") { should eq("555-1212") }
45
+ # end
46
+ #
47
+ # When the subject is a `Hash`, you can refer to the Hash keys by
48
+ # specifying a `Symbol` or `String` in an array.
49
+ #
50
+ # @example
51
+ #
52
+ # describe "a configuration Hash" do
53
+ # subject do
54
+ # { :max_users => 3,
55
+ # 'admin' => :all_permissions.
56
+ # 'john_doe' => {:permissions => [:read, :write]}}
57
+ # end
58
+ #
59
+ # its([:max_users]) { should eq(3) }
60
+ # its(['admin']) { should eq(:all_permissions) }
61
+ # its(['john_doe', :permissions]) { should eq([:read, :write]) }
62
+ #
63
+ # # You can still access its regular methods this way:
64
+ # its(:keys) { should include(:max_users) }
65
+ # its(:count) { should eq(2) }
66
+ # end
67
+ #
68
+ # With an implicit subject, `is_expected` can be used as an alternative
69
+ # to `should` (e.g. for one-liner use). An `are_expected` alias is also
70
+ # supplied.
71
+ #
72
+ # @example
73
+ #
74
+ # describe Array do
75
+ # its(:size) { is_expected.to eq(0) }
76
+ # end
77
+ #
78
+ # You can pass more than one argument on the `its` block to add
79
+ # some metadata to the generated example
80
+ #
81
+ # @example
82
+ #
83
+ # # This ...
84
+ # describe Array do
85
+ # its(:size, :focus) { should eq(0) }
86
+ # end
87
+ #
88
+ # # ... generates the same runtime structure as this:
89
+ # describe Array do
90
+ # describe "size" do
91
+ # it "should eq(0)", :focus do
92
+ # subject.size.should eq(0)
93
+ # end
94
+ # end
95
+ # end
96
+ #
97
+ # Note that this method does not modify `subject` in any way, so if you
98
+ # refer to `subject` in `let` or `before` blocks, you're still
99
+ # referring to the outer subject.
100
+ #
101
+ # @example
102
+ #
103
+ # describe Person do
104
+ # subject { Person.new }
105
+ # before { subject.age = 25 }
106
+ # its(:age) { should eq(25) }
107
+ # end
108
+ # :reek:DuplicateMethodCall
109
+ # :reek:TooManyStatements
110
+ def it!(*options, &block)
111
+ it_lambda_caller = caller.reject { |file_line| file_line =~ %r{/rspec/subject_as_lambda} }
112
+ describe(nil, caller: it_lambda_caller) do
113
+ let(:__it_lambda_subject) do
114
+ subject
115
+ end
116
+
117
+ def is_expected # rubocop:disable Lint/NestedMethodDefinition, Naming/PredicateName
118
+ expect { __it_lambda_subject }
119
+ end
120
+ alias_method :are_expected, :is_expected
121
+
122
+ options << {} unless options.last.is_a?(Hash)
123
+ options.last[:caller] = it_lambda_caller
124
+
125
+ example(nil, *options, &block)
126
+ end
127
+ end
128
+
129
+ alias specify! it!
130
+ end
131
+ end
132
+
133
+ RSpec.configure do |rspec|
134
+ rspec.extend RSpec::SubjectAsLambda
135
+ rspec.backtrace_exclusion_patterns << %r{/lib/rspec/subject_as_lambda}
136
+ end
137
+
138
+ RSpec::SharedContext.send(:include, RSpec::SubjectAsLambda)
@@ -13,11 +13,23 @@ module StubRequests
13
13
  # @note This module can either be used by its class methods
14
14
  # or included in say RSpec
15
15
  #
16
+ # @author Mikael Henriksson <mikael@zoolutions.se>
17
+ #
18
+ # :reek:DataClump
16
19
  module API
17
20
  # extends "self"
18
21
  # @!parse extend self
19
22
  extend self
20
23
 
24
+ # :reek:LongParameterList { max_params: 4 }
25
+ # @api private
26
+ def self._stub_endpoint(service_id, endpoint_id, uri_replacements = {}, options = {})
27
+ _service, endpoint, uri = StubRequests::URI.for_service_endpoint(service_id, endpoint_id, uri_replacements)
28
+ endpoint_stub = WebMock::Builder.build(endpoint.verb, uri, options)
29
+
30
+ ::WebMock::StubRegistry.instance.register_request_stub(endpoint_stub)
31
+ end
32
+
21
33
  # :nodoc:
22
34
  def self.included(base)
23
35
  base.send(:extend, self)
@@ -25,49 +37,71 @@ module StubRequests
25
37
 
26
38
  # Register a service in the service registry
27
39
  #
40
+ #
28
41
  # @param [Symbol] service_id a descriptive id for the service
29
42
  # @param [Symbol] service_uri the uri used to call the service
30
43
  #
44
+ # @example Register a service with endpoints
45
+ # register_service(:documents, "https://company.com/api/v1") do
46
+ # register_endpoints do
47
+ # register(:show, :get, "documents/:id")
48
+ # register(:index, :get, "documents")
49
+ # register(:create, :post, "documents")
50
+ # register(:update, :patch, "documents/:id")
51
+ # register(:destroy, :delete, "documents/:id")
52
+ # end
53
+ # end
54
+ #
31
55
  # @return [Service] a new service or a previously registered service
32
56
  #
33
57
  # :reek:UtilityFunction
34
58
  def register_service(service_id, service_uri, &block)
35
- service = ServiceRegistry.instance.register_service(service_id, service_uri)
36
- Docile.dsl_eval(service.endpoint_registry, &block) if block.present?
59
+ service = ServiceRegistry.instance.register(service_id, service_uri)
60
+ Docile.dsl_eval(service.endpoints, &block) if block.present?
37
61
  service
38
62
  end
39
63
 
40
64
  #
41
65
  # Stub a request to a registered service endpoint
42
66
  #
67
+ #
43
68
  # @param [Symbol] service_id the id of a registered service
44
69
  # @param [Symbol] endpoint_id the id of a registered endpoint
45
- # @param [Hash<Symbol>] uri_replacements a list of uri replacements
70
+ # @param [Hash<Symbol>] uri_replacements a list of URI replacements
46
71
  # @param [Hash<Symbol>] options
47
72
  # @option options [optional, Hash<Symbol>] :request webmock request options
48
73
  # @option options [optional, Hash<Symbol>] :response webmock response options
49
74
  # @option options [optional, Array, Exception, StandardError, String] :error webmock error to raise
50
- # @option options [optional, TrueClass] :timeout set to truthy to raise timeeout with webmock
75
+ # @option options [optional, TrueClass] :timeout set to true to raise some kind of timeout error
76
+ #
77
+ # @note the kind of timeout error raised by webmock is depending on the HTTP client used
51
78
  #
52
79
  # @example Stub a request to a registered service endpoint
53
80
  # register_stub(
54
81
  # :google_api,
55
82
  # :get_map_location,
83
+ # {}, # No URI replacements needed for this endpoint
56
84
  # { request: { headers: { "Accept" => "application/json" }}},
57
85
  # { response: { body: { id: "abyasdjasd", status: "successful" }}}
58
86
  # )
59
87
  #
88
+ # @example Stub a request to a registered service endpoint using block version
89
+ # register_stub(:documents, :index) do
90
+ # with(headers: { "Accept" => "application/json" }}})
91
+ # to_return(body: "No content", status: 204)
92
+ # end
93
+ #
60
94
  # @see #stub_http_request
61
95
  # @return [WebMock::RequestStub] a mocked request
62
96
  #
63
97
  # :reek:UtilityFunction
64
98
  # :reek:LongParameterList { max_params: 5 }
65
99
  def stub_endpoint(service_id, endpoint_id, uri_replacements = {}, options = {}, &callback)
66
- service = ServiceRegistry.instance.get_service!(service_id)
67
- endpoint = service.get_endpoint!(endpoint_id)
68
- uri = URI::Builder.build(service.uri, endpoint.uri_template, uri_replacements)
100
+ service, endpoint, uri = StubRequests::URI.for_service_endpoint(service_id, endpoint_id, uri_replacements)
101
+ endpoint_stub = WebMock::Builder.build(endpoint.verb, uri, options, &callback)
69
102
 
70
- StubRequests::WebMockBuilder.build(endpoint.verb, uri, options, &callback)
103
+ Metrics.record(service, endpoint, endpoint_stub)
104
+ ::WebMock::StubRegistry.instance.register_request_stub(endpoint_stub)
71
105
  end
72
106
  end
73
107
  end
@@ -13,6 +13,8 @@ module StubRequests
13
13
  #
14
14
  # Module ArgumentValidation provides validation of method arguments
15
15
  #
16
+ # @author Mikael Henriksson <mikael@zoolutions.se>
17
+ #
16
18
  module ArgumentValidation
17
19
  extend self
18
20
 
@@ -23,17 +25,26 @@ module StubRequests
23
25
  # @param [Object] value the value to validate
24
26
  # @param [Array<Class>, Array<Module>, Class, Module] is_a
25
27
  #
26
- # @raise [InvalidType] when the value is disallowed
28
+ # @raise [InvalidArgumentType] when the value is disallowed
27
29
  #
28
30
  # @return [true] when the value is allowed
29
31
  #
30
- def validate!(value, is_a:)
31
- expected_types = Array(is_a)
32
- return true if expected_types.any? { |type| value.is_a?(type) }
32
+ # :reek:UtilityFunction
33
+ def validate!(name, value, is_a:)
34
+ validate! :name, name, is_a: [Symbol, String] unless name
35
+
36
+ expected_types = Array(is_a).flatten
37
+ return true if validate(value, expected_types)
33
38
 
34
- raise StubRequests::InvalidType,
39
+ raise StubRequests::InvalidArgumentType,
40
+ name: name,
35
41
  actual: value.class,
36
- expected: expected_types.join(", ")
42
+ expected: expected_types
43
+ end
44
+
45
+ # :reek:UtilityFunction
46
+ def validate(value, expected_types)
47
+ expected_types.any? { |type| value.is_a?(type) }
37
48
  end
38
49
  end
39
50
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Abstraction over WebMock to reduce duplication
5
+ #
6
+ # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # @since 0.1.0
8
+ #
9
+ module StubRequests
10
+ #
11
+ # Class Configuration contains gem configuration
12
+ #
13
+ # @author Mikael Henriksson <mikael@zoolutions.se>
14
+ # @since 0.1.2
15
+ #
16
+ class Configuration
17
+ include Property
18
+
19
+ property :record_metrics, type: [TrueClass, FalseClass], default: false
20
+ end
21
+ end
@@ -1,3 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "stub_requests/core_ext/array/extract_options"
4
+ require "stub_requests/core_ext/kernel/singleton_class"
5
+ require "stub_requests/core_ext/module/redefine_method"
6
+ require "stub_requests/core_ext/class/attribute"
3
7
  require "stub_requests/core_ext/object/blank"