faraday-hot_mock 0.4.0 → 0.5.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: 56228dde369003b5c2b7a68b7af56e2533c13d07ffc9dc997c8fe3a937c48f55
4
- data.tar.gz: bc60f461818b035f6e3d14a28d6b6f9943d47bac85ce398013a91569fba6268f
3
+ metadata.gz: d42875d59eb57c21511d1c8edb287415cfae818f0a5af8b3be38f06086c8920f
4
+ data.tar.gz: 22551de3ae9e35709702c762880abbf797407f4e95e4f84a53e6bc3f930c4337
5
5
  SHA512:
6
- metadata.gz: 6398844d597bda4844ef3967f104dd6300ff9d9226128b34df2ef2ae096e740f0037b9708f53f70acf5151405a581d507a15ff4e3e9db3fc0d590bfabcdd8694
7
- data.tar.gz: 3ee86b689589bb1cf24d012a47feddefe1e2d8074497953acf7ee85d1936a02387ec3124b07b2cd366345005a5e5dc73a67507e7b63452f209e05ed226905afa
6
+ metadata.gz: 8bf83f23c923e2459e5cc1d50005959df3f9113cb029c2cdf28f6a28967f67f2c00003d1ee2f4fcd25a00e2787665ea73056759137266f3e22de604c8cda606e
7
+ data.tar.gz: 30dbdcccbb2bad3aa706614b4b1b759ec18e7e995e422cf8fa6beb568034940732cce587a345e2874fb2afd68d60e1f308817ce815defdcadb95bed016e6ff5a
data/README.md CHANGED
@@ -8,15 +8,15 @@ _**This adapter is meant for Faraday usage in Rails, not for Faraday that's used
8
8
 
9
9
  ## Why Use Faraday::HotMock instead of VCR?
10
10
 
11
- VCR focuses on keeping HTTP requests out of tests - Faraday::HotMock focuses on simulating API responses during development.
11
+ [VCR](https://github.com/vcr/vcr) focuses on keeping HTTP requests out of tests - Faraday::HotMock focuses on simulating API responses during development.
12
12
 
13
- To use VCR in development would require wrapping code in VCR blocks, which must then be undone before deployment. Simple, but tedious and error-prone.
13
+ To use [VCR](https://github.com/vcr/vcr) in development would require wrapping code in [VCR](https://github.com/vcr/vcr) blocks, which must then be undone before deployment. Simple, but tedious and error-prone.
14
14
 
15
15
  Faraday::HotMock requires no code changes to the application - it doesn't mock anything in production, even if you try. So while the HotMock adapter is "used", it just passes requests to the default or adapter or specified fallback.
16
16
 
17
- VCR works with any HTTP library, Faraday::HotMock only works with Faraday. This is a critical limitation unless you use only or primarily Faraday.
17
+ [VCR](https://github.com/vcr/vcr) works with any HTTP library, Faraday::HotMock only works with Faraday. This is a critical limitation unless you use only or primarily Faraday.
18
18
 
19
- You could, ostensibly, replace VCR with Faraday::HotMock in tests. VCR is battle-tested, well-written and widely used, so it's likely a better choice for testing. But the goal is to make Faraday::HotMock just as useful in all non-production environments.
19
+ You could, ostensibly, replace VCR with Faraday::HotMock in tests. [VCR](https://github.com/vcr/vcr) is battle-tested, well-written and widely used, so it's likely a better choice for testing. But the goal is to make Faraday::HotMock just as useful in all non-production environments.
20
20
 
21
21
  ## How It Works
22
22
 
@@ -81,14 +81,49 @@ It can also be a terrible idea if your mocks are designed for your specific need
81
81
 
82
82
  It's up to you and your team what makes sense.
83
83
 
84
- In most cases, it makes sense to check in the mocks for the test environment, and ignore all the rest so in most cases you should add to your `.gitignore`:
84
+ In most cases, it makes sense to not check in the mocks for any environment, so in most cases you should add to your `.gitignore`:
85
85
 
86
86
  ```
87
87
  # Ignore Faraday HotMocks except in test env
88
88
  lib/faraday/mocks/**
89
- !lib/faraday/mocks/test
90
89
  ```
91
90
 
91
+ ### Scenarios
92
+
93
+ You can use directories to conditionally group mocks. For example, you might want a "success" scenario and an "failure" scenario.
94
+
95
+ To do that, simply create the `/scenarios/success` and `/scenarios/failure` subdirectories within `lib/faraday/mocks/#{Rails.env}/`, and place the appropriate mock files in each, probably with the same endpoints but with different responses.
96
+
97
+ Then call `Faraday::HotMock.scenario = :success` or `Faraday::HotMock.scenario = :failure` to switch between them.
98
+
99
+ When a scenario is active, only mocks in that scenario directory will be considered. If no matching mock is found in that scenario, then the real request will be made.
100
+
101
+ To use the mocks not in the `scenarios` directory again, simply set `Faraday::HotMock.scenario = nil`.
102
+
103
+ ### Testing
104
+
105
+ In tests, you can certainly use a mocking library of choice. In many cases, that might be easier. This is because Faraday::HotMock is built for quick iteration using runtime-loaded YAML files, which isn't needed in tests.
106
+
107
+ If instead you want to use Faraday::HotMock, you can create mocked responses by hand, or use `Faraday::HotMock.mock!` to define mocks in a very similar way to other mocking libraries (similar to `stub_request` in WebMock, for example).
108
+
109
+ The most basic setup would be:
110
+
111
+ - Call `Faraday::HotMock.enable!` in your test setup
112
+ - Call `Faraday::HotMock.disable!` in your test teardown
113
+ - In a given test/spec or in a method, call `Faraday::HotMock.mock!(method: [method], url_pattern: [url], status: [status code], headers: [headers hash], body: [body])` to define a mock for that test/spec.
114
+ - Remove the mock file in teardown by referencing `Faraday::HotMock.hot_mock_file` (via `File.delete` or `FileUtils.rm`) since you probably don't want them to persist between tests
115
+
116
+ If you use scenarios, then you can do a bit less:
117
+
118
+ - Call `Faraday::HotMock.enable!` in your test setup
119
+ - Call `Faraday::HotMock.disable!` in your test teardown
120
+ - Call `Faraday::HotMock.scenario = :your_scenario_name` in a given test/spec
121
+ - Call `Faraday::HotMock.scenario = nil` in your test teardown if using scenarios
122
+
123
+ Overall, this may be a bit more work but it has the advantage that you can use the same mocking mechanism in both development and testing, which can reduce surprises when moving code between the two.
124
+
125
+ Small bonus: if you use `Faraday::HotMock` everywhere, you can remove the dependency for whichever mocking library/libraries you were using before.
126
+
92
127
  ### Convenience Methods
93
128
 
94
129
  You can enable or disable mocking programmatically with these methods:
@@ -23,11 +23,34 @@ module Faraday
23
23
  end
24
24
 
25
25
  if Faraday::HotMock.enabled? && (mock = Faraday::HotMock.mocked?(method: env.method, url: env.url))
26
- save_response(env, mock["status"] || 200, mock["body"] || "", mock["headers"] || {})
26
+ interpolate(mock, env) if mock_interpolated?(mock)
27
+
28
+ save_response(
29
+ env,
30
+ mock["status"] || 200,
31
+ mock["body"] || "",
32
+ (mock["headers"] || {}).merge("x-hot-mocked" => "true")
33
+ )
27
34
  else
28
35
  @fallback_adapter.new(@app, @options).call(env)
29
36
  end
30
37
  end
38
+
39
+ private
40
+
41
+ def mock_interpolated?(mock)
42
+ mock.key?("interpolate") && mock["body"].is_a?(Hash)
43
+ end
44
+
45
+ def interpolate(mock, env)
46
+ request_hash = JSON.parse(env.request_body) rescue {}
47
+
48
+ interpolated_hash = mock["interpolate"].transform_values do |v|
49
+ v = request_hash[v]
50
+ end.compact
51
+
52
+ mock["body"].merge!(interpolated_hash || {})
53
+ end
31
54
  end
32
55
  end
33
56
  end
@@ -1,5 +1,5 @@
1
1
  module Faraday
2
2
  module HotMock
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -7,6 +7,8 @@ module Faraday
7
7
  module HotMock
8
8
  extend self
9
9
 
10
+ attr_accessor :scenario
11
+
10
12
  def disable!
11
13
  FileUtils.rm_f(hot_mocking_file)
12
14
  end
@@ -31,7 +33,7 @@ module Faraday
31
33
  end
32
34
  end
33
35
 
34
- def delete_mock(method:, url:)
36
+ def delete(method:, url:)
35
37
  return unless File.exist?(hot_mock_file)
36
38
 
37
39
  mocks = YAML.load_file(hot_mock_file) || []
@@ -42,6 +44,7 @@ module Faraday
42
44
  end
43
45
 
44
46
  def mock!(method:, url:, status:, headers: {}, body: nil)
47
+ FileUtils.mkdir_p(hot_mock_dir)
45
48
  FileUtils.touch(hot_mock_file)
46
49
 
47
50
  mocks = YAML.load_file(hot_mock_file) || []
@@ -78,7 +81,7 @@ module Faraday
78
81
  "method" => method.to_s.upcase,
79
82
  "url_pattern" => url,
80
83
  "status" => response.status,
81
- "headers" => response.headers.to_h.merge("x-hotmock-recorded-at" => Time.now.utc.iso8601),
84
+ "headers" => response.headers.to_h.merge("x-hot-mock-recorded-at" => Time.now.utc.iso8601),
82
85
  "body" => response.body
83
86
  }
84
87
 
@@ -102,7 +105,7 @@ module Faraday
102
105
  "method" => method.to_s.upcase,
103
106
  "url_pattern" => url,
104
107
  "status" => response.status,
105
- "headers" => response.headers.to_h.merge("x-hotmock-recorded-at" => Time.now.utc.iso8601),
108
+ "headers" => response.headers.to_h.merge("x-hot-mock-recorded-at" => Time.now.utc.iso8601, "x-hot-mock" => "true"),
106
109
  "body" => response.body
107
110
  }
108
111
 
@@ -115,6 +118,10 @@ module Faraday
115
118
  Rails.root.join "lib/faraday/mocks/#{Rails.env}"
116
119
  end
117
120
 
121
+ def scenario_dir
122
+ Rails.root.join "lib/faraday/mocks/#{Rails.env}/scenarios"
123
+ end
124
+
118
125
  def hot_mocking_file
119
126
  Rails.root.join "tmp/mocking-#{Rails.env}.txt"
120
127
  end
@@ -137,7 +144,11 @@ module Faraday
137
144
  end
138
145
 
139
146
  def all_hot_mock_files
140
- Dir.glob(File.join(hot_mock_dir, "**", "*.{yml,yaml}"))
147
+ if scenario
148
+ Dir.glob(File.join(hot_mock_dir, "scenarios", scenario.to_s, "**", "*.{yml,yaml}"))
149
+ else
150
+ Dir.glob(File.join(hot_mock_dir, "**", "*.{yml,yaml}")).reject { |path| path.include?("/scenarios/") }
151
+ end
141
152
  end
142
153
  end
143
154
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday-hot_mock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Hogge