spec/rspec/its_spec.rb in rspec-its-1.3.1 vs spec/rspec/its_spec.rb in rspec-its-2.0.0

- old
+ new

@@ -1,394 +1,424 @@ +# frozen_string_literal: true + require 'spec_helper' -module RSpec - describe Its do - describe "#its" do - context "with implicit subject" do - context "preserves described_class" do - its(:symbol) { expect(described_class).to be Its } - its([]) { expect(described_class).to be Its } - end - end +RSpec.describe RSpec::Its do + context "with implicit subject" do + context "preserves described_class" do + its(:symbol) { expect(described_class).to be RSpec::Its } + its([]) { expect(described_class).to be RSpec::Its } + end + end - context "with explicit subject" do - subject do - Class.new do - def initialize - @call_count = 0 - end - - def call_count - @call_count += 1 - end - end.new + context "with explicit subject" do + subject do + Class.new do + def initialize + @call_count = 0 end - before(:each, :meta) do - subject.call_count + def call_count + @call_count += 1 end + end.new + end - context "with some metadata" do - its(:call_count, :meta) { should eq(2) } - end + before(:each, :meta) do + subject.call_count + end - context "with a call counter" do - its(:call_count) { should eq(1) } - end + context "with some metadata" do + its(:call_count, :meta) { is_expected.to eq(2) } + end - context "with nil value" do - subject do - Class.new do - def nil_value - nil - end - end.new - end - its(:nil_value) { should be_nil } - end + context "with a call counter" do + its(:call_count) { is_expected.to eq(1) } + end - context "with nested attributes" do - subject do - Class.new do - def name - "John" - end - end.new + context "with nil value" do + subject do + Class.new do + def nil_value + nil end - its("name") { should eq("John") } - its("name.size") { should eq(4) } - if RUBY_VERSION >= "2.4.0" - its("name.size.class") { should eq(Integer) } - else - its("name.size.class") { should eq(Fixnum) } - end + end.new + end - context "using should_not" do - its("name") { should_not eq("Paul") } - end + its(:nil_value) { is_expected.to be_nil } + end - context "using is_expected" do - its("name") { is_expected.to eq("John") } + context "with nested attributes" do + subject do + Class.new do + def name + "John" end + end.new + end - context "using will_not" do - its("name") { will_not raise_error } + its("name") { is_expected.to eq("John") } + its("name.size") { is_expected.to eq(4) } + its("name.size.class") { is_expected.to eq(Integer) } + + context "using are_expected" do + its("name.chars.to_a") { are_expected.to eq(%w[J o h n]) } + end + + context "using will_not" do + its("name") { will_not raise_error } + end + + context "using should" do + its("name") { should eq("John") } + end + + context "using should_not" do + its("name") { should_not eq("Paul") } + end + end + + context "when it responds to #[]" do + subject do + Class.new do + def [](*objects) + objects.map do |object| + "#{object.class}: #{object}" + end.join("; ") end - context "using are_expected" do - its("name.chars.to_a") { are_expected.to eq(%w[J o h n]) } + def name + "George" end - end + end.new + end - context "when it responds to #[]" do - subject do - Class.new do - def [](*objects) - objects.map do |object| - "#{object.class}: #{object.to_s}" - end.join("; ") - end + its([:a]) { is_expected.to eq("Symbol: a") } + its(['a']) { is_expected.to eq("String: a") } + its([:b, 'c', 4]) { is_expected.to eq("Symbol: b; String: c; Integer: 4") } + its(:name) { is_expected.to eq("George") } - def name - "George" - end - end.new + context "when referring to an attribute that doesn't exist" do + context "it raises an error" do + its(:age) do + expect do + is_expected.to eq(64) + end.to raise_error(NoMethodError) end - its([:a]) { should eq("Symbol: a") } - its(['a']) { should eq("String: a") } - if RUBY_VERSION >= "2.4.0" - its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Integer: 4") } - else - its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") } - end - its(:name) { should eq("George") } - context "when referring to an attribute that doesn't exist" do - context "it raises an error" do - its(:age) do - expect do - should eq(64) - end.to raise_error(NoMethodError) - end - context "using will" do - its(:age) { will raise_error(NoMethodError) } - end - end + context "using will" do + its(:age) { will raise_error(NoMethodError) } end + end + end - context "when it's a hash" do - subject { {:a => {:deep => {:key => "value"}}} } + context "when it's a hash" do + subject { { a: { deep: { key: "value" } } } } - its([:a]) { should eq({:deep => {:key => "value"}}) } - its([:a, :deep]) { should eq({:key => "value"}) } - its([:a, :deep, :key]) { should eq("value") } + its([:a]) { is_expected.to eq({ deep: { key: "value" } }) } + its(%i[a deep]) { is_expected.to eq({ key: "value" }) } + its(%i[a deep key]) { is_expected.to eq("value") } - context "when referring to a key that doesn't exist" do - its([:not_here]) { should be_nil } - its([:a, :ghost]) { should be_nil } - its([:deep, :ghost]) { expect { should eq("missing") }.to raise_error(NoMethodError) } + context "when referring to a key that doesn't exist" do + its([:not_here]) { is_expected.to be_nil } + its(%i[a ghost]) { are_expected.to be_nil } + its(%i[deep ghost]) { expect { is_expected.to eq("missing") }.to raise_error(NoMethodError) } - context "using will" do - its([:deep, :ghost]) { will raise_error(NoMethodError) } - end - end + context "using will" do + its(%i[deep ghost]) { will raise_error(NoMethodError) } end end + end + end - context "when it does not respond to #[]" do - subject { Object.new } + context "when it does not respond to #[]" do + subject { Object.new } - context "it raises an error" do - its([:a]) do - expect do - should eq("Symbol: a") - end.to raise_error(NoMethodError) - end + context "it raises an error" do + its([:a]) do + expect { is_expected.to eq("Symbol: a") }.to raise_error(NoMethodError) + end - context "using will" do - its([:a]) { will raise_error(NoMethodError) } - end - end + context "using will" do + its([:a]) { will raise_error(NoMethodError) } end + end + end - context "calling and overriding super" do - it "calls to the subject defined in the parent group" do - group = RSpec::Core::ExampleGroup.describe(Array) do - subject { [1, 'a'] } + context "calling and overriding super" do + it "calls to the subject defined in the parent group" do + group = RSpec::Core::ExampleGroup.describe(Array) do + subject { [1, 'a'] } - its(:last) { should eq("a") } + its(:last) { is_expected.to eq("a") } - describe '.first' do - def subject; - super().first; - end - - its(:next) { should eq(2) } - end + describe '.first' do + def subject + super.first end - expect(group.run(NullFormatter.new)).to be_truthy + its(:next) { is_expected.to eq(2) } end end - context "with nil subject" do - subject do - Class.new do - def initialize - @counter = -1 - end + expect(group.run(NullFormatter.new)).to be_truthy + end + end - def nil_if_first_time - @counter += 1 - @counter == 0 ? nil : true - end - end.new + context "with nil subject" do + subject do + Class.new do + def initialize + @counter = -1 end - its(:nil_if_first_time) { should be(nil) } - end - context "with false subject" do - subject do - Class.new do - def initialize - @counter = -1 - end - - def false_if_first_time - @counter += 1 - @counter > 0 - end - end.new + def nil_if_first_time + @counter += 1 + @counter == 0 ? nil : true end - its(:false_if_first_time) { should be(false) } - end + end.new + end - describe 'accessing `subject` in `before` and `let`' do - subject { 'my subject' } - before { @subject_in_before = subject } - let(:subject_in_let) { subject } - let!(:eager_loaded_subject_in_let) { subject } + its(:nil_if_first_time) { is_expected.to be(nil) } + end - # These examples read weird, because we're actually - # specifying the behaviour of `its` itself - its(nil) { expect(subject).to eq('my subject') } - its(nil) { expect(@subject_in_before).to eq('my subject') } - its(nil) { expect(subject_in_let).to eq('my subject') } - its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') } - end + context "with false subject" do + subject do + Class.new do + def initialize + @counter = -1 + end - describe "in shared_context" do - shared_context "shared stuff" do - subject { Array } - its(:name) { should eq "Array" } + def false_if_first_time + @counter += 1 + @counter > 0 end + end.new + end - include_context "shared stuff" - end + its(:false_if_first_time) { is_expected.to be(false) } + end - describe "when extending SharedContext" do - it 'works with an implicit subject' do - shared = Module.new do - extend RSpec::SharedContext - its(:size) { should eq 0 } - end - group = RSpec::Core::ExampleGroup.describe(Array) do - include shared - end + describe 'accessing `subject` in `before` and `let`' do + subject { 'my subject' } - group.run(NullFormatter.new) + before { @subject_in_before = subject } - result = group.children.first.examples.first.execution_result - # Following conditional needed to work across mix of RSpec and ruby versions without warning - status = result.respond_to?(:status) ? result.status : result[:status].to_sym - expect(status).to eq(:passed) - end - end - end - context "with metadata" do - context "preserves access to metadata that doesn't end in hash" do - its([], :foo) do |example| - expect(example.metadata[:foo]).to be(true) - end - end - context "preserves access to metadata that ends in hash" do - its([], :foo, :bar => 17) do |example| - expect(example.metadata[:foo]).to be(true) - expect(example.metadata[:bar]).to be(17) - end - end - end + let(:subject_in_let) { subject } + let!(:eager_loaded_subject_in_let) { subject } - context "when expecting errors" do - subject do - Class.new do - def good; end + # These examples read weird, because we're actually + # specifying the behaviour of `its` itself + its(nil) { expect(subject).to eq('my subject') } + its(nil) { expect(@subject_in_before).to eq('my subject') } + its(nil) { expect(subject_in_let).to eq('my subject') } + its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') } + end - def bad - raise ArgumentError, "message" - end - end.new - end + describe "in shared_context" do + shared_context "shared stuff" do + subject { Array } - its(:good) { will_not raise_error } - its(:bad) { will raise_error(ArgumentError) } - its(:bad) { will raise_error("message") } - its(:bad) { will raise_error(ArgumentError, "message") } + its(:name) { is_expected.to eq "Array" } end - context "when expecting throws" do - subject do - Class.new do - def good; end + include_context "shared stuff" + end - def bad - throw :abort, "message" - end - end.new + describe "when extending SharedContext" do + it 'works with an implicit subject' do + shared = Module.new do + extend RSpec::SharedContext + its(:size) { is_expected.to eq 0 } end - its(:good) { will_not throw_symbol } - its(:bad) { will throw_symbol } - its(:bad) { will throw_symbol(:abort) } - its(:bad) { will throw_symbol(:abort, "message") } + group = RSpec::Core::ExampleGroup.describe(Array) do + include shared + end + + group.run(NullFormatter.new) + + result = group.children.first.examples.first.execution_result + # Following conditional needed to work across mix of RSpec and ruby versions without warning + status = result.respond_to?(:status) ? result.status : result[:status].to_sym + expect(status).to eq(:passed) end + end + end - context "with change observation" do - subject do - Class.new do - attr_reader :count + context "with metadata" do + context "preserves access to metadata that doesn't end in hash" do + its([], :foo) do |example| + expect(example.metadata[:foo]).to be(true) + end + end - def initialize - @count = 0 - end + context "preserves access to metadata that ends in hash" do + its([], :foo, bar: 17) do |example| + expect(example.metadata[:foo]).to be(true) + expect(example.metadata[:bar]).to be(17) + end + end + end - def increment - @count += 1 - end + context "when expecting errors" do + subject do + Class.new do + def good; end - def noop; end - end.new + def bad + raise ArgumentError, "message" end + end.new + end - its(:increment) { will change { subject.count }.by(1) } - its(:increment) { will change { subject.count }.from(0) } - its(:increment) { will change { subject.count }.from(0).to(1) } - its(:increment) { will change { subject.count }.by_at_least(1) } - its(:increment) { will change { subject.count }.by_at_most(1) } + its(:good) { will_not raise_error } + its(:bad) { will raise_error(ArgumentError) } + its(:bad) { will raise_error("message") } + its(:bad) { will raise_error(ArgumentError, "message") } + end - its(:noop) { will_not change { subject.count } } - its(:noop) { will_not change { subject.count }.from(0) } + context "when expecting throws" do + subject do + Class.new do + def good; end - its(:increment) do - expect { will_not change { subject.count }.by(0) }.to \ - raise_error(NotImplementedError, '`expect { }.not_to change { }.by()` is not supported') + def bad + throw :abort, "message" end + end.new + end - its(:increment) do - expect { will_not change { subject.count }.by_at_least(2) }.to \ - raise_error(NotImplementedError, '`expect { }.not_to change { }.by_at_least()` is not supported') + its(:good) { will_not throw_symbol } + its(:bad) { will throw_symbol } + its(:bad) { will throw_symbol(:abort) } + its(:bad) { will throw_symbol(:abort, "message") } + end + + context "with change observation" do + subject do + Class.new do + attr_reader :count + + def initialize + @count = 0 end - its(:increment) do - expect { will_not change { subject.count }.by_at_most(3) }.to \ - raise_error(NotImplementedError, '`expect { }.not_to change { }.by_at_most()` is not supported') + def increment + @count += 1 end - end - context "with output capture" do - subject do - Class.new do - def stdout - print "some output" - end + def noop; end + end.new + end - def stderr - $stderr.print "some error" - end + its(:increment) { will change { subject.count }.by(1) } + its(:increment) { will change { subject.count }.from(0) } + its(:increment) { will change { subject.count }.from(0).to(1) } + its(:increment) { will change { subject.count }.by_at_least(1) } + its(:increment) { will change { subject.count }.by_at_most(1) } - def noop; end - end.new - end + its(:noop) { will_not(change { subject.count }) } + its(:noop) { will_not change { subject.count }.from(0) } - its(:stdout) { will output("some output").to_stdout } - its(:stderr) { will output("some error").to_stderr } + its(:increment) do + expect { will_not change { subject.count }.by(0) }.to \ + raise_error(NotImplementedError, '`expect { }.not_to change { }.by()` is not supported') + end - its(:noop) { will_not output("some error").to_stderr } - its(:noop) { will_not output("some output").to_stdout } - end + its(:increment) do + expect { will_not change { subject.count }.by_at_least(2) }.to \ + raise_error(NotImplementedError, '`expect { }.not_to change { }.by_at_least()` is not supported') + end - context "#will with non block expectations" do - subject do - Class.new do - def terminator - "back" - end - end.new + its(:increment) do + expect { will_not change { subject.count }.by_at_most(3) }.to \ + raise_error(NotImplementedError, '`expect { }.not_to change { }.by_at_most()` is not supported') + end + end + + context "with output capture" do + subject do + Class.new do + def stdout + print "some output" end - its(:terminator) do - expect { will be("back") }.to \ - raise_error(ArgumentError, '`will` only supports block expectations') + def stderr + $stderr.print "some error" end - its(:terminator) do - expect { will_not be("back") }.to \ - raise_error(ArgumentError, '`will_not` only supports block expectations') + def noop; end + end.new + end + + its(:stdout) { will output("some output").to_stdout } + its(:stderr) { will output("some error").to_stderr } + + its(:noop) { will_not output("some error").to_stderr } + its(:noop) { will_not output("some output").to_stdout } + end + + context "#will with non block expectations" do + subject do + Class.new do + def terminator + "back" end - end + end.new + end - context "when example is redefined" do - subject do - Class.new do - def will_still_work; true; end - end.new + its(:terminator) do + expect { will be("back") }.to \ + raise_error(ArgumentError, '`will` only supports block expectations') + end + + its(:terminator) do + expect { will_not be("back") }.to \ + raise_error(ArgumentError, '`will_not` only supports block expectations') + end + end + + context "when example is redefined" do + subject do + Class.new do + def will_still_work + true end + end.new + end - def self.example(*_args) - raise + def self.example(*_args) + raise + end + + its(:will_still_work) { is_expected.to be true } + end + + context "with private method" do + subject(:klass) do + Class.new do + def name + private_name end - its(:will_still_work) { is_expected.to be true } + private + + def private_name + "John" + end + end.new + end + + context "when referring indirectly" do + its(:name) { is_expected.to eq "John" } + end + + context "when attempting to refer directly" do + context "it raises an error" do + its(:private_name) do + expect { is_expected.to eq("John") }.to raise_error(NoMethodError) + end end end end end