fixturama 0.1.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 +4 -4
- data/CHANGELOG.md +99 -0
- data/README.md +76 -4
- data/lib/fixturama.rb +48 -20
- data/lib/fixturama/changes.rb +72 -0
- data/lib/fixturama/changes/base.rb +28 -0
- data/lib/fixturama/changes/chain.rb +64 -0
- data/lib/fixturama/changes/chain/actions.rb +31 -0
- data/lib/fixturama/changes/chain/arguments.rb +59 -0
- data/lib/fixturama/changes/chain/raise_action.rb +43 -0
- data/lib/fixturama/changes/chain/return_action.rb +33 -0
- data/lib/fixturama/changes/const.rb +30 -0
- data/lib/fixturama/changes/env.rb +35 -0
- data/lib/fixturama/changes/request.rb +91 -0
- data/lib/fixturama/changes/request/response.rb +62 -0
- data/lib/fixturama/changes/request/responses.rb +22 -0
- data/lib/fixturama/changes/seed.rb +39 -0
- data/lib/fixturama/config.rb +5 -0
- data/lib/fixturama/fixture_error.rb +31 -0
- data/lib/fixturama/loader.rb +6 -2
- data/lib/fixturama/loader/context.rb +14 -5
- data/lib/fixturama/loader/value.rb +1 -0
- data/lib/fixturama/version.rb +4 -0
- metadata +85 -73
- data/.gitignore +0 -12
- data/.rspec +0 -2
- data/.rubocop.yml +0 -22
- data/.travis.yml +0 -17
- data/Gemfile +0 -9
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -6
- data/fixturama.gemspec +0 -24
- data/lib/fixturama/seed.rb +0 -15
- data/lib/fixturama/stubs.rb +0 -79
- data/lib/fixturama/stubs/chain.rb +0 -90
- data/lib/fixturama/stubs/chain/actions.rb +0 -39
- data/lib/fixturama/stubs/chain/actions/raise.rb +0 -21
- data/lib/fixturama/stubs/chain/actions/return.rb +0 -23
- data/lib/fixturama/stubs/chain/arguments.rb +0 -86
- data/lib/fixturama/stubs/const.rb +0 -43
- data/lib/fixturama/stubs/request.rb +0 -98
- data/lib/fixturama/stubs/request/response.rb +0 -43
- data/lib/fixturama/stubs/request/responses.rb +0 -20
- data/lib/fixturama/utils.rb +0 -39
- data/spec/fixturama/load_fixture/_spec.rb +0 -53
- data/spec/fixturama/load_fixture/data.json +0 -5
- data/spec/fixturama/load_fixture/data.yaml +0 -3
- data/spec/fixturama/load_fixture/data.yml +0 -3
- data/spec/fixturama/seed_fixture/_spec.rb +0 -36
- data/spec/fixturama/seed_fixture/seed.yml +0 -16
- data/spec/fixturama/stub_fixture/_spec.rb +0 -120
- data/spec/fixturama/stub_fixture/stub.yml +0 -73
- data/spec/spec_helper.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e21218a92d62cab4b0bbc73fe1f2ac02eb5c66a7315357a68189067d138d92a
|
4
|
+
data.tar.gz: 81861ef1dbf1eba81874fb929875c89f04dc3ebdeba9694ae02989762dd7aca5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f09063278691d752987cc1b9bbc8d20a715624cce81f81e9c61b521d52af28b9fbe03e09ac9357e01c154b987608558231b3c0ca8d1bdd5677303f887630b3ad
|
7
|
+
data.tar.gz: b93be44d444875df3d793bb7947bbd9c906a0fcc699c3b1ec4625186a38eed3b58b8a11f11d6e7ae421db4615534533029c2fece7d592a357649ef24598e63a9
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,100 @@ 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.5.0] - [2021-04-03]
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Support for <de>serialization PORO objects (nepalez)
|
13
|
+
|
14
|
+
```yaml
|
15
|
+
# target.yml
|
16
|
+
---
|
17
|
+
number: <%= object(be_positive) %>
|
18
|
+
```
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
RSpec.describe "something" do
|
22
|
+
subject { { "number" => 42 } }
|
23
|
+
|
24
|
+
# no explicit params is needed here
|
25
|
+
let(:target) { load_fixture "target.yml" }
|
26
|
+
|
27
|
+
it { is_expected.to match(target) }
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
## [0.4.1] - [2021-03-31]
|
32
|
+
|
33
|
+
### Fixed
|
34
|
+
|
35
|
+
- Dependency from hashie updated to allow v4+ (nepalez)
|
36
|
+
|
37
|
+
## [0.4.0] - [2020-03-15]
|
38
|
+
|
39
|
+
### Added
|
40
|
+
|
41
|
+
- Support for stubbing ENV variables (nepalez)
|
42
|
+
|
43
|
+
```yaml
|
44
|
+
---
|
45
|
+
- env: GOOGLE_CLOUD_KEY
|
46
|
+
value: foo
|
47
|
+
|
48
|
+
- env: GOOGLE_CLOUD_PASSWORD
|
49
|
+
value: bar
|
50
|
+
```
|
51
|
+
|
52
|
+
This would stub selected variables only, not touching the others
|
53
|
+
|
54
|
+
## [0.3.0] - [2020-03-08]
|
55
|
+
|
56
|
+
### Added
|
57
|
+
|
58
|
+
- Support for exception arguments (nepalez)
|
59
|
+
|
60
|
+
```yaml
|
61
|
+
---
|
62
|
+
- class: API
|
63
|
+
chain: get_product
|
64
|
+
arguments:
|
65
|
+
- 1
|
66
|
+
actions:
|
67
|
+
- raise: API::NotFoundError
|
68
|
+
arguments: # <--- that's that
|
69
|
+
- "Cannot find a product by id: 1"
|
70
|
+
```
|
71
|
+
|
72
|
+
which would raise `API::NotFoundError.new("Cannot find a product by id: 1")`
|
73
|
+
|
74
|
+
## [0.2.0] - [2020-02-17]
|
75
|
+
|
76
|
+
### Added
|
77
|
+
|
78
|
+
- Stubbing and seeding from the same source file via the `call_fixture` method (nepalez)
|
79
|
+
|
80
|
+
```yaml
|
81
|
+
# ./changes.yml
|
82
|
+
---
|
83
|
+
- type: user
|
84
|
+
params:
|
85
|
+
id: 1
|
86
|
+
|
87
|
+
- const: DEFAULT_USER_ID
|
88
|
+
value: 1
|
89
|
+
|
90
|
+
- url: https://example.com/users/default
|
91
|
+
method: get
|
92
|
+
responses:
|
93
|
+
- body:
|
94
|
+
id: 1
|
95
|
+
name: Andrew
|
96
|
+
```
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
before { call_fixture "#{__dir__}/changes.yml" }
|
100
|
+
```
|
101
|
+
|
8
102
|
## [0.1.0] - [2020-02-09]
|
9
103
|
|
10
104
|
### Added
|
@@ -200,3 +294,8 @@ This is a first public release with features extracted from production app.
|
|
200
294
|
[0.0.6]: https://github.com/nepalez/fixturama/compare/v0.0.5...v0.0.6
|
201
295
|
[0.0.7]: https://github.com/nepalez/fixturama/compare/v0.0.6...v0.0.7
|
202
296
|
[0.1.0]: https://github.com/nepalez/fixturama/compare/v0.0.7...v0.1.0
|
297
|
+
[0.2.0]: https://github.com/nepalez/fixturama/compare/v0.1.0...v0.2.0
|
298
|
+
[0.3.0]: https://github.com/nepalez/fixturama/compare/v0.2.0...v0.3.0
|
299
|
+
[0.4.0]: https://github.com/nepalez/fixturama/compare/v0.3.0...v0.4.0
|
300
|
+
[0.4.1]: https://github.com/nepalez/fixturama/compare/v0.4.0...v0.4.1
|
301
|
+
[0.5.0]: https://github.com/nepalez/fixturama/compare/v0.4.1...v0.5.0
|
data/README.md
CHANGED
@@ -99,6 +99,38 @@ This feature can also be useful to produce a "partially defined" fixtures with [
|
|
99
99
|
subject { load_fixture "#{__dir__}/data.yml", user: kind_of(ActiveRecord::Base) }
|
100
100
|
```
|
101
101
|
|
102
|
+
Since the v0.5.0 we support another way to serialize PORO objects in fixtures. Just wrap them to the `object()` method:
|
103
|
+
|
104
|
+
```yaml
|
105
|
+
---
|
106
|
+
:account: <%= object(user) %>
|
107
|
+
```
|
108
|
+
|
109
|
+
This time you don't need sending objects explicitly.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
RSpec.describe "example" do
|
113
|
+
subject { load_fixture "#{__dir__}/data.yml" }
|
114
|
+
|
115
|
+
let(:user) { FactoryBot.create(:user) }
|
116
|
+
|
117
|
+
# The same object will be returned
|
118
|
+
it { is_expected.to eq(account: user) }
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
Under the hood we use `Marshal.dump` and `Marshal.restore` to serialize and deserialize the object back.
|
123
|
+
|
124
|
+
**Notice**, that deserialization creates a new instance of the object which is not equivalent to the source (`user` in the example above)!
|
125
|
+
In most cases this is enough. For example, you can provide matchers like:
|
126
|
+
|
127
|
+
```yaml
|
128
|
+
---
|
129
|
+
number: <%= object(be_positive) %>
|
130
|
+
```
|
131
|
+
|
132
|
+
The loaded object would contain `{ "number" => be_positive }`.
|
133
|
+
|
102
134
|
### Seeding
|
103
135
|
|
104
136
|
The seed (`seed_fixture`) file should be a YAML/JSON with opinionated parameters, namely:
|
@@ -124,22 +156,28 @@ Use the `count: 2` key to create more objects at once.
|
|
124
156
|
|
125
157
|
### Stubbing
|
126
158
|
|
127
|
-
|
159
|
+
The gem supports stubbing message chains, constants and http requests with the following keys.
|
128
160
|
|
129
161
|
For message chains:
|
130
162
|
|
131
163
|
- `class` for stubbed class
|
132
164
|
- `chain` for messages chain
|
133
165
|
- `arguments` (optional) for specific arguments
|
134
|
-
- `actions` for an array of actions for consecutive invocations of the chain
|
135
|
-
|
136
|
-
|
166
|
+
- `actions` for an array of actions for consecutive invocations of the chain with keys
|
167
|
+
- `return` for a value to be returned
|
168
|
+
- `raise` for an exception to be risen
|
169
|
+
- `repeate` for a number of invocations with this action
|
137
170
|
|
138
171
|
For constants:
|
139
172
|
|
140
173
|
- `const` for stubbed constant
|
141
174
|
- `value` for a value of the constant
|
142
175
|
|
176
|
+
For environment variables:
|
177
|
+
|
178
|
+
- `env` for the name of a variable
|
179
|
+
`value` for a value of the variable
|
180
|
+
|
143
181
|
For http requests:
|
144
182
|
|
145
183
|
- `url` or `uri` for the URI of the request (treats values like `/.../` as regular expressions)
|
@@ -152,6 +190,7 @@ For http requests:
|
|
152
190
|
- `status`
|
153
191
|
- `body`
|
154
192
|
- `headers`
|
193
|
+
- `repeate` for the number of times this response should be returned before switching to the next one
|
155
194
|
|
156
195
|
```yaml
|
157
196
|
# ./stubs.yml
|
@@ -179,11 +218,19 @@ For http requests:
|
|
179
218
|
- <%= profile_id %>
|
180
219
|
actions:
|
181
220
|
- return: true
|
221
|
+
repeate: 1 # this is the default value
|
182
222
|
- raise: ActiveRecord::RecordNotFound
|
223
|
+
arguments:
|
224
|
+
- "Profile with id: 1 not found" # for error message
|
183
225
|
|
226
|
+
# Here we stubbing a constant
|
184
227
|
- const: NOTIFIER_TIMEOUT_SEC
|
185
228
|
value: 10
|
186
229
|
|
230
|
+
# This is a stub for ENV['DEFAULT_EMAIL']
|
231
|
+
- env: DEFAULT_EMAIL
|
232
|
+
value: foo@example.com
|
233
|
+
|
187
234
|
# Examples for stubbing HTTP
|
188
235
|
- uri: /example.com/foo/ # regexp!
|
189
236
|
method: delete
|
@@ -192,6 +239,7 @@ For http requests:
|
|
192
239
|
password: bar
|
193
240
|
responses:
|
194
241
|
- status: 200 # for the first call
|
242
|
+
repeate: 1 # this is the default value, but you can set another one
|
195
243
|
- status: 404 # for any other call
|
196
244
|
|
197
245
|
- uri: htpps://example.com/foo # exact string!
|
@@ -231,6 +279,30 @@ I find it especially helpful when I need to check different edge cases. Instead
|
|
231
279
|
|
232
280
|
Looking at the spec I can easily figure out the "structure" of expectation, while looking at fixtures I can check the concrete corner cases.
|
233
281
|
|
282
|
+
## Single Source of Changes
|
283
|
+
|
284
|
+
If you will, you can list all stubs and seeds at the one single file like
|
285
|
+
|
286
|
+
```yaml
|
287
|
+
# ./changes.yml
|
288
|
+
---
|
289
|
+
- type: user
|
290
|
+
params:
|
291
|
+
id: 1
|
292
|
+
name: Andrew
|
293
|
+
|
294
|
+
- const: DEFAULT_USER_ID
|
295
|
+
value: 1
|
296
|
+
```
|
297
|
+
|
298
|
+
This fixture can be applied via `call_fixture` method just like we did above with `seed_fixture` and `stub_fixture`:
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
before { call_fixture "#{__dir__}/changes.yml" }
|
302
|
+
```
|
303
|
+
|
304
|
+
In fact, since the `v0.2.0` all those methods are just the aliases of the `call_fixture`.
|
305
|
+
|
234
306
|
## License
|
235
307
|
|
236
308
|
The gem is available as open source under the terms of the [MIT License][license].
|
data/lib/fixturama.rb
CHANGED
@@ -6,44 +6,72 @@ require "rspec"
|
|
6
6
|
require "webmock/rspec"
|
7
7
|
require "yaml"
|
8
8
|
|
9
|
+
#
|
10
|
+
# A set of helpers to prettify specs with fixtures
|
11
|
+
#
|
9
12
|
module Fixturama
|
13
|
+
require_relative "fixturama/fixture_error"
|
10
14
|
require_relative "fixturama/config"
|
11
|
-
require_relative "fixturama/utils"
|
12
15
|
require_relative "fixturama/loader"
|
13
|
-
require_relative "fixturama/
|
14
|
-
require_relative "fixturama/seed"
|
16
|
+
require_relative "fixturama/changes"
|
15
17
|
|
18
|
+
# Set the initial value for database-generated IDs
|
19
|
+
# @param [#to_i] value
|
20
|
+
# @return [Fixturama]
|
16
21
|
def self.start_ids_from(value)
|
17
22
|
Config.start_ids_from(value)
|
23
|
+
self
|
18
24
|
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
# @!method read_fixture(path, options)
|
27
|
+
# Read the text content of the fixture
|
28
|
+
# @param [#to_s] path The path to the fixture file
|
29
|
+
# @param [Hash<Symbol, _>] options
|
30
|
+
# The list of options to be accessible in the fixture
|
31
|
+
# @return [String]
|
32
|
+
def read_fixture(path, **options)
|
33
|
+
content = File.read(path)
|
34
|
+
hashie = Hashie::Mash.new(options)
|
35
|
+
bindings = hashie.instance_eval { binding }
|
23
36
|
|
24
|
-
|
25
|
-
fixturama_stubs.apply(self)
|
37
|
+
ERB.new(content).result(bindings)
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
40
|
+
# @!method load_fixture(path, options)
|
41
|
+
# Load data from a fixture
|
42
|
+
# @param (see #read_fixture)
|
43
|
+
# @return [Object]
|
44
|
+
def load_fixture(path, **options)
|
45
|
+
Loader.new(self, path, options).call
|
30
46
|
end
|
31
47
|
|
32
|
-
|
33
|
-
|
48
|
+
# @!method call_fixture(path, options)
|
49
|
+
# Stub different objects and seed the database from a fixture
|
50
|
+
# @param (see #read_fixture)
|
51
|
+
# @return [RSpec::Core::Example] the current example
|
52
|
+
def call_fixture(path, **options)
|
53
|
+
items = Array load_fixture(path, **options)
|
54
|
+
items.each { |item| changes.add(item) }
|
55
|
+
tap { changes.call(self) }
|
56
|
+
rescue FixtureError => err
|
57
|
+
raise err.with_file(path)
|
34
58
|
end
|
35
59
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
60
|
+
# @!method seed_fixture(path, options)
|
61
|
+
# The alias for the +call_fixture+
|
62
|
+
# @param (see #call_fixture)
|
63
|
+
# @return (see #call_fixture)
|
64
|
+
alias seed_fixture call_fixture
|
40
65
|
|
41
|
-
|
42
|
-
|
66
|
+
# @!method stub_fixture(path, options)
|
67
|
+
# The alias for the +call_fixture+
|
68
|
+
# @param (see #call_fixture)
|
69
|
+
# @return (see #call_fixture)
|
70
|
+
alias stub_fixture call_fixture
|
43
71
|
|
44
72
|
private
|
45
73
|
|
46
|
-
def
|
47
|
-
@
|
74
|
+
def changes
|
75
|
+
@changes ||= Changes.new
|
48
76
|
end
|
49
77
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Fixturama
|
2
|
+
#
|
3
|
+
# @private
|
4
|
+
# Registry of changes (stubs and seeds)
|
5
|
+
#
|
6
|
+
class Changes
|
7
|
+
require_relative "changes/base"
|
8
|
+
require_relative "changes/chain"
|
9
|
+
require_relative "changes/const"
|
10
|
+
require_relative "changes/env"
|
11
|
+
require_relative "changes/request"
|
12
|
+
require_relative "changes/seed"
|
13
|
+
|
14
|
+
# Match option keys to the type of an item
|
15
|
+
TYPES = {
|
16
|
+
actions: Chain,
|
17
|
+
arguments: Chain,
|
18
|
+
basic_auth: Request,
|
19
|
+
body: Request,
|
20
|
+
chain: Chain,
|
21
|
+
class: Chain,
|
22
|
+
const: Const,
|
23
|
+
count: Seed,
|
24
|
+
env: Env,
|
25
|
+
headers: Request,
|
26
|
+
http_method: Request,
|
27
|
+
object: Chain,
|
28
|
+
params: Seed,
|
29
|
+
query: Request,
|
30
|
+
response: Request,
|
31
|
+
responses: Request,
|
32
|
+
traits: Seed,
|
33
|
+
type: Seed,
|
34
|
+
uri: Request,
|
35
|
+
url: Request,
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
# Adds new change to the registry
|
39
|
+
# @param [Hash] options
|
40
|
+
# @return [Fixturama::Changes]
|
41
|
+
# @raise [Fixturama::FixtureError] if the options cannot be processed
|
42
|
+
def add(options)
|
43
|
+
options = Hash(options).transform_keys(&:to_sym)
|
44
|
+
types = options.keys.map { |key| TYPES[key] }.compact.uniq
|
45
|
+
raise "Wrong count" unless types.count == 1
|
46
|
+
|
47
|
+
@changes << types.first.new(options)
|
48
|
+
self
|
49
|
+
rescue FixtureError => err
|
50
|
+
raise err
|
51
|
+
rescue StandardError => err
|
52
|
+
raise FixtureError.new("an operation", options, err)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Apply all registered changes to the RSpec example
|
56
|
+
# @param [RSpec::Core::Example] example
|
57
|
+
# @return [self]
|
58
|
+
def call(example)
|
59
|
+
@changes
|
60
|
+
.group_by(&:key)
|
61
|
+
.values
|
62
|
+
.map { |changes| changes.reduce :merge }
|
63
|
+
.each { |change| change.call(example) }
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def initialize
|
69
|
+
@changes = []
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Fixturama::Changes
|
2
|
+
#
|
3
|
+
# @private
|
4
|
+
# @abstract
|
5
|
+
# Base class for changes downloaded from a fixture
|
6
|
+
#
|
7
|
+
class Base
|
8
|
+
# @!attribute [r] key The key identifier of the change
|
9
|
+
# @return [String]
|
10
|
+
alias key hash
|
11
|
+
|
12
|
+
# Merge the other change into the current one
|
13
|
+
# @param [Fixturama::Changes::Base] other
|
14
|
+
# @return [Fixturama::Changes::Base]
|
15
|
+
def merge(other)
|
16
|
+
# By default just take the other change if applicable
|
17
|
+
other.instance_of?(self.class) && other.key == key ? other : self
|
18
|
+
end
|
19
|
+
|
20
|
+
# @abstract
|
21
|
+
# Call the corresponding change (either a stub or a seed)
|
22
|
+
# @param [RSpec::Core::Example] _example The RSpec example
|
23
|
+
# @return [self]
|
24
|
+
def call(_example)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|