fixturama 0.1.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|