Module: MiniSpec::Utils

Extended by:
Utils
Included in:
ExceptionInspector, Mocks::Validations, ThrowInspector, Utils
Defined in:
lib/minispec/utils.rb,
lib/minispec/utils/raise.rb,
lib/minispec/utils/throw.rb,
lib/minispec/utils/pretty_print.rb

Instance Method Summary collapse

Instance Method Details

#any_match?(label, matchers) ⇒ Boolean

checks whether given label matches any matcher. even if label matched, it will return ‘false` if label matches some rejector.

Parameters:

  • label
  • matchers

    an ‘Array` of matchers and rejectors. matchers contained as hashes, rejectors as arrays.

Returns:

  • (Boolean)

    ‘true` or `false`



100
101
102
103
104
105
106
107
108
# File 'lib/minispec/utils.rb', line 100

def any_match? label, matchers
  reject, select = matchers.partition {|m| m.is_a?(Hash)}

  rejected = rejected?(label, reject)
  if select.any?
    return select.find {|x| (x == :*) || match?(label, x)} && !rejected
  end
  !rejected
end

#array_elements_map(array) ⇒ Object



78
79
80
81
# File 'lib/minispec/utils.rb', line 78

def array_elements_map array
  # borrowed from thoughtbot/shoulda
  array.inject({}) {|h,e| h[e] ||= array.select { |i| i == e }.size; h}
end

#catch_symbol(expected_symbol, &block) ⇒ Object

calling given block and catching thrown symbol, if any.

Parameters:

  • expected_symbol
  • &block (Proc)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/minispec/utils/throw.rb', line 33

def catch_symbol expected_symbol, &block
  thrown_symbol, thrown_value = nil
  begin
    if expected_symbol
      thrown_value = catch :__ms__nothing_thrown do
        catch expected_symbol do
          block.call
          throw :__ms__nothing_thrown, :__ms__nothing_thrown
        end
      end
      thrown_symbol = expected_symbol unless thrown_value == :__ms__nothing_thrown
    else
      block.call
    end
  rescue => e
    raise(e) unless thrown_symbol = extract_thrown_symbol(e)
  end
  [thrown_symbol, thrown_value]
end

#exception_raised?(subject, context, *args) ⇒ ExceptionError

checks whether given object is a exception of given class(if any), and/or match given String/Regexp(if any)

if no args given any raised exception accepted. if a class given it checks whether raised exception is of given type. if a string or regexp given it checks whether raised message matches it.

Parameters:

  • subject

    potentially a Exception instance

  • context (Hash)
  • *args (Array)

    actual expectations. can be a Class, String or Regexp

Returns:

  • (ExceptionError)

    if not raised as expected

    true

    if raised an exception that meets expectations



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/minispec/utils/raise.rb', line 21

def exception_raised? subject, context, *args
  if context[:right_proc]
    args.any? && raise(ArgumentError, 'Both arguments and block given. Please use either one.')
    return MiniSpec::ExceptionInspector.raised_as_expected_by_proc?(subject, context)
  end

  type, match = nil
  args.each { |a| a.is_a?(Class) ? type = a : match = a }
  regexp = match.is_a?(Regexp) ? match : /^#{Regexp.escape(match.to_s)}\z/

  context = {negation: context[:negation]} # it is critical to not alter received context
  if context[:is_a_exception]         = subject.is_a?(Exception)
    context[:valid_exception_type]    = type  ? (subject.class == type)  : nil
    context[:valid_exception_message] = match ? (subject.to_s =~ regexp) : nil
  end

  MiniSpec::ExceptionInspector.raised_as_expected?(subject, type, match, context)
end

#extract_thrown_symbol(exception) ⇒ Object

extract thrown symbol from given exception

Parameters:

  • exception


57
58
59
60
61
# File 'lib/minispec/utils/throw.rb', line 57

def extract_thrown_symbol exception
  return unless exception.is_a?(Exception)
  return unless s = exception.message.scan(/uncaught throw\W+(\w+)/).flatten[0]
  s.to_sym
end

#match?(label, x) ⇒ Boolean

compare given label to given expression. if expression is a ‘Regexp` comparing using `=~`. otherwise `==` are used

Parameters:

  • label
  • x

Returns:

  • (Boolean)

    ‘true` or `false`



135
136
137
# File 'lib/minispec/utils.rb', line 135

def match? label, x
  x.is_a?(Regexp) ? label.to_s =~ x : label == x
end

#method_visibility(object, method) ⇒ Symbol Also known as: method_defined?

determines method’s visibility

Parameters:

  • object
  • method

Returns:

  • (Symbol)

    or nil



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/minispec/utils.rb', line 59

def method_visibility object, method
  {
       public: :public_methods,
    protected: :protected_methods,
      private: :private_methods
  }.each_pair do |v,m|
    if v == :public
      # in case public_methods overridden to include method
      # but method in fact does not exists,
      # most notable ActiveRecord::Base#find which rely on method_missing
      return v if object.respond_to?(method)
    else
      return v if object.send(m).include?(method)
    end
  end
  nil
end

#pp(obj) ⇒ Object



26
27
28
29
30
31
32
# File 'lib/minispec/utils/pretty_print.rb', line 26

def pp obj
  out = ''
  q = MiniSpec::PrettyPrint.new(out)
  q.guard_inspect_key { q.pp(obj) }
  q.flush
  out
end

#rejected?(label, reject) ⇒ Boolean

checks whether given label matches any rejector.

Parameters:

  • label
  • reject

    an ‘Array` of rejectors, each being a `Hash` containing `:except` key

Returns:

  • (Boolean)

    ‘true` or `false`



116
117
118
119
120
121
122
123
124
125
# File 'lib/minispec/utils.rb', line 116

def rejected? label, reject
  if reject.any? && (x = reject.first[:except])
    if x.is_a?(Array)
      return true if x.find {|m| match?(label, m)}
    else
      return true if match?(label, x)
    end
  end
  false
end

#shorten_source(source) ⇒ Object

get rid of Dir.pwd from given path



88
89
90
# File 'lib/minispec/utils.rb', line 88

def shorten_source source
  source.to_s.sub(/\A#{Dir.pwd}\/?/, '')
end

#source(proc) ⇒ Object



83
84
85
# File 'lib/minispec/utils.rb', line 83

def source proc
  shorten_source(proc.source_location*':')
end

#symbol_thrown?(expected_symbol, expected_value, context, &block) ⇒ Boolean

checks whether given block throws a symbol and if yes compare it with expected one. if a optional value given it will be compared to thrown one.

Parameters:

  • expected_symbol
  • expected_value
  • &proc (Proc)

Returns:

  • (Boolean)

    a failure [ThrowError] if expectation not met. true if expectations met.



17
18
19
20
21
22
23
24
25
26
# File 'lib/minispec/utils/throw.rb', line 17

def symbol_thrown? expected_symbol, expected_value, context, &block
  thrown_symbol, thrown_value = catch_symbol(expected_symbol, &block)

  if context[:right_proc]
    expected_symbol && raise(ArgumentError, 'Both arguments and block given. Please use either one.')
    return MiniSpec::ThrowInspector.thrown_as_expected_by_proc?(thrown_symbol, context)
  end

  MiniSpec::ThrowInspector.thrown_as_expected?(expected_symbol, expected_value, thrown_symbol, thrown_value, context)
end

#undefine_method(object, method) ⇒ Object



5
6
7
8
# File 'lib/minispec/utils.rb', line 5

def undefine_method object, method
  return unless method_defined?(object, method)
  object.instance_eval('undef :%s' % method)
end

#valid_proxy_arguments?(left_method, *args, &proc) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

checking whether correct arguments passed to proxy methods.

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)

    if more than two arguments given

  • (ArgumentError)

    if both argument and block given



16
17
18
19
# File 'lib/minispec/utils.rb', line 16

def valid_proxy_arguments? left_method, *args, &proc
  args.size > 2 && raise(ArgumentError, '#%s - wrong number of arguments, %i for 0..2' % [left_method, args.size])
  args.size > 0 && proc && raise(ArgumentError, '#%s accepts either arguments or a block, not both' % left_method)
end

#zipper(received, expected) ⇒ Hash

Examples:

received = [:a, :b, :c]
expected = [1]
=> {:a=>1, :b=>1, :c=>1}
received = [:a, :b, :c]
expected = []
=> {:a=>nil, :b=>nil, :c=>nil}
received = [:a, :b, :c]
expected = [1, 2]
=> {:a=>1, :b=>2, :c=>2}
received = [:a, :b, :c]
expected = [1, 2, 3, 4]
=> {:a=>1, :b=>2, :c=>3}

Parameters:

  • received (Array)
  • expected (Array)

Returns:

  • (Hash)


45
46
47
48
49
50
51
# File 'lib/minispec/utils.rb', line 45

def zipper received, expected
  result = {}
  received.uniq.each_with_index do |m,i|
    result[m] = expected[i] || expected[i-1] || expected[0]
  end
  result
end