radius-spec 0.4.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/.yardopts +1 -0
- data/CHANGELOG.md +42 -1
- data/Gemfile +1 -1
- data/README.md +330 -31
- data/benchmarks/bm_setup.rb +1 -0
- data/common_rubocop.yml +23 -3
- data/common_rubocop_rails.yml +60 -1
- data/lib/radius/spec/model_factory.rb +35 -22
- data/lib/radius/spec/rails.rb +1 -1
- 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 -1
- metadata +9 -7
- data/bin/travis +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 229205333f0d39f679032b076188c7a18013408c034486de29c4f4a684ddcf74
|
4
|
+
data.tar.gz: 37aa800e6bfdb5b273de8837cbe62f87ca8f4f6b3a93bce091b7bbe6867cd64e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0dde94d3cb6579e8faf68027cf1f77c1d8268d4d7c1979b05c5554e4e000769e2b6240f398d396558d0c71c2c717ead0062c5f236d4d03a49981fa91c8a95ca
|
7
|
+
data.tar.gz: 027ef0ac9fcbc76dbaa374382035829e7607c4d3dc2979f2bbc8413b7cbd032961760ed798ac1bda7b83fba9899127c82c96743e8d716fca50f2fb93e01bb0bd
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,44 @@
|
|
1
|
+
## 0.5.0 (September 26, 2018)
|
2
|
+
|
3
|
+
[Full Changelog](https://github.com/RadiusNetworks/radius-spec/compare/v0.4.0...v0.5.0)
|
4
|
+
|
5
|
+
### Enhancements
|
6
|
+
|
7
|
+
- Add common VCR configuration (Aaron Kromer, #16)
|
8
|
+
- Filters out `Authorization` headers
|
9
|
+
- Filters out the following sensitive/environment varying `ENV` values, as
|
10
|
+
well as their URL and form encoded variants:
|
11
|
+
- `AWS_ACCESS_KEY_ID`
|
12
|
+
- `AWS_SECRET_ACCESS_KEY`
|
13
|
+
- `GOOGLE_CLIENT_ID`
|
14
|
+
- `GOOGLE_CLIENT_SECRET`
|
15
|
+
- `RADIUS_OAUTH_PROVIDER_APP_ID`
|
16
|
+
- `RADIUS_OAUTH_PROVIDER_APP_SECRET`
|
17
|
+
- `RADIUS_OAUTH_PROVIDER_URL`
|
18
|
+
- Add "temp file" helpers for working with file stubs (Aaron Kromer, #15)
|
19
|
+
- Upgrade to Rubocop 0.59.x (Aaron Kromer, #14)
|
20
|
+
- Adjust common Rubocop configuration (Aaron Kromer, #14)
|
21
|
+
- `Layout/EmptyLineAfterGuardClause` is enabled by default
|
22
|
+
- Enable `Rails/SaveBang` to highlight potential lurking issues
|
23
|
+
- Expand `Rails/FindBy` and `Rails/FindEach` to check all `/app` and `/lib`
|
24
|
+
- Add more functional methods
|
25
|
+
- `default_scope`
|
26
|
+
- `filter_sensitive_data`
|
27
|
+
- Add `build!` factory method to compliment `build` to help resolving Rubocop
|
28
|
+
violations for `Rails/SaveBang` (Aaron Kromer, #14)
|
29
|
+
- Load model factory for specs tagged with 'type: :mailer' (Aaron Kromer, #11)
|
30
|
+
- Include the following negated RSpec matchers (Aaron Kromer, #12)
|
31
|
+
- `exclude` / `excluding`
|
32
|
+
- `not_eq`
|
33
|
+
- `not_change`
|
34
|
+
- `not_raise_error` / `not_raise_exception`
|
35
|
+
|
36
|
+
### Bug Fixes
|
37
|
+
|
38
|
+
- Fix `NoMethodError: undefined method 'strip'` when the fixture path is a
|
39
|
+
`Pathname` object (Aaron Kromer, #13)
|
40
|
+
|
41
|
+
|
1
42
|
## 0.4.0 (July 10, 2018)
|
2
43
|
|
3
44
|
[Full Changelog](https://github.com/RadiusNetworks/radius-spec/compare/v0.3.0...v0.4.0)
|
@@ -88,7 +129,7 @@
|
|
88
129
|
|
89
130
|
### Bug Fixes
|
90
131
|
|
91
|
-
- Fix `NameError: undefined local variable or method
|
132
|
+
- Fix `NameError: undefined local variable or method config` for Rails RSpec
|
92
133
|
configuration (Aaron Kromer, #1)
|
93
134
|
- Fix model factory build issue in which registered template attributes, which
|
94
135
|
use symbol keys, are not replaced by custom attributes using string keys
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -249,7 +249,7 @@ constant so no changes need to be made if that's your preference.
|
|
249
249
|
|
250
250
|
Attribute keys may be defined using either strings or symbols. However, they
|
251
251
|
will be stored internally as symbols. This means that when an object instance
|
252
|
-
is
|
252
|
+
is created using the factory the attribute hash will be provided to `new` with
|
253
253
|
symbol keys.
|
254
254
|
|
255
255
|
##### Dynamic Attribute Values (i.e. Generators)
|
@@ -418,26 +418,26 @@ There are a few behaviors to note for using the builder:
|
|
418
418
|
|
419
419
|
##### Optional Block
|
420
420
|
|
421
|
-
Both `build` and `
|
421
|
+
Both `build` and `build!` support providing an optional block. This block is
|
422
422
|
passed directly to `new` when creating the object. This is to support the
|
423
423
|
common Ruby idiom of yielding `self` within initialize:
|
424
424
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
end
|
425
|
+
```ruby
|
426
|
+
class AnyClass
|
427
|
+
def initialize(attrs = {})
|
428
|
+
# setup attrs
|
429
|
+
yield self if block_given?
|
431
430
|
end
|
431
|
+
end
|
432
432
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
end
|
433
|
+
RSpec.describe AnyClass, :model_factory do
|
434
|
+
it "passes the block to the object initializer" do
|
435
|
+
block_capture = nil
|
436
|
+
an_object = build("AnyClass") { |instance| block_capture = instance }
|
437
|
+
expect(block_capture).to be an_object
|
439
438
|
end
|
440
|
-
|
439
|
+
end
|
440
|
+
```
|
441
441
|
|
442
442
|
Since Ruby always supports passing a block to a method, even if the method does
|
443
443
|
not use the block, it's possible the block will not run if the class being
|
@@ -451,29 +451,328 @@ this feature.
|
|
451
451
|
|
452
452
|
We suggest that you create instances using the following syntax:
|
453
453
|
|
454
|
-
|
455
|
-
|
456
|
-
```
|
454
|
+
```ruby
|
455
|
+
let(:an_instance) { build("AnyClass") }
|
457
456
|
|
458
|
-
|
457
|
+
before do
|
458
|
+
an_instance.save!
|
459
|
+
end
|
460
|
+
```
|
459
461
|
|
460
|
-
|
461
|
-
let(:an_instance) { build("AnyClass") }
|
462
|
+
Or alternatively:
|
462
463
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
464
|
+
```ruby
|
465
|
+
created_instance = build("AnyClass")
|
466
|
+
created_instance.save!
|
467
|
+
```
|
467
468
|
|
468
469
|
This way it is explicit what objects need to be persisted and in what order.
|
469
470
|
|
470
|
-
|
471
|
-
|
472
|
-
|
471
|
+
This can get tedious at times, especially for those who only need to create an
|
472
|
+
object to embed as an attribute of another object:
|
473
|
+
|
474
|
+
```ruby
|
475
|
+
collaborator = build("AnotherClass")
|
476
|
+
collaborator.save!
|
477
|
+
|
478
|
+
# collaborator is not used against directly after this line
|
479
|
+
created_instance = build("AnyClass", collaborator: collaborator)
|
480
|
+
created_instance.save!
|
481
|
+
```
|
482
|
+
|
483
|
+
For these cases the `build!` helper is available. This is simply an alias for
|
484
|
+
`build.tap(&:save!)`, but it supports omitting the `save!` call for objects
|
485
|
+
which do not support it. While it provides a safety guarantee that `save!` will
|
486
|
+
be called (instead of potentially `save`) it is less explicit.
|
487
|
+
|
488
|
+
```ruby
|
489
|
+
created_instance = build("AnyClass", collaborator: build!("AnotherClass"))
|
490
|
+
created_instance.save!
|
491
|
+
```
|
492
|
+
|
493
|
+
We still discourage the use of `build!` directly in `let` blocks for all of the
|
494
|
+
above mentioned reasons.
|
495
|
+
|
496
|
+
##### Legacy "Creating" Instances
|
497
|
+
|
498
|
+
Many of our existing projects use a legacy `create` helper. This is simply an
|
499
|
+
alias for `build!`. It is provided only for backwards compatibility support and
|
500
|
+
will be removed in a future release. New code should not use this method.
|
501
|
+
|
502
|
+
```ruby
|
503
|
+
created_instance = create("AnyClass")
|
504
|
+
```
|
505
|
+
|
506
|
+
### Negated Matchers
|
507
|
+
|
508
|
+
This gem defines the following [negated matchers](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/define-negated-matcher)
|
509
|
+
to allow for use [composing matchers](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/composing-matchers)
|
510
|
+
and with [compound expectations](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/compound-expectations).
|
511
|
+
|
512
|
+
| Matcher | Inverse Of |
|
513
|
+
|-----------------------|------------|
|
514
|
+
| `exclude` | [`include`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/include-matcher) |
|
515
|
+
| `excluding` | [`including`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/include-matcher) |
|
516
|
+
| `not_eq` | [`eq`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/equality-matchers#compare-using-eq-(==)) |
|
517
|
+
| `not_change` | [`change`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/change-matcher) |
|
518
|
+
| `not_raise_error` | [`raise_error`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/raise-error-matcher) |
|
519
|
+
| `not_raise_exception` | [`raise_exception`](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/raise-error-matcher) |
|
520
|
+
|
521
|
+
#### Composing Matchers
|
522
|
+
|
523
|
+
There is no equivalent of `not_to` for composed matchers when only a subset of
|
524
|
+
the values needs to be negated. The negated matchers allow this type of fine
|
525
|
+
grain comparison:
|
526
|
+
|
527
|
+
```ruby
|
528
|
+
x = [1, 2, :value]
|
529
|
+
expect(x).to contain_exactly(be_odd, be_even, not_eq(:target))
|
530
|
+
```
|
531
|
+
|
532
|
+
This also works for verifying / stubbing a message with argument constraints:
|
533
|
+
|
534
|
+
```ruby
|
535
|
+
allow(obj).to receive(:meth).with(1, 2, not_eq(5))
|
536
|
+
obj.meth(1, 2, 3)
|
537
|
+
expect(obj).to have_received(:meth).with(not_eq(2), 2, 3)
|
538
|
+
```
|
539
|
+
|
540
|
+
This is great for verifying option hashes:
|
541
|
+
|
542
|
+
```ruby
|
543
|
+
expect(obj).to have_received(:meth).with(
|
544
|
+
some_value,
|
545
|
+
excluding(:some_opt, :another_opt),
|
546
|
+
)
|
547
|
+
```
|
548
|
+
|
549
|
+
#### Compound Negated Matchers
|
550
|
+
|
551
|
+
Normally it's not possible to chain to a negative match:
|
552
|
+
|
553
|
+
```ruby
|
554
|
+
a = b = 0
|
555
|
+
expect {
|
556
|
+
a = 1
|
557
|
+
}.not_to change {
|
558
|
+
b
|
559
|
+
}.from(0).and change {
|
560
|
+
a
|
561
|
+
}.to(1)
|
562
|
+
```
|
563
|
+
|
564
|
+
Fails with:
|
565
|
+
|
566
|
+
NotImplementedError:
|
567
|
+
`expect(...).not_to matcher.and matcher` is not supported, since it creates
|
568
|
+
a bit of an ambiguity. Instead, define negated versions of whatever
|
569
|
+
matchers you wish to negate with `RSpec::Matchers.define_negated_matcher`
|
570
|
+
and use `expect(...).to matcher.and matcher`.
|
571
|
+
|
572
|
+
Per the error the negated matcher allows for the following:
|
573
|
+
|
574
|
+
```ruby
|
575
|
+
a = b = 0
|
576
|
+
expect {
|
577
|
+
a = 1
|
578
|
+
}.to change {
|
579
|
+
a
|
580
|
+
}.to(1).and not_change {
|
581
|
+
b
|
582
|
+
}.from(0)
|
583
|
+
```
|
584
|
+
|
585
|
+
Similarly, complex expectations can be set on lists:
|
586
|
+
|
587
|
+
```ruby
|
588
|
+
a = %i[red blue green]
|
589
|
+
expect(a).to include(:red).and exclude(:yellow)
|
590
|
+
expect(a).to exclude(:yellow).and include(:red)
|
591
|
+
```
|
592
|
+
|
593
|
+
### Working with Temp Files
|
594
|
+
|
595
|
+
These helpers are meant to ease the creation of temporary files to either stub
|
596
|
+
the data out or provide a location for data to be saved then verified.
|
597
|
+
|
598
|
+
In the case of file stubs, using these helpers allows you to co-locate the file
|
599
|
+
data with the specs. This makes it easy for someone to read the spec and
|
600
|
+
understand the test case; instead of having to find a fixture file and look at
|
601
|
+
its data. This also makes it easy to change the data between specs, allowing
|
602
|
+
them to focus on just what they need.
|
603
|
+
|
604
|
+
#### Usage
|
605
|
+
|
606
|
+
There are multiple ways you can use these helpers. Which method you choose
|
607
|
+
depends on how much perceived magic/syntactic sugar you want:
|
608
|
+
|
609
|
+
- Call the helpers directly on the module:
|
610
|
+
|
611
|
+
```ruby
|
612
|
+
require 'radius/spec/tempfile'
|
613
|
+
|
614
|
+
def write_hello_world(filepath)
|
615
|
+
File.write filepath, "Hello World"
|
616
|
+
end
|
617
|
+
|
618
|
+
Radius::Spec::Tempfile.using_tempfile do |pathname|
|
619
|
+
write_hello_world pathname
|
620
|
+
File.read(pathname)
|
621
|
+
# => "Hello World"
|
622
|
+
end
|
623
|
+
```
|
624
|
+
- Include the helper methods explicitly:
|
625
|
+
|
626
|
+
```ruby
|
627
|
+
require 'radius/spec/tempfile'
|
628
|
+
|
629
|
+
RSpec.describe AnyClass do
|
630
|
+
include Radius::Spec::Tempfile
|
631
|
+
|
632
|
+
it "includes the file helpers" do
|
633
|
+
using_tempfile do |pathname|
|
634
|
+
code_under_test pathname
|
635
|
+
expect(pathname.read).to eq "Any written data"
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
```
|
640
|
+
- Include the helper methods via metadata:
|
641
|
+
|
642
|
+
```ruby
|
643
|
+
RSpec.describe AnyClass do
|
644
|
+
it "includes the file helpers", :tempfile do
|
645
|
+
using_tempfile do |pathname|
|
646
|
+
code_under_test pathname
|
647
|
+
expect(pathname.read).to eq "Any written data"
|
648
|
+
end
|
649
|
+
end
|
650
|
+
end
|
651
|
+
```
|
652
|
+
|
653
|
+
When using this metadata option you do not need to explicitly require the
|
654
|
+
tempfile feature. This gem registers metadata with the RSpec configuration
|
655
|
+
when it loads and `RSpec` is defined. When the metadata is first used it
|
656
|
+
will automatically require the tempfile feature and include the helpers.
|
657
|
+
|
658
|
+
Any of following metadata will include the factory helpers:
|
659
|
+
|
660
|
+
- `:tempfile`
|
661
|
+
- `:tmpfile`
|
662
|
+
|
663
|
+
There are a few additional behaviors to note:
|
664
|
+
|
665
|
+
- Data can be stubbed by the helper through the `data` keyword arg:
|
666
|
+
|
667
|
+
```ruby
|
668
|
+
stub_data = "Any file stub data text."
|
669
|
+
Radius::Spec::Tempfile.using_tempfile(data: stub_data) do |stubpath|
|
670
|
+
File.read(stubpath)
|
671
|
+
# => "Any file stub data text."
|
672
|
+
end
|
673
|
+
```
|
674
|
+
|
675
|
+
It can even be inlined using heredocs:
|
676
|
+
|
677
|
+
```ruby
|
678
|
+
Radius::Spec::Tempfile.using_tempfile(data: <<~TEXT) do |stubpath|
|
679
|
+
Any file stub data text.
|
680
|
+
TEXT
|
681
|
+
# Yard formats heredoc args oddly
|
682
|
+
File.read(stubpath)
|
683
|
+
# => "Any file stub data text.\n"
|
684
|
+
end
|
685
|
+
```
|
686
|
+
|
687
|
+
> NOTE: That when inlining like this heredocs add an extra new line. To
|
688
|
+
> remove it use `.chomp` on the kwarg:
|
689
|
+
>
|
690
|
+
> ```ruby
|
691
|
+
> using_tempfile(data: <<~TEXT.chomp) do |pathname|
|
692
|
+
> This has no newline.
|
693
|
+
> TEXT
|
694
|
+
> # ...
|
695
|
+
> end
|
696
|
+
> ```
|
697
|
+
|
698
|
+
- Additional arguments and options are forwarded directly to
|
699
|
+
[Tempfile.create](https://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/Tempfile.html#method-c-create)
|
700
|
+
|
701
|
+
This allows you to set custom file extensions:
|
702
|
+
|
703
|
+
```ruby
|
704
|
+
Radius::Spec::Tempfile.using_tempfile(%w[custom_name .myext]) do |pathname|
|
705
|
+
pathname.extname
|
706
|
+
# => ".myext"
|
707
|
+
end
|
708
|
+
```
|
709
|
+
|
710
|
+
Or change the file encoding:
|
711
|
+
|
712
|
+
```ruby
|
713
|
+
Radius::Spec::Tempfile.using_tempfile(encoding: "ISO-8859-1", data: <<~DATA) do |pathname|
|
714
|
+
Résumé
|
715
|
+
DATA
|
716
|
+
# Yard formats heredoc args oddly
|
717
|
+
File.read(pathname)
|
718
|
+
# => "R\xE9sum\xE9\n"
|
719
|
+
end
|
720
|
+
```
|
721
|
+
|
722
|
+
### Common VCR Configuration
|
723
|
+
|
724
|
+
A project must include both [`vcr`](https://rubygems.org/gems/vcr) and
|
725
|
+
[`webmock`](https://rubygems.org/gems/webmock) to use this configuration.
|
726
|
+
Neither of those gems will be installed as dependencies of this gem. This is
|
727
|
+
intended to give projects more flexibility in choosing which additional features
|
728
|
+
they will use.
|
729
|
+
|
730
|
+
The main `radius/spec/rspec` setup will load the common VCR configuration
|
731
|
+
automatically when a spec is tagged with the `:vcr` metadata. This will
|
732
|
+
configure VCR to:
|
733
|
+
|
734
|
+
- save specs to `/spec/cassettes`
|
735
|
+
|
736
|
+
- use record mode `once` when a single spec or spec file is run
|
737
|
+
|
738
|
+
This helps ease the development of new specs without requiring any
|
739
|
+
configuration / setting changes.
|
740
|
+
|
741
|
+
- uses record mode `none` otherwise, along setting VCR to fail when unused
|
742
|
+
interactions remain in a cassette
|
743
|
+
|
744
|
+
This is intended to better alert developers to unexpected side effects of
|
745
|
+
changes as any addition or removal of a request will cause a failure.
|
746
|
+
|
747
|
+
- all `Authorization` HTTP headers are filtered by default
|
748
|
+
|
749
|
+
This is a common oversight when recording specs. Often token based
|
750
|
+
authentication is picked up by the other filtered environment settings, but
|
751
|
+
basic authentication is not. Additionally, certain types of digest
|
752
|
+
authentication may cause specs to leak state. This filtering guards all of
|
753
|
+
these cases from accidental credential leak.
|
754
|
+
|
755
|
+
- the following common sensitive, or often environment variable, settings are
|
756
|
+
filtered
|
757
|
+
|
758
|
+
Those settings which often change between developer machines, and even the
|
759
|
+
CI server, can cause for flaky specs. It may also be frustrating for
|
760
|
+
developers to have to adjust their local systems to match others just to
|
761
|
+
get a few specs to pass. This is intended to help mitigate those issues:
|
762
|
+
|
763
|
+
- `AWS_ACCESS_KEY_ID`
|
764
|
+
- `AWS_SECRET_ACCESS_KEY`
|
765
|
+
- `GOOGLE_CLIENT_ID`
|
766
|
+
- `GOOGLE_CLIENT_SECRET`
|
767
|
+
- `RADIUS_OAUTH_PROVIDER_APP_ID`
|
768
|
+
- `RADIUS_OAUTH_PROVIDER_APP_SECRET`
|
769
|
+
- `RADIUS_OAUTH_PROVIDER_URL`
|
770
|
+
|
771
|
+
- a project's local `support/vcr.rb` file will be loaded after the common
|
772
|
+
VCR configuration loads; if it's available
|
473
773
|
|
474
|
-
|
475
|
-
|
476
|
-
```
|
774
|
+
This allows projects to overwrite common settings if they need to, as well,
|
775
|
+
as add on addition settings or filtering of data.
|
477
776
|
|
478
777
|
## Development
|
479
778
|
|
data/benchmarks/bm_setup.rb
CHANGED
data/common_rubocop.yml
CHANGED
@@ -106,6 +106,10 @@ Metrics/BlockLength:
|
|
106
106
|
- 'spec/spec_helper.rb'
|
107
107
|
- 'spec/**/*_spec.rb'
|
108
108
|
- 'spec/support/model_factories.rb'
|
109
|
+
ExcludedMethods:
|
110
|
+
- 'refine'
|
111
|
+
- 'RSpec.configure'
|
112
|
+
- 'VCR.configure'
|
109
113
|
|
110
114
|
# We generally prefer to use the default line length of 80. Though sometimes
|
111
115
|
# we just need a little extra space because it makes it easier to read.
|
@@ -266,7 +270,9 @@ Style/BlockDelimiters:
|
|
266
270
|
- create!
|
267
271
|
- build
|
268
272
|
- build!
|
273
|
+
- default_scope
|
269
274
|
- each_with_object
|
275
|
+
- filter_sensitive_data
|
270
276
|
- find
|
271
277
|
- git_source
|
272
278
|
- let
|
@@ -280,6 +286,19 @@ Style/BlockDelimiters:
|
|
280
286
|
- proc
|
281
287
|
- it
|
282
288
|
|
289
|
+
# Prefer `Time` over `DateTime`.
|
290
|
+
#
|
291
|
+
# While these are not necessarily interchangeable we prefer `Time`. According
|
292
|
+
# to the Ruby docs `DateTime` is meant more for historical dates; it also does
|
293
|
+
# not consider leap seconds or summer time rules.
|
294
|
+
#
|
295
|
+
# Lastly, `DateTime` is part of the stdlib which is written in Ruby; where as
|
296
|
+
# `Time` is part of core and written in C.
|
297
|
+
#
|
298
|
+
# Configuration parameters: AllowCoercion
|
299
|
+
Style/DateTime:
|
300
|
+
Enabled: true
|
301
|
+
|
283
302
|
# The double negation idiom is a common Ruby-ism. All languages have various
|
284
303
|
# idioms and part of learning the language is learning the common idioms. Once
|
285
304
|
# learning the meaning it is not cryptic as Rubocop implies.
|
@@ -391,9 +410,10 @@ Style/MethodCalledOnDoEndBlock:
|
|
391
410
|
Style/MultilineBlockChain:
|
392
411
|
Enabled: false
|
393
412
|
|
394
|
-
# Context for this cop is too dependent.
|
395
|
-
#
|
396
|
-
# comparison is
|
413
|
+
# Context for this cop is too dependent.
|
414
|
+
#
|
415
|
+
# Often using the numeric comparison is faster. Also, depending on the context
|
416
|
+
# a numeric comparison may produce a more consistent style:
|
397
417
|
#
|
398
418
|
# # numeric comparison is more natural and consistent
|
399
419
|
# if n < 0
|
data/common_rubocop_rails.yml
CHANGED
@@ -106,6 +106,34 @@ Rails/ApplicationRecord:
|
|
106
106
|
Rails/CreateTableWithTimestamps:
|
107
107
|
Enabled: false
|
108
108
|
|
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
|
+
|
109
137
|
# We understand the trade-offs for using the through model versus a lookup
|
110
138
|
# table. As such this cop is just noise as it flags only those cases we really
|
111
139
|
# do want a lookup table.
|
@@ -122,7 +150,7 @@ Rails/HasAndBelongsToMany:
|
|
122
150
|
# For most of us `unless blank?` reads just as easily as `if present?`.
|
123
151
|
# Sometimes contextually, it can read better depending on the branch logic and
|
124
152
|
# surrounding context. As `if present?` requires an additional negation and
|
125
|
-
# method call it is technically slower. In the general case the perf
|
153
|
+
# method call it is technically slower. In the general case the perf difference
|
126
154
|
# isn't much but in some cases it matters. Thus, we are not enforcing changing
|
127
155
|
# `unless blank?` to `if present?` and are leaving it up to the context to
|
128
156
|
# decide which is a better fit.
|
@@ -144,6 +172,37 @@ Rails/Present:
|
|
144
172
|
Rails/ReadWriteAttribute:
|
145
173
|
Enabled: false
|
146
174
|
|
175
|
+
# This ensures we do not ignore potential validation issues in the code. Doing
|
176
|
+
# so can lead to strange and surprising bugs where records are expected to
|
177
|
+
# be created, or be modified, but are not.
|
178
|
+
#
|
179
|
+
# # If author is a new record the book may not be created since the FK is
|
180
|
+
# # invalid. Perhaps omitting other fields, maybe new required fields, is
|
181
|
+
# # an oversight in the book creation as well.
|
182
|
+
# author.save
|
183
|
+
# Book.create(author: author)
|
184
|
+
#
|
185
|
+
# Or side effects are expected to occur but they do not:
|
186
|
+
#
|
187
|
+
# # This is a condensed default Rails scaffold controller for `destroy`.
|
188
|
+
# #
|
189
|
+
# # Once a `has_many` or `has_one` associations is added which specifies
|
190
|
+
# # `dependent: :restrict_with_error` this no longer behaves as expected.
|
191
|
+
# # Given such associations are often added much later in time errors in
|
192
|
+
# # this action are an all to common oversight in Rails.
|
193
|
+
# def destroy
|
194
|
+
# @book.destroy
|
195
|
+
# respond_to do |format|
|
196
|
+
# format.html do
|
197
|
+
# redirect_to books_url, notice: 'Book was successfully destroyed.'
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# Configuration parameters: AllowImplicitReturn, AllowedReceivers.
|
203
|
+
Rails/SaveBang:
|
204
|
+
Enabled: true
|
205
|
+
|
147
206
|
# According to the Rails docs while the following methods skip validations they
|
148
207
|
# only update the specified (single) attribute reducing risks. We'd rather not
|
149
208
|
# warn for those cases:
|
@@ -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
|
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
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
VCR.configure do |config|
|
7
|
+
config.cassette_library_dir = "spec/cassettes"
|
8
|
+
config.hook_into :webmock
|
9
|
+
config.configure_rspec_metadata!
|
10
|
+
config.ignore_localhost = true
|
11
|
+
|
12
|
+
record_mode = case
|
13
|
+
when RSpec.configuration.files_to_run.one?
|
14
|
+
# When developing new features we often run new specs in
|
15
|
+
# isolation as we write the code. This is the time to allow
|
16
|
+
# creating the cassettes.
|
17
|
+
:once
|
18
|
+
when ENV['CI']
|
19
|
+
# Never let CI record
|
20
|
+
:none
|
21
|
+
else
|
22
|
+
# Default to blocking new requests to catch issues
|
23
|
+
:none
|
24
|
+
end
|
25
|
+
config.default_cassette_options = {
|
26
|
+
record: record_mode,
|
27
|
+
|
28
|
+
# Required for working proxy
|
29
|
+
update_content_length_header: true,
|
30
|
+
|
31
|
+
# Raise errors when recorded cassettes no longer match interactions
|
32
|
+
allow_unused_http_interactions: false,
|
33
|
+
}
|
34
|
+
|
35
|
+
# Filter out common sensitive or environment specific data
|
36
|
+
%w[
|
37
|
+
AWS_ACCESS_KEY_ID
|
38
|
+
AWS_SECRET_ACCESS_KEY
|
39
|
+
GOOGLE_CLIENT_ID
|
40
|
+
GOOGLE_CLIENT_SECRET
|
41
|
+
RADIUS_OAUTH_PROVIDER_APP_ID
|
42
|
+
RADIUS_OAUTH_PROVIDER_APP_SECRET
|
43
|
+
RADIUS_OAUTH_PROVIDER_URL
|
44
|
+
].each do |secret|
|
45
|
+
config.filter_sensitive_data("<#{secret}>") { ENV[secret] }
|
46
|
+
|
47
|
+
config.filter_sensitive_data("<#{secret}_FORM>") {
|
48
|
+
URI.encode_www_form_component(ENV[secret]) if ENV[secret]
|
49
|
+
}
|
50
|
+
|
51
|
+
config.filter_sensitive_data("<#{secret}_URI>") {
|
52
|
+
ERB::Util.url_encode(ENV[secret]) if ENV[secret]
|
53
|
+
}
|
54
|
+
|
55
|
+
config.filter_sensitive_data('<AUTHORIZATION_HEADER>') { |interaction|
|
56
|
+
interaction.request.headers['Authorization']&.first
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
RSpec.configure do |config|
|
62
|
+
{
|
63
|
+
vcr_record: :once,
|
64
|
+
vcr_record_new: :new_episodes,
|
65
|
+
}.each do |tag, record_mode|
|
66
|
+
config.define_derived_metadata(tag) do |metadata|
|
67
|
+
case metadata[:vcr]
|
68
|
+
when nil, true
|
69
|
+
metadata[:vcr] = { record: record_mode }
|
70
|
+
when Hash
|
71
|
+
metadata[:vcr][:record] = record_mode
|
72
|
+
else
|
73
|
+
raise "Unknown VCR metadata value: #{metadata[:vcr].inspect}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
config.define_derived_metadata(:focus) do |metadata|
|
79
|
+
# VCR is flagged as falsey
|
80
|
+
next if metadata.key?(:vcr) && !metadata[:vcr]
|
81
|
+
|
82
|
+
case metadata[:vcr]
|
83
|
+
when nil, true
|
84
|
+
metadata[:vcr] = { record: :once }
|
85
|
+
when Hash
|
86
|
+
metadata[:vcr][:record] ||= :once
|
87
|
+
else
|
88
|
+
raise "Unknown VCR metadata value: #{metadata[:vcr].inspect}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Try to any custom VCR config for the app
|
94
|
+
# rubocop:disable Lint/HandleExceptions
|
95
|
+
begin
|
96
|
+
require 'support/vcr'
|
97
|
+
rescue LoadError
|
98
|
+
# Ignore as this is an optional convenience feature
|
99
|
+
end
|
100
|
+
# rubocop:enable Lint/HandleExceptions
|
data/lib/radius/spec/version.rb
CHANGED
data/radius-spec.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.required_ruby_version = ">= 2.5"
|
32
32
|
|
33
33
|
spec.add_runtime_dependency "rspec", "~> 3.7"
|
34
|
-
spec.add_runtime_dependency "rubocop", "~> 0.
|
34
|
+
spec.add_runtime_dependency "rubocop", "~> 0.59.1"
|
35
35
|
|
36
36
|
spec.add_development_dependency "bundler", "~> 1.16"
|
37
37
|
spec.add_development_dependency "rake", "~> 12.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radius-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radius Networks
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-09-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
34
|
+
version: 0.59.1
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
41
|
+
version: 0.59.1
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,7 +109,6 @@ files:
|
|
109
109
|
- bin/rspec
|
110
110
|
- bin/rubocop
|
111
111
|
- bin/setup
|
112
|
-
- bin/travis
|
113
112
|
- bin/yard
|
114
113
|
- common_rubocop.yml
|
115
114
|
- common_rubocop_rails.yml
|
@@ -117,6 +116,9 @@ files:
|
|
117
116
|
- lib/radius/spec/model_factory.rb
|
118
117
|
- lib/radius/spec/rails.rb
|
119
118
|
- lib/radius/spec/rspec.rb
|
119
|
+
- lib/radius/spec/rspec/negated_matchers.rb
|
120
|
+
- lib/radius/spec/tempfile.rb
|
121
|
+
- lib/radius/spec/vcr.rb
|
120
122
|
- lib/radius/spec/version.rb
|
121
123
|
- radius-spec.gemspec
|
122
124
|
homepage: https://github.com/RadiusNetworks/radius-spec
|
@@ -124,8 +126,8 @@ licenses:
|
|
124
126
|
- Apache-2.0
|
125
127
|
metadata:
|
126
128
|
bug_tracker_uri: https://github.com/RadiusNetworks/radius-spec/issues
|
127
|
-
changelog_uri: https://github.com/RadiusNetworks/radius-spec/blob/v0.
|
128
|
-
source_code_uri: https://github.com/RadiusNetworks/radius-spec/tree/v0.
|
129
|
+
changelog_uri: https://github.com/RadiusNetworks/radius-spec/blob/v0.5.0/CHANGELOG.md
|
130
|
+
source_code_uri: https://github.com/RadiusNetworks/radius-spec/tree/v0.5.0
|
129
131
|
post_install_message:
|
130
132
|
rdoc_options: []
|
131
133
|
require_paths:
|
data/bin/travis
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'travis' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("travis", "travis")
|