radius-spec 0.3.0 → 0.7.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/.rubocop.yml +5 -1
- data/.travis.yml +3 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +115 -1
- data/Gemfile +2 -1
- data/README.md +330 -31
- data/benchmarks/bm_setup.rb +1 -0
- data/benchmarks/call_vs_yield.rb +33 -0
- data/benchmarks/casecmp_vs_downcase.rb +488 -0
- data/bin/ci +1 -1
- data/common_rubocop.yml +243 -21
- data/common_rubocop_rails.yml +135 -17
- data/lib/radius/spec/model_factory.rb +35 -22
- data/lib/radius/spec/rails.rb +2 -2
- data/lib/radius/spec/rspec.rb +20 -0
- data/lib/radius/spec/rspec/negated_matchers.rb +19 -0
- data/lib/radius/spec/tempfile.rb +162 -0
- data/lib/radius/spec/vcr.rb +100 -0
- data/lib/radius/spec/version.rb +1 -1
- data/radius-spec.gemspec +4 -3
- metadata +40 -18
- data/bin/travis +0 -29
data/common_rubocop_rails.yml
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require: rubocop-rails
|
2
|
+
|
1
3
|
inherit_mode:
|
2
4
|
merge:
|
3
5
|
- Exclude
|
@@ -5,10 +7,6 @@ inherit_mode:
|
|
5
7
|
|
6
8
|
inherit_from: common_rubocop.yml
|
7
9
|
|
8
|
-
# Enable additional Rails cops
|
9
|
-
Rails:
|
10
|
-
Enabled: true
|
11
|
-
|
12
10
|
AllCops:
|
13
11
|
Exclude:
|
14
12
|
- 'bin/puma'
|
@@ -27,6 +25,9 @@ Documentation:
|
|
27
25
|
|
28
26
|
Metrics/BlockLength:
|
29
27
|
Exclude:
|
28
|
+
- 'bin/setup'
|
29
|
+
- 'bin/update'
|
30
|
+
- 'config/routes.rb'
|
30
31
|
- 'spec/rails_helper.rb'
|
31
32
|
|
32
33
|
# Rails foreign keys and indexes can get long. We want to ignore our annotation
|
@@ -39,6 +40,52 @@ Metrics/LineLength:
|
|
39
40
|
- '\A# fk_rails_'
|
40
41
|
- '\A# index_'
|
41
42
|
|
43
|
+
# For our Rails apps several of them use the `respond_to` with `format` blocks
|
44
|
+
# to handle various mime types (mostly HTML and JSON). Given our `do` / `end`
|
45
|
+
# block style for non-functional blocks (which includes both `respond_to` and
|
46
|
+
# `format`) the general method limit of is too small. This also applies to the
|
47
|
+
# helper methods which define the allowed parameters for the action; especially
|
48
|
+
# for larger forms.
|
49
|
+
#
|
50
|
+
# Here is an example of a minimal controller `update` method which uses the
|
51
|
+
# `respond_to` style to support just the HTML and JSON formats:
|
52
|
+
#
|
53
|
+
# ```ruby
|
54
|
+
# def update
|
55
|
+
# respond_to do |format|
|
56
|
+
# if @resource.update(resource_params)
|
57
|
+
# format.html do
|
58
|
+
# redirect_to resources_url, notice: 'Resource was successfully updated.'
|
59
|
+
# end
|
60
|
+
# format.json do
|
61
|
+
# render :show, status: :ok, location: @resource
|
62
|
+
# end
|
63
|
+
# else
|
64
|
+
# format.html do
|
65
|
+
# render :edit
|
66
|
+
# end
|
67
|
+
# format.json do
|
68
|
+
# render json: @resource.errors, status: :unprocessable_entity
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
# ```
|
74
|
+
#
|
75
|
+
# We do believe that the default size of 10, which is what we explicitly
|
76
|
+
# configure below so there's no confusion, is a good general limit to help
|
77
|
+
# encourage a balance between terseness and procedural code. Thus we do not
|
78
|
+
# want to raise the limit, instead we just want to exclude these controllers.
|
79
|
+
#
|
80
|
+
# At this time there is no way for us to exclude just the common controller
|
81
|
+
# actions / *_params methods so we exclude the entire file.
|
82
|
+
#
|
83
|
+
# Configuration parameters: CountComments.
|
84
|
+
Metrics/MethodLength:
|
85
|
+
Max: 10
|
86
|
+
Exclude:
|
87
|
+
- 'app/controllers/**/*_controller.rb'
|
88
|
+
|
42
89
|
# Ignore subclass parent for one off benchmarks
|
43
90
|
#
|
44
91
|
# Benchmarks are generally meant to be small and targeted. They often have
|
@@ -59,14 +106,58 @@ Rails/ApplicationRecord:
|
|
59
106
|
Rails/CreateTableWithTimestamps:
|
60
107
|
Enabled: false
|
61
108
|
|
62
|
-
#
|
109
|
+
# Usage of `find_by` is more expressive of intent than `where.first`. We should
|
110
|
+
# check all app code, not just the models to improve intent expression.
|
111
|
+
#
|
112
|
+
# Since rake tasks often live in `lib` we also check all of lib as well.
|
113
|
+
#
|
114
|
+
# Configuration parameters: Include.
|
115
|
+
# Include: app/models/**/*.rb
|
116
|
+
Rails/FindBy:
|
117
|
+
Enabled: true
|
118
|
+
Include:
|
119
|
+
- 'app/**/*.rb'
|
120
|
+
- 'lib/**/*.rb'
|
121
|
+
|
122
|
+
# Usage of `each` for large datasets can be a performance issue; specially a
|
123
|
+
# drain on system memory. When possible it's better to use `find_each` so that
|
124
|
+
# chunks of data are evaluated at a time.
|
125
|
+
#
|
126
|
+
# We should check all app code, not just the models to help prevent this. Since
|
127
|
+
# rake tasks often live in `lib` we also check all of lib as well.
|
128
|
+
#
|
129
|
+
# Configuration parameters: Include.
|
130
|
+
# Include: app/models/**/*.rb
|
131
|
+
Rails/FindEach:
|
132
|
+
Enabled: true
|
133
|
+
Include:
|
134
|
+
- 'app/**/*.rb'
|
135
|
+
- 'lib/**/*.rb'
|
136
|
+
|
137
|
+
# We understand the trade-offs for using the through model versus a lookup
|
138
|
+
# table. As such this cop is just noise as it flags only those cases we really
|
139
|
+
# do want a lookup table.
|
140
|
+
#
|
141
|
+
# Configuration parameters: Include.
|
142
|
+
# Include: app/models/**/*.rb
|
143
|
+
Rails/HasAndBelongsToMany:
|
144
|
+
Enabled: false
|
145
|
+
|
146
|
+
# We find the combo `:only` and `:if` readable. While the `:except` and `:if`
|
147
|
+
# combo is easier to read as a combined proc. As a team we are fine with
|
148
|
+
# handling this in PR reviews, until such time which Rubocop provides an option
|
149
|
+
# for us to configure this.
|
150
|
+
Rails/IgnoredSkipActionFilterOption:
|
151
|
+
Enabled: false
|
152
|
+
|
153
|
+
# The ActiveSupport monkey patches for `present?` are nearly all defined as:
|
63
154
|
#
|
64
155
|
# !blank?
|
65
156
|
#
|
66
|
-
# For most of
|
157
|
+
# For most of us `unless blank?` reads just as easily as `if present?`.
|
67
158
|
# Sometimes contextually, it can read better depending on the branch logic and
|
68
159
|
# surrounding context. As `if present?` requires an additional negation and
|
69
|
-
# method call it is technically slower. In the general case the perf
|
160
|
+
# method call it is technically slower. In the general case the perf difference
|
70
161
|
# isn't much but in some cases it matters. Thus, we are not enforcing changing
|
71
162
|
# `unless blank?` to `if present?` and are leaving it up to the context to
|
72
163
|
# decide which is a better fit.
|
@@ -79,7 +170,7 @@ Rails/Present:
|
|
79
170
|
# We prefer you use the attribute readers and writes. For those special cases
|
80
171
|
# where the intent is really to interact with the raw underlying attribute we
|
81
172
|
# prefer `read_attribute` and `write_attribute`; as this makes the intent
|
82
|
-
#
|
173
|
+
# explicit. Ideally we'd never use the hash like accessor `[:attr]`.
|
83
174
|
#
|
84
175
|
# We disable this cop because it is not configurable.
|
85
176
|
#
|
@@ -88,6 +179,37 @@ Rails/Present:
|
|
88
179
|
Rails/ReadWriteAttribute:
|
89
180
|
Enabled: false
|
90
181
|
|
182
|
+
# This ensures we do not ignore potential validation issues in the code. Doing
|
183
|
+
# so can lead to strange and surprising bugs where records are expected to
|
184
|
+
# be created, or be modified, but are not.
|
185
|
+
#
|
186
|
+
# # If author is a new record the book may not be created since the FK is
|
187
|
+
# # invalid. Perhaps omitting other fields, maybe new required fields, is
|
188
|
+
# # an oversight in the book creation as well.
|
189
|
+
# author.save
|
190
|
+
# Book.create(author: author)
|
191
|
+
#
|
192
|
+
# Or side effects are expected to occur but they do not:
|
193
|
+
#
|
194
|
+
# # This is a condensed default Rails scaffold controller for `destroy`.
|
195
|
+
# #
|
196
|
+
# # Once a `has_many` or `has_one` associations is added which specifies
|
197
|
+
# # `dependent: :restrict_with_error` this no longer behaves as expected.
|
198
|
+
# # Given such associations are often added much later in time errors in
|
199
|
+
# # this action are an all to common oversight in Rails.
|
200
|
+
# def destroy
|
201
|
+
# @book.destroy
|
202
|
+
# respond_to do |format|
|
203
|
+
# format.html do
|
204
|
+
# redirect_to books_url, notice: 'Book was successfully destroyed.'
|
205
|
+
# end
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# Configuration parameters: AllowImplicitReturn, AllowedReceivers.
|
210
|
+
Rails/SaveBang:
|
211
|
+
Enabled: true
|
212
|
+
|
91
213
|
# According to the Rails docs while the following methods skip validations they
|
92
214
|
# only update the specified (single) attribute reducing risks. We'd rather not
|
93
215
|
# warn for those cases:
|
@@ -105,17 +227,13 @@ Rails/ReadWriteAttribute:
|
|
105
227
|
# - http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html
|
106
228
|
# - http://api.rubyonrails.org/classes/ActiveRecord/Relation.html
|
107
229
|
#
|
230
|
+
# Configuration parameters: Blacklist, Whitelist.
|
108
231
|
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
109
232
|
Rails/SkipsModelValidations:
|
110
|
-
|
111
|
-
- '
|
112
|
-
- '
|
113
|
-
- '
|
114
|
-
- 'update_all'
|
115
|
-
- 'update_attribute'
|
116
|
-
- 'update_column'
|
117
|
-
- 'update_columns'
|
118
|
-
- 'update_counters'
|
233
|
+
Whitelist:
|
234
|
+
- 'decrement!'
|
235
|
+
- 'increment!'
|
236
|
+
- 'touch'
|
119
237
|
|
120
238
|
# Rails uses compact style by default so we're disabling this with a :hammer:
|
121
239
|
# for things likely to be generated by Rails (i.e. most things in app).
|
@@ -268,6 +268,7 @@ module Radius
|
|
268
268
|
def safe_transform(value)
|
269
269
|
return value.call if value.is_a?(Proc)
|
270
270
|
return value if value.frozen?
|
271
|
+
|
271
272
|
value.dup
|
272
273
|
end
|
273
274
|
|
@@ -426,44 +427,56 @@ module Radius
|
|
426
427
|
|
427
428
|
# Convenience wrapper for building, and persisting, a model template.
|
428
429
|
#
|
429
|
-
# This is a thin wrapper around
|
430
|
-
# persistence message `save!` will only be called on objects which
|
431
|
-
# respond to it.
|
432
|
-
#
|
433
|
-
# ### Avoid for New Code
|
430
|
+
# This is a thin wrapper around:
|
434
431
|
#
|
435
|
-
#
|
436
|
-
#
|
437
|
-
#
|
432
|
+
# ```ruby
|
433
|
+
# build(name, attrs, &block).tap(&:save!)
|
434
|
+
# ```
|
438
435
|
#
|
439
|
-
#
|
440
|
-
#
|
436
|
+
# The persistence message `save!` will only be called on objects which
|
437
|
+
# respond to it.
|
441
438
|
#
|
442
|
-
#
|
443
|
-
#
|
439
|
+
# @note It is generally suggested that you avoid using `build!` for new
|
440
|
+
# code. Instead be explicit about when and how objects are persisted.
|
441
|
+
# This allows you to have fine grain control over how your data is
|
442
|
+
# setup.
|
444
443
|
#
|
445
|
-
#
|
446
|
-
#
|
447
|
-
# end
|
448
|
-
# ```
|
444
|
+
# We suggest that you create instances which need to be persisted
|
445
|
+
# before your specs using the following syntax:
|
449
446
|
#
|
450
|
-
#
|
451
|
-
#
|
447
|
+
# ```ruby
|
448
|
+
# let(:an_instance) { build("AnyClass") }
|
452
449
|
#
|
453
|
-
#
|
454
|
-
#
|
455
|
-
#
|
450
|
+
# before do
|
451
|
+
# an_instance.save!
|
452
|
+
# end
|
453
|
+
# ```
|
456
454
|
#
|
457
455
|
# @param (see .build)
|
458
456
|
# @return (see .build)
|
459
457
|
# @raise (see .build)
|
460
458
|
# @see .build
|
461
459
|
# @see .define_factory
|
462
|
-
|
460
|
+
# @since 0.5.0
|
461
|
+
def build!(name, custom_attrs = {}, &block)
|
463
462
|
instance = build(name, custom_attrs, &block)
|
464
463
|
instance.save! if instance.respond_to?(:save!)
|
465
464
|
instance
|
466
465
|
end
|
466
|
+
|
467
|
+
# Legacy helper provided for backwards compatibility support.
|
468
|
+
#
|
469
|
+
# This provides the same behavior as {.build!} and will be removed in a
|
470
|
+
# future release.
|
471
|
+
#
|
472
|
+
# @param (see .build)
|
473
|
+
# @return (see .build)
|
474
|
+
# @raise (see .build)
|
475
|
+
# @see .build
|
476
|
+
# @see .define_factory
|
477
|
+
def create(name, custom_attrs = {}, &block)
|
478
|
+
build!(name, custom_attrs, &block)
|
479
|
+
end
|
467
480
|
end
|
468
481
|
end
|
469
482
|
end
|
data/lib/radius/spec/rails.rb
CHANGED
@@ -7,7 +7,7 @@ require 'rspec/rails'
|
|
7
7
|
|
8
8
|
RSpec.configure do |config|
|
9
9
|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
10
|
-
config.fixture_path = ::Rails.root.join("spec", "fixtures")
|
10
|
+
config.fixture_path = ::Rails.root.join("spec", "fixtures").to_path
|
11
11
|
|
12
12
|
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
13
13
|
# examples within a transaction, remove the following line or assign false
|
@@ -40,7 +40,7 @@ RSpec.configure do |config|
|
|
40
40
|
# - http://guides.rubyonrails.org/v5.1.4/testing.html#implementing-a-system-test
|
41
41
|
# - https://relishapp.com/rspec/rspec-core/v/3-7/docs/filtering/exclusion-filters
|
42
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"
|
43
|
+
config.filter_run_excluding type: "system" unless config.files_to_run.one?
|
44
44
|
|
45
45
|
# Always clear the cache before specs to avoid state leak problems
|
46
46
|
config.before do
|
data/lib/radius/spec/rspec.rb
CHANGED
@@ -109,6 +109,11 @@ RSpec.configure do |config|
|
|
109
109
|
config.include Radius::Spec::ModelFactory, :model_factory, :model_factories
|
110
110
|
end
|
111
111
|
|
112
|
+
config.when_first_matching_example_defined(:tempfile, :tmpfile) do
|
113
|
+
require 'radius/spec/tempfile'
|
114
|
+
config.include Radius::Spec::Tempfile, :tempfile, :tmpfile
|
115
|
+
end
|
116
|
+
|
112
117
|
config.when_first_matching_example_defined(type: :controller) do
|
113
118
|
require 'radius/spec/model_factory'
|
114
119
|
config.include Radius::Spec::ModelFactory, type: :controller
|
@@ -124,6 +129,11 @@ RSpec.configure do |config|
|
|
124
129
|
config.include Radius::Spec::ModelFactory, type: :job
|
125
130
|
end
|
126
131
|
|
132
|
+
config.when_first_matching_example_defined(type: :mailer) do
|
133
|
+
require 'radius/spec/model_factory'
|
134
|
+
config.include Radius::Spec::ModelFactory, type: :mailer
|
135
|
+
end
|
136
|
+
|
127
137
|
config.when_first_matching_example_defined(type: :model) do
|
128
138
|
require 'radius/spec/model_factory'
|
129
139
|
config.include Radius::Spec::ModelFactory, type: :model
|
@@ -138,4 +148,14 @@ RSpec.configure do |config|
|
|
138
148
|
require 'radius/spec/model_factory'
|
139
149
|
config.include Radius::Spec::ModelFactory, type: :system
|
140
150
|
end
|
151
|
+
|
152
|
+
config.when_first_matching_example_defined(:webmock) do
|
153
|
+
require 'webmock/rspec'
|
154
|
+
end
|
155
|
+
|
156
|
+
config.when_first_matching_example_defined(:vcr, :vcr_record, :vcr_record_new) do
|
157
|
+
require 'radius/spec/vcr'
|
158
|
+
end
|
141
159
|
end
|
160
|
+
|
161
|
+
require 'radius/spec/rspec/negated_matchers'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Define negated matchers for use with composable matchers and compound
|
4
|
+
# expectations.
|
5
|
+
#
|
6
|
+
# @see https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/composing-matchers
|
7
|
+
# @see https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/compound-expectations
|
8
|
+
RSpec::Matchers.define_negated_matcher :exclude, :include
|
9
|
+
RSpec::Matchers.define_negated_matcher :excluding, :including
|
10
|
+
RSpec::Matchers.define_negated_matcher :not_eq, :eq
|
11
|
+
|
12
|
+
# Allows us to check that a block doesn't raise an exception while also
|
13
|
+
# checking for other changes using compound expectations; since you can't chain
|
14
|
+
# a negative (`not_to`) with any other matchers
|
15
|
+
#
|
16
|
+
# @see https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/compound-expectations
|
17
|
+
RSpec::Matchers.define_negated_matcher :not_change, :change
|
18
|
+
RSpec::Matchers.define_negated_matcher :not_raise_error, :raise_error
|
19
|
+
RSpec::Matchers.define_negated_matcher :not_raise_exception, :raise_exception
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Radius
|
7
|
+
module Spec
|
8
|
+
# Temporary file helpers
|
9
|
+
#
|
10
|
+
# These helpers are meant to ease the creation of temporary files to either
|
11
|
+
# stub the data out or provide a location for data to be saved then
|
12
|
+
# verified.
|
13
|
+
#
|
14
|
+
# In the case of file stubs, using these helpers allows you to co-locate
|
15
|
+
# the file data with the specs. This makes it easy for someone to read the
|
16
|
+
# spec and understand the test case; instead of having to find a fixture
|
17
|
+
# file and look at its data. This also makes it easy to change the data
|
18
|
+
# between specs, allowing them to focus on just what they need.
|
19
|
+
#
|
20
|
+
# To make these helpers available require them after the gem:
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# require 'radius/spec'
|
24
|
+
# require 'radius/spec/tempfile'
|
25
|
+
# ```
|
26
|
+
#
|
27
|
+
# ### Including Helpers in Specs
|
28
|
+
#
|
29
|
+
# There are multiple ways you can use these helpers. Which method you
|
30
|
+
# choose depends on how much perceived magic/syntactic sugar you want:
|
31
|
+
#
|
32
|
+
# - call the helpers directly on the module
|
33
|
+
# - manually include the helper methods in the specs
|
34
|
+
# - use metadata to auto load this feature and include it in the specs
|
35
|
+
#
|
36
|
+
# When using the metadata option you do not need to explicitly require the
|
37
|
+
# module. This gem registers metadata with the RSpec configuration when it
|
38
|
+
# loads and `RSpec` is defined. When the matching metadata is first used it
|
39
|
+
# will automatically require and include the helpers.
|
40
|
+
#
|
41
|
+
# Any of following metadata will include the factory helpers:
|
42
|
+
#
|
43
|
+
# - `:tempfile`
|
44
|
+
# - `:tmpfile`
|
45
|
+
#
|
46
|
+
# @example use a helper directly in specs
|
47
|
+
# require 'radius/spec/tempfile'
|
48
|
+
#
|
49
|
+
# RSpec.describe AnyClass do
|
50
|
+
# it "includes the file helpers" do
|
51
|
+
# Radius::Spec::Tempfile.using_tempfile do |pathname|
|
52
|
+
# code_under_test pathname
|
53
|
+
# expect(pathname.read).to eq "Any written data"
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# @example manually include the helpers
|
58
|
+
# require 'radius/spec/tempfile'
|
59
|
+
#
|
60
|
+
# RSpec.describe AnyClass do
|
61
|
+
# include Radius::Spec::Tempfile
|
62
|
+
# it "includes the file helpers" do
|
63
|
+
# using_tempfile do |pathname|
|
64
|
+
# code_under_test pathname
|
65
|
+
# expect(pathname.read).to eq "Any written data"
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
# @example use metadata to auto include the helpers
|
70
|
+
# RSpec.describe AnyClass do
|
71
|
+
# it "includes the file helpers", :tempfile do
|
72
|
+
# using_tempfile do |pathname|
|
73
|
+
# code_under_test pathname
|
74
|
+
# expect(pathname.read).to eq "Any written data"
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
# @since 0.5.0
|
79
|
+
module Tempfile
|
80
|
+
module_function
|
81
|
+
|
82
|
+
# Convenience wrapper for managaing temporary files.
|
83
|
+
#
|
84
|
+
# This creates a temporary file and yields its path to the provided
|
85
|
+
# block. When the block returns the temporary file is deleted.
|
86
|
+
#
|
87
|
+
# ### Optional Parameters
|
88
|
+
#
|
89
|
+
# The block is required. All other parameters are optional. All
|
90
|
+
# parameters except `data` are Ruby version dependent and will be
|
91
|
+
# forwarded directly to the stdlib's
|
92
|
+
# {https://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/Tempfile.html#method-c-create
|
93
|
+
# `Tempfile.create`}. The when the `data` parameter is provided it's
|
94
|
+
# contents will be written to the temporary file prior to yielding to the
|
95
|
+
# block.
|
96
|
+
#
|
97
|
+
# @example creating a tempfile to pass to code
|
98
|
+
# def write_hello_world(filepath)
|
99
|
+
# File.write filepath, "Hello World"
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# Radius::Spec::Tempfile.using_tempfile do |pathname|
|
103
|
+
# write_hello_world pathname
|
104
|
+
# end
|
105
|
+
# @example creating a file stub
|
106
|
+
# stub_data = "Any file stub data text."
|
107
|
+
# Radius::Spec::Tempfile.using_tempfile(data: stub_data) do |stubpath|
|
108
|
+
# # File.read(stubpath)
|
109
|
+
# # => "Any file stub data text."
|
110
|
+
# code_under_test stubpath
|
111
|
+
# end
|
112
|
+
# @example creating a file stub inline
|
113
|
+
# Radius::Spec::Tempfile.using_tempfile(data: <<~TEXT) do |stubpath|
|
114
|
+
# Any file stub data text.
|
115
|
+
# TEXT
|
116
|
+
# # File.read(stubpath)
|
117
|
+
# # => "Any file stub data text.\n"
|
118
|
+
# code_under_test stubpath
|
119
|
+
# end
|
120
|
+
# @example creating a file stub inline without trailing newline
|
121
|
+
# Radius::Spec::Tempfile.using_tempfile(data: <<~TEXT.chomp) do |stubpath|
|
122
|
+
# Any file stub data text.
|
123
|
+
# TEXT
|
124
|
+
# # File.read(stubpath)
|
125
|
+
# # => "Any file stub data text."
|
126
|
+
# code_under_test stubpath
|
127
|
+
# end
|
128
|
+
# @example writing binary data inline
|
129
|
+
# Radius::Spec::Tempfile.using_tempfile(encoding: Encoding::BINARY, data: <<~BIN.chomp) do |binpath|
|
130
|
+
# \xC8\x90\xC5\x9D\xE1\xB9\x95\xC4\x93\xC4\x89
|
131
|
+
# BIN
|
132
|
+
# # File.read(binpath)
|
133
|
+
# # => "Ȑŝṕēĉ"
|
134
|
+
# code_under_test binpath
|
135
|
+
# end
|
136
|
+
# @param args [Object] addition file creation options
|
137
|
+
#
|
138
|
+
# Passed directly to {https://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/Tempfile.html#method-c-create
|
139
|
+
# `Tempfile.create`}; see the stdlib docs for details on available
|
140
|
+
# options.
|
141
|
+
# @param data [String] stub data to write to the file before yielding
|
142
|
+
# @param kwargs [Hash{Symbol => Object}] addition file creation options
|
143
|
+
#
|
144
|
+
# Passed directly to {https://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/Tempfile.html#method-c-create
|
145
|
+
# `Tempfile.create`}; see the stdlib docs for details on available
|
146
|
+
# options.
|
147
|
+
# @yieldparam pathname [Pathname] {https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html path}
|
148
|
+
# of the created temporary file
|
149
|
+
# @note A block must be provided
|
150
|
+
# @see https://ruby-doc.org/stdlib/libdoc/pathname/rdoc/Pathname.html Pathname
|
151
|
+
# @see https://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/Tempfile.html Tempfile
|
152
|
+
def using_tempfile(*args, data: nil, **kwargs)
|
153
|
+
args << 'tmpfile' if args.empty?
|
154
|
+
::Tempfile.create(*args, **kwargs) do |f|
|
155
|
+
f.write(data)
|
156
|
+
f.close
|
157
|
+
yield Pathname(f.path)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|