fixturama 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64d9722c641abfd4aa64fbf45b8f1177f768d1b8d2b99a89aa824e1f64db9417
4
- data.tar.gz: e1186c8944916943bbab46584747553b07b9d5cfc4e9d875d1a401fc8bd7017a
3
+ metadata.gz: 5bfb62ba99d427f8a3f03b6d46a0fb7e6712dd31bfff6da7c17fb075cfa930f0
4
+ data.tar.gz: fa1b0359c0681a73723a915dd499945602b350b3b802b68e6962a66753a5d208
5
5
  SHA512:
6
- metadata.gz: 29d44cd1b06c482ba40df2d4397c064888a64ae1f9a0a4151aa581bf81a83e9ca1a5e84c052340d515032d0f580f11418f9838a5efe00fd722401117248a0311
7
- data.tar.gz: 2b8a86f7fffdb20bae92839790254e052d2dbbbb39172003c9cfb4439620c782e4bc3f2ccdd985540dcba4d19e1fc228a3f7d940d58a865ad289f2f265427589
6
+ metadata.gz: 987b0cf303e78879b18278d85ace7cf26261e6c76000b0081571cb40a3dcf763435cb5560de122bf3a466b9c781684c8ed8d183697fbd1b84aa619c8409e34c8
7
+ data.tar.gz: d85486458d90dbff1e3f2136c5862e081aa1a1861bb5e6320fb68bbc258d11ce1e978de5603c900080ef719809e97a4d0bf793a46c8f90af33e7a6626d258835
data/.rubocop.yml CHANGED
@@ -5,7 +5,7 @@ AllCops:
5
5
  StyleGuideCopsOnly: true
6
6
  TargetRubyVersion: 2.3
7
7
 
8
- Metrics/LineLength:
8
+ Layout/LineLength:
9
9
  AllowHeredoc: true
10
10
  AllowURI: true
11
11
  URISchemes:
data/.travis.yml CHANGED
@@ -10,14 +10,8 @@ script:
10
10
  - bundle exec rubocop
11
11
  rvm:
12
12
  - 2.3.0
13
- - 2.6.0
14
- - jruby-9.2.0.0
13
+ - 2.7.0
15
14
  - ruby-head
16
- - jruby-head
17
- env:
18
- global:
19
- - JRUBY_OPTS='--dev -J-Xmx1024M'
20
15
  matrix:
21
16
  allow_failures:
22
17
  - rvm: ruby-head
23
- - rvm: jruby-head
data/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
+ ## [0.1.0] - [2020-02-09]
9
+
10
+ ### Added
11
+
12
+ - Stubbing of the HTTP requests using webmock (nepalez)
13
+
14
+ ```yaml
15
+ ---
16
+ - url: example.com/foo
17
+ method: get
18
+ body: foobar
19
+ query:
20
+ foo: bar
21
+ basic_auth:
22
+ user: foo
23
+ password: bar
24
+ headers:
25
+ Accept: utf-8
26
+ responses:
27
+ - status: 200
28
+ body: foobar
29
+ - status: 404
30
+ ```
31
+
8
32
  ## [0.0.7] - [2019-07-01]
9
33
 
10
34
  ### Added
@@ -175,3 +199,4 @@ This is a first public release with features extracted from production app.
175
199
  [0.0.5]: https://github.com/nepalez/fixturama/compare/v0.0.4...v0.0.5
176
200
  [0.0.6]: https://github.com/nepalez/fixturama/compare/v0.0.5...v0.0.6
177
201
  [0.0.7]: https://github.com/nepalez/fixturama/compare/v0.0.6...v0.0.7
202
+ [0.1.0]: https://github.com/nepalez/fixturama/compare/v0.0.7...v0.1.0
data/README.md CHANGED
@@ -133,12 +133,25 @@ For message chains:
133
133
  - `arguments` (optional) for specific arguments
134
134
  - `actions` for an array of actions for consecutive invocations of the chain
135
135
 
136
+ Every action either `return` some value, or `raise` some exception
137
+
136
138
  For constants:
137
139
 
138
140
  - `const` for stubbed constant
139
141
  - `value` for a value of the constant
140
142
 
141
- Every action either `return` some value, or `raise` some exception
143
+ For http requests:
144
+
145
+ - `url` or `uri` for the URI of the request (treats values like `/.../` as regular expressions)
146
+ - `method` for the specific http-method (like `get` or `post`)
147
+ - `body` for the request body (treats values like `/.../` as regular expressions)
148
+ - `headers` for the request headers
149
+ - `query` for the request query
150
+ - `basic_auth` for the `user` and `password` of basic authentication
151
+ - `response` or `responses` for consecutively envoked responses with keys:
152
+ - `status`
153
+ - `body`
154
+ - `headers`
142
155
 
143
156
  ```yaml
144
157
  # ./stubs.yml
@@ -170,6 +183,21 @@ Every action either `return` some value, or `raise` some exception
170
183
 
171
184
  - const: NOTIFIER_TIMEOUT_SEC
172
185
  value: 10
186
+
187
+ # Examples for stubbing HTTP
188
+ - uri: /example.com/foo/ # regexp!
189
+ method: delete
190
+ basic_auth:
191
+ user: foo
192
+ password: bar
193
+ responses:
194
+ - status: 200 # for the first call
195
+ - status: 404 # for any other call
196
+
197
+ - uri: htpps://example.com/foo # exact string!
198
+ method: delete
199
+ responses:
200
+ - status: 401
173
201
  ```
174
202
 
175
203
  ```graphql
data/fixturama.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "fixturama"
3
- gem.version = "0.0.7"
3
+ gem.version = "0.1.0"
4
4
  gem.author = "Andrew Kozin (nepalez)"
5
5
  gem.email = "andrew.kozin@gmail.com"
6
6
  gem.homepage = "https://github.com/nepalez/fixturama"
@@ -15,9 +15,10 @@ Gem::Specification.new do |gem|
15
15
 
16
16
  gem.add_runtime_dependency "factory_bot", "~> 4.0"
17
17
  gem.add_runtime_dependency "rspec", "~> 3.0"
18
- gem.add_runtime_dependency "hashie", "~> 3.6"
18
+ gem.add_runtime_dependency "hashie", "~> 3.0"
19
+ gem.add_runtime_dependency "webmock", "~> 3.0"
19
20
 
20
21
  gem.add_development_dependency "rake", "~> 10"
21
- gem.add_development_dependency "rspec-its", "~> 1.2"
22
+ gem.add_development_dependency "rspec-its", "~> 1.0"
22
23
  gem.add_development_dependency "rubocop", "~> 0.49"
23
24
  end
data/lib/fixturama.rb CHANGED
@@ -3,6 +3,7 @@ require "factory_bot"
3
3
  require "hashie/mash"
4
4
  require "json"
5
5
  require "rspec"
6
+ require "webmock/rspec"
6
7
  require "yaml"
7
8
 
8
9
  module Fixturama
@@ -5,6 +5,7 @@ module Fixturama
5
5
  class Stubs
6
6
  require_relative "stubs/chain"
7
7
  require_relative "stubs/const"
8
+ require_relative "stubs/request"
8
9
 
9
10
  #
10
11
  # Register new action and apply the corresponding stub
@@ -35,14 +36,15 @@ module Fixturama
35
36
  stub = case stub_type(options)
36
37
  when :message_chain then Chain.new(options)
37
38
  when :constant then Const.new(options)
39
+ when :request then Request.new(options)
38
40
  end
39
41
 
40
- @stubs[stub.to_s] ||= stub if stub
42
+ @stubs[stub.key] ||= stub if stub
41
43
  end
42
44
 
43
45
  def stub_type(options)
44
- return :message_chain if options[:class] || options[:object]
45
- return :constant if options[:const]
46
+ key = (TYPES.keys & options.keys).first
47
+ return TYPES[key] if key
46
48
 
47
49
  raise ArgumentError, <<~MESSAGE
48
50
  Cannot figure out what to stub from #{options}.
@@ -50,6 +52,26 @@ module Fixturama
50
52
  MESSAGE
51
53
  end
52
54
 
55
+ # Matches keys to the type of the stub
56
+ TYPES = {
57
+ arguments: :message_chain,
58
+ actions: :message_chain,
59
+ basic_auth: :request,
60
+ body: :request,
61
+ chain: :message_chain,
62
+ class: :message_chain,
63
+ const: :constant,
64
+ headers: :request,
65
+ http_method: :request,
66
+ object: :message_chain,
67
+ query: :request,
68
+ response: :request,
69
+ responses: :request,
70
+ uri: :request,
71
+ url: :request,
72
+ value: :constant,
73
+ }.freeze
74
+
53
75
  def symbolize(options)
54
76
  Hash(options).transform_keys { |key| key.to_s.to_sym }
55
77
  end
@@ -16,6 +16,7 @@ module Fixturama
16
16
  "#{receiver}.#{messages.join(".")}"
17
17
  end
18
18
  alias to_str to_s
19
+ alias key to_s
19
20
 
20
21
  #
21
22
  # Register new action for some arguments
@@ -13,6 +13,7 @@ module Fixturama
13
13
  const.to_s
14
14
  end
15
15
  alias to_str to_s
16
+ alias key to_s
16
17
 
17
18
  #
18
19
  # Overload the definition for the constant
@@ -0,0 +1,98 @@
1
+ #
2
+ # Stubbed request
3
+ #
4
+ class Fixturama::Stubs::Request
5
+ require_relative "request/response"
6
+ require_relative "request/responses"
7
+
8
+ def to_s
9
+ "#{http_method.upcase} #{uri.to_s == "" ? "*" : uri}"
10
+ end
11
+ alias to_str to_s
12
+
13
+ # every stub is unique
14
+ alias key hash
15
+ def update!(_); end
16
+
17
+ def apply!(example)
18
+ stub = example.stub_request(http_method, uri)
19
+ stub = stub.with(request) if request.any?
20
+ stub.to_return { |_| responses.next }
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :options
26
+
27
+ def initialize(options)
28
+ @options = options
29
+ with_error { @options = Hash(options).symbolize_keys }
30
+ end
31
+
32
+ HTTP_METHODS = %i[get post put patch delete head options any].freeze
33
+
34
+ def http_method
35
+ value = with_error("method") { options[:method]&.to_sym&.downcase } || :any
36
+ return value if HTTP_METHODS.include?(value)
37
+
38
+ raise ArgumentError, "Invalid HTTP method #{value} in #{@optons}"
39
+ end
40
+
41
+ def uri
42
+ with_error("uri") { maybe_regexp(options[:uri] || options[:url]) }
43
+ end
44
+
45
+ def headers
46
+ with_error("headers") do
47
+ Hash(options[:headers]).transform_keys(&:to_s) if options.key?(:headers)
48
+ end
49
+ end
50
+
51
+ def query
52
+ with_error("query") do
53
+ Hash(options[:query]).transform_keys(&:to_s) if options.key?(:query)
54
+ end
55
+ end
56
+
57
+ def body
58
+ with_error("body") do
59
+ case options[:body]
60
+ when NilClass then nil
61
+ when Hash then options[:body]
62
+ else maybe_regexp(options[:body])
63
+ end
64
+ end
65
+ end
66
+
67
+ def basic_auth
68
+ with_error("basic auth") do
69
+ value = options[:auth] || options[:basic_auth]
70
+ Hash(value).transform_keys(&:to_s).values_at("user", "pass") if value
71
+ end
72
+ end
73
+
74
+ def request
75
+ @request ||= {
76
+ headers: headers,
77
+ body: body,
78
+ query: query,
79
+ basic_auth: basic_auth
80
+ }.select { |_, val| val }
81
+ end
82
+
83
+ def responses
84
+ @responses ||= Responses.new(options[:response] || options[:responses])
85
+ end
86
+
87
+ def with_error(part = nil)
88
+ yield
89
+ rescue RuntimeError
90
+ message = ["Cannot extract a request", part, "from #{options}"].join(" ")
91
+ raise ArgumentError, message, __FILE__, __LINE__ - 1
92
+ end
93
+
94
+ def maybe_regexp(str)
95
+ str = str.to_s
96
+ str[%r{\A/.*/\z}] ? Regexp.new(str[1..-2]) : str
97
+ end
98
+ end
@@ -0,0 +1,43 @@
1
+ class Fixturama::Stubs::Request
2
+ class Response
3
+ def to_h
4
+ { status: status, body: body, headers: headers }.select { |_, val| val }
5
+ end
6
+
7
+ private
8
+
9
+ def initialize(options)
10
+ @options = options
11
+ @options = with_error { Hash(options).transform_keys(&:to_sym) }
12
+ end
13
+
14
+ attr_reader :options
15
+
16
+ def status
17
+ with_error("status") { options[:status]&.to_i } || 200
18
+ end
19
+
20
+ def body
21
+ with_error("body") do
22
+ case options[:body]
23
+ when NilClass then nil
24
+ when Hash then JSON.dump(options[:body])
25
+ else options[:body].to_s
26
+ end
27
+ end
28
+ end
29
+
30
+ def headers
31
+ with_error("headers") do
32
+ Hash(options[:headers]).map { |k, v| [k.to_s, v.to_s] }.to_h
33
+ end
34
+ end
35
+
36
+ def with_error(part = nil)
37
+ yield
38
+ rescue RuntimeError
39
+ text = ["Cannot extract a response", part, "from #{options}"].join(" ")
40
+ raise ArgumentError, text, __FILE__, __LINE__ - 1
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ class Fixturama::Stubs::Request
2
+ class Responses
3
+ def next
4
+ list.count > @count ? list[@count].tap { @count += 1 } : list.last
5
+ end
6
+
7
+ private
8
+
9
+ def initialize(list)
10
+ @count = 0
11
+ list ||= [{ status: 200 }]
12
+ @list = case list
13
+ when Array then list.map { |item| Response.new(item).to_h }
14
+ else [Response.new(list).to_h]
15
+ end
16
+ end
17
+
18
+ attr_reader :list
19
+ end
20
+ end
@@ -26,7 +26,10 @@ RSpec.describe "seed_fixture" do
26
26
 
27
27
  it "runs the factory", aggregate_failures: true do
28
28
  expect(FactoryBot).to receive(:create_list).with(:foo, 1, :baz, qux: 42)
29
- expect(FactoryBot).to receive(:create_list).with(:foo, 3, :bar, {})
29
+ expect(FactoryBot).to receive(:create_list) do |*args, **opts|
30
+ expect(args).to eq [:foo, 3, :bar]
31
+ expect(opts).to be_empty
32
+ end
30
33
 
31
34
  subject
32
35
  end
@@ -93,4 +93,28 @@ RSpec.describe "stub_fixture" do
93
93
  expect(TIMEOUT).to eq 10
94
94
  end
95
95
  end
96
+
97
+ context "when http request stubbed" do
98
+ before { stub_fixture "#{__dir__}/stub.yml" }
99
+
100
+ it "stubs the request properly" do
101
+ req = Net::HTTP::Get.new("/foo")
102
+ res = Net::HTTP.start("www.example.com") { |http| http.request(req) }
103
+
104
+ expect(res.code).to eq "200"
105
+ expect(res.body).to eq "foo"
106
+ expect(res["Content-Length"]).to eq "3"
107
+ end
108
+
109
+ def delete_request
110
+ req = Net::HTTP::Delete.new("/foo")
111
+ Net::HTTP.start("www.example.com") { |http| http.request(req) }
112
+ end
113
+
114
+ it "stubs repetitive requests properly" do
115
+ expect(delete_request.code).to eq "200"
116
+ expect(delete_request.code).to eq "404"
117
+ expect(delete_request.code).to eq "404"
118
+ end
119
+ end
96
120
  end
@@ -58,3 +58,16 @@
58
58
 
59
59
  - const: TIMEOUT
60
60
  value: 10
61
+
62
+ - method: get
63
+ uri: www.example.com/foo
64
+ responses:
65
+ - body: foo
66
+ headers:
67
+ Content-Length: 3
68
+
69
+ - method: delete
70
+ uri: /example.com/foo/ # Regexp!
71
+ responses:
72
+ - status: 200
73
+ - status: 404 # for any request except for the first one
metadata CHANGED
@@ -1,100 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fixturama
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kozin (nepalez)
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-01 00:00:00.000000000 Z
11
+ date: 2020-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: factory_bot
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
18
  version: '4.0'
20
- type: :runtime
19
+ name: factory_bot
21
20
  prerelease: false
21
+ type: :runtime
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
32
  version: '3.0'
34
- type: :runtime
33
+ name: rspec
35
34
  prerelease: false
35
+ type: :runtime
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: hashie
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - "~>"
46
45
  - !ruby/object:Gem::Version
47
- version: '3.6'
46
+ version: '3.0'
47
+ name: hashie
48
+ prerelease: false
48
49
  type: :runtime
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ name: webmock
49
62
  prerelease: false
63
+ type: :runtime
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '3.6'
68
+ version: '3.0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: rake
57
70
  requirement: !ruby/object:Gem::Requirement
58
71
  requirements:
59
72
  - - "~>"
60
73
  - !ruby/object:Gem::Version
61
74
  version: '10'
62
- type: :development
75
+ name: rake
63
76
  prerelease: false
77
+ type: :development
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '10'
69
83
  - !ruby/object:Gem::Dependency
70
- name: rspec-its
71
84
  requirement: !ruby/object:Gem::Requirement
72
85
  requirements:
73
86
  - - "~>"
74
87
  - !ruby/object:Gem::Version
75
- version: '1.2'
76
- type: :development
88
+ version: '1.0'
89
+ name: rspec-its
77
90
  prerelease: false
91
+ type: :development
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '1.2'
96
+ version: '1.0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: rubocop
85
98
  requirement: !ruby/object:Gem::Requirement
86
99
  requirements:
87
100
  - - "~>"
88
101
  - !ruby/object:Gem::Version
89
102
  version: '0.49'
90
- type: :development
103
+ name: rubocop
91
104
  prerelease: false
105
+ type: :development
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0.49'
97
- description:
111
+ description:
98
112
  email: andrew.kozin@gmail.com
99
113
  executables: []
100
114
  extensions: []
@@ -126,6 +140,9 @@ files:
126
140
  - lib/fixturama/stubs/chain/actions/return.rb
127
141
  - lib/fixturama/stubs/chain/arguments.rb
128
142
  - lib/fixturama/stubs/const.rb
143
+ - lib/fixturama/stubs/request.rb
144
+ - lib/fixturama/stubs/request/response.rb
145
+ - lib/fixturama/stubs/request/responses.rb
129
146
  - lib/fixturama/utils.rb
130
147
  - spec/fixturama/load_fixture/_spec.rb
131
148
  - spec/fixturama/load_fixture/data.json
@@ -140,7 +157,7 @@ homepage: https://github.com/nepalez/fixturama
140
157
  licenses:
141
158
  - MIT
142
159
  metadata: {}
143
- post_install_message:
160
+ post_install_message:
144
161
  rdoc_options: []
145
162
  require_paths:
146
163
  - lib
@@ -155,8 +172,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
172
  - !ruby/object:Gem::Version
156
173
  version: '0'
157
174
  requirements: []
158
- rubygems_version: 3.0.3
159
- signing_key:
175
+ rubyforge_project:
176
+ rubygems_version: 2.7.6
177
+ signing_key:
160
178
  specification_version: 4
161
179
  summary: A set of helpers to prettify specs with fixtures
162
180
  test_files: