Module: Saharspec::Its::Map

Defined in:
lib/saharspec/its/map.rb

Instance Method Summary collapse

Instance Method Details

#its_map(attribute, *options, &block) ⇒ Object

Creates nested example which has current subject mapped by specified attribute as its subject.

Examples:


# with attribute
subject { %w[test me please] }
its_map(:length) { is_expected.to eq [4, 2, 6] }

# with attribute chain
its_map('reverse.upcase') { is_expected.to eq %w[TSET EM ESAELP] }

# with Hash (or any other object responding to `#[]`)
subject {
  [
    {title: 'Slaughterhouse Five', author: {first: 'Kurt', last: 'Vonnegut'}},
    {title: 'Hitchhickers Guide To The Galaxy', author: {first: 'Duglas', last: 'Adams'}}
  ]
}
its_map([:title]) { are_expected.to eq ['Slaughterhouse Five', 'Hitchhickers Guide To The Galaxy'] }
# multiple attributes for nested hashes
its_map([:author, :last]) { are_expected.to eq ['Vonnegut', 'Adams'] }

Parameters:

  • attribute (String, Symbol, Array<String, Symbol>)

    Attribute name (String or Symbol), attribute chain (string separated with dots) or arguments to #[] method (Array)

  • options

    Other options that can be passed to usual RSpec example.

  • block (Proc)

    The test itself. Inside it, is_expected (or are_expected) is related to result of mapping the subject.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/saharspec/its/map.rb', line 35

def its_map(attribute, *options, &block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  # rubocop:disable Lint/NestedMethodDefinition
  # TODO: better desciption for different cases
  describe("map(&:#{attribute})") do
    let(:__its_map_subject) do
      if Array === attribute
        if subject.all? { |s| Hash === s }
          subject.map do |s|
            attribute.inject(s) { |inner, attr| inner[attr] }
          end
        else
          subject.map { |inner| inner[*attribute] }
        end
      else
        attribute_chain = attribute.to_s.split('.').map(&:to_sym)
        attribute_chain.inject(subject) do |inner_subject, attr|
          inner_subject.map(&attr)
        end
      end
    end

    def is_expected
      expect(__its_map_subject)
    end

    alias_method :are_expected, :is_expected

    options << {} unless options.last.is_a?(Hash)

    example(nil, *options, &block)
  end
  # rubocop:enable Lint/NestedMethodDefinition
end