rspec-its-2.0.0/0000755000004100000410000000000014740426640013461 5ustar www-datawww-datarspec-its-2.0.0/.gitignore0000644000004100000410000000027314740426640015453 0ustar www-datawww-data*.gem *.rbc .bundle .config .yardoc .ruby-version .ruby-gemset Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp bin/* rspec-its-2.0.0/.github/0000755000004100000410000000000014740426640015021 5ustar www-datawww-datarspec-its-2.0.0/.github/dependabot.yml0000644000004100000410000000016614740426640017654 0ustar www-datawww-dataversion: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" rspec-its-2.0.0/.github/workflows/0000755000004100000410000000000014740426640017056 5ustar www-datawww-datarspec-its-2.0.0/.github/workflows/ci.yml0000644000004100000410000000337114740426640020200 0ustar www-datawww-dataname: RSpec CI on: push: branches: - 'main' - '*-maintenance' - '*-dev' pull_request: branches: - '*' env: RSPEC_CI: true jobs: rubocop: name: Rubocop runs-on: 'ubuntu-20.04' steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.3' - run: script/update_rubygems_and_install_bundler - run: bundle install - run: bundle exec rubocop -c .rubocop.yml test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} runs-on: ${{ matrix.os || 'ubuntu-20.04' }} strategy: matrix: ruby: - '3.4' - '3.3' - '3.2' - '3.1' - '3.0' env: - BRANCH: "main" include: - ruby: '3.3' name_extra: "against RSpec 3.13" env: BRANCH: "3-13-maintenance" - ruby: '3.2' name_extra: "against RSpec 3.13" env: BRANCH: "3-13-maintenance" - ruby: '3.1' name_extra: "against RSpec 3.13" env: BRANCH: "3-13-maintenance" - ruby: '3.0' name_extra: "against RSpec 3.13" env: BRANCH: "3-13-maintenance" fail-fast: false continue-on-error: ${{ matrix.allow_failure || endsWith(matrix.ruby, 'head') }} env: ${{ matrix.env }} steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: bundler: ${{ matrix.bundler || 2 }} ruby-version: ${{ matrix.ruby }} - run: script/update_rubygems_and_install_bundler - run: bundle install --standalone - run: bundle binstubs --all - run: script/test_all rspec-its-2.0.0/.github/FUNDING.yml0000644000004100000410000000032214740426640016633 0ustar www-datawww-data# This file was generated on 2019-12-05T21:32:24+00:00 from the rspec-dev repo. # DO NOT modify it by hand as your changes will get lost the next time it is generated. github: [JonRowe] open_collective: rspec rspec-its-2.0.0/lib/0000755000004100000410000000000014740426640014227 5ustar www-datawww-datarspec-its-2.0.0/lib/rspec/0000755000004100000410000000000014740426640015343 5ustar www-datawww-datarspec-its-2.0.0/lib/rspec/its.rb0000644000004100000410000001226714740426640016477 0ustar www-datawww-data# frozen_string_literal: true require 'rspec/its/subject' require 'rspec/its/version' require 'rspec/core' RSpec::Core::ExampleGroup.define_example_method :__its_example module RSpec # Adds the `its` to RSpec Example Groups, included by default. module Its # Creates a nested example group named by the submitted `attribute`, # and then generates an example using the submitted block. # # @example # # # This ... # RSpec.describe Array do # its(:size) { is_expected.to eq(0) } # end # # # ... generates the same runtime structure as this: # RSpec.describe Array do # describe "size" do # it "is_expected.to eq(0)" do # expect(subject.size).to eq(0) # end # end # end # # 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. # # @example # # RSpec.describe Person do # subject(:person) do # Person.new.tap do |person| # person.phone_numbers << "555-1212" # end # end # # its("phone_numbers.first") { is_expected.to eq("555-1212") } # end # # When the subject is a `Hash`, you can refer to the Hash keys by # specifying a `Symbol` or `String` in an array. # # @example # # RSpec.describe "a configuration Hash" do # subject do # { :max_users => 3, # 'admin' => :all_permissions. # 'john_doe' => {:permissions => [:read, :write]}} # end # # its([:max_users]) { is_expected.to eq(3) } # its(['admin']) { is_expected.to eq(:all_permissions) } # its(['john_doe', :permissions]) { are_expected.to eq([:read, :write]) } # # # You can still access its regular methods this way: # its(:keys) { is_expected.to include(:max_users) } # its(:count) { is_expected.to eq(2) } # end # # With an implicit subject, `should` can be used as an alternative # to `is_expected` (e.g. for one-liner use). An `are_expected` alias is also # supplied. # # @example # # RSpec.describe Array do # its(:size) { should eq(0) } # end # # With an implicit subject, `will` can be used as an alternative # to `expect { subject.attribute }.to matcher` (e.g. for one-liner use). # # @example # # RSpec.describe Array do # its(:foo) { will raise_error(NoMethodError) } # end # # 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). # # @example # # RSpec.describe Array do # its(:size) { will_not raise_error } # end # # You can pass more than one argument on the `its` block to add # some metadata to the generated example # # @example # # # This ... # RSpec.describe Array do # its(:size, :focus) { is_expected.to eq(0) } # end # # # ... generates the same runtime structure as this: # RSpec.describe Array do # describe "size" do # it "is expected to eq(0)", :focus do # expect(subject.size).to eq(0) # end # end # end # # 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. # # @example # # RSpec.describe Person do # subject { Person.new } # # before { subject.age = 25 } # # its(:age) { is_expected.to eq(25) } # end def its(attribute, *options, &block) its_caller = caller.grep_v(%r{/lib/rspec/its}) describe(attribute.to_s, caller: its_caller) do let(:__its_subject) { RSpec::Its::Subject.for(attribute, subject) } def is_expected expect(__its_subject) end alias_method :are_expected, :is_expected def will(matcher = nil, message = nil) raise ArgumentError, "`will` only supports block expectations" unless matcher.supports_block_expectations? expect { __its_subject }.to matcher, message end def will_not(matcher = nil, message = nil) raise ArgumentError, "`will_not` only supports block expectations" unless matcher.supports_block_expectations? 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.is_a?(Hash) options.last.merge!(caller: its_caller) __its_example(nil, *options, &block) end end end end RSpec.configure do |rspec| rspec.extend RSpec::Its rspec.backtrace_exclusion_patterns << %r{/lib/rspec/its} end RSpec::SharedContext.send(:include, RSpec::Its) rspec-its-2.0.0/lib/rspec/its/0000755000004100000410000000000014740426640016142 5ustar www-datawww-datarspec-its-2.0.0/lib/rspec/its/version.rb0000644000004100000410000000013114740426640020147 0ustar www-datawww-data# frozen_string_literal: true module RSpec module Its VERSION = '2.0.0' end end rspec-its-2.0.0/lib/rspec/its/subject.rb0000644000004100000410000000117414740426640020131 0ustar www-datawww-data# frozen_string_literal: true module RSpec module Its # @api private # Handles turning subject into an expectation target module Subject def for(attribute, subject) 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.public_send(attr) end end end module_function :for end end end rspec-its-2.0.0/LICENSE.txt0000644000004100000410000000233714740426640015311 0ustar www-datawww-data(The MIT License) Copyright (c) 2024 The RSpec Development Team Copyright (c) 2013 Peter Alfvin Copyright (c) 2012 David Chelimsky, Myron Marston Copyright (c) 2006 David Chelimsky, The RSpec Development Team MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rspec-its-2.0.0/spec/0000755000004100000410000000000014740426640014413 5ustar www-datawww-datarspec-its-2.0.0/spec/spec_helper.rb0000644000004100000410000000057214740426640017235 0ustar www-datawww-data# frozen_string_literal: true require 'rspec/its' Dir['./spec/support/**/*'].each { |f| require f } class NullFormatter private def method_missing(method, *args, &block) # ignore end def respond_to_missing?(method, *args, &block) # ignore end end RSpec.configure do |config| config.run_all_when_everything_filtered = true config.order = 'random' end rspec-its-2.0.0/spec/rspec/0000755000004100000410000000000014740426640015527 5ustar www-datawww-datarspec-its-2.0.0/spec/rspec/its_spec.rb0000644000004100000410000002457414740426640017701 0ustar www-datawww-data# frozen_string_literal: true require 'spec_helper' 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 end before(:each, :meta) do subject.call_count end context "with some metadata" do its(:call_count, :meta) { is_expected.to eq(2) } end context "with a call counter" do its(:call_count) { is_expected.to eq(1) } end context "with nil value" do subject do Class.new do def nil_value nil end end.new end its(:nil_value) { is_expected.to be_nil } end context "with nested attributes" do subject do Class.new do def name "John" end end.new end 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 def name "George" end end.new 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") } 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 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" } } } } 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]) { 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(%i[deep ghost]) { will raise_error(NoMethodError) } end end end end context "when it does not respond to #[]" do subject { Object.new } 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 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'] } its(:last) { is_expected.to eq("a") } describe '.first' do def subject super.first end its(:next) { is_expected.to eq(2) } end end expect(group.run(NullFormatter.new)).to be_truthy end end context "with nil subject" do subject do Class.new do def initialize @counter = -1 end def nil_if_first_time @counter += 1 @counter == 0 ? nil : true end end.new end its(:nil_if_first_time) { is_expected.to 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 end its(:false_if_first_time) { is_expected.to be(false) } 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 } # 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 describe "in shared_context" do shared_context "shared stuff" do subject { Array } its(:name) { is_expected.to eq "Array" } end include_context "shared stuff" end 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 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 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 context "when expecting errors" do subject do Class.new do def good; end def bad raise ArgumentError, "message" end end.new end 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 context "when expecting throws" do subject do Class.new do def good; end def bad throw :abort, "message" end end.new 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") } end context "with change observation" do subject do Class.new do attr_reader :count def initialize @count = 0 end def increment @count += 1 end def noop; 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(:noop) { will_not(change { subject.count }) } its(:noop) { will_not change { subject.count }.from(0) } 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(: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 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 def stderr $stderr.print "some error" end 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.new end 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 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 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 rspec-its-2.0.0/.rspec0000644000004100000410000000004014740426640014570 0ustar www-datawww-data--color --order rand --warnings rspec-its-2.0.0/Rakefile0000644000004100000410000000051614740426640015130 0ustar www-datawww-data# frozen_string_literal: true require "bundler" Bundler.setup Bundler::GemHelper.install_tasks require "rake" require "rspec/core/rake_task" require "cucumber/rake/task" Cucumber::Rake::Task.new(:cucumber) desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.ruby_opts = %w[-w] end task default: %i[spec cucumber] rspec-its-2.0.0/features/0000755000004100000410000000000014740426640015277 5ustar www-datawww-datarspec-its-2.0.0/features/step_definitions/0000755000004100000410000000000014740426640020645 5ustar www-datawww-datarspec-its-2.0.0/features/step_definitions/additional_cli_steps.rb0000644000004100000410000000250614740426640025352 0ustar www-datawww-data# frozen_string_literal: true When(/^I run rspec( with the documentation option)?$/) do |documentation| rspec_its_gem_location = File.expand_path('../../lib/rspec/its', __dir__) require_option = "--require #{rspec_its_gem_location}" format_option = documentation ? "--format documentation" : "" rspec_command = ['rspec', require_option, format_option, 'example_spec.rb'].join(' ') step "I run `#{rspec_command}`" end When(/^I run rspec specifying line number (\d+)$/) do |line_number| rspec_its_gem_location = File.expand_path('../../lib/rspec/its', __dir__) require_option = "--require #{rspec_its_gem_location}" file_specification = "example_spec.rb:#{line_number}" rspec_command = ['rspec', require_option, file_specification].join(' ') step "I run `#{rspec_command}`" end Then(/^the example(?:s)? should(?: all)? pass$/) do step 'the output should contain "0 failures"' step 'the output should not contain "0 examples"' step 'the exit status should be 0' end Then("the example should fail") do step 'the output should contain "1 failure"' step 'the exit status should not be 0' end Then(/^the output should contain "(.*?)" and "(.*?)"$/) do |string1, string2| unless [string1, string2].all? { |s| all_output.include?(s) } fail %(Both "#{string1}" and "#{string2}" were found in:\n#{all_output}) end end rspec-its-2.0.0/features/its.feature0000644000004100000410000001145414740426640017460 0ustar www-datawww-dataFeature: attribute of subject Scenario: specify value of a nested attribute Given a file named "example_spec.rb" with: """ruby class Person attr_reader :phone_numbers def initialize @phone_numbers = [] end end RSpec.describe Person do context "with one phone number (555-1212)"do subject(:person) do person = Person.new person.phone_numbers << "555-1212" person end its("phone_numbers.first") { is_expected.to eq("555-1212") } end end """ When I run rspec with the documentation option Then the output should contain: """ Person with one phone number (555-1212) phone_numbers.first is expected to eq "555-1212" """ Scenario: specify value of an attribute of a hash Given a file named "example_spec.rb" with: """ruby RSpec.describe Hash do context "with two items" do subject do {:one => 'one', :two => 'two'} end its(:size) { is_expected.to eq(2) } end end """ When I run rspec Then the examples should all pass Scenario: specify value for key in a hash Given a file named "example_spec.rb" with: """ruby RSpec.describe Hash do context "with keys :one and 'two'" do subject do {:one => 1, "two" => 2} end its([:one]) { is_expected.to eq(1) } its(["two"]) { is_expected.to eq(2) } end end """ When I run rspec Then the examples should all pass Scenario: specify value for key in a hash-like object Given a file named "example_spec.rb" with: """ruby require 'matrix' RSpec.describe Matrix do context "with values [[1, 2], [3, 4]]" do subject do Matrix[[1, 2], [3, 4]] end its([0, 1]) { are_expected.to eq(2) } its([1, 0]) { are_expected.to eq(3) } its([1, 2]) { are_expected.to be_nil } end end """ When I run rspec Then the examples should all pass Scenario: failures are correctly reported as coming from the `its` line Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do context "when first created" do its(:size) { is_expected.to_not eq(0) } end end """ When I run rspec Then the output should contain "Failure/Error: its(:size) { is_expected.to_not eq(0) }" And the output should not match /#[^\n]*rspec[\x2f]its/ Scenario: examples can be specified by exact line number Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do context "when first created" do its(:size) { is_expected.to eq(0) } end end """ When I run rspec specifying line number 3 Then the examples should all pass Scenario: examples can be specified by line number within containing block Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do context "when first created" do its(:size) { is_expected.to eq(0) } end it "should never execute this" do expect(true).to be(false) end end """ When I run rspec specifying line number 2 Then the examples should all pass Scenario: specify a method throws an exception Given a file named "example_spec.rb" with: """ruby class Klass def foo true end end RSpec.describe Klass do subject(:klass) { Klass.new } its(:foo) { will_not raise_error } its(:bar) { will raise_error(NoMethodError) } end """ When I run rspec Then the examples should all pass Scenario: specify a method does not throw an exception Given a file named "example_spec.rb" with: """ruby class Klass; end RSpec.describe Klass do subject(:klass) { Klass.new } its(:foo) { will_not raise_error } end """ When I run rspec Then the example should fail And the output should contain "Failure/Error: its(:foo) { will_not raise_error }" And the output should match /expected no Exception, got # 2.2.0' gem 'bundler', '> 2.0.0' gem 'coveralls', require: false gem 'cucumber', '>= 1.3.8' gem 'ffi', '~> 1.17.0' gem 'matrix', '~> 0.4.2' gem 'rake', '~> 13.2.0' gem 'rubocop', '~> 1.68.0' rspec-its-2.0.0/README.md0000644000004100000410000000476214740426640014751 0ustar www-datawww-data# RSpec::Its [![Build Status](https://github.com/rspec/rspec-its/actions/workflows/ci.yml/badge.svg)](https://github.com/rspec/rspec-its/actions/workflows/ci.yml/badge.svg) RSpec::Its provides the `its` method as a short-hand to specify the expected value of an attribute. ## Installation Add this line to your application's Gemfile: ```ruby gem 'rspec-its' ``` And then execute: $ bundle Or install it yourself as: $ gem install rspec-its And require it as: ```ruby require 'rspec/its' ``` ## Usage Use the `its` method to generate a nested example group with a single example that specifies the expected value of an attribute of the subject using `is_expected`. The `its` method can also specify the block expectations of an attribute of the subject using `will` or `will_not`. `its` accepts a symbol or a string, and a block representing the example. ```ruby its(:size) { is_expected.to eq(1) } its("length") { is_expected.to eq(1) } ``` You can use a string with dots to specify a nested attribute (i.e. an attribute of the attribute of the subject). ```ruby its("phone_numbers.size") { is_expected.to_not eq(0) } ``` The following should-style method is also available: ```ruby its(:size) { should eq(1) } ``` as is an alias of `is_expected` for pluralized use: ```ruby its(:keys) { are_expected.to eq([:key1, :key2]) } ``` The following block expect-style method is also available: ```ruby its(:size) { will_not raise_error } ``` as is this alias for pluralized use: ```ruby its(:keys) { will raise_error(NoMethodError) } ``` When the subject implements the `[]` operator, you can pass in an array with a single key to refer to the value returned by that operator when passed that key as an argument. ```ruby its([:key]) { is_expected.to eq(value) } ``` For hashes, multiple keys within the array will result in successive accesses into the hash. For example: ```ruby subject { {key1: {key2: 3} } } its([:key1, :key2]) { is_expected.to eq(3) } ``` For other objects, multiple keys within the array will be passed as separate arguments in a single method call to [], as in: ```ruby subject { Matrix[ [:a, :b], [:c, :d] ] } its([1,1]) { is_expected.to eq(:d) } ``` Metadata arguments are supported. ```ruby its(:size, focus: true) { is_expected.to eq(1) } ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request rspec-its-2.0.0/Changelog.md0000644000004100000410000000404314740426640015673 0ustar www-datawww-data### 2.0.0 / 2024-11-04 Version 2.0.0 drops support for Ruby below 3, and changes the supported RSpec version to "main" and current release series. (At the time of writing this is 3.13.x, but it means the current supported release only). Breaking changes: * Now uses `public_send` so that private methods will not be accidentally reachable. (James Ottaway #33, #101) ### 1.3.1 / 2024-10-23 [full changelog](http://github.com/rspec/rspec-its/compare/v1.3.0...v1.3.1) Bug fixes: * Prevent overridden `example` methods causing issues by creating our own Example Group creation alias `__its_example`. (Jon Rowe, #95) ### 1.3.0 / 2019-04-09 [full changelog](http://github.com/rspec/rspec-its/compare/v1.2.0...v1.3.0) Enhancements: * Introduced `will` and `will_not` as to allow one line block expectations. (Russ Buchanan, #67) ### 1.2.0 / 2015-02-06 [full changelog](http://github.com/rspec/rspec-its/compare/v1.1.0...v1.2.0) Breaking Changes: Enhancements: * Introduced `are_expected` as alias for `is_expected` Bug fixes: * Restored ability to pass key/value metadata parameters, broken by https://github.com/rspec/rspec-its/commit/71307bc7051f482bfc2798daa390bee9142b0d5a ### 1.1.0 / 2014-04-13 [full changelog](http://github.com/rspec/rspec-its/compare/v1.0.1...v1.1.0) Breaking Changes: Enhancements: * For hashes, multiple array elements are treated as successive access keys * Metadata arguments are now supported Bug fixes: * Enable `its` example selection by line number in command line ### 1.0.1 / 2014-04-13 [full changelog](http://github.com/rspec/rspec-its/compare/v1.0.0...v1.0.1) Bug fixes: * Maintain implicit subject in all cases (addresses problem with latest RSpec 3 version) ### 1.0.0 / 2014-02-07 [full changelog](http://github.com/rspec/rspec-its/compare/v1.0.0.pre...v1.0.0) Breaking Changes: Enhancements: * Add `is_expected` support to match RSpec 3.0 Deprecations: Bug Fixes: * Report failures and backtrace from client perspective ### 1.0.0.pre / 2013-10-11 Features * Initial extraction of `its()` functionality to separate gem rspec-its-2.0.0/.rubocop.yml0000644000004100000410000000127014740426640015733 0ustar www-datawww-dataAllCops: NewCops: enable SuggestExtensions: false Metrics/BlockLength: Enabled: true Exclude: - spec/**/*_spec.rb Layout/LineLength: Max: 120 Lint/NestedMethodDefinition: Exclude: - lib/rspec/its.rb Lint/SendWithMixinArgument: Exclude: - lib/rspec/its.rb Metrics/AbcSize: Exclude: - lib/rspec/its.rb Metrics/MethodLength: Max: 25 Naming/PredicateName: Exclude: - lib/rspec/its.rb Style/CaseEquality: Exclude: - lib/rspec/its/subject.rb Style/SignalException: Exclude: - features/**/*.rb Style/SpecialGlobalVars: Exclude: - rspec-its.gemspec # We don't care about single vs double quotes. Style/StringLiterals: Enabled: false rspec-its-2.0.0/rspec-its.gemspec0000644000004100000410000000261614740426640016744 0ustar www-datawww-data# frozen_string_literal: true lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'rspec/its/version' Gem::Specification.new do |spec| spec.name = "rspec-its" spec.version = RSpec::Its::VERSION spec.authors = ["The RSpec Development Team"] spec.email = ["maintainers@rspec.info"] spec.description = 'RSpec extension gem for attribute matching' spec.summary = 'Provides "its" method formerly part of rspec-core' spec.homepage = "https://github.com/rspec/rspec-its" spec.license = "MIT" spec.required_ruby_version = '> 3.0.0' spec.metadata['bug_tracker_uri'] = 'https://github.com/rspec/rspec-its/issues' spec.metadata['changelog_uri'] = "https://github.com/rspec/rspec-its/blob/v#{spec.version}/Changelog.md" spec.metadata['documentation_uri'] = "https://www.rubydoc.info/gems/rspec-its/#{spec.version}" spec.metadata['mailing_list_uri'] = 'https://groups.google.com/forum/#!forum/rspec' spec.metadata['rubygems_mfa_required'] = 'true' spec.metadata['source_code_uri'] = 'https://github.com/rspec/rspec-its' spec.files = `git ls-files`.split($/) - %w[cucumber.yml] spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.add_dependency 'rspec-core', '>= 3.13.0' spec.add_dependency 'rspec-expectations', '>= 3.13.0' end rspec-its-2.0.0/script/0000755000004100000410000000000014740426640014765 5ustar www-datawww-datarspec-its-2.0.0/script/test_all0000755000004100000410000000233514740426640016525 0ustar www-datawww-data#!/bin/bash set -e -x # idea taken from: http://blog.headius.com/2010/03/jruby-startup-time-tips.html export JRUBY_OPTS='-X-C' # disable JIT since these processes are so short lived # force jRuby to use client mode JVM or a compilation mode thats as close as possible, # idea taken from https://github.com/jruby/jruby/wiki/Improving-startup-time export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "Running rspec specs" bin/rspec spec --format progress --profile echo "Running cucumber specs" if [ -z ${BRANCH+" is set"} ]; then echo "BRANCH must be set for this script." exit 1 else echo "Using $BRANCH" fi if ruby -e "exit(defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java')"; then # This is JRUBY which requires this one weird path trick... PATH="${PWD}/bin:$PATH" \ bundle exec cucumber --strict elif ruby -e "exit(RUBY_VERSION.to_f >= 3.4)"; then # This is a monkey patch to fix an issue with cucumber using outdated hash syntax, remove when cucumber is updated or ruby 3.4 released sed -i '$i\class Hash; alias :__initialize :initialize; def initialize(*args, **_kw, &block) = __initialize(*args, &block); end' bin/cucumber bin/cucumber --strict else bundle exec cucumber --strict fi; rspec-its-2.0.0/script/update_rubygems_and_install_bundler0000755000004100000410000000016514740426640024177 0ustar www-datawww-data#!/bin/bash set -e echo "Installing latest rubygems / bundler" yes | gem update --system yes | gem install bundler