Module: RSpec::Its

Defined in:
lib/rspec/its.rb,
lib/rspec/its/version.rb

Constant Summary collapse

VERSION =
"1.3.0"

Instance Method Summary collapse

Instance Method Details

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

Creates a nested example group named by the submitted ‘attribute`, and then generates an example using the submitted block.

The attribute can be a ‘Symbol` or a `String`. Given a `String` with dots, the result is as though you concatenated that `String` onto the subject in an expression.

When the subject is a ‘Hash`, you can refer to the Hash keys by specifying a `Symbol` or `String` in an array.

With an implicit subject, ‘is_expected` can be used as an alternative to `should` (e.g. for one-liner use). An `are_expected` alias is also supplied.

With an implicit subject, ‘will` can be used as an alternative to `expect { subject.attribute }.to matcher` (e.g. for one-liner use).

With an implicit subject, ‘will_not` can be used as an alternative to `expect { subject.attribute }.to_not matcher` (e.g. for one-liner use).

You can pass more than one argument on the ‘its` block to add some metadata to the generated example

Note that this method does not modify ‘subject` in any way, so if you refer to `subject` in `let` or `before` blocks, you’re still referring to the outer subject.

Examples:


# This ...
describe Array do
  its(:size) { should eq(0) }
end

# ... generates the same runtime structure as this:
describe Array do
  describe "size" do
    it "should eq(0)" do
      subject.size.should eq(0)
    end
  end
end

describe Person do
  subject do
    Person.new.tap do |person|
      person.phone_numbers << "555-1212"
    end
  end

  its("phone_numbers.first") { should eq("555-1212") }
end

describe "a configuration Hash" do
  subject do
    { :max_users => 3,
      'admin' => :all_permissions.
      'john_doe' => {:permissions => [:read, :write]}}
  end

  its([:max_users]) { should eq(3) }
  its(['admin']) { should eq(:all_permissions) }
  its(['john_doe', :permissions]) { should eq([:read, :write]) }

  # You can still access its regular methods this way:
  its(:keys) { should include(:max_users) }
  its(:count) { should eq(2) }
end

describe Array do
  its(:size) { is_expected.to eq(0) }
end

describe Array do
  its(:foo) { will raise_error(NoMethodError) }
end

describe Array do
  its(:size) { will_not raise_error }
end

# This ...
describe Array do
  its(:size, :focus) { should eq(0) }
end

# ... generates the same runtime structure as this:
describe Array do
  describe "size" do
    it "should eq(0)", :focus do
      subject.size.should eq(0)
    end
  end
end

describe Person do
  subject { Person.new }
  before { subject.age = 25 }
  its(:age) { should eq(25) }
end


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/rspec/its.rb', line 121

def its(attribute, *options, &block)
  its_caller = caller.select {|file_line| file_line !~ %r(/lib/rspec/its) }
  describe(attribute.to_s, :caller => its_caller) do
    let(:__its_subject) do
      if Array === attribute
        if Hash === subject
          attribute.inject(subject) {|inner, attr| inner[attr] }
        else
          subject[*attribute]
        end
      else
        attribute_chain = attribute.to_s.split('.')
        attribute_chain.inject(subject) do |inner_subject, attr|
          inner_subject.send(attr)
        end
      end
    end

    def is_expected
      expect(__its_subject)
    end
    alias_method :are_expected, :is_expected

    def will(matcher=nil, message=nil)
      unless matcher.supports_block_expectations?
        raise ArgumentError, "`will` only supports block expectations"
      end
      expect { __its_subject }.to matcher, message
    end

    def will_not(matcher=nil, message=nil)
      unless matcher.supports_block_expectations?
        raise ArgumentError, "`will_not` only supports block expectations"
      end
      expect { __its_subject }.to_not matcher, message
    end

    def should(matcher=nil, message=nil)
      RSpec::Expectations::PositiveExpectationHandler.handle_matcher(__its_subject, matcher, message)
    end

    def should_not(matcher=nil, message=nil)
      RSpec::Expectations::NegativeExpectationHandler.handle_matcher(__its_subject, matcher, message)
    end

    options << {} unless options.last.kind_of?(Hash)
    options.last.merge!(:caller => its_caller)

    example(nil, *options, &block)

  end
end