radius-spec 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.
@@ -0,0 +1,472 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Radius
4
+ module Spec
5
+ # Basic Model Factory
6
+ #
7
+ # This factory is **not** Rails specific. It works for any object type that
8
+ # responds to `new` with a hash of attributes or keywords; including
9
+ # `Struct` using the new Ruby 2.5 `keyword_init` flag.
10
+ #
11
+ # To make this feature available require it after the gem:
12
+ #
13
+ # ```ruby
14
+ # require 'radius/spec'
15
+ # require 'radius/spec/model_factory'
16
+ # ```
17
+ #
18
+ # ### Storing Factory Templates
19
+ #
20
+ # Our convention is to store all of a project's factory templates in the
21
+ # file `spec/support/model_factories.rb`. As this is our convention, when
22
+ # the model factory is required it will attempt to load this file
23
+ # automatically as a convenience.
24
+ #
25
+ # ### Including Helpers in Specs
26
+ #
27
+ # There are multiple ways you can build object instances using this model
28
+ # factory. Which method you choose depends on how much perceived
29
+ # magic/syntactic sugar you want:
30
+ #
31
+ # - call the model factory directly
32
+ # - manually include the factory helper methods in the specs
33
+ # - use metadata to auto load this feature and include it in the specs
34
+ #
35
+ # When using the metadata option you do not need to explicitly require the
36
+ # model factory feature. This gem registers metadata with the RSpec
37
+ # configuration when it loads and `RSpec` is defined. When the metadata is
38
+ # first used it will automatically require the model factory feature and
39
+ # include the helpers.
40
+ #
41
+ # Any of following metadata will include the factory helpers:
42
+ #
43
+ # - `:model_factory`
44
+ # - `:model_factories`
45
+ # - `type: :controller`
46
+ # - `type: :feature`
47
+ # - `type: :job`
48
+ # - `type: :model`
49
+ # - `type: :request`
50
+ # - `type: :system`
51
+ #
52
+ # @example defining a single factory template
53
+ # require 'radius/spec/model_factory'
54
+ #
55
+ # Radius::Spec::ModelFactory.define_factory(
56
+ # "AnyClass",
57
+ # attr1: :any_value,
58
+ # attr2: :another_value,
59
+ # )
60
+ # @example defining multiple templates
61
+ # require 'radius/spec/model_factory'
62
+ #
63
+ # Radius::Spec::ModelFactory.catalog do |c|
64
+ # c.factory "AnyClass", attr1: :any_value, attr2: :another_value
65
+ #
66
+ # c.factory "AnotherClass",
67
+ # attr1: :any_value,
68
+ # attr2: :another_value,
69
+ # attr3: %i[any list of values]
70
+ # end
71
+ # @example building a domain model from a factory template
72
+ # an_instance = Radius::Spec::ModelFactory.build("AnyClass")
73
+ # @example building a domain model with custom attributes
74
+ # an_instance = Radius::Spec::ModelFactory.build(
75
+ # "AnyClass",
76
+ # attr1: "Any Custom Value",
77
+ # attr2: %w[any custom array],
78
+ # )
79
+ # @example call the model factory directly in specs
80
+ # require 'radius/spec/model_factory'
81
+ #
82
+ # RSpec.describe AnyClass do
83
+ # it "includes the factory helpers" do
84
+ # an_object = Radius::Spec::ModelFactory.build("AnyClass")
85
+ # expect(an_object.name).to eq "Any Name"
86
+ # end
87
+ # end
88
+ # @example manually include the factory helper methods
89
+ # require 'radius/spec/model_factory'
90
+ #
91
+ # RSpec.describe AnyClass do
92
+ # include Radius::Spec::ModelFactory
93
+ #
94
+ # it "includes the factory helpers" do
95
+ # an_object = build(AnyClass)
96
+ # expect(an_object.name).to eq "Any Name"
97
+ # end
98
+ # end
99
+ # @example use metadata to auto include the factory helper methods
100
+ # RSpec.describe AnyClass, :model_factory do
101
+ # it "includes the factory helpers" do
102
+ # an_object = build("AnyClass")
103
+ # expect(an_object.name).to eq "Any Name"
104
+ # end
105
+ # end
106
+ # @since 0.1.0
107
+ module ModelFactory
108
+ # Indicates that a model does not have a template registered with the
109
+ # factory {Radius::Spec::ModelFactory.catalog}.
110
+ class TemplateNotFound < KeyError; end
111
+
112
+ class << self
113
+ # Suggested method for defining multiple factory templates at once.
114
+ #
115
+ # Most projects end up having many domain models which need factories
116
+ # defined. Having to reference the full module constant every time you
117
+ # want to define a factory is tedious. Use this to define all of your
118
+ # model templates within a block.
119
+ #
120
+ # @example
121
+ # require 'radius/spec/model_factory'
122
+ #
123
+ # Radius::Spec::ModelFactory.catalog do |c|
124
+ # c.factory "AnyClass", attr1: :any_value, attr2: :another_value
125
+ #
126
+ # c.factory "AnotherClass",
127
+ # attr1: :any_value,
128
+ # attr2: :another_value,
129
+ # attr3: %i[any list of values]
130
+ # end
131
+ # @yieldparam catalog current catalog storing the registered templates
132
+ # @return [void]
133
+ # @see .factory
134
+ def catalog
135
+ yield self
136
+ end
137
+
138
+ # Convenience helper for registering a template to the current catalog.
139
+ #
140
+ # Registers the `class_name` in the catalog mapped to the provided
141
+ # `attrs` attribute template.
142
+ #
143
+ # ### Lazy Class Loading
144
+ #
145
+ # When testing in isolation we often don't want to wait a long time for
146
+ # a lot of unnecessary project/app code to load. With that in mind we
147
+ # want to keep loading the model factory and all factory templates as
148
+ # fast as possible. This mean not loading the associated project/app
149
+ # code at factory template definition time. This way if you only need
150
+ # one or two factories your remaining domain model code won't be
151
+ # loaded.
152
+ #
153
+ # Lazy class loading occurs when you register factory template using a
154
+ # string or symbol for the fully qualified `class_name`. The only
155
+ # requirement for this feature is that the class must be loaded by the
156
+ # project/app, or made available via some auto-loading mechanism, by
157
+ # the time the first instance is built by the factory.
158
+ #
159
+ # ### Template Attribute Keys
160
+ #
161
+ # Attribute keys may be defined using either strings or symbols.
162
+ # However, they will be stored internally as symbols. This means that
163
+ # when an object instance is create using the factory the **attribute
164
+ # hash will be provided to `new` with _symbol_ keys**.
165
+ #
166
+ # ### Dynamic Attribute Values (i.e. Generators)
167
+ #
168
+ # Dynamic attributes values may be registered by providing a `Proc` for
169
+ # the value. For any template attribute which has a `Proc` for a value
170
+ # making an instance through the factory will send `call` to the proc
171
+ # with no args.
172
+ #
173
+ # <div class="note notetag">
174
+ # <strong>Note:</strong>
175
+ # <div class="inline">
176
+ # <p>
177
+ # This only applies to template values which are instances of
178
+ # <code>Proc</code>. If you define a template value using another
179
+ # object which responds to <code>call</code> that object will be set as
180
+ # the built instance's attribute value without receiving
181
+ # <code>call</code>.
182
+ # </p>
183
+ # </div>
184
+ # </div>
185
+ #
186
+ # While this is a powerful technique we suggest keeping it's use to a
187
+ # minimum. There's a lot of benefit to generative, mutation, and fuzzy
188
+ # testing. We just aren't convinced it should be the default when you
189
+ # generate unit / general integration test data.
190
+ #
191
+ # ### Optional and Required attributes
192
+ #
193
+ # Templates may use the special symbols `:optional` and `:required` as
194
+ # a means of documenting attributes. These special symbols are meant as
195
+ # descriptive placeholders for developers reading the factory
196
+ # definition. Any template attribute with a value of `:optional`, which
197
+ # is not overwritten by a custom value, will be removed just prior to
198
+ # building a new instance.
199
+ #
200
+ # Those attributes marked as `:required` will not be removed. Instead
201
+ # the symbol `:required` will be set as the attribute's value if it
202
+ # isn't overwritten by the custom data. This type of value is a _benign
203
+ # default_ meant to cause errors to provide a more helpful description
204
+ # (i.e. this attribute is required).
205
+ #
206
+ # For Rails projects, we suggest using `:required` for any association
207
+ # that is necessary for the object to be valid. We do not recommend
208
+ # attempting to generate default records within the factory as this can
209
+ # lead to unexpected database state; and hide relevant information away
210
+ # from the specs which may depend on it.
211
+ #
212
+ # ### "Safe" Attribute Duplication
213
+ #
214
+ # In an effort to help limit accidental state leak between instances
215
+ # the factory will duplicate all non-frozen template values prior to
216
+ # building the instance. Duplication is only applied to the values
217
+ # registered for the templates. Custom values provided when building
218
+ # the instance are not duplicated.
219
+ #
220
+ # @example register a domain template using class constant
221
+ # Radius::Spec::ModelFactory.define_factory AnyClass,
222
+ # any_attr: :any_value
223
+ # @example register a domain template using lazy class loading
224
+ # Radius::Spec::ModelFactory.define_factory :AnyClass,
225
+ # any_attr: :any_value
226
+ # @example register a nested class using lazy class loading
227
+ # Radius::Spec::ModelFactory.define_factory "AnyModule::AnyClass",
228
+ # any_attr: :any_value
229
+ # @example advanced example using additional features
230
+ # Radius::Spec::ModelFactory.define_factory(
231
+ # "AnyClass",
232
+ # dynamic: -> { rand(0..100) },
233
+ # safe_array: [1, 2, 3],
234
+ # )
235
+ #
236
+ # AnyClass = Struct.new(:dynamic, :safe_array, keyword_init: true)
237
+ #
238
+ # instance_a = Radius::Spec::ModelFactory.build("AnyClass")
239
+ # # => #<struct AnyClass dynamic=10, safe_array=[1, 2, 3]>
240
+ #
241
+ # instance_a.safe_array << 4
242
+ # # => #<struct AnyClass dynamic=10, safe_array=[1, 2, 3, 4]>
243
+ #
244
+ # instance_b = Radius::Spec::ModelFactory.build("AnyClass")
245
+ # # => #<struct AnyClass dynamic=32, safe_array=[1, 2, 3]>
246
+ # @param class_name [Class, String, Symbol] fully qualified domain
247
+ # model class name or constant
248
+ # @param attrs [Hash{String,Symbol => Object}] hash of attributes and
249
+ # default values to register
250
+ # @return [void]
251
+ def define_factory(class_name, attrs = {})
252
+ templates[class_name.to_s] = attrs.transform_keys(&:to_sym).freeze
253
+ end
254
+ alias_method :factory, :define_factory
255
+
256
+ # @private
257
+ def safe_transform(value)
258
+ return value.call if value.is_a?(Proc)
259
+ return value if value.frozen?
260
+ value.dup
261
+ end
262
+
263
+ # @private
264
+ def template(name)
265
+ templates.fetch(name) {
266
+ raise TemplateNotFound, "template not found: #{name}"
267
+ }
268
+ end
269
+
270
+ # @private
271
+ def templates
272
+ @templates ||= {}
273
+ end
274
+ end
275
+
276
+ module_function
277
+
278
+ # Convenience wrapper for building a model template.
279
+ #
280
+ # All `custom_attrs` values are provided as is to the class initializer
281
+ # (i.e. they are **not** duplicate or modified in any way). When an
282
+ # attribute exists in both the registered template and `custom_attrs` the
283
+ # value in `custom_attrs` will be used. The `custom_attrs` may also
284
+ # include new attributes not defined in the factory template.
285
+ #
286
+ # ### Optional Block
287
+ #
288
+ # The `block` is optional. When provided it is passed directly to `new`
289
+ # when initializing the instance. This is to support the common Ruby
290
+ # idiom of yielding `self` within initialize:
291
+ #
292
+ # ```ruby
293
+ # class AnyClass
294
+ # def initialize(attrs = {})
295
+ # # setup attrs
296
+ # yield self if block_given?
297
+ # end
298
+ # end
299
+ # ```
300
+ #
301
+ # <div class="note notetag">
302
+ # <strong>Note:</strong>
303
+ # <div class="inline">
304
+ # <p>
305
+ # Since Ruby always supports passing a block to a method, even if the
306
+ # method does not use the block, it's possible the block will not run if
307
+ # the class being instantiated does yield to it.
308
+ # </p>
309
+ # <p>
310
+ # Also, while the common idiom is to <code>yield self</code> classes are
311
+ # free to yield anything. You need to be aware of how the class normally
312
+ # behaves when passing a block to <code>new</code>.
313
+ # </p>
314
+ # </div>
315
+ # </div>
316
+ #
317
+ # The examples below show different ways of interacting with the
318
+ # following domain model and registered factory template:
319
+ #
320
+ # ```ruby
321
+ # Radius::Spec::ModelFactory.factory "AnyClass",
322
+ # simple_attr: "any value",
323
+ # array_attr: %w[any value],
324
+ # optional_attr: :optional,
325
+ # dynamic_attr: -> { rand(0..100) }
326
+ #
327
+ # class AnyClass
328
+ # def initialize(**opts)
329
+ # opts.each do |k, v|
330
+ # public_send "#{k}=", v
331
+ # end
332
+ # yield self if block_given?
333
+ # end
334
+ #
335
+ # attr_accessor :array_attr, :dynamic_attr, :optional_attr, :simple_attr
336
+ # end
337
+ # ```
338
+ #
339
+ # @example building the default template using lazy class loading
340
+ # Radius::Spec::ModelFactory.build("AnyClass")
341
+ # # => #<AnyClass @array_attr=["any", "value"],
342
+ # # @dynamic_attr=88,
343
+ # # @simple_attr="any value">
344
+ # @example building the default template using class constant
345
+ # Radius::Spec::ModelFactory.build(AnyClass)
346
+ # # => #<AnyClass @array_attr=["any", "value"],
347
+ # # @dynamic_attr=3,
348
+ # # @simple_attr="any value">
349
+ # @example building the default template with a block
350
+ # Radius::Spec::ModelFactory.build("AnyClass") { |instance|
351
+ # instance.simple_attr = "Block Value"
352
+ # }
353
+ # # => #<AnyClass @array_attr=["any", "value"],
354
+ # # @dynamic_attr=27,
355
+ # # @simple_attr="Block Value">
356
+ # @example building an instance with custom attributes
357
+ # Radius::Spec::ModelFactory.build(
358
+ # "AnyClass",
359
+ # simple_attr: "Custom Value",
360
+ # dynamic_attr: "Static Value",
361
+ # optional_attr: "Optional Value",
362
+ # )
363
+ # # => #<AnyClass @array_attr=["any", "value"],
364
+ # # @dynamic_attr="Static Value",
365
+ # # @optional_attr="Optional Value",
366
+ # # @simple_attr="Custom Value">
367
+ # @example registered template values are safe from modification
368
+ # instance_a = Radius::Spec::ModelFactory.build("AnyClass")
369
+ # instance_b = Radius::Spec::ModelFactory.build("AnyClass")
370
+ # instance_a.simple_attr.upcase!
371
+ # instance_a.array_attr << "modified"
372
+ # puts "#{instance_a.simple_attr}: #{instance_a.array_attr}"
373
+ # puts "#{instance_b.simple_attr}: #{instance_b.array_attr}"
374
+ #
375
+ # # Outputs:
376
+ # # ANY VALUE: ["any", "value", "modified"]
377
+ # # any value: ["any", "value"]
378
+ # @example building instances with custom shared data
379
+ # shared_array = %w[this is shared]
380
+ # instance_a = Radius::Spec::ModelFactory.build(
381
+ # "AnyClass",
382
+ # array_attr: shared_array,
383
+ # simple_attr: "Instance A",
384
+ # )
385
+ # instance_b = Radius::Spec::ModelFactory.build(
386
+ # "AnyClass",
387
+ # array_attr: shared_array,
388
+ # simple_attr: "Instance B",
389
+ # )
390
+ # instance_a.array_attr << "modified"
391
+ # puts "#{instance_a.simple_attr}: #{instance_a.array_attr}"
392
+ # puts "#{instance_b.simple_attr}: #{instance_b.array_attr}"
393
+ #
394
+ # # Outputs:
395
+ # # Instance A: ["this", "is", "shared", "modified"]
396
+ # # Instance B: ["this", "is", "shared", "modified"]
397
+ # @param name [Class, String, Symbol] fully qualified domain model class
398
+ # name or constant
399
+ # @param custom_attrs [Hash{String,Symbol => Object}] hash of custom
400
+ # attributes to replace registered template default values
401
+ # @param block optional block which is passed through to `new` when
402
+ # instantiating `name`
403
+ # @return instance of `name` instantiated with `custom_attrs` and the
404
+ # registered template attributes
405
+ # @raise [TemplateNotFound] when no template is defined for `name`
406
+ # @see .define_factory
407
+ def build(name, custom_attrs = {}, &block)
408
+ name = name.to_s
409
+ template = ::Radius::Spec::ModelFactory.template(name)
410
+ template_only = template.keys - custom_attrs.keys
411
+ attrs = template.slice(*template_only)
412
+ .delete_if { |_, v| :optional == v }
413
+ .transform_values! { |v|
414
+ ::Radius::Spec::ModelFactory.safe_transform(v)
415
+ }
416
+ .merge(custom_attrs)
417
+ # TODO: Always yield to the provided block even if new doesn't
418
+ ::Object.const_get(name).new(attrs, &block)
419
+ end
420
+
421
+ # Convenience wrapper for building, and persisting, a model template.
422
+ #
423
+ # This is a thin wrapper around `build(name, attrs).tap(&:save!)`. The
424
+ # persistence message `save!` will only be called on objects which
425
+ # respond to it.
426
+ #
427
+ # ### Avoid for New Code
428
+ #
429
+ # It is strongly suggested that you avoid using `create` for new code.
430
+ # Instead be explicit about when and how objects are persisted. This
431
+ # allows you to have fine grain control over how your data is setup.
432
+ #
433
+ # We suggest that you create instances which need to be persisted before
434
+ # your specs using the following syntax:
435
+ #
436
+ # ```ruby
437
+ # let(:an_instance) { build("AnyClass") }
438
+ #
439
+ # before do
440
+ # an_instance.save!
441
+ # end
442
+ # ```
443
+ #
444
+ # Alternatively if you really want for the instance be lazy instantiated,
445
+ # and persisted, pass the appropriate persistence method as the block:
446
+ #
447
+ # ```ruby
448
+ # let(:an_instance) { build("AnyClass", &:save!) }
449
+ # ```
450
+ #
451
+ # @param (see .build)
452
+ # @return (see .build)
453
+ # @raise (see .build)
454
+ # @see .build
455
+ # @see .define_factory
456
+ def create(name, custom_attrs = {}, &block)
457
+ instance = build(name, custom_attrs, &block)
458
+ instance.save! if instance.respond_to?(:save!)
459
+ instance
460
+ end
461
+ end
462
+ end
463
+ end
464
+
465
+ # Try to load the factories defined for the specs
466
+ # rubocop:disable Lint/HandleExceptions
467
+ begin
468
+ require 'support/model_factories'
469
+ rescue LoadError
470
+ # Ignore as this is an optional convenience feature
471
+ end
472
+ # rubocop:enable Lint/HandleExceptions
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ensure the gem, and default RSpec config, are already loaded
4
+ require 'radius/spec'
5
+ require 'radius/spec/rspec'
6
+ require 'rspec/rails'
7
+
8
+ RSpec.configure do
9
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
10
+ config.fixture_path = ::Rails.root.join("spec", "fixtures")
11
+
12
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
13
+ # examples within a transaction, remove the following line or assign false
14
+ # instead of true.
15
+ config.use_transactional_fixtures = true
16
+
17
+ # Filter lines from Rails gems in backtraces.
18
+ config.filter_rails_from_backtrace!
19
+ # arbitrary gems may also be filtered via:
20
+ # config.filter_gems_from_backtrace("gem name")
21
+
22
+ # Skip system tests by default.
23
+ #
24
+ # This is what Rails does by default:
25
+ #
26
+ # > By default, running `bin/rails` test won't run your system tests. Make
27
+ # > sure to run `bin/rails test:system` to actually run them.
28
+ #
29
+ # Running system tests often requires additional external dependencies. Not
30
+ # every project is setup to install all of the system test dependencies by
31
+ # default. To avoid issues across projects we default to excluding these
32
+ # specs. Projects are free to overwrite this filter in their custom RSpec
33
+ # configuration.
34
+ #
35
+ # This can be overridden on the command line:
36
+ #
37
+ # bin/rspec -t type:system
38
+ #
39
+ # See:
40
+ # - http://guides.rubyonrails.org/v5.1.4/testing.html#implementing-a-system-test
41
+ # - https://relishapp.com/rspec/rspec-core/v/3-7/docs/filtering/exclusion-filters
42
+ # - http://rspec.info/documentation/3.7/rspec-core/RSpec/Core/Configuration.html#filter_run_excluding-instance_method
43
+ config.filter_run_excluding type: "system"
44
+
45
+ # Always clear the cache before specs to avoid state leak problems
46
+ config.before do
47
+ Rails.cache.clear
48
+ end
49
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Given that it is always loaded, you are encouraged to keep this file as
4
+ # light-weight as possible. Requiring heavyweight dependencies from this file
5
+ # will add to the boot time of your test suite on EVERY test run, even for an
6
+ # individual file that may not need all of that loaded. Instead, consider making
7
+ # a separate helper file that requires the additional dependencies and performs
8
+ # the additional setup, and require it from the spec files that actually need
9
+ # it.
10
+ #
11
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
12
+ RSpec.configure do |config|
13
+ # rspec-expectations config goes here. You can use an alternate
14
+ # assertion/expectation library such as wrong or the stdlib/minitest
15
+ # assertions if you prefer.
16
+ config.expect_with :rspec do |expectations|
17
+ # This option will default to `true` in RSpec 4. It makes the `description`
18
+ # and `failure_message` of custom matchers include text for helper methods
19
+ # defined using `chain`, e.g.:
20
+ # be_bigger_than(2).and_smaller_than(4).description
21
+ # # => "be bigger than 2 and smaller than 4"
22
+ # ...rather than:
23
+ # # => "be bigger than 2"
24
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
25
+ end
26
+
27
+ # rspec-mocks config goes here. You can use an alternate test double
28
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
29
+ config.mock_with :rspec do |mocks|
30
+ # Prevents you from mocking or stubbing a method that does not exist on
31
+ # a real object. This is generally recommended, and will default to
32
+ # `true` in RSpec 4.
33
+ mocks.verify_partial_doubles = true
34
+ mocks.allow_message_expectations_on_nil = false
35
+ mocks.verify_doubled_constant_names = (
36
+ ENV.key?("CI") || !config.files_to_run.one?
37
+ )
38
+ end
39
+
40
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41
+ # have no way to turn it off -- the option exists only for backwards
42
+ # compatibility in RSpec 3). It causes shared context metadata to be
43
+ # inherited by the metadata hash of host groups and examples, rather than
44
+ # triggering implicit auto-inclusion in groups with matching metadata.
45
+ config.shared_context_metadata_behavior = :apply_to_host_groups
46
+
47
+ # This allows you to limit a spec run to individual examples or groups
48
+ # you care about by tagging them with `:focus` metadata. When nothing
49
+ # is tagged with `:focus`, all examples get run. RSpec also provides
50
+ # aliases for `it`, `describe`, and `context` that include `:focus`
51
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
52
+ config.filter_run_when_matching :focus
53
+
54
+ # Allows RSpec to persist some state between runs in order to support
55
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
56
+ # you configure your source control system to ignore this file.
57
+ config.example_status_persistence_file_path = ".rspec_status"
58
+
59
+ # Limits the available syntax to the non-monkey patched syntax that is
60
+ # recommended. For more details, see:
61
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
62
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
63
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
64
+ config.disable_monkey_patching!
65
+
66
+ # This setting enables warnings. It's recommended, but in some cases may
67
+ # be too noisy due to issues in dependencies.
68
+ config.warnings = true
69
+
70
+ # Many RSpec users commonly either run the entire suite or an individual
71
+ # file, and it's useful to allow more verbose output when running an
72
+ # individual spec file.
73
+ if config.files_to_run.one?
74
+ # Use the documentation formatter for detailed output,
75
+ # unless a formatter has already been configured
76
+ # (e.g. via a command-line flag).
77
+ config.default_formatter = "doc"
78
+ end
79
+
80
+ # RSpec will exit with code 0 indicating success if no examples are defined.
81
+ # This option allows you to configure RSpec to exit with code 1 indicating
82
+ # failure. This is useful in CI environments, as it helps detect when you've
83
+ # misconfigured RSpec to look for specs in the wrong place or with the wrong
84
+ # pattern. See http://rspec.info/blog/2017/05/rspec-3-6-has-been-released/#core-configfailifnoexamples
85
+ config.fail_if_no_examples = true
86
+
87
+ # Print the 10 slowest examples and example groups at the
88
+ # end of the spec run, to help surface which specs are running
89
+ # particularly slow.
90
+ config.profile_examples = 10 if ENV["CI"]
91
+
92
+ # Run specs in random order to surface order dependencies. If you find an
93
+ # order dependency and want to debug it, you can fix the order by providing
94
+ # the seed, which is printed after each run.
95
+ # --seed 1234
96
+ config.order = :random
97
+
98
+ # Seed global randomization in this process using the `--seed` CLI option.
99
+ # Setting this allows you to use `--seed` to deterministically reproduce
100
+ # test failures related to randomization by passing the same `--seed` value
101
+ # as the one that triggered the failure.
102
+ Kernel.srand config.seed
103
+
104
+ config.when_first_matching_example_defined(
105
+ :model_factory,
106
+ :model_factories,
107
+ ) do
108
+ require 'radius/spec/model_factory'
109
+ config.include Radius::Spec::ModelFactory, :model_factory, :model_factories
110
+ end
111
+
112
+ config.when_first_matching_example_defined(type: :controller) do
113
+ require 'radius/spec/model_factory'
114
+ config.include Radius::Spec::ModelFactory, type: :controller
115
+ end
116
+
117
+ config.when_first_matching_example_defined(type: :feature) do
118
+ require 'radius/spec/model_factory'
119
+ config.include Radius::Spec::ModelFactory, type: :feature
120
+ end
121
+
122
+ config.when_first_matching_example_defined(type: :job) do
123
+ require 'radius/spec/model_factory'
124
+ config.include Radius::Spec::ModelFactory, type: :job
125
+ end
126
+
127
+ config.when_first_matching_example_defined(type: :model) do
128
+ require 'radius/spec/model_factory'
129
+ config.include Radius::Spec::ModelFactory, type: :model
130
+ end
131
+
132
+ config.when_first_matching_example_defined(type: :request) do
133
+ require 'radius/spec/model_factory'
134
+ config.include Radius::Spec::ModelFactory, type: :request
135
+ end
136
+
137
+ config.when_first_matching_example_defined(type: :system) do
138
+ require 'radius/spec/model_factory'
139
+ config.include Radius::Spec::ModelFactory, type: :system
140
+ end
141
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Radius
4
+ module Spec
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "radius/spec/version"
4
+
5
+ module Radius
6
+ # Namespace for RSpec plug-ins and helpers
7
+ module Spec
8
+ end
9
+ end
10
+
11
+ require "radius/spec/rspec" if defined?(RSpec)