sinclair 1.6.5 → 1.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/.circleci/config.yml +2 -2
- data/Dockerfile +2 -2
- data/README.md +3 -1
- data/config/check_specs.yml +3 -0
- data/config/yardstick.yml +7 -1
- data/lib/sinclair/config.rb +46 -0
- data/lib/sinclair/config_class.rb +15 -0
- data/lib/sinclair/configurable.rb +8 -0
- data/lib/sinclair/matchers/add_class_method.rb +16 -13
- data/lib/sinclair/matchers/add_class_method_to.rb +9 -23
- data/lib/sinclair/matchers/add_instance_method.rb +16 -18
- data/lib/sinclair/matchers/add_instance_method_to.rb +12 -16
- data/lib/sinclair/matchers/add_method.rb +39 -30
- data/lib/sinclair/matchers/add_method_to.rb +4 -56
- data/lib/sinclair/matchers/base.rb +45 -0
- data/lib/sinclair/matchers/change_class_method.rb +42 -0
- data/lib/sinclair/matchers/change_class_method_on.rb +64 -0
- data/lib/sinclair/matchers/change_instance_method.rb +42 -0
- data/lib/sinclair/matchers/change_instance_method_on.rb +98 -0
- data/lib/sinclair/matchers/change_method_on.rb +25 -0
- data/lib/sinclair/matchers/method_to.rb +82 -0
- data/lib/sinclair/matchers.rb +38 -30
- data/lib/sinclair/options/class_methods.rb +95 -0
- data/lib/sinclair/options.rb +10 -60
- data/lib/sinclair/version.rb +1 -1
- data/sinclair.gemspec +12 -12
- data/spec/integration/readme/my_class_spec.rb +1 -1
- data/spec/integration/yard/sinclair/config_spec.rb +27 -0
- data/spec/integration/yard/sinclair/options_parser_spec.rb +9 -0
- data/spec/lib/sinclair/config_class_spec.rb +1 -33
- data/spec/lib/sinclair/config_spec.rb +71 -0
- data/spec/lib/sinclair/matchers/add_class_method_to_spec.rb +40 -16
- data/spec/lib/sinclair/matchers/add_instance_method_to_spec.rb +36 -12
- data/spec/lib/sinclair/matchers/change_class_method_on_spec.rb +138 -0
- data/spec/lib/sinclair/matchers/change_class_method_spec.rb +38 -0
- data/spec/lib/sinclair/matchers/change_instance_method_on_spec.rb +149 -0
- data/spec/lib/sinclair/matchers/change_instance_method_spec.rb +38 -0
- data/spec/lib/sinclair/matchers_spec.rb +30 -0
- data/spec/lib/sinclair/options/class_methods_spec.rb +255 -0
- data/spec/lib/sinclair/options_spec.rb +28 -237
- data/spec/support/models/builder_options.rb +7 -0
- data/spec/support/models/login_configurable.rb +7 -0
- data/spec/support/models/open_options.rb +7 -0
- data/spec/support/shared_examples/config.rb +48 -0
- metadata +43 -28
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Checks if a class method was changed
|
9
|
+
# by the call of a block
|
10
|
+
#
|
11
|
+
# This is used with a RSpec DSL method
|
12
|
+
# change_class_method(method_name).on(class_object)
|
13
|
+
class ChangeClassMethodOn < ChangeMethodOn
|
14
|
+
# @param [Class] klass
|
15
|
+
# Class where the class method should be added to
|
16
|
+
#
|
17
|
+
# @param method_name [SYmbol,String] method name
|
18
|
+
def initialize(target, method_name)
|
19
|
+
@klass = target
|
20
|
+
super(method_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return expectaton description
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
def description
|
27
|
+
"change class method '#{method_name}' on #{klass}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns message on expectation failure
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
def failure_message_for_should
|
34
|
+
"expected class method '#{method_name}' to be changed on #{klass} but " \
|
35
|
+
"#{initial_state ? "it didn't" : "it didn't exist"}"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns message on expectation failure for negative expectation
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
def failure_message_for_should_not
|
42
|
+
"expected class method '#{method_name}' not to be changed on #{klass} but it was"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Checks if class has instance method defined
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
def state
|
51
|
+
klass.methods(false).include?(method_name.to_sym) \
|
52
|
+
&& klass.method(method_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Raises when block was not given
|
56
|
+
#
|
57
|
+
# @raise SyntaxError
|
58
|
+
def raise_block_syntax_error
|
59
|
+
raise SyntaxError, 'Block not received by the `change_class_method_on` matcher. ' \
|
60
|
+
'Perhaps you want to use `{ ... }` instead of do/end?'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# AddInstanceMethod is able to build an instance of
|
9
|
+
# {Sinclair::Matchers::ChangeInstanceMethodOn}
|
10
|
+
class ChangeInstanceMethod < Base
|
11
|
+
include AddMethod
|
12
|
+
|
13
|
+
# @api public
|
14
|
+
#
|
15
|
+
# Builds final matcher
|
16
|
+
#
|
17
|
+
# @return [Sinclair::Matchers::ChangeInstanceMethodOn]
|
18
|
+
alias on to
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @private
|
23
|
+
#
|
24
|
+
# Error description on wrong usage
|
25
|
+
#
|
26
|
+
# @return String
|
27
|
+
def matcher_error
|
28
|
+
'You should specify which instance the method is being changed on' \
|
29
|
+
"change_method(:#{method_name}).on(instance)"
|
30
|
+
end
|
31
|
+
|
32
|
+
# @private
|
33
|
+
#
|
34
|
+
# Class of the real matcher
|
35
|
+
#
|
36
|
+
# @return [Class<Sinclair::Matchers::Base>]
|
37
|
+
def add_method_to_class
|
38
|
+
ChangeInstanceMethodOn
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Checks if a method was changed
|
9
|
+
# by the call of a block
|
10
|
+
#
|
11
|
+
# This is used with a RSpec DSL method
|
12
|
+
# change_method(method_name).on(class_object)
|
13
|
+
class ChangeInstanceMethodOn < ChangeMethodOn
|
14
|
+
# @overload initialize(klass, method_name)
|
15
|
+
# @param [Class] klass
|
16
|
+
# class where the method should be added to
|
17
|
+
#
|
18
|
+
# @overload initialize(instance, method_name)
|
19
|
+
# @param [Object] instance
|
20
|
+
# instance of the class where the method should be added to
|
21
|
+
#
|
22
|
+
# @param method_name [Symbol,String] method name
|
23
|
+
def initialize(target, method_name)
|
24
|
+
if target.is_a?(Class)
|
25
|
+
@klass = target
|
26
|
+
else
|
27
|
+
@instance = target
|
28
|
+
end
|
29
|
+
|
30
|
+
super(method_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returnst expectaton description
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def description
|
37
|
+
"change method '#{method_name}' on #{klass} instances"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns message on expectation failure
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
def failure_message_for_should
|
44
|
+
"expected '#{method_name}' to be changed on #{klass} but " \
|
45
|
+
"#{initial_state ? "it didn't" : "it didn't exist"}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns message on expectation failure for negative expectation
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
def failure_message_for_should_not
|
52
|
+
"expected '#{method_name}' not to be changed on #{klass} but it was"
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
# @method instance
|
58
|
+
# @api private
|
59
|
+
# @private
|
60
|
+
#
|
61
|
+
# Instance of the class where the method should be added
|
62
|
+
#
|
63
|
+
# @return [Object]
|
64
|
+
attr_reader :instance
|
65
|
+
|
66
|
+
# @private
|
67
|
+
#
|
68
|
+
# Class to be analised
|
69
|
+
#
|
70
|
+
# @return [Class]
|
71
|
+
def klass
|
72
|
+
@klass ||= instance.class
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# @private
|
78
|
+
#
|
79
|
+
# Checks if class has instance method defined
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
def state
|
83
|
+
klass.method_defined?(method_name) &&
|
84
|
+
klass.instance_method(method_name)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @private
|
88
|
+
#
|
89
|
+
# Raises when block was not given
|
90
|
+
#
|
91
|
+
# @raise SyntaxError
|
92
|
+
def raise_block_syntax_error
|
93
|
+
raise SyntaxError, 'Block not received by the `change_instance_method_on` matcher. ' \
|
94
|
+
'Perhaps you want to use `{ ... }` instead of do/end?'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
# @abstract
|
8
|
+
#
|
9
|
+
# Base class for change_method_on matcher
|
10
|
+
class ChangeMethodOn < Base
|
11
|
+
include MethodTo
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @private
|
16
|
+
#
|
17
|
+
# Checks if a method was changed
|
18
|
+
#
|
19
|
+
# @return Boolean
|
20
|
+
def check
|
21
|
+
initial_state && initial_state != final_state
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
# Common methods on final matchers
|
8
|
+
module MethodTo
|
9
|
+
# Used for other versions of rspec
|
10
|
+
#
|
11
|
+
# Some versions call failure_message, others
|
12
|
+
# call failure_message_for_should
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
def failure_message
|
16
|
+
failure_message_for_should
|
17
|
+
end
|
18
|
+
|
19
|
+
# Used for other versions of rspec
|
20
|
+
#
|
21
|
+
# Some versions call failure_message_when_negated, others
|
22
|
+
# call failure_message_for_should_not
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def failure_message_when_negated
|
26
|
+
failure_message_for_should_not
|
27
|
+
end
|
28
|
+
|
29
|
+
# Checks if expectation is true or not
|
30
|
+
#
|
31
|
+
# @return [Boolean] expectation check
|
32
|
+
def matches?(event_proc)
|
33
|
+
return false unless event_proc.is_a?(Proc)
|
34
|
+
|
35
|
+
raise_block_syntax_error if block_given?
|
36
|
+
perform_change(event_proc)
|
37
|
+
check
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
# @method klass
|
43
|
+
# @api private
|
44
|
+
# @private
|
45
|
+
#
|
46
|
+
# Class where class method should be added to
|
47
|
+
#
|
48
|
+
# @return [Class]
|
49
|
+
attr_reader :klass
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @method initial_state
|
54
|
+
# @api private
|
55
|
+
# @private
|
56
|
+
#
|
57
|
+
# State before running the block
|
58
|
+
#
|
59
|
+
# @return [Object]
|
60
|
+
|
61
|
+
# @method final_state
|
62
|
+
# @api private
|
63
|
+
# @private
|
64
|
+
#
|
65
|
+
# State after running the block
|
66
|
+
#
|
67
|
+
# @return [Object]
|
68
|
+
attr_reader :initial_state, :final_state
|
69
|
+
|
70
|
+
# @private
|
71
|
+
#
|
72
|
+
# Call block to check if it aded a method or not
|
73
|
+
#
|
74
|
+
# @return [Boolan]
|
75
|
+
def perform_change(event_proc)
|
76
|
+
@initial_state = state
|
77
|
+
event_proc.call
|
78
|
+
@final_state = state
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/sinclair/matchers.rb
CHANGED
@@ -7,33 +7,21 @@ class Sinclair
|
|
7
7
|
# Matchers module will have the DSL to be included in RSpec in order to have
|
8
8
|
# access to the matchers
|
9
9
|
#
|
10
|
-
# @example
|
11
|
-
# RSpec.configure do |config|
|
12
|
-
# config.include Sinclair::Matchers
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# class MyModel
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# RSpec.describe 'my test' do
|
19
|
-
# let(:klass) { Class.new(MyModel) }
|
20
|
-
# let(:builder) { Sinclair.new(klass) }
|
21
|
-
#
|
22
|
-
# before do
|
23
|
-
# builder.add_method(:class_name, 'self.class.name')
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# it do
|
27
|
-
# expect { builder.build }.to add_method(:class_name).to(klass)
|
28
|
-
# end
|
29
|
-
# end
|
10
|
+
# @example (see Sinclair::Matchers::AddMethod#to)
|
30
11
|
module Matchers
|
31
|
-
autoload :
|
32
|
-
autoload :AddInstanceMethod,
|
33
|
-
autoload :AddClassMethod,
|
34
|
-
autoload :
|
35
|
-
autoload :
|
36
|
-
autoload :
|
12
|
+
autoload :Base, 'sinclair/matchers/base'
|
13
|
+
autoload :AddInstanceMethod, 'sinclair/matchers/add_instance_method'
|
14
|
+
autoload :AddClassMethod, 'sinclair/matchers/add_class_method'
|
15
|
+
autoload :AddMethod, 'sinclair/matchers/add_method'
|
16
|
+
autoload :AddMethodTo, 'sinclair/matchers/add_method_to'
|
17
|
+
autoload :AddInstanceMethodTo, 'sinclair/matchers/add_instance_method_to'
|
18
|
+
autoload :AddClassMethodTo, 'sinclair/matchers/add_class_method_to'
|
19
|
+
autoload :ChangeClassMethod, 'sinclair/matchers/change_class_method'
|
20
|
+
autoload :ChangeInstanceMethod, 'sinclair/matchers/change_instance_method'
|
21
|
+
autoload :ChangeMethodOn, 'sinclair/matchers/change_method_on'
|
22
|
+
autoload :ChangeClassMethodOn, 'sinclair/matchers/change_class_method_on'
|
23
|
+
autoload :ChangeInstanceMethodOn, 'sinclair/matchers/change_instance_method_on'
|
24
|
+
autoload :MethodTo, 'sinclair/matchers/method_to'
|
37
25
|
|
38
26
|
# DSL to AddInstanceMethod
|
39
27
|
#
|
@@ -41,8 +29,8 @@ class Sinclair
|
|
41
29
|
# @example (see Sinclair::Matchers::AddInstanceMethod#to)
|
42
30
|
#
|
43
31
|
# @return [AddInstanceMethod] RSpec Matcher
|
44
|
-
def add_method(
|
45
|
-
Sinclair::Matchers::AddInstanceMethod.new(
|
32
|
+
def add_method(method_name)
|
33
|
+
Sinclair::Matchers::AddInstanceMethod.new(method_name)
|
46
34
|
end
|
47
35
|
|
48
36
|
# DSL to AddClassMethod
|
@@ -51,8 +39,28 @@ class Sinclair
|
|
51
39
|
# @example (see Sinclair::Matchers::AddClassMethod#to)
|
52
40
|
#
|
53
41
|
# @return [AddClassMethod] RSpec Matcher
|
54
|
-
def add_class_method(
|
55
|
-
Sinclair::Matchers::AddClassMethod.new(
|
42
|
+
def add_class_method(method_name)
|
43
|
+
Sinclair::Matchers::AddClassMethod.new(method_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
# DSL to ChangeInstanceMethod
|
47
|
+
#
|
48
|
+
# @example (see Sinclair::Matchers)
|
49
|
+
# @example (see Sinclair::Matchers::ChangeInstanceMethod#to)
|
50
|
+
#
|
51
|
+
# @return [ChangeInstanceMethod] RSpec Matcher
|
52
|
+
def change_method(method_name)
|
53
|
+
Sinclair::Matchers::ChangeInstanceMethod.new(method_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
# DSL to ChangeClassMethod
|
57
|
+
#
|
58
|
+
# @example (see Sinclair::Matchers)
|
59
|
+
# @example (see Sinclair::Matchers::ChangeClassMethod#to)
|
60
|
+
#
|
61
|
+
# @return [ChangeClassMethod] RSpec Matcher
|
62
|
+
def change_class_method(method_name)
|
63
|
+
Sinclair::Matchers::ChangeClassMethod.new(method_name)
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
class Sinclair
|
6
|
+
class Options
|
7
|
+
# Class Methods for {Sinclai::Options}
|
8
|
+
module ClassMethods
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
# returns invalid options
|
12
|
+
#
|
13
|
+
# @return [Array<Symbol>]
|
14
|
+
def invalid_options_in(names)
|
15
|
+
names.map(&:to_sym) - allowed_options.to_a
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# Allow new option
|
21
|
+
#
|
22
|
+
# This does not create the method
|
23
|
+
#
|
24
|
+
# @param name [String,Symbol] options to be allowed
|
25
|
+
#
|
26
|
+
# @return [Set<Symbol>]
|
27
|
+
def allow(name)
|
28
|
+
allowed_options << name.to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
# @private
|
33
|
+
#
|
34
|
+
# Options allowed when initializing options
|
35
|
+
#
|
36
|
+
# @return [Set<Symbol>]
|
37
|
+
def allowed_options
|
38
|
+
@allowed_options ||= superclass.try(:allowed_options).dup || Set.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
#
|
43
|
+
# checks if class skips initialization validation
|
44
|
+
#
|
45
|
+
# @return [TrueClass,FalseClass]
|
46
|
+
def skip_validation?
|
47
|
+
@skip_validation ||= superclass.try(:skip_validation?) || false
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api public
|
51
|
+
#
|
52
|
+
# Add available options
|
53
|
+
#
|
54
|
+
# @example (see Options)
|
55
|
+
#
|
56
|
+
# @return (see Sinclair#build)
|
57
|
+
#
|
58
|
+
# @overload with_options(*options)
|
59
|
+
# @param options [Array<Symbol>] list of accepted
|
60
|
+
# options
|
61
|
+
# @overload with_options(*options, **defaults)
|
62
|
+
# @param options [Array<Symbol>] list of accepted
|
63
|
+
# options
|
64
|
+
# @param defaults [Hash<Symbol,Object>] default options
|
65
|
+
# hash
|
66
|
+
def with_options(*options)
|
67
|
+
Builder.new(self, *options).build
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api public
|
71
|
+
#
|
72
|
+
# Changes class to skip attributes validation
|
73
|
+
#
|
74
|
+
# when initializing options, options
|
75
|
+
# will accept any arguments when validation
|
76
|
+
# is skipped
|
77
|
+
#
|
78
|
+
# @return [TrueClass]
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# class BuilderOptions < Sinclair::Options
|
82
|
+
# with_options :name
|
83
|
+
#
|
84
|
+
# skip_validation
|
85
|
+
# end
|
86
|
+
# options = BuilderOptions.new(name: 'Joe', age: 10)
|
87
|
+
#
|
88
|
+
# options.name # returns 'Joe'
|
89
|
+
# options.try(:age) # returns nil
|
90
|
+
def skip_validation
|
91
|
+
@skip_validation = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/sinclair/options.rb
CHANGED
@@ -20,64 +20,10 @@ class Sinclair
|
|
20
20
|
# options.port # returns 8080
|
21
21
|
# options.protocol # returns 'https'
|
22
22
|
class Options
|
23
|
-
autoload :Builder,
|
23
|
+
autoload :Builder, 'sinclair/options/builder'
|
24
|
+
autoload :ClassMethods, 'sinclair/options/class_methods'
|
24
25
|
|
25
|
-
|
26
|
-
# @api private
|
27
|
-
#
|
28
|
-
# returns invalid options
|
29
|
-
#
|
30
|
-
# @return [Array<Symbol>]
|
31
|
-
def invalid_options_in(names)
|
32
|
-
names.map(&:to_sym) - allowed_options.to_a
|
33
|
-
end
|
34
|
-
|
35
|
-
# @api private
|
36
|
-
#
|
37
|
-
# Allow new option
|
38
|
-
#
|
39
|
-
# This does not create the method
|
40
|
-
#
|
41
|
-
# @param name [String,Symbol] options to be allowed
|
42
|
-
#
|
43
|
-
# @return [Set<Symbol>]
|
44
|
-
def allow(name)
|
45
|
-
allowed_options << name.to_sym
|
46
|
-
end
|
47
|
-
|
48
|
-
# @api private
|
49
|
-
# @private
|
50
|
-
#
|
51
|
-
# Options allowed when initializing options
|
52
|
-
#
|
53
|
-
# @return [Set<Symbol>]
|
54
|
-
def allowed_options
|
55
|
-
@allowed_options ||= superclass.try(:allowed_options).dup || Set.new
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# @api public
|
61
|
-
# @!visibility public
|
62
|
-
#
|
63
|
-
# Add available options
|
64
|
-
#
|
65
|
-
# @example (see Options)
|
66
|
-
#
|
67
|
-
# @return (see Sinclair#build)
|
68
|
-
#
|
69
|
-
# @overload with_options(*options)
|
70
|
-
# @param options [Array<Symbol>] list of accepted
|
71
|
-
# options
|
72
|
-
# @overload with_options(*options, **defaults)
|
73
|
-
# @param options [Array<Symbol>] list of accepted
|
74
|
-
# options
|
75
|
-
# @param defaults [Hash<Symbol,Object>] default options
|
76
|
-
# hash
|
77
|
-
def with_options(*options)
|
78
|
-
Builder.new(self, *options).build
|
79
|
-
end
|
80
|
-
end
|
26
|
+
extend ClassMethods
|
81
27
|
|
82
28
|
# @param options [Hash] hash with options (see {.options}, {.with_options})
|
83
29
|
# @example (see Options)
|
@@ -108,7 +54,7 @@ class Sinclair
|
|
108
54
|
# # protocol: 'https'
|
109
55
|
# # }
|
110
56
|
def to_h
|
111
|
-
|
57
|
+
allowed_options.inject({}) do |hash, option|
|
112
58
|
hash.merge(option => public_send(option))
|
113
59
|
end
|
114
60
|
end
|
@@ -121,13 +67,15 @@ class Sinclair
|
|
121
67
|
def ==(other)
|
122
68
|
return false unless self.class == other.class
|
123
69
|
|
124
|
-
|
70
|
+
allowed_options.all? do |name|
|
125
71
|
public_send(name) == other.public_send(name)
|
126
72
|
end
|
127
73
|
end
|
128
74
|
|
129
75
|
private
|
130
76
|
|
77
|
+
delegate :allowed_options, :skip_validation?, :invalid_options_in, to: :class
|
78
|
+
|
131
79
|
# @private
|
132
80
|
# @api private
|
133
81
|
#
|
@@ -137,7 +85,9 @@ class Sinclair
|
|
137
85
|
#
|
138
86
|
# @return [NilClass]
|
139
87
|
def check_options(options)
|
140
|
-
|
88
|
+
return if skip_validation?
|
89
|
+
|
90
|
+
invalid_keys = invalid_options_in(options.keys)
|
141
91
|
|
142
92
|
return if invalid_keys.empty?
|
143
93
|
|
data/lib/sinclair/version.rb
CHANGED
data/sinclair.gemspec
CHANGED
@@ -21,20 +21,20 @@ Gem::Specification.new do |gem|
|
|
21
21
|
|
22
22
|
gem.add_runtime_dependency 'activesupport', '~> 5.2.0'
|
23
23
|
|
24
|
-
gem.add_development_dependency 'bundler', '
|
25
|
-
gem.add_development_dependency 'pry', '0.
|
26
|
-
gem.add_development_dependency 'pry-nav', '0.
|
24
|
+
gem.add_development_dependency 'bundler', '2.3.20'
|
25
|
+
gem.add_development_dependency 'pry', '0.14.1'
|
26
|
+
gem.add_development_dependency 'pry-nav', '1.0.0'
|
27
27
|
gem.add_development_dependency 'rake', '13.0.1'
|
28
|
-
gem.add_development_dependency 'reek', '
|
29
|
-
gem.add_development_dependency 'rspec', '3.
|
30
|
-
gem.add_development_dependency 'rspec-core', '3.
|
31
|
-
gem.add_development_dependency 'rspec-expectations', '3.
|
32
|
-
gem.add_development_dependency 'rspec-mocks', '3.
|
33
|
-
gem.add_development_dependency 'rspec-support', '3.
|
28
|
+
gem.add_development_dependency 'reek', '6.0.3'
|
29
|
+
gem.add_development_dependency 'rspec', '3.11.0'
|
30
|
+
gem.add_development_dependency 'rspec-core', '3.11.0'
|
31
|
+
gem.add_development_dependency 'rspec-expectations', '3.11.0'
|
32
|
+
gem.add_development_dependency 'rspec-mocks', '3.11.1'
|
33
|
+
gem.add_development_dependency 'rspec-support', '3.11.0'
|
34
34
|
gem.add_development_dependency 'rubocop', '0.80.1'
|
35
35
|
gem.add_development_dependency 'rubocop-rspec', '1.38.1'
|
36
|
-
gem.add_development_dependency 'rubycritic', '4.
|
37
|
-
gem.add_development_dependency 'simplecov', '0.
|
38
|
-
gem.add_development_dependency 'yard', '0.9.
|
36
|
+
gem.add_development_dependency 'rubycritic', '4.7.0'
|
37
|
+
gem.add_development_dependency 'simplecov', '0.21.2'
|
38
|
+
gem.add_development_dependency 'yard', '0.9.27'
|
39
39
|
gem.add_development_dependency 'yardstick', '0.9.9'
|
40
40
|
end
|
@@ -24,5 +24,32 @@ describe Sinclair::Config do
|
|
24
24
|
.to eq('{"password":null,"username":"bob"}')
|
25
25
|
end
|
26
26
|
end
|
27
|
+
|
28
|
+
describe '#options' do
|
29
|
+
subject(:config) { configurable.config }
|
30
|
+
|
31
|
+
let(:configurable) { LoginConfigurable }
|
32
|
+
|
33
|
+
before do
|
34
|
+
LoginConfigurable.configure do |conf|
|
35
|
+
conf.username :some_username
|
36
|
+
conf.password :some_password
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns options with correct values' do
|
41
|
+
expect(config.options.username).to eq(:some_username)
|
42
|
+
expect(config.options.password).to eq(:some_password)
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when merging with given attributes' do
|
46
|
+
subject(:options) { config.options(password: :correct_password) }
|
47
|
+
|
48
|
+
it 'returns options with custom values' do
|
49
|
+
expect(options.username).to eq(:some_username)
|
50
|
+
expect(options.password).to eq(:correct_password)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
27
54
|
end
|
28
55
|
end
|