radius-spec 0.2.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/.travis.yml +4 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +122 -1
- data/Gemfile +9 -5
- data/README.md +352 -34
- data/benchmarks/bm_setup.rb +70 -0
- data/benchmarks/call_vs_yield.rb +181 -0
- data/benchmarks/case_equality_vs_class_check.rb +73 -0
- data/benchmarks/casecmp_vs_downcase.rb +488 -0
- data/benchmarks/cover_vs_include.rb +106 -0
- data/benchmarks/delete_vs_tr.rb +100 -0
- data/benchmarks/double_negation.rb +167 -0
- data/benchmarks/empty_literal.rb +75 -0
- data/benchmarks/format_string.rb +58 -0
- data/benchmarks/format_string_token.rb +160 -0
- data/benchmarks/gsub_vs_tr.rb +95 -0
- data/benchmarks/hash_merge.rb +112 -0
- data/benchmarks/kwargs.rb +159 -0
- data/benchmarks/max_ternary.rb +105 -0
- data/benchmarks/max_ternary_micro.rb +129 -0
- data/benchmarks/unfreeze_string.rb +86 -0
- data/benchmarks/unpack_first.rb +54 -0
- data/bin/ci +2 -2
- data/bin/ci-code-review +28 -0
- data/common_rubocop.yml +270 -32
- data/common_rubocop_rails.yml +127 -13
- 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 +1 -0
- metadata +43 -10
- data/bin/travis +0 -29
data/common_rubocop_rails.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
inherit_mode:
|
2
2
|
merge:
|
3
3
|
- Exclude
|
4
|
+
- IgnoredPatterns
|
4
5
|
|
5
6
|
inherit_from: common_rubocop.yml
|
6
7
|
|
@@ -26,6 +27,9 @@ Documentation:
|
|
26
27
|
|
27
28
|
Metrics/BlockLength:
|
28
29
|
Exclude:
|
30
|
+
- 'bin/setup'
|
31
|
+
- 'bin/update'
|
32
|
+
- 'config/routes.rb'
|
29
33
|
- 'spec/rails_helper.rb'
|
30
34
|
|
31
35
|
# Rails foreign keys and indexes can get long. We want to ignore our annotation
|
@@ -38,6 +42,52 @@ Metrics/LineLength:
|
|
38
42
|
- '\A# fk_rails_'
|
39
43
|
- '\A# index_'
|
40
44
|
|
45
|
+
# For our Rails apps several of them use the `respond_to` with `format` blocks
|
46
|
+
# to handle various mime types (mostly HTML and JSON). Given our `do` / `end`
|
47
|
+
# block style for non-functional blocks (which includes both `respond_to` and
|
48
|
+
# `format`) the general method limit of is too small. This also applies to the
|
49
|
+
# helper methods which define the allowed parameters for the action; especially
|
50
|
+
# for larger forms.
|
51
|
+
#
|
52
|
+
# Here is an example of a minimal controller `update` method which uses the
|
53
|
+
# `respond_to` style to support just the HTML and JSON formats:
|
54
|
+
#
|
55
|
+
# ```ruby
|
56
|
+
# def update
|
57
|
+
# respond_to do |format|
|
58
|
+
# if @resource.update(resource_params)
|
59
|
+
# format.html do
|
60
|
+
# redirect_to resources_url, notice: 'Resource was successfully updated.'
|
61
|
+
# end
|
62
|
+
# format.json do
|
63
|
+
# render :show, status: :ok, location: @resource
|
64
|
+
# end
|
65
|
+
# else
|
66
|
+
# format.html do
|
67
|
+
# render :edit
|
68
|
+
# end
|
69
|
+
# format.json do
|
70
|
+
# render json: @resource.errors, status: :unprocessable_entity
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# ```
|
76
|
+
#
|
77
|
+
# We do believe that the default size of 10, which is what we explicitly
|
78
|
+
# configure below so there's no confusion, is a good general limit to help
|
79
|
+
# encourage a balance between terseness and procedural code. Thus we do not
|
80
|
+
# want to raise the limit, instead we just want to exclude these controllers.
|
81
|
+
#
|
82
|
+
# At this time there is no way for us to exclude just the common controller
|
83
|
+
# actions / *_params methods so we exclude the entire file.
|
84
|
+
#
|
85
|
+
# Configuration parameters: CountComments.
|
86
|
+
Metrics/MethodLength:
|
87
|
+
Max: 10
|
88
|
+
Exclude:
|
89
|
+
- 'app/controllers/**/*_controller.rb'
|
90
|
+
|
41
91
|
# Ignore subclass parent for one off benchmarks
|
42
92
|
#
|
43
93
|
# Benchmarks are generally meant to be small and targeted. They often have
|
@@ -58,14 +108,51 @@ Rails/ApplicationRecord:
|
|
58
108
|
Rails/CreateTableWithTimestamps:
|
59
109
|
Enabled: false
|
60
110
|
|
61
|
-
#
|
111
|
+
# Usage of `find_by` is more expressive of intent than `where.first`. We should
|
112
|
+
# check all app code, not just the models to improve intent expression.
|
113
|
+
#
|
114
|
+
# Since rake tasks often live in `lib` we also check all of lib as well.
|
115
|
+
#
|
116
|
+
# Configuration parameters: Include.
|
117
|
+
# Include: app/models/**/*.rb
|
118
|
+
Rails/FindBy:
|
119
|
+
Enabled: true
|
120
|
+
Include:
|
121
|
+
- 'app/**/*.rb'
|
122
|
+
- 'lib/**/*.rb'
|
123
|
+
|
124
|
+
# Usage of `each` for large datasets can be a performance issue; specially a
|
125
|
+
# drain on system memory. When possible it's better to use `find_each` so that
|
126
|
+
# chunks of data are evaluated at a time.
|
127
|
+
#
|
128
|
+
# We should check all app code, not just the models to help prevent this. Since
|
129
|
+
# rake tasks often live in `lib` we also check all of lib as well.
|
130
|
+
#
|
131
|
+
# Configuration parameters: Include.
|
132
|
+
# Include: app/models/**/*.rb
|
133
|
+
Rails/FindEach:
|
134
|
+
Enabled: true
|
135
|
+
Include:
|
136
|
+
- 'app/**/*.rb'
|
137
|
+
- 'lib/**/*.rb'
|
138
|
+
|
139
|
+
# We understand the trade-offs for using the through model versus a lookup
|
140
|
+
# table. As such this cop is just noise as it flags only those cases we really
|
141
|
+
# do want a lookup table.
|
142
|
+
#
|
143
|
+
# Configuration parameters: Include.
|
144
|
+
# Include: app/models/**/*.rb
|
145
|
+
Rails/HasAndBelongsToMany:
|
146
|
+
Enabled: false
|
147
|
+
|
148
|
+
# The ActiveSupport monkey patches for `present?` are nearly all defined as:
|
62
149
|
#
|
63
150
|
# !blank?
|
64
151
|
#
|
65
|
-
# For most of
|
152
|
+
# For most of us `unless blank?` reads just as easily as `if present?`.
|
66
153
|
# Sometimes contextually, it can read better depending on the branch logic and
|
67
154
|
# surrounding context. As `if present?` requires an additional negation and
|
68
|
-
# method call it is technically slower. In the general case the perf
|
155
|
+
# method call it is technically slower. In the general case the perf difference
|
69
156
|
# isn't much but in some cases it matters. Thus, we are not enforcing changing
|
70
157
|
# `unless blank?` to `if present?` and are leaving it up to the context to
|
71
158
|
# decide which is a better fit.
|
@@ -78,7 +165,7 @@ Rails/Present:
|
|
78
165
|
# We prefer you use the attribute readers and writes. For those special cases
|
79
166
|
# where the intent is really to interact with the raw underlying attribute we
|
80
167
|
# prefer `read_attribute` and `write_attribute`; as this makes the intent
|
81
|
-
#
|
168
|
+
# explicit. Ideally we'd never use the hash like accessor `[:attr]`.
|
82
169
|
#
|
83
170
|
# We disable this cop because it is not configurable.
|
84
171
|
#
|
@@ -87,6 +174,37 @@ Rails/Present:
|
|
87
174
|
Rails/ReadWriteAttribute:
|
88
175
|
Enabled: false
|
89
176
|
|
177
|
+
# This ensures we do not ignore potential validation issues in the code. Doing
|
178
|
+
# so can lead to strange and surprising bugs where records are expected to
|
179
|
+
# be created, or be modified, but are not.
|
180
|
+
#
|
181
|
+
# # If author is a new record the book may not be created since the FK is
|
182
|
+
# # invalid. Perhaps omitting other fields, maybe new required fields, is
|
183
|
+
# # an oversight in the book creation as well.
|
184
|
+
# author.save
|
185
|
+
# Book.create(author: author)
|
186
|
+
#
|
187
|
+
# Or side effects are expected to occur but they do not:
|
188
|
+
#
|
189
|
+
# # This is a condensed default Rails scaffold controller for `destroy`.
|
190
|
+
# #
|
191
|
+
# # Once a `has_many` or `has_one` associations is added which specifies
|
192
|
+
# # `dependent: :restrict_with_error` this no longer behaves as expected.
|
193
|
+
# # Given such associations are often added much later in time errors in
|
194
|
+
# # this action are an all to common oversight in Rails.
|
195
|
+
# def destroy
|
196
|
+
# @book.destroy
|
197
|
+
# respond_to do |format|
|
198
|
+
# format.html do
|
199
|
+
# redirect_to books_url, notice: 'Book was successfully destroyed.'
|
200
|
+
# end
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# Configuration parameters: AllowImplicitReturn, AllowedReceivers.
|
205
|
+
Rails/SaveBang:
|
206
|
+
Enabled: true
|
207
|
+
|
90
208
|
# According to the Rails docs while the following methods skip validations they
|
91
209
|
# only update the specified (single) attribute reducing risks. We'd rather not
|
92
210
|
# warn for those cases:
|
@@ -104,17 +222,13 @@ Rails/ReadWriteAttribute:
|
|
104
222
|
# - http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html
|
105
223
|
# - http://api.rubyonrails.org/classes/ActiveRecord/Relation.html
|
106
224
|
#
|
225
|
+
# Configuration parameters: Blacklist, Whitelist.
|
107
226
|
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
108
227
|
Rails/SkipsModelValidations:
|
109
|
-
|
110
|
-
- '
|
111
|
-
- '
|
112
|
-
- '
|
113
|
-
- 'update_all'
|
114
|
-
- 'update_attribute'
|
115
|
-
- 'update_column'
|
116
|
-
- 'update_columns'
|
117
|
-
- 'update_counters'
|
228
|
+
Whitelist:
|
229
|
+
- 'decrement!'
|
230
|
+
- 'increment!'
|
231
|
+
- 'touch'
|
118
232
|
|
119
233
|
# Rails uses compact style by default so we're disabling this with a :hammer:
|
120
234
|
# 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
|