ruby-rspec_3.13.0c0e0m0s1.orig/0000775000000000000000000000000014567461030014571 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/0000775000000000000000000000000014567461030017417 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.rubocop_rspec_base.yml0000664000000000000000000001500514566142077024066 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. # This file contains defaults for RSpec projects. Individual projects # can customize by inheriting this file and overriding particular settings. Layout/AccessModifierIndentation: Enabled: false # "Use alias_method instead of alias" # We're fine with `alias`. Style/Alias: Enabled: false # "Avoid the use of the case equality operator ===" # We prefer using `Class#===` over `Object#is_a?` because `Class#===` # is less likely to be monkey patched than `is_a?` on a user object. Style/CaseEquality: Enabled: false # Warns when the class is excessively long. Metrics/ClassLength: Max: 100 Style/CollectionMethods: PreferredMethods: reduce: 'inject' # Over time we'd like to get this down, but this is what we're at now. Metrics/CyclomaticComplexity: Max: 10 # We use YARD to enforce documentation. It works better than rubocop's # enforcement...rubocop complains about the places we re-open # `RSpec::Expectations` and `RSpec::Matchers` w/o having doc commments. Style/Documentation: Enabled: false # We still support 1.8.7 which requires trailing dots Layout/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: Enabled: false # each_with_object is unavailable on 1.8.7 so we have to disable this one. Style/EachWithObject: Enabled: false Style/FormatString: EnforcedStyle: percent # As long as we support ruby 1.8.7 we have to use hash rockets. Style/HashSyntax: EnforcedStyle: hash_rockets # We can't use the new lambda syntax, since we still support 1.8.7. Style/Lambda: Enabled: false # Over time we'd like to get this down, but this is what we're at now. Layout/LineLength: Max: 100 # Over time we'd like to get this down, but this is what we're at now. Metrics/MethodLength: Max: 15 # Who cares what we call the argument for binary operator methods? Naming/BinaryOperatorParameterName: Enabled: false Style/PercentLiteralDelimiters: PreferredDelimiters: '%': () # double-quoted string '%i': '[]' # array of symbols '%q': () # single-quoted string '%Q': () # double-quoted string '%r': '{}' # regular expression pattern '%s': () # a symbol '%w': '[]' # array of single-quoted strings '%W': '[]' # array of double-quoted strings '%x': () # a shell command as a string # We have too many special cases where we allow generator methods or prefer a # prefixed predicate due to it's improved readability. Naming/PredicateName: Enabled: false # On 1.8 `proc` is `lambda`, so we use `Proc.new` to ensure we get real procs on all supported versions. # http://batsov.com/articles/2014/02/04/the-elements-of-style-in-ruby-number-12-proc-vs-proc-dot-new/ Style/Proc: Enabled: false # Exceptions should be rescued with `Support::AllExceptionsExceptOnesWeMustNotRescue` Lint/RescueException: Enabled: true # We haven't adopted the `fail` to signal exceptions vs `raise` for re-raises convention. Style/SignalException: Enabled: false # We've tended to use no space, so it's less of a change to stick with that. Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space # We don't care about single vs double qoutes. Style/StringLiterals: Enabled: false # This rule favors constant names from the English standard library which we don't load. Style/SpecialGlobalVars: Enabled: false Style/TrailingCommaInArrayLiteral: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingCommaInArguments: Enabled: false Style/TrivialAccessors: AllowDSLWriters: true AllowPredicates: true ExactNameMatch: true Style/ParallelAssignment: Enabled: false Layout/EmptyLineBetweenDefs: Enabled: false Layout/FirstParameterIndentation: Enabled: false Layout/ParameterAlignment: EnforcedStyle: with_first_parameter Layout/SpaceInsideBlockBraces: Enabled: false Layout/SpaceInsideParens: Enabled: false Naming/ConstantName: Enabled: false Style/ClassCheck: Enabled: false Style/ConditionalAssignment: Enabled: false Style/EmptyMethod: Enabled: false Style/FormatStringToken: Enabled: false Style/GuardClause: Enabled: false Style/IdenticalConditionalBranches: Enabled: false Style/IfUnlessModifier: Enabled: false Style/IfUnlessModifierOfIfUnless: Enabled: false Lint/MissingSuper: Enabled: false Style/MissingRespondToMissing: Enabled: false Style/MixinUsage: Enabled: false Style/MultipleComparison: Enabled: false Style/MutableConstant: Enabled: false Style/NestedModifier: Enabled: false Style/NestedParenthesizedCalls: Enabled: false Style/NumericPredicate: Enabled: false Style/RedundantParentheses: Enabled: false Style/StringLiteralsInInterpolation: Enabled: false Style/SymbolArray: Enabled: false Style/SymbolProc: Enabled: false Style/YodaCondition: Enabled: false Style/ZeroLengthPredicate: Enabled: false Layout/ClosingParenthesisIndentation: Enabled: false Layout/ExtraSpacing: Enabled: false Layout/MultilineMethodCallBraceLayout: Enabled: false Layout/MultilineMethodCallIndentation: Enabled: false Layout/MultilineOperationIndentation: Enabled: false Layout/SpaceAroundBlockParameters: Enabled: false Layout/SpaceAroundOperators: Enabled: false Layout/SpaceBeforeComma: Enabled: false Style/BlockDelimiters: Enabled: false Style/EmptyCaseCondition: Enabled: false Style/MultilineIfModifier: Enabled: false Style/RescueStandardError: Enabled: false Style/StderrPuts: Enabled: false Style/TernaryParentheses: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Layout/AssignmentIndentation: Enabled: false Layout/EmptyLineAfterMagicComment: Enabled: false Layout/FirstArrayElementIndentation: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/SpaceInsidePercentLiteralDelimiters: Enabled: false Style/EmptyElse: Enabled: false Style/IfInsideElse: Enabled: false Style/RedundantReturn: Enabled: false Style/StructInheritance: Enabled: false Naming/VariableNumber: Enabled: false Layout/SpaceInsideStringInterpolation: Enabled: false Style/DateTime: Enabled: false Style/ParenthesesAroundCondition: Enabled: false Layout/EmptyLinesAroundBlockBody: Enabled: false Lint/ImplicitStringConcatenation: Enabled: false Lint/NestedMethodDefinition: Enabled: false Style/RegexpLiteral: Enabled: false Style/TrailingUnderscoreVariable: Enabled: false Layout/EmptyLinesAroundAccessModifier: Enabled: false ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/ISSUE_TEMPLATE.md0000664000000000000000000000103114566142077022125 0ustar rootroot ### Subject of the issue ### Your environment * Ruby version: * rspec-support version: ### Steps to reproduce ### Expected behavior ### Actual behavior ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/DEVELOPMENT.md0000664000000000000000000001153014566142077021531 0ustar rootroot # Development Setup Generally speaking, you only need to clone the project and install the dependencies with [Bundler](https://bundler.io/). You can either get a full RSpec development environment using [rspec-dev](https://github.com/rspec/rspec-dev#README) or you can set this project up individually. ## Setting up rspec-support individually For most contributors, setting up the project individually will be simpler. Unless you have a specific reason to use rspec-dev, we recommend using this approach. Clone the repo: ``` $ git clone git@github.com:rspec/rspec-support.git ``` Install the dependencies using [Bundler](https://bundler.io/): ``` $ cd rspec-support $ bundle install ``` To minimize boot time and to ensure we don't depend upon any extra dependencies loaded by Bundler, our CI builds avoid loading Bundler at runtime by using Bundler's [`--standalone option`](https://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone). While not strictly necessary (many/most of our contributors do not do this!), if you want to exactly reproduce our CI builds you'll want to do the same: ``` $ bundle install --standalone --binstubs ``` The `--binstubs` option creates the `bin/rspec` file that, like `bundle exec rspec`, will load all the versions specified in `Gemfile.lock` without loading bundler at runtime! ## Using rspec-dev See the [rspec-dev README](https://github.com/rspec/rspec-dev#README) for setup instructions. The rspec-dev project contains many rake tasks for helping manage an RSpec development environment, making it easy to do things like: * Change branches across all repos * Update all repos with the latest code from `main` * Cut a new release across all repos * Push out updated build scripts to all repos These sorts of tasks are essential for the RSpec maintainers but will probably be unnecessary complexity if you're just contributing to one repository. If you are getting setup to make your first contribution, we recommend you take the simpler route of setting up rspec-support individually. ## Gotcha: Version mismatch from sibling repos The [Gemfile](Gemfile) is designed to be flexible and support using the other RSpec repositories either from a local sibling directory (e.g. `../rspec-`) or, if there is no such directory, directly from git. This generally does the "right thing", but can be a gotcha in some situations. For example, if you are setting up `rspec-core`, and you happen to have an old clone of `rspec-expectations` in a sibling directory, it'll be used even though it might be months or years out of date, which can cause confusing failures. To avoid this problem, you can either `export USE_GIT_REPOS=1` to force the use of `:git` dependencies instead of local dependencies, or update the code in the sibling directory. rspec-dev contains rake tasks to help you keep all repos in sync. ## Extra Gems If you need additional gems for any tasks---such as `benchmark-ips` for benchmarking or `byebug` for debugging---you can create a `Gemfile-custom` file containing those gem declarations. The `Gemfile` evaluates that file if it exists, and it is git-ignored. # Running the build The [Travis CI build](https://travis-ci.org/rspec/rspec-support) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` See [build detail](BUILD_DETAIL.md) for more detail. # What to Expect To ensure high, uniform code quality, all code changes (including changes from the maintainers!) are subject to a pull request code review. We'll often ask for clarification or suggest alternate ways to do things. Our code reviews are intended to be a two-way conversation. Here's a short, non-exhaustive checklist of things we typically ask contributors to do before PRs are ready to merge. It can help get your PR merged faster if you do these in advance! - [ ] New behavior is covered by tests and all tests are passing. - [ ] No Ruby warnings are issued by your changes. - [ ] Documentation reflects changes and renders as intended. - [ ] RuboCop passes (e.g. `bundle exec rubocop lib`). - [ ] Commits are squashed into a reasonable number of logical changesets that tell an easy-to-follow story. - [ ] No changelog entry is necessary (we'll add it as part of the merge process!) # Adding Docs RSpec uses [YARD](https://yardoc.org/) for its API documentation. To ensure the docs render well, we recommend running a YARD server and viewing your edits in a browser. To run a YARD server: ``` $ bundle exec yard server --reload # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard server --reload ``` Then navigate to `localhost:8808` to view the rendered docs. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/0000775000000000000000000000000014566142077021542 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/caller.rb0000664000000000000000000000451014566142077023331 0ustar rootroot$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__)) require 'benchmark' require 'rspec/support/caller_filter' n = 10000 puts "#{n} times - ruby #{RUBY_VERSION}" puts puts "* Using a chunked fetch is quicker than the old method of array-access." Benchmark.bm(20) do |bm| bm.report("CallerFilter") do n.times do RSpec::CallerFilter.first_non_rspec_line end end bm.report("Direct caller access") do n.times do caller(1)[4] end end end puts puts "* Chunking fetches of caller adds a ~17% overhead." Benchmark.bm(20) do |bm| bm.report("Chunked") do n.times do caller(1, 2) caller(3, 2) caller(5, 2) end end bm.report("All at once") do n.times do caller(1, 6) end end end puts puts "* `caller` scales linearly with length parameter." Benchmark.bm(20) do |bm| (1..10).each do |x| bm.report(x) do n.times do caller(1, x) end end end end # > ruby benchmarks/caller.rb # 10000 times - ruby 2.0.0 # # * Using a chunked fetch is quicker than the old method of array-access. # user system total real # CallerFilter 0.140000 0.010000 0.150000 ( 0.145381) # Direct caller access 0.170000 0.000000 0.170000 ( 0.180610) # # * Chunking fetches of caller adds a ~17% overhead. # user system total real # Chunked 0.150000 0.000000 0.150000 ( 0.181162) # All at once 0.130000 0.010000 0.140000 ( 0.138732) # # * `caller` scales linearly with length parameter. # user system total real # 1 0.030000 0.000000 0.030000 ( 0.035000) # 2 0.050000 0.000000 0.050000 ( 0.059879) # 3 0.080000 0.000000 0.080000 ( 0.098468) # 4 0.090000 0.010000 0.100000 ( 0.097619) # 5 0.110000 0.000000 0.110000 ( 0.126220) # 6 0.130000 0.000000 0.130000 ( 0.136739) # 7 0.150000 0.000000 0.150000 ( 0.159055) # 8 0.160000 0.010000 0.170000 ( 0.172416) # 9 0.180000 0.000000 0.180000 ( 0.203038) # 10 0.200000 0.000000 0.200000 ( 0.210551) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/skip_frames_for_caller_filter.rb0000664000000000000000000000146514566142077030135 0ustar rootrootrequire 'rspec/support/caller_filter' eval <<-EOS, binding, "/lib/rspec/core/some_file.rb", 1 # make it think this code is in rspec-core class Recurser def self.recurse(times, *args) return RSpec::CallerFilter.first_non_rspec_line(*args) if times.zero? recurse(times - 1, *args) end end EOS # Ensure the correct first_non_rspec_line is found in these cases. puts Recurser.recurse(20, 19) puts Recurser.recurse(20) require 'benchmark/ips' Benchmark.ips do |x| x.report("(no args)") { Recurser.recurse(20) } x.report("(19)") { Recurser.recurse(20, 19) } x.report("(19, 2)") { Recurser.recurse(20, 19, 2) } end __END__ (no args) 13.789k (± 7.8%) i/s - 69.377k (19) 55.410k (± 8.4%) i/s - 275.123k (19, 2) 61.076k (± 8.6%) i/s - 303.637k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/map_hash.rb0000664000000000000000000000360414566142077023652 0ustar rootrootrequire 'benchmark/ips' def use_map_and_hash_bracket(input) Hash[ input.map { |k, v| [k.to_s, v.to_s] } ] end def use_inject(input) input.inject({}) do |hash, (k, v)| hash[k.to_s] = v.to_s hash end end [10, 100, 1000].each do |size| hash = Hash[1.upto(size).map { |i| [i, i] }] unless use_map_and_hash_bracket(hash) == use_inject(hash) raise "Not the same!" end puts puts "A hash of #{size} pairs" Benchmark.ips do |x| x.report("Use map and Hash[]") { use_map_and_hash_bracket(hash) } x.report("Use inject") { use_inject(hash) } x.compare! end end __END__ `inject` appears to be slightly faster. A hash of 10 pairs Calculating ------------------------------------- Use map and Hash[] 8.742k i/100ms Use inject 9.565k i/100ms ------------------------------------------------- Use map and Hash[] 98.220k (± 6.8%) i/s - 489.552k Use inject 110.130k (± 6.1%) i/s - 554.770k Comparison: Use inject: 110129.9 i/s Use map and Hash[]: 98219.8 i/s - 1.12x slower A hash of 100 pairs Calculating ------------------------------------- Use map and Hash[] 1.080k i/100ms Use inject 1.124k i/100ms ------------------------------------------------- Use map and Hash[] 10.931k (± 4.5%) i/s - 55.080k Use inject 11.494k (± 5.0%) i/s - 57.324k Comparison: Use inject: 11494.4 i/s Use map and Hash[]: 10930.7 i/s - 1.05x slower A hash of 1000 pairs Calculating ------------------------------------- Use map and Hash[] 106.000 i/100ms Use inject 111.000 i/100ms ------------------------------------------------- Use map and Hash[] 1.081k (± 5.1%) i/s - 5.406k Use inject 1.111k (± 4.8%) i/s - 5.550k Comparison: Use inject: 1111.2 i/s Use map and Hash[]: 1080.8 i/s - 1.03x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/caller_vs_caller_locations_vs_raise.rb0000664000000000000000000001250714566142077031336 0ustar rootroot# This benchmark arose from rspec/rspec-support#199 where we experimented with # faster ways of generating / capturing a backtrace and whether it made sense # to lazily generate it using `raise` to capture the backtrace via an exception. # See also rspec/rspec-mocks#937 require 'benchmark/ips' def use_raise_to_capture_caller use_raise_lazily.backtrace end def use_raise_lazily raise "nope" rescue StandardError => exception return exception end def create_stack_trace(n, &block) return create_stack_trace(n - 1, &block) if n > 0 yield end [10, 50, 100].each do |frames| puts "-" * 80 puts "With #{frames} extra stack frames" puts "-" * 80 create_stack_trace(frames) do Benchmark.ips do |x| x.report("caller() ") { caller } x.report("caller_locations() ") { caller_locations } x.report("raise with backtrace ") { use_raise_to_capture_caller } x.report("raise and store (lazy)") { use_raise_lazily } x.report("caller(1, 2) ") { caller(1, 2) } x.report("caller_locations(1, 2)") { caller_locations(1, 2) } x.compare! end end end __END__ -------------------------------------------------------------------------------- With 10 extra stack frames -------------------------------------------------------------------------------- Calculating ------------------------------------- caller() 5.583k i/100ms caller_locations() 14.540k i/100ms raise with backtrace 4.544k i/100ms raise and store (lazy) 27.028k i/100ms caller(1, 2) 25.739k i/100ms caller_locations(1, 2) 48.848k i/100ms ------------------------------------------------- caller() 61.386k (±11.6%) i/s - 307.065k caller_locations() 176.033k (±12.8%) i/s - 872.400k raise with backtrace 48.348k (±10.5%) i/s - 240.832k raise and store (lazy) 425.768k (±10.7%) i/s - 2.108M caller(1, 2) 368.142k (±18.9%) i/s - 1.776M caller_locations(1, 2) 834.431k (±17.8%) i/s - 4.054M Comparison: caller_locations(1, 2): 834431.2 i/s raise and store (lazy): 425767.6 i/s - 1.96x slower caller(1, 2) : 368142.0 i/s - 2.27x slower caller_locations() : 176032.6 i/s - 4.74x slower caller() : 61386.0 i/s - 13.59x slower raise with backtrace : 48348.2 i/s - 17.26x slower -------------------------------------------------------------------------------- With 50 extra stack frames -------------------------------------------------------------------------------- Calculating ------------------------------------- caller() 2.282k i/100ms caller_locations() 6.446k i/100ms raise with backtrace 2.138k i/100ms raise and store (lazy) 23.649k i/100ms caller(1, 2) 22.113k i/100ms caller_locations(1, 2) 36.586k i/100ms ------------------------------------------------- caller() 24.105k (± 9.9%) i/s - 120.946k caller_locations() 68.610k (± 7.9%) i/s - 341.638k raise with backtrace 21.458k (± 9.6%) i/s - 106.900k raise and store (lazy) 341.152k (± 8.1%) i/s - 1.703M caller(1, 2) 297.805k (±12.5%) i/s - 1.482M caller_locations(1, 2) 557.278k (±16.6%) i/s - 2.744M Comparison: caller_locations(1, 2): 557278.2 i/s raise and store (lazy): 341151.6 i/s - 1.63x slower caller(1, 2) : 297804.8 i/s - 1.87x slower caller_locations() : 68610.3 i/s - 8.12x slower caller() : 24105.5 i/s - 23.12x slower raise with backtrace : 21458.2 i/s - 25.97x slower -------------------------------------------------------------------------------- With 100 extra stack frames -------------------------------------------------------------------------------- Calculating ------------------------------------- caller() 1.327k i/100ms caller_locations() 3.773k i/100ms raise with backtrace 1.235k i/100ms raise and store (lazy) 19.990k i/100ms caller(1, 2) 18.269k i/100ms caller_locations(1, 2) 29.668k i/100ms ------------------------------------------------- caller() 13.879k (± 9.9%) i/s - 69.004k caller_locations() 39.070k (± 7.6%) i/s - 196.196k raise with backtrace 12.703k (±12.7%) i/s - 62.985k raise and store (lazy) 243.959k (± 8.3%) i/s - 1.219M caller(1, 2) 230.289k (± 8.2%) i/s - 1.151M caller_locations(1, 2) 406.804k (± 8.8%) i/s - 2.047M Comparison: caller_locations(1, 2): 406804.3 i/s raise and store (lazy): 243958.7 i/s - 1.67x slower caller(1, 2) : 230288.9 i/s - 1.77x slower caller_locations() : 39069.8 i/s - 10.41x slower caller() : 13879.4 i/s - 29.31x slower raise with backtrace : 12702.9 i/s - 32.02x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/ripper.rb0000664000000000000000000000177014566142077023375 0ustar rootrootrequire 'benchmark/ips' require 'ripper' ruby_version = defined?(JRUBY_VERSION) ? JRUBY_VERSION : RUBY_VERSION puts "#{RUBY_ENGINE} #{ruby_version}" source = File.read(__FILE__) Benchmark.ips do |x| x.report("Ripper") do Ripper.sexp(source) Ripper.lex(source) end end __END__ ruby 1.9.3 Calculating ------------------------------------- Ripper 284.000 i/100ms ruby 2.2.3 Calculating ------------------------------------- Ripper 320.000 i/100ms jruby 1.7.5 Calculating ------------------------------------- Ripper 24.000 i/100ms jruby 1.7.13 Calculating ------------------------------------- Ripper 25.000 i/100ms jruby 1.7.14 Calculating ------------------------------------- Ripper 239.000 i/100ms jruby 1.7.22 Calculating ------------------------------------- Ripper 231.000 i/100ms jruby 9.0.1.0 Calculating ------------------------------------- Ripper 218.000 i/100ms ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/caller_vs_caller_locations.rb0000664000000000000000000000112014566142077027430 0ustar rootrootrequire 'benchmark/ips' Benchmark.ips do |x| x.report("caller() ") { caller } x.report("caller_locations() ") { caller_locations } x.report("caller(1, 2) ") { caller(1, 2) } x.report("caller_locations(1, 2)") { caller_locations(1, 2) } end __END__ caller() 118.586k (±17.7%) i/s - 573.893k caller_locations() 355.988k (±17.8%) i/s - 1.709M caller(1, 2) 336.841k (±18.6%) i/s - 1.615M caller_locations(1, 2) 781.330k (±23.5%) i/s - 3.665M ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/benchmarks/class_exec_vs_klass_exec.rb0000664000000000000000000000227414566142077027116 0ustar rootrootrequire 'benchmark/ips' require 'rspec/support' require 'rspec/support/with_keywords_when_needed' Klass = Class.new do def test(*args, **kwargs) end end def class_exec_args Klass.class_exec(:a, :b) { } end def klass_exec_args RSpec::Support::WithKeywordsWhenNeeded.class_exec(Klass, :a, :b) { } end def class_exec_kw_args Klass.class_exec(a: :b) { |a:| } end def klass_exec_kw_args RSpec::Support::WithKeywordsWhenNeeded.class_exec(Klass, a: :b) { |a:| } end Benchmark.ips do |x| x.report("class_exec(*args) ") { class_exec_args } x.report("klass_exec(*args) ") { klass_exec_args } x.report("class_exec(*args, **kwargs)") { class_exec_kw_args } x.report("klass_exec(*args, **kwargs)") { klass_exec_kw_args } end __END__ Calculating ------------------------------------- class_exec(*args) 5.555M (± 1.6%) i/s - 27.864M in 5.017682s klass_exec(*args) 657.945k (± 4.6%) i/s - 3.315M in 5.051511s class_exec(*args, **kwargs) 2.882M (± 3.3%) i/s - 14.555M in 5.056905s klass_exec(*args, **kwargs) 52.710k (± 4.1%) i/s - 265.188k in 5.041218s ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/0000775000000000000000000000000014566142077020731 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/cucumber.sh0000775000000000000000000000034214566142077023074 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh run_cukes ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/run_build0000775000000000000000000000151714566142077022646 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "binstub check" check_binstubs fold "specs" run_specs_and_record_done if additional_specs_available; then fold "additional specs" run_additional_specs fi fold "cukes" run_cukes if documentation_enforced; then fold "doc check" check_documentation_coverage fi if supports_cross_build_checks; then fold "one-by-one specs" run_specs_one_by_one export NO_COVERAGE=true run_all_spec_suites else echo "Skipping the rest of the build on non-MRI rubies" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/update_rubygems_and_install_bundler0000775000000000000000000000123614566142077030143 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh if is_ruby_31_plus; then echo "Installing most recent rubygems / bundler" yes | gem update --no-document --system yes | gem install --no-document bundler elif is_ruby_23_plus; then echo "Installing rubygems 3.2.22 / bundler 2.2.22" yes | gem update --system '3.2.22' yes | gem install bundler -v '2.2.22' else echo "Warning installing older versions of Rubygems / Bundler" gem update --system '2.7.8' gem install bundler -v '1.17.3' fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/functions.sh0000664000000000000000000001411714566142077023301 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source $SCRIPT_DIR/ci_functions.sh source $SCRIPT_DIR/predicate_functions.sh # If JRUBY_OPTS isn't set, use these. export JRUBY_OPTS=${JRUBY_OPTS:-"--server -Xcompile.invokedynamic=false"} SPECS_HAVE_RUN_FILE=specs.out MAINTENANCE_BRANCH=`cat maintenance-branch` # Don't allow rubygems to pollute what's loaded. Also, things boot faster # without the extra load time of rubygems. Only works on MRI Ruby 1.9+ if is_mri_192_plus; then export RUBYOPT="--disable=gem" fi function clone_repo { if [ ! -d $1 ]; then # don't clone if the dir is already there if [ -z "$2" ]; then DIR_TARGET="$1" else DIR_TARGET="$2" fi if [ -z "$3" ]; then BRANCH_TO_CLONE="${MAINTENANCE_BRANCH?}"; else BRANCH_TO_CLONE="$3"; fi; ci_retry eval "git clone https://github.com/rspec/$1 --depth 1 --branch ${BRANCH_TO_CLONE?} ${DIR_TARGET?}" fi; } function run_specs_and_record_done { local rspec_bin=bin/rspec # rspec-core needs to run with a special script that loads simplecov first, # so that it can instrument rspec-core's code before rspec-core has been loaded. if [ -f script/rspec_with_simplecov ] && is_mri; then rspec_bin=script/rspec_with_simplecov fi; echo "${PWD}/bin/rspec" $rspec_bin spec --backtrace --format progress --profile --format progress --out $SPECS_HAVE_RUN_FILE } function run_cukes { if [ -d features ]; then # 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 # # Note that we delay setting this until we run the cukes because we've seen # spec failures in our spec suite due to problems with this mode. export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "${PWD}/bin/cucumber" if is_mri_192; then # For some reason we get SystemStackError on 1.9.2 when using # the bin/cucumber approach below. That approach is faster # (as it avoids the bundler tax), so we use it on rubies where we can. bundle exec cucumber --strict elif is_jruby; then # For some reason JRuby doesn't like our improved bundler setup RUBYOPT="-I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict else # Prepare RUBYOPT for scenarios that are shelling out to ruby, # and PATH for those that are using `rspec` or `rake`. RUBYOPT="${RUBYOPT} -I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict fi fi } function run_specs_one_by_one { echo "Running each spec file, one-by-one..." for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done } function run_spec_suite_for { if [ ! -f ../$1/$SPECS_HAVE_RUN_FILE ]; then # don't rerun specs that have already run if [ -d ../$1 ]; then echo "Running specs for $1" pushd ../$1 unset BUNDLE_GEMFILE bundle_install_flags=`cat .github/workflows/ci.yml | grep "bundle install" | sed 's/.* bundle install//'` ci_retry eval "(unset RUBYOPT; exec bundle install $bundle_install_flags)" ci_retry eval "(unset RUBYOPT; exec bundle binstubs --all)" run_specs_and_record_done popd else echo "" echo "WARNING: The ../$1 directory does not exist. Usually the" echo "build cds into that directory and run the specs to ensure" echo "the specs still pass with your latest changes, but we are" echo "going to skip that step." echo "" fi; fi; } function check_binstubs { echo "Checking required binstubs" local success=0 local binstubs="" local gems="" if [ ! -x ./bin/rspec ]; then binstubs="$binstubs bin/rspec" gems="$gems rspec-core" success=1 fi if [ ! -x ./bin/rake ]; then binstubs="$binstubs bin/rake" gems="$gems rake" success=1 fi if [ -d features ]; then if [ ! -x ./bin/cucumber ]; then binstubs="$binstubs bin/cucumber" gems="$gems cucumber" success=1 fi fi if [ $success -eq 1 ]; then echo echo "Missing binstubs:$binstubs" echo "Install missing binstubs using one of the following:" echo echo " # Create the missing binstubs" echo " $ bundle binstubs$gems" echo echo " # To binstub all gems" echo " $ bundle binstubs --all" fi return $success } function check_documentation_coverage { echo "bin/yard stats --list-undoc" bin/yard stats --list-undoc | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') coverage ||= line[/([\d\.]+)% documented/, 1] puts line end unless Float(coverage) == 100 puts \"\n\nMissing documentation coverage (currently at #{coverage}%)\" exit(1) end if has_warnings puts \"\n\nYARD emitted documentation warnings.\" exit(1) end " # Some warnings only show up when generating docs, so do that as well. bin/yard doc --no-cache | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') has_errors ||= line.start_with?('[error]:') puts line end if has_warnings || has_errors puts \"\n\nYARD emitted documentation warnings or errors.\" exit(1) end " } function check_style_and_lint { echo "bin/rubocop lib" eval "(unset RUBYOPT; exec bin/rubocop lib)" } function run_all_spec_suites { fold "rspec-core specs" run_spec_suite_for "rspec-core" fold "rspec-expectations specs" run_spec_suite_for "rspec-expectations" fold "rspec-mocks specs" run_spec_suite_for "rspec-mocks" if rspec_rails_compatible; then if ! is_ruby_27_plus; then export RAILS_VERSION='~> 6.1.0' fi fold "rspec-rails specs" run_spec_suite_for "rspec-rails" fi if rspec_support_compatible; then fold "rspec-support specs" run_spec_suite_for "rspec-support" fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/legacy_setup.sh0000775000000000000000000000077214566142077023762 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh bundle install --standalone --binstubs --without coverage documentation if [ -x ./bin/rspec ]; then echo "RSpec bin detected" else if [ -x ./exe/rspec ]; then cp ./exe/rspec ./bin/rspec echo "RSpec restored from exe" else echo "No RSpec bin available" exit 1 fi fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/ci_functions.sh0000664000000000000000000000244714566142077023757 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. # Taken from: # https://github.com/travis-ci/travis-build/blob/e9314616e182a23e6a280199cd9070bfc7cae548/lib/travis/build/script/templates/header.sh#L34-L53 ci_retry() { local result=0 local count=1 while [ $count -le 3 ]; do [ $result -ne 0 ] && { echo -e "\n\033[33;1mThe command \"$@\" failed. Retrying, $count of 3.\033[0m\n" >&2 } "$@" result=$? [ $result -eq 0 ] && break count=$(($count + 1)) sleep 1 done [ $count -eq 3 ] && { echo "\n\033[33;1mThe command \"$@\" failed 3 times.\033[0m\n" >&2 } return $result } # Taken from https://github.com/vcr/vcr/commit/fa96819c92b783ec0c794f788183e170e4f684b2 # and https://github.com/vcr/vcr/commit/040aaac5370c68cd13c847c076749cd547a6f9b1 nano_cmd="$(type -p gdate date | head -1)" nano_format="+%s%N" [ "$(uname -s)" != "Darwin" ] || nano_format="${nano_format/%N/000000000}" fold() { local name="$1" local status=0 shift 1 echo "============= Starting $name ===============" "$@" status=$? if [ "$status" -eq 0 ]; then echo "============= Ending $name ===============" else STATUS="$status" fi return $status } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/predicate_functions.sh0000664000000000000000000000555114566142077025323 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. function is_mri { if ruby -e "exit(!defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_ruby_head { # This checks for the presence of our CI's ruby-head env variable if [ -z ${RUBY_HEAD+x} ]; then return 1 else return 0 fi; } function supports_cross_build_checks { if is_mri; then # We don't run cross build checks on ruby-head if is_ruby_head; then return 1 else return 0 fi else return 1 fi } function is_jruby { if ruby -e "exit(defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_mri_192 { if is_mri; then if ruby -e "exit(RUBY_VERSION == '1.9.2')"; then return 0 else return 1 fi else return 1 fi } function is_mri_192_plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 1.8)"; then return 0 else return 1 fi else return 1 fi } function is_mri_2plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 2.0)"; then return 0 else return 1 fi else return 1 fi } function is_ruby_23_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.3)"; then return 0 else return 1 fi } function is_ruby_25_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.5)"; then return 0 else return 1 fi } function is_ruby_27_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.7)"; then return 0 else return 1 fi } function is_ruby_31_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 3.1)"; then return 0 else return 1 fi } function rspec_rails_compatible { if is_ruby_25_plus; then # TODO remove when RSpec-Rails build is 3.1 safe by default if is_ruby_31_plus; then return 1 else return 0 fi else return 1 fi } function rspec_support_compatible { if [ "$MAINTENANCE_BRANCH" != "2-99-maintenance" ] && [ "$MAINTENANCE_BRANCH" != "2-14-maintenance" ]; then return 0 else return 1 fi } function additional_specs_available { type run_additional_specs > /dev/null 2>&1 return $? } function documentation_enforced { if [ -x ./bin/yard ]; then if is_mri_2plus; then return 0 else return 1 fi else return 1 fi } function style_and_lint_enforced { if is_ruby_head; then return 1 else if [ -x ./bin/rubocop ]; then return 0 else return 1 fi fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/run_rubocop0000775000000000000000000000063614566142077023221 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "rubocop" check_style_and_lint ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/script/clone_all_rspec_repos0000775000000000000000000000114614566142077025215 0ustar rootroot#!/bin/bash # This file was generated on 2024-02-23T14:21:37+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. set -e source script/functions.sh if is_mri; then pushd .. clone_repo "rspec-metagem" "rspec" clone_repo "rspec-core" clone_repo "rspec-expectations" clone_repo "rspec-mocks" clone_repo "rspec-rails" "rspec-rails" "6-1-maintenance" if rspec_support_compatible; then clone_repo "rspec-support" fi popd else echo "Not cloning all repos since we are not on MRI and they are only needed for the MRI build" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/LICENSE.md0000664000000000000000000000222514566142077021032 0ustar rootrootThe MIT License (MIT) ==================== * Copyright © 2013 David Chelimsky, Myron Marston, Jon Rowe, Sam Phippen, Xavier Shay, Bradley Schaefer 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. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.rubocop.yml0000664000000000000000000000166514566142077021707 0ustar rootrootinherit_from: - .rubocop_rspec_base.yml - .rubocop_todo.yml # Over time we'd like to get this down, but this is what we're at now. Metrics/AbcSize: Max: 28 # Over time we'd like to get this down, but this is what we're at now. Metrics/BlockLength: Max: 86 Exclude: - spec/**/* # Over time we'd like to get this down, but this is what we're at now. Metrics/PerceivedComplexity: Max: 10 Security/MarshalLoad: Exclude: - 'lib/rspec/support/spec/in_sub_process.rb' Style/EvalWithLocation: Exclude: # eval is only used here to check syntax - 'lib/rspec/support/ruby_features.rb' - 'benchmarks/skip_frames_for_caller_filter.rb' - 'spec/rspec/support/method_signature_verifier_spec.rb' Lint/AssignmentInCondition: Exclude: # The pattern makes sense here - 'lib/rspec/support/mutex.rb' Style/FrozenStringLiteralComment: Include: - lib/**/*.rb Layout/EmptyLineAfterMagicComment: Enabled: true ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/Changelog.md0000664000000000000000000003116714566142077021646 0ustar rootroot### Development [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.13.1...main) ### 3.13.1 / 2024-02-23 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.13.0...v3.13.1) Bug Fixes: * Exclude ruby internal require warnings from `RSpec::Support::CallerFilter#first_non_rspec_line`. (Jon Rowe, #593) ### 3.13.0 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.12.2...v3.13.0) Enchancements * Add `RubyFeatures#supports_syntax_suggest?`. (Jon Rowe, #571) ### 3.12.2 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.12.1...v3.12.2) Bug Fixes: * Properly surface errors from `in_sub_process`. (Jon Rowe, #575) * Add magic comment for freezing string literals. (Josh Nichols, #586) * Allow string keys for keyword arguments during verification of method signatures, (but only on Ruby 3+). (@malcolmohare, #591) ### 3.12.1 / 2023-06-26 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.12.0...v3.12.1) Bug Fixes: * Fix `RSpec::Support.thread_local_data` to be Thread local but not Fiber local. (Jon Rowe, #581) ### 3.12.0 / 2022-10-26 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.11.1...v3.12.0) Enhancements: * Add `RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash?` (Jean byroot Boussier, #535) ### 3.11.1 / 2022-09-12 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.11.0...v3.11.1) Bug Fixes: * Fix ripper detection on TruffleRuby. (Brandon Fish, #541) ### 3.11.0 / 2022-02-09 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.10.3...v3.11.0) No changes. Released to support other RSpec releases. ### 3.10.3 / 2021-11-03 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.10.2...v3.10.3) Bug Fixes: * Use `Mutex#owned?` to allow `RSpec::Support::ReentrantMutex` to work in nested Fibers on Ruby 3.0 and later. (Benoit Daloze, #503, #504) * Support `end`-less methods in `RSpec::Support::Source::Token` so that RSpec won't hang when an `end`-less method raises an error. (Yuji Nakayama, #505) ### 3.10.2 / 2021-01-28 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.10.1...v3.10.2) Bug Fixes: * Fix issue with `RSpec::Support.define_optimized_require_for_rspec` on JRuby 9.1.17.0 (Jon Rowe, #492) ### 3.10.1 / 2020-12-27 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.10.0...v3.10.1) Bug Fixes: * Fix deprecation expectations to fail correctly when asserting on messages. (Phil Pirozhkov, #453) ### 3.10.0 / 2020-10-30 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.9.4...v3.10.0) No changes. Released to support other RSpec releases. ### 3.9.4 / 2020-10-23 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.9.3...v3.9.4) Bug Fixes: * Flag ripper as supported on Truffle Ruby. (Brandon Fish, #427) * Prevent stubbing `File.read` from breaking source extraction. (Jon Rowe, #431) ### 3.9.3 / 2020-05-02 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.9.2...v3.9.3) Bug Fixes: * Mark ripper as unsupported on Truffle Ruby. (Brandon Fish, #395) * Mark ripper as unsupported on JRuby 9.2.0.0. (Brian Hawley, #400) * Capture `Mutex.new` for our `RSpec::Support:Mutex` in order to allow stubbing `Mutex.new`. (Jon Rowe, #411) ### 3.9.2 / 2019-12-30 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.9.1...v3.9.2) Bug Fixes: * Remove unneeded eval. (Matijs van Zuijlen, #394) ### 3.9.1 / 2019-12-28 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.9.0...v3.9.1) Bug Fixes: * Remove warning caused by keyword arguments on Ruby 2.7.0. (Jon Rowe, #392) ### 3.9.0 / 2019-10-07 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.8.3...v3.9.0) *NO CHANGES* Version 3.9.0 was released to allow other RSpec gems to release 3.9.0. ### 3.8.3 / 2019-10-02 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.8.2...v3.8.3) Bug Fixes: * Escape \r when outputting strings inside arrays. (Tomita Masahiro, Jon Rowe, #378) * Ensure that optional hash arguments are recognised correctly vs keyword arguments. (Evgeni Dzhelyov, #366) ### 3.8.2 / 2019-06-10 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.8.1...v3.8.2) Bug Fixes: * Ensure that an empty hash is recognised as empty keyword arguments when applicable. (Thomas Walpole, #375) * Ensure that diffing truthy values produce diffs consistently. (Lucas Nestor, #377) ### 3.8.1 / 2019-03-03 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.8.0...v3.8.1) Bug Fixes: * Ensure that inspecting a `SimpleDelegator` based object works regardless of visibility of the `__getobj__` method. (Jon Rowe, #369) ### 3.8.0 / 2018-08-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.7.1...v3.8.0) Bug Fixes: * Order hash keys before diffing to improve diff accuracy when using mocked calls. (James Crisp, #334) ### 3.7.1 / 2018-01-29 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.7.0...v3.7.1) Bug Fixes: * Fix source extraction logic so that it does not trigger a `SystemStackError` when processing deeply nested example groups. (Craig Bass, #343) ### 3.7.0 / 2017-10-17 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.6.0...v3.7.0) Enhancements: * Improve compatibility with `--enable-frozen-string-literal` option on Ruby 2.3+. (Pat Allan, #320) * Add `Support.class_of` for extracting class of any object. (Yuji Nakayama, #325) Bug Fixes: * Fix recursive const support to not blow up when given buggy classes that raise odd errors from `#to_str`. (Myron Marston, #317) ### 3.6.0 / 2017-05-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.6.0.beta2...3.6.0) Enhancements: * Import `Source` classes from rspec-core. (Yuji Nakayama, #315) ### 3.6.0.beta2 / 2016-12-12 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.6.0.beta1...v3.6.0.beta2) No user-facing changes. ### 3.6.0.beta1 / 2016-10-09 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0...v3.6.0.beta1) Bug Fixes: * Prevent truncated formatted object output from mangling console codes. (#294, Anson Kelly) ### 3.5.0 / 2016-07-01 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0.beta4...v3.5.0) **No user facing changes since beta4** ### 3.5.0.beta4 / 2016-06-05 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0.beta3...v3.5.0.beta4) Enhancements: * Improve `MethodSignature` to better support keyword arguments. (#250, Rob Smith). ### 3.5.0.beta3 / 2016-04-02 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0.beta2...v3.5.0.beta3) Bug Fixes: * Fix `EncodedString` to properly handle the behavior of `String#split` on JRuby when the string contains invalid bytes. (Jon Rowe, #268) * Fix `ObjectFormatter` so that formatting objects that don't respond to `#inspect` (such as `BasicObject`) does not cause `NoMethodError`. (Yuji Nakayama, #269) * Fix `ObjectFormatter` so that formatting recursive array or hash does not cause `SystemStackError`. (Yuji Nakayama, #270, #272) ### 3.5.0.beta2 / 2016-03-10 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.5.0.beta1...v3.5.0.beta2) No user-facing changes. ### 3.5.0.beta1 / 2016-02-06 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.4.1...v3.5.0.beta1) Enhancements: * Improve formatting of objects by allowing truncation to a pre-configured length. (Liam M, #256) ### 3.4.1 / 2015-11-20 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.4.0...v3.4.1) Bug Fixes: * Fix `RSpec::Support::RubyFeature.ripper_supported?` so it returns `false` on Rubinius since the Rubinius team has no plans to support it. This prevents rspec-core from trying to load and use ripper to extract failure snippets. (Aaron Stone, #251) Changes: * Remove `VersionChecker` in favor of `ComparableVersion`. (Yuji Nakayama, #266) ### 3.4.0 / 2015-11-11 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.3.0...v3.4.0) Enhancements: * Improve formatting of `Delegator` based objects (e.g. `SimpleDelegator`) in failure messages and diffs. (Andrew Horner, #215) * Add `ComparableVersion`. (Yuji Nakayama, #245) * Add `Ripper` support detection. (Yuji Nakayama, #245) Bug Fixes: * Work around bug in JRuby that reports that `attr_writer` methods have no parameters, causing RSpec's verifying doubles to wrongly fail when mocking or stubbing a writer method on JRuby. (Myron Marston, #225) ### 3.3.0 / 2015-06-12 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.2...v3.3.0) Enhancements: * Improve formatting of arrays and hashes in failure messages so they use our custom formatting of matchers, time objects, etc. (Myron Marston, Nicholas Chmielewski, #205) * Use improved formatting for diffs as well. (Nicholas Chmielewski, #205) Bug Fixes: * Fix `FuzzyMatcher` so that it checks `expected == actual` rather than `actual == expected`, which avoids errors in situations where the `actual` object's `==` is improperly implemented to assume that only objects of the same type will be given. This allows rspec-mocks' `anything` to match against objects with buggy `==` definitions. (Myron Marston, #193) ### 3.2.2 / 2015-02-23 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.1...v3.2.2) Bug Fixes: * Fix an encoding issue with `EncodedString#split` when encountering an invalid byte string. (Benjamin Fleischer, #1760) ### 3.2.1 / 2015-02-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.2.0...v3.2.1) Bug Fixes: * Fix `RSpec::CallerFilter` to work on Rubinius 2.2. (Myron Marston, #169) ### 3.2.0 / 2015-02-03 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.2...v3.2.0) Enhancements: * Add extra Ruby type detection. (Jon Rowe, #133) * Make differ instance re-usable. (Alexey Fedorov, #160) Bug Fixes: * Do not consider `[]` and `{}` to match when performing fuzzy matching. (Myron Marston, #157) ### 3.1.2 / 2014-10-08 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.1...v3.1.2) Bug Fixes: * Fix method signature to not blow up with a `NoMethodError` on 1.8.7 when verifying against an RSpec matcher. (Myron Marston, #116) ### 3.1.1 / 2014-09-26 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.1.0...v3.1.1) Bug Fixes: * Fix `RSpec::Support::DirectoryMaker` (used by `rspec --init` and `rails generate rspec:install`) so that it detects absolute paths on Windows properly. (Scott Archer, #107, #108, #109) (Jon Rowe, #110) ### 3.1.0 / 2014-09-04 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.4...v3.1.0) Bug Fixes: * Fix `FuzzyMatcher` so that it does not wrongly match a struct against an array. (Myron Marston, #97) * Prevent infinitely recursing `#flatten` methods from causing the differ to hang. (Jon Rowe, #101) ### 3.0.4 / 2014-08-14 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.3...v3.0.4) Bug Fixes: * Fix `FuzzyMatcher` so that it does not silence `ArgumentError` raised from broken implementations of `==`. (Myron Marston, #94) ### 3.0.3 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.2...v3.0.3) Bug Fixes: * Fix regression in `Support#method_handle_for` where proxy objects with method delegated would wrongly not return a method handle. (Jon Rowe, #90) * Properly detect Module#prepend support in Ruby 2.1+ (Ben Langfeld, #91) * Fix `rspec/support/warnings.rb` so it can be loaded and used in isolation. (Myron Marston, #93) ### 3.0.2 / 2014-06-20 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.1...v3.0.2) * Revert `BlockSignature` change from 3.0.1 because of a ruby bug that caused it to change the block's behavior (https://bugs.ruby-lang.org/issues/9967). (Myron Marston, rspec-mocks#721) ### 3.0.1 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0...v3.0.1) * Fix `BlockSignature` so that it correctly differentiates between required and optional block args. (Myron Marston, rspec-mocks#714) ### 3.0.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.rc1...v3.0.0) ### 3.0.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta2...v3.0.0.rc1) ### 3.0.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta1...v3.0.0.beta2) Bug Fixes: * Issue message when :replacement is passed to `RSpec.warn_with`. (Jon Rowe) ### 3.0.0.beta1 / 2013-11-07 [Full Changelog](https://github.com/rspec/rspec-support/compare/0dc12d1bdbbacc757a9989f8c09cd08ef3a4837e...v3.0.0.beta1) Initial release. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/CODE_OF_CONDUCT.md0000664000000000000000000000544414566142077022233 0ustar rootroot # Contributor Code of Conduct For the purpose of building a welcoming, harassment-free community that values contributions from anyone, the RSpec project has adopted the following code of conduct. All contributors and participants (including maintainers!) are expected to abide by its terms. As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the project maintainers listed at https://rspec.info/about/. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/3/0/ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/Gemfile0000664000000000000000000000435114566142077020723 0ustar rootrootsource 'https://rubygems.org' # Specify your gem's dependencies in rspec-support.gemspec gemspec branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp %w[rspec rspec-core rspec-expectations rspec-mocks].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path else if lib == 'rspec' gem 'rspec', :git => "https://github.com/rspec/rspec-metagem.git", :branch => branch else gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end end if RUBY_VERSION < '1.9.3' gem 'rake', '< 11.0.0' # rake 11 requires Ruby 1.9.3 or later elsif RUBY_VERSION < '2.0.0' gem 'rake', '< 12.0.0' # rake 12 requires Ruby 2.0.0 or later else gem 'rake', '>= 12.3.3' end if ENV['DIFF_LCS_VERSION'] gem 'diff-lcs', ENV['DIFF_LCS_VERSION'] else gem 'diff-lcs', '~> 1.4', '>= 1.4.3' end if RUBY_VERSION >= '3.3.0' # This is being extracted in Ruby 3.4 and issues a warning on 3.3 gem 'bigdecimal', :require => false end if RUBY_VERSION < '2.3.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.0.0' gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.3.0' gem "childprocess", "< 3.0.0" else gem "childprocess", ">= 3.0.0" end group :coverage do ### dep for ci/coverage gem 'simplecov', '~> 0.8' end if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java' gem 'json', '< 2.0.0' # is a dependency of simplecov else gem 'json', '> 2.3.0' end if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.10' elsif RUBY_VERSION < '2.4.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.15' elsif RUBY_VERSION < '2.0' # ffi dropped Ruby 1.8 support in 1.9.19 and Ruby 1.9 support in 1.11.0 gem 'ffi', '< 1.9.19' elsif RUBY_VERSION < '2.3.0' gem 'ffi', '~> 1.12.0' else gem 'ffi', '~> 1.13.0' end # No need to run rubocop on earlier versions if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' gem 'rubocop', "~> 1.0", "< 1.12" end eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom') ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/REPORT_TEMPLATE.md0000664000000000000000000000211714566142077022256 0ustar rootroot # Report template ```ruby # frozen_string_literal: true begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "rspec", "3.7.0" # Activate the gem and version you are reporting the issue against. end puts "Ruby version is: #{RUBY_VERSION}" require 'rspec/autorun' RSpec.describe 'additions' do it 'returns 2' do expect(1 + 1).to eq(2) end it 'returns 1' do expect(3 - 1).to eq(-1) end end ``` Simply copy the content of the appropriate template into a `.rb` file on your computer and make the necessary changes to demonstrate the issue. You can execute it by running `ruby rspec_report.rb` in your terminal. You can then share your executable test case as a [gist](https://gist.github.com), or simply paste the content into the issue description. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.rspec0000664000000000000000000000006114566142077020537 0ustar rootroot--order random --color --warnings -r spec_helper ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.rubocop_todo.yml0000664000000000000000000003006014566142077022723 0ustar rootroot# This configuration was generated by # `rubocop --auto-gen-config` # on 2022-01-09 17:43:27 UTC using RuboCop version 1.11.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 # Configuration parameters: Include. # Include: **/*.gemspec Gemspec/RequiredRubyVersion: Exclude: - 'rspec-support.gemspec' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: with_first_argument, with_fixed_indentation Layout/ArgumentAlignment: Exclude: - 'spec/rspec/support_spec.rb' # Offense count: 17 # Cop supports --auto-correct. Layout/EmptyLineAfterGuardClause: Exclude: - 'benchmarks/caller_vs_caller_locations_vs_raise.rb' - 'lib/rspec/support.rb' - 'lib/rspec/support/differ.rb' - 'lib/rspec/support/method_signature_verifier.rb' - 'lib/rspec/support/mutex.rb' - 'lib/rspec/support/recursive_const_methods.rb' - 'lib/rspec/support/reentrant_mutex.rb' - 'lib/rspec/support/source.rb' - 'lib/rspec/support/source/location.rb' - 'lib/rspec/support/source/token.rb' - 'lib/rspec/support/spec/library_wide_checks.rb' - 'lib/rspec/support/spec/stderr_splitter.rb' # Offense count: 3 # Cop supports --auto-correct. Layout/EmptyLines: Exclude: - 'benchmarks/caller.rb' - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: AllowAliasSyntax, AllowedMethods. # AllowedMethods: alias_method, public, protected, private Layout/EmptyLinesAroundAttributeAccessor: Exclude: - 'spec/rspec/support/fuzzy_matcher_spec.rb' - 'spec/rspec/support/method_signature_verifier_spec.rb' # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table # SupportedColonStyles: key, separator, table # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit Layout/HashAlignment: Exclude: - 'lib/rspec/support/source/token.rb' - 'rspec-support.gemspec' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: normal, indented_internal_methods Layout/IndentationConsistency: Exclude: - 'spec/rspec/support/differ_spec.rb' # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: Width, IgnoredPatterns. Layout/IndentationWidth: Exclude: - 'lib/rspec/support/method_signature_verifier.rb' - 'lib/rspec/support/ruby_features.rb' # Offense count: 50 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Layout/LineLength: Max: 156 # Offense count: 13 # Cop supports --auto-correct. Layout/SpaceAfterComma: Exclude: - 'rspec-support.gemspec' - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: space, no_space Layout/SpaceAroundEqualsInParameterDefault: Exclude: - 'spec/rspec/support/encoded_string_spec.rb' - 'spec/rspec/support/method_signature_verifier_spec.rb' # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBrackets: space, no_space Layout/SpaceInsideArrayLiteralBrackets: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/fuzzy_matcher_spec.rb' # Offense count: 20 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideHashLiteralBraces: Exclude: - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. # SupportedStyles: space, no_space # SupportedStylesForEmptyBrackets: space, no_space Layout/SpaceInsideReferenceBrackets: Exclude: - 'benchmarks/map_hash.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: final_newline, final_blank_line Layout/TrailingEmptyLines: Exclude: - 'spec/rspec/support/fuzzy_matcher_spec.rb' # Offense count: 4 Lint/AmbiguousBlockAssociation: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/encoded_string_spec.rb' - 'spec/rspec/support/ruby_features_spec.rb' - 'spec/rspec/support_spec.rb' # Offense count: 2 Lint/BinaryOperatorWithIdenticalOperands: Exclude: - 'spec/rspec/support/object_formatter_spec.rb' - 'spec/rspec/support/source/token_spec.rb' # Offense count: 3 # Configuration parameters: AllowedMethods. # AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'spec/rspec/support/fuzzy_matcher_spec.rb' - 'spec/rspec/support/recursive_const_methods_spec.rb' - 'spec/rspec/support/spec/in_sub_process_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowedImplicitNamespaces. # AllowedImplicitNamespaces: Gem Lint/RaiseException: Exclude: - 'spec/rspec/support_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/RedundantCopDisableDirective: Exclude: - 'lib/rspec/support/spec/in_sub_process.rb' # Offense count: 1 Lint/StructNewOverride: Exclude: - 'spec/rspec/support_spec.rb' # Offense count: 3 # Configuration parameters: AllowComments. Lint/SuppressedException: Exclude: - 'spec/rspec/support_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. Lint/UselessAccessModifier: Exclude: - 'lib/rspec/support/encoded_string.rb' # Offense count: 12 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. # IgnoredMethods: refine Metrics/BlockLength: Max: 834 # Offense count: 8 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: Max: 836 # Offense count: 1 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: Max: 10 # Offense count: 6 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'benchmarks/caller_vs_caller_locations_vs_raise.rb' - 'spec/rspec/support/method_signature_verifier_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: Exclude: - 'benchmarks/caller_vs_caller_locations_vs_raise.rb' - 'lib/rspec/support.rb' - 'lib/rspec/support/spec/in_sub_process.rb' # Offense count: 1 Security/Eval: Exclude: - 'Gemfile' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/object_formatter_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/CaseLikeIf: Exclude: - 'lib/rspec/support/directory_maker.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'spec/rspec/support/comparable_version_spec.rb' - 'spec/rspec/support/directory_maker_spec.rb' - 'spec/rspec/support/encoded_string_spec.rb' - 'spec/rspec/support/source/node_spec.rb' - 'spec/rspec/support/source/token_spec.rb' - 'spec/rspec/support/source_spec.rb' - 'spec/rspec/support/with_keywords_when_needed_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. # IgnoredMethods: ==, equal?, eql? Style/ClassEqualityComparison: Exclude: - 'lib/rspec/support/comparable_version.rb' # Offense count: 1 # Cop supports --auto-correct. Style/ColonMethodCall: Exclude: - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Style/EmptyLiteral: Exclude: - 'spec/rspec/support/method_signature_verifier_spec.rb' # Offense count: 3 # Cop supports --auto-correct. Style/Encoding: Exclude: - 'rspec-support.gemspec' - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/encoded_string_spec.rb' # Offense count: 4 # Cop supports --auto-correct. Style/ExpandPathArguments: Exclude: - 'Gemfile' - 'benchmarks/caller.rb' - 'rspec-support.gemspec' - 'spec/rspec/support/caller_filter_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: format, sprintf, percent Style/FormatString: Exclude: - 'spec/rspec/support/encoded_string_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/GlobalStdStream: Exclude: - 'spec/rspec/support/spec/stderr_splitter_spec.rb' # Offense count: 3 # Configuration parameters: AllowedVariables. Style/GlobalVars: Exclude: - 'spec/rspec/support/caller_filter_spec.rb' - 'spec/rspec/support/spec/stderr_splitter_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys Style/HashSyntax: Exclude: - 'benchmarks/class_exec_vs_klass_exec.rb' # Offense count: 2 # Cop supports --auto-correct. Style/LineEndConcatenation: Exclude: - 'spec/rspec/support_spec.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. Style/MethodCallWithoutArgsParentheses: Exclude: - 'spec/rspec/support/method_signature_verifier_spec.rb' # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedOctalStyle. # SupportedOctalStyles: zero_with_o, zero_only Style/NumericLiteralPrefix: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/object_formatter_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: Strict. Style/NumericLiterals: MinDigits: 6 # Offense count: 1 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/rspec/support/spec/in_sub_process.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/object_formatter_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: lower_case_q, upper_case_q Style/PercentQLiterals: Exclude: - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Style/RedundantPercentQ: Exclude: - 'spec/rspec/support/differ_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - 'lib/rspec/support/mutex.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Exclude: - 'spec/rspec/support/fuzzy_matcher_spec.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AllowIfMethodIsEmpty. Style/SingleLineMethods: Exclude: - 'spec/rspec/support/differ_spec.rb' - 'spec/rspec/support/fuzzy_matcher_spec.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: WordRegex. # SupportedStyles: percent, brackets Style/WordArray: EnforcedStyle: percent MinSize: 3 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/maintenance-branch0000664000000000000000000000002114566142077023056 0ustar rootroot3-13-maintenance ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/README.md0000664000000000000000000000261214566142077020705 0ustar rootroot# RSpec::Support [![Build Status](https://github.com/rspec/rspec-support/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-support/actions) `RSpec::Support` provides common functionality to `RSpec::Core`, `RSpec::Expectations` and `RSpec::Mocks`. It is considered suitable for internal use only at this time. ## Installation / Usage Install one or more of the `RSpec` gems. Want to run against the `main` branch? You'll need to include the dependent RSpec repos as well. Add the following to your `Gemfile`: ```ruby %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main' end ``` ## Contributing Once you've set up the environment, you'll need to cd into the working directory of whichever repo you want to work in. From there you can run the specs and cucumber features, and make patches. NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You can treat each RSpec repo as an independent project. - [Build details](BUILD_DETAIL.md) - [Code of Conduct](CODE_OF_CONDUCT.md) - [Detailed contributing guide](CONTRIBUTING.md) - [Development setup guide](DEVELOPMENT.md) ## Patches Please submit a pull request or a github issue. If you submit an issue, please include a link to either of: * a gist (or equivalent) of the patch * a branch or commit in your github fork of the repo ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/Rakefile0000664000000000000000000000140014566142077021065 0ustar rootrootrequire "bundler" Bundler.setup Bundler::GemHelper.install_tasks require "rake" require "rspec/core/rake_task" require "rspec/core/version" desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.ruby_opts = %w[-w] end task :default => [:spec] task :verify_private_key_present do private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') unless File.exist?(private_key) raise "Your private key is not present. This gem should not be built without it." end end task :build => :verify_private_key_present begin require 'rubocop/rake_task' desc 'Run RuboCop on the lib directory' RuboCop::RakeTask.new(:rubocop) do |task| task.patterns = ['lib/**/*.rb'] end rescue LoadError # No rubocop means no rubocop rake task end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/0000775000000000000000000000000014566142077020357 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/0000775000000000000000000000000014566142077021473 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support_spec.rb0000664000000000000000000002315314566142077024552 0ustar rootrootrequire 'rspec/support' require 'rspec/support/spec/library_wide_checks' module RSpec describe Support do extend Support::RubyFeatures it_behaves_like "library wide checks", "rspec-support", :consider_a_test_env_file => %r{rspec/support/spec}, :allowed_loaded_feature_regexps => [ /rbconfig/, # Used by RubyFeatures /prettyprint.rb/, /pp.rb/, /diff\/lcs/ # These are all loaded by the differ. ] describe '.method_handle_for(object, method_name)' do untampered_class = Class.new do def foo :bar end end http_request_class = Struct.new(:method, :uri) proxy_class = Struct.new(:original) do undef :=~ if respond_to?(:=~) undef :method if respond_to?(:method) def method_missing(name, *args, &block) original.__send__(name, *args, &block) end end it 'fetches method definitions for vanilla objects' do object = untampered_class.new expect(Support.method_handle_for(object, :foo).call).to eq :bar end it 'fetches method definitions for objects with method redefined' do request = http_request_class.new(:get, "http://foo.com/") expect(Support.method_handle_for(request, :uri).call).to eq "http://foo.com/" end it 'fetches method definitions for proxy objects' do object = proxy_class.new('abc') expect(Support.method_handle_for(object, :=~)).to be_a Method end it 'fetches method definitions for proxy objects' do object = proxy_class.new('abc') expect(Support.method_handle_for(object, :=~)).to be_a Method end it 'fails with `NameError` when an undefined method is fetched ' + 'from an object that has overridden `method` to raise an Exception' do object = double allow(object).to receive(:method).and_raise(Exception) expect { Support.method_handle_for(object, :some_undefined_method) }.to raise_error(NameError) end it 'fails with `NameError` when a method is fetched from an object ' + 'that has overridden `method` to not return a method' do object = proxy_class.new(double(:method => :baz)) expect { Support.method_handle_for(object, :=~) }.to raise_error(NameError) end context "for a BasicObject subclass", :if => RUBY_VERSION.to_f > 1.8 do let(:basic_class) do Class.new(BasicObject) do def foo :bar end end end let(:basic_class_with_method_override) do Class.new(basic_class) do def method :method end end end let(:basic_class_with_kernel) do Class.new(basic_class) do include ::Kernel end end let(:basic_class_with_proxying) do Class.new(BasicObject) do def method_missing(name, *args, &block) "foo".__send__(name, *args, &block) end end end it 'still works', :if => supports_rebinding_module_methods? do object = basic_class.new expect(Support.method_handle_for(object, :foo).call).to eq :bar end it 'works when `method` has been overridden', :if => supports_rebinding_module_methods? do object = basic_class_with_method_override.new expect(Support.method_handle_for(object, :foo).call).to eq :bar end it 'allows `method` to be proxied', :unless => supports_rebinding_module_methods? do object = basic_class_with_proxying.new expect(Support.method_handle_for(object, :reverse).call).to eq "oof" end it 'still works when Kernel has been mixed in' do object = basic_class_with_kernel.new expect(Support.method_handle_for(object, :foo).call).to eq :bar end end end describe '.class_of' do subject(:klass) do Support.class_of(object) end context 'with a String instance' do let(:object) do 'foo' end it { is_expected.to equal(String) } end context 'with a BasicObject instance' do let(:object) do basic_object_class.new end let(:basic_object_class) do defined?(BasicObject) ? BasicObject : fake_basic_object_class end let(:fake_basic_object_class) do Class.new do def self.to_s 'BasicObject' end undef class, inspect, respond_to? end end it { is_expected.to equal(basic_object_class) } end context 'with nil' do let(:object) do nil end it { is_expected.to equal(NilClass) } end context 'with an object having a singleton class' do let(:object) do object = 'foo' def object.some_method end object end it 'returns its non-singleton ancestor class' do expect(klass).to equal(String) end end context 'with a Class instance' do let(:object) do String end it { is_expected.to equal(Class) } end end describe ".thread_local_data" do it "contains data local to the current thread" do RSpec::Support.thread_local_data[:__for_test] = :oh_hai Thread.new do expect(RSpec::Support.thread_local_data).to eq({}) end.join end if defined?(Fiber) && RUBY_VERSION.to_f >= 2.0 it "shares data across fibres" do RSpec::Support.thread_local_data[:__for_test] = :oh_hai Fiber.new do expect(RSpec::Support.thread_local_data[:__for_test]).to eq(:oh_hai) end.resume end end end describe "failure notification" do before { @failure_notifier = RSpec::Support.failure_notifier } after { RSpec::Support.failure_notifier = @failure_notifier } let(:error) { NotImplementedError.new("some message") } let(:failures) { [] } let(:append_to_failures_array_notifier) { lambda { |failure, _opts| failures << failure } } def notify(failure) RSpec::Support.notify_failure(failure) end def append_to_failures_array_instead_of_raising avoid_raising_errors.and change { failures }.from([]).to([error]) end def raise_instead_of_appending_to_failures_array raise_error(error).and avoid_changing { failures } end it "defaults to raising the provided exception" do expect { notify(error) }.to raise_error(error) end it "can be set to another callable" do RSpec::Support.failure_notifier = append_to_failures_array_notifier expect { notify(error) }.to append_to_failures_array_instead_of_raising end it "isolates notifier changes to the current thread" do RSpec::Support.failure_notifier = append_to_failures_array_notifier Thread.new do expect { notify(error) }.to raise_instead_of_appending_to_failures_array end.join end it "can be changed for the duration of a block" do yielded = false RSpec::Support.with_failure_notifier(append_to_failures_array_notifier) do yielded = true expect { notify(error) }.to append_to_failures_array_instead_of_raising end expect(yielded).to be true end it "resets the notifier back to what it originally was when the block completes, even if an error was raised" do expect { RSpec::Support.with_failure_notifier(append_to_failures_array_notifier) do raise "boom" end }.to raise_error("boom") expect { notify(error) }.to raise_instead_of_appending_to_failures_array end end describe "warning notification" do include RSpec::Support::Warnings before { @warning_notifier = RSpec::Support.warning_notifier } after { RSpec::Support.warning_notifier = @warning_notifier } let(:warnings) { [] } let(:append_to_warnings_array_notifier) { lambda { |warning| warnings << warning } } def append_to_array_instead_of_warning change { warnings }.from([]).to([a_string_including('some warning')]) end it "defaults to warning with the provided text" do expect { warning('some warning') }.to output(a_string_including 'some warning').to_stderr end it "can be set to another callable" do RSpec::Support.warning_notifier = append_to_warnings_array_notifier expect { warning('some warning') }.to append_to_array_instead_of_warning end end describe Support::AllExceptionsExceptOnesWeMustNotRescue do it "rescues a StandardError" do expect { begin raise StandardError rescue subject end }.not_to raise_error end it 'rescues an Exception' do expect { begin raise Exception rescue subject end }.not_to raise_error end Support::AllExceptionsExceptOnesWeMustNotRescue::AVOID_RESCUING.each do |klass| exception = if klass == SignalException SignalException.new("INT") else klass end it "does not rescue a #{klass}" do expect { begin raise exception rescue subject end }.to raise_error(klass) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/0000775000000000000000000000000014566142077023207 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/warnings_spec.rb0000664000000000000000000000421314566142077026376 0ustar rootrootrequire "spec_helper" require "rspec/support/warnings" require 'rspec/support/spec/shell_out' RSpec.describe "rspec warnings and deprecations" do include RSpec::Support::ShellOut let(:warning_object) do Object.new.tap { |o| o.extend(RSpec::Support::Warnings) } end it 'works when required in isolation' do out, err, status = run_ruby_with_current_load_path("RSpec.deprecate('foo')", "-rrspec/support/warnings") expect(out).to eq("") expect(err).to start_with("DEPRECATION: foo is deprecated") expect(status.exitstatus).to eq(0) end context "when rspec-core is not available" do shared_examples "falling back to Kernel.warn" do |args| let(:method_name) { args.fetch(:method_name) } it 'falls back to warning with a plain message' do expect(::Kernel).to receive(:warn).with(/message/) warning_object.send(method_name, 'message') end it "handles being passed options" do expect(::Kernel).to receive(:warn).with(/message/) warning_object.send(method_name, "this is the message", :type => :test) end end it_behaves_like 'falling back to Kernel.warn', :method_name => :deprecate it_behaves_like 'falling back to Kernel.warn', :method_name => :warn_deprecation end shared_examples "warning helper" do |helper| it 'warns with the message text' do expect(::Kernel).to receive(:warn).with(/Message/) warning_object.send(helper, 'Message') end it 'sets the calling line' do expect(::Kernel).to receive(:warn).with(/#{__FILE__}:#{__LINE__+1}/) warning_object.send(helper, 'Message') end it 'optionally sets the replacement' do expect(::Kernel).to receive(:warn).with(/Use Replacement instead./) warning_object.send(helper, 'Message', :replacement => 'Replacement') end end describe "#warning" do it 'prepends WARNING:' do expect(::Kernel).to receive(:warn).with(/WARNING: Message\./) warning_object.warning 'Message' end it_should_behave_like 'warning helper', :warning end describe "#warn_with message, options" do it_should_behave_like 'warning helper', :warn_with end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/fuzzy_matcher_spec.rb0000664000000000000000000001530014566142077027437 0ustar rootrootrequire 'spec_helper' require 'rspec/support/fuzzy_matcher' module RSpec module Support RSpec.describe FuzzyMatcher, ".values_match?" do matcher :match_against do |actual| match { |expected| FuzzyMatcher.values_match?(expected, actual) } end it 'returns true when given equal values' do expect(1).to match_against(1.0) end it 'returns false when given unequal values that do not provide match logic' do expect(1).not_to match_against(1.1) end it 'can match a regex against a string' do expect(/foo/).to match_against("foobar") expect(/foo/).not_to match_against("fobar") end it 'can match a regex against itself' do expect(/foo/).to match_against(/foo/) expect(/foo/).not_to match_against(/bar/) end it 'can match a class against an instance' do expect(String).to match_against("foo") expect(String).not_to match_against(123) end it 'can match a class against itself' do expect(String).to match_against(String) expect(String).not_to match_against(Regexp) end it 'can match against a matcher' do expect(be_within(0.1).of(2)).to match_against(2.05) expect(be_within(0.1).of(2)).not_to match_against(2.15) end it 'does not ask the second argument if it fuzzy matches (===)' do expect("foo").not_to match_against(String) end context "when given two 0-arg lambdas" do it 'returns true when given the same lambda' do k = lambda { 3 } expect(k).to match_against(k) end it 'returns false when given different lambdas' do expect(lambda { 3 }).not_to match_against(lambda { 4 }) end end context "when given an object whose implementation of `==` wrongly assumes it will only be called with objects of the same type" do Color = Struct.new(:r, :g, :b) do def ==(other) other.r == r && other.g == g && other.b == b end end before(:context) do expect { Color.new(0, 0, 0) == Object.new }.to raise_error(NoMethodError, /undefined method [`']r'/) end it 'can match against an expected value that matches anything' do anything = Object.new.tap do |o| def o.===(*); true; end end expect(anything).to match_against(Color.new(0, 0, 0)) end it 'surfaces the `NoMethodError` when used as the expected value' do expect { FuzzyMatcher.values_match?(Color.new(0, 0, 0), Object.new) }.to raise_error(NoMethodError, /undefined method [`']r'/) end it 'can match against objects of the same type' do expect(Color.new(0, 0, 0)).to match_against(Color.new(0, 0, 0)) expect(Color.new(0, 0, 0)).not_to match_against(Color.new(0, 1, 0)) end end context "when given an object whose implementation of `==` raises an ArgumentError" do it 'surfaces the error' do klass = Class.new do attr_accessor :foo def ==(other) other.foo == foo end end instance = klass.new other = Object.new def other.foo(arg); end expect { instance == other }.to raise_error(ArgumentError) expect { FuzzyMatcher.values_match?(instance, other) }.to raise_error(ArgumentError) end end it "does not match a struct against an array" do struct = Struct.new(:foo, :bar).new("first", 2) expect(["first", 2]).not_to match_against(struct) end context "when given two arrays" do it 'returns true if they have equal values' do expect([1, 2.0]).to match_against([1.0, 2]) end it 'returns false when given unequal values that do not provide match logic' do expect([1, 2.0]).not_to match_against([1.1, 2]) end it 'does the fuzzy matching on the individual elements' do expect([String, Integer]).to match_against(["a", 2]) expect([String, Integer]).not_to match_against([2, "a"]) end it 'returns false if they have a different number of elements' do expect([String, Integer]).not_to match_against(['a', 2, nil]) end it 'supports arbitrary nested arrays' do a1 = [ [String, Integer, [be_within(0.1).of(2)]], 3, [[[ /foo/ ]]] ] a2 = [ ["a", 1, [2.05]], 3, [[[ "foobar" ]]] ] expect(a1).to match_against(a2) a2[0][2][0] += 1 expect(a1).not_to match_against(a2) end end it 'can match an array an arbitrary enumerable' do my_enum = Class.new do include Enumerable def each yield 1; yield "foo" end end.new expect([Integer, String]).to match_against(my_enum) expect([String, Integer]).not_to match_against(my_enum) end it 'does not match an empty hash against an empty array or vice-versa' do expect({}).not_to match_against([]) expect([]).not_to match_against({}) end context 'when given two hashes' do it 'returns true when their keys and values are equal' do expect(:a => 5, :b => 2.0).to match_against(:a => 5.0, :b => 2) end it 'returns false when given unequal values that do not provide match logic' do expect(:a => 5).not_to match_against(:a => 5.1) end it 'does the fuzzy matching on the individual values' do expect(:a => String, :b => /bar/).to match_against(:a => "foo", :b => "barn") expect(:a => String, :b => /bar/).not_to match_against(:a => "foo", :b => "brn") end it 'returns false if the expected hash has nil values that are not in the actual hash' do expect(:a => 'b', :b => nil).not_to match_against(:a => "b") end it 'returns false if actual hash has extra entries' do expect(:a => 'b').not_to match_against(:a => "b", :b => nil) end it 'does not fuzzy match on keys' do expect(/foo/ => 1).not_to match_against("foo" => 1) end it 'supports arbitrary nested hashes' do h1 = { :a => { :b => [String, Integer], :c => { :d => be_within(0.1).of(2) } } } h2 = { :a => { :b => ["foo", 5], :c => { :d => 2.05 } } } expect(h1).to match_against(h2) h2[:a][:c][:d] += 1 expect(h1).not_to match_against(h2) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/mutex_spec.rb0000664000000000000000000000030414566142077025705 0ustar rootrootrequire 'rspec/support/mutex' RSpec.describe RSpec::Support::Mutex do it "allows ::Mutex to be mocked", :if => defined?(::Mutex) do expect(Mutex).to receive(:new) ::Mutex.new end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/reentrant_mutex_spec.rb0000664000000000000000000000404214566142077027772 0ustar rootrootrequire 'rspec/support/reentrant_mutex' require 'thread_order' # There are no assertions specifically # They are pass if they don't deadlock RSpec.describe RSpec::Support::ReentrantMutex do let!(:mutex) { described_class.new } let!(:order) { ThreadOrder.new } after { order.apocalypse! } it 'can repeatedly synchronize within the same thread' do mutex.synchronize { mutex.synchronize { } } end it 'locks other threads out while in the synchronize block' do order.declare(:before) { mutex.synchronize { } } order.declare(:within) { mutex.synchronize { } } order.declare(:after) { mutex.synchronize { } } order.pass_to :before, :resume_on => :exit mutex.synchronize { order.pass_to :within, :resume_on => :sleep } order.pass_to :after, :resume_on => :exit end it 'resumes the next thread once all its synchronize blocks have completed' do order.declare(:thread) { mutex.synchronize { } } mutex.synchronize { order.pass_to :thread, :resume_on => :sleep } order.join_all end # On Ruby 3.1.3+, 3.2.0 and RUBY_HEAD the raise in this spec can # bypass the `raise_error` capture and break this spec but # it is not sufficient to pend it as the raise can escape to the other # threads somehow therefore poisoning them so its skipped entirely. # This is a temporary work around to allow green cross project builds but # needs a fix. if RUBY_VERSION >= '3.0' && RUBY_VERSION < '3.1.3' && !ENV['RUBY_HEAD'] it 'waits when trying to lock from another Fiber' do mutex.synchronize do ready = false f = Fiber.new do expect { ready = true mutex.send(:enter) raise 'should reach here: mutex is already locked on different Fiber' }.to raise_error(Exception, 'waited correctly') end main_thread = Thread.current t = Thread.new do Thread.pass until ready && main_thread.stop? main_thread.raise Exception, 'waited correctly' end f.resume t.join end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/source/0000775000000000000000000000000014566142077024507 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/source/token_spec.rb0000664000000000000000000000432414566142077027171 0ustar rootrootrequire 'rspec/support/source/token' class RSpec::Support::Source RSpec.describe Token, :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:target_token) do tokens.first end let(:tokens) do Token.tokens_from_ripper_tokens(ripper_tokens) end let(:ripper_tokens) do require 'ripper' Ripper.lex(source) end let(:source) do 'puts :foo' end # [ # [[1, 0], :on_ident, "puts"], # [[1, 4], :on_sp, " "], # [[1, 5], :on_symbeg, ":"], # [[1, 6], :on_ident, "foo"] # ] describe "#closed_by" do context "with a normal ruby multi line method" do let(:source) { "def foo\n :bar\nend" } specify 'the first token is closed by the last' do expect(tokens.first).to be_closed_by(tokens.last) end end context "with a ruby one line method definition" do let(:source) { 'def self.foo = "bar"' } specify 'the first token is closed by the =' do expect(tokens.first).to be_closed_by(tokens[6]) end end end describe '#location' do it 'returns a Location object with line and column numbers' do expect(target_token.location).to have_attributes(:line => 1, :column => 0) end end describe '#type' do it 'returns a type of the token' do expect(target_token.type).to eq(:on_ident) end end describe '#string' do it 'returns a source string corresponding to the token' do expect(target_token.string).to eq('puts') end end describe '#==' do context 'when both tokens have same Ripper token' do it 'returns true' do expect(Token.new(ripper_tokens[0]) == Token.new(ripper_tokens[0])).to be true end end context 'when both tokens have different Ripper token' do it 'returns false' do expect(Token.new(ripper_tokens[0]) == Token.new(ripper_tokens[1])).to be false end end end describe '#inspect' do it 'returns a string including class name, token type and source string' do expect(target_token.inspect).to eq('#') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/source/node_spec.rb0000664000000000000000000000646714566142077027010 0ustar rootrootrequire 'rspec/support/source/node' class RSpec::Support::Source RSpec.describe Node, :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:root_node) do Node.new(sexp) end let(:sexp) do require 'ripper' Ripper.sexp(source) end let(:source) { <<-END } variable = do_something(1, 2) variable.do_anything do |arg| puts arg end END # [:program, # [[:assign, # [:var_field, [:@ident, "variable", [1, 6]]], # [:method_add_arg, # [:fcall, [:@ident, "do_something", [1, 17]]], # [:arg_paren, # [:args_add_block, # [[:@int, "1", [1, 30]], [:@int, "2", [1, 33]]], # false]]]], # [:method_add_block, # [:call, # [:var_ref, [:@ident, "variable", [2, 6]]], # :".", # [:@ident, "do_anything", [2, 15]]], # [:do_block, # [:block_var, # [:params, [[:@ident, "arg", [2, 31]]], nil, nil, nil, nil, nil, nil], # false], # [[:command, # [:@ident, "puts", [3, 8]], # [:args_add_block, [[:var_ref, [:@ident, "arg", [3, 13]]]], false]]]]]]] describe '#args' do context 'when the sexp args consist of direct child sexps' do let(:target_node) do root_node.find { |node| node.type == :method_add_arg } end it 'returns the child nodes' do expect(target_node.args).to match([ an_object_having_attributes(:type => :fcall), an_object_having_attributes(:type => :arg_paren) ]) end end context 'when the sexp args include an array of sexps' do let(:target_node) do root_node.find { |node| node.type == :args_add_block } end it 'returns pseudo expression sequence node for the array' do expect(target_node.args).to match([ an_object_having_attributes(:type => :_expression_sequence), false ]) end end end describe '#each_ancestor' do let(:target_node) do root_node.find { |node| node.type == :arg_paren } end it 'yields ancestor nodes from parent to root' do expect { |b| target_node.each_ancestor(&b) }.to yield_successive_args( an_object_having_attributes(:type => :method_add_arg), an_object_having_attributes(:type => :assign), an_object_having_attributes(:type => :_expression_sequence), an_object_having_attributes(:type => :program) ) end end describe '#location' do context 'with identifier type node' do let(:target_node) do root_node.find { |node| node.type == :@ident } end it 'returns a Location object with line and column numbers' do expect(target_node.location).to have_attributes(:line => 1, :column => 6) end end context 'with non-identifier type node' do let(:target_node) do root_node.find { |node| node.type == :assign } end it 'returns nil' do expect(target_node.location).to be_nil end end end describe '#inspect' do it 'returns a string including class name and node type' do expect(root_node.inspect).to eq('#') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/method_signature_verifier_spec.rb0000664000000000000000000012641714566142077032015 0ustar rootrootrequire 'rspec/support' require 'rspec/support/method_signature_verifier' module RSpec module Support RSpec.describe 'verifying methods' do let(:signature) { MethodSignature.new(test_method) } def valid_non_kw_args?(arity) described_class.new(signature, [nil] * arity).valid? end def valid?(*args) described_class.new(signature, args).valid? end def error_description described_class.new(signature).error_message[/Expected (.*),/, 1] end def error_for(*args) described_class.new(signature, args).error_message end def signature_description signature.description end def validate_expectation(*args) obj = MethodSignatureExpectation.new obj.min_count = Integer === args.first ? args.shift : nil obj.max_count = Integer === args.first ? args.shift : nil obj.expect_unlimited_arguments = !args.delete(:unlimited_args).nil? obj.expect_arbitrary_keywords = !args.delete(:arbitrary_kw_args).nil? obj.keywords = args described_class.new(signature).with_expectation(obj).valid? end shared_context 'a method verifier' do describe 'with a method with arguments' do def arity_two(x, y); end let(:test_method) { method(:arity_two) } it 'covers only the exact arity' do expect(valid_non_kw_args?(1)).to eq(false) expect(valid_non_kw_args?(2)).to eq(true) expect(valid_non_kw_args?(3)).to eq(false) end it "allows matchers to be passed as arguments" do expect(valid?(anything, anything)).to eq(true) end it 'does not treat a last-arg hash as kw args' do expect(valid?(1, {})).to eq(true) end it 'describes the arity precisely' do expect(error_description).to eq("2") end it 'mentions only the arity in the description' do expect(signature_description).to eq("arity of 2") end it 'indicates it has no optional kw args' do expect(signature.optional_kw_args).to eq([]) end it 'indicates it has no required kw args' do expect(signature.required_kw_args).to eq([]) end describe 'with an expectation object' do it 'matches the exact arity' do expect(validate_expectation 1).to eq(false) expect(validate_expectation 2).to eq(true) expect(validate_expectation 3).to eq(false) end it 'matches a range including the min and max counts' do expect(validate_expectation 1, 2).to eq(false) expect(validate_expectation 2, 2).to eq(true) expect(validate_expectation 2, 3).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) end if RubyFeatures.kw_args_supported? it 'does not match keywords' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) end else it 'ignores keyword expectations' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(true) end it 'ignores arbitrary keyword expectations' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation 2, :arbitrary_kw_args).to eq(true) end end end end describe 'a method with splat arguments' do def arity_splat(_, *); end let(:test_method) { method(:arity_splat) } it 'covers a range from the lower bound upwards' do expect(valid_non_kw_args?(0)).to eq(false) expect(valid_non_kw_args?(1)).to eq(true) expect(valid_non_kw_args?(2)).to eq(true) expect(valid_non_kw_args?(3)).to eq(true) end it 'describes the arity with no upper bound' do expect(error_description).to eq("1 or more") end it 'mentions only the arity in the description' do expect(signature_description).to eq("arity of 1 or more") end describe 'with an expectation object' do it 'matches a value from the lower bound upwards' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(true) expect(validate_expectation 2).to eq(true) expect(validate_expectation 3).to eq(true) end it 'matches a range from the lower bound upwards' do expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(true) expect(validate_expectation 1, 2).to eq(true) expect(validate_expectation 2, 3).to eq(true) expect(validate_expectation 1, 2 ** 31).to eq(true) end if RubyFeatures.optional_and_splat_args_supported? it 'matches unlimited arguments with the minimum arity' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation 1, :unlimited_args).to eq(true) end else it 'ignores unlimited arguments expectations' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation 1, :unlimited_args).to eq(true) end end if RubyFeatures.kw_args_supported? it 'does not match keywords' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation 2, :arbitrary_kw_args).to eq(false) end else it 'ignores keyword expectations' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(true) end it 'ignores arbitrary keyword expectations' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation 2, :arbitrary_kw_args).to eq(true) end end end end describe 'a method with optional arguments' do def arity_optional(x, y, z = 1); end let(:test_method) { method(:arity_optional) } it 'covers a range from min to max possible arguments' do expect(valid_non_kw_args?(1)).to eq(false) expect(valid_non_kw_args?(2)).to eq(true) expect(valid_non_kw_args?(3)).to eq(true) if RubyFeatures.optional_and_splat_args_supported? expect(valid_non_kw_args?(4)).to eq(false) else expect(valid_non_kw_args?(4)).to eq(true) end end if RubyFeatures.optional_and_splat_args_supported? it 'describes the arity as a range' do expect(error_description).to eq("2 to 3") end else it 'describes the arity with no upper bound' do expect(error_description).to eq("2 or more") end end describe 'with an expectation object' do it 'matches a value from min to max possible arguments' do expect(validate_expectation 1).to eq(false) expect(validate_expectation 2).to eq(true) expect(validate_expectation 3).to eq(true) if RubyFeatures.optional_and_splat_args_supported? expect(validate_expectation 4).to eq(false) else expect(validate_expectation 4).to eq(true) end end it 'matches a range from the lower bound upwards' do expect(validate_expectation 1, 2).to eq(false) expect(validate_expectation 2, 2).to eq(true) expect(validate_expectation 2, 3).to eq(true) if RubyFeatures.optional_and_splat_args_supported? expect(validate_expectation 2, 4).to eq(false) else expect(validate_expectation 2, 4).to eq(true) end end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) end if RubyFeatures.kw_args_supported? it 'does not match keywords' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) end else it 'ignores keyword expectations' do expect(validate_expectation :optional_keyword).to eq(false) expect(validate_expectation 2, :optional_keyword).to eq(true) end it 'ignores arbitrary keyword expectations' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation 2, :arbitrary_kw_args).to eq(true) end end end end if RubyFeatures.kw_args_supported? describe 'a method with optional keyword arguments' do eval <<-RUBY def arity_kw(x, y:1, z:2); end RUBY let(:test_method) { method(:arity_kw) } it 'does not require any of the arguments' do expect(valid?(nil)).to eq(true) expect(valid?(nil, nil)).to eq(false) end it 'does not allow an invalid keyword arguments' do expect(valid?(nil, :a => 1)).to eq(false) end it 'mentions the invalid keyword args in the error', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do expect(error_for(nil, :a => 0, :b => 1)).to \ eq("Invalid keyword arguments provided: a, b") end it 'describes invalid arity precisely' do expect(error_for()).to \ eq("Wrong number of arguments. Expected 1, got 0.") end it 'does not blow up when given a BasicObject as the last arg' do expect(valid?(BasicObject.new)).to eq(true) end it 'does not mutate the provided args array' do args = [nil, { :y => 1 }] described_class.new(signature, args).valid? expect(args).to eq([nil, { :y => 1 }]) end it 'mentions the arity and optional kw args in the description', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do expect(signature_description).to eq("arity of 1 and optional keyword args (:y, :z)") end it "indicates the optional keyword args" do expect(signature.optional_kw_args).to contain_exactly(:y, :z) end it "indicates it has no required keyword args" do expect(signature.required_kw_args).to eq([]) end describe 'with an expectation object' do it 'matches the exact arity' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(true) expect(validate_expectation 2).to eq(false) end it 'matches the exact range' do expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(true) expect(validate_expectation 1, 2).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) end it 'matches optional keywords with the correct arity' do expect(validate_expectation :y).to eq(false) expect(validate_expectation :z).to eq(false) expect(validate_expectation :y, :z).to eq(false) expect(validate_expectation 1, :y).to eq(true) expect(validate_expectation 1, :z).to eq(true) expect(validate_expectation 1, :y, :z).to eq(true) expect(validate_expectation 2, :y).to eq(false) expect(validate_expectation 2, :z).to eq(false) expect(validate_expectation 2, :y, :z).to eq(false) end it 'does not match invalid keywords' do expect(validate_expectation :w).to eq(false) expect(validate_expectation :w, :z).to eq(false) expect(validate_expectation 1, :w).to eq(false) expect(validate_expectation 1, :w, :z).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) end end end end if RubyFeatures.kw_args_supported? describe 'a method with optional argument and keyword arguments' do eval <<-RUBY def arity_kw(x, y = {}, z:2); end RUBY let(:test_method) { method(:arity_kw) } it 'does not require any of the arguments' do expect(valid?(nil)).to eq(true) expect(valid?(nil, nil)).to eq(true) end it 'does not allow an invalid keyword arguments' do expect(valid?(nil, nil, :a => 1)).to eq(false) expect(valid?(nil, :a => 1)).to eq(false) end if RubyFeatures.kw_arg_separation? context "when ruby has kw arg separation" do it 'treats symbols as keyword arguments' do expect(valid?(nil, nil, :z => 1)).to eq(true) expect(valid?(nil, :z => 1)).to eq(true) end it 'fails to match string keys as kw args' do expect(valid?(nil, nil, 'z' => 1)).to eq(false) expect(valid?(nil, 'z' => 1)).to eq(false) end it 'mentions the invalid keyword args in the error', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do expect(error_for(1, 2, :a => 0)).to eq("Invalid keyword arguments provided: a") expect(error_for(1, :a => 0)).to eq("Invalid keyword arguments provided: a") expect(error_for(1, 'a' => 0, :b => 0)).to eq("Invalid keyword arguments provided: a, b") end end else it 'treats symbols as keyword arguments and the rest as optional argument' do expect(valid?(nil, 'a' => 1)).to eq(true) expect(valid?(nil, 'a' => 1, :z => 3)).to eq(true) expect(valid?(nil, 'a' => 1, :b => 3)).to eq(false) expect(valid?(nil, 'a' => 1, :b => 2, :z => 3)).to eq(false) end it 'mentions the invalid keyword args in the error', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do expect(error_for(1, 2, :a => 0)).to eq("Invalid keyword arguments provided: a") expect(error_for(1, :a => 0)).to eq("Invalid keyword arguments provided: a") expect(error_for(1, 'a' => 0, :b => 0)).to eq("Invalid keyword arguments provided: b") end end it 'describes invalid arity precisely' do expect(error_for()).to \ eq("Wrong number of arguments. Expected 1 to 2, got 0.") end it 'does not blow up when given a BasicObject as the last arg' do expect(valid?(BasicObject.new)).to eq(true) end it 'does not mutate the provided args array' do args = [nil, nil, { :y => 1 }] described_class.new(signature, args).valid? expect(args).to eq([nil, nil, { :y => 1 }]) end it 'mentions the arity and optional kw args in the description', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do expect(signature_description).to eq("arity of 1 to 2 and optional keyword args (:z)") end it "indicates the optional keyword args" do expect(signature.optional_kw_args).to contain_exactly(:z) end it "indicates it has no required keyword args" do expect(signature.required_kw_args).to eq([]) end describe 'with an expectation object' do it 'matches the exact arity' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(true) expect(validate_expectation 2).to eq(true) end it 'matches the exact range' do expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(true) expect(validate_expectation 1, 2).to eq(true) expect(validate_expectation 1, 3).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) end it 'matches optional keywords with the correct arity' do expect(validate_expectation :z).to eq(false) expect(validate_expectation 1, :z).to eq(true) # Are we OK with that? expect(validate_expectation 1, 2, :z).to eq(true) expect(validate_expectation 1, 2, :y).to eq(false) end it 'does not match invalid keywords' do expect(validate_expectation :w).to eq(false) expect(validate_expectation 2, :w).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) end end end end if RubyFeatures.required_kw_args_supported? describe 'a method with required keyword arguments' do eval <<-RUBY def arity_required_kw(x, y:, z:, a: 'default'); end RUBY let(:test_method) { method(:arity_required_kw) } it 'returns false unless all required keywords args are present' do expect(valid?(nil, :a => 0, :y => 1, :z => 2)).to eq(true) expect(valid?(nil, :a => 0, :y => 1)).to eq(false) expect(valid?(nil, nil, :a => 0, :y => 1, :z => 2)).to eq(false) expect(valid?(nil, nil)).to eq(false) end it 'mentions the missing required keyword args in the error' do expect(error_for(nil, :a => 0)).to \ eq("Missing required keyword arguments: y, z") end it 'is described precisely when arity is wrong' do expect(error_for(nil, nil, :z => 0, :y => 1)).to \ eq("Wrong number of arguments. Expected 1, got 2.") end it 'mentions the arity, optional kw args and required kw args in the description' do expect(signature_description).to \ eq("arity of 1 and optional keyword args (:a) and required keyword args (:y, :z)") end it "indicates the optional keyword args" do expect(signature.optional_kw_args).to contain_exactly(:a) end it "indicates the required keyword args" do expect(signature.required_kw_args).to contain_exactly(:y, :z) end describe 'with an expectation object' do it 'does not match the exact arity without the required keywords' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(false) expect(validate_expectation 1, :y).to eq(false) expect(validate_expectation 1, :z).to eq(false) expect(validate_expectation 2).to eq(false) end it 'does not match the range without the required keywords' do expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(false) expect(validate_expectation 1, 1, :y).to eq(false) expect(validate_expectation 1, 1, :z).to eq(false) expect(validate_expectation 1, 2).to eq(false) end it 'matches the exact arity with the required keywords' do expect(validate_expectation 0, :y, :z).to eq(false) expect(validate_expectation 1, :y, :z).to eq(true) expect(validate_expectation 2, :y, :z).to eq(false) end it 'matches the range with the required keywords' do expect(validate_expectation 0, 1, :y, :z).to eq(false) expect(validate_expectation 1, 1, :y, :z).to eq(true) expect(validate_expectation 1, 2, :y, :z).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation :y, :z, :unlimited_args).to eq(false) end it 'matches optional keywords with the required keywords' do expect(validate_expectation 1, :a, :y, :z).to eq(true) end it 'does not match optional keywords without the required keywords' do expect(validate_expectation :a).to eq(false) expect(validate_expectation :a, :y).to eq(false) expect(validate_expectation :a, :z).to eq(false) expect(validate_expectation 1, :a).to eq(false) expect(validate_expectation 1, :a, :y).to eq(false) expect(validate_expectation 1, :a, :z).to eq(false) end it 'does not match invalid keywords' do expect(validate_expectation :w).to eq(false) expect(validate_expectation :w, :y, :z).to eq(false) expect(validate_expectation 1, :w).to eq(false) expect(validate_expectation 1, :w, :y, :z).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation :y, :z, :arbitrary_kw_args).to eq(false) end end end describe 'a method with required keyword arguments and a splat' do eval <<-RUBY def arity_required_kw_splat(w, *x, y:, z:, a: 'default'); end RUBY let(:test_method) { method(:arity_required_kw_splat) } it 'returns false unless all required keywords args are present' do expect(valid?(nil, :a => 0, :y => 1, :z => 2)).to eq(true) expect(valid?(nil, :a => 0, :y => 1)).to eq(false) expect(valid?(nil, nil, :a => 0, :y => 1, :z => 2)).to eq(true) expect(valid?(nil, nil, nil)).to eq(false) expect(valid?).to eq(false) end it 'mentions missing required keyword args in the error' do expect(error_for(nil, :y => 1)).to \ eq("Missing required keyword arguments: z") end it 'mentions the arity, optional kw args and required kw args in the description' do expect(signature_description).to \ eq("arity of 1 or more and optional keyword args (:a) and required keyword args (:y, :z)") end describe 'with an expectation object' do it 'does not match a value from the lower bound upwards' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(false) expect(validate_expectation 1, :y).to eq(false) expect(validate_expectation 1, :z).to eq(false) expect(validate_expectation 2).to eq(false) end it 'does not match a range from the lower bound upwards' do expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(false) expect(validate_expectation 1, 1, :y).to eq(false) expect(validate_expectation 1, 1, :z).to eq(false) expect(validate_expectation 1, 2).to eq(false) end it 'matches a value from the lower bound upwards with the required keywords' do expect(validate_expectation 0, :y, :z).to eq(false) expect(validate_expectation 1, :y, :z).to eq(true) expect(validate_expectation 2, :y, :z).to eq(true) expect(validate_expectation 3, :y, :z).to eq(true) end it 'matches a range from the lower bound upwards with the required keywords' do expect(validate_expectation 0, 1, :y, :z).to eq(false) expect(validate_expectation 1, 1, :y, :z).to eq(true) expect(validate_expectation 1, 2, :y, :z).to eq(true) expect(validate_expectation 3, 4, :y, :z).to eq(true) expect(validate_expectation 3, 2 ** 31, :y, :z).to eq(true) end it 'matches unlimited arguments with the minimum arity and the required keywords' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation 1, :unlimited_args).to eq(false) expect(validate_expectation :y, :z, :unlimited_args).to eq(false) expect(validate_expectation 1, :y, :z, :unlimited_args).to eq(true) end it 'matches optional keywords with the required keywords' do expect(validate_expectation 1, :a, :y, :z).to eq(true) end it 'does not match optional keywords without the required keywords' do expect(validate_expectation :a).to eq(false) expect(validate_expectation :a, :y).to eq(false) expect(validate_expectation :a, :z).to eq(false) expect(validate_expectation 1, :a).to eq(false) expect(validate_expectation 1, :a, :y).to eq(false) expect(validate_expectation 1, :a, :z).to eq(false) end it 'does not match invalid keywords' do expect(validate_expectation :w).to eq(false) expect(validate_expectation :w, :y, :z).to eq(false) expect(validate_expectation 1, :w).to eq(false) expect(validate_expectation 1, :w, :y, :z).to eq(false) end it 'does not match arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation :y, :z, :arbitrary_kw_args).to eq(false) end end end describe 'a method with only a keyword arg splat' do eval <<-RUBY def arity_kw_arg_splat(**rest); end RUBY let(:test_method) { method(:arity_kw_arg_splat) } if RubyFeatures.kw_arg_separation? it 'allows undeclared keyword args' do expect(valid?(:x => 1)).to eq(true) expect(valid?(:x => 1, 'y' => 2)).to eq(true) expect(valid?('y' => 2)).to eq(true) end else it 'allows undeclared symbol keyword args' do expect(valid?(:x => 1)).to eq(true) expect(valid?(:x => 1, 'y' => 2)).to eq(false) expect(valid?('y' => 2)).to eq(false) end end it 'mentions the required kw args and keyword splat in the description' do expect(signature_description).to \ eq("any additional keyword args") end describe 'with an expectation object' do it 'allows zero non-kw args' do expect(validate_expectation 0).to eq(true) expect(validate_expectation 1).to eq(false) expect(validate_expectation 0, 0).to eq(true) expect(validate_expectation 0, 1).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) end it 'matches arbitrary keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(true) end end end describe 'a method with required keyword arguments and a keyword arg splat' do eval <<-RUBY def arity_kw_arg_splat(x:, **rest); end RUBY let(:test_method) { method(:arity_kw_arg_splat) } it 'allows extra undeclared keyword args' do expect(valid?(:x => 1)).to eq(true) expect(valid?(:x => 1, :y => 2)).to eq(true) expect(valid?(:x => 1, :y => 2, 'z' => 3)).to eq(RubyFeatures.kw_arg_separation?) end it 'mentions missing required keyword args in the error' do expect(error_for(:y => 1)).to \ eq("Missing required keyword arguments: x") end it 'mentions the required kw args and keyword splat in the description' do expect(signature_description).to \ eq("required keyword args (:x) and any additional keyword args") end describe 'with an expectation object' do it 'does not match the exact arity without the required keywords' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(false) end it 'does not match the exact range without the required keywords' do expect(validate_expectation 0, 0).to eq(false) expect(validate_expectation 0, 1).to eq(false) end it 'matches the exact arity with the required keywords' do expect(validate_expectation 0, :x).to eq(true) end it 'does matches the exact range without the required keywords' do expect(validate_expectation 0, 0, :x).to eq(true) expect(validate_expectation 0, 1, :x).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation :x, :unlimited_args).to eq(false) end it 'matches arbitrary keywords with the required keywords' do expect(validate_expectation 0, :x, :u, :v).to eq(true) end it 'does not match arbitrary keywords without the required keywords' do expect(validate_expectation :a).to eq(false) expect(validate_expectation 0, :a).to eq(false) end it 'matches arbitrary keywords with the required keywords' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation :x, :arbitrary_kw_args).to eq(true) end end end describe 'a method with a required arg and a keyword arg splat' do eval <<-RUBY def arity_kw_arg_splat(x, **rest); end RUBY let(:test_method) { method(:arity_kw_arg_splat) } it 'allows a single arg and any number of keyword args' do expect(valid?(nil)).to eq(true) expect(valid?(nil, :x => 1)).to eq(true) expect(valid?(nil, 'x' => 1)).to eq(RubyFeatures.kw_arg_separation?) expect(valid?(nil, :x => 1, :y => 2)).to eq(true) expect(valid?(nil, :x => 1, :y => 2, 'z' => 3)).to eq(RubyFeatures.kw_arg_separation?) expect(valid?(:x => 1)).to eq(true) expect(valid?(nil, {})).to eq(true) expect(valid?).to eq(false) expect(valid?(nil, nil)).to eq(false) expect(valid?(nil, nil, :x => 1)).to eq(false) end it 'describes the arity precisely' do expect(error_for()).to \ eq("Wrong number of arguments. Expected 1, got 0.") end it 'mentions the required kw args and keyword splat in the description' do expect(signature_description).to \ eq("arity of 1 and any additional keyword args") end describe 'with an expectation object' do it 'matches the exact arity' do expect(validate_expectation 0).to eq(false) expect(validate_expectation 1).to eq(true) expect(validate_expectation 2).to eq(false) end it 'matches the exact range' do expect(validate_expectation 0, 0).to eq(false) expect(validate_expectation 0, 1).to eq(false) expect(validate_expectation 1, 1).to eq(true) expect(validate_expectation 1, 2).to eq(false) expect(validate_expectation 2, 2).to eq(false) end it 'does not match unlimited arguments' do expect(validate_expectation :unlimited_args).to eq(false) expect(validate_expectation 1, :unlimited_args).to eq(false) end it 'matches unlisted keywords with the required arity' do expect(validate_expectation 1, :u, :v).to eq(true) end it 'matches unlisted keywords with the exact range' do expect(validate_expectation 1, 1, :u, :v).to eq(true) end it 'matches arbitrary keywords with the required arity' do expect(validate_expectation :arbitrary_kw_args).to eq(false) expect(validate_expectation 1, :arbitrary_kw_args).to eq(true) end end end end describe 'a method with a block' do def arity_block(_, &block); end let(:test_method) { method(:arity_block) } it 'does not count the block as a parameter' do expect(valid_non_kw_args?(1)).to eq(true) expect(valid_non_kw_args?(2)).to eq(false) end it 'describes the arity precisely' do expect(error_description).to eq("1") end end describe 'an `attr_writer` method' do attr_writer :foo let(:test_method) { method(:foo=) } it 'validates against a single argument' do expect(valid_non_kw_args?(1)).to eq true end it 'fails validation against 0 arguments' do expect(valid_non_kw_args?(0)).to eq false end it 'fails validation against 2 arguments' do expect(valid_non_kw_args?(2)).to eq false end end if Ruby.jruby? describe 'a single-argument Java method' do let(:test_method) { Java::JavaLang::String.instance_method(:char_at) } it 'validates against a single argument' do expect(valid_non_kw_args?(1)).to eq true end it 'fails validation against 0 arguments' do expect(valid_non_kw_args?(0)).to eq false end it 'fails validation against 2 arguments' do expect(valid_non_kw_args?(2)).to eq false end end end end let(:fake_matcher) { Object.new } let(:fake_matcher_def) { lambda {|x| fake_matcher == x }} before do RSpec::Support.register_matcher_definition(&fake_matcher_def) end after do RSpec::Support.deregister_matcher_definition(&fake_matcher_def) end describe MethodSignatureExpectation do describe '#max_count' do it { expect(subject).to respond_to(:max_count).with(0).arguments } end describe '#max_count=' do it { expect(subject).to respond_to(:max_count=).with(1).argument } describe 'with nil' do before(:each) { subject.max_count = 5 } it { expect { subject.max_count = nil }.to change(subject, :max_count).to be(nil) } end describe 'with a positive integer' do let(:value) { 7 } it { expect { subject.max_count = value }.to change(subject, :max_count).to eq(value) } end describe 'with zero' do it { expect { subject.max_count = 0 }.to change(subject, :max_count).to eq(0) } end describe 'with a negative integer value' do it 'should raise an error' do expect { subject.max_count = -1 }.to raise_error ArgumentError end end describe 'with a non-integer value' do it 'should raise an error' do expect { subject.max_count = :many }.to raise_error ArgumentError end end end describe '#min_count' do it { expect(subject).to respond_to(:min_count).with(0).arguments } end describe '#min_count=' do it { expect(subject).to respond_to(:min_count=).with(1).argument } describe 'with nil' do before(:each) { subject.min_count = 5 } it { expect { subject.min_count = nil }.to change(subject, :min_count).to be(nil) } end describe 'with a positive integer' do let(:value) { 7 } it { expect { subject.min_count = value }.to change(subject, :min_count).to eq(value) } end describe 'with zero' do it { expect { subject.min_count = 0 }.to change(subject, :min_count).to eq(0) } end describe 'with a negative integer value' do it 'should raise an error' do expect { subject.min_count = -1 }.to raise_error ArgumentError end end describe 'with a non-integer value' do it 'should raise an error' do expect { subject.min_count = :many }.to raise_error ArgumentError end end end describe '#empty?' do it { expect(subject).to respond_to(:empty?).with(0).arguments } it { expect(subject.empty?).to eq(true) } describe 'with a count expectation' do before(:each) { subject.min_count = 5 } it { expect(subject.empty?).to eq(false) } end describe 'with a keywords expectation' do before(:each) { subject.keywords << :greetings << :programs } it { expect(subject.empty?).to eq(false) } end end describe '#expect_arbitrary_keywords' do it { expect(subject).to respond_to(:expect_arbitrary_keywords).with(0).arguments } it 'should default to false' do expect(described_class.new.expect_arbitrary_keywords).to eq(false) end end describe '#expect_arbitrary_keywords=' do it { expect(subject).to respond_to(:expect_arbitrary_keywords=).with(1).argument } describe 'with true' do it { expect { subject.expect_arbitrary_keywords = true }.to change(subject, :expect_arbitrary_keywords).to eq(true) } end end describe '#expect_unlimited_arguments' do it { expect(subject).to respond_to(:expect_unlimited_arguments).with(0).arguments } it 'should default to false' do expect(described_class.new.expect_unlimited_arguments).to eq(false) end end describe '#expect_unlimited_arguments=' do it { expect(subject).to respond_to(:expect_unlimited_arguments=).with(1).argument } describe 'with true' do it { expect { subject.expect_unlimited_arguments = true }.to change(subject, :expect_unlimited_arguments).to eq(true) } end end describe '#keywords' do it { expect(subject).to respond_to(:keywords).with(0).arguments } it { expect(subject.keywords).to eq(Array.new) } end describe '#keywords=' do it { expect(subject).to respond_to(:keywords=).with(1).argument } describe 'with nil' do before(:each) { subject.keywords = [:greetings, :programs] } it { expect { subject.keywords = nil }.to change(subject, :keywords).to eq(Array.new) } end describe 'with an array' do let(:keywords) { [:greetings, :programs] } it { expect { subject.keywords = keywords }.to change(subject, :keywords).to eq(keywords) } end end end describe StrictSignatureVerifier do it_behaves_like 'a method verifier' if RubyFeatures.kw_args_supported? describe 'providing a matcher for optional keyword arguments' do eval <<-RUBY def arity_kw(x, y:1); end RUBY let(:test_method) { method(:arity_kw) } it 'is not allowed' do expect(valid?(nil, fake_matcher)).to eq(false) end end end if RubyFeatures.required_kw_args_supported? describe 'providing a matcher for required keyword arguments' do eval <<-RUBY def arity_kw_required(x, y:); end RUBY let(:test_method) { method(:arity_kw_required) } it 'is not allowed' do expect(valid?(nil, fake_matcher)).to eq(false) end end end end describe LooseSignatureVerifier do it_behaves_like 'a method verifier' if RubyFeatures.kw_args_supported? describe 'for optional keyword arguments' do eval <<-RUBY def arity_kw(x, y:1, z:2); end RUBY let(:test_method) { method(:arity_kw) } it 'allows a matcher' do expect(valid?(nil, fake_matcher)).to eq(true) end it 'allows a matcher only for positional arguments' do expect(valid?(fake_matcher)).to eq(true) end end end if RubyFeatures.required_kw_args_supported? describe 'providing a matcher for required keyword arguments' do eval <<-RUBY def arity_kw_required(x, y:); end RUBY let(:test_method) { method(:arity_kw_required) } it 'is allowed' do expect(valid?(nil, fake_matcher)).to eq(true) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/deprecation_helpers_spec.rb0000664000000000000000000000510114566142077030562 0ustar rootrootrequire 'rspec/matchers/fail_matchers' RSpec.describe RSpecHelpers do def deprecate!(message) RSpec.configuration.reporter.deprecation(:message => message) end def fail_with(snippet) raise_error(RSpec::Mocks::MockExpectationError, snippet) end def raise_unrelated_expectation! raise(RSpec::Expectations::ExpectationNotMetError, 'abracadabra') end describe '#expect_no_deprecations' do shared_examples_for 'expects no deprecations' do it 'passes when there were no deprecations' do expectation end it 'fails when there was a deprecation warning' do in_sub_process do expect { expectation deprecate!('foo') }.to fail_with(/received: 1 time/) end end it 'fails with a MockExpectationError when there was also an ExpectationNotMetError' do in_sub_process do expect { expectation deprecate!('bar') raise_unrelated_expectation! }.to fail_with(/received: 1 time/) end end end it_behaves_like 'expects no deprecations' do def expectation expect_no_deprecations end end # Alias it_behaves_like 'expects no deprecations' do def expectation expect_no_deprecation end end end describe '#expect_warn_deprecation' do it 'passes when there was a deprecation warning' do in_sub_process do expect_warn_deprecation(/bar/) deprecate!('bar') end end pending 'fails when there were no deprecations' do in_sub_process do expect { expect_warn_deprecation(/bar/) }.to raise_error(/received: 0 times/) end end it 'fails with a MockExpectationError when there was also an ExpectationNotMetError' do in_sub_process do expect { expect_warn_deprecation(/bar/) deprecate!('bar') raise_unrelated_expectation! }.to raise_error(RSpec::Expectations::ExpectationNotMetError) end end it 'fails when deprecation message is different' do in_sub_process do expect { expect_warn_deprecation(/bar/) deprecate!('foo') }.to raise_error(%r{match /bar/}) end end it 'fails when deprecation message is different and an ExpectationNotMetError was raised' do in_sub_process do expect { expect_warn_deprecation(/bar/) deprecate!('foo') raise_unrelated_expectation! }.to raise_error(%r{match /bar/}) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/source_spec.rb0000664000000000000000000001041614566142077026050 0ustar rootrootrequire 'rspec/support/source' module RSpec::Support RSpec.describe Source, :if => RSpec::Support::RubyFeatures.ripper_supported? do subject(:source) do Source.new(source_string) end let(:source_string) { <<-END.gsub(/^ +\|/, '') } |2.times do | puts :foo |end END # [:program, # [[:method_add_block, # [:call, [:@int, "2", [1, 0]], :".", [:@ident, "times", [1, 2]]], # [:do_block, # nil, # [[:command, # [:@ident, "puts", [2, 2]], # [:args_add_block, # [[:symbol_literal, [:symbol, [:@ident, "foo", [2, 8]]]]], # false]]]]]]] describe '.from_file', :isolated_directory do subject(:source) do Source.from_file(path) end let(:path) do 'source.rb' end before do File.open(path, 'w') { |file| file.write(source_string) } end it 'returns a Source with the absolute path' do expect(source.lines.first).to eq('2.times do') expect(source.path).not_to eq(path) expect(source.path).to end_with(path) end it 'continues to work if File.read is stubbed' do allow(::File).to receive(:read).and_raise expect(source.lines.first).to eq('2.times do') end end describe '#lines' do it 'returns an array of lines without linefeed' do expect(source.lines).to eq([ '2.times do', ' puts :foo', 'end' ]) end it 'returns an array of lines no matter the encoding' do source_string << "\xAE" encoded_string = source_string.force_encoding('US-ASCII') expect(Source.new(encoded_string).lines).to eq([ '2.times do', ' puts :foo', 'end', '?', ]) end end describe '#ast' do it 'returns a root node' do expect(source.ast).to have_attributes(:type => :program) end end describe '#tokens' do it 'returns an array of tokens' do expect(source.tokens).to all be_a(Source::Token) end end describe '#nodes_by_line_number' do it 'returns a hash containing nodes for each line number' do expect(source.nodes_by_line_number).to match( 1 => if RUBY_VERSION >= '2.6.0' [ an_object_having_attributes(:type => :@int), an_object_having_attributes(:type => :@period), an_object_having_attributes(:type => :@ident) ] else [ an_object_having_attributes(:type => :@int), an_object_having_attributes(:type => :@ident) ] end, 2 => [ an_object_having_attributes(:type => :@ident), an_object_having_attributes(:type => :@ident) ] ) expect(source.nodes_by_line_number[0]).to be_empty end end describe '#tokens_by_line_number' do it 'returns a hash containing tokens for each line number' do expect(source.tokens_by_line_number).to match( 1 => [ an_object_having_attributes(:type => :on_int), an_object_having_attributes(:type => :on_period), an_object_having_attributes(:type => :on_ident), an_object_having_attributes(:type => :on_sp), an_object_having_attributes(:type => :on_kw), an_object_having_attributes(:type => :on_ignored_nl) ], 2 => [ an_object_having_attributes(:type => :on_sp), an_object_having_attributes(:type => :on_ident), an_object_having_attributes(:type => :on_sp), an_object_having_attributes(:type => :on_symbeg), an_object_having_attributes(:type => :on_ident), an_object_having_attributes(:type => :on_nl) ], 3 => [ an_object_having_attributes(:type => :on_kw), an_object_having_attributes(:type => :on_nl) ] ) expect(source.tokens_by_line_number[0]).to be_empty end end describe '#inspect' do it 'returns a string including class name and file path' do expect(source.inspect).to start_with('#') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/differ_spec.rb0000664000000000000000000004277014566142077026017 0ustar rootroot# encoding: utf-8 require 'spec_helper' require 'ostruct' require 'timeout' require 'rspec/support/spec/string_matcher' module RSpec module Support RSpec.describe Differ do include Spec::DiffHelpers describe '#diff' do let(:differ) { RSpec::Support::Differ.new } it "outputs unified diff of two strings" do expected = "foo\nzap\nbar\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nanother\nline\n" actual = "foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n" if Diff::LCS::VERSION.to_f < 1.4 || Diff::LCS::VERSION >= "1.4.4" expected_diff = dedent(<<-'EOD') | | |@@ -1,6 +1,6 @@ | foo |-zap | bar |+zap | this | is | soo |@@ -9,6 +9,5 @@ | equal | insert | a |-another | line | EOD else expected_diff = dedent(<<-'EOD') | | |@@ -1,4 +1,6 @@ | foo |-zap | bar |+zap | this |@@ -9,6 +11,7 @@ | equal | insert | a |-another | line | EOD end diff = differ.diff(actual, expected) expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff of two strings when used multiple times" do expected = "foo\nzap\nbar\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nanother\nline\n" actual = "foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n" if Diff::LCS::VERSION.to_f < 1.4 || Diff::LCS::VERSION >= "1.4.4" expected_diff = dedent(<<-'EOS') | | |@@ -1,6 +1,6 @@ | foo |-zap | bar |+zap | this | is | soo |@@ -9,6 +9,5 @@ | equal | insert | a |-another | line | EOS else expected_diff = dedent(<<-'EOS') | | |@@ -1,4 +1,6 @@ | foo |-zap | bar |+zap | this |@@ -9,6 +11,7 @@ | equal | insert | a |-another | line | EOS end diff = differ.diff(actual, expected) expect(diff).to be_diffed_as(expected_diff) end it 'does not mutate any instance variables when diffing, so we can reason about it being reused' do expected = "foo\nzap\nbar\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nanother\nline\n" actual = "foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n" expect { differ.diff(actual, expected) }.not_to change { differ_ivars } end def differ_ivars Hash[ differ.instance_variables.map do |ivar| [ivar, differ.instance_variable_get(ivar)] end ] end if String.method_defined?(:encoding) it "returns an empty string if strings are not multiline" do expected = "Tu avec carte {count} item has".encode('UTF-16LE') actual = "Tu avec carté {count} itém has".encode('UTF-16LE') diff = differ.diff(actual, expected) expect(diff).to be_empty end it 'copes with encoded strings', :skip => RSpec::Support::OS.windows? do expected = "Tu avec carte {count} item has\n".encode('UTF-16LE') actual = "Tu avec carté {count} itém has\n".encode('UTF-16LE') expected_diff = dedent(<<-EOD).encode('UTF-16LE') | |@@ #{one_line_header} @@ |-Tu avec carte {count} item has |+Tu avec carté {count} itém has | EOD diff = differ.diff(actual, expected) expect(diff).to be_diffed_as(expected_diff) end it 'handles differently encoded strings that are compatible' do expected = "abc\n".encode('us-ascii') actual = "강인철\n".encode('UTF-8') expected_diff = "\n@@ #{one_line_header} @@\n-abc\n+강인철\n" diff = differ.diff(actual, expected) expect(diff).to be_diffed_as(expected_diff) end it 'uses the default external encoding when the two strings have incompatible encodings' do expected = "Tu avec carte {count} item has\n" actual = "Tu avec carté {count} itém has\n".encode('UTF-16LE') expected_diff = "\n@@ #{one_line_header} @@\n-Tu avec carte {count} item has\n+Tu avec carté {count} itém has\n" diff = differ.diff(actual, expected) expect(diff).to be_diffed_as(expected_diff) expect(diff.encoding).to eq(Encoding.default_external) end it 'handles any encoding error that occurs with a helpful error message' do expect(RSpec::Support::HunkGenerator).to receive(:new). and_raise(Encoding::CompatibilityError) expected = "Tu avec carte {count} item has\n".encode('us-ascii') actual = "Tu avec carté {count} itém has\n" diff = differ.diff(actual, expected) expect(diff).to match(/Could not produce a diff/) expect(diff).to match(/actual string \(UTF-8\)/) expect(diff).to match(/expected string \(US-ASCII\)/) end end it "outputs unified diff message of two objects" do animal_class = Class.new do include RSpec::Support::FormattingSupport def initialize(name, species) @name, @species = name, species end def inspect dedent(<<-EOA) | EOA end end expected = animal_class.new "bob", "giraffe" actual = animal_class.new "bob", "tortoise" expected_diff = dedent(<<-'EOD') | |@@ -1,5 +1,5 @@ | | EOD diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff message of two arrays" do expected = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'charlie', :width, 'quite wide' ] actual = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'tango' , :width, 'very wide' ] expected_diff = dedent(<<-'EOD') | | |@@ -5,7 +5,7 @@ | :metasyntactic, | "variable", | :delta, |- "tango", |+ "charlie", | :width, |- "very wide"] |+ "quite wide"] | EOD diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end it 'outputs a unified diff message for an array which flatten recurses' do klass = Class.new do def to_ary; [self]; end def inspect; ""; end end obj = klass.new diff = '' Timeout::timeout(1) do diff = differ.diff [obj], [] end expected_diff = dedent(<<-EOD) | |@@ #{one_line_header} @@ |-[] |+[] | EOD expect(diff).to be_diffed_as(expected_diff) end it 'outputs unified diff message of strings in arrays' do diff = differ.diff(["a\r\nb"], ["a\r\nc"]) expected_diff = dedent(<<-EOD) | |@@ #{one_line_header} @@ |-a\\r\\nc |+a\\r\\nb | EOD expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff message of two hashes" do expected = { :foo => 'bar', :baz => 'quux', :metasyntactic => 'variable', :delta => 'charlie', :width =>'quite wide' } actual = { :foo => 'bar', :metasyntactic => 'variable', :delta => 'charlotte', :width =>'quite wide' } expected_diff = dedent(<<-'EOD') | |@@ -1,4 +1,5 @@ |-:delta => "charlotte", |+:baz => "quux", |+:delta => "charlie", | :foo => "bar", | :metasyntactic => "variable", | :width => "quite wide", | EOD diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end unless RUBY_VERSION == '1.8.7' # We can't count on the ordering of the hash on 1.8.7... it "outputs unified diff message for hashes inside arrays with differing key orders" do expected = [{ :foo => 'bar', :baz => 'quux', :metasyntactic => 'variable', :delta => 'charlie', :width =>'quite wide' }] actual = [{ :metasyntactic => 'variable', :delta => 'charlotte', :width =>'quite wide', :foo => 'bar' }] expected_diff = dedent(<<-'EOD') | |@@ -1,4 +1,5 @@ |-[{:delta=>"charlotte", |+[{:baz=>"quux", |+ :delta=>"charlie", | :foo=>"bar", | :metasyntactic=>"variable", | :width=>"quite wide"}] | EOD diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end end it 'outputs unified diff message of two hashes with differing encoding' do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-"a" => "a", |#{ (RUBY_VERSION.to_f > 1.8) ? %Q{+"ö" => "ö"} : '+"\303\266" => "\303\266"' }, | EOD diff = differ.diff({'ö' => 'ö'}, {'a' => 'a'}) expect(diff).to be_diffed_as(expected_diff) end it 'outputs unified diff message of two hashes with encoding different to key encoding' do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-:a => "a", |#{ (RUBY_VERSION.to_f > 1.8) ? %Q{+\"한글\" => \"한글2\"} : '+"\355\225\234\352\270\200" => "\355\225\234\352\270\2002"' }, | EOD diff = differ.diff({ "한글" => "한글2"}, { :a => "a"}) expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff message of two hashes with object keys" do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-["a", "c"] => "b", |+["d", "c"] => "b", | EOD diff = differ.diff({ ['d','c'] => 'b'}, { ['a','c'] => 'b' }) expect(diff).to be_diffed_as(expected_diff) end context 'when special-case objects are inside hashes' do let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it "outputs unified diff message of two hashes with Time object keys" do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-#{formatted_time} => "b", |+#{formatted_time} => "c", | EOD diff = differ.diff({ time => 'c'}, { time => 'b' }) expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff message of two hashes with hashes inside them" do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-"b" => {"key_1"=>#{formatted_time}}, |+"c" => {"key_1"=>#{formatted_time}}, | EOD left_side_hash = {'c' => {'key_1' => time}} right_side_hash = {'b' => {'key_1' => time}} diff = differ.diff(left_side_hash, right_side_hash) expect(diff).to be_diffed_as(expected_diff) end end context 'when special-case objects are inside arrays' do let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it "outputs unified diff message of two arrays with Time object keys" do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-[#{formatted_time}, "b"] |+[#{formatted_time}, "c"] | EOD diff = differ.diff([time, 'c'], [time, 'b']) expect(diff).to be_diffed_as(expected_diff) end it "outputs unified diff message of two arrays with hashes inside them" do expected_diff = dedent(<<-"EOD") | |@@ #{one_line_header} @@ |-[{"b"=>#{formatted_time}}, "c"] |+[{"a"=>#{formatted_time}}, "c"] | EOD left_side_array = [{'a' => time}, 'c'] right_side_array = [{'b' => time}, 'c'] diff = differ.diff(left_side_array, right_side_array) expect(diff).to be_diffed_as(expected_diff) end end it "outputs unified diff of multi line strings" do expected = "this is:\n one string" actual = "this is:\n another string" expected_diff = dedent(<<-'EOD') | |@@ -1,3 +1,3 @@ | this is: |- another string |+ one string | EOD diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end it "splits items with newlines" do expected_diff = dedent(<<-"EOD") | |@@ #{removing_two_line_header} @@ |-a\\nb |-c\\nd | EOD diff = differ.diff [], ["a\nb", "c\nd"] expect(diff).to be_diffed_as(expected_diff) end it "shows inner arrays on a single line" do expected_diff = dedent(<<-"EOD") | |@@ #{removing_two_line_header} @@ |-a\\nb |-["c\\nd"] | EOD diff = differ.diff [], ["a\nb", ["c\nd"]] expect(diff).to be_diffed_as(expected_diff) end it "returns an empty string if no expected or actual" do diff = differ.diff nil, nil expect(diff).to be_empty end it "returns an empty string if expected is Numeric" do diff = differ.diff 1, "2" expect(diff).to be_empty end it "returns an empty string if actual is Numeric" do diff = differ.diff "1", 2 expect(diff).to be_empty end it "returns an empty string if expected or actual are procs" do diff = differ.diff lambda {}, lambda {} expect(diff).to be_empty end it "returns a String if no diff is returned" do diff = differ.diff 1, 2 expect(diff).to be_a(String) end it "returns a String if a diff is performed" do diff = differ.diff "a\n", "b\n" expect(diff).to be_a(String) end it "includes object delegation information in the diff output" do in_sub_process_if_possible do require "delegate" object = Object.new delegator = SimpleDelegator.new(object) expected_diff = dedent(<<-EOS) | |@@ #{one_line_header} @@ |-[#] |+[#{object.inspect}] | EOS diff = differ.diff [object], [delegator] expect(diff).to eq(expected_diff) end end context "with :object_preparer option set" do let(:differ) do RSpec::Support::Differ.new(:object_preparer => lambda { |s| s.to_s.reverse }) end it "uses the output of object_preparer for diffing" do expected = :foo actual = :poo expected_diff = dedent(<<-EOS) | |@@ #{one_line_header} @@ |-"oop" |+"oof" | EOS diff = differ.diff(expected, actual) expect(diff).to be_diffed_as(expected_diff) end end context "with :color option set" do let(:differ) { RSpec::Support::Differ.new(:color => true) } it "outputs colored diffs" do expected = "foo bar baz\n" actual = "foo bang baz\n" expected_diff = "\e[0m\n\e[0m\e[34m@@ #{one_line_header} @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m" diff = differ.diff(expected,actual) expect(diff).to be_diffed_as(expected_diff) end end context 'when expected or actual is false' do it 'generates a diff' do expect(differ.diff(true, false)).to_not be_empty expect(differ.diff(false, true)).to_not be_empty end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/comparable_version_spec.rb0000664000000000000000000000262314566142077030423 0ustar rootrootrequire 'rspec/support/comparable_version' module RSpec::Support RSpec.describe ComparableVersion do describe '#<=>' do [ ['1.2.3', '1.2.3', 0], ['1.2.4', '1.2.3', 1], ['1.3.0', '1.2.3', 1], ['1.2.3', '1.2.4', -1], ['1.2.3', '1.3.0', -1], ['1.2.10', '1.2.3', 1], ['1.2.3', '1.2.10', -1], ['1.2.3.0', '1.2.3', 0], ['1.2.3', '1.2.3.0', 0], ['1.2.3.1', '1.2.3', 1], ['1.2.3.1', '1.2.3.0', 1], ['1.2.3', '1.2.3.1', -1], ['1.2.3.0', '1.2.3.1', -1], ['1.2.3.rc1', '1.2.3', -1], ['1.2.3.rc1', '1.2.3.rc2', -1], ['1.2.3.rc2', '1.2.3.rc10', -1], ['1.2.3.alpha2', '1.2.3.beta1', -1], ['1.2.3', '1.2.3.rc1', 1], ['1.2.3.rc2', '1.2.3.rc1', 1], ['1.2.3.rc10', '1.2.3.rc2', 1], ['1.2.3.beta1', '1.2.3.alpha2', 1] ].each do |subject_string, other_string, expected| context "with #{subject_string.inspect} and #{other_string.inspect}" do subject do ComparableVersion.new(subject_string) <=> ComparableVersion.new(other_string) end it { is_expected.to eq(expected) } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/ruby_features_spec.rb0000664000000000000000000001362514566142077027434 0ustar rootrootrequire 'rspec/support/ruby_features' module RSpec module Support RSpec.describe OS do describe ".windows?" do %w[cygwin mswin mingw bccwin wince emx].each do |fragment| it "returns true when host os is #{fragment}" do stub_const("RbConfig::CONFIG", 'host_os' => fragment) expect(OS.windows?).to be true end end %w[darwin linux].each do |fragment| it "returns false when host os is #{fragment}" do stub_const("RbConfig::CONFIG", 'host_os' => fragment) expect(OS.windows?).to be false end end end describe ".windows_file_path?" do it "returns true when the file alt separator is a colon" do stub_const("File::ALT_SEPARATOR", "\\") unless OS.windows? expect(OS).to be_windows_file_path end it "returns false when file alt separator is not present" do stub_const("File::ALT_SEPARATOR", nil) if OS.windows? expect(OS).to_not be_windows_file_path end end end RSpec.describe Ruby do specify "jruby? reflects the state of RUBY_PLATFORM" do stub_const("RUBY_PLATFORM", "java") expect(Ruby).to be_jruby stub_const("RUBY_PLATFORM", "") expect(Ruby).to_not be_jruby end specify "rbx? reflects the state of RUBY_ENGINE" do stub_const("RUBY_ENGINE", "rbx") expect(Ruby).to be_rbx hide_const("RUBY_ENGINE") expect(Ruby).to_not be_rbx end specify "jruby_9000? reflects the state of RUBY_PLATFORM and JRUBY_VERSION" do stub_const("RUBY_PLATFORM", "java") stub_const("JRUBY_VERSION", "") expect(Ruby).to_not be_jruby_9000 stub_const("JRUBY_VERSION", "9.0.3.0") expect(Ruby).to be_jruby_9000 stub_const("RUBY_PLATFORM", "") expect(Ruby).to_not be_jruby_9000 end specify "rbx? reflects the state of RUBY_ENGINE" do hide_const("RUBY_ENGINE") expect(Ruby).to be_mri stub_const("RUBY_ENGINE", "ruby") expect(Ruby).to be_mri stub_const("RUBY_ENGINE", "rbx") expect(Ruby).to_not be_mri end end RSpec.describe RubyFeatures do specify "#module_refinement_supported? reflects refinement support" do if Ruby.mri? && RUBY_VERSION >= '2.1.0' expect(RubyFeatures.module_refinement_supported?).to eq true end end specify "#fork_supported? exists" do RubyFeatures.fork_supported? end specify "#supports_exception_cause? exists" do RubyFeatures.supports_exception_cause? end specify "#kw_args_supported? exists" do RubyFeatures.kw_args_supported? end specify "#required_kw_args_supported? exists" do RubyFeatures.required_kw_args_supported? end specify "distincts_kw_args_from_positional_hash?" do RubyFeatures.distincts_kw_args_from_positional_hash? end specify "#supports_rebinding_module_methods? exists" do RubyFeatures.supports_rebinding_module_methods? end specify "#supports_syntax_suggest?" do expect(RubyFeatures.supports_syntax_suggest?).to eq(RUBY_VERSION.to_f >= 3.2) end specify "#supports_taint?" do RubyFeatures.supports_taint? end specify "#caller_locations_supported? exists" do RubyFeatures.caller_locations_supported? if Ruby.mri? expect(RubyFeatures.caller_locations_supported?).to eq(RUBY_VERSION >= '2.0.0') end end describe "#ripper_supported?" do def ripper_is_implemented? in_sub_process_if_possible do begin require 'ripper' !!defined?(::Ripper) && Ripper.respond_to?(:lex) rescue LoadError false end end end def ripper_works_correctly? ripper_reports_correct_line_number? && ripper_can_parse_source_including_keywordish_symbol? && ripper_can_parse_source_referencing_keyword_arguments? end # https://github.com/jruby/jruby/issues/3386 def ripper_reports_correct_line_number? in_sub_process_if_possible do require 'ripper' tokens = ::Ripper.lex('foo') token = tokens.first location = token.first line_number = location.first line_number == 1 end end # https://github.com/jruby/jruby/issues/4562 def ripper_can_parse_source_including_keywordish_symbol? in_sub_process_if_possible do require 'ripper' sexp = ::Ripper.sexp(':if') !sexp.nil? end end # https://github.com/jruby/jruby/issues/5209 def ripper_can_parse_source_referencing_keyword_arguments? in_sub_process_if_possible do require 'ripper' # It doesn't matter if keyword arguments don't exist. if Ruby.mri? || Ruby.jruby? || Ruby.truffleruby? if RUBY_VERSION < '2.0' true else begin !::Ripper.sexp('def a(**kw_args); end').nil? rescue NoMethodError false end end end end end it 'returns whether Ripper is correctly implemented in the current environment' do if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version.between?('9.0.0.0', '9.2.1.0') pending "Ripper is not supported on JRuby 9.1.17.0 despite this tests claims" end expect(RubyFeatures.ripper_supported?).to eq(ripper_is_implemented? && ripper_works_correctly?) end it 'does not load Ripper' do expect { RubyFeatures.ripper_supported? }.not_to change { defined?(::Ripper) } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/matcher_definition_spec.rb0000664000000000000000000000230414566142077030400 0ustar rootrootrequire "spec_helper" module RSpec module Support RSpec.describe "matcher definitions" do RSpec::Matchers.define :fake_matcher do |expected| match { |actual| expected == actual } description { :fake_matcher } end RSpec::Matchers.define :matcher_with_no_description do match { true } undef description end describe ".rspec_description_for_object" do it "returns the object for a non matcher object" do o = Object.new expect(RSpec::Support.rspec_description_for_object(o)).to be o end it "returns the object's description for a matcher object that has a description" do expect(RSpec::Support.rspec_description_for_object(fake_matcher(nil))).to eq :fake_matcher end it "returns the object for a matcher that does not have a description" do matcher = matcher_with_no_description expect(matcher_with_no_description).not_to respond_to(:description) expect(RSpec::Support.is_a_matcher?(matcher_with_no_description)).to eq true expect(RSpec::Support.rspec_description_for_object(matcher)).to be matcher end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/directory_maker_spec.rb0000664000000000000000000000312014566142077027725 0ustar rootrootrequire "spec_helper" require "fileutils" RSpec::Support.require_rspec_support("directory_maker") module RSpec::Support RSpec.describe DirectoryMaker do shared_examples_for "an mkdir_p implementation" do include_context "isolated directory" let(:dirname) { File.join(%w[tmp a recursive structure]) } def directory_exists?(dirname) File.exist?(dirname) && File.directory?(dirname) end it "makes directories recursively" do mkdir_p.call(dirname) expect(directory_exists?(dirname)).to be true end it "does not raise if the directory already exists" do Dir.mkdir("tmp") mkdir_p.call(dirname) expect(directory_exists?(dirname)).to be true end context "when a file already exists" do before { File.open("tmp", "w") } it "raises, as it can't make the directory", :failing_on_windows_ci do expect { mkdir_p.call(dirname) }.to raise_error(Errno::EEXIST) end end context "when the path specified is absolute" do let(:dirname) { "bees/ponies" } it "makes directories recursively" do mkdir_p.call(File.expand_path(dirname)) expect(directory_exists?(dirname)).to be true end end end describe ".mkdir_p" do subject(:mkdir_p) { DirectoryMaker.method(:mkdir_p) } it_behaves_like "an mkdir_p implementation" end describe "FileUtils.mkdir_p" do subject(:mkdir_p) { FileUtils.method(:mkdir_p) } it_behaves_like "an mkdir_p implementation" end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/spec/0000775000000000000000000000000014566142077024141 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/spec/stderr_splitter_spec.rb0000664000000000000000000000540014566142077030730 0ustar rootrootrequire 'rspec/support/spec/stderr_splitter' require 'tempfile' require 'rspec/support/spec/in_sub_process' RSpec.describe 'RSpec::Support::StdErrSplitter' do include RSpec::Support::InSubProcess let(:splitter) { RSpec::Support::StdErrSplitter.new stderr } let(:stderr) { STDERR } before do allow(stderr).to receive(:write) end around do |example| original = $stderr $stderr = splitter example.run $stderr = original end it 'conforms to the stderr interface' do # There some methods that appear in the list of the #methods but actually not implemented: # # $stderr.pressed? # NotImplementedError: pressed?() function is unimplemented on this machine stderr_methods = stderr.methods.select { |method| stderr.respond_to?(method) } # On 2.2, there's a weird issue where stderr sometimes responds to `birthtime` and sometimes doesn't... stderr_methods -= [:birthtime] if RUBY_VERSION =~ /^2\.2/ # No idea why, but on our AppVeyor windows builds it doesn't respond to these... stderr_methods -= [:close_on_exec?, :close_on_exec=] if RSpec::Support::OS.windows? && ENV['CI'] expect(splitter).to respond_to(*stderr_methods) end it 'acknowledges its own interface' do expect(splitter).to respond_to :==, :write, :has_output?, :reset!, :verify_no_warnings!, :output end it 'supports methods that stderr supports but StringIO does not' do expect(StringIO.new).not_to respond_to(:stat) expect(splitter.stat).to be_a(File::Stat) end it 'supports #to_io' do expect(splitter.to_io).to be(stderr.to_io) end it 'behaves like stderr' do splitter.write 'a warning' expect(stderr).to have_received(:write) end it 'pretends to be stderr' do expect(splitter).to eq stderr end it 'resets when reopened' do in_sub_process(false) do warn 'a warning' allow(stderr).to receive(:write).and_call_original Tempfile.open('stderr') do |file| splitter.reopen(file) expect { splitter.verify_no_warnings! }.not_to raise_error end end end it 'tracks when output to' do splitter.write 'a warning' expect(splitter).to have_output end it 'will ignore examples without a warning' do splitter.verify_no_warnings! end it 'will ignore examples after a reset a warning' do warn 'a warning' splitter.reset! splitter.verify_no_warnings! end unless RSpec::Support::Ruby.rbx? || RSpec::Support::Ruby.truffleruby? # TruffleRuby doesn't support warnings for now # https://github.com/oracle/truffleruby/issues/2595 it 'will fail an example which generates a warning' do true unless $undefined expect { splitter.verify_no_warnings! }.to raise_error(/Warnings were generated:/) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/spec/shell_out_spec.rb0000664000000000000000000000344314566142077027502 0ustar rootrootrequire 'rspec/support/spec/shell_out' RSpec.describe RSpec::Support::ShellOut, :slow do include described_class it 'shells out and returns stdout and stderr' do stdout, stderr, _ = shell_out("ruby", "-e", "$stdout.print 'yes'; $stderr.print 'no'") expect(stdout).to eq("yes") expect(stderr).to eq("no") end it 'returns the exit status as the third argument' do _, _, good_status = shell_out("ruby", "-e", '3 + 3') expect(good_status.exitstatus).to eq(0) unless RUBY_VERSION.to_f < 1.9 # except 1.8... _, _, bad_status = shell_out("ruby", "-e", 'boom') expect(bad_status.exitstatus).to eq(1) end end it 'can shell out to ruby with the current load path' do skip "Need to investigate why this is failing -- see " \ "https://travis-ci.org/rspec/rspec-core/jobs/60327106 and " \ "https://travis-ci.org/rspec/rspec-support/jobs/60296920 for examples" out, err, status = run_ruby_with_current_load_path('puts $LOAD_PATH.sort.join("\n")') expect(err).to eq("") expect(out).to include(*$LOAD_PATH.first(10)) expect(status.exitstatus).to eq(0) end it 'passes along the provided ruby flags' do out, err, status = run_ruby_with_current_load_path('puts "version"', '-v') expect(out).to include('version', RUBY_DESCRIPTION) expect(strip_known_warnings err).to eq('') expect(status.exitstatus).to eq(0) end it 'filters out the annoying output issued by `ruby -w` when the GC ENV vars are set' do with_env 'RUBY_GC_HEAP_FREE_SLOTS' => '10001', 'RUBY_GC_MALLOC_LIMIT' => '16777217', 'RUBY_FREE_MIN' => '10001' do out, err, status = run_ruby_with_current_load_path('', '-w') expect(out).to eq('') expect(strip_known_warnings err).to eq('') expect(status.exitstatus).to eq(0) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/spec/with_isolated_std_err_spec.rb0000664000000000000000000000076714566142077032073 0ustar rootrootrequire 'rspec/support/spec' RSpec.describe 'isolating a spec from the stderr splitter' do include RSpec::Support::WithIsolatedStdErr it 'allows a spec to output a warning' do with_isolated_stderr do $stderr.puts "Imma gonna warn you" end end it 'resets $stderr to its original value even if an error is raised' do orig_stderr = $stderr expect { with_isolated_stderr { raise "boom" } }.to raise_error("boom") expect($stderr).to be(orig_stderr) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/spec/in_sub_process_spec.rb0000664000000000000000000000277014566142077030523 0ustar rootrootrequire 'tempfile' RSpec.describe 'isolating code to a sub process' do it 'isolates the block from the main process' do in_sub_process do module NotIsolated end expect(defined? NotIsolated).to eq "constant" end expect(defined? NotIsolated).to be_nil end if Process.respond_to?(:fork) && !(RUBY_PLATFORM == 'java' && RUBY_VERSION == '1.8.7') it 'returns the result of sub process' do expect(in_sub_process { :foo }).to eq(:foo) end it 'returns a UnmarshableObject if the result of sub process cannot be marshaled' do expect(in_sub_process { proc {} }).to be_a(RSpec::Support::InSubProcess::UnmarshableObject) end it 'captures and reraises errors to the main process' do expect { in_sub_process { raise "An Internal Error" } }.to raise_error "An Internal Error" end it 'captures and reraises test failures' do expect { in_sub_process { expect(true).to be false } }.to raise_error(/expected false/) end it 'fails if the sub process generates warnings' do expect { in_sub_process do # Redirect stderr so we don't get "boom" in our test suite output $stderr.reopen(Tempfile.new("stderr")) warn "boom" end }.to raise_error(RuntimeError, a_string_including("Warnings", "boom")) end else it 'pends the block' do expect { in_sub_process { true } }.to raise_error(/This spec requires forking to work properly/) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/with_keywords_when_needed_spec.rb0000664000000000000000000000273014566142077031777 0ustar rootrootrequire 'rspec/support/with_keywords_when_needed' module RSpec::Support RSpec.describe "WithKeywordsWhenNeeded" do describe ".class_exec" do extend RubyFeatures let(:klass) do Class.new do def self.check_argument(argument) raise ArgumentError unless argument == 42 end end end def run(klass, *args, &block) WithKeywordsWhenNeeded.class_exec(klass, *args, &block) end it "will run a block without keyword arguments" do run(klass, 42) { |arg| check_argument(arg) } end it "will run a block with a hash without keyword arguments" do run(klass, "value" => 42) { |arg| check_argument(arg["value"]) } end it "will run a block with optional keyword arguments when none are provided", :if => kw_args_supported? do binding.eval(<<-CODE, __FILE__, __LINE__) run(klass, 42) { |arg, val: nil| check_argument(arg) } CODE end it "will run a block with optional keyword arguments when they are provided", :if => required_kw_args_supported? do binding.eval(<<-CODE, __FILE__, __LINE__) run(klass, val: 42) { |val: nil| check_argument(val) } CODE end it "will run a block with required keyword arguments", :if => required_kw_args_supported? do binding.eval(<<-CODE, __FILE__, __LINE__) run(klass, val: 42) { |val:| check_argument(val) } CODE end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/caller_filter_spec.rb0000664000000000000000000000423314566142077027357 0ustar rootrootrequire 'spec_helper' require 'fileutils' require 'rspec/support/caller_filter' module RSpec describe CallerFilter do it 'can receive skip_frames and increment arguments' do expect(RSpec::CallerFilter.first_non_rspec_line(1, 5)).to include("#{__FILE__}:#{__LINE__}") end it 'returns the immediate caller when called from a spec' do expect(RSpec::CallerFilter.first_non_rspec_line).to include("#{__FILE__}:#{__LINE__}") end describe "the filtering regex" do def ruby_files_in_lib(lib) # http://rubular.com/r/HYpUMftlG2 path = $LOAD_PATH.find { |p| p.match(/\/rspec-#{lib}(-[a-f0-9]+)?\/lib/) } Dir["#{path}/**/*.rb"].sort.tap do |files| # Just a sanity check... expect(files.count).to be > 5 end end def unmatched_from(files) files.reject { |file| file.match(CallerFilter::IGNORE_REGEX) } end %w[ core mocks expectations support ].each do |lib| it "matches all ruby files in rspec-#{lib}" do files = ruby_files_in_lib(lib) expect(unmatched_from files).to eq([]) end end it "does not match other ruby files" do files = %w[ /path/to/lib/rspec/some-extension/foo.rb /path/to/spec/rspec/core/some_spec.rb ] expect(unmatched_from files).to eq(files) end def in_rspec_support_lib(name) root = File.expand_path("../../../../lib/rspec/support", __FILE__) dir = "#{root}/#{name}" FileUtils.mkdir(dir) yield dir ensure FileUtils.rm_rf(dir) end it 'does not match rubygems lines from `require` statements' do with_isolated_stderr do require 'rubygems' # ensure rubygems is loaded end in_rspec_support_lib("test_dir") do |dir| File.open("#{dir}/file.rb", "w") do |file| file.write("$_caller_filter = RSpec::CallerFilter.first_non_rspec_line") end $_caller_filter = nil expect { require "rspec/support/test_dir/file" }.to change { $_caller_filter }.to(include __FILE__) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/object_formatter_spec.rb0000664000000000000000000003067714566142077030114 0ustar rootrootrequire 'rspec/support/object_formatter' require 'rspec/matchers/fail_matchers' module RSpec module Support RSpec.describe ObjectFormatter, ".format" do context 'with an array object containing other objects for which we have custom formatting' do let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } let(:input) { ["string", time, [3, time]] } it 'formats those objects within the array output, at any level of nesting' do formatted = ObjectFormatter.format(input) expect(formatted).to eq(%Q{["string", #{formatted_time}, [3, #{formatted_time}]]}) end end context "with a hash object containing other objects for which we have custom formatting" do let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } let(:input) { { "key" => time, time => "value", "nested" => { "key" => time } } } it 'formats those objects within the hash output, at any level of nesting' do formatted = ObjectFormatter.format(input) if RUBY_VERSION == '1.8.7' # We can't count on the ordering of the hash on 1.8.7... expect(formatted).to include(%Q{"key"=>#{formatted_time}}, %Q{#{formatted_time}=>"value"}, %Q{"nested"=>{"key"=>#{formatted_time}}}) else expect(formatted).to eq(%Q{{"key"=>#{formatted_time}, #{formatted_time}=>"value", "nested"=>{"key"=>#{formatted_time}}}}) end end end unless RUBY_VERSION == '1.8.7' # We can't count on the ordering of the hash on 1.8.7... context 'with a hash object' do let(:input) { { :c => "ccc", :a => "aaa", "b" => 'bbb' } } let(:expected) { '{:a=>"aaa", "b"=>"bbb", :c=>"ccc"}' } it 'sorts keys to ensure objects are always displayed the same way' do formatted = ObjectFormatter.format(input) expect(formatted).to eq expected end end end context 'with Time objects' do let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it 'produces an extended output' do expected_output = "1969-12-31 19:01:40.000101" expect(formatted_time).to include(expected_output) end end context 'with DateTime objects' do def with_date_loaded in_sub_process_if_possible do require 'date' yield end end let(:date_time) { DateTime.new(2000, 1, 1, 1, 1, Rational(1, 10)) } let(:formatted_date_time) { ObjectFormatter.format(date_time) } it 'formats the DateTime using inspect' do with_date_loaded do expect(formatted_date_time).to eq(date_time.inspect) end end it 'does not require DateTime to be defined since you need to require `date` to make it available' do hide_const('DateTime') expect(ObjectFormatter.format('Test String')).to eq('"Test String"') end context 'when ActiveSupport is loaded' do it "uses a custom format to ensure the output is different when DateTimes differ" do stub_const("ActiveSupport", Module.new) with_date_loaded do expected_date_time = 'Sat, 01 Jan 2000 01:01:00.100000000 +0000' expect(formatted_date_time).to eq(expected_date_time) end end end end context 'with BigDecimal objects' do let(:float) { 3.3 } let(:decimal) { BigDecimal("3.3") } let(:formatted_decimal) { ObjectFormatter.format(decimal) } if RUBY_VERSION >= '2.4' it "uses Ruby's BigDecimal formatting since it is improved in 2.4+" do in_sub_process_if_possible do require 'bigdecimal' expect(formatted_decimal).to eq('0.33e1') end end else it 'includes a conventional representation of the decimal' do in_sub_process_if_possible do require 'bigdecimal' # Suppress warning on JRuby 1.7: # file:/Users/me/.rbenv/versions/jruby-1.7.26/lib/jruby.jar!/jruby/bigdecimal.rb:1 # warning: loading in progress, circular require considered harmful - bigdecimal.jar $stderr.reset! expect(formatted_decimal).to include('3.3 (#" end end it 'includes the delegator class in the description even when protected' do with_delegate_loaded do protected_delegator = Class.new(SimpleDelegator) { protected :__getobj__ } expect( ObjectFormatter.format(protected_delegator.new(object)) ).to eq "#<#{protected_delegator.inspect}(#{object.inspect})>" end end it 'does not require Delegator to be defined' do hide_const("Delegator") expect(ObjectFormatter.format(object)).to eq object.inspect end context 'for a specially-formatted object' do let(:decimal) { BigDecimal("3.3") } let(:formatted_decimal) { ObjectFormatter.format(decimal) } let(:object) { decimal } it 'formats the underlying object normally' do with_delegate_loaded do require 'bigdecimal' # Suppress warning on JRuby 1.7: # file:/Users/me/.rbenv/versions/jruby-1.7.26/lib/jruby.jar!/jruby/bigdecimal.rb:1 # warning: loading in progress, circular require considered harmful - bigdecimal.jar $stderr.reset! expect(ObjectFormatter.format(delegator)).to eq "#" end end end end context 'with objects that implement description' do RSpec::Matchers.define :matcher_with_description do match { true } description { "description" } end RSpec::Matchers.define :matcher_without_a_description do match { true } undef description end it "produces a description when a matcher object has a description" do expect(ObjectFormatter.format(matcher_with_description)).to eq("description") end it "does not produce a description unless the object is a matcher" do double = double('non-matcher double', :description => true) expect(ObjectFormatter.format(double)).to eq(double.inspect) end it "produces an inspected object when a matcher is missing a description" do expect(ObjectFormatter.format(matcher_without_a_description)).to eq( matcher_without_a_description.inspect) end end context 'with an object that does not respond to #class and #inspect such as BasicObject' do subject(:output) do ObjectFormatter.format(input) end let(:input) do if defined?(BasicObject) BasicObject.new else fake_basic_object_class.new end end let(:fake_basic_object_class) do Class.new do def self.to_s 'BasicObject' end undef class, inspect, respond_to? end end if RUBY_VERSION == '1.9.2' it 'produces an #inspect-like output without object id' do expect(output).to eq('#') end else it "produces an output emulating MRI's #inspect-like output generated by C implementation" do expect(output).to match(/\A#\z/) end end end context 'with a recursive array' do subject(:output) do ObjectFormatter.format(input) end let(:input) do array = [time] array << array array end let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it 'formats the recursive element as [...] and other elements with custom formatting' do expect(output).to eq("[#{formatted_time}, [...]]") end end context 'with a recursive-key hash' do subject(:output) do ObjectFormatter.format(input) end let(:input) do hash = {} hash[hash] = time hash end let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it 'formats the recursive element as {...} and other elements with custom formatting' do expect(output).to eq("{{...}=>#{formatted_time}}") end end context 'with a recursive-value hash' do subject(:output) do ObjectFormatter.format(input) end let(:input) do hash = {} hash[time] = hash hash end let(:time) { Time.utc(1969, 12, 31, 19, 01, 40, 101) } let(:formatted_time) { ObjectFormatter.format(time) } it 'formats the recursive element as {...} and other elements with custom formatting' do expect(output).to eq("{#{formatted_time}=>{...}}") end end context 'with a non-immediate recursive array' do subject(:output) do ObjectFormatter.format(input) end let(:input) do array = [] array[0] = { :recursive_array => array } array end it 'formats the recursive element as [...]' do expect(output).to eq('[{:recursive_array=>[...]}]') end end context 'with a non-immediate recursive hash' do subject(:output) do ObjectFormatter.format(input) end let(:input) do hash = {} hash[:array] = [:next_is_recursive_hash, hash] hash end it 'formats the recursive element as {...}' do expect(output).to eq('{:array=>[:next_is_recursive_hash, {...}]}') end end context 'with an array including a same collection object multiple times' do subject(:output) do ObjectFormatter.format(input) end let(:input) do hash = { :key => 'value' } [hash, hash] end it 'does not omit them' do expect(output).to eq('[{:key=>"value"}, {:key=>"value"}]') end end context 'with truncation enabled' do it 'produces an output of limited length' do formatter = ObjectFormatter.new(10) expect(formatter.format('Test String Of A Longer Length')).to eq('"Test ...ngth"') end it 'does not truncate shorter strings' do formatter = ObjectFormatter.new(10) expect(formatter.format('Testing')).to eq('"Testing"') end context 'with ANSI escape codes that fall on the truncate split' do it 'removes that escape code so terminals do not get corrupted print a partial escape code' do formatter = ObjectFormatter.new(38) object = Class.new do def inspect "#<\e[33mClass\e[0m \e[36mname: \e[0m\"foobars\" \e[36mcount: \e[0m42>" end end.new expect(formatter.format(object)).to eq("#<\e[33mClass\e[0m ...\e[36mcount: \e[0m42>") end end end context 'with truncation disabled' do it 'does not limit the output length' do formatter = ObjectFormatter.new(nil) expect(formatter.format('Test String Of A Longer Length')).to eq('"Test String Of A Longer Length"') end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/recursive_const_methods_spec.rb0000664000000000000000000000312014566142077031502 0ustar rootrootrequire 'rspec/support/recursive_const_methods' module RSpec module Support RSpec.describe RecursiveConstMethods do include described_class module Foo class Parent UNDETECTED = 'Not seen when looking up constants in Bar' end class Bar < Parent VAL = 10 end end describe '#recursive_const_defined?' do it 'finds constants' do const, _ = recursive_const_defined?('::RSpec::Support::Foo::Bar::VAL') expect(const).to eq(10) end it 'returns the fully qualified name of the constant' do _, name = recursive_const_defined?('::RSpec::Support::Foo::Bar::VAL') expect(name).to eq('RSpec::Support::Foo::Bar::VAL') end it 'does not find constants in ancestors' do expect(recursive_const_defined?('::RSpec::Support::Foo::Bar::UNDETECTED')).to be_falsy end it 'does not blow up on buggy classes that raise weird errors on `to_str`' do allow(Foo::Bar).to receive(:to_str).and_raise("boom!") const, _ = recursive_const_defined?('::RSpec::Support::Foo::Bar::VAL') expect(const).to eq(10) end end describe '#recursive_const_get' do it 'gets constants' do expect(recursive_const_get('::RSpec::Support::Foo::Bar::VAL')).to eq(10) end it 'does not get constants in ancestors' do expect do recursive_const_get('::RSpec::Support::Foo::Bar::UNDETECTED') end.to raise_error(NameError) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/rspec/support/encoded_string_spec.rb0000664000000000000000000002734514566142077027550 0ustar rootroot# encoding: utf-8 require 'spec_helper' require 'rspec/support/encoded_string' require 'rspec/support/spec/string_matcher' module RSpec::Support RSpec.describe EncodedString do let(:utf8_encoding) { 'UTF-8' } delegated_methods = String.instance_methods.map(&:to_s) & %w[eql? lines == encoding empty?] delegated_methods.each do |delegated_method| it "responds to #{delegated_method}" do encoded_string = EncodedString.new("abc", utf8_encoding) expect(encoded_string).to respond_to(delegated_method) end end describe '::pick_encoding' do if String.method_defined?(:encoding) it "picks the default external encoding for incompatible encodings" do str1 = forced_encoding("\xa1", "iso-8859-1") str2 = forced_encoding("\xa1\xa1", "euc-jp") expect(Encoding.compatible?(str1, str2)).to be_nil expect(EncodedString.pick_encoding(str1, str2)).to eq(Encoding.default_external) end # https://github.com/ruby/spec/blob/91ce9f6549/core/encoding/compatible_spec.rb#L31 it "picks a compatible encoding" do str1 = forced_encoding "abc", Encoding::US_ASCII str2 = "\u3042".encode("utf-8") expect(EncodedString.pick_encoding(str1, str2)).to eq(Encoding::UTF_8) end else it "returns nil" do str1 = "\xa1" str2 = "\xa1\xa1" expect(EncodedString.pick_encoding(str1, str2)).to be_nil end end end if String.method_defined?(:encoding) describe '#source_encoding' do it 'knows the original encoding of the string' do str = EncodedString.new("abc".encode('ASCII-8BIT'), "UTF-8") expect(str.source_encoding.to_s).to eq('ASCII-8BIT') end end describe '#to_s' do context 'when encoding a string with invalid bytes in the target encoding' do # see https://github.com/jruby/jruby/blob/c1be61a501/test/mri/ruby/test_transcode.rb#L13 let(:source_encoding) { Encoding.find('US-ASCII') } let(:target_encoding) { Encoding.find('UTF-8') } let(:string) { forced_encoding("I have a bad byté\x80", source_encoding) } it 'normally raises an EncodedString::InvalidByteSequenceError' do expect { string.encode(target_encoding) }.to raise_error(Encoding::InvalidByteSequenceError) end # See JRuby issue https://github.com/jruby/jruby/issues/2580 it 'replaces invalid byte sequences with the REPLACE string', :pending => RSpec::Support::Ruby.jruby? && !RSpec::Support::Ruby.jruby_9000? do resulting_string = build_encoded_string(string, target_encoding).to_s replacement = EncodedString::REPLACE * 3 expected_string = forced_encoding("I have a bad byt#{replacement}", target_encoding) expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end end context 'when no converter is known for an encoding' do # see https://github.com/rubyspec/rubyspec/blob/91ce9f6549/core/string/shared/encode.rb#L12 let(:source_encoding) { Encoding.find('ASCII-8BIT') } let(:no_converter_encoding) { Encoding::Emacs_Mule } let(:string) { forced_encoding("\x80", source_encoding) } it 'normally raises an Encoding::ConverterNotFoundError' do expect { string.encode(no_converter_encoding) }.to raise_error(Encoding::ConverterNotFoundError) end # See comment above ENCODE_UNCONVERTABLE_BYTES in encoded_string.rb # for why the behavior differs by (MRI) Ruby version. if RUBY_VERSION < '2.1' it 'does nothing' do resulting_string = build_encoded_string(string, no_converter_encoding).to_s expected_string = forced_encoding("\x80", no_converter_encoding) expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end else it 'forces the encoding and replaces invalid characters with the REPLACE string' do resulting_string = build_encoded_string(string, no_converter_encoding).to_s expected_string = forced_encoding(EncodedString::REPLACE, no_converter_encoding) expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end it 'does not mutate the input string' do expect { build_encoded_string(string, no_converter_encoding) }.not_to change { [string, string.encoding] } end end end # see https://github.com/ruby/ruby/blob/34fbf57aaa/transcode.c#L4289 # ISO-8859-1 -> UTF-8 -> EUC-JP # "\xa0" NO-BREAK SPACE, which is available in UTF-8 but not in EUC-JP context 'when there is an undefined conversion to the target encoding' do let(:source_encoding) { Encoding.find('ISO-8859-1') } let(:incompatible_encoding) { Encoding.find('EUC-JP') } let(:string) { forced_encoding("\xa0 hi I am not going to work", source_encoding) } it 'normally raises an Encoding::UndefinedConversionError' do expect { string.encode(incompatible_encoding) }.to raise_error(Encoding::UndefinedConversionError) end it 'replaces all undefines conversions with the REPLACE string' do resulting_string = build_encoded_string(string, incompatible_encoding).to_s replacement = EncodedString::REPLACE expected_string = forced_encoding("#{replacement} hi I am not going to work", 'EUC-JP') expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end end end let(:ascii_arrow_symbol) { "\xAE" } let(:utf_8_euro_symbol) { "\xE2\x82\xAC" } describe '#<<' do context 'with strings that can be converted to the target encoding' do let(:valid_ascii_string) { forced_encoding("abcde", "ASCII-8BIT") } let(:valid_unicode_string) { forced_encoding(utf_8_euro_symbol, 'UTF-8') } it 'encodes and appends the string' do resulting_string = build_encoded_string(valid_unicode_string, utf8_encoding) << valid_ascii_string expected_string = forced_encoding("#{utf_8_euro_symbol}abcde", 'UTF-8') expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end end context 'with a string that cannot be converted to the target encoding' do context 'when appending a string with an incompatible character encoding' do let(:ascii_string) { forced_encoding(ascii_arrow_symbol, "ASCII-8BIT") } let(:valid_unicode_string) { forced_encoding(utf_8_euro_symbol, 'UTF-8') } it "normally raises an Encoding::CompatibilityError" do expect { valid_unicode_string.encode(utf8_encoding) << ascii_string }.to raise_error(Encoding::CompatibilityError) end it 'replaces unconvertable characters with the REPLACE string' do resulting_string = build_encoded_string(valid_unicode_string, utf8_encoding) << ascii_string expected_string = "#{utf_8_euro_symbol}#{EncodedString::REPLACE}" expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end end end context 'with two ascii strings with a target encoding of UTF-8 ' do it 'has an encoding of UTF-8' do ascii_string = forced_encoding('abc', "ASCII-8BIT") other_ascii_string = forced_encoding('123', "ASCII-8BIT") resulting_string = build_encoded_string(ascii_string, utf8_encoding) << other_ascii_string expected_string = forced_encoding('abc123', utf8_encoding) expect(resulting_string).to be_identical_string(expected_string).with_same_encoding end end end describe '#split' do context 'when there is an undefined conversion to the target encoding' do let(:wrapped_string_template) { "abaaaaaaaaaa%saaaaa" } let(:wrapped_string) { sprintf(wrapped_string_template, ascii_arrow_symbol).force_encoding("ASCII-8BIT") } it 'normally raises an Encoding::UndefinedConversionError' do expect { wrapped_string.encode(utf8_encoding) }.to raise_error(Encoding::UndefinedConversionError) end it 'splits the string based on the delimiter accounting for encoding' do delimiter = forced_encoding("b", utf8_encoding) resulting_string = build_encoded_string(wrapped_string, utf8_encoding).split(delimiter) exp1, exp2 = sprintf(wrapped_string_template, EncodedString::REPLACE).force_encoding(utf8_encoding).split(delimiter) expect(resulting_string).to match [ a_string_identical_to(exp1).with_same_encoding, a_string_identical_to(exp2).with_same_encoding ] end it 'handles invalidly encoded strings' do source_string = forced_encoding("an\xAE\nother", 'US-ASCII') expect( build_encoded_string(source_string, utf8_encoding).split("\n") ).to eq([ 'an?', 'other' ]) end end # see https://github.com/rspec/rspec-expectations/blob/f8a1232/spec/rspec/expectations/fail_with_spec.rb#L50 # https://github.com/rspec/rspec-expectations/issues/201 # https://github.com/rspec/rspec-expectations/pull/220 context 'with a string that cannot be converted to the target encoding' do let(:binary_poop) {'💩' } # [128169] "\u{1F4A9}" let(:non_ascii_compatible_string) { "This is a pile of poo: #{binary_poop}, yuck".encode("UTF-16LE") } it 'normally raises an Encoding::CompatibilityError' do expect { non_ascii_compatible_string.split("\n") }.to raise_error(Encoding::CompatibilityError) end it 'makes no changes to the resulting string' do resulting_array = build_encoded_string(non_ascii_compatible_string).split("\n") expect(resulting_array).to match [ a_string_identical_to(non_ascii_compatible_string).with_same_encoding ] end end context 'when the string has an invalid byte sequence' do let(:message_with_invalid_byte_sequence) { forced_encoding("\xEF \255 \xAD I have bad bytes", utf8_encoding) } it 'normally raises an ArgumentError' do expect(message_with_invalid_byte_sequence).not_to be_valid_encoding expect { message_with_invalid_byte_sequence.split("\n") }.to raise_error(ArgumentError) end it 'replaces invalid bytes with the REPLACE string' do resulting_array = build_encoded_string(message_with_invalid_byte_sequence, utf8_encoding).split("\n") expected_string = "? ? ? I have bad bytes" expect(resulting_array).to match [ a_string_identical_to(expected_string).with_same_encoding ] end end end def build_encoded_string(string, target_encoding = string.encoding) EncodedString.new(string, target_encoding) end def forced_encoding(string, encoding) string.dup.force_encoding(encoding) end else describe '#source_encoding' do it 'defaults to US-ASCII' do str = EncodedString.new("abc", "UTF-8") expect(str.source_encoding).to eq('US-ASCII') end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/spec/spec_helper.rb0000664000000000000000000000031614566142077023175 0ustar rootrootrequire 'rspec/support/spec' RSpec::Support::Spec.setup_simplecov RSpec::Matchers.define_negated_matcher :avoid_raising_errors, :raise_error RSpec::Matchers.define_negated_matcher :avoid_changing, :change ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/rspec-support.gemspec0000664000000000000000000000323414566142077023622 0ustar rootroot# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'rspec/support/version' Gem::Specification.new do |spec| spec.name = "rspec-support" spec.version = RSpec::Support::Version::STRING spec.authors = ["David Chelimsky","Myron Marson","Jon Rowe","Sam Phippen","Xaviery Shay","Bradley Schaefer"] spec.email = "rspec-users@rubyforge.org" spec.homepage = "https://github.com/rspec/rspec-support" spec.summary = "rspec-support-#{RSpec::Support::Version::STRING}" spec.description = "Support utilities for RSpec gems" spec.license = "MIT" spec.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-support/issues', 'changelog_uri' => "https://github.com/rspec/rspec-support/blob/v#{spec.version}/Changelog.md", 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-support', } spec.files = `git ls-files -- lib/*`.split("\n") spec.files += %w[README.md LICENSE.md Changelog.md] spec.test_files = [] spec.rdoc_options = ["--charset=UTF-8"] spec.require_paths = ["lib"] private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) spec.signing_key = private_key spec.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')] end spec.required_ruby_version = '>= 1.8.7' spec.add_development_dependency "rake", "> 10.0.0" spec.add_development_dependency "thread_order", "~> 1.1.0" end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.github/0000775000000000000000000000000014566142077020765 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.github/workflows/0000775000000000000000000000000014566142077023022 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.github/workflows/ci.yml0000664000000000000000000001143014566142077024137 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. name: RSpec CI on: push: branches: - 'main' - '*-maintenance' - '*-dev' pull_request: branches: - '*' permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: RSPEC_CI: true # This tells rspec-rails what branch to run in ci RSPEC_VERSION: '~> 3.13.0' jobs: rubocop: name: Rubocop runs-on: 'ubuntu-20.04' steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.0' - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_rubocop test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} runs-on: ${{ matrix.os || 'ubuntu-20.04' }} strategy: matrix: ruby: - '3.3' - '3.2' - '3.1' - '3.0' - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 env: - DIFF_LCS_VERSION: "> 1.4.3" include: - ruby: ruby-head env: RUBY_HEAD: true - ruby: jruby-9.2.13.0 env: JRUBY_OPTS: "--dev" - ruby: 2.7 name_extra: "with diff-lcs 1.3" env: DIFF_LCS_VERSION: "~> 1.3.0" - ruby: 2.7 name_extra: "with diff-lcs 1.4.3" env: DIFF_LCS_VERSION: "1.4.3" fail-fast: false continue-on-error: ${{ matrix.allow_failure || endsWith(matrix.ruby, 'head') }} env: ${{ matrix.env }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: ${{ matrix.bundler || '2.2.22' }} ruby-version: ${{ matrix.ruby }} - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_build legacy: name: Legacy Ruby Builds (${{ matrix.container.version }}) runs-on: ubuntu-20.04 container: image: ${{ matrix.container.tag }} options: ${{ matrix.container.options || '--add-host github-complains-if-this-is-empty.com:127.0.0.1' }} strategy: fail-fast: false matrix: container: - version: "2.1.9" tag: ghcr.io/rspec/docker-ci:2.1.9 post: git config --global --add safe.directory `pwd` - version: "2.0" tag: ghcr.io/rspec/docker-ci:2.0.0 - version: "1.9.3" tag: ghcr.io/rspec/docker-ci:1.9.3 - version: "1.9.2" tag: ghcr.io/rspec/docker-ci:1.9.2 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "1.8.7" tag: ghcr.io/rspec/docker-ci:1.8.7 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "REE" tag: ghcr.io/rspec/docker-ci:ree options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 1.7" tag: ghcr.io/rspec/docker-ci:jruby-1.7 - version: "JRuby 1.7 1.8 mode" tag: ghcr.io/rspec/docker-ci:jruby-1.7 jruby_opts: '--dev --1.8' pre: gem uninstall jruby-openssl options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 9.1.17.0" tag: ghcr.io/rspec/docker-ci:jruby-9.1.17.0 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" env: LEGACY_CI: true JRUBY_OPTS: ${{ matrix.container.jruby_opts || '--dev' }} steps: - uses: actions/checkout@v3 - run: ${{ matrix.container.pre }} - run: script/legacy_setup.sh - run: ${{ matrix.container.post }} - run: bundle exec bin/rspec - run: bundle exec script/cucumber.sh windows: name: Ruby ${{ matrix.ruby }} (Windows) runs-on: windows-latest strategy: matrix: ruby: - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 fail-fast: false steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: '2.2.22' ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: choco install ansicon - run: bundle exec rspec --backtrace ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.github/dependabot.yml0000664000000000000000000000043714566142077023621 0ustar rootroot# This file was generated on 2024-02-23T14:21:37+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. version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.github/FUNDING.yml0000664000000000000000000000033514566142077022603 0ustar rootroot# This file was generated on 2023-04-16T20:53:24+01: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, benoittgt] open_collective: rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/CONTRIBUTING.md0000664000000000000000000001033614566142077021661 0ustar rootroot # Contributing RSpec is a community-driven project that has benefited from improvements from over *500* contributors. We welcome contributions from *everyone*. While contributing, please follow the project [code of conduct](CODE_OF_CONDUCT.md), so that everyone can be included. If you'd like to help make RSpec better, here are some ways you can contribute: - by running RSpec HEAD to help us catch bugs before new releases - by [reporting bugs you encounter](https://github.com/rspec/rspec-support/issues/new) with [report template](#report-template) - by [suggesting new features](https://github.com/rspec/rspec-support/issues/new) - by improving RSpec's Feature or API [documentation](https://rspec.info/documentation/) - by improving [RSpec's website](https://rspec.info/) ([source](https://github.com/rspec/rspec.github.io)) - by taking part in [feature and issue discussions](https://github.com/rspec/rspec-support/issues) - by adding a failing test for reproducible [reported bugs](https://github.com/rspec/rspec-support/issues) - by reviewing [pull requests](https://github.com/rspec/rspec-support/pulls) and suggesting improvements - by [writing code](DEVELOPMENT.md) (no patch is too small! fix typos or bad whitespace) If you need help getting started, check out the [DEVELOPMENT](DEVELOPMENT.md) file for steps that will get you up and running. Thanks for helping us make RSpec better! ## `Small` issues These issue are ones that we be believe are best suited for new contributors to get started with. They represent a meaningful contribution to the project that should not be too hard to pull off. ## Report template Having a way to reproduce your issue will be very helpful for others to help confirm, investigate and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared one basic [bug report templates](REPORT_TEMPLATE.md) for you to use as a starting point. ## Maintenance branches Maintenance branches are how we manage the different supported point releases of RSpec. As such, while they might look like good candidates to merge into main, please do not open pull requests to merge them. ## Working on multiple RSpec gems at the same time RSpec is composed of multiple gems (`rspec-core`, `rspec-mocks`, etc). Sometimes you have to work on a combination of them at the same time. When submitting your code for review, we ask that you get a passing build (green CI). If you are working across the repositories, please add a commit that temporarily pins your PR to the right branch of the other repository you depend on. For example, if we wanted a change in `rspec-expectations` that relied on a change for on `rspec-mocks`. We add a commit with the title: >[WIP] Use rspec-mocks with "custom-failure-message" branch And content: ```diff diff --git a/Gemfile b/Gemfile -%w[rspec rspec-core rspec-mocks rspec-support].each do |lib| +%w[rspec rspec-core rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path @@ -11,6 +11,7 @@ branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end +gem 'rspec-mocks', :git => "https://github.com/rspec/rspec-mocks.git", :branch => "custom-failure-message" ``` In general the process is: 1. Create PRs explaining what you are trying to achieve. 2. Pin the repositories to each other. 3. Check they pass (go green). 4. Await review if appropriate. 5. Remove the commit from step 2. We will merge ignoring the failure. 6. Remove the commit from the other, check it passes with the other commit now on `main`. 7. Merge the other. 8. We will trigger builds for the `main` branch of affected repositories to check if everything is in order. Steps 5-8 should happen continuously (e.g. one after another but within a short timespan) so that we don't leave a broken main around. It is important to triage that build process and revert if necessary. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/BUILD_DETAIL.md0000664000000000000000000001244314566142077021634 0ustar rootroot # The CI build, in detail The [Travis CI build](https://travis-ci.org/rspec/rspec-support) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` It can be useful to run the build steps individually to repro a failing part of a Travis build. Let's break the build down into the individual steps. ## Specs RSpec dogfoods itself. Its primary defense against regressions is its spec suite. Run with: ``` $ bundle exec rspec # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rspec ``` The spec suite performs a couple extra checks that are worth noting: * *That all the code is warning-free.* Any individual example that produces output to `stderr` will fail. We also have a spec that loads all the `lib` and `spec` files in a newly spawned process to detect load-time warnings and fail if there are any. RSpec must be warning-free so that users who enable Ruby warnings will not get warnings from our code. * *That only a minimal set of stdlibs are loaded.* Since Ruby makes loaded libraries available for use in any context, we want to minimize how many bits of the standard library we load and use. Otherwise, RSpec's use of part of the standard library could mask a problem where a gem author forgets to load a part of the standard library they rely on. The spec suite contains a spec that defines a list of allowed loaded stdlibs. In addition, we use [SimpleCov](https://github.com/colszowka/simplecov) to measure and enforce test coverage. If the coverage falls below a project-specific threshold, the build will fail. ## Cukes RSpec uses [cucumber](https://cucumber.io/) for both acceptance testing and [documentation](https://rspec.info/documentation). Since we publish our cukes as documentation, please limit new cucumber scenarios to user-facing examples that help demonstrate usage. Any tests that exist purely to prevent regressions should be written as specs, even if they are written in an acceptance style. Duplication between our YARD API docs and the cucumber documentation is fine. Run with: ``` $ bundle exec cucumber # or, if you installed your bundle with `--standalone --binstubs`: $ bin/cucumber ``` ## YARD documentation RSpec uses [YARD](https://yardoc.org/) for API documentation on the [rspec.info site](https://rspec.info/). Our commitment to [SemVer](https://semver.org) requires that we explicitly declare our public API, and our build uses YARD to ensure that every class, module and method has either been labeled `@private` or has at least some level of documentation. For new APIs, this forces us to make an intentional decision about whether or not it should be part of RSpec's public API or not. To run the YARD documentation coverage check, run: ``` $ bundle exec yard stats --list-undoc # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard stats --list-undoc ``` We also want to prevent YARD errors or warnings when actually generating the docs. To check for those, run: ``` $ bundle exec yard doc --no-cache # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard doc --no-cache ``` ## RuboCop We use [RuboCop](https://github.com/rubocop-hq/rubocop) to enforce style conventions on the project so that the code has stylistic consistency throughout. Run with: ``` $ bundle exec rubocop lib # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rubocop lib ``` Our RuboCop configuration is a work-in-progress, so if you get a failure due to a RuboCop default, feel free to ask about changing the configuration. Otherwise, you'll need to address the RuboCop failure, or, as a measure of last resort, by wrapping the offending code in comments like `# rubocop:disable SomeCheck` and `# rubocop:enable SomeCheck`. ## Run spec files one-by-one A fast TDD cycle depends upon being able to run a single spec file, without the rest of the test suite. While rare, it's fairly easy to create a situation where a spec passes when the entire suite runs but fails when its individual file is run. To guard against this, our CI build runs each spec file individually, using a bit of bash like: ``` for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done ``` Since this step boots RSpec so many times, it runs much, much faster when we can avoid the overhead of bundler. This is a main reason our CI build installs the bundle with `--standalone --binstubs` and runs RSpec via `bin/rspec` rather than `bundle exec rspec`. ## Running the spec suite for each of the other repos While each of the RSpec repos is an independent gem (generally designed to be usable on its own), there are interdependencies between the gems, and the specs for each tend to use features from the other gems. We don't want to merge a pull request for one repo that might break the build for another repo, so our CI build includes a spec that runs the spec suite of each of the _other_ project repos. Note that we only run the spec suite, not the full build, of the other projects, as the spec suite runs very quickly compared to the full build. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/.gitignore0000664000000000000000000000032114566142077021411 0ustar rootroot*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp bin bundle Gemfile-custom spec/examples.txt specs.out ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/0000775000000000000000000000000014566142077020173 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/0000775000000000000000000000000014566142077021307 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support.rb0000664000000000000000000001253214566142077023353 0ustar rootroot# frozen_string_literal: true module RSpec module Support # @api private # # Defines a helper method that is optimized to require files from the # named lib. The passed block MUST be `{ |f| require_relative f }` # because for `require_relative` to work properly from within the named # lib the line of code must be IN that lib. # # `require_relative` is preferred when available because it is always O(1), # regardless of the number of dirs in $LOAD_PATH. `require`, on the other # hand, does a linear O(N) search over the dirs in the $LOAD_PATH until # it can resolve the file relative to one of the dirs. def self.define_optimized_require_for_rspec(lib, &require_relative) name = "require_rspec_#{lib}" if RUBY_PLATFORM == 'java' && !Kernel.respond_to?(:require) # JRuby 9.1.17.0 has developed a regression for require (class << self; self; end).__send__(:define_method, name) do |f| Kernel.send(:require, "rspec/#{lib}/#{f}") end elsif Kernel.respond_to?(:require_relative) (class << self; self; end).__send__(:define_method, name) do |f| require_relative.call("#{lib}/#{f}") end else (class << self; self; end).__send__(:define_method, name) do |f| require "rspec/#{lib}/#{f}" end end end define_optimized_require_for_rspec(:support) { |f| require_relative(f) } require_rspec_support "version" require_rspec_support "ruby_features" # @api private KERNEL_METHOD_METHOD = ::Kernel.instance_method(:method) # @api private # # Used internally to get a method handle for a particular object # and method name. # # Includes handling for a few special cases: # # - Objects that redefine #method (e.g. an HTTPRequest struct) # - BasicObject subclasses that mixin a Kernel dup (e.g. SimpleDelegator) # - Objects that undefine method and delegate everything to another # object (e.g. Mongoid association objects) if RubyFeatures.supports_rebinding_module_methods? def self.method_handle_for(object, method_name) KERNEL_METHOD_METHOD.bind(object).call(method_name) rescue NameError => original begin handle = object.method(method_name) raise original unless handle.is_a? Method handle rescue Support::AllExceptionsExceptOnesWeMustNotRescue raise original end end else def self.method_handle_for(object, method_name) if ::Kernel === object KERNEL_METHOD_METHOD.bind(object).call(method_name) else object.method(method_name) end rescue NameError => original begin handle = object.method(method_name) raise original unless handle.is_a? Method handle rescue Support::AllExceptionsExceptOnesWeMustNotRescue raise original end end end # @api private # # Used internally to get a class of a given object, even if it does not respond to #class. def self.class_of(object) object.class rescue NoMethodError singleton_class = class << object; self; end singleton_class.ancestors.find { |ancestor| !ancestor.equal?(singleton_class) } end # A single thread local variable so we don't excessively pollute that namespace. if RUBY_VERSION.to_f >= 2 def self.thread_local_data Thread.current.thread_variable_get(:__rspec) || Thread.current.thread_variable_set(:__rspec, {}) end else def self.thread_local_data Thread.current[:__rspec] ||= {} end end # @api private def self.failure_notifier=(callable) thread_local_data[:failure_notifier] = callable end # @private DEFAULT_FAILURE_NOTIFIER = lambda { |failure, _opts| raise failure } # @api private def self.failure_notifier thread_local_data[:failure_notifier] || DEFAULT_FAILURE_NOTIFIER end # @api private def self.notify_failure(failure, options={}) failure_notifier.call(failure, options) end # @api private def self.with_failure_notifier(callable) orig_notifier = failure_notifier self.failure_notifier = callable yield ensure self.failure_notifier = orig_notifier end class << self # @api private attr_writer :warning_notifier end # @private DEFAULT_WARNING_NOTIFIER = lambda { |warning| ::Kernel.warn warning } # @api private def self.warning_notifier @warning_notifier ||= DEFAULT_WARNING_NOTIFIER end # @private module AllExceptionsExceptOnesWeMustNotRescue # These exceptions are dangerous to rescue as rescuing them # would interfere with things we should not interfere with. AVOID_RESCUING = [NoMemoryError, SignalException, Interrupt, SystemExit] def self.===(exception) AVOID_RESCUING.none? { |ar| ar === exception } end end # The Differ is only needed when a spec fails with a diffable failure. # In the more common case of all specs passing or the only failures being # non-diffable, we can avoid the extra cost of loading the differ, diff-lcs, # pp, etc by avoiding an unnecessary require. Instead, autoload will take # care of loading the differ on first use. autoload :Differ, "rspec/support/differ" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/0000775000000000000000000000000014566142077023023 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/differ.rb0000664000000000000000000001325614566142077024616 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support 'encoded_string' RSpec::Support.require_rspec_support 'hunk_generator' RSpec::Support.require_rspec_support "object_formatter" require 'pp' module RSpec module Support # rubocop:disable Metrics/ClassLength class Differ def diff(actual, expected) diff = "" unless actual.nil? || expected.nil? if all_strings?(actual, expected) if any_multiline_strings?(actual, expected) diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected)) end elsif no_procs?(actual, expected) && no_numbers?(actual, expected) diff = diff_as_object(actual, expected) end end diff.to_s end # rubocop:disable Metrics/MethodLength def diff_as_string(actual, expected) encoding = EncodedString.pick_encoding(actual, expected) actual = EncodedString.new(actual, encoding) expected = EncodedString.new(expected, encoding) output = EncodedString.new("\n", encoding) hunks = build_hunks(actual, expected) hunks.each_cons(2) do |prev_hunk, current_hunk| begin if current_hunk.overlaps?(prev_hunk) add_old_hunk_to_hunk(current_hunk, prev_hunk) else add_to_output(output, prev_hunk.diff(format_type).to_s) end ensure add_to_output(output, "\n") end end finalize_output(output, hunks.last.diff(format_type).to_s) if hunks.last color_diff output rescue Encoding::CompatibilityError handle_encoding_errors(actual, expected) end # rubocop:enable Metrics/MethodLength def diff_as_object(actual, expected) actual_as_string = object_to_string(actual) expected_as_string = object_to_string(expected) diff_as_string(actual_as_string, expected_as_string) end def color? @color end def initialize(opts={}) @color = opts.fetch(:color, false) @object_preparer = opts.fetch(:object_preparer, lambda { |string| string }) end private def no_procs?(*args) safely_flatten(args).none? { |a| Proc === a } end def all_strings?(*args) safely_flatten(args).all? { |a| String === a } end def any_multiline_strings?(*args) all_strings?(*args) && safely_flatten(args).any? { |a| multiline?(a) } end def no_numbers?(*args) safely_flatten(args).none? { |a| Numeric === a } end def coerce_to_string(string_or_array) return string_or_array unless Array === string_or_array diffably_stringify(string_or_array).join("\n") end def diffably_stringify(array) array.map do |entry| if Array === entry entry.inspect else entry.to_s.gsub("\n", "\\n").gsub("\r", "\\r") end end end if String.method_defined?(:encoding) def multiline?(string) string.include?("\n".encode(string.encoding)) end else def multiline?(string) string.include?("\n") end end def build_hunks(actual, expected) HunkGenerator.new(actual, expected).hunks end def finalize_output(output, final_line) add_to_output(output, final_line) add_to_output(output, "\n") end def add_to_output(output, string) output << string end def add_old_hunk_to_hunk(hunk, oldhunk) hunk.merge(oldhunk) end def safely_flatten(array) array = array.flatten(1) until (array == array.flatten(1)) array end def format_type :unified end def color(text, color_code) "\e[#{color_code}m#{text}\e[0m" end def red(text) color(text, 31) end def green(text) color(text, 32) end def blue(text) color(text, 34) end def normal(text) color(text, 0) end def color_diff(diff) return diff unless color? diff.lines.map do |line| case line[0].chr when "+" green line when "-" red line when "@" line[1].chr == "@" ? blue(line) : normal(line) else normal(line) end end.join end def object_to_string(object) object = @object_preparer.call(object) case object when Hash hash_to_string(object) when Array PP.pp(ObjectFormatter.prepare_for_inspection(object), "".dup) when String object =~ /\n/ ? object : object.inspect else PP.pp(object, "".dup) end end def hash_to_string(hash) formatted_hash = ObjectFormatter.prepare_for_inspection(hash) formatted_hash.keys.sort_by { |k| k.to_s }.map do |key| pp_key = PP.singleline_pp(key, "".dup) pp_value = PP.singleline_pp(formatted_hash[key], "".dup) "#{pp_key} => #{pp_value}," end.join("\n") end def handle_encoding_errors(actual, expected) if actual.source_encoding != expected.source_encoding "Could not produce a diff because the encoding of the actual string " \ "(#{actual.source_encoding}) differs from the encoding of the expected " \ "string (#{expected.source_encoding})" else "Could not produce a diff because of the encoding of the string " \ "(#{expected.source_encoding})" end end end # rubocop:enable Metrics/ClassLength end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/object_formatter.rb0000664000000000000000000001754014566142077026710 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support 'matcher_definition' module RSpec module Support # Provide additional output details beyond what `inspect` provides when # printing Time, DateTime, or BigDecimal # @api private class ObjectFormatter # rubocop:disable Metrics/ClassLength ELLIPSIS = "..." attr_accessor :max_formatted_output_length # Methods are deferred to a default instance of the class to maintain the interface # For example, calling ObjectFormatter.format is still possible def self.default_instance @default_instance ||= new end def self.format(object) default_instance.format(object) end def self.prepare_for_inspection(object) default_instance.prepare_for_inspection(object) end def initialize(max_formatted_output_length=200) @max_formatted_output_length = max_formatted_output_length @current_structure_stack = [] end def format(object) if max_formatted_output_length.nil? prepare_for_inspection(object).inspect else formatted_object = prepare_for_inspection(object).inspect if formatted_object.length < max_formatted_output_length formatted_object else beginning = truncate_string formatted_object, 0, max_formatted_output_length / 2 ending = truncate_string formatted_object, -max_formatted_output_length / 2, -1 beginning + ELLIPSIS + ending end end end # Prepares the provided object to be formatted by wrapping it as needed # in something that, when `inspect` is called on it, will produce the # desired output. # # This allows us to apply the desired formatting to hash/array data structures # at any level of nesting, simply by walking that structure and replacing items # with custom items that have `inspect` defined to return the desired output # for that item. Then we can just use `Array#inspect` or `Hash#inspect` to # format the entire thing. def prepare_for_inspection(object) case object when Array prepare_array(object) when Hash prepare_hash(object) else inspector_class = INSPECTOR_CLASSES.find { |inspector| inspector.can_inspect?(object) } inspector_class.new(object, self) end end def prepare_array(array) with_entering_structure(array) do array.map { |element| prepare_element(element) } end end def prepare_hash(input_hash) with_entering_structure(input_hash) do sort_hash_keys(input_hash).inject({}) do |output_hash, key_and_value| key, value = key_and_value.map { |element| prepare_element(element) } output_hash[key] = value output_hash end end end def sort_hash_keys(input_hash) if input_hash.keys.all? { |k| k.is_a?(String) || k.is_a?(Symbol) } Hash[input_hash.sort_by { |k, _v| k.to_s }] else input_hash end end def prepare_element(element) if recursive_structure?(element) case element when Array then InspectableItem.new('[...]') when Hash then InspectableItem.new('{...}') else raise # This won't happen end else prepare_for_inspection(element) end end def with_entering_structure(structure) @current_structure_stack.push(structure) return_value = yield @current_structure_stack.pop return_value end def recursive_structure?(object) @current_structure_stack.any? { |seen_structure| seen_structure.equal?(object) } end InspectableItem = Struct.new(:text) do def inspect text end def pretty_print(pp) pp.text(text) end end BaseInspector = Struct.new(:object, :formatter) do def self.can_inspect?(_object) raise NotImplementedError end def inspect raise NotImplementedError end def pretty_print(pp) pp.text(inspect) end end class TimeInspector < BaseInspector FORMAT = "%Y-%m-%d %H:%M:%S" def self.can_inspect?(object) Time === object end if Time.method_defined?(:nsec) def inspect object.strftime("#{FORMAT}.#{"%09d" % object.nsec} %z") end else # for 1.8.7 def inspect object.strftime("#{FORMAT}.#{"%06d" % object.usec} %z") end end end class DateTimeInspector < BaseInspector FORMAT = "%a, %d %b %Y %H:%M:%S.%N %z" def self.can_inspect?(object) defined?(DateTime) && DateTime === object end # ActiveSupport sometimes overrides inspect. If `ActiveSupport` is # defined use a custom format string that includes more time precision. def inspect if defined?(ActiveSupport) object.strftime(FORMAT) else object.inspect end end end class BigDecimalInspector < BaseInspector def self.can_inspect?(object) defined?(BigDecimal) && BigDecimal === object end def inspect "#{object.to_s('F')} (#{object.inspect})" end end class DescribableMatcherInspector < BaseInspector def self.can_inspect?(object) Support.is_a_matcher?(object) && object.respond_to?(:description) end def inspect object.description end end class UninspectableObjectInspector < BaseInspector OBJECT_ID_FORMAT = '%#016x' def self.can_inspect?(object) object.inspect false rescue NoMethodError true end def inspect "#<#{klass}:#{native_object_id}>" end def klass Support.class_of(object) end # http://stackoverflow.com/a/2818916 def native_object_id OBJECT_ID_FORMAT % (object.__id__ << 1) rescue NoMethodError # In Ruby 1.9.2, BasicObject responds to none of #__id__, #object_id, #id... '-' end end class DelegatorInspector < BaseInspector def self.can_inspect?(object) defined?(Delegator) && Delegator === object end def inspect "#<#{object.class}(#{formatter.format(object.send(:__getobj__))})>" end end class InspectableObjectInspector < BaseInspector def self.can_inspect?(object) object.inspect true rescue NoMethodError false end def inspect object.inspect end end INSPECTOR_CLASSES = [ TimeInspector, DateTimeInspector, BigDecimalInspector, UninspectableObjectInspector, DescribableMatcherInspector, DelegatorInspector, InspectableObjectInspector ].tap do |classes| # 2.4 has improved BigDecimal formatting so we do not need # to provide our own. # https://github.com/ruby/bigdecimal/pull/42 classes.delete(BigDecimalInspector) if RUBY_VERSION >= '2.4' end private # Returns the substring defined by the start_index and end_index # If the string ends with a partial ANSI code code then that # will be removed as printing partial ANSI # codes to the terminal can lead to corruption def truncate_string(str, start_index, end_index) cut_str = str[start_index..end_index] # ANSI color codes are like: \e[33m so anything with \e[ and a # number without a 'm' is an incomplete color code cut_str.sub(/\e\[\d+$/, '') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/source/0000775000000000000000000000000014566142077024323 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/source/location.rb0000664000000000000000000000106714566142077026464 0ustar rootroot# frozen_string_literal: true module RSpec module Support class Source # @private # Represents a source location of node or token. Location = Struct.new(:line, :column) do include Comparable def self.location?(array) array.is_a?(Array) && array.size == 2 && array.all? { |e| e.is_a?(Integer) } end def <=>(other) line_comparison = (line <=> other.line) return line_comparison unless line_comparison == 0 column <=> other.column end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/source/node.rb0000664000000000000000000000521714566142077025602 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support 'source/location' module RSpec module Support class Source # @private # A wrapper for Ripper AST node which is generated with `Ripper.sexp`. class Node include Enumerable attr_reader :sexp, :parent def self.sexp?(array) array.is_a?(Array) && array.first.is_a?(Symbol) end def initialize(ripper_sexp, parent=nil) @sexp = ripper_sexp.freeze @parent = parent end def type sexp[0] end def args @args ||= raw_args.map do |raw_arg| if Node.sexp?(raw_arg) Node.new(raw_arg, self) elsif Location.location?(raw_arg) Location.new(*raw_arg) elsif raw_arg.is_a?(Array) ExpressionSequenceNode.new(raw_arg, self) else raw_arg end end.freeze end def children @children ||= args.select { |arg| arg.is_a?(Node) }.freeze end def location @location ||= args.find { |arg| arg.is_a?(Location) } end # We use a loop here (instead of recursion) to prevent SystemStackError def each return to_enum(__method__) unless block_given? node_queue = [] node_queue << self while (current_node = node_queue.shift) yield current_node node_queue.concat(current_node.children) end end def each_ancestor return to_enum(__method__) unless block_given? current_node = self while (current_node = current_node.parent) yield current_node end end def inspect "#<#{self.class} #{type}>" end private def raw_args sexp[1..-1] || [] end end # @private # Basically `Ripper.sexp` generates arrays whose first element is a symbol (type of sexp), # but it exceptionally generates typeless arrays for expression sequence: # # Ripper.sexp('foo; bar') # => [ # :program, # [ # Typeless array # [:vcall, [:@ident, "foo", [1, 0]]], # [:vcall, [:@ident, "bar", [1, 5]]] # ] # ] # # We wrap typeless arrays in this pseudo type node # so that it can be handled in the same way as other type node. class ExpressionSequenceNode < Node def type :_expression_sequence end private def raw_args sexp end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/source/token.rb0000664000000000000000000000436114566142077025774 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support 'source/location' module RSpec module Support class Source # @private # A wrapper for Ripper token which is generated with `Ripper.lex`. class Token CLOSING_TYPES_BY_OPENING_TYPE = { :on_lbracket => :on_rbracket, :on_lparen => :on_rparen, :on_lbrace => :on_rbrace, :on_heredoc_beg => :on_heredoc_end }.freeze CLOSING_KEYWORDS_BY_OPENING_KEYWORD = { 'def' => 'end', 'do' => 'end', }.freeze attr_reader :token def self.tokens_from_ripper_tokens(ripper_tokens) ripper_tokens.map { |ripper_token| new(ripper_token) }.freeze end def initialize(ripper_token) @token = ripper_token.freeze end def location @location ||= Location.new(*token[0]) end def type token[1] end def string token[2] end def ==(other) token == other.token end alias_method :eql?, :== def inspect "#<#{self.class} #{type} #{string.inspect}>" end def keyword? type == :on_kw end def equals_operator? type == :on_op && string == '=' end def opening? opening_delimiter? || opening_keyword? end def closed_by?(other) delimiter_closed_by?(other) || keyword_closed_by?(other) end private def opening_delimiter? CLOSING_TYPES_BY_OPENING_TYPE.key?(type) end def opening_keyword? return false unless keyword? CLOSING_KEYWORDS_BY_OPENING_KEYWORD.key?(string) end def delimiter_closed_by?(other) other.type == CLOSING_TYPES_BY_OPENING_TYPE[type] end def keyword_closed_by?(other) return false unless keyword? return true if other.string == CLOSING_KEYWORDS_BY_OPENING_KEYWORD[string] # Ruby 3's `end`-less method definition: `def method_name = body` string == 'def' && other.equals_operator? && location.line == other.location.line end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/version.rb0000664000000000000000000000017214566142077025035 0ustar rootroot# frozen_string_literal: true module RSpec module Support module Version STRING = '3.13.1' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/matcher_definition.rb0000664000000000000000000000224214566142077027203 0ustar rootroot# frozen_string_literal: true module RSpec module Support # @private def self.matcher_definitions @matcher_definitions ||= [] end # Used internally to break cyclic dependency between mocks, expectations, # and support. We don't currently have a consistent implementation of our # matchers, though we are considering changing that: # https://github.com/rspec/rspec-mocks/issues/513 # # @private def self.register_matcher_definition(&block) matcher_definitions << block end # Remove a previously registered matcher. Useful for cleaning up after # yourself in specs. # # @private def self.deregister_matcher_definition(&block) matcher_definitions.delete(block) end # @private def self.is_a_matcher?(object) matcher_definitions.any? { |md| md.call(object) } end # @api private # # gives a string representation of an object for use in RSpec descriptions def self.rspec_description_for_object(object) if RSpec::Support.is_a_matcher?(object) && object.respond_to?(:description) object.description else object end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/fuzzy_matcher.rb0000664000000000000000000000275714566142077026255 0ustar rootroot# frozen_string_literal: true module RSpec module Support # Provides a means to fuzzy-match between two arbitrary objects. # Understands array/hash nesting. Uses `===` or `==` to # perform the matching. module FuzzyMatcher # @api private def self.values_match?(expected, actual) if Hash === actual return hashes_match?(expected, actual) if Hash === expected elsif Array === expected && Enumerable === actual && !(Struct === actual) return arrays_match?(expected, actual.to_a) end return true if expected == actual begin expected === actual rescue ArgumentError # Some objects, like 0-arg lambdas on 1.9+, raise # ArgumentError for `expected === actual`. false end end # @private def self.arrays_match?(expected_list, actual_list) return false if expected_list.size != actual_list.size expected_list.zip(actual_list).all? do |expected, actual| values_match?(expected, actual) end end # @private def self.hashes_match?(expected_hash, actual_hash) return false if expected_hash.size != actual_hash.size expected_hash.all? do |expected_key, expected_value| actual_value = actual_hash.fetch(expected_key) { return false } values_match?(expected_value, actual_value) end end private_class_method :arrays_match?, :hashes_match? end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/ruby_features.rb0000664000000000000000000001243414566142077026233 0ustar rootroot# frozen_string_literal: true require 'rbconfig' RSpec::Support.require_rspec_support "comparable_version" module RSpec module Support # @api private # # Provides query methods for different OS or OS features. module OS module_function def windows? !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) end def windows_file_path? ::File::ALT_SEPARATOR == '\\' end end # @api private # # Provides query methods for different rubies module Ruby module_function def jruby? RUBY_PLATFORM == 'java' end def jruby_version @jruby_version ||= ComparableVersion.new(JRUBY_VERSION) end def jruby_9000? jruby? && JRUBY_VERSION >= '9.0.0.0' end def rbx? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' end def non_mri? !mri? end def mri? !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' end def truffleruby? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'truffleruby' end end # @api private # # Provides query methods for ruby features that differ among # implementations. module RubyFeatures module_function if Ruby.jruby? && RUBY_VERSION.to_f < 1.9 # On JRuby 1.7 `--1.8` mode, `Process.respond_to?(:fork)` returns true, # but when you try to fork, it raises an error: # NotImplementedError: fork is not available on this platform # # When we drop support for JRuby 1.7 and/or Ruby 1.8, we can drop # this special case. def fork_supported? false end else def fork_supported? Process.respond_to?(:fork) end end def optional_and_splat_args_supported? Method.method_defined?(:parameters) end def caller_locations_supported? respond_to?(:caller_locations, true) end if Exception.method_defined?(:cause) def supports_exception_cause? true end else def supports_exception_cause? false end end if RUBY_VERSION.to_f >= 3.2 def supports_syntax_suggest? true end else def supports_syntax_suggest? false end end if RUBY_VERSION.to_f >= 3.0 # https://rubyreferences.github.io/rubychanges/3.0.html#keyword-arguments-are-now-fully-separated-from-positional-arguments def kw_arg_separation? true end else def kw_arg_separation? false end end if RUBY_VERSION.to_f >= 2.7 def supports_taint? false end else def supports_taint? true end end ripper_requirements = [ComparableVersion.new(RUBY_VERSION) >= '1.9.2'] ripper_requirements.push(false) if Ruby.rbx? if Ruby.jruby? ripper_requirements.push(Ruby.jruby_version >= '1.7.5') # Ripper on JRuby 9.0.0.0.rc1 - 9.1.8.0 reports wrong line number # or cannot parse source including `:if`. # Ripper on JRuby 9.x.x.x < 9.1.17.0 can't handle keyword arguments # Neither can JRuby 9.2, e.g. < 9.2.1.0 ripper_requirements.push(!Ruby.jruby_version.between?('9.0.0.0.rc1', '9.2.0.0')) end # TruffleRuby disables ripper due to low performance ripper_requirements.push(false) if Ruby.truffleruby? if ripper_requirements.all? def ripper_supported? true end else def ripper_supported? false end end def distincts_kw_args_from_positional_hash? RUBY_VERSION >= '3.0.0' end if Ruby.mri? def kw_args_supported? RUBY_VERSION >= '2.0.0' end def required_kw_args_supported? RUBY_VERSION >= '2.1.0' end def supports_rebinding_module_methods? RUBY_VERSION.to_i >= 2 end else # RBX / JRuby et al support is unknown for keyword arguments begin eval("o = Object.new; def o.m(a: 1); end;"\ " raise SyntaxError unless o.method(:m).parameters.include?([:key, :a])") def kw_args_supported? true end rescue SyntaxError def kw_args_supported? false end end begin eval("o = Object.new; def o.m(a: ); end;"\ "raise SyntaxError unless o.method(:m).parameters.include?([:keyreq, :a])") def required_kw_args_supported? true end rescue SyntaxError def required_kw_args_supported? false end end begin Module.new { def foo; end }.instance_method(:foo).bind(Object.new) def supports_rebinding_module_methods? true end rescue TypeError def supports_rebinding_module_methods? false end end end def module_refinement_supported? Module.method_defined?(:refine) || Module.private_method_defined?(:refine) end def module_prepends_supported? Module.method_defined?(:prepend) || Module.private_method_defined?(:prepend) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/encoded_string.rb0000664000000000000000000001367714566142077026355 0ustar rootroot# frozen_string_literal: true module RSpec module Support # @private class EncodedString # Reduce allocations by storing constants. UTF_8 = "UTF-8" US_ASCII = "US-ASCII" # Ruby's default replacement string is: # U+FFFD ("\xEF\xBF\xBD"), for Unicode encoding forms, else # ? ("\x3F") REPLACE = "?" def initialize(string, encoding=nil) @encoding = encoding @source_encoding = detect_source_encoding(string) @string = matching_encoding(string) end attr_reader :source_encoding delegated_methods = String.instance_methods.map(&:to_s) & %w[eql? lines == encoding empty?] delegated_methods.each do |name| define_method(name) { |*args, &block| @string.__send__(name, *args, &block) } end def <<(string) @string << matching_encoding(string) end if Ruby.jruby? def split(regex_or_string) @string.split(matching_encoding(regex_or_string)) rescue ArgumentError # JRuby raises an ArgumentError when splitting a source string that # contains invalid bytes. remove_invalid_bytes(@string).split regex_or_string end else def split(regex_or_string) @string.split(matching_encoding(regex_or_string)) end end def to_s @string end alias :to_str :to_s if String.method_defined?(:encoding) private # Encoding Exceptions: # # Raised by Encoding and String methods: # Encoding::UndefinedConversionError: # when a transcoding operation fails # if the String contains characters invalid for the target encoding # e.g. "\x80".encode('UTF-8','ASCII-8BIT') # vs "\x80".encode('UTF-8','ASCII-8BIT', undef: :replace, replace: '') # # => '' # Encoding::CompatibilityError # when Encoding.compatible?(str1, str2) is nil # e.g. utf_16le_emoji_string.split("\n") # e.g. valid_unicode_string.encode(utf8_encoding) << ascii_string # Encoding::InvalidByteSequenceError: # when the string being transcoded contains a byte invalid for # either the source or target encoding # e.g. "\x80".encode('UTF-8','US-ASCII') # vs "\x80".encode('UTF-8','US-ASCII', invalid: :replace, replace: '') # # => '' # ArgumentError # when operating on a string with invalid bytes # e.g."\x80".split("\n") # TypeError # when a symbol is passed as an encoding # Encoding.find(:"UTF-8") # when calling force_encoding on an object # that doesn't respond to #to_str # # Raised by transcoding methods: # Encoding::ConverterNotFoundError: # when a named encoding does not correspond with a known converter # e.g. 'abc'.force_encoding('UTF-8').encode('foo') # or a converter path cannot be found # e.g. "\x80".force_encoding('ASCII-8BIT').encode('Emacs-Mule') # # Raised by byte <-> char conversions # RangeError: out of char range # e.g. the UTF-16LE emoji: 128169.chr def matching_encoding(string) string = remove_invalid_bytes(string) string.encode(@encoding) rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError # Originally defined as a constant to avoid unneeded allocations, this hash must # be defined inline (without {}) to avoid warnings on Ruby 2.7 # # In MRI 2.1 'invalid: :replace' changed to also replace an invalid byte sequence # see https://github.com/ruby/ruby/blob/v2_1_0/NEWS#L176 # https://www.ruby-forum.com/topic/6861247 # https://twitter.com/nalsh/status/553413844685438976 # # For example, given: # "\x80".force_encoding("Emacs-Mule").encode(:invalid => :replace).bytes.to_a # # On MRI 2.1 or above: 63 # '?' # else : 128 # "\x80" # string.encode(@encoding, :invalid => :replace, :undef => :replace, :replace => REPLACE) rescue Encoding::ConverterNotFoundError # Originally defined as a constant to avoid unneeded allocations, this hash must # be defined inline (without {}) to avoid warnings on Ruby 2.7 string.dup.force_encoding(@encoding).encode(:invalid => :replace, :replace => REPLACE) end # Prevents raising ArgumentError if String.method_defined?(:scrub) # https://github.com/ruby/ruby/blob/eeb05e8c11/doc/NEWS-2.1.0#L120-L123 # https://github.com/ruby/ruby/blob/v2_1_0/string.c#L8242 # https://github.com/hsbt/string-scrub # https://github.com/rubinius/rubinius/blob/v2.5.2/kernel/common/string.rb#L1913-L1972 def remove_invalid_bytes(string) string.scrub(REPLACE) end else # http://stackoverflow.com/a/8711118/879854 # Loop over chars in a string replacing chars # with invalid encoding, which is a pretty good proxy # for the invalid byte sequence that causes an ArgumentError def remove_invalid_bytes(string) string.chars.map do |char| char.valid_encoding? ? char : REPLACE end.join end end def detect_source_encoding(string) string.encoding end def self.pick_encoding(source_a, source_b) Encoding.compatible?(source_a, source_b) || Encoding.default_external end else def self.pick_encoding(_source_a, _source_b) end private def matching_encoding(string) string end def detect_source_encoding(_string) US_ASCII end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/0000775000000000000000000000000014566142077023755 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/stderr_splitter.rb0000664000000000000000000000410714566142077027535 0ustar rootroot# frozen_string_literal: true require 'stringio' module RSpec module Support class StdErrSplitter def initialize(original) @orig_stderr = original @output_tracker = ::StringIO.new @last_line = nil end respond_to_name = (::RUBY_VERSION.to_f < 1.9) ? :respond_to? : :respond_to_missing? define_method respond_to_name do |*args| @orig_stderr.respond_to?(*args) || super(*args) end def method_missing(name, *args, &block) @output_tracker.__send__(name, *args, &block) if @output_tracker.respond_to?(name) @orig_stderr.__send__(name, *args, &block) end def ==(other) @orig_stderr == other end def reopen(*args) reset! @orig_stderr.reopen(*args) end # To work around JRuby error: # can't convert RSpec::Support::StdErrSplitter into String def to_io @orig_stderr.to_io end # To work around JRuby error: # TypeError: $stderr must have write method, RSpec::StdErrSplitter given def write(line) return if line =~ %r{^\S+/gems/\S+:\d+: warning:} # http://rubular.com/r/kqeUIZOfPG # Ruby 2.7.0 warnings from keyword arguments span multiple lines, extend check above # to look for the next line. return if @last_line =~ %r{^\S+/gems/\S+:\d+: warning:} && line =~ %r{warning: The called method .* is defined here} # Ruby 2.7.0 complains about hashes used in place of keyword arguments # Aruba 0.14.2 uses this internally triggering that here return if line =~ %r{lib/ruby/2\.7\.0/fileutils\.rb:622: warning:} @orig_stderr.write(line) @output_tracker.write(line) ensure @last_line = line end def has_output? !output.empty? end def reset! @output_tracker = ::StringIO.new end def verify_no_warnings! raise "Warnings were generated: #{output}" if has_output? reset! end def output @output_tracker.string end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/string_matcher.rb0000664000000000000000000000264514566142077027322 0ustar rootroot# frozen_string_literal: true require 'rspec/matchers' # Special matcher for comparing encoded strings so that # we don't run any expectation failures through the Differ, # which also relies on EncodedString. Instead, confirm the # strings have the same bytes. RSpec::Matchers.define :be_identical_string do |expected| if String.method_defined?(:encoding) match do expected_encoding? && actual.bytes.to_a == expected.bytes.to_a end failure_message do "expected\n#{actual.inspect} (#{actual.encoding.name}) to be identical to\n"\ "#{expected.inspect} (#{expected.encoding.name})\n"\ "The exact bytes are printed below for more detail:\n"\ "#{actual.bytes.to_a}\n"\ "#{expected.bytes.to_a}\n"\ end # Depends on chaining :with_same_encoding for it to # check for string encoding. def expected_encoding? if defined?(@expect_same_encoding) && @expect_same_encoding actual.encoding == expected.encoding else true end end else match do actual.split(//) == expected.split(//) end failure_message do "expected\n#{actual.inspect} to be identical to\n#{expected.inspect}\n" end end chain :with_same_encoding do @expect_same_encoding ||= true end end RSpec::Matchers.alias_matcher :a_string_identical_to, :be_identical_string RSpec::Matchers.alias_matcher :be_diffed_as, :be_identical_string ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/diff_helpers.rb0000664000000000000000000000144514566142077026740 0ustar rootroot# frozen_string_literal: true require 'diff/lcs' module RSpec module Support module Spec module DiffHelpers # In the updated version of diff-lcs several diff headers change format slightly # compensate for this and change minimum version in RSpec 4 if ::Diff::LCS::VERSION.to_f < 1.4 def one_line_header(line_number=2) "-1,#{line_number} +1,#{line_number}" end else def one_line_header(_=2) "-1 +1" end end if Diff::LCS::VERSION.to_f < 1.4 || Diff::LCS::VERSION >= "1.4.4" def removing_two_line_header "-1,3 +1" end else def removing_two_line_header "-1,3 +1,5" end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/with_isolated_stderr.rb0000664000000000000000000000040614566142077030524 0ustar rootroot# frozen_string_literal: true module RSpec module Support module WithIsolatedStdErr def with_isolated_stderr original = $stderr $stderr = StringIO.new yield ensure $stderr = original end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/library_wide_checks.rb0000664000000000000000000001247114566142077030303 0ustar rootroot# frozen_string_literal: true require 'rspec/support/spec/shell_out' module RSpec module Support module WhitespaceChecks # This malformed whitespace detection logic has been borrowed from bundler: # https://github.com/bundler/bundler/blob/v1.8.0/spec/quality_spec.rb def check_for_tab_characters(filename) failing_lines = [] File.readlines(filename).each_with_index do |line, number| failing_lines << number + 1 if line =~ /\t/ end return if failing_lines.empty? "#{filename} has tab characters on lines #{failing_lines.join(', ')}" end def check_for_extra_spaces(filename) failing_lines = [] File.readlines(filename).each_with_index do |line, number| next if line =~ /^\s+#.*\s+\n$/ failing_lines << number + 1 if line =~ /\s+\n$/ end return if failing_lines.empty? "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}" end end end end RSpec.shared_examples_for "library wide checks" do |lib, options| consider_a_test_env_file = options.fetch(:consider_a_test_env_file, /MATCHES NOTHING/) allowed_loaded_feature_regexps = options.fetch(:allowed_loaded_feature_regexps, []) preamble_for_lib = options[:preamble_for_lib] preamble_for_spec = "require 'rspec/core'; require 'spec_helper'" skip_spec_files = options.fetch(:skip_spec_files, /MATCHES NOTHING/) include RSpec::Support::ShellOut include RSpec::Support::WhitespaceChecks define_method :files_to_require_for do |sub_dir| slash = File::SEPARATOR lib_path_re = /#{slash + lib}[^#{slash}]*#{slash}lib/ load_path = $LOAD_PATH.grep(lib_path_re).first directory = load_path.sub(/lib$/, sub_dir) files = Dir["#{directory}/**/*.rb"] extract_regex = /#{Regexp.escape(directory) + File::SEPARATOR}(.+)\.rb$/ # We sort to ensure the files are loaded in a consistent order, regardless # of OS. Otherwise, it could load in a different order on Travis than # locally, and potentially trigger a "circular require considered harmful" # warning or similar. files.sort.map { |file| file[extract_regex, 1] } end def command_from(code_lines) code_lines.join("\n") end def load_all_files(files, preamble, postamble=nil) requires = files.map { |f| "require '#{f}'" } command = command_from(Array(preamble) + requires + Array(postamble)) stdout, stderr, status = with_env 'NO_COVERAGE' => '1' do options = %w[ -w ] options << "--disable=gem" if RUBY_VERSION.to_f >= 1.9 && RSpec::Support::Ruby.mri? run_ruby_with_current_load_path(command, *options) end [stdout, strip_known_warnings(stderr), status.exitstatus] end define_method :load_all_lib_files do files = all_lib_files - lib_test_env_files preamble = ['orig_loaded_features = $".dup', preamble_for_lib] postamble = ['puts(($" - orig_loaded_features).join("\n"))'] @loaded_feature_lines, stderr, exitstatus = load_all_files(files, preamble, postamble) ["", stderr, exitstatus] end define_method :load_all_spec_files do files = files_to_require_for("spec") + lib_test_env_files files = files.reject { |f| f =~ skip_spec_files } load_all_files(files, preamble_for_spec) end attr_reader :all_lib_files, :lib_test_env_files, :lib_file_results, :spec_file_results before(:context) do @all_lib_files = files_to_require_for("lib") @lib_test_env_files = all_lib_files.grep(consider_a_test_env_file) @lib_file_results, @spec_file_results = [ # Load them in parallel so it's faster... Thread.new { load_all_lib_files }, Thread.new { load_all_spec_files } ].map(&:join).map(&:value) end def have_successful_no_warnings_output eq ["", "", 0] end it "issues no warnings when loaded", :slow do expect(lib_file_results).to have_successful_no_warnings_output end it "issues no warnings when the spec files are loaded", :slow do expect(spec_file_results).to have_successful_no_warnings_output end it 'only loads a known set of stdlibs so gem authors are forced ' \ 'to load libs they use to have passing specs', :slow do loaded_features = @loaded_feature_lines.split("\n") if RUBY_VERSION == '1.8.7' # On 1.8.7, $" returns the relative require path if that was used # to require the file. LIB_REGEX will not match the relative version # since it has a `/lib` prefix. Here we deal with this by expanding # relative files relative to the $LOAD_PATH dir (lib). Dir.chdir("lib") { loaded_features.map! { |f| File.expand_path(f) } } end loaded_features.reject! { |feature| RSpec::CallerFilter::LIB_REGEX =~ feature } loaded_features.reject! { |feature| allowed_loaded_feature_regexps.any? { |r| r =~ feature } } expect(loaded_features).to eq([]) end RSpec::Matchers.define :be_well_formed do match do |actual| actual.empty? end failure_message do |actual| actual.join("\n") end end it "has no malformed whitespace", :slow do error_messages = [] `git ls-files -z`.split("\x0").each do |filename| error_messages << check_for_tab_characters(filename) error_messages << check_for_extra_spaces(filename) end expect(error_messages.compact).to be_well_formed end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/shell_out.rb0000664000000000000000000000646014566142077026306 0ustar rootroot# frozen_string_literal: true require 'open3' require 'rake/file_utils' require 'shellwords' module RSpec module Support module ShellOut def with_env(vars) original = ENV.to_hash vars.each { |k, v| ENV[k] = v } begin yield ensure ENV.replace(original) end end if Open3.respond_to?(:capture3) # 1.9+ def shell_out(*command) stdout, stderr, status = Open3.capture3(*command) return stdout, filter(stderr), status end else # 1.8.7 # popen3 doesn't provide the exit status so we fake it out. FakeProcessStatus = Struct.new(:exitstatus) def shell_out(*command) stdout = stderr = nil Open3.popen3(*command) do |_in, out, err| stdout = out.read stderr = err.read end status = FakeProcessStatus.new(0) return stdout, filter(stderr), status end end def run_ruby_with_current_load_path(ruby_command, *flags) command = [ FileUtils::RUBY, "-I#{$LOAD_PATH.map(&:shellescape).join(File::PATH_SEPARATOR)}", "-e", ruby_command, *flags ] # Unset these env vars because `ruby -w` will issue warnings whenever # they are set to non-default values. with_env 'RUBY_GC_HEAP_FREE_SLOTS' => nil, 'RUBY_GC_MALLOC_LIMIT' => nil, 'RUBY_FREE_MIN' => nil do shell_out(*command) end end LINES_TO_IGNORE = [ # Ignore bundler warning. %r{bundler/source/rubygems}, # Ignore bundler + rubygems warning. %r{site_ruby/\d\.\d\.\d/rubygems}, %r{jruby-\d\.\d\.\d+\.\d/lib/ruby/stdlib/rubygems}, # This is required for windows for some reason %r{lib/bundler/rubygems}, # This is a JRuby file that generates warnings on 9.0.3.0 %r{lib/ruby/stdlib/jar}, # This is a JRuby file that generates warnings on 9.1.7.0 %r{org/jruby/RubyKernel\.java}, # This is a JRuby gem that generates warnings on 9.1.7.0 %r{ffi-1\.13\.\d+-java}, %r{uninitialized constant FFI}, # These are related to the above, there is a warning about io from FFI %r{jruby-\d\.\d\.\d+\.\d/lib/ruby/stdlib/io}, %r{io/console on JRuby shells out to stty for most operations}, # This is a JRuby 9.1.17.0 error on Github Actions %r{io/console not supported; tty will not be manipulated}, # This is a JRuby 9.2.1.x error %r{jruby/kernel/gem_prelude}, %r{lib/jruby\.jar!/jruby/preludes}, # Ignore some JRuby errors for gems %r{jruby/\d\.\d(\.\d)?/gems/aruba}, %r{jruby/\d\.\d(\.\d)?/gems/ffi}, ] def strip_known_warnings(input) input.split("\n").reject do |l| LINES_TO_IGNORE.any? { |to_ignore| l =~ to_ignore } || # Remove blank lines l == "" || l.nil? end.join("\n") end private if Ruby.jruby? def filter(output) output.each_line.reject do |line| line.include?("lib/ruby/shared/rubygems") end.join($/) end else def filter(output) output end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/with_isolated_directory.rb0000664000000000000000000000043714566142077031231 0ustar rootroot# frozen_string_literal: true require 'tmpdir' RSpec.shared_context "isolated directory" do around do |ex| Dir.mktmpdir do |tmp_dir| Dir.chdir(tmp_dir, &ex) end end end RSpec.configure do |c| c.include_context "isolated directory", :isolated_directory => true end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/formatting_support.rb0000664000000000000000000000026714566142077030255 0ustar rootroot# frozen_string_literal: true module RSpec module Support module FormattingSupport def dedent(string) string.gsub(/^\s+\|/, '').chomp end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/deprecation_helpers.rb0000664000000000000000000000316214566142077030323 0ustar rootroot# frozen_string_literal: true module RSpecHelpers def expect_deprecation_with_call_site(file, line, snippet=//) expect(RSpec.configuration.reporter).to receive(:deprecation). with(include(:deprecated => match(snippet), :call_site => include([file, line].join(':')))) end def expect_deprecation_without_call_site(snippet=//) expect(RSpec.configuration.reporter).to receive(:deprecation). with(include(:deprecated => match(snippet), :call_site => eq(nil))) end def expect_warn_deprecation_with_call_site(file, line, snippet=//) expect(RSpec.configuration.reporter).to receive(:deprecation). with(include(:message => match(snippet), :call_site => include([file, line].join(':')))) end def expect_warn_deprecation(snippet=//) expect(RSpec.configuration.reporter).to receive(:deprecation). with(include(:message => match(snippet))) end def allow_deprecation allow(RSpec.configuration.reporter).to receive(:deprecation) end def expect_no_deprecations expect(RSpec.configuration.reporter).not_to receive(:deprecation) end alias expect_no_deprecation expect_no_deprecations def expect_warning_without_call_site(expected=//) expect(::Kernel).to receive(:warn). with(match(expected).and(satisfy { |message| !(/Called from/ =~ message) })) end def expect_warning_with_call_site(file, line, expected=//) expect(::Kernel).to receive(:warn). with(match(expected).and(match(/Called from #{file}:#{line}/))) end def expect_no_warnings expect(::Kernel).not_to receive(:warn) end def allow_warning allow(::Kernel).to receive(:warn) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec/in_sub_process.rb0000664000000000000000000000464014566142077027323 0ustar rootroot# frozen_string_literal: true module RSpec module Support module InSubProcess if Process.respond_to?(:fork) && !(Ruby.jruby? && RUBY_VERSION == '1.8.7') UnmarshableObject = Struct.new(:error) # Useful as a way to isolate a global change to a subprocess. def in_sub_process(prevent_warnings=true) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize exception_reader, exception_writer = IO.pipe result_reader, result_writer = IO.pipe # Set binary mode to avoid errors surrounding ascii-8bit to utf-8 conversion # this happens with warnings on rspec-rails for example [exception_reader, exception_writer, result_reader, result_writer].each { |io| io.binmode } pid = Process.fork do warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr) begin result = yield warning_preventer.verify_no_warnings! if prevent_warnings # rubocop:disable Lint/HandleExceptions rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception # rubocop:enable Lint/HandleExceptions end exception_writer.write marshal_dump_with_unmarshable_object_handling(exception) exception_reader.close exception_writer.close result_writer.write marshal_dump_with_unmarshable_object_handling(result) result_reader.close result_writer.close exit! # prevent at_exit hooks from running (e.g. minitest) end exception_writer.close result_writer.close Process.waitpid(pid) exception = Marshal.load(exception_reader.read) exception_reader.close raise exception if exception result = Marshal.load(result_reader.read) result_reader.close result end alias :in_sub_process_if_possible :in_sub_process def marshal_dump_with_unmarshable_object_handling(object) Marshal.dump(object) rescue TypeError => error Marshal.dump(UnmarshableObject.new(error)) end else def in_sub_process(*) skip "This spec requires forking to work properly, " \ "and your platform does not support forking" end def in_sub_process_if_possible(*) yield end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/recursive_const_methods.rb0000664000000000000000000000504414566142077030313 0ustar rootroot# frozen_string_literal: true module RSpec module Support # Provides recursive constant lookup methods useful for # constant stubbing. module RecursiveConstMethods # We only want to consider constants that are defined directly on a # particular module, and not include top-level/inherited constants. # Unfortunately, the constant API changed between 1.8 and 1.9, so # we need to conditionally define methods to ignore the top-level/inherited # constants. # # Given: # class A; B = 1; end # class C < A; end # # On 1.8: # - C.const_get("Hash") # => ::Hash # - C.const_defined?("Hash") # => false # - C.constants # => ["B"] # - None of these methods accept the extra `inherit` argument # On 1.9: # - C.const_get("Hash") # => ::Hash # - C.const_defined?("Hash") # => true # - C.const_get("Hash", false) # => raises NameError # - C.const_defined?("Hash", false) # => false # - C.constants # => [:B] # - C.constants(false) #=> [] if Module.method(:const_defined?).arity == 1 def const_defined_on?(mod, const_name) mod.const_defined?(const_name) end def get_const_defined_on(mod, const_name) return mod.const_get(const_name) if const_defined_on?(mod, const_name) raise NameError, "uninitialized constant #{mod.name}::#{const_name}" end def constants_defined_on(mod) mod.constants.select { |c| const_defined_on?(mod, c) } end else def const_defined_on?(mod, const_name) mod.const_defined?(const_name, false) end def get_const_defined_on(mod, const_name) mod.const_get(const_name, false) end def constants_defined_on(mod) mod.constants(false) end end def recursive_const_get(const_name) normalize_const_name(const_name).split('::').inject(Object) do |mod, name| get_const_defined_on(mod, name) end end def recursive_const_defined?(const_name) parts = normalize_const_name(const_name).split('::') parts.inject([Object, '']) do |(mod, full_name), name| yield(full_name, name) if block_given? && !(Module === mod) return false unless const_defined_on?(mod, name) [get_const_defined_on(mod, name), [mod.name, name].join('::')] end end def normalize_const_name(const_name) const_name.sub(/\A::/, '') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/spec.rb0000664000000000000000000000503714566142077024307 0ustar rootroot# frozen_string_literal: true require 'rspec/support' require 'rspec/support/spec/in_sub_process' RSpec::Support.require_rspec_support "spec/deprecation_helpers" RSpec::Support.require_rspec_support "spec/diff_helpers" RSpec::Support.require_rspec_support "spec/with_isolated_stderr" RSpec::Support.require_rspec_support "spec/stderr_splitter" RSpec::Support.require_rspec_support "spec/formatting_support" RSpec::Support.require_rspec_support "spec/with_isolated_directory" RSpec::Support.require_rspec_support "ruby_features" warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr) RSpec.configure do |c| c.include RSpecHelpers c.include RSpec::Support::WithIsolatedStdErr c.include RSpec::Support::FormattingSupport c.include RSpec::Support::InSubProcess unless defined?(Debugger) # debugger causes warnings when used c.before do warning_preventer.reset! end c.after do warning_preventer.verify_no_warnings! end end if c.files_to_run.one? c.full_backtrace = true c.default_formatter = 'doc' end c.filter_run_when_matching :focus c.example_status_persistence_file_path = "./spec/examples.txt" c.define_derived_metadata :failing_on_windows_ci do |meta| meta[:pending] ||= "This spec fails on Windows CI and needs someone to fix it." end if RSpec::Support::OS.windows? && ENV['CI'] end module RSpec module Support module Spec def self.setup_simplecov(&block) # Simplecov emits some ruby warnings when loaded, so silence them. old_verbose, $VERBOSE = $VERBOSE, false return if ENV['NO_COVERAGE'] || RUBY_VERSION < '1.9.3' return if RUBY_ENGINE != 'ruby' || RSpec::Support::OS.windows? # Don't load it when we're running a single isolated # test file rather than the whole suite. return if RSpec.configuration.files_to_run.one? require 'simplecov' start_simplecov(&block) rescue LoadError warn "Simplecov could not be loaded" ensure $VERBOSE = old_verbose end def self.start_simplecov(&block) SimpleCov.start do add_filter "bundle/" add_filter "tmp/" add_filter do |source_file| # Filter out `spec` directory except when it is under `lib` # (as is the case in rspec-support) source_file.filename.include?('/spec/') && !source_file.filename.include?('/lib/') end instance_eval(&block) if block end end private_class_method :start_simplecov end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/source.rb0000664000000000000000000000472114566142077024654 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support 'encoded_string' RSpec::Support.require_rspec_support 'ruby_features' module RSpec module Support # @private # Represents a Ruby source file and provides access to AST and tokens. class Source attr_reader :source, :path # This class protects us against having File read and expand_path # stubbed out within tests. class File class << self [:read, :expand_path].each do |method_name| define_method(method_name, &::File.method(method_name)) end end end def self.from_file(path) source = File.read(path) new(source, path) end if String.method_defined?(:encoding) def initialize(source_string, path=nil) @source = RSpec::Support::EncodedString.new(source_string, Encoding.default_external) @path = path ? File.expand_path(path) : '(string)' end else # for 1.8.7 # :nocov: def initialize(source_string, path=nil) @source = RSpec::Support::EncodedString.new(source_string) @path = path ? File.expand_path(path) : '(string)' end # :nocov: end def lines @lines ||= source.split("\n") end def inspect "#<#{self.class} #{path}>" end if RSpec::Support::RubyFeatures.ripper_supported? RSpec::Support.require_rspec_support 'source/node' RSpec::Support.require_rspec_support 'source/token' def ast @ast ||= begin require 'ripper' sexp = Ripper.sexp(source) raise SyntaxError unless sexp Node.new(sexp) end end def tokens @tokens ||= begin require 'ripper' tokens = Ripper.lex(source) Token.tokens_from_ripper_tokens(tokens) end end def nodes_by_line_number @nodes_by_line_number ||= begin nodes_by_line_number = ast.select(&:location).group_by { |node| node.location.line } Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number) end end def tokens_by_line_number @tokens_by_line_number ||= begin nodes_by_line_number = tokens.group_by { |token| token.location.line } Hash.new { |hash, key| hash[key] = [] }.merge(nodes_by_line_number) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/caller_filter.rb0000664000000000000000000000777614566142077026200 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support "ruby_features" module RSpec # Consistent implementation for "cleaning" the caller method to strip out # non-rspec lines. This enables errors to be reported at the call site in # the code using the library, which is far more useful than the particular # internal method that raised an error. class CallerFilter RSPEC_LIBS = %w[ core mocks expectations support matchers rails ] ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ] LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)} # rubygems/core_ext/kernel_require.rb isn't actually part of rspec (obviously) but we want # it ignored when we are looking for the first meaningful line of the backtrace outside # of RSpec. It can show up in the backtrace as the immediate first caller # when `CallerFilter.first_non_rspec_line` is called from the top level of a required # file, but it depends on if rubygems is loaded or not. We don't want to have to deal # with this complexity in our `RSpec.deprecate` calls, so we ignore it here. IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb", " e raise e unless directory_exists?(stack) rescue Errno::ENOTDIR => e raise Errno::EEXIST, e.message end end end if OS.windows_file_path? def self.generate_stack(path) if path.start_with?(File::SEPARATOR) File::SEPARATOR elsif path[1] == ':' '' else '.' end end def self.generate_path(stack, part) if stack == '' part elsif stack == File::SEPARATOR File.join('', part) else File.join(stack, part) end end else def self.generate_stack(path) path.start_with?(File::SEPARATOR) ? File::SEPARATOR : "." end def self.generate_path(stack, part) File.join(stack, part) end end def self.directory_exists?(dirname) File.exist?(dirname) && File.directory?(dirname) end private_class_method :directory_exists? private_class_method :generate_stack private_class_method :generate_path end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/reentrant_mutex.rb0000664000000000000000000000414314566142077026576 0ustar rootroot# frozen_string_literal: true module RSpec module Support # Allows a thread to lock out other threads from a critical section of code, # while allowing the thread with the lock to reenter that section. # # Based on Monitor as of 2.2 - # https://github.com/ruby/ruby/blob/eb7ddaa3a47bf48045d26c72eb0f263a53524ebc/lib/monitor.rb#L9 # # Depends on Mutex, but Mutex is only available as part of core since 1.9.1: # exists - http://ruby-doc.org/core-1.9.1/Mutex.html # dne - http://ruby-doc.org/core-1.9.0/Mutex.html # # @private class ReentrantMutex def initialize @owner = nil @count = 0 @mutex = Mutex.new end def synchronize enter yield ensure exit end private # This is fixing a bug #501 that is specific to Ruby 3.0. The new implementation # depends on `owned?` that was introduced in Ruby 2.0, so both should work for Ruby 2.x. if RUBY_VERSION.to_f >= 3.0 def enter @mutex.lock unless @mutex.owned? @count += 1 end def exit unless @mutex.owned? raise ThreadError, "Attempt to unlock a mutex which is locked by another thread/fiber" end @count -= 1 @mutex.unlock if @count == 0 end else def enter @mutex.lock if @owner != Thread.current @owner = Thread.current @count += 1 end def exit @count -= 1 return unless @count == 0 @owner = nil @mutex.unlock end end end if defined? ::Mutex # On 1.9 and up, this is in core, so we just use the real one class Mutex < ::Mutex # If you mock Mutex.new you break our usage of Mutex, so # instead we capture the original method to return Mutexes. NEW_MUTEX_METHOD = Mutex.method(:new) def self.new NEW_MUTEX_METHOD.call end end else # For 1.8.7 # :nocov: RSpec::Support.require_rspec_support "mutex" # :nocov: end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/warnings.rb0000664000000000000000000000215314566142077025201 0ustar rootroot# frozen_string_literal: true require 'rspec/support' RSpec::Support.require_rspec_support "caller_filter" module RSpec module Support module Warnings def deprecate(deprecated, options={}) warn_with "DEPRECATION: #{deprecated} is deprecated.", options end # @private # # Used internally to print deprecation warnings # when rspec-core isn't loaded def warn_deprecation(message, options={}) warn_with "DEPRECATION: \n #{message}", options end # @private # # Used internally to print warnings def warning(text, options={}) warn_with "WARNING: #{text}.", options end # @private # # Used internally to print longer warnings def warn_with(message, options={}) call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line } message += " Use #{options[:replacement]} instead." if options[:replacement] message += " Called from #{call_site}." if call_site Support.warning_notifier.call message end end end extend RSpec::Support::Warnings end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/comparable_version.rb0000664000000000000000000000211114566142077027215 0ustar rootroot# frozen_string_literal: true module RSpec module Support # @private class ComparableVersion include Comparable attr_reader :string def initialize(string) @string = string end def <=>(other) other = self.class.new(other) unless other.is_a?(self.class) return 0 if string == other.string longer_segment_count = [self, other].map { |version| version.segments.count }.max longer_segment_count.times do |index| self_segment = segments[index] || 0 other_segment = other.segments[index] || 0 if self_segment.class == other_segment.class result = self_segment <=> other_segment return result unless result == 0 else return self_segment.is_a?(String) ? -1 : 1 end end 0 end def segments @segments ||= string.scan(/[a-z]+|\d+/i).map do |segment| if segment =~ /\A\d+\z/ segment.to_i else segment end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/with_keywords_when_needed.rb0000664000000000000000000000205514566142077030601 0ustar rootroot# frozen_string_literal: true RSpec::Support.require_rspec_support("method_signature_verifier") module RSpec module Support module WithKeywordsWhenNeeded # This module adds keyword sensitive support for core ruby methods # where we cannot use `ruby2_keywords` directly. module_function if RSpec::Support::RubyFeatures.kw_args_supported? # Remove this in RSpec 4 in favour of explicitly passed in kwargs where # this is used. Works around a warning in Ruby 2.7 def class_exec(klass, *args, &block) if MethodSignature.new(block).has_kw_args_in?(args) binding.eval(<<-CODE, __FILE__, __LINE__) kwargs = args.pop klass.class_exec(*args, **kwargs, &block) CODE else klass.class_exec(*args, &block) end end ruby2_keywords :class_exec if respond_to?(:ruby2_keywords, true) else def class_exec(klass, *args, &block) klass.class_exec(*args, &block) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/mutex.rb0000664000000000000000000000335114566142077024514 0ustar rootroot# frozen_string_literal: true module RSpec module Support # On 1.8.7, it's in the stdlib. # We don't want to load the stdlib, b/c this is a test tool, and can affect # the test environment, causing tests to pass where they should fail. # # So we're transcribing/modifying it from # https://github.com/ruby/ruby/blob/v1_8_7_374/lib/thread.rb#L56 # Some methods we don't need are deleted. Anything I don't # understand (there's quite a bit, actually) is left in. # # Some formatting changes are made to appease the robot overlord: # https://travis-ci.org/rspec/rspec-core/jobs/54410874 # @private class Mutex def initialize @waiting = [] @locked = false @waiting.taint taint end # @private def lock while Thread.critical = true && @locked @waiting.push Thread.current Thread.stop end @locked = true Thread.critical = false self end # @private def unlock return unless @locked Thread.critical = true @locked = false wakeup_and_run_waiting_thread self end # @private def synchronize lock begin yield ensure unlock end end private def wakeup_and_run_waiting_thread begin t = @waiting.shift t.wakeup if t rescue ThreadError retry end Thread.critical = false begin t.run if t rescue ThreadError :noop end end # Avoid warnings for library wide checks spec end unless defined?(::RSpec::Support::Mutex) || defined?(::Mutex) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/lib/rspec/support/method_signature_verifier.rb0000664000000000000000000003267614566142077030622 0ustar rootroot# frozen_string_literal: true require 'rspec/support' RSpec::Support.require_rspec_support "ruby_features" RSpec::Support.require_rspec_support "matcher_definition" module RSpec module Support # Extracts info about the number of arguments and allowed/required # keyword args of a given method. # # @private class MethodSignature # rubocop:disable Metrics/ClassLength attr_reader :min_non_kw_args, :max_non_kw_args, :optional_kw_args, :required_kw_args def initialize(method) @method = method @optional_kw_args = [] @required_kw_args = [] classify_parameters end def non_kw_args_arity_description case max_non_kw_args when min_non_kw_args then min_non_kw_args.to_s when INFINITY then "#{min_non_kw_args} or more" else "#{min_non_kw_args} to #{max_non_kw_args}" end end def valid_non_kw_args?(positional_arg_count, optional_max_arg_count=positional_arg_count) return true if positional_arg_count.nil? min_non_kw_args <= positional_arg_count && optional_max_arg_count <= max_non_kw_args end def classify_arity(arity=@method.arity) if arity < 0 # `~` inverts the one's complement and gives us the # number of required args @min_non_kw_args = ~arity @max_non_kw_args = INFINITY else @min_non_kw_args = arity @max_non_kw_args = arity end end if RubyFeatures.optional_and_splat_args_supported? def description @description ||= begin parts = [] unless non_kw_args_arity_description == "0" parts << "arity of #{non_kw_args_arity_description}" end if @optional_kw_args.any? parts << "optional keyword args (#{@optional_kw_args.map(&:inspect).join(", ")})" end if @required_kw_args.any? parts << "required keyword args (#{@required_kw_args.map(&:inspect).join(", ")})" end parts << "any additional keyword args" if @allows_any_kw_args parts.join(" and ") end end def missing_kw_args_from(given_kw_args) @required_kw_args - given_kw_args end def invalid_kw_args_from(given_kw_args) return [] if @allows_any_kw_args given_kw_args - @allowed_kw_args end # If the last argument is Hash, Ruby will treat only symbol keys as keyword arguments # the rest will be grouped in another Hash and passed as positional argument. def has_kw_args_in?(args) Hash === args.last && could_contain_kw_args?(args) && (RubyFeatures.kw_arg_separation? || args.last.empty? || args.last.keys.any? { |x| x.is_a?(Symbol) }) end # Without considering what the last arg is, could it # contain keyword arguments? def could_contain_kw_args?(args) return false if args.count <= min_non_kw_args @allows_any_kw_args || @allowed_kw_args.any? end def arbitrary_kw_args? @allows_any_kw_args end def unlimited_args? @max_non_kw_args == INFINITY end def classify_parameters optional_non_kw_args = @min_non_kw_args = 0 @allows_any_kw_args = false @method.parameters.each do |(type, name)| case type # def foo(a:) when :keyreq then @required_kw_args << name # def foo(a: 1) when :key then @optional_kw_args << name # def foo(**kw_args) when :keyrest then @allows_any_kw_args = true # def foo(a) when :req then @min_non_kw_args += 1 # def foo(a = 1) when :opt then optional_non_kw_args += 1 # def foo(*a) when :rest then optional_non_kw_args = INFINITY end end @max_non_kw_args = @min_non_kw_args + optional_non_kw_args @allowed_kw_args = @required_kw_args + @optional_kw_args end else def description "arity of #{non_kw_args_arity_description}" end def missing_kw_args_from(_given_kw_args) [] end def invalid_kw_args_from(_given_kw_args) [] end def has_kw_args_in?(_args) false end def could_contain_kw_args?(*) false end def arbitrary_kw_args? false end def unlimited_args? false end alias_method :classify_parameters, :classify_arity end INFINITY = 1 / 0.0 end if RSpec::Support::Ruby.jruby? # JRuby has only partial support for UnboundMethod#parameters, so we fall back on using #arity # https://github.com/jruby/jruby/issues/2816 and https://github.com/jruby/jruby/issues/2817 if RubyFeatures.optional_and_splat_args_supported? && Java::JavaLang::String.instance_method(:char_at).parameters == [] class MethodSignature < remove_const(:MethodSignature) private def classify_parameters super if (arity = @method.arity) != 0 && @method.parameters.empty? classify_arity(arity) end end end end # JRuby used to always report -1 arity for Java proxy methods. # The workaround essentially makes use of Java's introspection to figure # out matching methods (which could be more than one partly because Java # supports multiple overloads, and partly because JRuby introduces # aliases to make method names look more Rubyesque). If there is only a # single match, we can use that methods arity directly instead of the # default -1 arity. # # This workaround only works for Java proxy methods, and in order to # support regular methods and blocks, we need to be careful about calling # owner and java_class as they might not be available if Java::JavaLang::String.instance_method(:char_at).arity == -1 class MethodSignature < remove_const(:MethodSignature) private def classify_parameters super return unless @method.arity == -1 return unless @method.respond_to?(:owner) return unless @method.owner.respond_to?(:java_class) java_instance_methods = @method.owner.java_class.java_instance_methods compatible_overloads = java_instance_methods.select do |java_method| @method == @method.owner.instance_method(java_method.name) end if compatible_overloads.size == 1 classify_arity(compatible_overloads.first.arity) end end end end end # Encapsulates expectations about the number of arguments and # allowed/required keyword args of a given method. # # @api private class MethodSignatureExpectation def initialize @min_count = nil @max_count = nil @keywords = [] @expect_unlimited_arguments = false @expect_arbitrary_keywords = false end attr_reader :min_count, :max_count, :keywords attr_accessor :expect_unlimited_arguments, :expect_arbitrary_keywords def max_count=(number) raise ArgumentError, 'must be a non-negative integer or nil' \ unless number.nil? || (number.is_a?(Integer) && number >= 0) @max_count = number end def min_count=(number) raise ArgumentError, 'must be a non-negative integer or nil' \ unless number.nil? || (number.is_a?(Integer) && number >= 0) @min_count = number end def empty? @min_count.nil? && @keywords.to_a.empty? && !@expect_arbitrary_keywords && !@expect_unlimited_arguments end def keywords=(values) @keywords = values.to_a || [] end end # Deals with the slightly different semantics of block arguments. # For methods, arguments are required unless a default value is provided. # For blocks, arguments are optional, even if no default value is provided. # # However, we want to treat block args as required since you virtually # always want to pass a value for each received argument and our # `and_yield` has treated block args as required for many years. # # @api private class BlockSignature < MethodSignature if RubyFeatures.optional_and_splat_args_supported? def classify_parameters super @min_non_kw_args = @max_non_kw_args unless @max_non_kw_args == INFINITY end end end # Abstract base class for signature verifiers. # # @api private class MethodSignatureVerifier attr_reader :non_kw_args, :kw_args, :min_non_kw_args, :max_non_kw_args def initialize(signature, args=[]) @signature = signature @non_kw_args, @kw_args = split_args(*args) @min_non_kw_args = @max_non_kw_args = @non_kw_args @arbitrary_kw_args = @unlimited_args = false end def with_expectation(expectation) # rubocop:disable Metrics/MethodLength return self unless MethodSignatureExpectation === expectation if expectation.empty? @min_non_kw_args = @max_non_kw_args = @non_kw_args = nil @kw_args = [] else @min_non_kw_args = @non_kw_args = expectation.min_count || 0 @max_non_kw_args = expectation.max_count || @min_non_kw_args if RubyFeatures.optional_and_splat_args_supported? @unlimited_args = expectation.expect_unlimited_arguments else @unlimited_args = false end if RubyFeatures.kw_args_supported? @kw_args = expectation.keywords @arbitrary_kw_args = expectation.expect_arbitrary_keywords else @kw_args = [] @arbitrary_kw_args = false end end self end def valid? missing_kw_args.empty? && invalid_kw_args.empty? && valid_non_kw_args? && arbitrary_kw_args? && unlimited_args? end def error_message if missing_kw_args.any? "Missing required keyword arguments: %s" % [ missing_kw_args.join(", ") ] elsif invalid_kw_args.any? "Invalid keyword arguments provided: %s" % [ invalid_kw_args.join(", ") ] elsif !valid_non_kw_args? "Wrong number of arguments. Expected %s, got %s." % [ @signature.non_kw_args_arity_description, non_kw_args ] end end private def valid_non_kw_args? @signature.valid_non_kw_args?(min_non_kw_args, max_non_kw_args) end def missing_kw_args @signature.missing_kw_args_from(kw_args) end def invalid_kw_args @signature.invalid_kw_args_from(kw_args) end def arbitrary_kw_args? !@arbitrary_kw_args || @signature.arbitrary_kw_args? end def unlimited_args? !@unlimited_args || @signature.unlimited_args? end def split_args(*args) kw_args = if @signature.has_kw_args_in?(args) && !RubyFeatures.kw_arg_separation? last = args.pop non_kw_args = last.reject { |k, _| k.is_a?(Symbol) } if non_kw_args.empty? last.keys else args << non_kw_args last.select { |k, _| k.is_a?(Symbol) }.keys end elsif @signature.has_kw_args_in?(args) && RubyFeatures.kw_arg_separation? args.pop.keys else [] end [args.length, kw_args] end end # Figures out whether a given method can accept various arguments. # Surprisingly non-trivial. # # @private StrictSignatureVerifier = MethodSignatureVerifier # Allows matchers to be used instead of providing keyword arguments. In # practice, when this happens only the arity of the method is verified. # # @private class LooseSignatureVerifier < MethodSignatureVerifier private def split_args(*args) if RSpec::Support.is_a_matcher?(args.last) && @signature.could_contain_kw_args?(args) args.pop @signature = SignatureWithKeywordArgumentsMatcher.new(@signature) end super(*args) end # If a matcher is used in a signature in place of keyword arguments, all # keyword argument validation needs to be skipped since the matcher is # opaque. # # Instead, keyword arguments will be validated when the method is called # and they are actually known. # # @private class SignatureWithKeywordArgumentsMatcher def initialize(signature) @signature = signature end def missing_kw_args_from(_kw_args) [] end def invalid_kw_args_from(_kw_args) [] end def non_kw_args_arity_description @signature.non_kw_args_arity_description end def valid_non_kw_args?(*args) @signature.valid_non_kw_args?(*args) end def has_kw_args_in?(args) @signature.has_kw_args_in?(args) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-support/SECURITY.md0000664000000000000000000000030114566142077021210 0ustar rootroot## Security contact information To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/0000775000000000000000000000000014567461030017017 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.rubocop_rspec_base.yml0000664000000000000000000001500514557670305023466 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. # This file contains defaults for RSpec projects. Individual projects # can customize by inheriting this file and overriding particular settings. Layout/AccessModifierIndentation: Enabled: false # "Use alias_method instead of alias" # We're fine with `alias`. Style/Alias: Enabled: false # "Avoid the use of the case equality operator ===" # We prefer using `Class#===` over `Object#is_a?` because `Class#===` # is less likely to be monkey patched than `is_a?` on a user object. Style/CaseEquality: Enabled: false # Warns when the class is excessively long. Metrics/ClassLength: Max: 100 Style/CollectionMethods: PreferredMethods: reduce: 'inject' # Over time we'd like to get this down, but this is what we're at now. Metrics/CyclomaticComplexity: Max: 10 # We use YARD to enforce documentation. It works better than rubocop's # enforcement...rubocop complains about the places we re-open # `RSpec::Expectations` and `RSpec::Matchers` w/o having doc commments. Style/Documentation: Enabled: false # We still support 1.8.7 which requires trailing dots Layout/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: Enabled: false # each_with_object is unavailable on 1.8.7 so we have to disable this one. Style/EachWithObject: Enabled: false Style/FormatString: EnforcedStyle: percent # As long as we support ruby 1.8.7 we have to use hash rockets. Style/HashSyntax: EnforcedStyle: hash_rockets # We can't use the new lambda syntax, since we still support 1.8.7. Style/Lambda: Enabled: false # Over time we'd like to get this down, but this is what we're at now. Layout/LineLength: Max: 100 # Over time we'd like to get this down, but this is what we're at now. Metrics/MethodLength: Max: 15 # Who cares what we call the argument for binary operator methods? Naming/BinaryOperatorParameterName: Enabled: false Style/PercentLiteralDelimiters: PreferredDelimiters: '%': () # double-quoted string '%i': '[]' # array of symbols '%q': () # single-quoted string '%Q': () # double-quoted string '%r': '{}' # regular expression pattern '%s': () # a symbol '%w': '[]' # array of single-quoted strings '%W': '[]' # array of double-quoted strings '%x': () # a shell command as a string # We have too many special cases where we allow generator methods or prefer a # prefixed predicate due to it's improved readability. Naming/PredicateName: Enabled: false # On 1.8 `proc` is `lambda`, so we use `Proc.new` to ensure we get real procs on all supported versions. # http://batsov.com/articles/2014/02/04/the-elements-of-style-in-ruby-number-12-proc-vs-proc-dot-new/ Style/Proc: Enabled: false # Exceptions should be rescued with `Support::AllExceptionsExceptOnesWeMustNotRescue` Lint/RescueException: Enabled: true # We haven't adopted the `fail` to signal exceptions vs `raise` for re-raises convention. Style/SignalException: Enabled: false # We've tended to use no space, so it's less of a change to stick with that. Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space # We don't care about single vs double qoutes. Style/StringLiterals: Enabled: false # This rule favors constant names from the English standard library which we don't load. Style/SpecialGlobalVars: Enabled: false Style/TrailingCommaInArrayLiteral: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingCommaInArguments: Enabled: false Style/TrivialAccessors: AllowDSLWriters: true AllowPredicates: true ExactNameMatch: true Style/ParallelAssignment: Enabled: false Layout/EmptyLineBetweenDefs: Enabled: false Layout/FirstParameterIndentation: Enabled: false Layout/ParameterAlignment: EnforcedStyle: with_first_parameter Layout/SpaceInsideBlockBraces: Enabled: false Layout/SpaceInsideParens: Enabled: false Naming/ConstantName: Enabled: false Style/ClassCheck: Enabled: false Style/ConditionalAssignment: Enabled: false Style/EmptyMethod: Enabled: false Style/FormatStringToken: Enabled: false Style/GuardClause: Enabled: false Style/IdenticalConditionalBranches: Enabled: false Style/IfUnlessModifier: Enabled: false Style/IfUnlessModifierOfIfUnless: Enabled: false Lint/MissingSuper: Enabled: false Style/MissingRespondToMissing: Enabled: false Style/MixinUsage: Enabled: false Style/MultipleComparison: Enabled: false Style/MutableConstant: Enabled: false Style/NestedModifier: Enabled: false Style/NestedParenthesizedCalls: Enabled: false Style/NumericPredicate: Enabled: false Style/RedundantParentheses: Enabled: false Style/StringLiteralsInInterpolation: Enabled: false Style/SymbolArray: Enabled: false Style/SymbolProc: Enabled: false Style/YodaCondition: Enabled: false Style/ZeroLengthPredicate: Enabled: false Layout/ClosingParenthesisIndentation: Enabled: false Layout/ExtraSpacing: Enabled: false Layout/MultilineMethodCallBraceLayout: Enabled: false Layout/MultilineMethodCallIndentation: Enabled: false Layout/MultilineOperationIndentation: Enabled: false Layout/SpaceAroundBlockParameters: Enabled: false Layout/SpaceAroundOperators: Enabled: false Layout/SpaceBeforeComma: Enabled: false Style/BlockDelimiters: Enabled: false Style/EmptyCaseCondition: Enabled: false Style/MultilineIfModifier: Enabled: false Style/RescueStandardError: Enabled: false Style/StderrPuts: Enabled: false Style/TernaryParentheses: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Layout/AssignmentIndentation: Enabled: false Layout/EmptyLineAfterMagicComment: Enabled: false Layout/FirstArrayElementIndentation: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/SpaceInsidePercentLiteralDelimiters: Enabled: false Style/EmptyElse: Enabled: false Style/IfInsideElse: Enabled: false Style/RedundantReturn: Enabled: false Style/StructInheritance: Enabled: false Naming/VariableNumber: Enabled: false Layout/SpaceInsideStringInterpolation: Enabled: false Style/DateTime: Enabled: false Style/ParenthesesAroundCondition: Enabled: false Layout/EmptyLinesAroundBlockBody: Enabled: false Lint/ImplicitStringConcatenation: Enabled: false Lint/NestedMethodDefinition: Enabled: false Style/RegexpLiteral: Enabled: false Style/TrailingUnderscoreVariable: Enabled: false Layout/EmptyLinesAroundAccessModifier: Enabled: false ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/ISSUE_TEMPLATE.md0000664000000000000000000000102714557670305021532 0ustar rootroot ### Subject of the issue ### Your environment * Ruby version: * rspec-mocks version: ### Steps to reproduce ### Expected behavior ### Actual behavior ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/DEVELOPMENT.md0000664000000000000000000001151614557670305021135 0ustar rootroot # Development Setup Generally speaking, you only need to clone the project and install the dependencies with [Bundler](https://bundler.io/). You can either get a full RSpec development environment using [rspec-dev](https://github.com/rspec/rspec-dev#README) or you can set this project up individually. ## Setting up rspec-mocks individually For most contributors, setting up the project individually will be simpler. Unless you have a specific reason to use rspec-dev, we recommend using this approach. Clone the repo: ``` $ git clone git@github.com:rspec/rspec-mocks.git ``` Install the dependencies using [Bundler](https://bundler.io/): ``` $ cd rspec-mocks $ bundle install ``` To minimize boot time and to ensure we don't depend upon any extra dependencies loaded by Bundler, our CI builds avoid loading Bundler at runtime by using Bundler's [`--standalone option`](https://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone). While not strictly necessary (many/most of our contributors do not do this!), if you want to exactly reproduce our CI builds you'll want to do the same: ``` $ bundle install --standalone --binstubs ``` The `--binstubs` option creates the `bin/rspec` file that, like `bundle exec rspec`, will load all the versions specified in `Gemfile.lock` without loading bundler at runtime! ## Using rspec-dev See the [rspec-dev README](https://github.com/rspec/rspec-dev#README) for setup instructions. The rspec-dev project contains many rake tasks for helping manage an RSpec development environment, making it easy to do things like: * Change branches across all repos * Update all repos with the latest code from `main` * Cut a new release across all repos * Push out updated build scripts to all repos These sorts of tasks are essential for the RSpec maintainers but will probably be unnecessary complexity if you're just contributing to one repository. If you are getting setup to make your first contribution, we recommend you take the simpler route of setting up rspec-mocks individually. ## Gotcha: Version mismatch from sibling repos The [Gemfile](Gemfile) is designed to be flexible and support using the other RSpec repositories either from a local sibling directory (e.g. `../rspec-`) or, if there is no such directory, directly from git. This generally does the "right thing", but can be a gotcha in some situations. For example, if you are setting up `rspec-core`, and you happen to have an old clone of `rspec-expectations` in a sibling directory, it'll be used even though it might be months or years out of date, which can cause confusing failures. To avoid this problem, you can either `export USE_GIT_REPOS=1` to force the use of `:git` dependencies instead of local dependencies, or update the code in the sibling directory. rspec-dev contains rake tasks to help you keep all repos in sync. ## Extra Gems If you need additional gems for any tasks---such as `benchmark-ips` for benchmarking or `byebug` for debugging---you can create a `Gemfile-custom` file containing those gem declarations. The `Gemfile` evaluates that file if it exists, and it is git-ignored. # Running the build The [Travis CI build](https://travis-ci.org/rspec/rspec-mocks) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` See [build detail](BUILD_DETAIL.md) for more detail. # What to Expect To ensure high, uniform code quality, all code changes (including changes from the maintainers!) are subject to a pull request code review. We'll often ask for clarification or suggest alternate ways to do things. Our code reviews are intended to be a two-way conversation. Here's a short, non-exhaustive checklist of things we typically ask contributors to do before PRs are ready to merge. It can help get your PR merged faster if you do these in advance! - [ ] New behavior is covered by tests and all tests are passing. - [ ] No Ruby warnings are issued by your changes. - [ ] Documentation reflects changes and renders as intended. - [ ] RuboCop passes (e.g. `bundle exec rubocop lib`). - [ ] Commits are squashed into a reasonable number of logical changesets that tell an easy-to-follow story. - [ ] No changelog entry is necessary (we'll add it as part of the merge process!) # Adding Docs RSpec uses [YARD](https://yardoc.org/) for its API documentation. To ensure the docs render well, we recommend running a YARD server and viewing your edits in a browser. To run a YARD server: ``` $ bundle exec yard server --reload # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard server --reload ``` Then navigate to `localhost:8808` to view the rendered docs. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/0000775000000000000000000000000014557670305021142 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/thread_safety.rb0000664000000000000000000000114414557670305024311 0ustar rootroot$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__)) require 'benchmark' require 'rspec/mocks' Benchmark.bm do |bm| bm.report("fetching a proxy") do RSpec::Mocks.with_temporary_scope do o = Object.new 100_000.times { RSpec::Mocks.space.proxy_for(o) } end end end # Without synchronize (not thread-safe): # # user system total real # fetching a proxy 0.120000 0.000000 0.120000 ( 0.141333) # # With synchronize (thread-safe): # user system total real # fetching a proxy 0.180000 0.000000 0.180000 ( 0.189553) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/find_original_method_early.rb0000664000000000000000000000413514557670305027032 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'rspec/mocks' require "rspec/mocks/standalone" =begin This benchmark script is for troubleshooting the performance of #264. To use it, you have to edit the code in #264 a bit: wrap the call in `MethodDouble#initialize` to `find_original_method` in a conditional like `if $find_original`. That allows the code below to compare the perf of stubbing a method with the original method being found vs. not. =end require 'benchmark' n = 10_000 Foo = Class.new(Object) do n.times do |i| define_method "meth_#{i}" do end end end Benchmark.bmbm do |bm| puts "#{n} times - ruby #{RUBY_VERSION}" perform_report = lambda do |label, find_original, &create_object| dbl = create_object.call $find_original = find_original bm.report(label) do n.times do |i| dbl.stub("meth_#{i}") end end RSpec::Mocks.space.reset_all end perform_report.call("Find original - partial mock", true) { Foo.new } perform_report.call("Don't find original - partial mock", false) { Foo.new } perform_report.call("Find original - test double", true) { double } perform_report.call("Don't find original - test double", false) { double } end =begin 10000 times - ruby 1.9.3 Rehearsal ---------------------------------------------------------------------- Don't find original - partial mock 1.050000 0.020000 1.070000 ( 1.068561) Don't find original - test double 1.190000 0.010000 1.200000 ( 1.199815) Find original - partial mock 1.270000 0.010000 1.280000 ( 1.282944) Find original - test double 1.320000 0.020000 1.340000 ( 1.336136) ------------------------------------------------------------- total: 4.890000sec user system total real Don't find original - partial mock 0.990000 0.000000 0.990000 ( 1.000959) Don't find original - test double 0.930000 0.010000 0.940000 ( 0.931871) Find original - partial mock 1.040000 0.000000 1.040000 ( 1.046354) Find original - test double 0.980000 0.010000 0.990000 ( 0.983577) =end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/boot_time.sh0000775000000000000000000000110514557670305023457 0ustar rootroottime (for i in {1..100}; do ruby -Ilib:../rspec-support/lib -rrspec/mocks -e ""; done) # 3 runs before our autoload changes # real 0m4.497s # user 0m3.662s # sys 0m0.677s # # real 0m4.472s # user 0m3.644s # sys 0m0.671s # # real 0m4.465s # user 0m3.640s # sys 0m0.668s # 3 runs after our autoload changes: # # real 0m4.038s # user 0m3.274s # sys 0m0.609s # # real 0m4.038s # user 0m3.274s # sys 0m0.609s # # real 0m4.038s # user 0m3.274s # sys 0m0.609s # It's modest, but that's about a 10% improvement: an average # of about 40ms to load rather than 45 ms to load. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/double_creation.rb0000664000000000000000000000450314557670305024627 0ustar rootroot$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__)) require 'benchmark' require 'rspec/mocks' n = 1000 puts "#{n} times - ruby #{RUBY_VERSION}" puts Benchmark.bm do |bm| RSpec::Mocks.setup(self) (0..9).each do |m| attrs = m.times.inject({}) {|h, x| h["method_#{x}"] = x h } bm.report("#{m} attrs") do n.times do double(attrs) end end end end # $ export OLD_REV=d483e0a893d97c7b8e612e878a9f3562a210df9f # $ git checkout $OLD_REV # $ ruby benchmarks/double_creation.rb # 1000 times - ruby 2.0.0 # # user system total real # 0 attrs 0.010000 0.000000 0.010000 ( 0.003686) # 1 attrs 0.110000 0.000000 0.110000 ( 0.143132) # 2 attrs 0.230000 0.010000 0.240000 ( 0.311358) # 3 attrs 0.400000 0.020000 0.420000 ( 0.465994) # 4 attrs 0.570000 0.010000 0.580000 ( 0.597902) # 5 attrs 0.920000 0.010000 0.930000 ( 1.060219) # 6 attrs 1.350000 0.020000 1.370000 ( 1.388386) # 7 attrs 1.770000 0.030000 1.800000 ( 1.805518) # 8 attrs 2.620000 0.030000 2.650000 ( 2.681484) # 9 attrs 3.320000 0.030000 3.350000 ( 3.380757) # # $ export NEW_REV=13e9d11542a6b60c5dc7ffa4527c98bb255d0a1f # $ git checkout $NEW_REV # $ ruby benchmarks/double_creation.rb # 1000 times - ruby 2.0.0 # # user system total real # 0 attrs 0.010000 0.000000 0.010000 ( 0.001544) # 1 attrs 0.040000 0.000000 0.040000 ( 0.043522) # 2 attrs 0.060000 0.000000 0.060000 ( 0.081742) # 3 attrs 0.090000 0.010000 0.100000 ( 0.104526) # 4 attrs 0.120000 0.010000 0.130000 ( 0.132472) # 5 attrs 0.150000 0.010000 0.160000 ( 0.162368) # 6 attrs 0.190000 0.010000 0.200000 ( 0.204610) # 7 attrs 0.220000 0.010000 0.230000 ( 0.237983) # 8 attrs 0.260000 0.010000 0.270000 ( 0.281562) # 9 attrs 0.310000 0.020000 0.330000 ( 0.334489) # # $ git log $OLD_REV..$NEW_REV --oneline # 13e9d11 Remove unused arguments from simple stub interface. # 009a697 Extract CallerFilter class to unify caller manipulation. # 46c1eb0 Introduce "simple" stub as an optimization over using a normal stub. # 4a04b3e Extract constant ArgumentListMatcher::MATCH_ALL. # 860d591 Speed up double creation with multiple attributes by caching caller. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/transfer_nested_constants.rb0000664000000000000000000000435414557670305026757 0ustar rootroot$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__)) require 'benchmark' require 'rspec/mocks' N = ENV.fetch('N', 10_000).to_i M = ENV.fetch('M', 5).to_i puts "#{N} times, #{M} constants - ruby #{RUBY_VERSION}" puts class A M.times do |x| const_set("C#{x}", Object.new) end end Benchmark.bm(20) do |bm| RSpec::Mocks.setup(self) bm.report("with constants") do N.times do class_double('A').as_stubbed_const(:transfer_nested_constants => true) end end bm.report("without constants") do N.times do class_double('A').as_stubbed_const(:transfer_nested_constants => false) end end end # > for n in 1 10000; do for m in 0 5 100; do echo; \ # env N=$n M=$m ruby benchmarks/transfer_nested_constants.rb; \ # echo; done; done # # 1 times, 0 constants - ruby 2.0.0 # # user system total real # with constants 0.000000 0.000000 0.000000 ( 0.000180) # without constants 0.000000 0.000000 0.000000 ( 0.000071) # # # 1 times, 5 constants - ruby 2.0.0 # # user system total real # with constants 0.000000 0.000000 0.000000 ( 0.000197) # without constants 0.000000 0.000000 0.000000 ( 0.000123) # # # 1 times, 100 constants - ruby 2.0.0 # # user system total real # with constants 0.000000 0.000000 0.000000 ( 0.000433) # without constants 0.000000 0.000000 0.000000 ( 0.000115) # # # 10000 times, 0 constants - ruby 2.0.0 # # user system total real # with constants 0.900000 0.020000 0.920000 ( 0.935583) # without constants 0.660000 0.010000 0.670000 ( 0.680178) # # # 10000 times, 5 constants - ruby 2.0.0 # # user system total real # with constants 1.080000 0.020000 1.100000 ( 1.114722) # without constants 0.720000 0.020000 0.740000 ( 0.741976) # # # 10000 times, 100 constants - ruby 2.0.0 # # user system total real # with constants 3.870000 0.110000 3.980000 ( 4.000176) # without constants 0.930000 0.010000 0.940000 ( 0.947197) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/allocations/0000775000000000000000000000000014557670305023452 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/allocations/helper.rb0000664000000000000000000000073214557670305025260 0ustar rootroot$LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__) require "allocation_stats" require 'rspec/mocks/standalone' def benchmark_allocations(burn: 1) stats = AllocationStats.new(:burn => burn).trace do yield end columns = if ENV['DETAIL'] [:sourcefile, :sourceline, :class_plus] else [:class_plus] end puts stats.allocations(:alias_paths => true).group_by(*columns).from_pwd.sort_by_size.to_text end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/allocations/lambda_vs_block_with_select.rb0000664000000000000000000000530714557670305031500 0ustar rootrootrequire 'memory_profiler' n = 10_000 def find_with_proc(argument) lambda do |lambda_arg| lambda_arg == argument end end def find(argument, lambda_arg) lambda_arg == argument end puts "#{n} items - ruby #{RUBY_VERSION}" puts puts "find_with_proc" MemoryProfiler.report do 100.times do 1.upto(n).select(&find_with_proc(50)) end end.pretty_print puts puts "find" MemoryProfiler.report do 100.times do 1.upto(n).select { |i| find(50, i) } end end.pretty_print # $ ruby benchmarks/allocations/2_lambda_ref_find.rb # 10000 items - ruby 3.2.2 # # find_with_proc # Total allocated: 29600 bytes (400 objects) # Total retained: 0 bytes (0 objects) # # allocated memory by gem # ----------------------------------- # 29600 other # # allocated memory by file # ----------------------------------- # 29600 benchmarks/allocations/2_lambda_ref_find.rb # # allocated memory by location # ----------------------------------- # 21600 benchmarks/allocations/2_lambda_ref_find.rb:22 # 8000 benchmarks/allocations/2_lambda_ref_find.rb:6 # # allocated memory by class # ----------------------------------- # 13600 Enumerator # 8000 Array # 8000 Proc # # allocated objects by gem # ----------------------------------- # 400 other # # allocated objects by file # ----------------------------------- # 400 benchmarks/allocations/2_lambda_ref_find.rb # # allocated objects by location # ----------------------------------- # 300 benchmarks/allocations/2_lambda_ref_find.rb:22 # 100 benchmarks/allocations/2_lambda_ref_find.rb:6 # # allocated objects by class # ----------------------------------- # 200 Array # 100 Enumerator # 100 Proc # # # find # Total allocated: 21600 bytes (300 objects) # Total retained: 0 bytes (0 objects) # # allocated memory by gem # ----------------------------------- # 21600 other # # allocated memory by file # ----------------------------------- # 21600 benchmarks/allocations/2_lambda_ref_find.rb # # allocated memory by location # ----------------------------------- # 21600 benchmarks/allocations/2_lambda_ref_find.rb:31 # # allocated memory by class # ----------------------------------- # 13600 Enumerator # 8000 Array # # allocated objects by gem # ----------------------------------- # 300 other # # allocated objects by file # ----------------------------------- # 300 benchmarks/allocations/2_lambda_ref_find.rb # # allocated objects by location # ----------------------------------- # 300 benchmarks/allocations/2_lambda_ref_find.rb:31 # # allocated objects by class # ----------------------------------- # 200 Array # 100 Enumerator ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/allocations/1_object_1000_mocks.rb0000664000000000000000000000663714557670305027335 0ustar rootrootrequire_relative "helper" symbols = (1..1000).map { |x| :"#{x}" } benchmark_allocations do o = Object.new symbols.each do |sym| expect(o).to receive(sym) end symbols.each do |sym| o.send(sym) end RSpec::Mocks.space.verify_all RSpec::Mocks.space.reset_all end __END__ As of commit 9ee3e3adb529113bf1cc75cc4424d014f880dc47: class_plus count ---------------------------------------------------- ----- Array 22003 Proc 3001 RubyVM::Env 3001 Array 2000 String 2000 Hash 1002 RSpec::Mocks::ExpectationTarget 1000 Enumerator 1000 RSpec::Mocks::Matchers::Receive 1000 Array 1000 RSpec::Mocks::InstanceMethodStasher 1000 RSpec::Mocks::MethodDouble 1000 Array 1000 RSpec::Mocks::MessageExpectation 1000 Array 1000 Array 1000 Array 1000 Array 1000 RSpec::Mocks::Proxy::SpecificMessage 1000 RSpec::Mocks::Implementation 1000 Array 1 RSpec::Mocks::PartialDoubleProxy 1 RSpec::Mocks::ErrorGenerator 1 Array 1 After PR #936: class_plus count ---------------------------------------------------- ----- Array 21003 RubyVM::Env 3001 Proc 3001 String 2000 RSpec::Mocks::InstanceMethodStasher 1000 RSpec::Mocks::Matchers::Receive 1000 RSpec::Mocks::ExpectationTarget 1000 RSpec::Mocks::Implementation 1000 RSpec::Mocks::MessageExpectation 1000 RSpec::Mocks::MethodDouble 1000 Array 1000 Array 1000 Array 1000 Enumerator 1000 Array 1000 Array 1000 RSpec::Mocks::Proxy::SpecificMessage 1000 Array 1000 Array 1000 Hash 2 RSpec::Mocks::PartialDoubleProxy 1 Array 1 RSpec::Mocks::ErrorGenerator 1 Array 1 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/accessing_configuration_via_method_vs_cache.rb0000664000000000000000000000242114557670305032406 0ustar rootrootrequire 'benchmark' n = 10_000 require 'rspec/mocks' # precache config RSpec::Mocks.configuration Benchmark.benchmark do |bm| puts "#{n} times - ruby #{RUBY_VERSION}" puts puts "directly" 3.times do bm.report do n.times do original_state = RSpec::Mocks.configuration.temporarily_suppress_partial_double_verification RSpec::Mocks.configuration.temporarily_suppress_partial_double_verification = true RSpec::Mocks.configuration.temporarily_suppress_partial_double_verification = original_state end end end puts puts "with cached value" 3.times do bm.report do n.times do config = RSpec::Mocks.configuration original_state = config.temporarily_suppress_partial_double_verification config.temporarily_suppress_partial_double_verification = true config.temporarily_suppress_partial_double_verification = original_state end end end end __END__ 10000 times - ruby 2.3.1 directly 0.000000 0.000000 0.000000 ( 0.002654) 0.000000 0.000000 0.000000 ( 0.002647) 0.010000 0.000000 0.010000 ( 0.002645) with cached value 0.000000 0.000000 0.000000 ( 0.001386) 0.000000 0.000000 0.000000 ( 0.001387) 0.000000 0.000000 0.000000 ( 0.001399) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/each_value_v_values_each.rb0000664000000000000000000000227514557670305026455 0ustar rootrootrequire 'benchmark' n = 10_000 m = 1.upto(1000).inject({}) { |m, i| m[i] = i; m } Benchmark.benchmark do |bm| puts "#{n} times - ruby #{RUBY_VERSION}" puts puts "each_value" 3.times do bm.report do n.times do m.each_value {} end end end puts puts "values.each" 3.times do bm.report do n.times do m.values.each {} end end end end # $ ruby benchmarks/values_each_v_each_value.rb # 10000 times - ruby 1.9.3 # # each_value # 0.720000 0.000000 0.720000 ( 0.720237) # 0.720000 0.000000 0.720000 ( 0.724956) # 0.730000 0.000000 0.730000 ( 0.730352) # # values.each # 0.910000 0.000000 0.910000 ( 0.917496) # 0.910000 0.010000 0.920000 ( 0.909319) # 0.910000 0.000000 0.910000 ( 0.911225) # $ ruby benchmarks/values_each_v_each_value.rb # 10000 times - ruby 2.0.0 # # each_value # 0.730000 0.000000 0.730000 ( 0.738443) # 0.720000 0.000000 0.720000 ( 0.720183) # 0.720000 0.000000 0.720000 ( 0.720866) # # values.each # 0.940000 0.000000 0.940000 ( 0.942597) # 0.960000 0.010000 0.970000 ( 0.959248) # 0.960000 0.000000 0.960000 ( 0.959099) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/benchmarks/method_defined_at_any_visibility.rb0000664000000000000000000000523514557670305030234 0ustar rootrootrequire 'benchmark' n = 1_000_000 Foo = Class.new do 1.upto(n) do |i| define_method(:"public_method_#{i}") {} define_method(:"protected_method_#{i}") {} protected :"protected_method_#{i}" define_method(:"private_method_#{i}") {} private :"protected_method_#{i}" end end Benchmark.benchmark do |bm| puts "#{n} times - ruby #{RUBY_VERSION}" puts puts "using method_defined? and private_method_defined?" puts [:public, :protected, :private, :undefined].each do |vis| puts " - #{vis} methods" 3.times do GC.start bm.report do n.times do |i| name = :"#{vis}_method_#{i}" Foo.method_defined?(name) || Foo.private_method_defined?(name) end end end end puts puts "using public_method_defined?, protected_method_defined? and private_method_defined?" puts [:public, :protected, :private, :undefined].each do |vis| puts " - #{vis} methods" 3.times do GC.start bm.report do n.times do |i| name = :"#{vis}_method_#{i}" Foo.public_method_defined?(name) || Foo.protected_method_defined?(name) Foo.private_method_defined?(name) end end end end end =begin 1000000 times - ruby 2.0.0 using method_defined? and private_method_defined? - public methods 1.410000 0.040000 1.450000 ( 1.462588) 1.380000 0.000000 1.380000 ( 1.372015) 1.370000 0.000000 1.370000 ( 1.372362) - protected methods 1.410000 0.000000 1.410000 ( 1.402750) 1.440000 0.000000 1.440000 ( 1.442719) 1.460000 0.010000 1.470000 ( 1.464763) - private methods 1.390000 0.000000 1.390000 ( 1.393956) 1.340000 0.000000 1.340000 ( 1.349340) 1.360000 0.000000 1.360000 ( 1.361910) - undefined methods 3.260000 0.050000 3.310000 ( 3.316372) 1.260000 0.010000 1.270000 ( 1.266557) 1.250000 0.000000 1.250000 ( 1.248734) using public_method_defined?, protected_method_defined? and private_method_defined? - public methods 1.550000 0.000000 1.550000 ( 1.550655) 1.540000 0.010000 1.550000 ( 1.543906) 1.540000 0.000000 1.540000 ( 1.538267) - protected methods 1.590000 0.000000 1.590000 ( 1.598310) 1.600000 0.000000 1.600000 ( 1.595205) 1.600000 0.000000 1.600000 ( 1.604186) - private methods 1.530000 0.000000 1.530000 ( 1.530080) 1.560000 0.000000 1.560000 ( 1.562656) 1.560000 0.000000 1.560000 ( 1.569161) - undefined methods 1.300000 0.000000 1.300000 ( 1.298066) 1.310000 0.000000 1.310000 ( 1.310737) 1.290000 0.000000 1.290000 ( 1.288307) =end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/tmp/0000775000000000000000000000000014557670305017625 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/tmp/.gitkeep0000664000000000000000000000000014557670305021244 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/rspec-mocks.gemspec0000664000000000000000000000431614557670305022624 0ustar rootroot# -*- encoding: utf-8 -*- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require "rspec/mocks/version" Gem::Specification.new do |s| s.name = "rspec-mocks" s.version = RSpec::Mocks::Version::STRING s.platform = Gem::Platform::RUBY s.license = "MIT" s.authors = ["Steven Baker", "David Chelimsky", "Myron Marston"] s.email = "rspec@googlegroups.com" s.homepage = "https://github.com/rspec/rspec-mocks" s.summary = "rspec-mocks-#{RSpec::Mocks::Version::STRING}" s.description = "RSpec's 'test double' framework, with support for stubbing and mocking" s.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-mocks/issues', 'changelog_uri' => "https://github.com/rspec/rspec-mocks/blob/v#{s.version}/Changelog.md", 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-mocks', } s.files = `git ls-files -- lib/*`.split("\n") s.files += %w[README.md LICENSE.md Changelog.md .yardopts .document] s.test_files = [] s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" s.required_ruby_version = '>= 1.8.7' private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) s.signing_key = private_key s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')] end if RSpec::Mocks::Version::STRING =~ /[a-zA-Z]+/ # pin to exact version for rc's and betas s.add_runtime_dependency "rspec-support", "= #{RSpec::Mocks::Version::STRING}" else # pin to major/minor ignoring patch s.add_runtime_dependency "rspec-support", "~> #{RSpec::Mocks::Version::STRING.split('.')[0..1].concat(['0']).join('.')}" end s.add_runtime_dependency "diff-lcs", ">= 1.2.0", "< 2.0" s.add_development_dependency 'rake', '> 10.0.0' s.add_development_dependency 'cucumber', '>= 1.3' if RUBY_VERSION.to_f >= 2.4 s.add_development_dependency 'aruba', '>= 1.1.0', '< 3.0.0' else s.add_development_dependency 'aruba', '~> 0.14.10' end s.add_development_dependency 'minitest', '~> 5.2' end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/0000775000000000000000000000000014557670305020331 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/cucumber.sh0000775000000000000000000000034214557670305022474 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh run_cukes ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/run_build0000775000000000000000000000151714557670305022246 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "binstub check" check_binstubs fold "specs" run_specs_and_record_done if additional_specs_available; then fold "additional specs" run_additional_specs fi fold "cukes" run_cukes if documentation_enforced; then fold "doc check" check_documentation_coverage fi if supports_cross_build_checks; then fold "one-by-one specs" run_specs_one_by_one export NO_COVERAGE=true run_all_spec_suites else echo "Skipping the rest of the build on non-MRI rubies" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/update_rubygems_and_install_bundler0000775000000000000000000000122514557670305027541 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh if is_ruby_31_plus; then echo "Installing rubygems 3.3.6 / bundler 2.3.6" yes | gem update --system '3.3.6' yes | gem install bundler -v '2.3.6' elif is_ruby_23_plus; then echo "Installing rubygems 3.2.22 / bundler 2.2.22" yes | gem update --system '3.2.22' yes | gem install bundler -v '2.2.22' else echo "Warning installing older versions of Rubygems / Bundler" gem update --system '2.7.8' gem install bundler -v '1.17.3' fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/functions.sh0000664000000000000000000001404014557670305022674 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source $SCRIPT_DIR/ci_functions.sh source $SCRIPT_DIR/predicate_functions.sh # If JRUBY_OPTS isn't set, use these. # see https://docs.travis-ci.com/user/ci-environment/ export JRUBY_OPTS=${JRUBY_OPTS:-"--server -Xcompile.invokedynamic=false"} SPECS_HAVE_RUN_FILE=specs.out MAINTENANCE_BRANCH=`cat maintenance-branch` # Don't allow rubygems to pollute what's loaded. Also, things boot faster # without the extra load time of rubygems. Only works on MRI Ruby 1.9+ if is_mri_192_plus; then export RUBYOPT="--disable=gem" fi function clone_repo { if [ ! -d $1 ]; then # don't clone if the dir is already there if [ -z "$2" ]; then BRANCH_TO_CLONE="${MAINTENANCE_BRANCH?}"; else BRANCH_TO_CLONE="$2"; fi; ci_retry eval "git clone https://github.com/rspec/$1 --depth 1 --branch ${BRANCH_TO_CLONE?}" fi; } function run_specs_and_record_done { local rspec_bin=bin/rspec # rspec-core needs to run with a special script that loads simplecov first, # so that it can instrument rspec-core's code before rspec-core has been loaded. if [ -f script/rspec_with_simplecov ] && is_mri; then rspec_bin=script/rspec_with_simplecov fi; echo "${PWD}/bin/rspec" $rspec_bin spec --backtrace --format progress --profile --format progress --out $SPECS_HAVE_RUN_FILE } function run_cukes { if [ -d features ]; then # 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 # # Note that we delay setting this until we run the cukes because we've seen # spec failures in our spec suite due to problems with this mode. export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "${PWD}/bin/cucumber" if is_mri_192; then # For some reason we get SystemStackError on 1.9.2 when using # the bin/cucumber approach below. That approach is faster # (as it avoids the bundler tax), so we use it on rubies where we can. bundle exec cucumber --strict elif is_jruby; then # For some reason JRuby doesn't like our improved bundler setup RUBYOPT="-I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict else # Prepare RUBYOPT for scenarios that are shelling out to ruby, # and PATH for those that are using `rspec` or `rake`. RUBYOPT="${RUBYOPT} -I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict fi fi } function run_specs_one_by_one { echo "Running each spec file, one-by-one..." for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done } function run_spec_suite_for { if [ ! -f ../$1/$SPECS_HAVE_RUN_FILE ]; then # don't rerun specs that have already run if [ -d ../$1 ]; then echo "Running specs for $1" pushd ../$1 unset BUNDLE_GEMFILE bundle_install_flags=`cat .github/workflows/ci.yml | grep "bundle install" | sed 's/.* bundle install//'` ci_retry eval "(unset RUBYOPT; exec bundle install $bundle_install_flags)" ci_retry eval "(unset RUBYOPT; exec bundle binstubs --all)" run_specs_and_record_done popd else echo "" echo "WARNING: The ../$1 directory does not exist. Usually the" echo "build cds into that directory and run the specs to ensure" echo "the specs still pass with your latest changes, but we are" echo "going to skip that step." echo "" fi; fi; } function check_binstubs { echo "Checking required binstubs" local success=0 local binstubs="" local gems="" if [ ! -x ./bin/rspec ]; then binstubs="$binstubs bin/rspec" gems="$gems rspec-core" success=1 fi if [ ! -x ./bin/rake ]; then binstubs="$binstubs bin/rake" gems="$gems rake" success=1 fi if [ -d features ]; then if [ ! -x ./bin/cucumber ]; then binstubs="$binstubs bin/cucumber" gems="$gems cucumber" success=1 fi fi if [ $success -eq 1 ]; then echo echo "Missing binstubs:$binstubs" echo "Install missing binstubs using one of the following:" echo echo " # Create the missing binstubs" echo " $ bundle binstubs$gems" echo echo " # To binstub all gems" echo " $ bundle binstubs --all" fi return $success } function check_documentation_coverage { echo "bin/yard stats --list-undoc" bin/yard stats --list-undoc | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') coverage ||= line[/([\d\.]+)% documented/, 1] puts line end unless Float(coverage) == 100 puts \"\n\nMissing documentation coverage (currently at #{coverage}%)\" exit(1) end if has_warnings puts \"\n\nYARD emitted documentation warnings.\" exit(1) end " # Some warnings only show up when generating docs, so do that as well. bin/yard doc --no-cache | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') has_errors ||= line.start_with?('[error]:') puts line end if has_warnings || has_errors puts \"\n\nYARD emitted documentation warnings or errors.\" exit(1) end " } function check_style_and_lint { echo "bin/rubocop lib" eval "(unset RUBYOPT; exec bin/rubocop lib)" } function run_all_spec_suites { fold "rspec-core specs" run_spec_suite_for "rspec-core" fold "rspec-expectations specs" run_spec_suite_for "rspec-expectations" fold "rspec-mocks specs" run_spec_suite_for "rspec-mocks" if rspec_rails_compatible; then if ! is_ruby_27_plus; then export RAILS_VERSION='~> 6.1.0' fi fold "rspec-rails specs" run_spec_suite_for "rspec-rails" fi if rspec_support_compatible; then fold "rspec-support specs" run_spec_suite_for "rspec-support" fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/legacy_setup.sh0000775000000000000000000000077214557670305023362 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh bundle install --standalone --binstubs --without coverage documentation if [ -x ./bin/rspec ]; then echo "RSpec bin detected" else if [ -x ./exe/rspec ]; then cp ./exe/rspec ./bin/rspec echo "RSpec restored from exe" else echo "No RSpec bin available" exit 1 fi fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/ci_functions.sh0000664000000000000000000000376314557670305023361 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. # Taken from: # https://github.com/travis-ci/travis-build/blob/e9314616e182a23e6a280199cd9070bfc7cae548/lib/travis/build/script/templates/header.sh#L34-L53 ci_retry() { local result=0 local count=1 while [ $count -le 3 ]; do [ $result -ne 0 ] && { echo -e "\n\033[33;1mThe command \"$@\" failed. Retrying, $count of 3.\033[0m\n" >&2 } "$@" result=$? [ $result -eq 0 ] && break count=$(($count + 1)) sleep 1 done [ $count -eq 3 ] && { echo "\n\033[33;1mThe command \"$@\" failed 3 times.\033[0m\n" >&2 } return $result } # Taken from https://github.com/vcr/vcr/commit/fa96819c92b783ec0c794f788183e170e4f684b2 # and https://github.com/vcr/vcr/commit/040aaac5370c68cd13c847c076749cd547a6f9b1 nano_cmd="$(type -p gdate date | head -1)" nano_format="+%s%N" [ "$(uname -s)" != "Darwin" ] || nano_format="${nano_format/%N/000000000}" travis_time_start() { travis_timer_id=$(printf %08x $(( RANDOM * RANDOM ))) travis_start_time=$($nano_cmd -u "$nano_format") printf "travis_time:start:%s\r\e[0m" $travis_timer_id } travis_time_finish() { local travis_end_time=$($nano_cmd -u "$nano_format") local duration=$(($travis_end_time-$travis_start_time)) printf "travis_time:end:%s:start=%s,finish=%s,duration=%s\r\e[0m" \ $travis_timer_id $travis_start_time $travis_end_time $duration } fold() { local name="$1" local status=0 shift 1 if [ -n "$TRAVIS" ]; then printf "travis_fold:start:%s\r\e[0m" "$name" travis_time_start else echo "============= Starting $name ===============" fi "$@" status=$? [ -z "$TRAVIS" ] || travis_time_finish if [ "$status" -eq 0 ]; then if [ -n "$TRAVIS" ]; then printf "travis_fold:end:%s\r\e[0m" "$name" else echo "============= Ending $name ===============" fi else STATUS="$status" fi return $status } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/predicate_functions.sh0000664000000000000000000000555114557670305024723 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. function is_mri { if ruby -e "exit(!defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_ruby_head { # This checks for the presence of our CI's ruby-head env variable if [ -z ${RUBY_HEAD+x} ]; then return 1 else return 0 fi; } function supports_cross_build_checks { if is_mri; then # We don't run cross build checks on ruby-head if is_ruby_head; then return 1 else return 0 fi else return 1 fi } function is_jruby { if ruby -e "exit(defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_mri_192 { if is_mri; then if ruby -e "exit(RUBY_VERSION == '1.9.2')"; then return 0 else return 1 fi else return 1 fi } function is_mri_192_plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 1.8)"; then return 0 else return 1 fi else return 1 fi } function is_mri_2plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 2.0)"; then return 0 else return 1 fi else return 1 fi } function is_ruby_23_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.3)"; then return 0 else return 1 fi } function is_ruby_25_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.5)"; then return 0 else return 1 fi } function is_ruby_27_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.7)"; then return 0 else return 1 fi } function is_ruby_31_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 3.1)"; then return 0 else return 1 fi } function rspec_rails_compatible { if is_ruby_25_plus; then # TODO remove when RSpec-Rails build is 3.1 safe by default if is_ruby_31_plus; then return 1 else return 0 fi else return 1 fi } function rspec_support_compatible { if [ "$MAINTENANCE_BRANCH" != "2-99-maintenance" ] && [ "$MAINTENANCE_BRANCH" != "2-14-maintenance" ]; then return 0 else return 1 fi } function additional_specs_available { type run_additional_specs > /dev/null 2>&1 return $? } function documentation_enforced { if [ -x ./bin/yard ]; then if is_mri_2plus; then return 0 else return 1 fi else return 1 fi } function style_and_lint_enforced { if is_ruby_head; then return 1 else if [ -x ./bin/rubocop ]; then return 0 else return 1 fi fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/ignores0000664000000000000000000001033014557670305021717 0ustar rootroot# grep -v -f doesn't work properly when empty, so this line is here. # The `alias_method` calls below are only executed at file load time # (when the method cache will be busted by defining methods anyway). lib/rspec/mocks/argument_matchers.rb: alias_method :hash_not_including, :hash_excluding lib/rspec/mocks/argument_matchers.rb: alias_method :an_instance_of, :instance_of lib/rspec/mocks/argument_matchers.rb: alias_method :a_kind_of, :kind_of lib/rspec/mocks/method_double.rb: alias_method :save_original_method!, :original_method lib/rspec/mocks/test_double.rb: alias_method :to_str, :to_s lib/rspec/mocks/error_generator.rb: MockExpectationError = Class.new(Exception) lib/rspec/mocks/error_generator.rb: ExpiredTestDoubleError = Class.new(MockExpectationError) lib/rspec/mocks/error_generator.rb: OutsideOfExampleError = Class.new(StandardError) lib/rspec/mocks/error_generator.rb: UnsupportedMatcherError = Class.new(StandardError) lib/rspec/mocks/error_generator.rb: NegationUnsupportedError = Class.new(StandardError) lib/rspec/mocks/message_expectation.rb: CannotModifyFurtherError = Class.new(StandardError) lib/rspec/mocks/mutate_const.rb: extend RecursiveConstMethods lib/rspec/mocks/mutate_const.rb: extend RecursiveConstMethods # These calls are explicitly opt-in, probably at configuration time. lib/rspec/mocks/marshal_extension.rb: alias_method :dump_without_rspec_mocks, :dump lib/rspec/mocks/marshal_extension.rb: alias_method :dump, :dump_with_rspec_mocks lib/rspec/mocks/marshal_extension.rb: alias_method :dump, :dump_without_rspec_mocks # False positives due to naming lib/rspec/mocks/any_instance/recorder.rb: def build_alias_method_name(method_name) lib/rspec/mocks/any_instance/recorder.rb: if public_protected_or_private_method_defined?(build_alias_method_name(method_name)) lib/rspec/mocks/any_instance/recorder.rb: alias_method_name = build_alias_method_name(method_name) lib/rspec/mocks/any_instance/recorder.rb: alias_method_name = build_alias_method_name(method_name) lib/rspec/mocks/proxy.rb: build_alias_method_name(message) # Instance method stashing needs to blow away method cache, no way around it. lib/rspec/mocks/any_instance/recorder.rb: alias_method method_name, alias_method_name lib/rspec/mocks/any_instance/recorder.rb: alias_method alias_method_name, method_name lib/rspec/mocks/any_instance/recorder.rb: remove_method method_name lib/rspec/mocks/any_instance/recorder.rb: remove_method alias_method_name lib/rspec/mocks/any_instance/recorder.rb: remove_method method_name lib/rspec/mocks/instance_method_stasher.rb: @klass.__send__(:alias_method, stashed_method_name, @method) lib/rspec/mocks/instance_method_stasher.rb: @klass.__send__(:alias_method, @method, stashed_method_name) lib/rspec/mocks/instance_method_stasher.rb: @klass.__send__(:remove_method, stashed_method_name) # Constant stubbing needs to blow away method cache, no way around it. lib/rspec/mocks/method_double.rb: object_singleton_class.__send__(:remove_method, @method_name) lib/rspec/mocks/mutate_const.rb: @context.const_set(@const_name, @original_value) lib/rspec/mocks/mutate_const.rb: @context.const_set(@const_name, @mutated_value) lib/rspec/mocks/mutate_const.rb: @context.const_set(@const_name, @original_value) lib/rspec/mocks/mutate_const.rb: @mutated_value.const_set(const, get_const_defined_on(original_value, const)) lib/rspec/mocks/mutate_const.rb: klass.const_set(name, Module.new) lib/rspec/mocks/mutate_const.rb: context.const_set(@const_name, @mutated_value) lib/rspec/mocks/mutate_const.rb: @context.__send__(:remove_const, @const_name) lib/rspec/mocks/mutate_const.rb: @context.__send__(:remove_const, @const_name) lib/rspec/mocks/mutate_const.rb: @context.__send__(:remove_const, @const_name) lib/rspec/mocks/mutate_const.rb: @deepest_defined_const.__send__(:remove_const, @const_to_remove) # We provide our own wrapper around extend for others to use if they choose. lib/rspec/mocks/test_double.rb: object.extend self ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/run_rubocop0000775000000000000000000000063614557670305022621 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "rubocop" check_style_and_lint ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/list_method_cache_busters.sh0000775000000000000000000000237514557670305026104 0ustar rootroot#!/bin/bash # set -x # This list is from https://charlie.bz/blog/things-that-clear-rubys-method-cache IGNORE_FILE=/tmp/cache_busters_ignore COMMENT_LINE_RE="^(\w|\/)+\.rb: +#" cat script/ignores | grep -v "^$" | ruby -ne 'puts $_.split(/\s+###/)[0]' > $IGNORE_FILE egrep 'def [a-z]*\..*' -R lib | grep -v "def self" | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" egrep 'undef\\b' -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep alias_method -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep remove_method -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep const_set -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep remove_const -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" egrep '\bextend\b' -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep 'Class.new' -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep private_constant -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep public_constant -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep "Marshal.load" -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep "OpenStruct.new" -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/script/clone_all_rspec_repos0000775000000000000000000000111014557670305024604 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh if is_mri; then pushd .. clone_repo "rspec" clone_repo "rspec-core" clone_repo "rspec-expectations" clone_repo "rspec-mocks" clone_repo "rspec-rails" "6-1-maintenance" if rspec_support_compatible; then clone_repo "rspec-support" fi popd else echo "Not cloning all repos since we are not on MRI and they are only needed for the MRI build" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/LICENSE.md0000664000000000000000000000230114557670305020425 0ustar rootrootThe MIT License (MIT) ===================== * Copyright © 2012 David Chelimsky, Myron Marston * Copyright © 2006 David Chelimsky, The RSpec Development Team * Copyright © 2005 Steven Baker 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. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.rubocop.yml0000664000000000000000000000074414557670305021304 0ustar rootrootinherit_from: - .rubocop_todo.yml - .rubocop_rspec_base.yml # All these metrics should go down over time. Metrics/ClassLength: Max: 279 Metrics/CyclomaticComplexity: Max: 18 Layout/LineLength: Max: 193 Exclude: - features/**/* - spec/**/* Metrics/MethodLength: Max: 49 Metrics/AbcSize: Max: 47 Metrics/BlockLength: Max: 45 Exclude: - spec/**/* Metrics/ModuleLength: Max: 220 Exclude: - spec/**/* Metrics/PerceivedComplexity: Max: 19 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/Changelog.md0000664000000000000000000014413214557670305021243 0ustar rootroot### Development [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.0...main) ### 3.13.0 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.7...v3.13.0) Enhancements: * Add an `array_excluding` matcher for arguments. (Zane Wolfgang Pickett, #1528) ### 3.12.7 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.6...v3.12.7) Bug Fixes: * Reduce allocations from "any_instance" style mocks. (Carlos Palhares, #1479) ### 3.12.6 / 2023-07-11 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.5...v3.12.6) Bug Fixes: * Fix an issue with `and_call_original` when using the `method_missing` fallback with keyword arguments. (Igor Drozdov, #1552) ### 3.12.5 / 2023-03-30 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.4...v3.12.5) Bug Fixes: * Fix compatibility issue with Rails where active_support monkey patches `with` when using any instance. (Lachlan Sylvester, #1540) ### 3.12.4 / 2023-03-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.3...v3.12.4) Bug Fixes: * Fix an issue with asserting that Array#reverse is never called. (Brad Trick, #1533) * Fix compatibility issue with Rails where active_support monkey patches `with`. (Jean Boussier, #1531, #1534) ### 3.12.3 / 2023-01-17 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.2...v3.12.3) Bug Fixes: * Fix keyword delegation in `send` for verifying doubles on Ruby 3. (Charlie Honig, #1485) ### 3.12.2 / 2023-01-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.1...v3.12.2) Bug Fixes: * Fix implementation blocks for mocks using keyword arguments on Ruby 3.2.0. (Adam Steel, #1508) * Fix keyword argument assertions when mocking using `with` on Ruby 3.2.0. (Slava Kardakov, Benoit Tigeot, Phil Pirozhkov, Benoit Daloze, #1514) ### 3.12.1 / 2022-12-10 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.0...v3.12.1) Bug Fixes: * Remove empty diff marker when a diff only contains console codes. (Jon Rowe, #1506) * Show keyword vs hash diff marker when arguments are not `==` (Jon Rowe, #1506) * Change check to detect frozen objects to rescue errors rather than pre-empting by checking `frozen?` due to some objects mis-behaving. (Keegan Roth, #1401) * Prevent unfulfilled expectations using `expect_any_instance_of` across a class inheritance boundary from raising rather than failing. (Jon Rowe, #1496) * Prevent a misleading error message when using `allow(...).not_to` with unsupported matchers. (Phil Pirozhkov, #1503) ### 3.12.0 / 2022-10-26 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.2...v3.12.0) Enhancements: * Improve diff output when diffing keyword arguments against hashes. (Jean Boussier, #1461) ### 3.11.2 / 2022-10-25 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.1...v3.11.2) Bug Fixes: * Use the original implementation of `Class.new` to detect overridden definitions of `new` rather than the owner, fixing detection of "double aliased" methods in Ruby 3 and above. (Benoit Daloze, #1470, #1476) * Support keyword argument semantics when constraining argument expectations using `with` on Ruby 3.0+ with `instance_double` (Andrii Malyshko, #1473) ### 3.11.1 / 2022-03-31 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.0...v3.11.1) Bug Fixes: * Add extra `ruby2_keywords` calls to properly designate methods using `*args` to pass keyword around, fixes an issue with TruffleRuby. (Benoit Daloze, #1464) ### 3.11.0 / 2022-02-09 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.3...v3.11.0) Enhancements: * Add `and_invoke` implementation for configuring responses to `receive` (and `receive_messages`) with multiple callable objects. (Kyle Smith, #1411) ### 3.10.3 / 2022-01-28 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.2...v3.10.3) Bug Fixes: * Suppress warning by setting `$VERBOSE` to nil. (Nobuyoshi Nakada, #1414) * Support keyword argument semantics when constraining argument expectations using `with` on Ruby 3.0+ (Yusuke Endoh, #1394) ### 3.10.2 / 2021-01-27 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.1...v3.10.2) Bug Fixes: * Support keyword arguments with `and_call_original` on Ruby 3.0. (Bryan Powell, #1385) * `RSpec::Mocks::Constant#previously_defined?` is now always a boolean. (Phil Pirozhkov, #1397) * Support keyword arguments on Ruby 3.0 when used with `expect_any_instance_of` or `allow_any_instance_of` with `and_call_original`. (Jess Hottenstein, #1407) ### 3.10.1 / 2020-12-27 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.0...v3.10.1) Bug Fixes: * Issue `ArgumentError` rather than `TypeError` when unsupported methods on unsupported objects are attempted to be stubbed. (@zhisme, #1357) ### 3.10.0 / 2020-10-30 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.9.1...v3.10.0) Enhancements: * Add the ability to set a custom error generator in `MessageExpectation`. This will allow rspec-expectations to inject a custom failure message. (Benoit Tigeot and Nicolas Zermati, #1312) * Return the result of the block passed to `RSpec::Mocks.with_temporary_scope` when block run. (@expeehaa, #1329) ### 3.9.1 / 2019-12-31 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.9.0...v3.9.1) Bug Fixes: * Trigger `RSpec::Mocks.configuration.verifying_double_callbacks` when using `allow_any_instance_of` or `expect_any_instance_of` (Daniel Orner, #1309) ### 3.9.0 / 2019-10-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.2...v3.9.0) Enhancements: * Improve thread safety of message expectations by using Mutex to prevent deadlocking errors. (Ry Biesemeyer, #1236) * Add the ability to use `time` as an alias for `times`. For example: `expect(Class).to receive(:method).exactly(1).time`. (Pistos, Benoit Tigeot, #1271) ### 3.8.2 / 2019-10-02 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.1...v3.8.2) * Allow `array_including` argument matchers to be nested. (Emmanuel Delmas, #1291) ### 3.8.1 / 2019-06-13 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.0...v3.8.1) Bug Fixes: * Ensure stubbing methods does not change their visibility. (Kevin Boschert, #1277) ### 3.8.0 / 2018-08-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.7.0...v3.8.0) Bug Fixes: * Issue error when encountering invalid "counted" negative message expectations. (Sergiy Yarinovskiy, #1212) * Ensure `allow_any_instance_of` and `expect_any_instance_of` can be temporarily supressed. (Jon Rowe, #1228) * Ensure `expect_any_instance_of(double).to_not have_received(:some_method)` fails gracefully (as its not supported) rather than issuing a `NoMethodError`. (Maxim Krizhanovsky, #1231) ### 3.7.0 / 2017-10-17 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0...v3.7.0) Enhancements: * Improve compatibility with `--enable-frozen-string-literal` option on Ruby 2.3+. (Pat Allan, #1165) Bug Fixes: * Fix `hash_including` and `hash_excluding` so that they work against subclasses of `Hash`. (Aaron Rosenberg, #1167) ### 3.6.0 / 2017-05-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0.beta2...v3.6.0) Bug Fixes: * Fix "instance variable @color not initialized" warning when using rspec-mocks without rspec-core. (Myron Marston, #1142) * Restore aliased module methods properly when stubbing on 1.8.7. (Samuel Giddins, #1144) * Allow a message chain expectation to be constrained by argument(s). (Jon Rowe, #1156) ### 3.6.0.beta2 / 2016-12-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0.beta1...v3.6.0.beta2) Enhancements: * Add new `without_partial_double_verification { }` API that lets you temporarily turn off partial double verification for an example. (Jon Rowe, #1104) ### 3.6.0.beta1 / 2016-10-09 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0...v3.6.0.beta1) Bug Fixes: * Return the test double instance form `#freeze` (Alessandro Berardi, #1109) * Allow the special logic for stubbing `new` to work when `.method` has been redefined. (Proby, #1119) ### 3.5.0 / 2016-07-01 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0.beta4...v3.5.0) Enhancements: * Provides a nice string representation of `RSpec::Mocks::MessageExpectation` (Myron Marston, #1095) ### 3.5.0.beta4 / 2016-06-05 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0.beta3...v3.5.0.beta4) Enhancements: * Add `and_throw` to any instance handling. (Tobias Bühlmann, #1068) ### 3.5.0.beta3 / 2016-04-02 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0.beta2...v3.5.0.beta3) Enhancements: * Issue warning when attempting to use unsupported `allow(...).to receive(...).ordered`. (Jon Rowe, #1000) * Add `rspec/mocks/minitest_integration`, to properly integrate rspec-mocks with minitest. (Myron Marston, #1065) ### 3.5.0.beta2 / 2016-03-10 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0.beta1...v3.5.0.beta2) Enhancements: * Improve error message displayed when using `and_wrap_original` on pure test doubles. (betesh, #1063) Bug Fixes: * Fix issue that prevented `receive_message_chain(...).with(...)` working correctly on "any instance" mocks. (Jon Rowe, #1061) ### 3.5.0.beta1 / 2016-02-06 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.4.1...v3.5.0.beta1) Bug Fixes: * Allow `any_instance_of(...).to receive(...)` to use `and_yield` multiple times. (Kilian Cirera Sant, #1054) * Allow matchers which inherit from `rspec-mocks` matchers to be used for `allow`. (Andrew Kozin, #1056) * Prevent stubbing `respond_to?` on partial doubles from causing infinite recursion. (Jon Rowe, #1013) * Prevent aliased methods from disapearing after being mocked with `any_instance` (regression from #1043). (Joe Rafaniello, #1060) ### 3.4.1 / 2016-01-10 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.4.0...v3.4.1) Bug Fixes: * Fix `any_instance` to work properly on Ruby 2.3. (Joe Rafaniello, #1043) ### 3.4.0 / 2015-11-11 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.3.2...v3.4.0) Enhancements: * Make `expect(...).to have_received` work without relying upon rspec-expectations. (Myron Marston, #978) * Add option for failing tests when expectations are set on `nil`. (Liz Rush, #983) Bug Fixes: * Fix `have_received { ... }` so that any block passed when the message was received is forwarded to the `have_received` block. (Myron Marston, #1006) * Fix infinite loop in error generator when stubbing `respond_to?`. (Alex Dowad, #1022) * Fix issue with using `receive` on subclasses (at a class level) with 1.8.7. (Alex Dowad, #1026) ### 3.3.2 / 2015-07-15 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.3.1...v3.3.2) Bug Fixes: * Prevent thread deadlock errors during proxy creation (e.g. when using `before_verifying_doubles` callbacks). (Jon Rowe, #980, #979) ### 3.3.1 / 2015-06-19 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.3.0...v3.3.1) Bug Fixes: * Fix bug in `before_verifying_double` callback logic that caused it to be called once for each class in the ancestor list when mocking or stubbing a class. Now it is only called for the mocked or stubbed class, as you would expect. (Sam Phippen, #974) ### 3.3.0 / 2015-06-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.1...v3.3.0) Enhancements: * When stubbing `new` on `MyClass` or `class_double(MyClass)`, use the method signature from `MyClass#initialize` to verify arguments. (Myron Marston, #886) * Use matcher descriptions when generating description of received arguments for mock expectation failures. (Tim Wade, #891) * Avoid loading `stringio` unnecessarily. (Myron Marston, #894) * Verifying doubles failure messages now distinguish between class and instance level methods. (Tim Wade, #896, #908) * Improve mock expectation failure messages so that it combines both number of times and the received arguments in the output. (John Ceh, #918) * Improve how test doubles are represented in failure messages. (Siva Gollapalli, Myron Marston, #932) * Rename `RSpec::Mocks::Configuration#when_declaring_verifying_double` to `RSpec::Mocks::Configuration#before_verifying_doubles` and utilise when verifying partial doubles. (Jon Rowe, #940) * Use rspec-support's `ObjectFormatter` for improved formatting of arguments in failure messages so that, for example, full time precisions is displayed for time objects. (Gavin Miller, Myron Marston, #955) Bug Fixes: * Ensure expectations that raise eagerly also raise during RSpec verification. This means that if exceptions are caught inside test execution the test will still fail. (Sam Phippen, #884) * Fix `have_received(msg).with(args).exactly(n).times` and `receive(msg).with(args).exactly(n).times` failure messages for when the message was received the wrong number of times with the specified args, and also received additional times with other arguments. Previously it confusingly listed the arguments as being mis-matched (even when the double was allowed to receive with any args) rather than listing the count. (John Ceh, #918) * Fix `any_args`/`anything` support so that we avoid calling `obj == anything` on user objects that may have improperly implemented `==` in a way that raises errors. (Myron Marston, #924) * Fix edge case involving stubbing the same method on a class and a subclass which previously hit a `NoMethodError` internally in RSpec. (Myron Marston #954) * Fix edge case where the message received count would be incremented multiple times for one failure. (Myron Marston, #957) * Fix failure messages for when spies received the expected message with different arguments and also received another message. (Maurício Linhares, #960) * Silence whitespace-only diffs. (Myron Marston, #969) ### 3.2.1 / 2015-02-23 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.2.0...v3.2.1) Bug Fixes: * Add missing `rspec/support/differ` require so that rspec-mocks can be used w/o rspec-expectations (which also loads the differ and hided the fact we forgot to require it). (Myron Marston, #893) * Revert tracking of received arg mutation (added in 3.2.0 to provide an error in a situation we can't support) as our implementation has side effects on non-standard objects and there's no solution we could come up with that always works. (Myron Marston, #900) ### 3.2.0 / 2015-02-03 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.3...v3.2.0) Enhancements: * Treat `any_args` as an arg splat, allowing it to match an arbitrary number of args at any point in an arg list. (Myron Marston, #786) * Print diffs when arguments in mock expectations are mismatched. (Sam Phippen, #751) * Support names for verified doubles (`instance_double`, `instance_spy`, `class_double`, `class_spy`, `object_double`, `object_spy`). (Cezary Baginski, #826) * Make `array_including` and `hash_including` argument matchers composable. (Sam Phippen, #819) * Make `allow_any_instance_of(...).to receive(...).and_wrap_original` work. (Ryan Fitzgerald, #869) Bug Fixes: * Provide a clear error when users wrongly combine `no_args` with additional arguments (e.g. `expect().to receive().with(no_args, 1)`). (Myron Marston, #786) * Provide a clear error when users wrongly use `any_args` multiple times in the same argument list (e.g. `expect().to receive().with(any_args, 1, any_args)`. (Myron Marston, #786) * Prevent the error generator from using user object #description methods. See [#685](https://github.com/rspec/rspec-mocks/issues/685). (Sam Phippen, #751) * Make verified doubles declared as `(instance|class)_double(SomeConst)` work properly when `SomeConst` has previously been stubbed. `(instance|class)_double("SomeClass")` already worked properly. (Myron Marston, #824) * Add a matcher description for `receive`, `receive_messages` and `receive_message_chain`. (Myron Marston, #828) * Validate invocation args for null object verified doubles. (Myron Marston, #829) * Fix `RSpec::Mocks::Constant.original` when called with an invalid constant to return an object indicating the constant name is invalid, rather than blowing up. (Myron Marston, #833) * Make `extend RSpec::Mocks::ExampleMethods` on any object work properly to add the rspec-mocks API to that object. Previously, `expect` would be undefined. (Myron Marston, #846) * Fix `require 'rspec/mocks/standalone'` so that it only affects `main` and not every object. It's really only intended to be used in a REPL like IRB, but some gems have loaded it, thinking it needs to be loaded when using rspec-mocks outside the context of rspec-core. (Myron Marston, #846) * Prevent message expectations from being modified by customization methods (e.g. `with`) after they have been invoked. (Sam Phippen and Melanie Gilman, #837) * Handle cases where a method stub cannot be removed due to something external to RSpec monkeying with the method definition. This can happen, for example, when you `file.reopen(io)` after previously stubbing a method on the `file` object. (Myron Marston, #853) * Provide a clear error when received message args are mutated before a `have_received(...).with(...)` expectation. (Myron Marston, #868) ### 3.1.3 / 2014-10-08 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.2...v3.1.3) Bug Fixes: * Correct received messages count when used with `have_received` matcher. (Jon Rowe, #793) * Provide a clear error message when you use `allow_any_instance_of(...)` or `expect_any_instance_of(...)` with the `have_received` matcher (they are not intended to be used together and previously caused an odd internal failure in rspec-mocks). (Jon Rowe, #799). * Fix verified double `with` verification so that it applies to method stubs. (Myron Marston, #790) ### 3.1.2 / 2014-09-26 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.1...v3.1.2) Bug Fixes: * Provide a clear error message when you use `allow(...)` with the `have_received` matcher (they are not intended to be used together and previously caused an odd internal failure in rspec-mocks). (Jon Rowe, #788). ### 3.1.1 / 2014-09-18 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.0...v3.1.1) Bug Fixes: * Prevent included modules being detected as prepended modules on Ruby 2.0 when using `any_instance_of(...)`. (Tony Novak, #781) ### 3.1.0 / 2014-09-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.4...v3.1.0) Enhancements: * Add spying methods (`spy`, `ìnstance_spy`, `class_spy` and `object_spy`) which create doubles as null objects for use with spying in testing. (Sam Phippen, #671) * `have_received` matcher will raise "does not implement" errors correctly when used with verifying doubles and partial doubles. (Xavier Shay, #722) * Allow matchers to be used in place of keyword arguments in `with` expectations. (Xavier Shay, #726) * Add `thrice` modifier to message expectation interface as a synonym for `exactly(3).times`. (Dennis Taylor, #753) * Add more `thrice` synonyms e.g. `.at_least(:thrice)`, `.at_most(:thrice)`, `receive(...).thrice` and `have_received(...).thrice`. (Jon Rowe, #754) * Add `and_wrap_original` modifier for partial doubles to mutate the response from a method. (Jon Rowe, #762) Bug Fixes: * Remove `any_number_of_times` from `any_instance` recorders that were erroneously causing mention of the method in documentation. (Jon Rowe, #760) * Prevent included modules being detected as prepended modules on Ruby 2.0. (Eugene Kenny, #771) ### 3.0.4 / 2014-08-14 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.3...v3.0.4) Bug Fixes: * Restore `kind_of(x)` to match using `arg.kind_of?(x)` (like RSpec 2) rather than `x === arg`. (Jon Rowe, #750) ### 3.0.3 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.2...v3.0.3) Bug Fixes: * `have_received` matcher will raise "does not implement" errors correctly when used with verifying doubles and partial doubles. (Xavier Shay, #722) * Make `double.as_null_object.dup` and `double.as_null_object.clone` make the copies be null objects. (Myron Marston, #732) * Don't inadvertently define `BasicObject` in 1.8.7. (Chris Griego, #739) ### 3.0.2 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.1...v3.0.2) Bug Fixes: * Fix edge case that triggered "can't add a new key into hash during iteration" during mock verification. (Sam Phippen, Myron Marston, #711) * Fix verifying doubles so that when they accidentally leak into another example, they provide the same clear error message that normal doubles do. (Myron Marston, #718) * Make `ordered` work with exact receive counts. (Sam Phippen, #713) ### 3.0.1 / 2014-06-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0...v3.0.1) Bug Fixes: * Fix `receive_message_chain(...)` so that it supports `with` just like `stub_chain` did. (Jon Rowe, #697) * Fix regression in `expect_any_instance_of` so that it expects the message on _any_ instance rather than on _every_ instance. (Myron Marston, #699) ### 3.0.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.rc1...v3.0.0) Bug Fixes: * Fix module prepend detection to work properly on ruby 2.0 for a case where a module is extended onto itself. (Myron Marston) * Fix `transfer_nested_constants` option so that transferred constants get properly reset at the end of the example. (Myron Marston) * Fix `config.transfer_nested_constants = true` so that you don't erroneously get errors when stubbing a constant that is not a module or a class. (Myron Marston) * Fix regression that caused `double(:class => SomeClass)` to later trigger infinite recursion. (Myron Marston) * Fix bug in `have_received(...).with(...).ordered` where it was not taking the args into account when checking the order. (Myron Marston) * Fix bug in `have_received(...).ordered` where it was wrongly considering stubs when checking the order. (Myron Marston) * Message expectation matchers now show descriptions from argument matchers when their expectations aren't met. (Jon Rowe) * Display warning when encountering `TypeError` during instance method staging on 2.0.0-p195, suffers from https://bugs.ruby-lang.org/issues/8686 too. (Cezar Halmagean). ### 3.0.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.beta2...v3.0.0.rc1) Breaking Changes for 3.0.0: * Remove `RSpec::Mocks::TestDouble.extend_onto`. (Myron Marston) * Remove `RSpec::Mocks::ConstantStubber`. (Jon Rowe) * Make monkey-patch of Marshal to support dumping of stubbed objects opt-in. (Xavier Shay) Enhancements: * Instead of crashing when cleaning up stub methods on a frozen object, it now issues a warning explaining that it's impossible to clean up the stubs. (Justin Coyne and Sam Phippen) * Add meaningful descriptions to `anything`, `duck_type` and `instance_of` argument matchers. (Jon Rowe) Bug Fixes: * Fix regression introduced in 3.0.0.beta2 that caused `double.as_null_object.to_str` to return the double rather than a string. (Myron Marston) * Fix bug in `expect(dbl).to receive_message_chain(:foo, :bar)` where it was not setting an expectation for the last message in the chain. (Jonathan del Strother) * Allow verifying partial doubles to have private methods stubbed. (Xavier Shay) * Fix bug with allowing/expecting messages on Class objects which have had their singleton class prepended to. (Jon Rowe) * Fix an issue with 1.8.7 not running implementation blocks on partial doubles. (Maurício Linhares) * Prevent `StackLevelTooDeep` errors when stubbing an `any_instance` method that's accessed in `inspect` by providing our own inspect output. (Jon Rowe) * Fix bug in `any_instance` logic that did not allow you to mock or stub private methods if `verify_partial_doubles` was configured. (Oren Dobzinski) * Include useful error message when trying to observe an unimplemented method on an any instance. (Xavier Shay) * Fix `and_call_original` to work properly when multiple classes in an inheritance hierarchy have been stubbed with the same method. (Myron Marston) * Fix `any_instance` so that it updates existing instances that have already been stubbed. (Myron Marston) * Fix verified doubles so that their class name is included in failure messages. (Myron Marston) * Fix `expect_any_instance_of` so that when the message is received on an individual instance that has been directly stubbed, it still satisfies the expectation. (Sam Phippen, Myron Marston) * Explicitly disallow using `any_instance` to mock or stub a method that is defined on a module prepended onto the class. This triggered `SystemStackError` before and is very hard to support so we are not supporting it at this time. (Myron Marston) ### 3.0.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.0.0.beta1...v3.0.0.beta2) Breaking Changes for 3.0.0: * Rename `RSpec::Mocks::Mock` to `RSpec::Mocks::Double`. (Myron Marston) * Change how to integrate rspec-mocks in other test frameworks. You now need to include `RSpec::Mocks::ExampleMethods` in your test context. (Myron Marston) * Prevent RSpec mocks' doubles and partial doubles from being used outside of the per-test lifecycle (e.g. from a `before(:all)` hook). (Sam Phippen) * Remove the `host` argument of `RSpec::Mocks.setup`. Instead `RSpec::Mocks::ExampleMethods` should be included directly in the scope where RSpec's mocking capabilities are used. (Sam Phippen) * Make test doubles raise errors if you attempt to use them after they get reset, to help surface issues when you accidentally retain references to test doubles and attempt to reuse them in another example. (Myron Marston) * Remove support for `and_return { value }` and `and_return` without arguments. (Yuji Nakayama) Enhancements: * Add `receive_message_chain` which provides the functionality of the old `stub_chain` for the new allow/expect syntax. Use it like so: `allow(...).to receive_message_chain(:foo, :bar, :bazz)`. (Sam Phippen). * Change argument matchers to use `===` as their primary matching protocol, since their semantics mirror that of a case or rescue statement (which uses `===` for matching). (Myron Marston) * Add `RSpec::Mocks.with_temporary_scope`, which allows you to create temporary rspec-mocks scopes in arbitrary places (such as a `before(:all)` hook). (Myron Marston) * Support keyword arguments when checking arity with verifying doubles. (Xavier Shay) Bug Fixes: * Fix regression in 3.0.0.beta1 that caused `double("string_name" => :value)` to stop working. (Xavier Shay) * Fix the way rspec-mocks and rspec-core interact so that if users define a `let` with the same name as one of the methods from `RSpec::Mocks::ArgumentMatchers`, the user's `let` takes precedence. (Michi Huber, Myron Marston) * Fix verified doubles so that their methods match the visibility (public, protected or private) of the interface they verify against. (Myron Marston) * Fix verified null object doubles so that they do not wrongly report that they respond to anything. They only respond to methods available on the interface they verify against. (Myron Marston) * Fix deprecation warning for use of old `:should` syntax w/o explicit config so that it no longer is silenced by an extension gem such as rspec-rails when it calls `config.add_stub_and_should_receive_to`. (Sam Phippen) * Fix `expect` syntax so that it does not wrongly emit a "You're overriding a previous implementation for this stub" warning when you are not actually doing that. (Myron Marston) * Fix `any_instance.unstub` when used on sub classes for whom the super class has had `any_instance.stub` invoked on. (Jon Rowe) * Fix regression in `stub_chain`/`receive_message_chain` that caused it to raise an `ArgumentError` when passing args to the stubbed methods. (Sam Phippen) * Correct stub of undefined parent modules all the way down when stubbing a nested constant. (Xavier Shay) * Raise `VerifyingDoubleNotDefinedError` when a constant is not defined for a verifying class double. (Maurício Linhares) * Remove `Double#to_str`, which caused confusing `raise some_double` behavior. (Maurício Linhares) ### 3.0.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.4...v3.0.0.beta1) Breaking Changes for 3.0.0: * Raise an explicit error if `should_not_receive(...).and_return` is used. (Sam Phippen) * Remove 1.8.6 workarounds. (Jon Rowe) * Remove `stub!` and `unstub!`. (Sam Phippen) * Remove `mock(name, methods)` and `stub(name, methods)`, leaving `double(name, methods)` for creating test doubles. (Sam Phippen, Michi Huber) * Remove `any_number_of_times` since `should_receive(:msg).any_number_of_times` is really a stub in a mock's clothing. (Sam Phippen) * Remove support for re-using the same null-object test double in multiple examples. Test doubles are designed to only live for one example. (Myron Marston) * Make `at_least(0)` raise an error. (Sam Phippen) * Remove support for `require 'spec/mocks'` which had been kept in place for backwards compatibility with RSpec 1. (Myron Marston) * Blocks provided to `with` are always used as implementation. (Xavier Shay) * The config option (added in 2.99) to yield the receiver to `any_instance` implementation blocks now defaults to "on". (Sam Phippen) Enhancements: * Allow the `have_received` matcher to use a block to set further expectations on arguments. (Tim Cowlishaw) * Provide `instance_double` and `class_double` to create verifying doubles, ported from `rspec-fire`. (Xavier Shay) * `as_null_object` on a verifying double only responds to defined methods. (Xavier Shay) * Provide `object_double` to create verified doubles of specific object instances. (Xavier Shay) * Provide `verify_partial_doubles` configuration that provides `object_double` like verification behaviour on partial doubles. (Xavier Shay) * Improved performance of double creation, particularly those with many attributes. (Xavier Shay) * Default value of `transfer_nested_constants` option for constant stubbing can be configured. (Xavier Shay) * Messages can be allowed or expected on in bulk via `receive_messages(:message => :value)`. (Jon Rowe) * `allow(Klass.any_instance)` and `expect(Klass.any_instance)` now print a warning. This is usually a mistake, and users usually want `allow_any_instance_of` or `expect_any_instance_of` instead. (Sam Phippen) * `instance_double` and `class_double` raise `ArgumentError` if the underlying module is loaded and the arity of the method being invoked does not match the arity of the method as it is actually implemented. (Andy Lindeman) * Spies can now check their invocation ordering is correct. (Jon Rowe) Deprecations: * Using the old `:should` syntax without explicitly configuring it is deprecated. It will continue to work but will emit a deprecation warning in RSpec 3 if you do not explicitly enable it. (Sam Phippen) Bug Fixes: * Fix `and_call_original` to handle a complex edge case involving singleton class ancestors. (Marc-André Lafortune, Myron Marston) * When generating an error message for unexpected arguments, use `#inspect` rather than `#description` if `#description` returns `nil` or `''` so that you still get a useful message. (Nick DeLuca) ### 2.99.4 / 2015-06-19 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.3...v2.99.4) Bug Fixes: * Add missing deprecation for using `with` with no arguments e.g. `with()`. (Yousuke, #970) ### 2.99.3 / 2015-01-09 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.2...v2.99.3) Bug Fixes: * Fix regression that caused an error when a test double was deserialized from YAML. (Yuji Nakayama, #777) ### 2.99.2 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.1...v2.99.2) Enhancements: * Warn about upcoming change to `#===` matching and `DateTime#===` behaviour. (Jon Rowe, #735) ### 2.99.1 / 2014-06-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0...v2.99.1) Bug Fixes: * Fix bug that caused errors at the end of each example when a `double.as_null_object` had been frozen. (Yuji Nakayama, #698) Deprecations: * Deprecate freezing a test double. (Yuji Nakayama, #698) ### 2.99.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.rc1...v2.99.0) No changes. Just taking it out of pre-release. ### 2.99.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta2...v2.99.0.rc1) Deprecations: * Deprecate `RSpec::Mocks::TestDouble.extend_onto`. (Myron Marston) * Deprecate `RSpec::Mocks::ConstantStubber`. (Jon Rowe) * Deprecate `Marshal.dump` monkey-patch without opt-in. (Xavier Shay) ### 2.99.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta1...v2.99.0.beta2) Deprecations: * Deprecate `RSpec::Mocks::Mock` in favor of `RSpec::Mocks::Double`. (Myron Marston) * Deprecate the `host` argument of `RSpec::Mocks.setup`. Instead `RSpec::Mocks::ExampleMethods` should be included directly in the scope where RSpec's mocking capabilities are used. (Sam Phippen) * Deprecate using any of rspec-mocks' features outside the per-test lifecycle (e.g. from a `before(:all)` hook). (Myron Marston) * Deprecate re-using a test double in another example. (Myron Marston) * Deprecate `and_return { value }` and `and_return` without arguments. (Yuji Nakayama) ### 2.99.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.4...v2.99.0.beta1) Deprecations * Expecting to use lambdas or other strong arity implementations for stub methods with mis-matched arity is deprecated and support for them will be removed in 3.0. Either provide the right amount of arguments or use a weak arity implementation (methods with splats or procs). (Jon Rowe) * Using the same test double instance in multiple examples is deprecated. Test doubles are only meant to live for one example. The mocks and stubs have always been reset between examples; however, in 2.x the `as_null_object` state was not reset and some users relied on this to have a null object double that is used for many examples. This behavior will be removed in 3.0. (Myron Marston) * Print a detailed warning when an `any_instance` implementation block is used when the new `yield_receiver_to_any_instance_implementation_blocks` config option is not explicitly set, as RSpec 3.0 will default to enabling this new feature. (Sam Phippen) Enhancements: * Add a config option to yield the receiver to `any_instance` implementation blocks. (Sam Phippen) ### 2.14.6 / 2014-02-20 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.5...v2.14.6) Bug Fixes: * Ensure `any_instance` method stubs and expectations are torn down regardless of expectation failures. (Sam Phippen) ### 2.14.5 / 2014-02-01 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.4...v2.14.5) Bug Fixes: * Fix regression that caused block implementations to not receive all args on 1.8.7 if the block also receives a block, due to Proc#arity reporting `1` no matter how many args the block receives if it receives a block, too. (Myron Marston) ### 2.14.4 / 2013-10-15 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.3...v2.14.4) Bug Fixes: * Fix issue where unstubing methods on "any instances" would not remove stubs on existing instances (Jon Rowe) * Fix issue with receive(:message) do ... end precedence preventing the usage of modifications (`and_return` etc) (Jon Rowe) ### 2.14.3 / 2013-08-08 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.2...v2.14.3) Bug Fixes: * Fix stubbing some instance methods for classes whose hierarchy includes a prepended Module (Bradley Schaefer) ### 2.14.2 / 2013-07-30 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.1...v2.14.2) Bug Fixes: * Fix `as_null_object` doubles so that they return `nil` from `to_ary` (Jon Rowe). * Fix regression in 2.14 that made `stub!` (with an implicit receiver) return a test double rather than stub a method (Myron Marston). ### 2.14.1 / 2013-07-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.0...v2.14.1) Bug Fixes: * Restore `double.as_null_object` behavior from 2.13 and earlier: a double's nullness persisted between examples in earlier examples. While this is not an intended use case (test doubles are meant to live for only one example), we don't want to break behavior users rely on in a minor relase. This will be deprecated in 2.99 and removed in 3.0. (Myron Marston) ### 2.14.0 / 2013-07-06 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.14.0.rc1...v2.14.0) Enhancements: * Document test spies in the readme. (Adarsh Pandit) * Add an `array_including` matcher. (Sam Phippen) * Add a syntax-agnostic API for mocking or stubbing a method. This is intended for use by libraries such as rspec-rails that need to mock or stub a method, and work regardless of the syntax the user has configured (Paul Annesley, Myron Marston and Sam Phippen). Bug Fixes: * Fix `double` so that it sets up passed stubs correctly regardless of the configured syntax (Paul Annesley). * Allow a block implementation to be used in combination with `and_yield`, `and_raise`, `and_return` or `and_throw`. This got fixed in 2.13.1 but failed to get merged into master for the 2.14.0.rc1 release (Myron Marston). * `Marshal.dump` does not unnecessarily duplicate objects when rspec-mocks has not been fully initialized. This could cause errors when using `spork` or similar preloading gems (Andy Lindeman). ### 2.14.0.rc1 / 2013-05-27 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.13.0...v2.14.0.rc1) Enhancements: * Refactor internals so that the mock proxy methods and state are held outside of the mocked object rather than inside it. This paves the way for future syntax enhancements and removes the need for some hacky work arounds for `any_instance` dup'ing and `YAML` serialization, among other things. Note that the code now relies upon `__id__` returning a unique, consistent value for any object you want to mock or stub (Myron Marston). * Add support for test spies. This allows you to verify a message was received afterwards using the `have_received` matcher. Note that you must first stub the method or use a null double. (Joe Ferris and Joël Quenneville) * Make `at_least` and `at_most` style receive expectations print that they were expecting at least or at most some number of calls, rather than just the number of calls given in the expectation (Sam Phippen) * Make `with` style receive expectations print the args they were expecting, and the args that they got (Sam Phippen) * Fix some warnings seen under ruby 2.0.0p0 (Sam Phippen). * Add a new `:expect` syntax for message expectations (Myron Marston and Sam Phippen). Bug fixes * Fix `any_instance` so that a frozen object can be `dup`'d when methods have been stubbed on that type using `any_instance` (Jon Rowe). * Fix `and_call_original` so that it properly raises an `ArgumentError` when the wrong number of args are passed (Jon Rowe). * Fix `double` on 1.9.2 so you can wrap them in an Array using `Array(my_double)` (Jon Rowe). * Fix `stub_const` and `hide_const` to handle constants that redefine `send` (Sam Phippen). * Fix `Marshal.dump` extension so that it correctly handles nil. (Luke Imhoff, Jon Rowe) * Fix isolation of `allow_message_expectations_on_nil` (Jon Rowe) * Use inspect to format actual arguments on expectations in failure messages (#280, Ben Langfeld) * Protect against improperly initialised test doubles (#293) (Joseph Shraibman and Jon Rowe) Deprecations * Deprecate `stub` and `mock` as aliases for `double`. `double` is the best term for creating a test double, and it reduces confusion to have only one term (Michi Huber). * Deprecate `stub!` and `unstub!` in favor of `stub` and `unstub` (Jon Rowe). * Deprecate `at_least(0).times` and `any_number_of_times` (Michi Huber). ### 2.13.1 / 2013-04-06 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.13.0...v2.13.1) Bug fixes * Allow a block implementation to be used in combination with `and_yield`, `and_raise`, `and_return` or `and_throw` (Myron Marston). ### 2.13.0 / 2013-02-23 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.2...v2.13.0) Bug fixes * Fix bug that caused weird behavior when a method that had previously been stubbed with multiple return values (e.g. `obj.stub(:foo).and_return(1, 2)`) was later mocked with a single return value (e.g. `obj.should_receive(:foo).once.and_return(1)`). (Myron Marston) * Fix bug related to a mock expectation for a method that already had multiple stubs with different `with` constraints. Previously, the first stub was used, even though it may not have matched the passed args. The fix defers this decision until the message is received so that the proper stub response can be chosen based on the passed arguments (Myron Marston). * Do not call `nil?` extra times on a mocked object, in case `nil?` itself is expected a set number of times (Myron Marston). * Fix `missing_default_stub_error` message so array args are handled properly (Myron Marston). * Explicitly disallow `any_instance.unstub!` (Ryan Jones). * Fix `any_instance` stubbing so that it works with `Delegator` subclasses (Myron Marston). * Fix `and_call_original` so that it works with `Delegator` subclasses (Myron Marston). * Fix `any_instance.should_not_receive` when `any_instance.should_receive` is used on the same class in the same example. Previously it would wrongly report a failure even when the message was not received (Myron Marston). ### 2.12.2 / 2013-01-27 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.1...v.2.12.2) Bug fixes * Fix `and_call_original` to work properly for methods defined on a module extended onto an object instance (Myron Marston). * Fix `stub_const` with an undefined constnat name to work properly with constant strings that are prefixed with `::` -- and edge case I missed in the bug fix in the 2.12.1 release (Myron Marston). * Ensure method visibility on a partial mock is restored after reseting method stubs, even on a singleton module (created via `extend self`) when the method visibility differs between the instance and singleton versions (Andy Lindeman). ### 2.12.1 / 2012-12-21 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.12.0...v2.12.1) Bug fixes * Fix `any_instance` to support `and_call_original`. (Myron Marston) * Properly restore stubbed aliased methods on rubies that report the incorrect owner (Myron Marston and Andy Lindeman). * Fix `hide_const` and `stub_const` with a defined constnat name to work properly with constant strings that are prefixed with `::` (Myron Marston). ### 2.12.0 / 2012-11-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.3...v2.12.0) Enhancements * `and_raise` can accept an exception class and message, more closely matching `Kernel#raise` (e.g., `foo.stub(:bar).and_raise(RuntimeError, "message")`) (Bas Vodde) * Add `and_call_original`, which will delegate the message to the original method (Myron Marston). Deprecations: * Add deprecation warning when using `and_return` with `should_not_receive` (Neha Kumari) ### 2.11.3 / 2012-09-19 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.2...v2.11.3) Bug fixes * Fix `:transfer_nested_constants` option of `stub_const` so that it doesn't blow up when there are inherited constants. (Myron Marston) * `any_instance` stubs can be used on classes that override `Object#method`. (Andy Lindeman) * Methods stubbed with `any_instance` are unstubbed after the test finishes. (Andy Lindeman) * Fix confusing error message when calling a mocked class method an extra time with the wrong arguments (Myron Marston). ### 2.11.2 / 2012-08-11 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.1...v2.11.2) Bug fixes * Don't modify `dup` on classes that don't support `dup` (David Chelimsky) * Fix `any_instance` so that it works properly with methods defined on a superclass. (Daniel Eguzkiza) * Fix `stub_const` so that it works properly for nested constants that share a name with a top-level constant (e.g. "MyGem::Hash"). (Myron Marston) ### 2.11.1 / 2012-07-09 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.0...v2.11.1) Bug fixes * Fix `should_receive` so that when it is called on an `as_null_object` double with no implementation, and there is a previous explicit stub for the same method, the explicit stub remains (rather than being overridden with the null object implementation--`return self`). (Myron Marston) ### 2.11.0 / 2012-07-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.10.1...v2.11.0) Enhancements * Expose ArgumentListMatcher as a formal API * supports use by 3rd party mock frameworks like Surrogate * Add `stub_const` API to stub constants for the duration of an example (Myron Marston). Bug fixes * Fix regression of edge case behavior. `double.should_receive(:foo) { a }` was causing a NoMethodError when `double.stub(:foo).and_return(a, b)` had been setup before (Myron Marston). * Infinite loop generated by using `any_instance` and `dup`. (Sidu Ponnappa @kaiwren) * `double.should_receive(:foo).at_least(:once).and_return(a)` always returns a even if `:foo` is already stubbed. * Prevent infinite loop when interpolating a null double into a string as an integer (`"%i" % double.as_null_object`). (Myron Marston) * Fix `should_receive` so that null object behavior (e.g. returning self) is preserved if no implementation is given (Myron Marston). * Fix `and_raise` so that it raises `RuntimeError` rather than `Exception` by default, just like ruby does. (Andrew Marshall) ### 2.10.1 / 2012-05-05 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.10.0...v2.10.1) Bug fixes * fix regression of edge case behavior (https://github.com/rspec/rspec-mocks/issues/132) * fixed failure of `object.should_receive(:message).at_least(0).times.and_return value` * fixed failure of `object.should_not_receive(:message).and_return value` ### 2.10.0 / 2012-05-03 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.9.0...v2.10.0) Bug fixes * fail fast when an `exactly` or `at_most` expectation is exceeded ### 2.9.0 / 2012-03-17 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0...v2.9.0) Enhancements * Support order constraints across objects (preethiramdev) Bug fixes * Allow a `as_null_object` to be passed to `with` * Pass proc to block passed to stub (Aubrey Rhodes) * Initialize child message expectation args to match any args (#109 - preethiramdev) ### 2.8.0 / 2012-01-04 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0.rc2...v2.8.0) No changes for this release. Just releasing with the other rspec gems. ### 2.8.0.rc2 / 2011-12-19 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.8.0.rc1...v2.8.0.rc2) No changes for this release. Just releasing with the other rspec gems. ### 2.8.0.rc1 / 2011-11-06 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.7.0...v2.8.0.rc1) Enhancements * Eliminate Ruby warnings (Matijs van Zuijlen) ### 2.7.0 / 2011-10-16 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.6.0...v2.7.0) Enhancements * Use `__send__` rather than `send` (alextk) * Add support for `any_instance.stub_chain` (Sidu Ponnappa) * Add support for `any_instance` argument matching based on `with` (Sidu Ponnappa and Andy Lindeman) Changes * Check for `failure_message_for_should` or `failure_message` instead of `description` to detect a matcher (Tibor Claassen) Bug fixes * pass a hash to `any_instance.stub`. (Justin Ko) * allow `to_ary` to be called without raising `NoMethodError` (Mikhail Dieterle) * `any_instance` properly restores private methods (Sidu Ponnappa) ### 2.6.0 / 2011-05-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.5.0...v2.6.0) Enhancements * Add support for `any_instance.stub` and `any_instance.should_receive` (Sidu Ponnappa and Andy Lindeman) Bug fixes * fix bug in which multiple chains with shared messages ending in hashes failed to return the correct value ### 2.5.0 / 2011-02-05 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.4.0...v2.5.0) Bug fixes * message expectation counts now work in combination with a stub (Damian Nurzynski) * fix failure message when message received with incorrect args (Josep M. Bach) ### 2.4.0 / 2011-01-02 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.3.0...v2.4.0) No functional changes in this release, which was made to align with the rspec-core-2.4.0 release. ### 2.3.0 / 2010-12-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.2.0...v2.3.0) Bug fixes * Fix our Marshal extension so that it does not interfere with objects that have their own `@mock_proxy` instance variable. (Myron Marston) ### 2.2.0 / 2010-11-28 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.1.0...v2.2.0) Enhancements * Added "rspec/mocks/standalone" for exploring the rspec-mocks in irb. Bug fix * Eliminate warning on splat args without parens (Gioele Barabucci) * Fix bug where `obj.should_receive(:foo).with(stub.as_null_object)` would pass with a false positive. ### 2.1.0 / 2010-11-07 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.1...v2.1.0) Bug fixes * Fix serialization of stubbed object (Josep M Bach) ### 2.0.0 / 2010-10-10 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.22...v2.0.0) ### 2.0.0.rc / 2010-10-05 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.22...v2.0.0.rc) Enhancements * support passing a block to an expectation block (Nicolas Braem) * `obj.should_receive(:msg) {|&block| ... }` Bug fixes * Fix YAML serialization of stub (Myron Marston) * Fix rdoc rake task (Hans de Graaff) ### 2.0.0.beta.22 / 2010-09-12 [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.0.0.beta.20...v2.0.0.beta.22) Bug fixes * fixed regression that broke `obj.stub_chain(:a, :b => :c)` * fixed regression that broke `obj.stub_chain(:a, :b) { :c }` * `respond_to?` always returns true when using `as_null_object` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/CODE_OF_CONDUCT.md0000664000000000000000000000544414557670305021633 0ustar rootroot # Contributor Code of Conduct For the purpose of building a welcoming, harassment-free community that values contributions from anyone, the RSpec project has adopted the following code of conduct. All contributors and participants (including maintainers!) are expected to abide by its terms. As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the project maintainers listed at https://rspec.info/about/. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/3/0/ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/Gemfile0000664000000000000000000000571614557670305020331 0ustar rootrootsource "https://rubygems.org" gemspec branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp %w[rspec rspec-core rspec-expectations rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path else gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end if RUBY_VERSION < '1.9.3' gem 'rake', '< 11.0.0' # rake 11 requires Ruby 1.9.3 or later elsif RUBY_VERSION < '2.0.0' gem 'rake', '< 12.0.0' # rake 12 requires Ruby 2.0.0 or later else gem 'rake', '> 12.3.2' end if ENV['DIFF_LCS_VERSION'] gem 'diff-lcs', ENV['DIFF_LCS_VERSION'] else gem 'diff-lcs', '~> 1.4', '>= 1.4.3' end gem 'yard', '~> 0.9.24', :require => false # No need to run rubocop on earlier versions if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' gem "rubocop", "~> 1.0", "< 1.12" end # allow gems to be installed on older rubies and/or windows if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.10' elsif RUBY_VERSION < '2.4.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.15' elsif RUBY_VERSION < '1.9' gem 'ffi', '< 1.9.19' # ffi dropped Ruby 1.8 support in 1.9.19 elsif RUBY_VERSION < '2.0' gem 'ffi', '< 1.11.0' # ffi dropped Ruby 1.9 support in 1.11.0 elsif RUBY_VERSION < '2.3.0' gem 'ffi', '~> 1.12.0' else gem 'ffi', '~> 1.15.0' end if RUBY_VERSION <= '2.3.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.0.0' gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.3.0' gem "childprocess", "< 3.0.0" else gem "childprocess", ">= 3.0.0" end if RUBY_VERSION < '1.9.2' gem 'contracts', '~> 0.15.0' # is a dependency of aruba end # Version 5.12 of minitest requires Ruby 2.4 if RUBY_VERSION < '2.4.0' gem 'minitest', '< 5.12.0' end if RUBY_VERSION < '2.0.0' gem 'thor', '< 1.0.0' else gem 'thor', '> 1.0.0' end ### deps for rdoc.info group :documentation do gem 'redcarpet', :platform => :mri gem 'github-markup', :platform => :mri end group :coverage do gem 'simplecov', '~> 0.8' end if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java' gem 'json', '< 2.0.0' # this is a dependency of simplecov else gem 'json', '> 2.3.0' end if RUBY_VERSION < '2.0.0' gem 'cucumber', "<= 1.3.22" elsif !ENV['DIFF_LCS_VERSION'].to_s.empty? && ENV['DIFF_LCS_VERSION'].scan(/\d\.\d/).first.to_f < 1.5 # Older version of diff-lcs cause a downstream error with cucumber and modern rails gem "activesupport", "< 7" end platforms :jruby do if RUBY_VERSION < '1.9.0' # Pin jruby-openssl on older J Ruby gem "jruby-openssl", "< 0.10.0" # Pin child-process on older J Ruby gem "childprocess", "< 1.0.0" else gem "jruby-openssl" end end eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom') ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/Gemfile-custom.sample0000664000000000000000000000051114557670305023105 0ustar rootrootgroup :development do gem 'interactive_rspec' gem 'guard-rspec', '~> 1.2.1' gem 'growl', '1.0.3' gem 'spork', '0.9.0' platform :mri do gem 'rb-fsevent', '~> 0.9.0' gem 'ruby-prof', '~> 0.10.0' case RUBY_VERSION when /^1.8/ gem 'ruby-debug' when /^1.9/ gem 'debugger' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/REPORT_TEMPLATE.md0000664000000000000000000000211714557670305021656 0ustar rootroot # Report template ```ruby # frozen_string_literal: true begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "rspec", "3.7.0" # Activate the gem and version you are reporting the issue against. end puts "Ruby version is: #{RUBY_VERSION}" require 'rspec/autorun' RSpec.describe 'additions' do it 'returns 2' do expect(1 + 1).to eq(2) end it 'returns 1' do expect(3 - 1).to eq(-1) end end ``` Simply copy the content of the appropriate template into a `.rb` file on your computer and make the necessary changes to demonstrate the issue. You can execute it by running `ruby rspec_report.rb` in your terminal. You can then share your executable test case as a [gist](https://gist.github.com), or simply paste the content into the issue description. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.document0000664000000000000000000000006014557670305020640 0ustar rootrootlib/**/*.rb - README.md LICENSE.md Changelog.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.yardopts0000664000000000000000000000011414557670305020667 0ustar rootroot--exclude features --no-private --markup markdown - Changelog.md LICENSE.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.rspec0000664000000000000000000000004114557670305020135 0ustar rootroot--warnings --require spec_helper ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.rubocop_todo.yml0000664000000000000000000004307014557670305022330 0ustar rootroot# This configuration was generated by # `rubocop --auto-gen-config` # on 2022-01-09 17:32:27 UTC using RuboCop version 1.11.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 # Configuration parameters: Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/DuplicatedGem: Exclude: - 'Gemfile' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: - 'Gemfile' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemspec Gemspec/OrderedDependencies: Exclude: - 'rspec-mocks.gemspec' # Offense count: 1 # Configuration parameters: Include. # Include: **/*.gemspec Gemspec/RequiredRubyVersion: Exclude: - 'rspec-mocks.gemspec' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: with_first_argument, with_fixed_indentation Layout/ArgumentAlignment: Exclude: - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyleAlignWith. # SupportedStylesAlignWith: either, start_of_block, start_of_line Layout/BlockAlignment: Exclude: - 'spec/rspec/mocks/any_instance_spec.rb' # Offense count: 37 # Cop supports --auto-correct. Layout/EmptyLineAfterGuardClause: Enabled: false # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: AllowAliasSyntax, AllowedMethods. # AllowedMethods: alias_method, public, protected, private Layout/EmptyLinesAroundAttributeAccessor: Exclude: - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses Layout/FirstArgumentIndentation: Exclude: - 'lib/rspec/mocks/error_generator.rb' - 'spec/rspec/mocks/nil_expectation_warning_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table # SupportedColonStyles: key, separator, table # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit Layout/HashAlignment: Exclude: - 'lib/rspec/mocks/method_double.rb' - 'rspec-mocks.gemspec' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: normal, indented_internal_methods Layout/IndentationConsistency: Exclude: - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: Width, IgnoredPatterns. Layout/IndentationWidth: Exclude: - 'lib/rspec/mocks/any_instance/expectation_chain.rb' - 'lib/rspec/mocks/method_reference.rb' - 'lib/rspec/mocks/test_double.rb' - 'spec/rspec/mocks/matchers/receive_spec.rb' - 'spec/rspec/mocks_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Layout/LeadingEmptyLines: Exclude: - 'spec/rspec/mocks/space_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Layout/LineLength: Max: 325 # Offense count: 3 # Cop supports --auto-correct. Layout/SpaceAfterComma: Exclude: - 'spec/rspec/mocks/array_including_matcher_spec.rb' # Offense count: 43 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideHashLiteralBraces: Exclude: - 'spec/rspec/mocks/argument_matchers_spec.rb' - 'spec/rspec/mocks/diffing_spec.rb' - 'spec/rspec/mocks/hash_excluding_matcher_spec.rb' - 'spec/rspec/mocks/hash_including_matcher_spec.rb' - 'spec/rspec/mocks/should_syntax_spec.rb' # Offense count: 44 Lint/AmbiguousBlockAssociation: Exclude: - 'spec/rspec/mocks/and_call_original_spec.rb' - 'spec/rspec/mocks/and_wrap_original_spec.rb' - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/argument_matchers_spec.rb' - 'spec/rspec/mocks/block_return_value_spec.rb' - 'spec/rspec/mocks/combining_implementation_instructions_spec.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/matchers/receive_spec.rb' - 'spec/rspec/mocks/serialization_spec.rb' - 'spec/rspec/mocks/space_spec.rb' - 'spec/rspec/mocks/stub_spec.rb' - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' # Offense count: 3 # Cop supports --auto-correct. Lint/AmbiguousRegexpLiteral: Exclude: - 'features/step_definitions/additional_cli_steps.rb' # Offense count: 20 # Configuration parameters: AllowedMethods. # AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/argument_matchers_spec.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/expiration_spec.rb' - 'spec/rspec/mocks/instance_method_stasher_spec.rb' - 'spec/rspec/mocks/marshal_extension_spec.rb' - 'spec/rspec/mocks/matchers/have_received_spec.rb' - 'spec/rspec/mocks/mock_expectation_error_spec.rb' - 'spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb' - 'spec/rspec/mocks/serialization_spec.rb' - 'spec/rspec/mocks/spy_spec.rb' - 'spec/rspec/mocks/stub_spec.rb' - 'spec/rspec/mocks/verifying_doubles/class_double_with_class_loaded_spec.rb' - 'spec/rspec/mocks/verifying_doubles/construction_spec.rb' - 'spec/rspec/mocks/verifying_doubles/instance_double_with_class_loaded_spec.rb' # Offense count: 1 Lint/DuplicateRequire: Exclude: - 'spec/spec_helper.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: runtime_error, standard_error Lint/InheritException: Exclude: - 'lib/rspec/mocks/error_generator.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/RedundantStringCoercion: Exclude: - 'spec/rspec/mocks/message_expectation_string_representation_spec.rb' # Offense count: 2 Lint/RescueException: Exclude: - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/SendWithMixinArgument: Exclude: - 'lib/rspec/mocks/minitest_integration.rb' # Offense count: 1 Lint/ShadowingOuterLocalVariable: Exclude: - 'benchmarks/each_value_v_values_each.rb' # Offense count: 2 Lint/StructNewOverride: Exclude: - 'spec/rspec/mocks/and_call_original_spec.rb' - 'spec/rspec/mocks/any_instance_spec.rb' # Offense count: 5 # Configuration parameters: AllowComments. Lint/SuppressedException: Exclude: - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/mock_expectation_error_spec.rb' - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks_spec.rb' - 'spec/spec_helper.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. Lint/UselessAccessModifier: Exclude: - 'lib/rspec/mocks/method_double.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowComments. Lint/UselessMethodDefinition: Exclude: - 'lib/rspec/mocks/verifying_message_expectation.rb' # Offense count: 1 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 47 # Offense count: 100 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. # IgnoredMethods: refine Metrics/BlockLength: Max: 1066 # Offense count: 8 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: Max: 1066 # Offense count: 23 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'lib/rspec/mocks/message_expectation.rb' - 'spec/rspec/mocks/and_call_original_spec.rb' - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' - 'spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb' - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks/verifying_doubles/class_double_with_class_loaded_spec.rb' - 'spec/support/doubled_classes.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: Exclude: - 'lib/rspec/mocks/error_generator.rb' - 'spec/rspec/mocks/matchers/receive_messages_spec.rb' - 'spec/rspec/mocks_spec.rb' # Offense count: 2 Security/Eval: Exclude: - 'Gemfile' - 'spec/rspec/mocks/verifying_doubles/method_visibility_spec.rb' # Offense count: 5 Security/MarshalLoad: Exclude: - 'spec/rspec/mocks/marshal_extension_spec.rb' # Offense count: 4 # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Exclude: - 'benchmarks/method_defined_at_any_visibility.rb' - 'spec/rspec/mocks/stub_spec.rb' # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: separated, grouped Style/AccessorGrouping: Exclude: - 'lib/rspec/mocks/message_expectation.rb' - 'lib/rspec/mocks/proxy.rb' # Offense count: 10 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/matchers/receive_messages_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' - 'spec/rspec/mocks/verifying_doubles/naming_spec.rb' # Offense count: 3 # Cop supports --auto-correct. Style/BlockComments: Exclude: - 'benchmarks/find_original_method_early.rb' - 'benchmarks/method_defined_at_any_visibility.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/matchers/receive_message_chain_spec.rb' - 'spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb' - 'spec/rspec/mocks/space_spec.rb' # Offense count: 1 Style/CombinableLoops: Exclude: - 'benchmarks/allocations/1_object_1000_mocks.rb' # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: Keywords. # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE Style/CommentAnnotation: Exclude: - 'spec/rspec/mocks/and_call_original_spec.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/CommentedKeyword: Exclude: - 'spec/rspec/mocks/matchers/receive_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/EachForSimpleLoop: Exclude: - 'spec/rspec/mocks/double_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/Encoding: Exclude: - 'rspec-mocks.gemspec' # Offense count: 9 # Cop supports --auto-correct. Style/EvalWithLocation: Exclude: - 'spec/rspec/mocks/and_yield_spec.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb' - 'spec/rspec/mocks/verifying_doubles/method_visibility_spec.rb' - 'spec/support/doubled_classes.rb' # Offense count: 6 # Cop supports --auto-correct. Style/ExpandPathArguments: Exclude: - 'Gemfile' - 'benchmarks/allocations/helper.rb' - 'benchmarks/double_creation.rb' - 'benchmarks/thread_safety.rb' - 'benchmarks/transfer_nested_constants.rb' - 'rspec-mocks.gemspec' # Offense count: 2 # Cop supports --auto-correct. Style/ExplicitBlockArgument: Exclude: - 'benchmarks/allocations/helper.rb' - 'spec/rspec/mocks/partial_double_spec.rb' # Offense count: 134 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Enabled: false # Offense count: 3 # Configuration parameters: AllowedVariables. Style/GlobalVars: Exclude: - 'benchmarks/find_original_method_early.rb' - 'spec/rspec/mocks/configuration_spec.rb' - 'spec/spec_helper.rb' # Offense count: 2 # Cop supports --auto-correct. Style/HashEachMethods: Exclude: - 'benchmarks/each_value_v_values_each.rb' - 'lib/rspec/mocks/space.rb' # Offense count: 1 # Cop supports --auto-correct. Style/HashTransformValues: Exclude: - 'lib/rspec/mocks/error_generator.rb' # Offense count: 3 Style/MultilineBlockChain: Exclude: - 'spec/rspec/mocks/failure_notification_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/MultilineTernaryOperator: Exclude: - 'spec/rspec/mocks/null_object_double_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/MultilineWhenThen: Exclude: - 'lib/rspec/mocks/error_generator.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedOctalStyle. # SupportedOctalStyles: zero_with_o, zero_only Style/NumericLiteralPrefix: Exclude: - 'spec/rspec/mocks/error_generator_spec.rb' # Offense count: 11 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/rspec/mocks/any_instance/proxy.rb' - 'lib/rspec/mocks/error_generator.rb' - 'lib/rspec/mocks/object_reference.rb' - 'lib/rspec/mocks/space.rb' - 'lib/rspec/mocks/test_double.rb' - 'lib/rspec/mocks/verifying_double.rb' - 'spec/rspec/mocks/partial_double_spec.rb' - 'spec/support/doubled_classes.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: lower_case_q, upper_case_q Style/PercentQLiterals: Exclude: - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/RedundantInterpolation: Exclude: - 'spec/rspec/mocks/double_spec.rb' # Offense count: 9 # Cop supports --auto-correct. Style/RedundantPercentQ: Exclude: - 'features/step_definitions/additional_cli_steps.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' - 'spec/rspec/mocks/verifying_doubles/naming_spec.rb' # Offense count: 27 # Cop supports --auto-correct. Style/RedundantRegexpEscape: Exclude: - 'spec/rspec/mocks/argument_matchers_spec.rb' - 'spec/rspec/mocks/diffing_spec.rb' - 'spec/rspec/mocks/partial_double_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/RescueModifier: Exclude: - 'spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - 'lib/rspec/mocks/method_reference.rb' - 'lib/rspec/mocks/proxy.rb' # Offense count: 17 # Cop supports --auto-correct. # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Exclude: - 'benchmarks/each_value_v_values_each.rb' - 'spec/rspec/mocks/double_spec.rb' - 'spec/rspec/mocks/failure_notification_spec.rb' - 'spec/rspec/mocks/instance_method_stasher_spec.rb' - 'spec/rspec/mocks/matchers/receive_messages_spec.rb' - 'spec/rspec/mocks/matchers/receive_spec.rb' - 'spec/rspec/mocks/reraising_eager_raises_spec.rb' - 'spec/rspec/mocks/stub_spec.rb' - 'spec/rspec/mocks/stubbed_message_expectations_spec.rb' # Offense count: 46 # Cop supports --auto-correct. # Configuration parameters: AllowIfMethodIsEmpty. Style/SingleLineMethods: Exclude: - 'spec/rspec/mocks/and_call_original_spec.rb' - 'spec/rspec/mocks/and_yield_spec.rb' - 'spec/rspec/mocks/any_instance_spec.rb' - 'spec/rspec/mocks/instance_method_stasher_spec.rb' - 'spec/rspec/mocks/matchers/receive_spec.rb' - 'spec/rspec/mocks/should_syntax_spec.rb' - 'spec/rspec/mocks/stub_implementation_spec.rb' - 'spec/rspec/mocks/stub_spec.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: AllowModifier. Style/SoleNestedConditional: Exclude: - 'lib/rspec/mocks/any_instance/message_chains.rb' - 'lib/rspec/mocks/any_instance/recorder.rb' - 'lib/rspec/mocks/argument_list_matcher.rb' - 'lib/rspec/mocks/proxy.rb' # Offense count: 5 # Cop supports --auto-correct. Style/StringConcatenation: Exclude: - 'lib/rspec/mocks/argument_matchers.rb' - 'lib/rspec/mocks/error_generator.rb' - 'lib/rspec/mocks/mutate_const.rb' - 'spec/rspec/mocks/block_return_value_spec.rb' - 'spec/rspec/mocks/mutate_const_spec.rb' ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/maintenance-branch0000664000000000000000000000002114557670305022456 0ustar rootroot3-13-maintenance ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/README.md0000664000000000000000000004243114557670305020310 0ustar rootroot# RSpec Mocks [![Build Status](https://github.com/rspec/rspec-mocks/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-mocks/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.svg)](https://codeclimate.com/github/rspec/rspec-mocks) rspec-mocks is a test-double framework for rspec with support for method stubs, fakes, and message expectations on generated test-doubles and real objects alike. ## Install gem install rspec # for rspec-core, rspec-expectations, rspec-mocks gem install rspec-mocks # for rspec-mocks only Want to run against the `main` branch? You'll need to include the dependent RSpec repos as well. Add the following to your `Gemfile`: ```ruby %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main' end ``` ## Contributing Once you've set up the environment, you'll need to cd into the working directory of whichever repo you want to work in. From there you can run the specs and cucumber features, and make patches. NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You can treat each RSpec repo as an independent project. For information about contributing to RSpec, please refer to the following markdown files: * [Build details](BUILD_DETAIL.md) * [Code of Conduct](CODE_OF_CONDUCT.md) * [Detailed contributing guide](CONTRIBUTING.md) * [Development setup guide](DEVELOPMENT.md) ## Test Doubles A test double is an object that stands in for another object in your system during a code example. Use the `double` method, passing in an optional identifier, to create one: ```ruby book = double("book") ``` Most of the time you will want some confidence that your doubles resemble an existing object in your system. Verifying doubles are provided for this purpose. If the existing object is available, they will prevent you from adding stubs and expectations for methods that do not exist or that have an invalid number of parameters. ```ruby book = instance_double("Book", :pages => 250) ``` Verifying doubles have some clever tricks to enable you to both test in isolation without your dependencies loaded while still being able to validate them against real objects. More detail is available in [their documentation](https://github.com/rspec/rspec-mocks/blob/main/features/verifying_doubles). Verifying doubles can also accept custom identifiers, just like double(), e.g.: ```ruby books = [] books << instance_double("Book", :rspec_book, :pages => 250) books << instance_double("Book", "(Untitled)", :pages => 5000) puts books.inspect # with names, it's clearer which were actually added ``` ## Method Stubs A method stub is an implementation that returns a pre-determined value. Method stubs can be declared on test doubles or real objects using the same syntax. rspec-mocks supports 3 forms for declaring method stubs: ```ruby allow(book).to receive(:title) { "The RSpec Book" } allow(book).to receive(:title).and_return("The RSpec Book") allow(book).to receive_messages( :title => "The RSpec Book", :subtitle => "Behaviour-Driven Development with RSpec, Cucumber, and Friends") ``` You can also use this shortcut, which creates a test double and declares a method stub in one statement: ```ruby book = double("book", :title => "The RSpec Book") ``` The first argument is a name, which is used for documentation and appears in failure messages. If you don't care about the name, you can leave it out, making the combined instantiation/stub declaration very terse: ```ruby double(:foo => 'bar') ``` This is particularly nice when providing a list of test doubles to a method that iterates through them: ```ruby order.calculate_total_price(double(:price => 1.99), double(:price => 2.99)) ``` ### Stubbing a chain of methods You can use `receive_message_chain` in place of `receive` to stub a chain of messages: ```ruby allow(double).to receive_message_chain("foo.bar") { :baz } allow(double).to receive_message_chain(:foo, :bar => :baz) allow(double).to receive_message_chain(:foo, :bar) { :baz } # Given any of the above forms: double.foo.bar # => :baz ``` Chains can be arbitrarily long, which makes it quite painless to violate the Law of Demeter in violent ways, so you should consider any use of `receive_message_chain` a code smell. Even though not all code smells indicate real problems (think fluent interfaces), `receive_message_chain` still results in brittle examples. For example, if you write `allow(foo).to receive_message_chain(:bar, :baz => 37)` in a spec and then the implementation calls `foo.baz.bar`, the stub will not work. ## Consecutive return values When a stub might be invoked more than once, you can provide additional arguments to `and_return`. The invocations cycle through the list. The last value is returned for any subsequent invocations: ```ruby allow(die).to receive(:roll).and_return(1, 2, 3) die.roll # => 1 die.roll # => 2 die.roll # => 3 die.roll # => 3 die.roll # => 3 ``` To return an array in a single invocation, declare an array: ```ruby allow(team).to receive(:players).and_return([double(:name => "David")]) ``` ## Message Expectations A message expectation is an expectation that the test double will receive a message some time before the example ends. If the message is received, the expectation is satisfied. If not, the example fails. ```ruby validator = double("validator") expect(validator).to receive(:validate) { "02134" } zipcode = Zipcode.new("02134", validator) zipcode.valid? ``` ## Test Spies Verifies the given object received the expected message during the course of the test. For a message to be verified, the given object must be setup to spy on it, either by having it explicitly stubbed or by being a null object double (e.g. `double(...).as_null_object`). Convenience methods are provided to easily create null object doubles for this purpose: ```ruby spy("invitation") # => same as `double("invitation").as_null_object` instance_spy("Invitation") # => same as `instance_double("Invitation").as_null_object` class_spy("Invitation") # => same as `class_double("Invitation").as_null_object` object_spy("Invitation") # => same as `object_double("Invitation").as_null_object` ``` Verifying messages received in this way implements the Test Spy pattern. ```ruby invitation = spy('invitation') user.accept_invitation(invitation) expect(invitation).to have_received(:accept) # You can also use other common message expectations. For example: expect(invitation).to have_received(:accept).with(mailer) expect(invitation).to have_received(:accept).twice expect(invitation).to_not have_received(:accept).with(mailer) # One can specify a return value on the spy the same way one would a double. invitation = spy('invitation', :accept => true) expect(invitation).to have_received(:accept).with(mailer) expect(invitation.accept).to eq(true) ``` Note that `have_received(...).with(...)` is unable to work properly when passed arguments are mutated after the spy records the received message. For example, this does not work properly: ```ruby greeter = spy("greeter") message = "Hello" greeter.greet_with(message) message << ", World" expect(greeter).to have_received(:greet_with).with("Hello") ``` ## Nomenclature ### Mock Objects and Test Stubs The names Mock Object and Test Stub suggest specialized Test Doubles. i.e. a Test Stub is a Test Double that only supports method stubs, and a Mock Object is a Test Double that supports message expectations and method stubs. There is a lot of overlapping nomenclature here, and there are many variations of these patterns (fakes, spies, etc). Keep in mind that most of the time we're talking about method-level concepts that are variations of method stubs and message expectations, and we're applying to them to _one_ generic kind of object: a Test Double. ### Test-Specific Extension a.k.a. Partial Double, a Test-Specific Extension is an extension of a real object in a system that is instrumented with test-double like behaviour in the context of a test. This technique is very common in Ruby because we often see class objects acting as global namespaces for methods. For example, in Rails: ```ruby person = double("person") allow(Person).to receive(:find) { person } ``` In this case we're instrumenting Person to return the person object we've defined whenever it receives the `find` message. We can also set a message expectation so that the example fails if `find` is not called: ```ruby person = double("person") expect(Person).to receive(:find) { person } ``` RSpec replaces the method we're stubbing or mocking with its own test-double-like method. At the end of the example, RSpec verifies any message expectations, and then restores the original methods. ## Expecting Arguments ```ruby expect(double).to receive(:msg).with(*args) expect(double).to_not receive(:msg).with(*args) ``` You can set multiple expectations for the same message if you need to: ```ruby expect(double).to receive(:msg).with("A", 1, 3) expect(double).to receive(:msg).with("B", 2, 4) ``` ## Argument Matchers Arguments that are passed to `with` are compared with actual arguments received using ===. In cases in which you want to specify things about the arguments rather than the arguments themselves, you can use any of the matchers that ship with rspec-expectations. They don't all make syntactic sense (they were primarily designed for use with RSpec::Expectations), but you are free to create your own custom RSpec::Matchers. rspec-mocks also adds some keyword Symbols that you can use to specify certain kinds of arguments: ```ruby expect(double).to receive(:msg).with(no_args) expect(double).to receive(:msg).with(any_args) expect(double).to receive(:msg).with(1, any_args) # any args acts like an arg splat and can go anywhere expect(double).to receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can be any kind of Numeric expect(double).to receive(:msg).with(1, boolean(), "b") #2nd argument can be true or false expect(double).to receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp expect(double).to receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all expect(double).to receive(:msg).with(1, duck_type(:abs, :div), "b") #2nd argument can be object that responds to #abs and #div expect(double).to receive(:msg).with(hash_including(:a => 5)) # first arg is a hash with a: 5 as one of the key-values expect(double).to receive(:msg).with(array_including(5)) # first arg is an array with 5 as one of the key-values expect(double).to receive(:msg).with(hash_excluding(:a => 5)) # first arg is a hash without a: 5 as one of the key-values expect(double).to receive(:msg).with(start_with('a')) # any matcher, custom or from rspec-expectations expect(double).to receive(:msg).with(satisfy { |data| data.dig(:a, :b, :c) == 5 }) # assert anything you want ``` ## Receive Counts ```ruby expect(double).to receive(:msg).once expect(double).to receive(:msg).twice expect(double).to receive(:msg).exactly(n).time expect(double).to receive(:msg).exactly(n).times expect(double).to receive(:msg).at_least(:once) expect(double).to receive(:msg).at_least(:twice) expect(double).to receive(:msg).at_least(n).time expect(double).to receive(:msg).at_least(n).times expect(double).to receive(:msg).at_most(:once) expect(double).to receive(:msg).at_most(:twice) expect(double).to receive(:msg).at_most(n).time expect(double).to receive(:msg).at_most(n).times ``` ## Ordering ```ruby expect(double).to receive(:msg).ordered expect(double).to receive(:other_msg).ordered # This will fail if the messages are received out of order ``` This can include the same message with different arguments: ```ruby expect(double).to receive(:msg).with("A", 1, 3).ordered expect(double).to receive(:msg).with("B", 2, 4).ordered ``` ## Setting Responses Whether you are setting a message expectation or a method stub, you can tell the object precisely how to respond. The most generic way is to pass a block to `receive`: ```ruby expect(double).to receive(:msg) { value } ``` When the double receives the `msg` message, it evaluates the block and returns the result. ```ruby expect(double).to receive(:msg).and_return(value) expect(double).to receive(:msg).exactly(3).times.and_return(value1, value2, value3) # returns value1 the first time, value2 the second, etc expect(double).to receive(:msg).and_raise(error) # `error` can be an instantiated object (e.g. `StandardError.new(some_arg)`) or a class (e.g. `StandardError`) # if it is a class, it must be instantiable with no args expect(double).to receive(:msg).and_throw(:msg) expect(double).to receive(:msg).and_yield(values, to, yield) expect(double).to receive(:msg).and_yield(values, to, yield).and_yield(some, other, values, this, time) # for methods that yield to a block multiple times ``` Any of these responses can be applied to a stub as well ```ruby allow(double).to receive(:msg).and_return(value) allow(double).to receive(:msg).and_return(value1, value2, value3) allow(double).to receive(:msg).and_raise(error) allow(double).to receive(:msg).and_throw(:msg) allow(double).to receive(:msg).and_yield(values, to, yield) allow(double).to receive(:msg).and_yield(values, to, yield).and_yield(some, other, values, this, time) ``` ## Arbitrary Handling Once in a while you'll find that the available expectations don't solve the particular problem you are trying to solve. Imagine that you expect the message to come with an Array argument that has a specific length, but you don't care what is in it. You could do this: ```ruby expect(double).to receive(:msg) do |arg| expect(arg.size).to eq 7 end ``` If the method being stubbed itself takes a block, and you need to yield to it in some special way, you can use this: ```ruby expect(double).to receive(:msg) do |&arg| begin arg.call ensure # cleanup end end ``` ## Delegating to the Original Implementation When working with a partial mock object, you may occasionally want to set a message expectation without interfering with how the object responds to the message. You can use `and_call_original` to achieve this: ```ruby expect(Person).to receive(:find).and_call_original Person.find # => executes the original find method and returns the result ``` ## Combining Expectation Details Combining the message name with specific arguments, receive counts and responses you can get quite a bit of detail in your expectations: ```ruby expect(double).to receive(:<<).with("illegal value").once.and_raise(ArgumentError) ``` While this is a good thing when you really need it, you probably don't really need it! Take care to specify only the things that matter to the behavior of your code. ## Stubbing and Hiding Constants See the [mutating constants README](https://github.com/rspec/rspec-mocks/blob/main/features/mutating_constants/README.md) for info on this feature. ## Use `before(:example)`, not `before(:context)` Stubs in `before(:context)` are not supported. The reason is that all stubs and mocks get cleared out after each example, so any stub that is set in `before(:context)` would work in the first example that happens to run in that group, but not for any others. Instead of `before(:context)`, use `before(:example)`. ## Settings mocks or stubs on any instance of a class rspec-mocks provides two methods, `allow_any_instance_of` and `expect_any_instance_of`, that will allow you to stub or mock any instance of a class. They are used in place of `allow` or `expect`: ```ruby allow_any_instance_of(Widget).to receive(:name).and_return("Wibble") expect_any_instance_of(Widget).to receive(:name).and_return("Wobble") ``` These methods add the appropriate stub or expectation to all instances of `Widget`. This feature is sometimes useful when working with legacy code, though in general we discourage its use for a number of reasons: * The `rspec-mocks` API is designed for individual object instances, but this feature operates on entire classes of objects. As a result there are some semantically confusing edge cases. For example in `expect_any_instance_of(Widget).to receive(:name).twice` it isn't clear whether each specific instance is expected to receive `name` twice, or if two receives total are expected. (It's the former.) * Using this feature is often a design smell. It may be that your test is trying to do too much or that the object under test is too complex. * It is the most complicated feature of `rspec-mocks`, and has historically received the most bug reports. (None of the core team actively use it, which doesn't help.) ## Further Reading There are many different viewpoints about the meaning of mocks and stubs. If you are interested in learning more, here is some recommended reading: * Mock Objects: http://www.mockobjects.com/ * Endo-Testing: http://www.ccs.neu.edu/research/demeter/related-work/extreme-programming/MockObjectsFinal.PDF * Mock Roles, Not Objects: http://www.jmock.org/oopsla2004.pdf * Test Double: http://www.martinfowler.com/bliki/TestDouble.html * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html ## Also see * [https://github.com/rspec/rspec](https://github.com/rspec/rspec) * [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core) * [https://github.com/rspec/rspec-expectations](https://github.com/rspec/rspec-expectations) * [https://github.com/rspec/rspec-rails](https://github.com/rspec/rspec-rails) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/Rakefile0000664000000000000000000000155714557670305020502 0ustar rootrootrequire 'bundler' Bundler.setup Bundler::GemHelper.install_tasks require 'rake' require 'rspec/core/rake_task' require 'rspec/mocks/version' require 'cucumber/rake/task' desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.ruby_opts = %w[-w] t.rspec_opts = %w[--color] end Cucumber::Rake::Task.new(:cucumber) task :clobber do rm_rf 'pkg' rm_rf 'tmp' rm_rf 'coverage' rm_rf '.yardoc' rm_rf 'doc' end namespace :clobber do desc "remove generated rbc files" task :rbc do Dir['**/*.rbc'].each { |f| File.delete(f) } end end task :default => [:spec, :cucumber] task :verify_private_key_present do private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') unless File.exist?(private_key) raise "Your private key is not present. This gem should not be built without it." end end task :build => :verify_private_key_present ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.autotest0000664000000000000000000000021614557670305020675 0ustar rootrootAutotest.add_hook :initialize do |at| at.clear_mappings at.add_mapping(%r%\.rb$%) { at.files_matching %r%^spec/.*_spec\.rb$% } end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/0000775000000000000000000000000014557670305017757 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/0000775000000000000000000000000014557670305021073 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/0000775000000000000000000000000014557670305022207 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/any_instance_spec.rb0000664000000000000000000015005014557670305026222 0ustar rootrootrequire 'delegate' module AnyInstanceSpec class GrandparentClass def foo(_a) 'bar' end def grandparent_method 1 end end class ParentClass < GrandparentClass def foo super(:a) end def caller_of_parent_aliased_method parent_aliased_method end alias parent_aliased_method grandparent_method end class ChildClass < ParentClass end end module RSpec module Mocks RSpec.describe "#any_instance" do class CustomErrorForAnyInstanceSpec < StandardError; end let(:klass) do Class.new do def existing_method; :existing_method_return_value; end def existing_method_with_arguments(_a, _b=nil); :existing_method_with_arguments_return_value; end def another_existing_method; end private def private_method; :private_method_return_value; end end end let(:existing_method_return_value) { :existing_method_return_value } context "chain" do it "yields the value specified" do allow_any_instance_of(klass).to receive(:foo).and_yield(1).and_yield(2) expect { |b| klass.new.foo(&b) }.to yield_successive_args(1, 2) end end context "invocation order" do context "when stubbing" do it "raises an error if 'with' follows 'and_return'" do expect { allow_any_instance_of(klass).to receive(:foo).and_return(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_raise'" do expect { allow_any_instance_of(klass).to receive(:foo).and_raise(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_yield'" do expect { allow_any_instance_of(klass).to receive(:foo).and_yield(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_throw'" do expect { allow_any_instance_of(klass).to receive(:foo).and_throw(:ball).with("football") }.to raise_error(NoMethodError) end it "allows chaining 'and_yield'" do allow_any_instance_of(klass).to receive(:foo).and_yield(1).and_yield(2).and_yield(3) expect { |b| klass.new.foo(&b) }.to yield_successive_args(1, 2, 3) end end context "when setting a message expectation" do it "raises an error if 'with' follows 'and_return'" do pending "see Github issue #42" expect { expect_any_instance_of(klass).to receive(:foo).and_return(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_raise'" do pending "see Github issue #42" expect { expect_any_instance_of(klass).to receive(:foo).and_raise(1).with("1") }.to raise_error(NoMethodError) end end end context "when stubbing" do it "does not suppress an exception when a method that doesn't exist is invoked" do allow_any_instance_of(klass).to receive(:foo) expect { klass.new.bar }.to raise_error(NoMethodError) end context 'multiple methods' do it "allows multiple methods to be stubbed in a single invocation" do allow_any_instance_of(klass).to receive_messages(:foo => 'foo', :bar => 'bar') instance = klass.new expect(instance.foo).to eq('foo') expect(instance.bar).to eq('bar') end context "allows a chain of methods to be stubbed using #receive_message_chain" do example "given symbols representing the methods" do allow_any_instance_of(klass).to receive_message_chain(:one, :two, :three).and_return(:four) expect(klass.new.one.two.three).to eq(:four) end example "given a hash as the last argument uses the value as the expected return value" do allow_any_instance_of(klass).to receive_message_chain(:one, :two, :three => :four) expect(klass.new.one.two.three).to eq(:four) end example "given a string of '.' separated method names representing the chain" do allow_any_instance_of(klass).to receive_message_chain('one.two.three').and_return(:four) expect(klass.new.one.two.three).to eq(:four) end it "can constrain the return value by the argument to the last call" do allow_any_instance_of(klass).to receive_message_chain(:one, :plus).with(1) { 2 } allow_any_instance_of(klass).to receive_message_chain(:one, :plus).with(2) { 3 } expect(klass.new.one.plus(1)).to eq(2) expect(klass.new.one.plus(2)).to eq(3) end it 'can use a chain of methods to perform an expectation' do expect_any_instance_of(klass).to receive_message_chain('message1.message2').with('some args') klass.new.message1.message2('some args') end end end context "behaves as 'every instance'" do let(:super_class) { Class.new { def foo; 'bar'; end } } let(:sub_class) { Class.new(super_class) { def bar; 'foo'; end } } it "stubs every instance in the spec" do allow_any_instance_of(klass).to receive(:foo).and_return(result = Object.new) expect(klass.new.foo).to eq(result) expect(klass.new.foo).to eq(result) end it "stubs instance created before any_instance was called" do instance = klass.new allow_any_instance_of(klass).to receive(:foo).and_return(result = Object.new) expect(instance.foo).to eq(result) end it 'handles freeze and duplication correctly' do allow_any_instance_of(String).to receive(:any_method) foo = 'foo'.freeze expect(foo.dup.concat 'bar').to eq 'foobar' end it 'handles stubbing on super and subclasses' do allow_any_instance_of(super_class).to receive(:foo) allow_any_instance_of(sub_class).to receive(:foo).and_return('baz') expect(sub_class.new.foo).to eq('baz') end it 'handles stubbing on a sub class when a super class is stubbed differently' do expect_any_instance_of(super_class).to receive(:foo) expect_any_instance_of(sub_class).to receive(:bar).and_return('baz') expect(sub_class.new.bar).to eq('baz') expect { verify_all }.to fail_with "Exactly one instance should have received the following message(s) but didn't: foo" end it 'handles method restoration on subclasses' do allow_any_instance_of(super_class).to receive(:foo) allow_any_instance_of(sub_class).to receive(:foo) allow_any_instance_of(sub_class).to receive(:foo).and_call_original expect(sub_class.new.foo).to eq("bar") end end context "when the class has a prepended module", :if => Support::RubyFeatures.module_prepends_supported? do it 'allows stubbing a method that is not defined on the prepended module' do klass.class_eval { prepend Module.new { def other; end } } allow_any_instance_of(klass).to receive(:foo).and_return(45) expect(klass.new.foo).to eq(45) end it 'prevents stubbing a method that is defined on the prepended module' do klass.class_eval { prepend Module.new { def foo; end } } expect { allow_any_instance_of(klass).to receive(:foo).and_return(45) }.to fail_with(/prepended module/) end it 'allows stubbing a chain starting with a method that is not defined on the prepended module' do klass.class_eval { prepend Module.new { def other; end } } allow_any_instance_of(klass).to receive_message_chain(:foo, :bar).and_return(45) expect(klass.new.foo.bar).to eq(45) end it 'prevents stubbing a chain starting with a method that is defined on the prepended module' do klass.class_eval { prepend Module.new { def foo; end } } expect { allow_any_instance_of(klass).to receive_message_chain(:foo, :bar).and_return(45) }.to fail_with(/prepended module/) end end context 'aliased methods' do it 'tracks aliased method calls' do instance = AnyInstanceSpec::ParentClass.new expect_any_instance_of(AnyInstanceSpec::ParentClass).to receive(:parent_aliased_method).with(no_args).and_return(2) expect(instance.caller_of_parent_aliased_method).to eq 2 reset_all expect(instance.caller_of_parent_aliased_method).to eq 1 end end context "with argument matching" do before do allow_any_instance_of(klass).to receive(:foo).with(:param_one, :param_two).and_return(:result_one) allow_any_instance_of(klass).to receive(:foo).with(:param_three, :param_four).and_return(:result_two) end it "returns the stubbed value when arguments match" do instance = klass.new expect(instance.foo(:param_one, :param_two)).to eq(:result_one) expect(instance.foo(:param_three, :param_four)).to eq(:result_two) end it "fails the spec with an expectation error when the arguments do not match" do expect do klass.new.foo(:param_one, :param_three) end.to fail end end context "with multiple stubs" do before do allow_any_instance_of(klass).to receive(:foo).and_return(1) allow_any_instance_of(klass).to receive(:bar).and_return(2) end it "stubs a method" do instance = klass.new expect(instance.foo).to eq(1) expect(instance.bar).to eq(2) end it "returns the same value for calls on different instances" do expect(klass.new.foo).to eq(klass.new.foo) expect(klass.new.bar).to eq(klass.new.bar) end end context "with #and_return" do it "can stub a method that doesn't exist" do allow_any_instance_of(klass).to receive(:foo).and_return(1) expect(klass.new.foo).to eq(1) end it "can stub a method that exists" do allow_any_instance_of(klass).to receive(:existing_method).and_return(1) expect(klass.new.existing_method).to eq(1) end it "returns the same object for calls on different instances" do return_value = Object.new allow_any_instance_of(klass).to receive(:foo).and_return(return_value) expect(klass.new.foo).to be(return_value) expect(klass.new.foo).to be(return_value) end it "can change how instances responds in the middle of an example" do instance = klass.new allow_any_instance_of(klass).to receive(:foo).and_return(1) expect(instance.foo).to eq(1) allow_any_instance_of(klass).to receive(:foo).and_return(2) expect(instance.foo).to eq(2) allow_any_instance_of(klass).to receive(:foo).and_raise("boom") expect { instance.foo }.to raise_error("boom") end end context "with #and_yield" do it "yields the value specified" do yielded_value = Object.new allow_any_instance_of(klass).to receive(:foo).and_yield(yielded_value) expect { |b| klass.new.foo(&b) }.to yield_with_args(yielded_value) end end context 'with #and_call_original and competing #with' do let(:klass) { Struct.new(:a_method) } it 'can combine and_call_original, with, and_return' do allow_any_instance_of(klass).to receive(:a_method).and_call_original allow_any_instance_of(klass).to receive(:a_method).with(:arg).and_return('value') expect(klass.new('org').a_method).to eq 'org' expect(klass.new.a_method(:arg)).to eq 'value' end end context "with #and_raise" do it "can stub a method that doesn't exist" do allow_any_instance_of(klass).to receive(:foo).and_raise(CustomErrorForAnyInstanceSpec) expect { klass.new.foo }.to raise_error(CustomErrorForAnyInstanceSpec) end it "can stub a method that exists" do allow_any_instance_of(klass).to receive(:existing_method).and_raise(CustomErrorForAnyInstanceSpec) expect { klass.new.existing_method }.to raise_error(CustomErrorForAnyInstanceSpec) end end context "with #and_throw" do it "can stub a method that doesn't exist" do allow_any_instance_of(klass).to receive(:foo).and_throw(:up) expect { klass.new.foo }.to throw_symbol(:up) end it "can stub a method that exists" do allow_any_instance_of(klass).to receive(:existing_method).and_throw(:up) expect { klass.new.existing_method }.to throw_symbol(:up) end end context "with a block" do it "stubs a method" do allow_any_instance_of(klass).to receive(:foo) { 1 } expect(klass.new.foo).to eq(1) end it "returns the same computed value for calls on different instances" do allow_any_instance_of(klass).to receive(:foo) { 1 + 2 } expect(klass.new.foo).to eq(klass.new.foo) end end context "when partially mocking objects" do let(:obj) { klass.new } it "resets partially mocked objects correctly" do allow_any_instance_of(klass).to receive(:existing_method).and_return("stubbed value") # Simply resetting the proxy doesn't work # what we need to have happen is # ::RSpec::Mocks.space.any_instance_recorder_for(klass).stop_all_observation! # but that is never invoked in :: expect { verify_all }.to( change { obj.existing_method }.from("stubbed value").to(:existing_method_return_value) ) end end context "core ruby objects" do it "works uniformly across *everything*" do allow_any_instance_of(Object).to receive(:foo).and_return(1) expect(Object.new.foo).to eq(1) end it "works with the non-standard constructor []" do allow_any_instance_of(Array).to receive(:foo).and_return(1) expect([].foo).to eq(1) end it "works with the non-standard constructor {}" do allow_any_instance_of(Hash).to receive(:foo).and_return(1) expect({}.foo).to eq(1) end it "works with the non-standard constructor \"\"" do allow_any_instance_of(String).to receive(:foo).and_return(1) expect("".dup.foo).to eq(1) end it "works with the non-standard constructor \'\'" do allow_any_instance_of(String).to receive(:foo).and_return(1) expect(''.dup.foo).to eq(1) end it "works with the non-standard constructor module" do allow_any_instance_of(Module).to receive(:foo).and_return(1) module RSpec::SampleRspecTestModule; end expect(RSpec::SampleRspecTestModule.foo).to eq(1) end it "works with the non-standard constructor class" do allow_any_instance_of(Class).to receive(:foo).and_return(1) class RSpec::SampleRspecTestClass; end expect(RSpec::SampleRspecTestClass.foo).to eq(1) end end end context "unstubbing using `and_call_original`" do it "replaces the stubbed method with the original method" do allow_any_instance_of(klass).to receive(:existing_method) allow_any_instance_of(klass).to receive(:existing_method).and_call_original expect(klass.new.existing_method).to eq(:existing_method_return_value) end it "removes all stubs with the supplied method name" do allow_any_instance_of(klass).to receive(:existing_method).with(1) allow_any_instance_of(klass).to receive(:existing_method).with(2) allow_any_instance_of(klass).to receive(:existing_method).and_call_original expect(klass.new.existing_method).to eq(:existing_method_return_value) end it "removes stubs even if they have already been invoked" do allow_any_instance_of(klass).to receive(:existing_method).and_return(:any_instance_value) obj = klass.new obj.existing_method allow_any_instance_of(klass).to receive(:existing_method).and_call_original expect(obj.existing_method).to eq(:existing_method_return_value) end it "removes stubs from sub class after Invocation when super class was originally stubbed" do allow_any_instance_of(klass).to receive(:existing_method).and_return(:any_instance_value) obj = Class.new(klass).new expect(obj.existing_method).to eq(:any_instance_value) allow_any_instance_of(klass).to receive(:existing_method).and_call_original expect(obj.existing_method).to eq(:existing_method_return_value) end it "removes any stubs set directly on an instance" do allow_any_instance_of(klass).to receive(:existing_method).and_return(:any_instance_value) obj = klass.new allow(obj).to receive(:existing_method).and_return(:local_method) allow_any_instance_of(klass).to receive(:existing_method).and_call_original expect(obj.existing_method).to eq(:existing_method_return_value) end it "does not remove any expectations with the same method name" do expect_any_instance_of(klass).to receive(:existing_method_with_arguments).with(3).and_return(:three) allow_any_instance_of(klass).to receive(:existing_method_with_arguments).with(1) allow_any_instance_of(klass).to receive(:existing_method_with_arguments).with(2) allow_any_instance_of(klass).to receive(:existing_method_with_arguments).and_call_original expect(klass.new.existing_method_with_arguments(3)).to eq(:three) end it 'does not get confused about string vs symbol usage for the message' do allow_any_instance_of(klass).to receive(:existing_method) { :stubbed } allow_any_instance_of(klass).to receive("existing_method").and_call_original expect(klass.new.existing_method).to eq(:existing_method_return_value) end end context "expect_any_instance_of(...).not_to receive" do it "fails if the method is called" do expect_any_instance_of(klass).not_to receive(:existing_method) expect_fast_failure_from(klass.new) do |instance| instance.existing_method end end it "passes if no method is called" do expect { expect_any_instance_of(klass).not_to receive(:existing_method) }.to_not raise_error end it "passes if only a different method is called" do expect_any_instance_of(klass).not_to receive(:existing_method) expect { klass.new.another_existing_method }.to_not raise_error end it "affects previously stubbed instances" do instance = klass.new allow_any_instance_of(klass).to receive(:foo).and_return(1) expect(instance.foo).to eq(1) expect_any_instance_of(klass).not_to receive(:foo) expect_fast_failure_from(instance) do instance.foo end end context "with constraints" do it "fails if the method is called with the specified parameters" do expect_any_instance_of(klass).not_to receive(:existing_method_with_arguments).with(:argument_one, :argument_two) expect_fast_failure_from(klass.new) do |instance| instance.existing_method_with_arguments(:argument_one, :argument_two) end end it "passes if the method is called with different parameters" do expect_any_instance_of(klass).not_to receive(:existing_method_with_arguments).with(:argument_one, :argument_two) expect { klass.new.existing_method_with_arguments(:argument_three, :argument_four) }.to_not raise_error end end context 'when used in combination with should_receive' do it 'passes if only the expected message is received' do expect_any_instance_of(klass).to receive(:foo) expect_any_instance_of(klass).not_to receive(:bar) klass.new.foo verify_all end end it "prevents confusing double-negative expressions involving `never`" do expect { expect_any_instance_of(klass).not_to receive(:not_expected).never }.to raise_error(/trying to negate it again/) end end context "setting a message expectation" do let(:foo_expectation_error_message) { 'Exactly one instance should have received the following message(s) but didn\'t: foo' } let(:existing_method_expectation_error_message) { 'Exactly one instance should have received the following message(s) but didn\'t: existing_method' } it "handles inspect accessing expected methods" do klass.class_eval do def inspect "The contents of output: #{stdout}" end end expect_any_instance_of(klass).to receive(:stdout).at_least(:twice) expect do klass.new.stdout klass.new.stdout end.to raise_error(/The message 'stdout' was received by/) reset_all end it "affects previously stubbed instances" do instance = klass.new allow_any_instance_of(klass).to receive(:foo).and_return(1) expect(instance.foo).to eq(1) expect_any_instance_of(klass).to receive(:foo).with(2).and_return(2) expect(instance.foo(2)).to eq(2) end it "does not set the expectation on every instance" do # Setup an unrelated object of the same class that won't receive the expected message. allow('non-related object'.dup).to receive(:non_related_method) expect_any_instance_of(Object).to receive(:foo) 'something'.dup.foo end it "does not modify the return value of stubs set on an instance" do expect_any_instance_of(Object).to receive(:foo).twice object = Object.new allow(object).to receive(:foo).and_return(3) expect(object.foo).to eq(3) expect(object.foo).to eq(3) end it "does not modify the return value of stubs set on an instance of a subclass" do subklass = Class.new(klass) subinstance = subklass.new allow_any_instance_of(klass).to receive(:foo).and_return(1) expect(subinstance.foo).to eq(1) expect_any_instance_of(klass).to receive(:foo).with(2).and_return(2) expect(subinstance.foo(2)).to eq(2) end it "properly notifies any instance recorders at multiple levels of hierarchy when a directly stubbed object receives a message" do subclass = Class.new(klass) instance = subclass.new expect_any_instance_of(klass).to receive(:msg_1) expect_any_instance_of(subclass).to receive(:msg_2) allow(instance).to receive_messages(:msg_1 => "a", :msg_2 => "b") expect(instance.msg_1).to eq("a") expect(instance.msg_2).to eq("b") end it "properly notifies any instance recorders when they are created after the object's mock proxy" do object = Object.new allow(object).to receive(:bar) expect_any_instance_of(Object).to receive(:foo).twice allow(object).to receive(:foo).and_return(3) expect(object.foo).to eq(3) expect(object.foo).to eq(3) end context "when the class has a prepended module", :if => Support::RubyFeatures.module_prepends_supported? do it 'allows mocking a method that is not defined on the prepended module' do klass.class_eval { prepend Module.new { def other; end } } expect_any_instance_of(klass).to receive(:foo).and_return(45) expect(klass.new.foo).to eq(45) end it 'prevents mocking a method that is defined on the prepended module' do klass.class_eval { prepend Module.new { def foo; end } } expect { expect_any_instance_of(klass).to receive(:foo).and_return(45) }.to fail_with(/prepended module/) end end context "when the class has an included module" do it 'allows mocking a method that is defined on the module' do mod = Module.new { def foo; end } klass.class_eval { include mod } expect_any_instance_of(mod).to receive(:foo).and_return(45) expect(klass.new.foo).to eq(45) end end context "when an instance has been directly stubbed" do it "fails when a second instance to receive the message" do expect_any_instance_of(klass).to receive(:foo) instance_1 = klass.new allow(instance_1).to receive(:foo).and_return(17) expect(instance_1.foo).to eq(17) expect { klass.new.foo }.to fail_with(/has already been received/) end end context "when argument matching is used and an instance has stubbed the message" do it "fails on verify if the arguments do not match" do expect_any_instance_of(klass).to receive(:foo).with(3) instance = klass.new allow(instance).to receive(:foo).and_return(2) expect(instance.foo(4)).to eq(2) expect { verify_all }.to fail end it "passes on verify if the arguments do match" do expect_any_instance_of(klass).to receive(:foo).with(3) instance = klass.new allow(instance).to receive(:foo).and_return(2) expect(instance.foo(3)).to eq(2) expect { verify_all }.not_to raise_error end end context "with an expectation is set on a method which does not exist" do it "returns the expected value" do expect_any_instance_of(klass).to receive(:foo).and_return(1) expect(klass.new.foo(1)).to eq(1) end it "fails if an instance is created but no invocation occurs" do expect do expect_any_instance_of(klass).to receive(:foo) klass.new verify_all end.to fail_with foo_expectation_error_message end it "fails if no instance is created" do expect do expect_any_instance_of(klass).to receive(:foo).and_return(1) verify_all end.to fail_with foo_expectation_error_message end it "fails if no instance is created and there are multiple expectations" do expect do expect_any_instance_of(klass).to receive(:foo) expect_any_instance_of(klass).to receive(:bar) verify_all end.to fail_with 'Exactly one instance should have received the following message(s) but didn\'t: bar, foo' end it "allows expectations on instances to take priority" do expect_any_instance_of(klass).to receive(:foo) klass.new.foo instance = klass.new expect(instance).to receive(:foo).and_return(result = Object.new) expect(instance.foo).to eq(result) end context "behaves as 'exactly one instance'" do it "passes if subsequent invocations do not receive that message" do expect_any_instance_of(klass).to receive(:foo) klass.new.foo klass.new end it "fails if the method is invoked on a second instance" do instance_one = klass.new instance_two = klass.new expect do expect_any_instance_of(klass).to receive(:foo) instance_one.foo instance_two.foo end.to fail_with(/The message 'foo' was received by .*#{instance_two.object_id}.* but has already been received by #{instance_one.inspect}/) end end context "normal expectations on the class object" do it "fail when unfulfilled" do expect do expect_any_instance_of(klass).to receive(:foo) expect(klass).to receive(:woot) klass.new.foo verify_all end.to(fail do |error| expect(error.message).not_to eq(existing_method_expectation_error_message) end) end it "pass when expectations are met" do expect_any_instance_of(klass).to receive(:foo) expect(klass).to receive(:woot).and_return(result = Object.new) klass.new.foo expect(klass.woot).to eq(result) end end end context "with an expectation is set on a method that exists" do it "returns the expected value" do expect_any_instance_of(klass).to receive(:existing_method).and_return(1) expect(klass.new.existing_method(1)).to eq(1) end it "fails if an instance is created but no invocation occurs" do expect do expect_any_instance_of(klass).to receive(:existing_method) klass.new verify_all end.to fail_with existing_method_expectation_error_message end it "fails if no instance is created" do expect do expect_any_instance_of(klass).to receive(:existing_method) verify_all end.to fail_with existing_method_expectation_error_message end it "fails if no instance is created and there are multiple expectations" do expect do expect_any_instance_of(klass).to receive(:existing_method) expect_any_instance_of(klass).to receive(:another_existing_method) verify_all end.to fail_with 'Exactly one instance should have received the following message(s) but didn\'t: another_existing_method, existing_method' end context "after any one instance has received a message" do it "passes if subsequent invocations do not receive that message" do expect_any_instance_of(klass).to receive(:existing_method) klass.new.existing_method klass.new end it "fails if the method is invoked on a second instance" do instance_one = klass.new instance_two = klass.new expect do expect_any_instance_of(klass).to receive(:existing_method) instance_one.existing_method instance_two.existing_method end.to fail_with(/The message 'existing_method' was received by .*#{instance_two.object_id}.* but has already been received by #{instance_one.inspect}/) end end end it 'works with a BasicObject subclass that mixes in Kernel', :if => defined?(BasicObject) do klazz = Class.new(BasicObject) do include ::Kernel def foo; end end expect_any_instance_of(klazz).to receive(:foo) klazz.new.foo end it 'works with a SimpleDelegator subclass', :if => (RUBY_VERSION.to_f > 1.8) do klazz = Class.new(SimpleDelegator) do def foo; end end expect_any_instance_of(klazz).to receive(:foo) klazz.new(Object.new).foo end context "with argument matching" do before do expect_any_instance_of(klass).to receive(:foo).with(:param_one, :param_two).and_return(:result_one) expect_any_instance_of(klass).to receive(:foo).with(:param_three, :param_four).and_return(:result_two) end it "returns the expected value when arguments match" do instance = klass.new expect(instance.foo(:param_one, :param_two)).to eq(:result_one) expect(instance.foo(:param_three, :param_four)).to eq(:result_two) end it "fails when the arguments match but different instances are used" do instances = Array.new(2) { klass.new } expect do expect(instances[0].foo(:param_one, :param_two)).to eq(:result_one) expect(instances[1].foo(:param_three, :param_four)).to eq(:result_two) end.to fail # ignore the fact that should_receive expectations were not met instances.each { |instance| reset instance } end it "is not affected by the invocation of existing methods on other instances" do expect(klass.new.existing_method_with_arguments(:param_one, :param_two)).to eq(:existing_method_with_arguments_return_value) instance = klass.new expect(instance.foo(:param_one, :param_two)).to eq(:result_one) expect(instance.foo(:param_three, :param_four)).to eq(:result_two) end it "fails when arguments do not match" do instance = klass.new expect do instance.foo(:param_one, :param_three) end.to fail # ignore the fact that should_receive expectations were not met reset instance end end context "message count" do context "the 'once' constraint" do it "passes for one invocation" do expect_any_instance_of(klass).to receive(:foo).once klass.new.foo end it "fails when no instances are declared" do expect do expect_any_instance_of(klass).to receive(:foo).once verify_all end.to fail_with foo_expectation_error_message end it "fails when an instance is declared but there are no invocations" do expect do expect_any_instance_of(klass).to receive(:foo).once klass.new verify_all end.to fail_with foo_expectation_error_message end it "fails for more than one invocation" do expect_any_instance_of(klass).to receive(:foo).once expect_fast_failure_from(klass.new) do |instance| 2.times { instance.foo } verify instance end end end context "the 'twice' constraint" do it "passes for two invocations" do expect_any_instance_of(klass).to receive(:foo).twice instance = klass.new 2.times { instance.foo } end it "fails for more than two invocations" do expect_any_instance_of(klass).to receive(:foo).twice expect_fast_failure_from(klass.new) do |instance| 3.times { instance.foo } verify instance end end end context "the 'thrice' constraint" do it "passes for three invocations" do expect_any_instance_of(klass).to receive(:foo).thrice instance = klass.new 3.times { instance.foo } end it "fails for more than three invocations" do expect_any_instance_of(klass).to receive(:foo).thrice expect_fast_failure_from(klass.new) do |instance| 4.times { instance.foo } verify instance end end it "fails for less than three invocations" do expect do expect_any_instance_of(klass).to receive(:foo).thrice instance = klass.new 2.times { instance.foo } verify instance end.to fail end end context "the 'exactly(n)' constraint" do describe "time alias" do it "passes for 1 invocation" do expect_any_instance_of(klass).to receive(:foo).exactly(1).time instance = klass.new instance.foo end it "fails for 2 invocations" do expect_any_instance_of(klass).to receive(:foo).exactly(1).time expect_fast_failure_from(klass.new) do |instance| 2.times { instance.foo } verify instance end end end it "passes for n invocations where n = 3" do expect_any_instance_of(klass).to receive(:foo).exactly(3).times instance = klass.new 3.times { instance.foo } end it "fails for n invocations where n < 3" do expect do expect_any_instance_of(klass).to receive(:foo).exactly(3).times instance = klass.new 2.times { instance.foo } verify instance end.to fail end it "fails for n invocations where n > 3" do expect_any_instance_of(klass).to receive(:foo).exactly(3).times expect_fast_failure_from(klass.new) do |instance| 4.times { instance.foo } verify instance end end end context "the 'at_least(n)' constraint" do it "passes for n invocations where n = 3" do expect_any_instance_of(klass).to receive(:foo).at_least(3).times instance = klass.new 3.times { instance.foo } end it "fails for n invocations where n < 3" do expect do expect_any_instance_of(klass).to receive(:foo).at_least(3).times instance = klass.new 2.times { instance.foo } verify instance end.to fail end it "passes for n invocations where n > 3" do expect_any_instance_of(klass).to receive(:foo).at_least(3).times instance = klass.new 4.times { instance.foo } end end context "the 'at_most(n)' constraint" do it "passes for n invocations where n = 3" do expect_any_instance_of(klass).to receive(:foo).at_most(3).times instance = klass.new 3.times { instance.foo } end it "passes for n invocations where n < 3" do expect_any_instance_of(klass).to receive(:foo).at_most(3).times instance = klass.new 2.times { instance.foo } end it "fails for n invocations where n > 3" do expect_any_instance_of(klass).to receive(:foo).at_most(3).times expect_fast_failure_from(klass.new) do |instance| 4.times { instance.foo } verify instance end end end context "the 'never' constraint" do it "passes for 0 invocations" do expect_any_instance_of(klass).to receive(:foo).never verify_all end it "fails on the first invocation" do expect_any_instance_of(klass).to receive(:foo).never expect_fast_failure_from(klass.new) do |instance| instance.foo end end context "when combined with other expectations" do it "passes when the other expectations are met" do expect_any_instance_of(klass).to receive(:foo).never expect_any_instance_of(klass).to receive(:existing_method).and_return(5) expect(klass.new.existing_method).to eq(5) end it "fails when the other expectations are not met" do expect do expect_any_instance_of(klass).to receive(:foo).never expect_any_instance_of(klass).to receive(:existing_method).and_return(5) verify_all end.to fail_with existing_method_expectation_error_message end end end end end context "when resetting post-verification" do let(:space) { RSpec::Mocks.space } context "existing method" do before(:each) do RSpec::Mocks.space.any_instance_recorder_for(klass) # to force it to be tracked end context "with stubbing" do context "public methods" do before(:each) do allow_any_instance_of(klass).to receive(:existing_method).and_return(1) expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_truthy end it "restores the class to its original state after each example when no instance is created" do verify_all expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey expect(klass.new.existing_method).to eq(existing_method_return_value) end it "restores the class to its original state after each example when one instance is created" do klass.new.existing_method verify_all expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey expect(klass.new.existing_method).to eq(existing_method_return_value) end it "restores the class to its original state after each example when more than one instance is created" do klass.new.existing_method klass.new.existing_method verify_all expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey expect(klass.new.existing_method).to eq(existing_method_return_value) end end context "private methods" do before :each do allow_any_instance_of(klass).to receive(:private_method).and_return(:something) verify_all end it "cleans up the backed up method" do expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey end it "restores a stubbed private method after the spec is run" do expect(klass.private_method_defined?(:private_method)).to be_truthy end it "ensures that the restored method behaves as it originally did" do expect(klass.new.send(:private_method)).to eq(:private_method_return_value) end end end context "with expectations" do context "private methods" do before :each do expect_any_instance_of(klass).to receive(:private_method).and_return(:something) klass.new.private_method verify_all end it "cleans up the backed up method" do expect(klass.method_defined?(:__existing_method_without_any_instance__)).to be_falsey end it "restores a stubbed private method after the spec is run" do expect(klass.private_method_defined?(:private_method)).to be_truthy end it "ensures that the restored method behaves as it originally did" do expect(klass.new.send(:private_method)).to eq(:private_method_return_value) end end context "ensures that the subsequent specs do not see expectations set in previous specs" do context "when the instance created after the expectation is set" do it "first spec" do expect_any_instance_of(klass).to receive(:existing_method).and_return(Object.new) klass.new.existing_method end it "second spec" do expect(klass.new.existing_method).to eq(existing_method_return_value) end end context "when the instance created before the expectation is set" do before :each do @instance = klass.new end it "first spec" do expect_any_instance_of(klass).to receive(:existing_method).and_return(Object.new) @instance.existing_method end it "second spec" do expect(@instance.existing_method).to eq(existing_method_return_value) end end end it "ensures that the next spec does not see that expectation" do expect_any_instance_of(klass).to receive(:existing_method).and_return(Object.new) klass.new.existing_method verify_all expect(klass.new.existing_method).to eq(existing_method_return_value) end end end context "with multiple calls to any_instance in the same example" do it "does not prevent the change from being rolled back" do allow_any_instance_of(klass).to receive(:existing_method).and_return(false) allow_any_instance_of(klass).to receive(:existing_method).and_return(true) verify_all expect(klass.new).to respond_to(:existing_method) expect(klass.new.existing_method).to eq(existing_method_return_value) end end it "adds an instance to the current space when stubbed method is invoked" do allow_any_instance_of(klass).to receive(:foo) instance = klass.new instance.foo expect(RSpec::Mocks.space.proxies.keys).to include(instance.object_id) end end context "passing the receiver to the implementation block" do context "when configured to pass the instance" do include_context 'with isolated configuration' before(:each) do RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks = true end describe "an any instance stub" do it "passes the instance as the first arg of the implementation block" do instance = klass.new expect { |b| expect_any_instance_of(klass).to receive(:bees).with(:sup, &b) instance.bees(:sup) }.to yield_with_args(instance, :sup) end it "does not pass the instance to and_call_original" do klazz = Class.new do def call(*args) args.first end end expect_any_instance_of(klazz).to receive(:call).and_call_original instance = klazz.new expect(instance.call(:bees)).to be :bees end end describe "an any instance expectation" do it "doesn't effect with" do instance = klass.new expect_any_instance_of(klass).to receive(:bees).with(:sup) instance.bees(:sup) end it "passes the instance as the first arg of the implementation block" do instance = klass.new expect { |b| expect_any_instance_of(klass).to receive(:bees).with(:sup, &b) instance.bees(:sup) }.to yield_with_args(instance, :sup) end end end context "when configured not to pass the instance" do include_context 'with isolated configuration' before(:each) do RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks = false end describe "an any instance stub" do it "does not pass the instance to the implementation block" do instance = klass.new expect { |b| expect_any_instance_of(klass).to receive(:bees).with(:sup, &b) instance.bees(:sup) }.to yield_with_args(:sup) end it "does not cause with to fail when the instance is passed" do instance = klass.new expect_any_instance_of(klass).to receive(:bees).with(:faces) instance.bees(:faces) end end end end context 'when used in conjunction with a `dup`' do it "doesn't cause an infinite loop" do skip "This intermittently fails on JRuby" if RUBY_PLATFORM == 'java' allow_any_instance_of(Object).to receive(:some_method) o = Object.new o.some_method expect { o.dup.some_method }.to_not raise_error end it "doesn't bomb if the object doesn't support `dup`" do klazz = Class.new do undef_method :dup end allow_any_instance_of(klazz).to receive(:foo) end it "doesn't fail when dup accepts parameters" do klazz = Class.new do def dup(_) end end allow_any_instance_of(klazz).to receive(:foo) expect { klazz.new.dup('Dup dup dup') }.to_not raise_error end end context "when directed at a method defined on a superclass" do let(:sub_klass) { Class.new(klass) } it "stubs the method correctly" do allow_any_instance_of(klass).to receive(:existing_method).and_return("foo") expect(sub_klass.new.existing_method).to eq "foo" end it "mocks the method correctly" do instance_one = sub_klass.new instance_two = sub_klass.new expect do expect_any_instance_of(klass).to receive(:existing_method) instance_one.existing_method instance_two.existing_method end.to fail_with(/The message 'existing_method' was received by .*#{instance_two.object_id}.* but has already been received by #{instance_one.inspect}/) end end context "when a class overrides Object#method" do let(:http_request_class) { Struct.new(:method, :uri) } it "stubs the method correctly" do allow_any_instance_of(http_request_class).to receive(:existing_method).and_return("foo") expect(http_request_class.new.existing_method).to eq "foo" end it "mocks the method correctly" do expect_any_instance_of(http_request_class).to receive(:existing_method).and_return("foo") expect(http_request_class.new.existing_method).to eq "foo" end end context "when used after the test has finished" do it "restores the original behavior of a stubbed method" do allow_any_instance_of(klass).to receive(:existing_method).and_return(:stubbed_return_value) instance = klass.new expect(instance.existing_method).to eq :stubbed_return_value verify_all expect(instance.existing_method).to eq :existing_method_return_value end it "does not restore a stubbed method not originally implemented in the class" do allow_any_instance_of(::AnyInstanceSpec::ChildClass).to receive(:foo).and_return :result expect(::AnyInstanceSpec::ChildClass.new.foo).to eq :result reset_all expect(::AnyInstanceSpec::ChildClass.new.foo).to eq 'bar' end it "restores the original behaviour, even if the expectation fails" do expect_any_instance_of(klass).to receive(:existing_method).with(1).and_return(:stubbed_return_value) instance = klass.new begin instance.existing_method verify_all rescue RSpec::Mocks::MockExpectationError end reset_all expect(instance.existing_method).to eq :existing_method_return_value end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/and_wrap_original_spec.rb0000664000000000000000000000672214557670305027234 0ustar rootrootRSpec.describe "and_wrap_original" do context "on a partial double" do let(:klass) do Class.new do def results (1..100).to_a end end end let(:instance) { klass.new } shared_examples "using and_wrap_original" do it "allows us to modify the results of the original method" do expect { allow_it.to receive(:results).and_wrap_original do |m| m.call.first(10) end }.to change { instance.results.size }.from(100).to(10) end it "raises a name error if the method does not exist" do expect { allow_it.to receive(:no_results).and_wrap_original { |m| m.call } instance.no_results }.to raise_error NameError end it "passes along the original method" do passed_method = nil original_method = instance.method(:results) allow_it.to receive(:results).and_wrap_original { |m| passed_method = m } instance.results expect(passed_method.call).to eq(original_method.call) end it "passes along the message arguments" do values = nil allow_it.to receive(:results).and_wrap_original { |_, *args| values = args } instance.results(1, 2, 3) expect(values).to eq [1, 2, 3] end it "passes along any supplied block" do value = nil allow_it.to receive(:results).and_wrap_original { |&b| value = b } instance.results(&(block = proc {})) expect(value).to eq block end it "ignores previous stubs" do allow_it.to receive(:results) { "results" } allow_it.to receive(:results).and_wrap_original { |m| m.call } expect(instance.results).to_not eq "results" end it "can be constrained by specific arguments" do allow_it.to receive(:results) { :all } allow_it.to receive(:results).with(5).and_wrap_original { |m, n| m.call.first(n) } expect(instance.results 5).to eq [1, 2, 3, 4, 5] expect(instance.results).to eq :all end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it "works for methods that accept keyword arguments, using a keyword argument block" do def instance.foo(bar: nil); bar; end allow(instance).to receive(:foo).and_wrap_original { |m, **kwargs| m.call(**kwargs) } expect(instance.foo(bar: "baz")).to eq("baz") end CODE end end describe "allow(...).to receive(...).and_wrap_original" do it_behaves_like "using and_wrap_original" do let(:allow_it) { allow(instance) } end end describe "allow_any_instance_of(...).to receive(...).and_wrap_original" do it_behaves_like "using and_wrap_original" do let(:allow_it) { allow_any_instance_of(klass) } end end end context "on a pure test double" do let(:instance) { double :my_method => :my_value } it 'raises an error' do mock_expectation = allow(instance).to receive(:my_method) expect { mock_expectation.and_wrap_original }.to raise_error(/pure test double.*and_wrap_original.*partial double/i) end it 'raises an error even if the double object responds to the message' do mock_expectation = allow(instance).to receive(:inspect) expect { mock_expectation.and_wrap_original }.to raise_error(/pure test double.*and_wrap_original.*partial double/i) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/to_ary_spec.rb0000664000000000000000000000235714557670305025052 0ustar rootrootRSpec.describe "a double receiving to_ary" do shared_examples "to_ary" do it "can be overridden with a stub" do allow(obj).to receive(:to_ary) { :non_nil_value } expect(obj.to_ary).to be(:non_nil_value) end it "responds when overridden" do allow(obj).to receive(:to_ary) { :non_nil_value } expect(obj).to respond_to(:to_ary) end it "supports Array#flatten" do dbl = double('foo') expect([dbl].flatten).to eq([dbl]) end end context "double as_null_object" do let(:obj) { double('obj').as_null_object } include_examples "to_ary" it "does respond to to_ary" do expect(obj).to respond_to(:to_ary) end it "does respond to to_a" do expect(obj).to respond_to(:to_a) end it "returns nil" do expect(obj.to_ary).to eq nil end end context "double without as_null_object" do let(:obj) { double('obj') } include_examples "to_ary" it "doesn't respond to to_ary" do expect(obj).not_to respond_to(:to_ary) end it "doesn't respond to to_a", :if => (RUBY_VERSION.to_f > 1.8) do expect(obj).not_to respond_to(:to_a) end it "raises " do expect { obj.to_ary }.to raise_error(NoMethodError) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/formatting_spec.rb0000664000000000000000000000670214557670305025725 0ustar rootrootrequire 'rspec/matchers/fail_matchers' require 'support/doubled_classes' RSpec.describe "Test doubles format well in failure messages" do include RSpec::Matchers::FailMatchers include RSpec::Support::Spec::DiffHelpers RSpec::Matchers.define :format_in_failures_as do |expected| match do |dbl| values_match?(expected, actual_formatting(dbl)) end def actual_formatting(double) expect(1).to eq(double) rescue RSpec::Expectations::ExpectationNotMetError => e e.message[/expected: (.*)$/, 1] else raise "Did not fail as expected" end end describe "`double`" do context "with a name" do specify '#' do expect(double "Book").to format_in_failures_as('#') end it 'formats the name as a symbol if that was how it was provided' do expect(double :book).to format_in_failures_as('#') end end context "without a name" do specify '#' do expect(double).to format_in_failures_as('#') end end it 'avoids sending `instance_variable_get` to the double as it may be stubbed' do dbl = double("Book") expect(dbl).not_to receive(:instance_variable_get) expect(dbl).to format_in_failures_as('#') end end describe "`instance_double(SomeClass)`" do context "with a name" do specify '#' do expect(instance_double(LoadedClass, "Book")).to format_in_failures_as('#') end end context "without a name" do specify '#' do expect(instance_double(LoadedClass)).to format_in_failures_as('#') end end it 'avoids sending `instance_variable_get` to the double as it may be stubbed' do dbl = instance_double(LoadedClass, "Book") expect(dbl).not_to receive(:instance_variable_get) expect(dbl).to format_in_failures_as('#') end end describe "`class_double(SomeClass)`" do context "with a name" do specify '#' do expect(class_double(LoadedClass, "Book")).to format_in_failures_as('#') end end context "without a name" do specify '#' do expect(class_double(LoadedClass)).to format_in_failures_as('#') end end end describe "`object_double([])`" do context "with a name" do specify '#' do expect(object_double([], "Name")).to format_in_failures_as('#') end end context "without a name" do specify '#' do expect(object_double([])).to format_in_failures_as('#') end end end it 'formats the doubles when they appear in data structures and diffs' do allow(RSpec::Expectations.configuration).to receive(:color?).and_return(false) foo = double("Foo") bar = double("Bar") expect { expect([foo]).to include(bar) }.to fail_with(<<-EOS.gsub(/^\s+\|/, '')) |expected [#] to include # |Diff: |@@ #{one_line_header} @@ |-[#] |+[#] EOS end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/double_spec.rb0000664000000000000000000007462714557670305025040 0ustar rootrootmodule RSpec module Mocks RSpec.describe Double do before(:each) { @double = double("test double") } after(:each) { reset @double } it "has method_missing as private" do expect(RSpec::Mocks::Double.private_instance_methods).to include_method(:method_missing) end it "does not respond_to? method_missing (because it's private)" do expect(RSpec::Mocks::Double.new).not_to respond_to(:method_missing) end it "uses 'Double' in failure messages" do dbl = double('name') expect { dbl.foo }.to raise_error(/# received/) end it "hides internals in its inspect representation" do m = double('cup') expect(m.inspect).to eq('#') end it 'does not blow up when resetting standard object methods' do dbl = double(:tainted? => true) expect(dbl.tainted?).to eq(true) expect { reset dbl }.not_to raise_error end it 'does not get string vs symbol messages confused' do dbl = double("foo" => 1) allow(dbl).to receive(:foo).and_return(2) expect(dbl.foo).to eq(2) expect { reset dbl }.not_to raise_error end it "generates the correct error when an unfulfilled expectation uses an unused double as a `with` argument" do expect { a = double('a') b = double('b') expect(a).to receive(:append).with(b) verify_all }.to fail end it 'allows string representation of methods in constructor' do dbl = double('foo' => 1) expect(dbl.foo).to eq(1) end it 'allows setter methods to be stubbed' do dbl = double('foo=' => 1) # Note the specified return value is thrown away. This is a Ruby semantics # thing. You cannot change the return value of assignment. expect(dbl.foo = "bar").to eq("bar") end it 'allows `class` to be stubbed even when `any_instance` has already been used' do # See https://github.com/rspec/rspec-mocks/issues/687 # The infinite recursion code path was only triggered when there were # active any instance recorders in the current example, so we make one here. allow_any_instance_of(Object).to receive(:bar).and_return(2) dbl = double(:foo => 1, :class => String) expect(dbl.foo).to eq(1) expect(dbl.class).to eq(String) end it 'allows `send` to be stubbed' do dbl = double allow(dbl).to receive(:send).and_return("received") expect(dbl.send(:some_msg)).to eq("received") end it "reports line number of expectation of unreceived message" do expected_error_line = __LINE__; expect(@double).to receive(:wont_happen).with("x", 3) expect { verify @double }.to fail { |e| # NOTE - this regexp ended w/ $, but jruby adds extra info at the end of the line expect(e.backtrace[0]).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/) } end it "reports line number of expectation of unreceived message after a message expectation after similar stub" do allow(@double).to receive(:wont_happen) expected_error_line = __LINE__; expect(@double).to receive(:wont_happen).with("x", 3) expect { verify @double }.to fail { |e| # NOTE - this regexp ended w/ $, but jruby adds extra info at the end of the line expect(e.backtrace[0]).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/) } end it "passes when not receiving message specified as not to be received" do expect(@double).not_to receive(:not_expected) verify @double end it "prevents confusing double-negative expressions involving `never`" do expect { expect(@double).not_to receive(:not_expected).never }.to raise_error(/trying to negate it again/) end it "warns when `and_return` is called on a negative expectation" do expect { expect(@double).not_to receive(:do_something).and_return(1) }.to raise_error(/not supported/) expect { expect(@double).not_to receive(:do_something).and_return(1) }.to raise_error(/not supported/) expect { expect(@double).to receive(:do_something).never.and_return(1) }.to raise_error(/not supported/) end it "passes when receiving message specified as not to be received with different args" do expect(@double).not_to receive(:message).with("unwanted text") expect(@double).to receive(:message).with("other text") @double.message "other text" verify @double end it "fails when receiving message specified as not to be received" do expect(@double).not_to receive(:not_expected) expect { @double.not_expected }.to raise_error( RSpec::Mocks::MockExpectationError, %Q|(Double "test double").not_expected(no args)\n expected: 0 times with any arguments\n received: 1 time| ) end it "fails when receiving message specified as not to be received with args" do expect(@double).not_to receive(:not_expected).with("unexpected text") expect { @double.not_expected("unexpected text") }.to raise_error( RSpec::Mocks::MockExpectationError, %Q|(Double "test double").not_expected("unexpected text")\n expected: 0 times with arguments: ("unexpected text")\n received: 1 time with arguments: ("unexpected text")| ) end it "fails when array arguments do not match" do expect(@double).not_to receive(:not_expected).with(["do not want"]) expect { @double.not_expected(["do not want"]) }.to raise_error( RSpec::Mocks::MockExpectationError, %Q|(Double "test double").not_expected(["do not want"])\n expected: 0 times with arguments: (["do not want"])\n received: 1 time with arguments: (["do not want"])| ) end context "when specifying a message should not be received with specific args" do context "using `expect(...).not_to receive()`" do it 'passes when receiving the message with different args' do expect(@double).not_to receive(:not_expected).with("unexpected text") @double.not_expected "really unexpected text" verify @double end end context "using `expect(...).to receive().never`" do it 'passes when receiving the message with different args' do expect(@double).to receive(:not_expected).with("unexpected text").never @double.not_expected "really unexpected text" verify @double end end end it 'does not get confused when a negative expectation is used with a string and symbol message' do allow(@double).to receive(:foo) { 3 } expect(@double).not_to receive(:foo).with(1) expect(@double).not_to receive("foo").with(2) expect(@double.foo).to eq(3) verify @double end it 'does not get confused when a positive expectation is used with a string and symbol message' do expect(@double).to receive(:foo).with(1) expect(@double).to receive("foo").with(2) @double.foo(1) @double.foo(2) verify @double end it "allows parameter as return value" do expect(@double).to receive(:something).with("a", "b", "c").and_return("booh") expect(@double.something("a", "b", "c")).to eq "booh" verify @double end it "returns the previously stubbed value if no return value is set" do allow(@double).to receive(:something).with("a", "b", "c").and_return(:stubbed_value) expect(@double).to receive(:something).with("a", "b", "c") expect(@double.something("a", "b", "c")).to eq :stubbed_value verify @double end it "returns nil if no return value is set and there is no previously stubbed value" do expect(@double).to receive(:something).with("a", "b", "c") expect(@double.something("a", "b", "c")).to be_nil verify @double end it "raises exception if args don't match when method called" do expect(@double).to receive(:something).with("a", "b", "c").and_return("booh") expect { @double.something("a", "d", "c") }.to fail_with "# received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")" end describe "even when a similar expectation with different arguments exist" do it "raises exception if args don't match when method called, correctly reporting the offending arguments" do expect(@double).to receive(:something).with("a", "b", "c").once expect(@double).to receive(:something).with("z", "x", "c").once expect { @double.something("a", "b", "c") @double.something("z", "x", "g") }.to fail_with "# received :something with unexpected arguments\n expected: (\"z\", \"x\", \"c\")\n got: (\"z\", \"x\", \"g\")" end end it "raises exception if args don't match when method called even when the method is stubbed" do allow(@double).to receive(:something) expect(@double).to receive(:something).with("a", "b", "c") expect { @double.something("a", "d", "c") verify @double }.to fail_with "# received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")" end it "raises exception if args don't match when method called even when using null_object" do @double = double("test double").as_null_object expect(@double).to receive(:something).with("a", "b", "c") expect { @double.something("a", "d", "c") verify @double }.to fail_with "# received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")" end describe 'with a method that has a default argument' do it "raises an exception if the arguments don't match when the method is called, correctly reporting the offending arguments" do def @double.method_with_default_argument(_={}); end expect(@double).to receive(:method_with_default_argument).with({}) expect { @double.method_with_default_argument(nil) verify @double }.to fail_with a_string_starting_with("# received :method_with_default_argument with unexpected arguments\n expected: ({})\n got: (nil)") end end it "fails if unexpected method called" do expect { @double.something("a", "b", "c") }.to fail_with "# received unexpected message :something with (\"a\", \"b\", \"c\")" end it "uses block for expectation if provided" do expect(@double).to receive(:something) do | a, b | expect(a).to eq "a" expect(b).to eq "b" "booh" end expect(@double.something("a", "b")).to eq "booh" verify @double end it "fails if expectation block fails" do expect(@double).to receive(:something) do |bool| expect(bool).to be_truthy end expect { @double.something false }.to raise_error(RSpec::Expectations::ExpectationNotMetError) end it "is wrappable in an array" do with_isolated_stderr do expect(Array(@double)).to eq([@double]) end end it "is wrappable in an array when a null object" do with_isolated_stderr do expect(Array(@double.as_null_object)).to eq [@double] end end it "responds to to_ary as a null object" do expect(@double.as_null_object.to_ary).to eq nil end it "responds to to_a as a null object" do if RUBY_VERSION.to_f > 1.8 expect(@double.as_null_object.to_a).to eq nil else with_isolated_stderr do expect(@double.as_null_object.to_a).to eq [@double] end end end it "passes proc to expectation block without an argument" do expect(@double).to receive(:foo) { |&block| expect(block.call).to eq(:bar) } @double.foo { :bar } end it "passes proc to expectation block with an argument" do expect(@double).to receive(:foo) { |_, &block| expect(block.call).to eq(:bar) } @double.foo(:arg) { :bar } end it "passes proc to stub block without an argument" do allow(@double).to receive(:foo) { |&block| expect(block.call).to eq(:bar) } @double.foo { :bar } end it "passes proc to stub block with an argument" do allow(@double).to receive(:foo) { |_, &block| expect(block.call).to eq(:bar) } @double.foo(:arg) { :bar } end it "fails right away when method defined as never is received" do expect(@double).to receive(:not_expected).never expect { @double.not_expected }. to fail_with %Q|(Double "test double").not_expected(no args)\n expected: 0 times with any arguments\n received: 1 time| end it "raises RuntimeError by default" do expect(@double).to receive(:something).and_raise expect { @double.something }.to raise_error(RuntimeError) end it "raises RuntimeError with a message by default" do expect(@double).to receive(:something).and_raise("error message") expect { @double.something }.to raise_error(RuntimeError, "error message") end it "raises an exception of a given type without an error message" do expect(@double).to receive(:something).and_raise(StandardError) expect { @double.something }.to raise_error(StandardError) end it "raises an exception of a given type with a message" do expect(@double).to receive(:something).and_raise(RuntimeError, "error message") expect { @double.something }.to raise_error(RuntimeError, "error message") end it "raises a given instance of an exception" do expect(@double).to receive(:something).and_raise(RuntimeError.new("error message")) expect { @double.something }.to raise_error(RuntimeError, "error message") end class OutOfGas < StandardError attr_reader :amount, :units def initialize(amount, units) @amount = amount @units = units end end it "raises a given instance of an exception with arguments other than the standard 'message'" do expect(@double).to receive(:something).and_raise(OutOfGas.new(2, :oz)) expect { @double.something }.to raise_error(OutOfGas) { |e| expect(e.amount).to eq 2 expect(e.units).to eq :oz } end it "does not raise when told to if args dont match" do expect(@double).to receive(:something).with(2).and_raise(RuntimeError) expect { @double.something 1 }.to fail end it "throws when told to" do expect(@double).to receive(:something).and_throw(:blech) expect { @double.something }.to throw_symbol(:blech) end it "ignores args on any args" do expect(@double).to receive(:something).at_least(:once).with(any_args) @double.something @double.something 1 @double.something "a", 2 @double.something [], {}, "joe", 7 verify @double end it "fails on no args if any args received" do expect(@double).to receive(:something).with(no_args) expect { @double.something 1 }.to fail_with "# received :something with unexpected arguments\n expected: (no args)\n got: (1)" end it "fails when args are expected but none are received" do expect(@double).to receive(:something).with(1) expect { @double.something }.to fail_with "# received :something with unexpected arguments\n expected: (1)\n got: (no args)" end it "returns value from block by default" do allow(@double).to receive(:method_that_yields).and_yield value = @double.method_that_yields { :returned_obj } expect(value).to eq :returned_obj verify @double end it "yields 0 args to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield a = nil @double.yield_back { |*x| a = x } expect(a).to eq [] verify @double end it "yields 0 args multiple times to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).once.with(no_args).once.and_yield. and_yield b = [] @double.yield_back { |*a| b << a } expect(b).to eq [[], []] verify @double end it "yields one arg to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield(99) a = nil @double.yield_back { |*x| a = x } expect(a).to eq [99] verify @double end it "yields one arg 3 times consecutively to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).once.with(no_args).once.and_yield(99). and_yield(43). and_yield("something fruity") b = [] @double.yield_back { |*a| b << a } expect(b).to eq [[99], [43], ["something fruity"]] verify @double end it "yields many args to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield(99, 27, "go") a = nil @double.yield_back { |*x| a = x } expect(a).to eq [99, 27, "go"] verify @double end it "yields many args 3 times consecutively to blocks that take a variable number of arguments" do expect(@double).to receive(:yield_back).once.with(no_args).once.and_yield(99, :green, "go"). and_yield("wait", :amber). and_yield("stop", 12, :red) b = [] @double.yield_back { |*a| b << a } expect(b).to eq [[99, :green, "go"], ["wait", :amber], ["stop", 12, :red]] verify @double end it "yields single value" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield(99) a = nil @double.yield_back { |x| a = x } expect(a).to eq 99 verify @double end it "yields single value 3 times consecutively" do expect(@double).to receive(:yield_back).once.with(no_args).once.and_yield(99). and_yield(43). and_yield("something fruity") b = [] @double.yield_back { |a| b << a } expect(b).to eq [99, 43, "something fruity"] verify @double end it "yields two values" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield('wha', 'zup') a, b = nil @double.yield_back { |x, y| a = x; b = y } expect(a).to eq 'wha' expect(b).to eq 'zup' verify @double end it "yields two values 3 times consecutively" do expect(@double).to receive(:yield_back).once.with(no_args).once.and_yield('wha', 'zup'). and_yield('not', 'down'). and_yield(14, 65) c = [] @double.yield_back { |a, b| c << [a, b] } expect(c).to eq [%w[wha zup], %w[not down], [14, 65]] verify @double end it "fails when calling yielding method with wrong arity" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield('wha', 'zup') expect { @double.yield_back { |_| } }.to fail_with "# yielded |\"wha\", \"zup\"| to block with arity of 1" end if kw_args_supported? it 'fails when calling yielding method with invalid kw args' do expect(@double).to receive(:yield_back).and_yield(:x => 1, :y => 2) expect { eval("@double.yield_back { |x: 1| }") }.to fail_with '# yielded |{:x=>1, :y=>2}| to block with optional keyword args (:x)' end end it "fails when calling yielding method consecutively with wrong arity" do expect(@double).to receive(:yield_back).once.with(no_args).and_yield('wha', 'zup'). and_yield('down'). and_yield(14, 65) expect { c = [] @double.yield_back { |a, b| c << [a, b] } }.to fail_with "# yielded |\"down\"| to block with arity of 2" end it "fails when calling yielding method without block" do expect(@double).to receive(:yield_back).with(no_args).once.and_yield('wha', 'zup') expect { @double.yield_back }.to fail_with "# asked to yield |[\"wha\", \"zup\"]| but no block was passed" end it "is able to double send" do expect(@double).to receive(:send).with(any_args) @double.send 'hi' verify @double end it "is able to raise from method calling yielding double" do expect(@double).to receive(:yield_me).and_yield 44 expect { @double.yield_me do |_| raise "Bang" end }.to raise_error(StandardError, "Bang") verify @double end it "clears expectations after verify" do expect(@double).to receive(:foobar) @double.foobar verify @double expect { @double.foobar }.to fail_with %q|# received unexpected message :foobar with (no args)| end it "restores objects to their original state on rspec_reset" do dbl = double("this is a double") expect(dbl).to receive(:blah) reset dbl verify dbl # should throw if reset didn't work end it "temporarily replaces a method stub on a double" do allow(@double).to receive(:msg).and_return(:stub_value) expect(@double).to receive(:msg).with(:arg).and_return(:double_value) expect(@double.msg(:arg)).to equal(:double_value) expect(@double.msg).to equal(:stub_value) expect(@double.msg).to equal(:stub_value) verify @double end it "does not require a different signature to replace a method stub" do allow(@double).to receive(:msg).and_return(:stub_value) expect(@double).to receive(:msg).and_return(:double_value) expect(@double.msg(:arg)).to equal(:double_value) expect(@double.msg).to equal(:stub_value) expect(@double.msg).to equal(:stub_value) verify @double end it "raises an error when a previously stubbed method has a negative expectation" do allow(@double).to receive(:msg).and_return(:stub_value) expect(@double).not_to receive(:msg) expect { @double.msg(:arg) }.to fail end it "temporarily replaces a method stub on a non-double" do non_double = Object.new allow(non_double).to receive(:msg).and_return(:stub_value) expect(non_double).to receive(:msg).with(:arg).and_return(:double_value) expect(non_double.msg(:arg)).to equal(:double_value) expect(non_double.msg).to equal(:stub_value) expect(non_double.msg).to equal(:stub_value) verify non_double end it "returns the stubbed value when no new value specified" do allow(@double).to receive(:msg).and_return(:stub_value) expect(@double).to receive(:msg) expect(@double.msg).to equal(:stub_value) verify @double end it "returns the stubbed value when stubbed with args and no new value specified" do allow(@double).to receive(:msg).with(:arg).and_return(:stub_value) expect(@double).to receive(:msg).with(:arg) expect(@double.msg(:arg)).to equal(:stub_value) verify @double end it "does not mess with the stub's yielded values when also doubleed" do allow(@double).to receive(:yield_back).and_yield(:stub_value) expect(@double).to receive(:yield_back).and_yield(:double_value) @double.yield_back { |v| expect(v).to eq :double_value } @double.yield_back { |v| expect(v).to eq :stub_value } verify @double end it "can yield multiple times when told to do so" do allow(@double).to receive(:foo).and_yield(:stub_value) expect(@double).to receive(:foo).and_yield(:first_yield).and_yield(:second_yield) expect { |b| @double.foo(&b) }.to yield_successive_args(:first_yield, :second_yield) expect { |b| @double.foo(&b) }.to yield_with_args(:stub_value) verify @double end it "assigns stub return values" do dbl = RSpec::Mocks::Double.new('name', :message => :response) expect(dbl.message).to eq :response end describe "a double message receiving a block" do before(:each) do @double = double("double") @calls = 0 end def add_call @calls += 1 end it "supports a block passed to `receive` for `expect`" do expect(@double).to receive(:foo) { add_call } @double.foo expect(@calls).to eq 1 end it "supports a block passed to `receive` for `expect` after a similar stub" do allow(@double).to receive(:foo).and_return(:bar) expect(@double).to receive(:foo) { add_call } @double.foo expect(@calls).to eq 1 end it "calls the block after #once" do expect(@double).to receive(:foo).once { add_call } @double.foo expect(@calls).to eq 1 end it "calls the block after #twice" do expect(@double).to receive(:foo).twice { add_call } @double.foo @double.foo expect(@calls).to eq 2 end it "calls the block after #times" do expect(@double).to receive(:foo).exactly(10).times { add_call } (1..10).each { @double.foo } expect(@calls).to eq 10 end it "calls the block after #ordered" do expect(@double).to receive(:foo).ordered { add_call } expect(@double).to receive(:bar).ordered { add_call } @double.foo @double.bar expect(@calls).to eq 2 end end describe 'string representation generated by #to_s' do it 'does not contain < because that might lead to invalid HTML in some situations' do dbl = double("Dog") valid_html_str = "#{dbl}" expect(valid_html_str).not_to include('<') end end describe "#to_str", :unless => RUBY_VERSION == '1.9.2' do it "should not respond to #to_str to avoid being coerced to strings by the runtime" do dbl = double("Foo") expect { dbl.to_str }.to raise_error( RSpec::Mocks::MockExpectationError, '# received unexpected message :to_str with (no args)') end end describe "double created with no name" do it "does not use a name in a failure message" do dbl = double expect { dbl.foo }.to raise_error.with_message(a_string_including("# received")) end it "does respond to initially stubbed methods" do dbl = double(:foo => "woo", :bar => "car") expect(dbl.foo).to eq "woo" expect(dbl.bar).to eq "car" end end describe "==" do it "sends '== self' to the comparison object" do first = double('first') second = double('second') expect(first).to receive(:==).with(second) second == first end end describe "with" do before { @double = double('double') } context "with args" do context "with matching args" do it "passes" do expect(@double).to receive(:foo).with('bar') @double.foo('bar') end end context "with non-matching args" do it "fails" do expect(@double).to receive(:foo).with('bar') expect do @double.foo('baz') end.to fail reset @double end end context "with non-matching doubles" do it "fails" do d1 = double('1') d2 = double('2') expect(@double).to receive(:foo).with(d1) expect do @double.foo(d2) end.to fail reset @double end end context "with non-matching doubles as_null_object" do it "fails" do d1 = double('1').as_null_object d2 = double('2').as_null_object expect(@double).to receive(:foo).with(d1) expect do @double.foo(d2) end.to fail reset @double end end end context "with a block" do context "with matching args" do it "returns the result of the block" do expect(@double).to receive(:foo).with('bar') { 'baz' } expect(@double.foo('bar')).to eq('baz') end end context "with non-matching args" do it "fails" do expect(@double).to receive(:foo).with('bar') { 'baz' } expect do expect(@double.foo('wrong')).to eq('baz') end.to raise_error(/received :foo with unexpected arguments/) reset @double end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/mock_expectation_error_spec.rb0000664000000000000000000000057114557670305030316 0ustar rootrootmodule RSpec module Mocks RSpec.describe 'MockExpectationError' do class Foo def self.foo bar rescue StandardError end end it 'is not caught by StandardError rescue blocks' do expect(Foo).not_to receive(:bar) expect_fast_failure_from(Foo) do Foo.foo end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb0000664000000000000000000000641314557670305032361 0ustar rootrootmodule RSpec module Mocks RSpec.describe ".allow_message" do let(:subject) { Object.new } it "sets up basic message allowance" do expect { ::RSpec::Mocks.allow_message(subject, :basic) }.to change { subject.respond_to?(:basic) }.to(true) expect(subject.basic).to eq(nil) end it "sets up message allowance with params and return value" do expect { ::RSpec::Mocks.allow_message(subject, :x).with(:in).and_return(:out) }.to change { subject.respond_to?(:x) }.to(true) expect(subject.x(:in)).to eq(:out) end it "supports block implementations" do ::RSpec::Mocks.allow_message(subject, :message) { :value } expect(subject.message).to eq(:value) end it "does not set an expectation that the message will be received" do ::RSpec::Mocks.allow_message(subject, :message) expect { verify subject }.not_to raise_error end it 'does not get confused when the string and symbol message form are both used' do ::RSpec::Mocks.allow_message(subject, :foo).with(1) { :a } ::RSpec::Mocks.allow_message(subject, "foo").with(2) { :b } expect(subject.foo(1)).to eq(:a) expect(subject.foo(2)).to eq(:b) reset subject end context 'when target cannot be proxied' do it 'raises ArgumentError with message' do expect { ::RSpec::Mocks.allow_message(:subject, :foo) { :a } }.to raise_error(ArgumentError) end end end RSpec.describe ".expect_message" do let(:subject) { Object.new } it "sets up basic message expectation, verifies as uncalled" do expect { ::RSpec::Mocks.expect_message(subject, :basic) }.to change { subject.respond_to?(:basic) }.to(true) expect { verify subject }.to fail end it "fails if never is specified and the message is called" do expect_fast_failure_from(subject, /expected.*0 times/) do ::RSpec::Mocks.expect_message(subject, :foo).never subject.foo end end it "sets up basic message expectation, verifies as called" do ::RSpec::Mocks.expect_message(subject, :basic) subject.basic verify subject end it "sets up message expectation with params and return value" do ::RSpec::Mocks.expect_message(subject, :msg).with(:in).and_return(:out) expect(subject.msg(:in)).to eq(:out) verify subject end it "accepts a block implementation for the expected message" do ::RSpec::Mocks.expect_message(subject, :msg) { :value } expect(subject.msg).to eq(:value) verify subject end it 'does not get confused when the string and symbol message form are both used' do ::RSpec::Mocks.expect_message(subject, :foo).with(1) ::RSpec::Mocks.expect_message(subject, "foo").with(2) subject.foo(1) subject.foo(2) verify subject end context 'when target cannot be proxied' do it 'raises ArgumentError with message' do expect { ::RSpec::Mocks.expect_message(:subject, :foo) { :a } }.to raise_error(ArgumentError) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/syntax_spec.rb0000664000000000000000000000030614557670305025073 0ustar rootrootmodule RSpec RSpec.describe Mocks do it "does not inadvertently define BasicObject on 1.8", :if => RUBY_VERSION.to_f < 1.9 do expect(defined?(::BasicObject)).to be nil end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/serialization_spec.rb0000664000000000000000000000520414557670305026424 0ustar rootrootmodule RSpec module Mocks RSpec.describe "Serialization of mocked objects" do include_context "with monkey-patched marshal" class SerializableObject < Struct.new(:foo, :bar); end def self.with_yaml_loaded(&block) context 'with YAML loaded' do module_exec(&block) end end def self.without_yaml_loaded(&block) context 'without YAML loaded' do before do # We can't really unload yaml, but we can fake it here... hide_const("YAML") Struct.class_exec do alias __old_to_yaml to_yaml undef to_yaml end end module_exec(&block) after do Struct.class_exec do alias to_yaml __old_to_yaml undef __old_to_yaml end end end end let(:serializable_object) { RSpec::Mocks::SerializableObject.new(7, "something") } def set_stub allow(serializable_object).to receive_messages(:bazz => 5) end shared_examples 'normal YAML serialization' do it 'serializes to yaml the same with and without stubbing, using #to_yaml' do expect { set_stub }.to_not change { serializable_object.to_yaml } end it 'serializes to yaml the same with and without stubbing, using YAML.dump' do expect { set_stub }.to_not change { ::YAML.dump(serializable_object) } end end with_yaml_loaded do compiled_with_psych = begin require 'psych' true rescue LoadError false end if compiled_with_psych context 'using Syck as the YAML engine' do before(:each) { ::YAML::ENGINE.yamler = 'syck' } around(:each) { |example| with_isolated_stderr(&example) } it_behaves_like 'normal YAML serialization' end if defined?(::YAML::ENGINE) context 'using Psych as the YAML engine' do before(:each) { ::YAML::ENGINE.yamler = 'psych' } if defined?(::YAML::ENGINE) it_behaves_like 'normal YAML serialization' end else it_behaves_like 'normal YAML serialization' end end without_yaml_loaded do it 'does not add #to_yaml to the stubbed object' do expect(serializable_object).not_to respond_to(:to_yaml) set_stub expect(serializable_object).not_to respond_to(:to_yaml) end end it 'marshals the same with and without stubbing' do expect { set_stub }.to_not change { Marshal.dump(serializable_object) } end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/instance_method_stasher_spec.rb0000664000000000000000000000457014557670305030451 0ustar rootrootmodule RSpec module Mocks RSpec.describe InstanceMethodStasher do class ExampleClass def hello :hello_defined_on_class end end def singleton_class_for(obj) class << obj; self; end end def stasher_for(obj, method_name) InstanceMethodStasher.new(obj, method_name) end it "stashes the current implementation of an instance method so it can be temporarily replaced" do obj = Object.new def obj.hello; :hello_defined_on_singleton_class; end; stashed_method = stasher_for(obj, :hello) stashed_method.stash with_isolated_stderr { def obj.hello; :overridden_hello; end } expect(obj.hello).to eql :overridden_hello stashed_method.restore expect(obj.hello).to eql :hello_defined_on_singleton_class end it "stashes private instance methods" do obj = Object.new def obj.hello; :hello_defined_on_singleton_class; end; singleton_class_for(obj).__send__(:private, :hello) stashed_method = stasher_for(obj, :hello) stashed_method.stash with_isolated_stderr { def obj.hello; :overridden_hello; end } stashed_method.restore expect(obj.send(:hello)).to eql :hello_defined_on_singleton_class end it "only stashes methods directly defined on the given class, not its ancestors" do obj = ExampleClass.new stashed_method = stasher_for(obj, :hello) stashed_method.stash def obj.hello; :overridden_hello; end; expect(obj.hello).to eql :overridden_hello stashed_method.restore expect(obj.hello).to eql :overridden_hello end it "does not unnecessarily create obfuscated aliased methods", :if => (RUBY_VERSION.to_f > 1.8) do obj = Object.new def obj.hello; :hello_defined_on_singleton_class; end; stashed_method = stasher_for(obj, :hello) stashed_method.stash expect(obj.methods.grep(/rspec/)).to eq([]) end it "undefines the original method", :if => (RUBY_VERSION.to_f > 1.8) do obj = Object.new def obj.hello; :hello_defined_on_singleton_class; end; stashed_method = stasher_for(obj, :hello) stashed_method.stash expect(obj.methods).not_to include(:hello) expect(obj).not_to respond_to(:hello) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/example_methods_spec.rb0000664000000000000000000000236414557670305026731 0ustar rootrootmodule RSpec module Mocks RSpec.describe ExampleMethods do it 'does not define private helper methods since it gets included into a ' \ 'namespace where users define methods and could inadvertently overwrite ' \ 'them' do expect(ExampleMethods.private_instance_methods).to eq([]) end def test_extend_on_new_object(*to_extend, &block) host = Object.new to_extend.each { |mod| host.extend mod } host.instance_eval do dbl = double expect(dbl).to receive(:foo).at_least(:once).and_return(1) dbl.foo instance_exec(dbl, &block) if block end end it 'works properly when extended onto an object' do test_extend_on_new_object ExampleMethods end it 'works properly when extended onto an object that has previous extended `RSpec::Matchers`' do test_extend_on_new_object RSpec::Matchers, ExampleMethods do |dbl| expect(dbl.foo).to eq(1) end end it 'works properly when extended onto an object that later extends `RSpec::Matchers`' do test_extend_on_new_object ExampleMethods, RSpec::Matchers do |dbl| expect(dbl.foo).to eq(1) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/stub_implementation_spec.rb0000664000000000000000000000757014557670305027641 0ustar rootrootmodule RSpec module Mocks RSpec.describe "stub implementation" do describe "with no args" do it "execs the block when called" do obj = double allow(obj).to receive(:foo) { :bar } expect(obj.foo).to eq :bar end end describe "with one arg" do it "execs the block with that arg when called" do obj = double allow(obj).to receive(:foo) { |given| given } expect(obj.foo(:bar)).to eq :bar end end describe "with variable args" do it "execs the block when called" do obj = double allow(obj).to receive(:foo) { |*given| given.first } expect(obj.foo(:bar)).to eq :bar end end end RSpec.describe "unstubbing with `and_call_original`" do it "replaces the stubbed method with the original method" do obj = Object.new def obj.foo; :original; end allow(obj).to receive(:foo) allow(obj).to receive(:foo).and_call_original expect(obj.foo).to eq :original end it "removes all stubs with the supplied method name" do obj = Object.new def obj.foo; :original; end allow(obj).to receive(:foo).with(1) allow(obj).to receive(:foo).with(2) allow(obj).to receive(:foo).and_call_original expect(obj.foo).to eq :original end it "does not remove any expectations with the same method name" do obj = Object.new def obj.foo; :original; end expect(obj).to receive(:foo).with(3).and_return(:three) allow(obj).to receive(:foo).with(1) allow(obj).to receive(:foo).with(2) allow(obj).to receive(:foo).and_call_original expect(obj.foo(3)).to eq :three end shared_examples_for "stubbing `new` on class objects" do it "restores the correct implementations when stubbed and unstubbed on a parent and child class" do parent = stub_const("Parent", Class.new) child = stub_const("Child", Class.new(parent)) allow(parent).to receive(:new) allow(child).to receive(:new) allow(parent).to receive(:new).and_call_original allow(child).to receive(:new).and_call_original expect(parent.new).to be_an_instance_of parent expect(child.new).to be_an_instance_of child end it "restores the correct implementations when stubbed and unstubbed on a grandparent and grandchild class" do grandparent = stub_const("GrandParent", Class.new) parent = stub_const("Parent", Class.new(grandparent)) child = stub_const("Child", Class.new(parent)) allow(grandparent).to receive(:new) allow(child).to receive(:new) allow(grandparent).to receive(:new).and_call_original allow(child).to receive(:new).and_call_original expect(grandparent.new).to be_an_instance_of grandparent expect(child.new).to be_an_instance_of child end end context "when partial doubles are not verified" do before { expect(RSpec::Mocks.configuration.verify_partial_doubles?).to be false } include_examples "stubbing `new` on class objects" end context "when partial doubles are verified" do include_context "with isolated configuration" before { RSpec::Mocks.configuration.verify_partial_doubles = true } include_examples "stubbing `new` on class objects" if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) it "handles keyword arguments correctly" do klass = Class.new do def initialize(kw:) end end allow(klass).to receive(:new).and_call_original klass.new(kw: 42) end RUBY end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/argument_matchers_spec.rb0000664000000000000000000004600114557670305027257 0ustar rootrootmodule RSpec module Mocks RSpec.describe "argument matchers matching" do let(:a_double) { double } after(:each, :reset => true) do reset a_double end describe "boolean" do it "accepts true as boolean" do expect(a_double).to receive(:random_call).with(boolean) a_double.random_call(true) end it "accepts false as boolean" do expect(a_double).to receive(:random_call).with(boolean) a_double.random_call(false) end it "rejects non boolean", :reset => true do expect(a_double).to receive(:random_call).with(boolean) expect { a_double.random_call("false") }.to fail_including "expected: (boolean)" end end describe "kind_of" do it "accepts fixnum as kind_of(Numeric)" do expect(a_double).to receive(:random_call).with(kind_of(Numeric)) a_double.random_call(1) end it "accepts float as kind_of(Numeric)" do expect(a_double).to receive(:random_call).with(kind_of(Numeric)) a_double.random_call(1.5) end it "handles non matching kinds nicely", :reset => true do expect(a_double).to receive(:random_call).with(kind_of(Numeric)) expect { a_double.random_call(true) }.to fail_including "expected: (kind of Numeric)" end it "matches arguments that have defined `kind_of?` to return true" do fix_num = double(:kind_of? => true) expect(a_double).to receive(:random_call).with(kind_of(Numeric)) a_double.random_call(fix_num) end it "handles a class thats overridden ===" do allow(Numeric).to receive(:===) { false } fix_num = double(:kind_of? => true) expect(a_double).to receive(:random_call).with(kind_of(Numeric)) a_double.random_call(fix_num) end end describe "instance_of" do it "accepts float as instance_of(Float)" do expect(a_double).to receive(:random_call).with(instance_of(Float)) a_double.random_call(1.1) end it "does NOT accept float as instance_of(Numeric)" do expect(a_double).not_to receive(:random_call).with(instance_of(Numeric)) a_double.random_call(1.1) end it "does NOT accept integer as instance_of(Numeric)" do expect(a_double).not_to receive(:random_call).with(instance_of(Numeric)) a_double.random_call(1) end it "rejects non numeric", :reset => true do expect(a_double).to receive(:random_call).with(an_instance_of(Numeric)) expect { a_double.random_call("1") }.to fail end it "rejects non string", :reset => true do expect(a_double).to receive(:random_call).with(an_instance_of(String)) expect { a_double.random_call(123) }.to fail end it "handles non matching instances nicely", :reset => true do expect(a_double).to receive(:random_call).with(instance_of(Numeric)) expect { a_double.random_call(1.5) }.to fail_including "expected: (an_instance_of(Numeric))" end end describe "anything" do it "accepts string as anything" do expect(a_double).to receive(:random_call).with("a", anything, "c") a_double.random_call("a", "whatever", "c") end it "doesn't accept no arguments" do expect(a_double).to_not receive(:random_call).with(anything) a_double.random_call end it "handles non matching instances nicely", :reset => true do expect(a_double).to receive(:random_call).with(anything) expect { a_double.random_call }.to fail_including "expected: (anything)" end end describe "duck_type" do it "matches duck type with one method" do expect(a_double).to receive(:random_call).with(duck_type(:length)) a_double.random_call([]) end it "matches duck type with two methods" do expect(a_double).to receive(:random_call).with(duck_type(:abs, :div)) a_double.random_call(1) end it "rejects goose when expecting a duck", :reset => true do expect(a_double).to receive(:random_call).with(duck_type(:abs, :div)) expect { a_double.random_call("I don't respond to :abs or :div") }.to fail_including "expected: (duck_type(:abs, :div))" end end describe "any_args" do context "as the only arg passed to `with`" do before { expect(a_double).to receive(:random_call).with(any_args) } it "matches no args" do a_double.random_call end it "matches one arg" do a_double.random_call("a string") end it "matches many args" do a_double.random_call("a string", :other, 3) end end context "as the last of three args" do before { expect(a_double).to receive(:random_call).with(1, /foo/, any_args) } it "matches a call of two args when it matches the first two explicit args" do a_double.random_call(1, "food") end it "matches a call of three args when it matches the first two explicit args" do a_double.random_call(1, "food", :more) end it "matches a call of four args when it matches the first two explicit args" do a_double.random_call(1, "food", :more, :args) end it "does not match a call where the first two args do not match", :reset => true do expect { a_double.random_call(1, "bar", 2, 3) }.to fail_including "expected: (1, /foo/, *(any args))" end it "does not match a call of no args", :reset => true do expect { a_double.random_call }.to fail_including "expected: (1, /foo/, *(any args))" end end context "as the first of three args" do before { expect(a_double).to receive(:random_call).with(any_args, 1, /foo/) } it "matches a call of two args when it matches the last two explicit args" do a_double.random_call(1, "food") end it "matches a call of three args when it matches the last two explicit args" do a_double.random_call(nil, 1, "food") end it "matches a call of four args when it matches the last two explicit args" do a_double.random_call(:some, :args, 1, "food") end it "does not match a call where the last two args do not match", :reset => true do expect { a_double.random_call(1, "bar", 2, 3) }.to fail_including "expected: (*(any args), 1, /foo/)" end it "does not match a call of no args", :reset => true do expect { a_double.random_call }.to fail_including "expected: (*(any args), 1, /foo/)" end end context "as the middle of three args" do before { expect(a_double).to receive(:random_call).with(1, any_args, /foo/) } it "matches a call of two args when it matches the first and last args" do a_double.random_call(1, "food") end it "matches a call of three args when it matches the first and last args" do a_double.random_call(1, nil, "food") end it "matches a call of four args when it matches the first and last args" do a_double.random_call(1, :some, :args, "food") end it "does not match a call where the first and last args do not match", :reset => true do expect { a_double.random_call(nil, "bar", 2, 3) }.to fail_including "expected: (1, *(any args), /foo/)" end it "does not match a call of no args", :reset => true do expect { a_double.random_call }.to fail_including "expected: (1, *(any args), /foo/)" end end context "when passed twice" do it 'immediately signals that this is invalid', :reset => true do expect { expect(a_double).to receive(:random_call).with(any_args, 1, any_args) }.to raise_error(ArgumentError, /any_args/) end end end describe "no_args" do it "matches no args against no_args" do expect(a_double).to receive(:random_call).with(no_args) a_double.random_call end it "fails no_args with one arg", :reset => true do expect(a_double).to receive(:msg).with(no_args) expect { a_double.msg(37) }.to fail_including "expected: (no args)" end context "when passed with other arguments" do it 'immediately signals that this is invalid', :reset => true do expect { expect(a_double).to receive(:random_call).with(no_args, 3) }.to raise_error(ArgumentError, /no_args/) end end end describe "hash_including" do it "matches hash with hash_including same hash" do expect(a_double).to receive(:random_call).with(hash_including(:a => 1)) a_double.random_call(:a => 1) end it "fails hash_including with missing key", :reset => true do expect(a_double).to receive(:random_call).with(hash_including(:a => 1)) expect { a_double.random_call(:a => 2) }.to fail_including "expected: (hash_including(:a=>1))" end end describe "hash_excluding" do it "matches hash with hash_excluding same hash" do expect(a_double).to receive(:random_call).with(hash_excluding(:a => 1)) a_double.random_call(:a => 2) end it "handles non matching instances nicely", :reset => true do expect(a_double).to receive(:random_call).with(hash_excluding(:a => 1)) expect { a_double.random_call(:a => 1) }.to fail_including "expected: (hash_not_including(:a=>1))" end end describe "array_including" do it "matches array with array_including same array" do expect(a_double).to receive(:random_call).with(array_including(1, 2)) a_double.random_call([1, 2]) end it "matches array with array_including using fuzzymatcher", :reset => true do expect(a_double).to receive(:random_call).with(array_including(a_value > 1)) a_double.random_call([1, 2]) end it "fails array_including when args aren't array", :reset => true do expect(a_double).to receive(:msg).with(array_including(1, 2, 3)) expect { a_double.msg(1, 2, 3) }.to fail_including "expected: (array_including(1, 2, 3))" end it "fails array_including when arg doesn't contain all elements", :reset => true do expect(a_double).to receive(:msg).with(array_including(1, 2, 3)) expect { a_double.msg([1, 2]) }.to fail_including "expected: (array_including(1, 2, 3))" end end describe "array_excluding" do it "matches array with array_excluding different array" do expect(a_double).to receive(:random_call).with(array_excluding(3, 4)) a_double.random_call([1, 2]) end it "fails array_excluding when is the same array", :reset => true do expect(a_double).to receive(:msg).with(array_excluding(1, 2, 3)) expect { a_double.msg(1, 2, 3) }.to fail_including "expected: (array_excluding(1, 2, 3))" end it "fails array_excluding when arg contains some elements", :reset => true do expect(a_double).to receive(:msg).with(array_excluding(2, 3)) expect { a_double.msg([1, 2]) }.to fail_including "expected: (array_excluding(2, 3))" end it "matches array_excluding when using the fuzzy matcher", :reset => true do expect(a_double).to receive(:msg).with(array_excluding(a_value > 3)) a_double.msg([1, 2]) end it "fails array_excluding when using the fuzzy matcher", :reset => true do expect(a_double).to receive(:msg).with(array_excluding(a_value > 1)) expect { a_double.msg([1, 2]) }.to fail_including "expected: (array_excluding(a value > 1))" end end context "handling arbitrary matchers" do it "matches any arbitrary object using #===" do matcher = double expect(matcher).to receive(:===).with(4).and_return(true) expect(a_double).to receive(:foo).with(matcher) a_double.foo(4) end it "matches against a Matcher", :reset => true do expect(a_double).to receive(:msg).with(equal(3)) # This spec is generating warnings on 1.8.7, not sure why so # this does with_isolated_stderr to kill them. @samphippen 3rd Jan 2013. expect { with_isolated_stderr { a_double.msg(37) } }.to fail_including "expected: (equal 3)" end it "fails when given an arbitrary object that returns false from #===", :reset => true do matcher = double expect(matcher).to receive(:===).with(4).at_least(:once).and_return(false) expect(a_double).to receive(:foo).with(matcher) expect { a_double.foo(4) }.to fail end end context "handling objects with a wrong definition of `==` that raises errors for other types" do Color = Struct.new(:r, :g, :b) do def ==(other) other.r == r && other.g == g && other.b == b end end before(:context) do expect { Color.new(0, 0, 0) == Object.new }.to raise_error(NoMethodError) end it 'matches against an equal instance of the same type' do expect(a_double).to receive(:random_call).with(Color.new(0, 0, 0)) a_double.random_call(Color.new(0, 0, 0)) end it 'fails when matched against an unequal instance of the same class', :reset do expect(a_double).to receive(:random_call).with(Color.new(0, 0, 0)) expect { a_double.random_call(Color.new(0, 1, 0)) }.to fail end it 'can match multiple instances of the type against multiple equal instances of the type' do expect(a_double).to receive(:random_call).with( Color.new(0, 0, 0), Color.new(0, 1, 0) ) a_double.random_call( Color.new(0, 0, 0), Color.new(0, 1, 0) ) end end context "handling non-matcher arguments" do it "matches string against regexp" do expect(a_double).to receive(:random_call).with(/bcd/) a_double.random_call("abcde") end it "matches regexp against regexp" do expect(a_double).to receive(:random_call).with(/bcd/) a_double.random_call(/bcd/) end it "fails if regexp does not match submitted string", :reset => true do expect(a_double).to receive(:random_call).with(/bcd/) expect { a_double.random_call("abc") }.to fail end it "fails if regexp does not match submitted regexp", :reset => true do expect(a_double).to receive(:random_call).with(/bcd/) expect { a_double.random_call(/bcde/) }.to fail end it "matches against a hash submitted and received by value" do expect(a_double).to receive(:random_call).with(:a => "a", :b => "b") a_double.random_call(:a => "a", :b => "b") end it "matches against a hash submitted as keyword arguments a and received as a positional argument (in both Ruby 2 and Ruby 3)" do opts = {:a => "a", :b => "b"} expect(a_double).to receive(:random_call).with(opts) a_double.random_call(:a => "a", :b => "b") end if RUBY_VERSION >= "3" it "fails to match against a hash submitted as a positional argument and received as keyword arguments in Ruby 3.0 or later", :reset => true do opts = {:a => "a", :b => "b"} expect(a_double).to receive(:random_call).with(:a => "a", :b => "b") expect do a_double.random_call(opts) end.to fail_with(/expected: \(\{(:a=>\"a\", :b=>\"b\"|:b=>\"b\", :a=>\"a\")\}\)/) end else it "matches against a hash submitted as a positional argument and received as keyword arguments in Ruby 2.7 or before" do opts = {:a => "a", :b => "b"} expect(a_double).to receive(:random_call).with(:a => "a", :b => "b") a_double.random_call(opts) end end it "fails for a hash w/ wrong values", :reset => true do expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") expect do a_double.random_call(:a => "b", :c => "e") end.to fail_with(/expected: \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\)/) end it "fails for a hash w/ wrong keys", :reset => true do expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") expect do a_double.random_call("a" => "b", "c" => "d") end.to fail_with(/expected: \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\)/) end it "matches a class against itself" do expect(a_double).to receive(:foo).with(Float) a_double.foo(Float) end it "fails a class against an unrelated class", :reset => true do expect(a_double).to receive(:foo).with(Float) expect { a_double.foo(Hash) }.to fail end it "matches a class against an instance of itself" do expect(a_double).to receive(:foo).with(Float) a_double.foo(3.3) end it "fails a class against an object of a different type", :reset => true do expect(a_double).to receive(:foo).with(Float) expect { a_double.foo(3) }.to fail end it "fails with zero arguments", :reset => true do expect do expect(a_double).to receive(:msg).with { |arg| expect(arg).to eq :received } end.to raise_error(ArgumentError, /must have at least one argument/) end it "fails with sensible message when args respond to #description", :reset => true do arg = double(:description => nil, :inspect => "my_thing") expect(a_double).to receive(:msg).with(3) expect { a_double.msg arg }.to fail_including "got: (my_thing)" end it "fails with sensible message when arg#description is nil", :reset => true do arg = double(:description => nil, :inspect => "my_thing") expect(a_double).to receive(:msg).with(arg) expect { a_double.msg 3 }.to fail_including "expected: (my_thing)" end it "fails with sensible message when arg#description is blank", :reset => true do arg = double(:description => "", :inspect => "my_thing") expect(a_double).to receive(:msg).with(arg) expect { a_double.msg 3 }.to fail_including "expected: (my_thing)" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/standalone_spec.rb0000664000000000000000000000123714557670305025701 0ustar rootrootrequire 'rspec/support/spec/in_sub_process' main = self RSpec.describe "Loading rspec/mocks/standalone" do include RSpec::Support::InSubProcess it "exposes the RSpec::Mocks API on `main`" do in_sub_process do require 'rspec/mocks/standalone' main.instance_eval do dbl = double expect(dbl).to receive(:foo) dbl.foo RSpec::Mocks.verify RSpec::Mocks.teardown end end end it "does not infect other objects with the RSpec::Mocks API" do in_sub_process do require 'rspec/mocks/standalone' object = Object.new expect(object).not_to respond_to(:double, :expect) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/stubbed_message_expectations_spec.rb0000664000000000000000000000620214557670305031470 0ustar rootrootRSpec.describe "expection set on previously stubbed method" do it "fails if message is not received after expectation is set" do dbl = double(:msg => nil) dbl.msg expect(dbl).to receive(:msg) expect { verify dbl }.to fail end it "outputs arguments of similar calls" do dbl = double('double', :foo => true) expect(dbl).to receive(:foo).with('first') dbl.foo('second') dbl.foo('third') expect { verify dbl }.to raise_error( RSpec::Mocks::MockExpectationError, a_string_including( %Q(# received :foo with unexpected arguments), "expected: (\"first\")", "got:", "(\"second\")", "(\"third\")")) reset dbl end it 'handles concurrent validation of expectations' do dbl = double('double', :foo => true) concurrency = 4 repetition = 10 expect(dbl).to receive(:foo).with(anything).exactly(concurrency * repetition).times concurrency.times.map do |thread| Thread.new do repetition.times do |index| dbl.foo("#{thread}-#{index}") end end end.map(&:join) verify dbl end it 'indicates the site of expectation in the stacktrace when outputing arguments of similar calls' do dbl = double('double', :foo => true) expect(dbl).to receive(:foo).with('first'); line = __LINE__ dbl.foo('second') dbl.foo('third') expect { verify dbl }.to raise_error(an_object_having_attributes( :backtrace => a_collection_starting_with( a_string_including("#{__FILE__}:#{line}") ) )) end context "with argument constraint on stub" do it "matches any args if no arg constraint set on expectation" do dbl = double("mock") allow(dbl).to receive(:foo).with(3).and_return("stub") expect(dbl).to receive(:foo).at_least(:once).and_return("expectation") dbl.foo verify dbl end it "matches specific args set on expectation" do dbl = double("mock") allow(dbl).to receive(:foo).with(3).and_return("stub") expect(dbl).to receive(:foo).at_least(:once).with(4).and_return("expectation") dbl.foo(4) verify dbl end it "fails if expectation's arg constraint is not met" do dbl = double("mock") allow(dbl).to receive(:foo).with(3).and_return("stub") expect(dbl).to receive(:foo).at_least(:once).with(4).and_return("expectation") dbl.foo(3) expect { verify dbl }.to raise_error(/expected: \(4\)\s+got: \(3\)/) end it 'distinguishes between individual values and arrays properly' do dbl = double allow(dbl).to receive(:foo).with('a', ['b']) expect { dbl.foo(['a'], 'b') }.to raise_error { |e| expect(e.message).to include('expected: ("a", ["b"])', 'got: (["a"], "b")') } end it 'distinguishes between duplicate individual values and arrays properly' do dbl = double allow(dbl).to receive(:foo).with('a', ['b'], 'b') expect { dbl.foo(['a'], 'b', 'b') }.to raise_error { |e| expect(e.message).to include('expected: ("a", ["b"], "b")', 'got: (["a"], "b", "b")') } end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/mock_ordering_spec.rb0000664000000000000000000000674514557670305026404 0ustar rootrootmodule RSpec module Mocks RSpec.describe "ordering" do before { @double = double("test double") } after { reset @double } it "passes when messages are received in order" do expect(@double).to receive(:one).ordered expect(@double).to receive(:two).ordered expect(@double).to receive(:three).ordered @double.one @double.two @double.three end it "passes when messages are received in order" do allow(@double).to receive(:something) expect(@double).to receive(:one).ordered expect(@double).to receive(:two).ordered expect(@double).to receive(:three).at_least(:once).ordered @double.one @double.two @double.three @double.three end it "passes when messages are received in order across objects" do a = double("a") b = double("b") expect(a).to receive(:one).ordered expect(b).to receive(:two).ordered expect(a).to receive(:three).ordered a.one b.two a.three end it "fails when messages are received out of order (2nd message 1st)" do expect(@double).to receive(:one).ordered expect(@double).to receive(:two).ordered expect { @double.two }.to fail_with "# received :two out of order" end it "fails when messages are received out of order (3rd message 1st)" do expect(@double).to receive(:one).ordered expect(@double).to receive(:two).ordered expect(@double).to receive(:three).ordered @double.one expect { @double.three }.to fail_with "# received :three out of order" end it "fails when messages are received out of order (3rd message 2nd)" do expect(@double).to receive(:one).ordered expect(@double).to receive(:two).ordered expect(@double).to receive(:three).ordered @double.one expect { @double.three }.to fail_with "# received :three out of order" end it "fails when messages are out of order across objects" do a = double("test double") b = double("another test double") expect(a).to receive(:one).ordered expect(b).to receive(:two).ordered expect(a).to receive(:three).ordered a.one expect { a.three }.to fail_with "# received :three out of order" reset a reset b end it "ignores order of non ordered messages" do expect(@double).to receive(:ignored_0) expect(@double).to receive(:ordered_1).ordered expect(@double).to receive(:ignored_1) expect(@double).to receive(:ordered_2).ordered expect(@double).to receive(:ignored_2) expect(@double).to receive(:ignored_3) expect(@double).to receive(:ordered_3).ordered expect(@double).to receive(:ignored_4) @double.ignored_3 @double.ordered_1 @double.ignored_0 @double.ordered_2 @double.ignored_4 @double.ignored_2 @double.ordered_3 @double.ignored_1 verify @double end it "supports duplicate messages" do expect(@double).to receive(:a).ordered expect(@double).to receive(:b).ordered expect(@double).to receive(:a).ordered @double.a @double.b @double.a end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/hash_excluding_matcher_spec.rb0000664000000000000000000000454214557670305030243 0ustar rootrootmodule RSpec module Mocks module ArgumentMatchers RSpec.describe HashExcludingMatcher do it "describes itself properly" do expect(HashExcludingMatcher.new(:a => 5).description).to eq "hash_not_including(:a=>5)" end describe "passing" do it "matches a hash without the specified key" do expect(hash_not_including(:c)).to be === {:a => 1, :b => 2} end it "matches a hash with the specified key, but different value" do expect(hash_not_including(:b => 3)).to be === {:a => 1, :b => 2} end it "matches a hash without the specified key, given as anything()" do expect(hash_not_including(:c => anything)).to be === {:a => 1, :b => 2} end it "matches an empty hash" do expect(hash_not_including(:a)).to be === {} end it "matches a hash without any of the specified keys" do expect(hash_not_including(:a, :b, :c)).to be === { :d => 7 } end it "matches against classes inheriting from Hash" do expect(hash_not_including(Class.new(Hash)[:c, 1])).not_to be === {:c => 1} end end describe "failing" do it "does not match a non-hash" do expect(hash_not_including(:a => 1)).not_to be === 1 end it "does not match a hash with a specified key" do expect(hash_not_including(:b)).not_to be === { :b => 2 } end it "does not match a hash with the specified key/value pair" do expect(hash_not_including(:b => 2)).not_to be === { :a => 1, :b => 2 } end it "does not match a hash with the specified key" do expect(hash_not_including(:a, :b => 3)).not_to be === { :a => 1, :b => 2 } end it "does not match a hash with one of the specified keys" do expect(hash_not_including(:a, :b)).not_to be === { :b => 2 } end it "does not match a hash with some of the specified keys" do expect(hash_not_including(:a, :b, :c)).not_to be === { :a => 1, :b => 2 } end it "does not match a hash with one key/value pair included" do expect(hash_not_including(:a, :b, :c, :d => 7)).not_to be === { :d => 7 } end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/spy_spec.rb0000664000000000000000000000621614557670305024366 0ustar rootrootrequire "spec_helper" RSpec.describe "the spy family of methods" do describe "spy" do it "responds to arbitrary methods" do expect(spy.respond_to?(:foo)).to be true end it "takes a name" do expect(spy(:bacon_bits).inspect).to include("bacon_bits") end it "records called methods" do expect(spy.tap { |s| s.foo }).to have_received(:foo) end it "takes a hash of method names and return values" do expect(spy(:foo => :bar).foo).to eq(:bar) end it "takes a name and a hash of method names and return values" do expect(spy(:bacon_bits, :foo => :bar).foo).to eq(:bar) end end shared_examples_for "a verifying spy with a foo method" do it "responds to methods on the verified object" do expect(subject.respond_to?(:foo)).to be true end it "does not respond to methods that are not on the verified object" do expect(subject.respond_to?(:other_method)).to be false end it "records called methods" do expect(subject.tap { |s| s.foo }).to have_received(:foo) end it 'fails fast when `have_received` is passed an undefined method name' do expect { expect(subject).to have_received(:bar) }.to fail_including("does not implement") end it 'fails fast when negative `have_received` is passed an undefined method name' do expect { expect(subject).to_not have_received(:bar) }.to fail_including("does not implement") end end describe "instance_spy" do context "when passing a class object" do let(:the_class) do Class.new do def foo 3 end end end subject { instance_spy(the_class) } it_behaves_like "a verifying spy with a foo method" it "takes a class and a hash of method names and return values" do expect(instance_spy(the_class, :foo => :bar).foo).to eq(:bar) end end context "passing a class by string reference" do DummyClass = Class.new do def foo 3 end end let(:the_class) { "DummyClass" } subject { instance_spy(the_class) } it_behaves_like "a verifying spy with a foo method" it "takes a class name string and a hash of method names and return values" do expect(instance_spy(the_class, :foo => :bar).foo).to eq(:bar) end end end describe "object_spy" do let(:the_class) do Class.new do def foo 3 end end end let(:the_instance) { the_class.new } subject { object_spy(the_instance) } it_behaves_like "a verifying spy with a foo method" it "takes an instance and a hash of method names and return values" do expect(object_spy(the_instance, :foo => :bar).foo).to eq(:bar) end end describe "class_spy" do let(:the_class) do Class.new do def self.foo 3 end end end subject { class_spy(the_class) } it_behaves_like "a verifying spy with a foo method" it "takes a class and a hash of method names and return values" do expect(class_spy(the_class, :foo => :bar).foo).to eq(:bar) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/and_invoke_spec.rb0000664000000000000000000000271714557670305025672 0ustar rootrootmodule RSpec module Mocks RSpec.describe 'and_invoke' do let(:obj) { double('obj') } context 'when a block is passed' do it 'raises ArgumentError' do expect { allow(obj).to receive(:foo).and_invoke('bar') { 'baz' } }.to raise_error(ArgumentError, /implementation block/i) end end context 'when no argument is passed' do it 'raises ArgumentError' do expect { allow(obj).to receive(:foo).and_invoke }.to raise_error(ArgumentError) end end context 'when a non-callable are passed in any position' do let(:non_callable) { nil } let(:callable) { lambda { nil } } it 'raises ArgumentError' do error = [ArgumentError, "Arguments to `and_invoke` must be callable."] expect { allow(obj).to receive(:foo).and_invoke(non_callable) }.to raise_error(*error) expect { allow(obj).to receive(:foo).and_invoke(callable, non_callable) }.to raise_error(*error) end end context 'when calling passed callables' do let(:dbl) { double } it 'passes the arguments into the callable' do expect(dbl).to receive(:square_then_cube).and_invoke(lambda { |i| i ** 2 }, lambda { |i| i ** 3 }) expect(dbl.square_then_cube(2)).to eq 4 expect(dbl.square_then_cube(2)).to eq 8 end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/marshal_extension_spec.rb0000664000000000000000000000422114557670305027270 0ustar rootrootRSpec.describe Marshal, 'extensions' do # An object that raises when code attempts to dup it. # # Because we manipulate the internals of RSpec::Mocks.space below, we need # an object that simply blows up when #dup is called without using any # partial mocking or stubbing from rspec-mocks itself. class UndupableObject def dup raise NotImplementedError end end describe '#dump' do context 'when rspec-mocks has been fully initialized' do include_context "with monkey-patched marshal" it 'duplicates objects with stubbed or mocked implementations before serialization' do obj = double(:foo => "bar") serialized = Marshal.dump(obj) expect(Marshal.load(serialized)).to be_an(obj.class) end it 'does not duplicate other objects before serialization' do obj = UndupableObject.new serialized = Marshal.dump(obj) expect(Marshal.load(serialized)).to be_an(UndupableObject) end it 'does not duplicate nil before serialization' do serialized = Marshal.dump(nil) expect(Marshal.load(serialized)).to be_nil end specify 'applying and unapplying patch is idempotent' do obj = double(:foo => "bar") config = RSpec::Mocks.configuration config.patch_marshal_to_support_partial_doubles = true config.patch_marshal_to_support_partial_doubles = true serialized = Marshal.dump(obj) expect(Marshal.load(serialized)).to be_an(obj.class) config.patch_marshal_to_support_partial_doubles = false config.patch_marshal_to_support_partial_doubles = false expect { Marshal.dump(obj) }.to raise_error(TypeError) end end context 'outside the per-test lifecycle' do def outside_per_test_lifecycle RSpec::Mocks.teardown yield ensure RSpec::Mocks.setup end it 'does not duplicate the object before serialization' do obj = UndupableObject.new outside_per_test_lifecycle do serialized = Marshal.dump(obj) expect(Marshal.load(serialized)).to be_an(UndupableObject) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/and_return_spec.rb0000664000000000000000000000106714557670305025713 0ustar rootrootmodule RSpec module Mocks RSpec.describe 'and_return' do let(:obj) { double('obj') } context 'when a block is passed' do it 'raises ArgumentError' do expect { allow(obj).to receive(:foo).and_return('bar') { 'baz' } }.to raise_error(ArgumentError, /implementation block/i) end end context 'when no argument is passed' do it 'raises ArgumentError' do expect { allow(obj).to receive(:foo).and_return }.to raise_error(ArgumentError) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/before_all_spec.rb0000664000000000000000000000354714557670305025651 0ustar rootrootrequire 'support/before_all_shared_example_group' RSpec.describe "Using rspec-mocks features in before(:all) blocks" do describe "#stub_const" do include_examples "fails in a before(:all) block" do def use_rspec_mocks stub_const("SomeNewConst", Class.new) end it 'does not stub the const' do expect(defined?(SomeNewConst)).to be_falsey end end end describe "#hide_const(for an undefined const)" do include_examples "fails in a before(:all) block" do def use_rspec_mocks hide_const("Foo") end end end describe "#hide_const(for a defined const)" do include_examples "fails in a before(:all) block" do def use_rspec_mocks hide_const("Float") end it 'does not hide the const' do expect(defined?(Float)).to be_truthy end end end describe "allow(...).to receive_message_chain" do include_examples "fails in a before(:all) block" do def use_rspec_mocks allow(Object).to receive_message_chain(:foo, :bar) end end end describe "#expect(...).to receive" do include_examples "fails in a before(:all) block" do def use_rspec_mocks expect(Object).to receive(:foo) end end end describe "#allow(...).to receive" do include_examples "fails in a before(:all) block" do def use_rspec_mocks allow(Object).to receive(:foo) end end end describe "#expect_any_instance_of(...).to receive" do include_examples "fails in a before(:all) block" do def use_rspec_mocks expect_any_instance_of(Object).to receive(:foo) end end end describe "#allow_any_instance_of(...).to receive" do include_examples "fails in a before(:all) block" do def use_rspec_mocks allow_any_instance_of(Object).to receive(:foo) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/test_double_spec.rb0000664000000000000000000000320214557670305026054 0ustar rootrootmodule RSpec module Mocks RSpec.describe TestDouble do describe "#freeze" do subject { double } it "gives a warning" do expect(RSpec).to receive(:warn_with).with(/freeze a test double/) subject.freeze end it "gives the correct call site for the warning" do expect_warning_with_call_site(__FILE__, __LINE__ + 1) subject.freeze end it "doesn't freeze the object" do allow(RSpec).to receive(:warn_with).with(/freeze a test double/) double.freeze allow(subject).to receive(:hi) expect { subject.hi }.not_to raise_error end it "returns the instance of the test double" do allow(RSpec).to receive(:warn_with).with(/freeze a test double/) expect(subject.freeze).to eq subject end end RSpec.shared_examples_for "a copy method" do |method| it "copies the `as_null_object` state when #{method}'d" do dbl = double.as_null_object copy = dbl.__send__(method) expect(copy.foo.bar).to be(copy) end end include_examples "a copy method", :dup include_examples "a copy method", :clone [[:should, :expect], [:expect], [:should]].each do |syntax| context "with syntax #{syntax.inspect}" do include_context "with syntax", syntax it 'stubs the methods passed in the stubs hash' do dbl = double("MyDouble", :a => 5, :b => 10) expect(dbl.a).to eq(5) expect(dbl.b).to eq(10) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/stub_chain_spec.rb0000664000000000000000000001506514557670305025674 0ustar rootrootmodule RSpec module Mocks RSpec.describe "A chained method stub" do let(:object) { Object.new } it 'does not get confused by symbol vs string usage for the messages' do allow(object).to receive_message_chain(:foo, :bar => 1) allow(object).to receive_message_chain("foo", :bazz => 2) expect(object.foo.bar).to eq(1) expect(object.foo.bazz).to eq(2) end context "with one method in chain" do context "using and_return" do it "returns expected value from chaining only one method call" do allow(object).to receive_message_chain(:msg1).and_return(:return_value) expect(object.msg1).to equal(:return_value) end end context "using a block" do it "returns the correct value" do allow(object).to receive_message_chain(:msg1) { :return_value } expect(object.msg1).to equal(:return_value) end end context "using a hash" do it "returns the value of the key/value pair" do allow(object).to receive_message_chain(:msg1 => :return_value) expect(object.msg1).to equal(:return_value) end end end context "with two methods in chain" do it "accepts any number of arguments to the stubbed messages in the chain" do allow(object).to receive_message_chain(:msg1, :msg2).and_return(:return_value) expect(object.msg1("nonsense", :value).msg2("another", :nonsense, 3.0, "value")).to eq(:return_value) end context "using and_return" do it "returns expected value from chaining two method calls" do allow(object).to receive_message_chain(:msg1, :msg2).and_return(:return_value) expect(object.msg1.msg2).to equal(:return_value) end end context "using a block" do it "returns the correct value" do allow(object).to receive_message_chain(:msg1, :msg2) { :return_value } expect(object.msg1.msg2).to equal(:return_value) end end context "using a hash" do it "returns the value of the key/value pair" do allow(object).to receive_message_chain(:msg1, :msg2 => :return_value) expect(object.msg1.msg2).to equal(:return_value) end end end context "with four methods in chain" do context "using and_return" do it "returns expected value from chaining two method calls" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg4).and_return(:return_value) expect(object.msg1.msg2.msg3.msg4).to equal(:return_value) end end context "using a block" do it "returns the correct value" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg4) { :return_value } expect(object.msg1.msg2.msg3.msg4).to equal(:return_value) end end context "using a hash" do it "returns the value of the key/value pair" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg4 => :return_value) expect(object.msg1.msg2.msg3.msg4).to equal(:return_value) end end context "using a hash with a string key" do it "returns the value of the key/value pair" do allow(object).to receive_message_chain("msg1.msg2.msg3.msg4" => :return_value) expect(object.msg1.msg2.msg3.msg4).to equal(:return_value) end end end it "returns expected value from chaining four method calls" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg4).and_return(:return_value) expect(object.msg1.msg2.msg3.msg4).to equal(:return_value) end context "with messages shared across multiple chains" do context "using and_return" do context "starting with the same message" do it "returns expected value" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3).and_return(:first) allow(object).to receive_message_chain(:msg1, :msg2, :msg4).and_return(:second) expect(object.msg1.msg2.msg3).to equal(:first) expect(object.msg1.msg2.msg4).to equal(:second) end end context "starting with the different messages" do it "returns expected value" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3).and_return(:first) allow(object).to receive_message_chain(:msg4, :msg2, :msg3).and_return(:second) expect(object.msg1.msg2.msg3).to equal(:first) expect(object.msg4.msg2.msg3).to equal(:second) end end end context "using => value" do context "starting with the same message" do it "returns expected value" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3 => :first) allow(object).to receive_message_chain(:msg1, :msg2, :msg4 => :second) expect(object.msg1.msg2.msg3).to equal(:first) expect(object.msg1.msg2.msg4).to equal(:second) end end context "starting with different messages" do it "returns expected value" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3 => :first) allow(object).to receive_message_chain(:msg4, :msg2, :msg3 => :second) expect(object.msg1.msg2.msg3).to equal(:first) expect(object.msg4.msg2.msg3).to equal(:second) end end end end it "returns expected value when chain is a dot separated string, like stub_chain('msg1.msg2.msg3')" do allow(object).to receive_message_chain("msg1.msg2.msg3").and_return(:return_value) expect(object.msg1.msg2.msg3).to equal(:return_value) end it "returns expected value from two chains with shared messages at the beginning" do allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg4).and_return(:first) allow(object).to receive_message_chain(:msg1, :msg2, :msg3, :msg5).and_return(:second) expect(object.msg1.msg2.msg3.msg4).to equal(:first) expect(object.msg1.msg2.msg3.msg5).to equal(:second) end it "handles private instance methods (like Object#select) in the middle of a chain" do allow(object).to receive_message_chain(:msg1, :select, :msg3 => 'answer') expect(object.msg1.select.msg3).to eq 'answer' end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/should_syntax_spec.rb0000664000000000000000000004622514557670305026463 0ustar rootrootrequire 'support/before_all_shared_example_group' RSpec.describe "Using the legacy should syntax" do include_context "with syntax", [:should, :expect] describe "#received_message?" do let(:dbl) { double("double").as_null_object } it "answers false for received_message? when no messages received" do expect(dbl.received_message?(:message)).to be_falsey end it "answers true for received_message? when message received" do dbl.message expect(dbl.received_message?(:message)).to be_truthy end it "answers true for received_message? when message received with correct args" do dbl.message 1, 2, 3 expect(dbl.received_message?(:message, 1, 2, 3)).to be_truthy end it "answers false for received_message? when message received with incorrect args" do dbl.message 1, 2, 3 expect(dbl.received_message?(:message, 1, 2)).to be_falsey end end describe "#stub" do it "supports options" do double.stub(:foo, :expected_from => "bar") end it 'returns `nil` from all terminal actions to discourage further configuration' do expect(double.stub(:foo).and_return(1)).to be_nil expect(double.stub(:foo).and_raise("boom")).to be_nil expect(double.stub(:foo).and_throw(:foo)).to be_nil end it 'sets up a canned response' do dbl = double dbl.stub(:foo).and_return(3) expect(dbl.foo).to eq(3) end it 'can stub multiple messages using a hash' do dbl = double dbl.stub(:foo => 2, :bar => 1) expect(dbl.foo).to eq(2) expect(dbl.bar).to eq(1) end include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.stub(:foo) end end end describe "#stub_chain" do it 'can stub a sequence of messages' do dbl = double dbl.stub_chain(:foo, :bar, :baz => 17) expect(dbl.foo.bar.baz).to eq(17) expect { dbl.foo.baz.bar }.to fail end include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.stub_chain(:foo, :bar) end end end describe "#unstub" do include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.unstub(:foo) end end it "replaces the stubbed method with the original method" do obj = Object.new def obj.foo; :original; end obj.stub(:foo) obj.unstub(:foo) expect(obj.foo).to eq :original end it "removes all stubs with the supplied method name" do obj = Object.new def obj.foo; :original; end obj.stub(:foo).with(1) obj.stub(:foo).with(2) obj.unstub(:foo) expect(obj.foo).to eq :original end it "does not remove any expectations with the same method name" do obj = Object.new def obj.foo; :original; end obj.should_receive(:foo).with(3).and_return(:three) obj.stub(:foo).with(1) obj.stub(:foo).with(2) obj.unstub(:foo) expect(obj.foo(3)).to eq :three end it "restores the correct implementations when stubbed and unstubbed on a parent and child class" do parent = Class.new child = Class.new(parent) parent.stub(:new) child.stub(:new) parent.unstub(:new) child.unstub(:new) expect(parent.new).to be_an_instance_of parent expect(child.new).to be_an_instance_of child end it "raises a MockExpectationError if the method has not been stubbed" do obj = Object.new expect { obj.unstub(:foo) }.to fail end end describe "#should_receive" do it 'fails on verification if the message is not received' do dbl = double dbl.should_receive(:foo) expect { verify_all }.to fail end it 'does not fail on verification if the message is received' do dbl = double dbl.should_receive(:foo) dbl.foo expect { verify_all }.not_to raise_error end it 'can set a canned response' do dbl = double dbl.should_receive(:bar).and_return(3) expect(dbl.bar).to eq(3) end include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.should_receive(:foo) end end context "with an options hash" do it "reports the file and line submitted with :expected_from" do begin mock = RSpec::Mocks::Double.new("a mock") mock.should_receive(:message, :expected_from => "/path/to/blah.ext:37") verify mock rescue Exception => e ensure expect(e.backtrace.to_s).to match(%r{/path/to/blah.ext:37}m) end end it "uses the message supplied with :message" do expect { m = RSpec::Mocks::Double.new("a mock") m.should_receive(:message, :message => "recebi nada") verify m }.to raise_error("recebi nada") end it "uses the message supplied with :message after a similar stub" do expect { m = RSpec::Mocks::Double.new("a mock") m.stub(:message) m.should_receive(:message, :message => "from mock") verify m }.to raise_error("from mock") end end end describe "#should_not_receive" do it "returns a negative message expectation" do expect(Object.new.should_not_receive(:foobar)).to be_negative end it 'fails when the message is received' do with_unfulfilled_double do |dbl| dbl.should_not_receive(:foo) expect { dbl.foo }.to fail end end it 'does not fail on verification if the message is not received' do dbl = double dbl.should_not_receive(:foo) expect { verify_all }.not_to raise_error end include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.should_not_receive(:foo) end end end describe "#any_instance" do let(:klass) do Class.new do def existing_method; :existing_method_return_value; end def existing_method_with_arguments(_a, _b=nil); :existing_method_with_arguments_return_value; end def another_existing_method; end private def private_method; :private_method_return_value; end end end include_examples "fails in a before(:all) block" do def use_rspec_mocks Object.any_instance.should_receive(:foo) end end it "adds a class to the current space" do expect { klass.any_instance }.to change { RSpec::Mocks.space.any_instance_recorders.size }.by(1) end it 'can stub a method' do klass.any_instance.stub(:foo).and_return(2) expect(klass.new.foo).to eq(2) end it 'can mock a method' do klass.any_instance.should_receive(:foo) klass.new expect { verify_all }.to fail end it 'can get method objects for the fluent interface', :if => RUBY_VERSION.to_f > 1.8 do and_return = klass.any_instance.stub(:foo).method(:and_return) and_return.call(23) expect(klass.new.foo).to eq(23) end it 'affects previously stubbed instances when stubbing a method' do instance = klass.new klass.any_instance.stub(:foo).and_return(2) expect(instance.foo).to eq(2) klass.any_instance.stub(:foo).and_return(1) expect(instance.foo).to eq(1) end it 'affects previously stubbed instances when mocking a method' do instance = klass.new klass.any_instance.stub(:foo).and_return(2) expect(instance.foo).to eq(2) klass.any_instance.should_receive(:foo).and_return(1) expect(instance.foo).to eq(1) end context "invocation order" do describe "#stub" do it "raises an error if 'stub' follows 'with'" do expect { klass.any_instance.with("1").stub(:foo) }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_return'" do expect { klass.any_instance.stub(:foo).and_return(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_raise'" do expect { klass.any_instance.stub(:foo).and_raise(1).with("1") }.to raise_error(NoMethodError) end it "raises an error if 'with' follows 'and_yield'" do expect { klass.any_instance.stub(:foo).and_yield(1).with("1") }.to raise_error(NoMethodError) end context "behaves as 'every instance'" do let(:super_class) { Class.new { def foo; 'bar'; end } } let(:sub_class) { Class.new(super_class) } it 'handles `unstub` on subclasses' do super_class.any_instance.stub(:foo) sub_class.any_instance.stub(:foo) sub_class.any_instance.unstub(:foo) expect(sub_class.new.foo).to eq("bar") end end end describe "#stub_chain" do it "raises an error if 'stub_chain' follows 'and_return'" do expect { klass.any_instance.and_return("1").stub_chain(:foo, :bar) }.to raise_error(NoMethodError) end context "allows a chain of methods to be stubbed using #stub_chain" do example "given symbols representing the methods" do klass.any_instance.stub_chain(:one, :two, :three).and_return(:four) expect(klass.new.one.two.three).to eq(:four) end example "given a hash as the last argument uses the value as the expected return value" do klass.any_instance.stub_chain(:one, :two, :three => :four) expect(klass.new.one.two.three).to eq(:four) end example "given a string of '.' separated method names representing the chain" do klass.any_instance.stub_chain('one.two.three').and_return(:four) expect(klass.new.one.two.three).to eq(:four) end end it 'affects previously stubbed instances' do instance = klass.new dbl = double klass.any_instance.stub(:foo).and_return(dbl) expect(instance.foo).to eq(dbl) klass.any_instance.stub_chain(:foo, :bar => 3) expect(instance.foo.bar).to eq(3) end end describe "#should_receive" do it "raises an error if 'should_receive' follows 'with'" do expect { klass.any_instance.with("1").should_receive(:foo) }.to raise_error(NoMethodError) end end describe "#should_not_receive" do it "fails if the method is called" do klass.any_instance.should_not_receive(:existing_method) instance = klass.new expect_fast_failure_from(instance) do instance.existing_method end end it "passes if no method is called" do expect { klass.any_instance.should_not_receive(:existing_method) }.to_not raise_error end it "passes if only a different method is called" do klass.any_instance.should_not_receive(:existing_method) expect { klass.new.another_existing_method }.to_not raise_error end context "with constraints" do it "fails if the method is called with the specified parameters" do klass.any_instance.should_not_receive(:existing_method_with_arguments).with(:argument_one, :argument_two) instance = klass.new expect_fast_failure_from(instance) do instance.existing_method_with_arguments(:argument_one, :argument_two) end end it "passes if the method is called with different parameters" do klass.any_instance.should_not_receive(:existing_method_with_arguments).with(:argument_one, :argument_two) expect { klass.new.existing_method_with_arguments(:argument_three, :argument_four) }.to_not raise_error end end context 'when used in combination with should_receive' do it 'passes if only the expected message is received' do klass.any_instance.should_receive(:foo) klass.any_instance.should_not_receive(:bar) klass.new.foo verify_all end end it "prevents confusing double-negative expressions involving `never`" do expect { klass.any_instance.should_not_receive(:not_expected).never }.to raise_error(/trying to negate it again/) end end describe "#unstub" do it "replaces the stubbed method with the original method" do klass.any_instance.stub(:existing_method) klass.any_instance.unstub(:existing_method) expect(klass.new.existing_method).to eq(:existing_method_return_value) end it "removes all stubs with the supplied method name" do klass.any_instance.stub(:existing_method).with(1) klass.any_instance.stub(:existing_method).with(2) klass.any_instance.unstub(:existing_method) expect(klass.new.existing_method).to eq(:existing_method_return_value) end it "removes stubs even if they have already been invoked" do klass.any_instance.stub(:existing_method).and_return(:any_instance_value) obj = klass.new obj.existing_method klass.any_instance.unstub(:existing_method) expect(obj.existing_method).to eq(:existing_method_return_value) end it "removes stubs from sub class after Invocation when super class was originally stubbed" do klass.any_instance.stub(:existing_method).and_return(:any_instance_value) obj = Class.new(klass).new expect(obj.existing_method).to eq(:any_instance_value) klass.any_instance.unstub(:existing_method) expect(obj.existing_method).to eq(:existing_method_return_value) end it "removes stubs set directly on an instance" do klass.any_instance.stub(:existing_method).and_return(:any_instance_value) obj = klass.new obj.stub(:existing_method).and_return(:local_method) klass.any_instance.unstub(:existing_method) expect(obj.existing_method).to eq(:existing_method_return_value) end it "does not remove message expectations set directly on an instance" do klass.any_instance.stub(:existing_method).and_return(:any_instance_value) obj = klass.new obj.should_receive(:existing_method).and_return(:local_method) klass.any_instance.unstub(:existing_method) expect(obj.existing_method).to eq(:local_method) end it "does not remove any expectations with the same method name" do klass.any_instance.should_receive(:existing_method_with_arguments).with(3).and_return(:three) klass.any_instance.stub(:existing_method_with_arguments).with(1) klass.any_instance.stub(:existing_method_with_arguments).with(2) klass.any_instance.unstub(:existing_method_with_arguments) expect(klass.new.existing_method_with_arguments(3)).to eq(:three) end it "raises a MockExpectationError if the method has not been stubbed" do expect { klass.any_instance.unstub(:existing_method) }.to fail_with 'The method `existing_method` was not stubbed or was already unstubbed' end it 'does not get confused about string vs symbol usage for the message' do klass.any_instance.stub(:existing_method) { :stubbed } klass.any_instance.unstub("existing_method") expect(klass.new.existing_method).to eq(:existing_method_return_value) end end end end end RSpec.context "with default syntax configuration" do orig_syntax = nil before(:all) { orig_syntax = RSpec::Mocks.configuration.syntax } after(:all) { RSpec::Mocks.configuration.syntax = orig_syntax } before { RSpec::Mocks.configuration.reset_syntaxes_to_default } if RSpec::Support::RubyFeatures.required_kw_args_supported? let(:expected_arguments) { [ /Using.*without explicitly enabling/, ] } let(:expected_keywords) { {:replacement => "the new `:expect` syntax or explicitly enable `:should`"} } it "it warns about should once, regardless of how many times it is called" do # Use eval to avoid syntax error on 1.8 and 1.9 eval("expect(RSpec).to receive(:deprecate).with(*expected_arguments, **expected_keywords)") o = Object.new o2 = Object.new o.should_receive(:bees) o2.should_receive(:bees) o.bees o2.bees end it "warns about should not once, regardless of how many times it is called" do # Use eval to avoid syntax error on 1.8 and 1.9 eval("expect(RSpec).to receive(:deprecate).with(*expected_arguments, **expected_keywords)") o = Object.new o2 = Object.new o.should_not_receive(:bees) o2.should_not_receive(:bees) end it "warns about stubbing once, regardless of how many times it is called" do # Use eval to avoid syntax error on 1.8 and 1.9 eval("expect(RSpec).to receive(:deprecate).with(*expected_arguments, **expected_keywords)") o = Object.new o2 = Object.new o.stub(:faces) o2.stub(:faces) end else let(:expected_arguments) { [ /Using.*without explicitly enabling/, {:replacement => "the new `:expect` syntax or explicitly enable `:should`"} ] } it "it warns about should once, regardless of how many times it is called" do expect(RSpec).to receive(:deprecate).with(*expected_arguments) o = Object.new o2 = Object.new o.should_receive(:bees) o2.should_receive(:bees) o.bees o2.bees end it "warns about should not once, regardless of how many times it is called" do expect(RSpec).to receive(:deprecate).with(*expected_arguments) o = Object.new o2 = Object.new o.should_not_receive(:bees) o2.should_not_receive(:bees) end it "warns about stubbing once, regardless of how many times it is called" do expect(RSpec).to receive(:deprecate).with(*expected_arguments) o = Object.new o2 = Object.new o.stub(:faces) o2.stub(:faces) end end it "warns about unstubbing once, regardless of how many times it is called" do expect(RSpec).to receive(:deprecate).with(/Using.*without explicitly enabling/, :replacement => "`allow(...).to receive(...).and_call_original` or explicitly enable `:should`") o = Object.new o2 = Object.new allow(o).to receive(:faces) allow(o2).to receive(:faces) o.unstub(:faces) o2.unstub(:faces) end it "doesn't warn about stubbing after a reset and setting should" do expect(RSpec).not_to receive(:deprecate) RSpec::Mocks.configuration.reset_syntaxes_to_default RSpec::Mocks.configuration.syntax = :should o = Object.new o2 = Object.new o.stub(:faces) o2.stub(:faces) end it "includes the call site in the deprecation warning" do obj = Object.new expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) obj.stub(:faces) end end RSpec.context "when the should syntax is enabled on a non-default syntax host" do include_context "with the default mocks syntax" it "continues to warn about the should syntax" do my_host = Class.new expect(RSpec).to receive(:deprecate) RSpec::Mocks::Syntax.enable_should(my_host) o = Object.new o.should_receive(:bees) o.bees end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/any_instance/0000775000000000000000000000000014557670305024662 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/any_instance/message_chains_spec.rb0000664000000000000000000000277714557670305031207 0ustar rootrootRSpec.describe RSpec::Mocks::AnyInstance::MessageChains do let(:recorder) { double } let(:chains) { RSpec::Mocks::AnyInstance::MessageChains.new } let(:stub_chain) { RSpec::Mocks::AnyInstance::StubChain.new recorder } let(:expectation_chain) { RSpec::Mocks::AnyInstance::PositiveExpectationChain.new recorder } it "knows if a method does not have an expectation set on it" do chains.add(:method_name, stub_chain) expect(chains.has_expectation?(:method_name)).to be_falsey end it "knows if a method has an expectation set on it" do chains.add(:method_name, stub_chain) chains.add(:method_name, expectation_chain) expect(chains.has_expectation?(:method_name)).to be_truthy end it "can remove all stub chains" do chains.add(:method_name, stub_chain) chains.add(:method_name, expectation_chain) chains.add(:method_name, RSpec::Mocks::AnyInstance::StubChain.new(recorder)) chains.remove_stub_chains_for!(:method_name) expect(chains[:method_name]).to eq([expectation_chain]) end context "creating stub chains" do it "understands how to add a stub chain for a method" do chains.add(:method_name, stub_chain) expect(chains[:method_name]).to eq([stub_chain]) end it "allows multiple stub chains for a method" do chains.add(:method_name, stub_chain) chains.add(:method_name, another_stub_chain = RSpec::Mocks::AnyInstance::StubChain.new(recorder)) expect(chains[:method_name]).to eq([stub_chain, another_stub_chain]) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/methods_spec.rb0000664000000000000000000000145014557670305025211 0ustar rootrootmodule RSpec module Mocks RSpec.describe "Methods added to every object" do include_context "with syntax", :expect def added_methods host = Class.new orig_instance_methods = host.instance_methods Syntax.enable_should(host) (host.instance_methods - orig_instance_methods).map(&:to_sym) end it 'limits the number of methods that get added to all objects' do # If really necessary, you can add to this list, but long term, # we are hoping to cut down on the number of methods added to all objects expect(added_methods).to match_array([ :as_null_object, :null_object?, :received_message?, :should_not_receive, :should_receive, :stub, :stub_chain, :unstub ]) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/0000775000000000000000000000000014557670305025726 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/construction_spec.rb0000664000000000000000000001417614557670305032030 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'Constructing a verifying double' do include_context 'with isolated configuration' class ClassThatDynamicallyDefinesMethods def self.define_attribute_methods! define_method(:some_method_defined_dynamically) { true } end end module CustomModule end describe 'instance doubles' do it 'cannot be constructed with a non-module object' do expect { instance_double(Object.new) }.to raise_error(/Module or String expected/) end it 'can be constructed with a struct' do o = instance_double(Struct.new(:defined_method), :defined_method => 1) expect(o.defined_method).to eq(1) end it 'allows named constants to be looked up and declared to verifying double callbacks' do expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.verify_doubled_constant_names = true config.when_declaring_verifying_double(&probe) end instance_double("RSpec::Mocks::ClassThatDynamicallyDefinesMethods") }.to yield_with_args(have_attributes :target => ClassThatDynamicallyDefinesMethods) end it 'allows anonymous constants to be looked up and declared to verifying double callbacks' do anonymous_module = Module.new expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.verify_doubled_constant_names = true config.when_declaring_verifying_double(&probe) end instance_double(anonymous_module) }.to yield_with_args(have_attributes :target => anonymous_module) end it 'allows classes to be customised' do test_class = Class.new(ClassThatDynamicallyDefinesMethods) RSpec.configuration.mock_with(:rspec) do |config| config.when_declaring_verifying_double do |reference| reference.target.define_attribute_methods! end end instance_double(test_class, :some_method_defined_dynamically => true) end describe 'any_instance' do let(:test_class) { Class.new(ClassThatDynamicallyDefinesMethods) } let(:not_implemented_error) { "#{test_class} does not implement #some_invalid_method" } before(:each) do RSpec.configuration.mock_with(:rspec) do |config| config.verify_partial_doubles = true config.when_declaring_verifying_double do |reference| reference.target.define_attribute_methods! if reference.target == test_class end end end it 'calls the callback for expect_any_instance_of' do expect_any_instance_of(test_class).to receive(:some_method_defined_dynamically) expect { expect_any_instance_of(test_class).to receive(:some_invalid_method) }.to raise_error(RSpec::Mocks::MockExpectationError, not_implemented_error) expect(test_class.new.some_method_defined_dynamically).to eq(nil) end it 'calls the callback for allow_any_instance_of' do allow_any_instance_of(test_class).to receive(:some_method_defined_dynamically) expect { allow_any_instance_of(test_class).to receive(:some_invalid_method) }.to raise_error(RSpec::Mocks::MockExpectationError, not_implemented_error) expect(test_class.new.some_method_defined_dynamically).to eq(nil) end it 'should not call the callback if verify_partial_doubles is off' do RSpec.configuration.mock_with(:rspec) do |config| config.verify_partial_doubles = false end expect(test_class.method_defined?(:some_method_defined_dynamically)).to be_falsey end end end describe 'class doubles' do it 'cannot be constructed with a non-module object' do expect { class_double(Object.new) }.to raise_error(/Module or String expected/) end it 'declares named modules to verifying double callbacks' do expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.when_declaring_verifying_double(&probe) end class_double CustomModule }.to yield_with_args(have_attributes :target => CustomModule) end it 'declares anonymous modules to verifying double callbacks' do anonymous_module = Module.new expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.when_declaring_verifying_double(&probe) end class_double anonymous_module }.to yield_with_args(have_attributes :target => anonymous_module) end end describe 'object doubles' do it 'declares the class to verifying double callbacks' do object = Object.new expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.when_declaring_verifying_double(&probe) end object_double object }.to yield_with_args(have_attributes :target => object) end end describe 'when verify_doubled_constant_names config option is set' do before do RSpec::Mocks.configuration.verify_doubled_constant_names = true end it 'prevents creation of instance doubles for unloaded constants' do expect { instance_double('LoadedClas') }.to raise_error(VerifyingDoubleNotDefinedError) end it 'prevents creation of class doubles for unloaded constants' do expect { class_double('LoadedClas') }.to raise_error(VerifyingDoubleNotDefinedError) end end it 'can only be named with a string or a module' do expect { instance_double(1) }.to raise_error(ArgumentError) expect { instance_double(nil) }.to raise_error(ArgumentError) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/object_double_spec.rb0000664000000000000000000001271714557670305032075 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'An object double' do let(:loaded_instance) { LoadedClass.new(1, 2) } it 'can replace an unloaded constant' do o = object_double("LoadedClass::NOINSTANCE").as_stubbed_const expect(LoadedClass::NOINSTANCE).to eq(o) expect(o).to receive(:undefined_instance_method) o.undefined_instance_method end it 'can replace a constant by name and verify instance methods' do o = object_double("LoadedClass::INSTANCE").as_stubbed_const expect(LoadedClass::INSTANCE).to eq(o) prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_class_method) } prevents { o.defined_instance_method } expect(o).to receive(:defined_instance_method) o.defined_instance_method expect(o).to receive(:defined_private_method) o.send :defined_private_method end it 'can create a double that matches the interface of any arbitrary object' do o = object_double(loaded_instance) prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_class_method) } prevents { o.defined_instance_method } expect(o).to receive(:defined_instance_method) o.defined_instance_method expect(o).to receive(:defined_private_method) o.send :defined_private_method end it 'does not allow transferring constants to an object' do expect { object_double("LoadedClass::INSTANCE"). as_stubbed_const(:transfer_nested_constants => true) }.to raise_error(/Cannot transfer nested constants/) end it 'does not allow as_stubbed_constant for real objects' do expect { object_double(loaded_instance).as_stubbed_const }.to raise_error(/Can not perform constant replacement with an anonymous object/) end it 'is not a module' do expect(object_double("LoadedClass::INSTANCE")).to_not be_a(Module) end it 'validates `with` args against the method signature when stubbing a method' do dbl = object_double(loaded_instance) prevents(/Wrong number of arguments. Expected 2, got 3./) { allow(dbl).to receive(:instance_method_with_two_args).with(3, :foo, :args) } end context "when a loaded object constant has previously been stubbed with an object" do before { stub_const("LoadedClass::INSTANCE", Object.new) } it "uses the original object to verify against for `object_double('ConstName')`" do o = object_double("LoadedClass::INSTANCE") allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_meth) } end it "uses the stubbed const value to verify against for `object_double(ConstName)`, " \ "which probably isn't what the user wants, but there's nothing else we can do since " \ "we can't get the constant name from the given object and thus cannot interrogate " \ "our stubbed const registry to see it has been stubbed" do o = object_double(LoadedClass::INSTANCE) prevents { allow(o).to receive(:defined_instance_method) } end end context "when a loaded object constant has previously been stubbed with a class" do before { stub_const("LoadedClass::INSTANCE", Class.new) } it "uses the original object to verify against for `object_double('ConstName')`" do o = object_double("LoadedClass::INSTANCE") allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_meth) } end it "uses the original object to verify against for `object_double(ConstName)`" do o = object_double(LoadedClass::INSTANCE) allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_meth) } end end context "when an unloaded object constant has previously been stubbed with an object" do before { stub_const("LoadedClass::NOINSTANCE", LoadedClass::INSTANCE) } it "treats it as being unloaded for `object_double('ConstName')`" do o = object_double("LoadedClass::NOINSTANCE") allow(o).to receive(:undefined_method) end it "uses the stubbed const value to verify against for `object_double(ConstName)`, " \ "which probably isn't what the user wants, but there's nothing else we can do since " \ "we can't get the constant name from the given object and thus cannot interrogate " \ "our stubbed const registry to see it has been stubbed" do o = object_double(LoadedClass::NOINSTANCE) allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_method) } end end context "when an unloaded object constant has previously been stubbed with a class" do before { stub_const("LoadedClass::NOINSTANCE", Class.new) } it "treats it as being unloaded for `object_double('ConstName')`" do o = object_double("LoadedClass::NOINSTANCE") allow(o).to receive(:undefined_method) end it "treats it as being unloaded for `object_double(ConstName)`" do o = object_double(LoadedClass::NOINSTANCE) allow(o).to receive(:undefined_method) end end end end end ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/class_double_with_class_loaded_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/class_double_with_clas0000664000000000000000000001766114557670305032360 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'A class double with the doubled class loaded' do include_context "with isolated configuration" before do RSpec::Mocks.configuration.verify_doubled_constant_names = true end it 'only allows class methods that exist to be stubbed' do o = class_double('LoadedClass', :defined_class_method => 1) expect(o.defined_class_method).to eq(1) prevents { allow(o).to receive(:undefined_instance_method) } prevents { allow(o).to receive(:defined_instance_method) } end it 'only allows class methods that exist to be expected' do o = class_double('LoadedClass') expect(o).to receive(:defined_class_method) o.defined_class_method prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_instance_method) } prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_instance_method) } end USE_INSTANCE_DOUBLE_MSG = "Perhaps you meant to use `instance_double`" it "suggests using `instance_double` when an instance method is stubbed" do o = class_double("LoadedClass") prevents(a_string_including(USE_INSTANCE_DOUBLE_MSG)) { allow(o).to receive(:defined_instance_method) } end it "doesn't suggest `instance_double` when a non-instance method is stubbed'" do o = class_double("LoadedClass") prevents(a_string_excluding(USE_INSTANCE_DOUBLE_MSG)) { allow(o).to receive(:undefined_instance_method) } end it 'gives a descriptive error message for NoMethodError' do o = class_double("LoadedClass") expect { o.defined_private_class_method }.to raise_error(NoMethodError, a_string_including("ClassDouble(LoadedClass)")) end it 'checks that stubbed methods are invoked with the correct arity' do o = class_double('LoadedClass', :defined_class_method => 1) expect { o.defined_class_method(:a) }.to raise_error(ArgumentError) end it 'allows dynamically defined class method stubs with arguments' do o = class_double('LoadedClass') allow(o).to receive(:dynamic_class_method).with(:a) { 1 } expect(o.dynamic_class_method(:a)).to eq(1) end it 'allows dynamically defined class method mocks with arguments' do o = class_double('LoadedClass') expect(o).to receive(:dynamic_class_method).with(:a) o.dynamic_class_method(:a) end it 'allows dynamically defined class methods to be expected' do o = class_double('LoadedClass', :dynamic_class_method => 1) expect(o.dynamic_class_method).to eq(1) end it 'allows class to be specified by constant' do o = class_double(LoadedClass, :defined_class_method => 1) expect(o.defined_class_method).to eq(1) end it 'can replace existing constants for the duration of the test' do original = LoadedClass object = class_double('LoadedClass').as_stubbed_const expect(object).to receive(:defined_class_method) expect(LoadedClass).to eq(object) ::RSpec::Mocks.teardown ::RSpec::Mocks.setup expect(LoadedClass).to eq(original) end it 'can transfer nested constants to the double' do class_double("LoadedClass"). as_stubbed_const(:transfer_nested_constants => true) expect(LoadedClass::M).to eq(:m) expect(LoadedClass::N).to eq(:n) end it 'correctly verifies expectations when constant is removed' do dbl1 = class_double(LoadedClass::Nested).as_stubbed_const class_double(LoadedClass).as_stubbed_const prevents { expect(dbl1).to receive(:undefined_class_method) } end it 'only allows defined methods for null objects' do o = class_double('LoadedClass').as_null_object expect(o.defined_class_method).to eq(o) prevents { o.undefined_method } end it 'verifies arguments for null objects' do o = class_double('LoadedClass').as_null_object expect { o.defined_class_method(:too, :many, :args) }.to raise_error(ArgumentError, "Wrong number of arguments. Expected 0, got 3.") end it 'validates `with` args against the method signature when stubbing a method' do dbl = class_double(LoadedClass) prevents(/Wrong number of arguments. Expected 0, got 2./) { allow(dbl).to receive(:defined_class_method).with(2, :args) } end context "when `.new` is stubbed" do before do expect(LoadedClass.instance_method(:initialize).arity).to eq(2) end it 'uses the method signature from `#initialize` for arg verification' do o = class_double(LoadedClass) prevents(/arguments/) { allow(o).to receive(:new).with(1) } allow(o).to receive(:new).with(1, 2) end context "on a class that has redefined `new`" do it "uses the method signature of the redefined `new` for arg verification" do klass = Class.new(LoadedClass) do def self.new(_); end end o = class_double(klass) prevents(/arguments/) { allow(o).to receive(:new).with(1, 2) } allow(o).to receive(:new).with(1) end end context "on a class that has undefined `new`" do it "prevents it from being stubbed" do klass = Class.new(LoadedClass) do class << self undef new end end o = class_double(klass) prevents(/does not implement the class method/) { allow(o).to receive(:new).with(1, 2) } end end context "on a class with a private `new`" do it 'uses the method signature from `#initialize` for arg verification' do if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version < '9.2.1.0' pending "Failing on JRuby due to https://github.com/jruby/jruby/issues/2565" end klass = Class.new(LoadedClass) do private_class_method :new end o = class_double(klass) prevents(/arguments/) { allow(o).to receive(:new).with(1) } allow(o).to receive(:new).with(1, 2) end end end context "when given an anonymous class" do it 'properly verifies' do subclass = Class.new(LoadedClass) o = class_double(subclass) allow(o).to receive(:defined_class_method) prevents { allow(o).to receive(:undefined_method) } end end context "when given a class that has an overridden `#name` method" do it "properly verifies" do check_verification class_double(LoadedClassWithOverriddenName) end it "can still stub the const" do class_double(LoadedClassWithOverriddenName).as_stubbed_const check_verification LoadedClassWithOverriddenName end def check_verification(o) allow(o).to receive(:defined_class_method) prevents { allow(o).to receive(:undefined_method) } end end context "when the class const has been previously stubbed" do before { stub_const("LoadedClass", Class.new) } it "uses the original class to verify against for `class_double('ClassName')`" do o = class_double("LoadedClass") allow(o).to receive(:defined_class_method) prevents { allow(o).to receive(:undefined_method) } end it "uses the original class to verify against for `instance_double(ClassName)`" do o = class_double(LoadedClass) allow(o).to receive(:defined_class_method) prevents { allow(o).to receive(:undefined_method) } end end end end end ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verificat0000664000000000000000000001517214557670305032345 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'Expected argument verification (when `#with` is called)' do # Note: these specs here aren't meant to be exhaustive. The specs in # rspec-support for the method signature verifier are. Here we are just # covering the code paths within the `with` implementation, including # the special handling for `any_args` and `no_args`. context "when doubling an unloaded class" do it 'allows any arguments' do expect(defined?(UnloadedClass)).to be_falsey inst_dbl = instance_double("UnloadedClass") expect { expect(inst_dbl).to receive(:message).with(:foo, :bar, :bazz) }.not_to raise_error reset inst_dbl end end context "when doubling a loaded class" do let(:dbl) { instance_double(LoadedClass) } after { reset dbl } context "when `any_args` is used" do context "as the only argument" do it "is allowed regardless of how many args the method requires" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(any_args) }.not_to raise_error end end context "as the first argument, with too many additional args" do it "is disallowed" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1, 2, 3) }.to fail_with("Wrong number of arguments. Expected 2, got 3.") end end context "as the first argument, with an allowed number of additional args" do it "is allowed" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1, 2) }.not_to raise_error expect { expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1) }.not_to raise_error end end end context "when `no_args` is used" do it "allows a method expectation on a method that accepts no arguments" do expect(LoadedClass.instance_method(:defined_instance_method).arity).to eq(0) expect { expect(dbl).to receive(:defined_instance_method).with(no_args) }.not_to raise_error end it "allows a method expectation on a method that has defaults for all arguments" do expect { expect(dbl).to receive(:instance_method_with_only_defaults).with(no_args) }.not_to raise_error end it "does not allow a method expectation on a method that has required arguments" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(no_args) }.to fail_with("Wrong number of arguments. Expected 2, got 0.") end if RSpec::Support::RubyFeatures.required_kw_args_supported? context "for a method with required keyword args" do it 'covers the required args when `any_args` is last' do expect { expect(dbl).to receive(:kw_args_method).with(1, any_args) }.not_to raise_error end it 'does not cover the required args when there are args after `any_args`' do expect { # Use eval to avoid syntax error on 1.8 and 1.9 eval("expect(dbl).to receive(:kw_args_method).with(any_args, optional_arg: 3)") }.to fail_with("Missing required keyword arguments: required_arg") end end end end if RSpec::Support::RubyFeatures.required_kw_args_supported? it 'does not cover required args when `any_args` is not used' do expect { expect(dbl).to receive(:kw_args_method).with(anything) }.to fail_with("Missing required keyword arguments: required_arg") end end context "when a list of args is provided" do it "allows a method expectation when the arity matches" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(1, 2) }.not_to raise_error end it "does not allow a method expectation with an arity mismatch" do expect { expect(dbl).to receive(:instance_method_with_two_args).with(1, 2, 3) }.to fail_with("Wrong number of arguments. Expected 2, got 3.") end end context "when `with` is called with no args" do it "fails with an error suggesting the user use `no_args` instead" do expect { expect(dbl).to receive(:instance_method_with_two_args).with }.to raise_error(ArgumentError, /no_args/) end end if RSpec::Support::RubyFeatures.required_kw_args_supported? context "for a method with keyword args" do it "matches against a hash submitted as keyword arguments and received as positional argument (in both Ruby 2 and Ruby 3)" do expect(dbl).to receive(:kw_args_method).with(1, {:required_arg => 2, :optional_arg => 3}) dbl.kw_args_method(1, :required_arg => 2, :optional_arg => 3) end if RUBY_VERSION >= "3" it "fails to match against a hash submitted as a positional argument and received as keyword arguments in Ruby 3.0 or later", :reset => true do expect(dbl).to receive(:kw_args_method).with(1, :required_arg => 2, :optional_arg => 3) expect do dbl.kw_args_method(1, {:required_arg => 2, :optional_arg => 3}) end.to fail_with(a_string_including("expected: (1, {:optional_arg=>3, :required_arg=>2}) (keyword arguments)", "got: (1, {:optional_arg=>3, :required_arg=>2}) (options hash)")) end else it "matches against a hash submitted as a positional argument and received as keyword arguments in Ruby 2.7 or before" do expect(dbl).to receive(:kw_args_method).with(1, :required_arg => 2, :optional_arg => 3) dbl.kw_args_method(1, {:required_arg => 2, :optional_arg => 3}) end end context "when using `send`" do let(:dbl) { instance_double(Class.new { eval "def m(k:); end" }) } it "matches against keyword arguments" do expect(dbl).to receive(:m).with(:k => 1) dbl.send(:m, :k => 1) end end end end end end end end ././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/class_double_with_class_not_loaded_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/class_double_with_clas0000664000000000000000000000441714557670305032353 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'A class double with the doubled class not loaded' do include_context "with isolated configuration" before do RSpec::Mocks.configuration.verify_doubled_constant_names = false end it 'includes the double name in errors for unexpected messages' do o = class_double("NonLoadedClass") expect { o.foo }.to fail_including('ClassDouble(NonLoadedClass)') end it 'allows any method to be stubbed' do o = class_double('NonloadedClass') allow(o).to receive(:undefined_instance_method).with(:arg).and_return(1) expect(o.undefined_instance_method(:arg)).to eq(1) end specify "trying to raise a class_double raises a TypeError", :unless => RUBY_VERSION == '1.9.2' do subject = Object.new class_double("StubbedError").as_stubbed_const allow(subject).to receive(:some_method).and_raise(StubbedError) expect { subject.some_method }.to raise_error(TypeError, 'exception class/object expected') end context "when stubbing a private module method" do before(:all) do Module.class_exec do private def use; end end end after(:all) do Module.class_exec do undef use end end it 'can mock private module methods' do double = Module.new allow(double).to receive(:use) expect { double.use }.to raise_error(/private method `use' called/) double = class_double("NonloadedClass") expect(double).to receive(:use).and_return(:ok) expect(double.use).to be(:ok) end end context "when the class const has been previously stubbed" do before { stub_const("NonLoadedClass", Class.new) } it "treats the class as being unloaded for `class_double('NonLoadedClass')`" do o = class_double("NonLoadedClass") allow(o).to receive(:undefined_method) end it "treats the class as being unloaded for `instance_double(NonLoadedClass)`" do o = class_double(NonLoadedClass) allow(o).to receive(:undefined_method) end end end end end ././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/instance_double_with_class_not_loaded_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/instance_double_with_c0000664000000000000000000000441614557670305032351 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'An instance double with the doubled class not loaded' do include_context "with isolated configuration" before do RSpec::Mocks.configuration.verify_doubled_constant_names = false end it 'includes the doubled module in errors for unexpected messages' do o = instance_double("NonLoadedClass") expect { o.foo }.to fail_including('InstanceDouble(NonLoadedClass)') end it 'allows any instance method to be stubbed' do o = instance_double('NonloadedClass') allow(o).to receive(:undefined_instance_method).with(:arg).and_return(true) expect(o.undefined_instance_method(:arg)).to eq(true) end it 'allows any instance method to be expected' do o = instance_double("NonloadedClass") expect(o).to receive(:undefined_instance_method). with(:arg). and_return(true) expect(o.undefined_instance_method(:arg)).to eq(true) end it 'handles classes that are materialized after mocking' do stub_const "A::B", Object.new o = instance_double "A", :undefined_instance_method => true expect(o.undefined_instance_method).to eq(true) end context 'for null objects' do let(:obj) { instance_double('NonLoadedClass').as_null_object } it 'returns self from any message' do expect(obj.a.b.c).to be(obj) end it 'reports it responds to any message' do expect(obj.respond_to?(:a)).to be true expect(obj.respond_to?(:a, false)).to be true expect(obj.respond_to?(:a, true)).to be true end end context "when the class const has been previously stubbed" do before { class_double("NonLoadedClass").as_stubbed_const } it "treats the class as unloaded for `instance_double('NonLoadedClass')`" do o = instance_double("NonLoadedClass") allow(o).to receive(:undefined_method) end it "treats the class as unloaded for `instance_double(NonLoadedClass)`" do o = instance_double(NonLoadedClass) allow(o).to receive(:undefined_method) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/naming_spec.rb0000664000000000000000000000505414557670305030542 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec::Matchers.define :fail_expectations_as do |expected| description { "include a meaningful name in the exception" } def error_message_for(_) expect(actual).to have_received(:defined_instance_and_class_method) rescue MockExpectationError, Expectations::ExpectationNotMetError => e e.message else raise("should have failed but did not") end failure_message do |actual| "expected #{actual.inspect} to fail expectations as:\n" \ " #{expected.inspect}, but failed with:\n" \ " #{@error_message.inspect}" end match do |actual| @error_message = error_message_for(actual) @error_message.include?(expected) end end RSpec.describe 'Verified double naming' do shared_examples "a named verifying double" do |type_desc| context "when a name is given as a string" do subject { create_double("LoadedClass", "foo") } it { is_expected.to fail_expectations_as(%Q{#{type_desc}(LoadedClass) "foo"}) } end context "when a name is given as a symbol" do subject { create_double("LoadedClass", :foo) } it { is_expected.to fail_expectations_as(%Q{#{type_desc}(LoadedClass) :foo}) } end context "when no name is given" do subject { create_double("LoadedClass") } it { is_expected.to fail_expectations_as(%Q{#{type_desc}(LoadedClass) (anonymous)}) } end end describe "instance_double" do it_behaves_like "a named verifying double", "InstanceDouble" do alias :create_double :instance_double end end describe "instance_spy" do it_behaves_like "a named verifying double", "InstanceDouble" do alias :create_double :instance_spy end end describe "class_double" do it_behaves_like "a named verifying double", "ClassDouble" do alias :create_double :class_double end end describe "class_spy" do it_behaves_like "a named verifying double", "ClassDouble" do alias :create_double :class_spy end end describe "object_double" do it_behaves_like "a named verifying double", "ObjectDouble" do alias :create_double :object_double end end describe "object_spy" do it_behaves_like "a named verifying double", "ObjectDouble" do alias :create_double :object_spy end end end end end ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/method_visibility_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/method_visibility_spec0000664000000000000000000001144014557670305032412 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe "Method visibility for verified doubles" do include_context "with isolated configuration" before do RSpec::Mocks.configuration.verify_doubled_constant_names = true end context "for an instance double (when the class is loaded)" do shared_examples "preserves method visibility" do |visibility| method_name = :"defined_#{visibility}_method" it "can allow a #{visibility} instance method" do o = instance_double('LoadedClass') allow(o).to receive(method_name).and_return(3) expect(o.send method_name).to eq(3) end it "can expect a #{visibility} instance method" do o = instance_double('LoadedClass') expect(o).to receive(method_name) o.send method_name end it "preserves #{visibility} visibility when allowing a #{visibility} method" do preserves_visibility(method_name, visibility) do instance_double('LoadedClass').tap do |o| allow(o).to receive(method_name) end end end it "preserves #{visibility} visibility when expecting a #{visibility} method" do preserves_visibility(method_name, visibility) do instance_double('LoadedClass').tap do |o| expect(o).to receive(method_name).at_least(:once) o.send(method_name) # to satisfy the expectation end end end it "preserves #{visibility} visibility on a null object" do preserves_visibility(method_name, visibility) do instance_double('LoadedClass').as_null_object end end end include_examples "preserves method visibility", :private include_examples "preserves method visibility", :protected end context "for a class double (when the class is loaded)" do shared_examples "preserves method visibility" do |visibility| method_name = :"defined_#{visibility}_class_method" it "can allow a #{visibility} instance method" do o = class_double('LoadedClass') allow(o).to receive(method_name).and_return(3) expect(o.send method_name).to eq(3) end it "can expect a #{visibility} instance method" do o = class_double('LoadedClass') expect(o).to receive(method_name) o.send method_name end it "preserves #{visibility} visibility when allowing a #{visibility} method" do preserves_visibility(method_name, visibility) do class_double('LoadedClass').tap do |o| allow(o).to receive(method_name) end end end it "preserves #{visibility} visibility when expecting a #{visibility} method" do preserves_visibility(method_name, visibility) do class_double('LoadedClass').tap do |o| expect(o).to receive(method_name).at_least(:once) o.send(method_name) # to satisfy the expectation end end end it "preserves #{visibility} visibility on a null object" do preserves_visibility(method_name, visibility) do class_double('LoadedClass').as_null_object end end end include_examples "preserves method visibility", :private include_examples "preserves method visibility", :protected end def preserves_visibility(method_name, visibility) double = yield expect { # send bypasses visibility, so we use eval instead. eval("double.#{method_name}") }.to raise_error(NoMethodError, a_message_indicating_visibility_violation(method_name, visibility)) expect { double.send(method_name) }.not_to raise_error expect { double.__send__(method_name) }.not_to raise_error unless double.null_object? # Null object doubles use `method_missing` and so the singleton class # doesn't know what methods are defined. singleton_class = class << double; self; end expect(singleton_class.send("#{visibility}_method_defined?", method_name)).to be true end end RSpec::Matchers.define :a_message_indicating_visibility_violation do |method_name, visibility| match do |msg| # This should NOT Be just `msg.match(visibility)` because the method being called # has the visibility name in it. We want to ensure it's a message that ruby is # stating is of the given visibility. msg.match("#{visibility} ") && msg.match(method_name.to_s) end end end end end ././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/instance_double_with_class_loaded_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/verifying_doubles/instance_double_with_c0000664000000000000000000002274714557670305032360 0ustar rootrootrequire 'support/doubled_classes' module RSpec module Mocks RSpec.describe 'An instance double with the doubled class loaded' do include_context "with isolated configuration" before do RSpec::Mocks.configuration.verify_doubled_constant_names = true end it 'only allows instance methods that exist to be stubbed' do o = instance_double('LoadedClass', :defined_instance_method => 1) expect(o.defined_instance_method).to eq(1) prevents(/does not implement the instance method/) { allow(o).to receive(:undefined_instance_method) } prevents(/does not implement the instance method/) { allow(o).to receive(:defined_class_method) } end it 'only allows instance methods that exist to be expected' do o = instance_double('LoadedClass') expect(o).to receive(:defined_instance_method) o.defined_instance_method prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_class_method) } prevents { expect(o).to receive(:undefined_instance_method) } prevents { expect(o).to receive(:defined_class_method) } end USE_CLASS_DOUBLE_MSG = "Perhaps you meant to use `class_double`" it "suggests using `class_double` when a class method is stubbed" do o = instance_double("LoadedClass") prevents(a_string_including(USE_CLASS_DOUBLE_MSG)) { allow(o).to receive(:defined_class_method) } end it "doesn't suggest `class_double` when a non-class method is stubbed" do o = instance_double("LoadedClass") prevents(a_string_excluding(USE_CLASS_DOUBLE_MSG)) { allow(o).to receive(:undefined_class_method) } end it 'allows `send` to be stubbed if it is defined on the class' do o = instance_double('LoadedClass') allow(o).to receive(:send).and_return("received") expect(o.send(:msg)).to eq("received") end it 'gives a descriptive error message for NoMethodError' do o = instance_double("LoadedClass") expect { o.defined_private_method }.to raise_error(NoMethodError, a_string_including("InstanceDouble(LoadedClass)")) end it 'does not allow dynamic methods to be expected' do # This isn't possible at the moment since an instance of the class # would be required for the verification, and we only have the # class itself. # # This spec exists as "negative" documentation of the absence of a # feature, to highlight the asymmetry from class doubles (that do # support this behaviour). prevents { instance_double('LoadedClass', :dynamic_instance_method => 1) } end it 'checks the arity of stubbed methods' do o = instance_double('LoadedClass') prevents { expect(o).to receive(:defined_instance_method).with(:a) } reset o end it 'checks that stubbed methods are invoked with the correct arity' do o = instance_double('LoadedClass', :defined_instance_method => 25) expect { o.defined_instance_method(:a) }.to raise_error(ArgumentError, "Wrong number of arguments. Expected 0, got 1.") end if required_kw_args_supported? it 'allows keyword arguments' do o = instance_double('LoadedClass', :kw_args_method => true) expect(o.kw_args_method(1, :required_arg => 'something')).to eq(true) end context 'for a method that only accepts keyword args' do it 'allows hash matchers like `hash_including` to be used in place of the keywords arg hash' do o = instance_double('LoadedClass') expect(o).to receive(:kw_args_method). with(1, hash_including(:required_arg => 1)) o.kw_args_method(1, :required_arg => 1) end it 'allows anything matcher to be used in place of the keywords arg hash' do o = instance_double('LoadedClass') expect(o).to receive(:kw_args_method).with(1, anything) o.kw_args_method(1, :required_arg => 1) end it 'still checks positional arguments when matchers used for keyword args' do o = instance_double('LoadedClass') prevents(/Expected 1, got 3/) { expect(o).to receive(:kw_args_method). with(1, 2, 3, hash_including(:required_arg => 1)) } reset o end it 'does not allow matchers to be used in an actual method call' do o = instance_double('LoadedClass') matcher = hash_including(:required_arg => 1) allow(o).to receive(:kw_args_method).with(1, matcher) expect { o.kw_args_method(1, matcher) }.to raise_error(ArgumentError) end end context 'for a method that accepts a mix of optional keyword and positional args' do it 'allows hash matchers like `hash_including` to be used in place of the keywords arg hash' do o = instance_double('LoadedClass') expect(o).to receive(:mixed_args_method).with(1, 2, hash_including(:optional_arg_1 => 1)) o.mixed_args_method(1, 2, :optional_arg_1 => 1) end end it 'checks that stubbed methods with required keyword args are ' \ 'invoked with the required arguments' do o = instance_double('LoadedClass', :kw_args_method => true) expect { o.kw_args_method(:optional_arg => 'something') }.to raise_error(ArgumentError) end end it 'validates `with` args against the method signature when stubbing a method' do dbl = instance_double(LoadedClass) prevents(/Wrong number of arguments. Expected 2, got 3./) { allow(dbl).to receive(:instance_method_with_two_args).with(3, :foo, :args) } end it 'allows class to be specified by constant' do o = instance_double(LoadedClass, :defined_instance_method => 1) expect(o.defined_instance_method).to eq(1) end context "when the class const has been previously stubbed" do before { class_double(LoadedClass).as_stubbed_const } it "uses the original class to verify against for `instance_double('LoadedClass')`" do o = instance_double("LoadedClass") allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_method) } end it "uses the original class to verify against for `instance_double(LoadedClass)`" do o = instance_double(LoadedClass) allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_method) } end end context "when given a class that has an overridden `#name` method" do it "properly verifies" do o = instance_double(LoadedClassWithOverriddenName) allow(o).to receive(:defined_instance_method) prevents { allow(o).to receive(:undefined_method) } end end context 'for null objects' do let(:obj) { instance_double('LoadedClass').as_null_object } it 'only allows defined methods' do expect(obj.defined_instance_method).to eq(obj) prevents { obj.undefined_method } prevents { obj.send(:undefined_method) } prevents { obj.__send__(:undefined_method) } end it 'verifies arguments' do expect { obj.defined_instance_method(:too, :many, :args) }.to raise_error(ArgumentError, "Wrong number of arguments. Expected 0, got 3.") end it "includes the double's name in a private method error" do expect { obj.rand }.to raise_error(NoMethodError, a_string_including("private", "InstanceDouble(LoadedClass)")) end it 'reports what public messages it responds to accurately' do expect(obj.respond_to?(:defined_instance_method)).to be true expect(obj.respond_to?(:defined_instance_method, true)).to be true expect(obj.respond_to?(:defined_instance_method, false)).to be true expect(obj.respond_to?(:undefined_method)).to be false expect(obj.respond_to?(:undefined_method, true)).to be false expect(obj.respond_to?(:undefined_method, false)).to be false end it 'reports that it responds to defined private methods when the appropriate arg is passed' do expect(obj.respond_to?(:defined_private_method)).to be false expect(obj.respond_to?(:defined_private_method, true)).to be true expect(obj.respond_to?(:defined_private_method, false)).to be false end if RUBY_VERSION.to_f < 2.0 # respond_to?(:protected_method) changed behavior in Ruby 2.0. it 'reports that it responds to protected methods' do expect(obj.respond_to?(:defined_protected_method)).to be true expect(obj.respond_to?(:defined_protected_method, true)).to be true expect(obj.respond_to?(:defined_protected_method, false)).to be true end else it 'reports that it responds to protected methods when the appropriate arg is passed' do expect(obj.respond_to?(:defined_protected_method)).to be false expect(obj.respond_to?(:defined_protected_method, true)).to be true expect(obj.respond_to?(:defined_protected_method, false)).to be false end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/at_most_spec.rb0000664000000000000000000001060114557670305025212 0ustar rootrootmodule RSpec module Mocks RSpec.describe "at_most" do before(:each) do @double = double end it "passes when at_most(n) is called exactly 1 time" do expect(@double).to receive(:do_something).at_most(1).time @double.do_something verify @double end it "passes when at_most(n) is called exactly n times" do expect(@double).to receive(:do_something).at_most(2).times @double.do_something @double.do_something verify @double end it "passes when at_most(n) is called less than n times" do expect(@double).to receive(:do_something).at_most(2).times @double.do_something verify @double end it "passes when at_most(n) is never called" do expect(@double).to receive(:do_something).at_most(2).times verify @double end it "passes when at_most(:once) is called once" do expect(@double).to receive(:do_something).at_most(:once) @double.do_something verify @double end it "passes when at_most(:once) is never called" do expect(@double).to receive(:do_something).at_most(:once) verify @double end it "passes when at_most(:twice) is called once" do expect(@double).to receive(:do_something).at_most(:twice) @double.do_something verify @double end it "passes when at_most(:twice) is called twice" do expect(@double).to receive(:do_something).at_most(:twice) @double.do_something @double.do_something verify @double end it "passes when at_most(:twice) is never called" do expect(@double).to receive(:do_something).at_most(:twice) verify @double end it "passes when at_most(:thrice) is called less than three times" do expect(@double).to receive(:do_something).at_most(:thrice) @double.do_something verify @double end it "passes when at_most(:thrice) is called thrice" do expect(@double).to receive(:do_something).at_most(:thrice) @double.do_something @double.do_something @double.do_something verify @double end it "returns the value given by a block when at_most(:once) method is called" do expect(@double).to receive(:to_s).at_most(:once) { "testing" } expect(@double.to_s).to eq "testing" verify @double end it "fails fast when at_most(n) times method is called n plus 1 times" do expect(@double).to receive(:do_something).at_most(2).times @double.do_something @double.do_something expect_fast_failure_from(@double, /expected: at most 2 times.*received: 3 times/m) do @double.do_something end end it "fails fast when at_most(n) times method is called n plus 1 time" do expect(@double).to receive(:do_something).at_most(1).time @double.do_something expect_fast_failure_from(@double, /expected: at most 1 time.*received: 2 times/m) do @double.do_something end end it "fails fast when at_most(:once) and is called twice" do expect(@double).to receive(:do_something).at_most(:once) @double.do_something expect_fast_failure_from(@double, /expected: at most 1 time.*received: 2 times/m) do @double.do_something end end it "fails fast when at_most(:twice) and is called three times" do expect(@double).to receive(:do_something).at_most(:twice) @double.do_something @double.do_something expect_fast_failure_from(@double, /expected: at most 2 times.*received: 3 times/m) do @double.do_something end end it "fails fast when at_most(:thrice) and is called four times" do expect(@double).to receive(:do_something).at_most(:thrice) @double.do_something @double.do_something @double.do_something expect_fast_failure_from(@double, /expected: at most 3 times.*received: 4 times/m) do @double.do_something end end context "when called with negative expectation" do it "raises an error" do expect { expect(@double).not_to receive(:do_something).at_most(:thrice) }.to raise_error(/`count` is not supported with negative message expectations/) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/null_object_double_spec.rb0000664000000000000000000001031014557670305027373 0ustar rootrootmodule RSpec module Mocks RSpec.describe "a double _not_ acting as a null object" do before(:each) do @double = double('non-null object') end it "says it does not respond to messages it doesn't understand" do expect(@double).not_to respond_to(:foo) end it "says it responds to messages it does understand" do allow(@double).to receive(:foo) expect(@double).to respond_to(:foo) end it "raises an error when interpolated in a string as an integer" do # Not sure why, but 1.9.2 (but not JRuby --1.9) raises a different # error than 1.8.7 and 1.9.3... expected_error = (RUBY_VERSION == '1.9.2' && RUBY_PLATFORM !~ /java/) ? RSpec::Mocks::MockExpectationError : TypeError expect { "%i" % @double }.to raise_error(expected_error) end end RSpec.describe "a double acting as a null object" do before(:each) do @double = double('null object').as_null_object end it "says it responds to everything" do expect(@double).to respond_to(:any_message_it_gets) end it "allows explicit stubs" do allow(@double).to receive(:foo) { "bar" } expect(@double.foo).to eq("bar") end it "allows explicit expectation" do expect(@double).to receive(:something) @double.something end it 'returns a string from `to_str`' do expect(@double.to_str).to be_a(String) end it 'continues to return self from an explicit expectation' do expect(@double).to receive(:bar) expect(@double.foo.bar).to be(@double) end it 'returns an explicitly stubbed value from an expectation with no implementation' do allow(@double).to receive_messages(:foo => "bar") expect(@double).to receive(:foo) expect(@double.foo).to eq("bar") end it "fails verification when explicit exception not met" do expect { expect(@double).to receive(:something) verify @double }.to fail end it "ignores unexpected methods" do @double.random_call("a", "d", "c") verify @double end it 'allows unexpected message sends using `send`' do val = @double.send(:foo).send(:bar) expect(val).to equal(@double) end it 'allows unexpected message sends using `__send__`' do val = @double.__send__(:foo).__send__(:bar) expect(val).to equal(@double) end it "allows expected message with different args first" do expect(@double).to receive(:message).with(:expected_arg) @double.message(:unexpected_arg) @double.message(:expected_arg) end it "allows expected message with different args second" do expect(@double).to receive(:message).with(:expected_arg) @double.message(:expected_arg) @double.message(:unexpected_arg) end it "can be interpolated in a string as an integer" do # This form of string interpolation calls # @double.to_int.to_int.to_int...etc until it gets an integer, # and thus gets stuck in an infinite loop unless our double # returns an int value from #to_int. expect(("%i" % @double)).to eq("0") end it "does not allow null objects to be used outside of examples" do RSpec::Mocks.teardown expect { @double.some.long.message.chain }.to raise_error(RSpec::Mocks::OutsideOfExampleError) expect { @double.as_null_object }.to raise_error(RSpec::Mocks::OutsideOfExampleError) end end RSpec.describe "#as_null_object" do it "sets the object to null_object" do obj = double('anything').as_null_object expect(obj).to be_null_object end end RSpec.describe "#null_object?" do it "defaults to false" do obj = double('anything') expect(obj).not_to be_null_object end end RSpec.describe "when using the :expect syntax" do include_context "with syntax", :expect it 'still supports null object doubles' do obj = double("foo").as_null_object expect(obj.foo.bar.bazz).to be(obj) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/stub_spec.rb0000664000000000000000000004577014557670305024540 0ustar rootrootmodule RSpec module Mocks RSpec.describe "A method stub" do before(:each) do @class = Class.new do class << self def existing_class_method existing_private_class_method end private def existing_private_class_method :original_value end end def existing_instance_method existing_private_instance_method end private def existing_private_instance_method :original_value end end @instance = @class.new @stub = Object.new end describe "using `and_return`" do it "returns declared value when message is received" do allow(@instance).to receive(:msg).and_return(:return_value) expect(@instance.msg).to equal(:return_value) verify @instance end end it "instructs an instance to respond_to the message" do allow(@instance).to receive(:msg) expect(@instance).to respond_to(:msg) end it "instructs a class object to respond_to the message" do allow(@class).to receive(:msg) expect(@class).to respond_to(:msg) end it "ignores when expected message is received with no args" do allow(@instance).to receive(:msg) @instance.msg expect do verify @instance end.not_to raise_error end it "ignores when message is received with args" do allow(@instance).to receive(:msg) @instance.msg(:an_arg) expect do verify @instance end.not_to raise_error end it "ignores when expected message is not received" do allow(@instance).to receive(:msg) expect do verify @instance end.not_to raise_error end it "handles multiple stubbed methods" do allow(@instance).to receive_messages(:msg1 => 1, :msg2 => 2) expect(@instance.msg1).to eq(1) expect(@instance.msg2).to eq(2) end it "is retained when stubbed object is `clone`d" do allow(@stub).to receive(:foobar).and_return(1) expect(@stub.clone.foobar).to eq(1) end it "is cleared when stubbed object when `dup`ed" do allow(@stub).to receive(:foobar).and_return(1) expect { @stub.dup.foobar }.to raise_error NoMethodError, /foobar/ end it "remains private when it stubs a private instance method" do allow(@instance).to receive(:existing_private_instance_method).and_return(1) expect { @instance.existing_private_instance_method }.to raise_error NoMethodError, /private method `existing_private_instance_method/ end it "remains private when it stubs a private class method" do allow(@class).to receive(:existing_private_class_method).and_return(1) expect { @class.existing_private_class_method }.to raise_error NoMethodError, /private method `existing_private_class_method/ end context "using `with`" do it 'determines which value is returned' do allow(@stub).to receive(:foo).with(1) { :one } allow(@stub).to receive(:foo).with(2) { :two } expect(@stub.foo(2)).to eq(:two) expect(@stub.foo(1)).to eq(:one) end it 'allows differing arities' do allow(@stub).to receive(:foo).with(:two, :args) { :two_args } allow(@stub).to receive(:foo).with(:three, :args, :total) { :three_args_total } expect(@stub.foo(:two, :args)).to eq(:two_args) expect(@stub.foo(:three, :args, :total)).to eq(:three_args_total) end end context "when the stubbed method is called" do it "does not call any methods on the passed args, since that could mutate them", :issue => 892 do recorder = Class.new(defined?(::BasicObject) ? ::BasicObject : ::Object) do def called_methods @called_methods ||= [] end def method_missing(name, *) called_methods << name self end end.new allow(@stub).to receive(:foo) expect { @stub.foo(recorder) }.not_to change(recorder, :called_methods) end end context "stubbing with prepend", :if => Support::RubyFeatures.module_prepends_supported? do module ToBePrepended def value "#{super}_prepended".to_sym end end it "handles stubbing prepended methods" do klass = Class.new { prepend ToBePrepended; def value; :original; end } instance = klass.new expect(instance.value).to eq :original_prepended allow(instance).to receive(:value) { :stubbed } expect(instance.value).to eq :stubbed end it "handles stubbing prepended methods on a class's singleton class" do klass = Class.new { class << self; prepend ToBePrepended; end; def self.value; :original; end } expect(klass.value).to eq :original_prepended allow(klass).to receive(:value) { :stubbed } expect(klass.value).to eq :stubbed end it "handles stubbing prepended methods on an object's singleton class" do object = Object.new def object.value; :original; end object.singleton_class.send(:prepend, ToBePrepended) expect(object.value).to eq :original_prepended allow(object).to receive(:value) { :stubbed } expect(object.value).to eq :stubbed end it 'does not unnecessarily prepend a module when the prepended module does not override the stubbed method' do object = Object.new def object.value; :original; end object.singleton_class.send(:prepend, Module.new) expect { allow(object).to receive(:value) { :stubbed } }.not_to change { object.singleton_class.ancestors } end it 'does not unnecessarily prepend a module when stubbing a method on a module extended onto itself' do mod = Module.new do extend self def foo; :bar; end end expect { allow(mod).to receive(:foo) }.not_to change { mod.singleton_class.ancestors } end it 'does not unnecessarily prepend a module when the module was included' do object = Object.new def object.value; :original; end object.singleton_class.send(:include, ToBePrepended) expect { allow(object).to receive(:value) { :stubbed } }.not_to change { object.singleton_class.ancestors } end it 'reuses our prepend module so as not to keep mutating the ancestors' do object = Object.new def object.value; :original; end object.singleton_class.send(:prepend, ToBePrepended) allow(object).to receive(:value) { :stubbed } RSpec::Mocks.teardown RSpec::Mocks.setup expect { allow(object).to receive(:value) { :stubbed } }.not_to change { object.singleton_class.ancestors } end context "when multiple modules are prepended, only one of which overrides the stubbed method" do it "can still be stubbed and reset" do object = Object.new object.singleton_class.class_eval do def value; :original; end prepend ToBePrepended prepend Module.new {} end expect(object.value).to eq :original_prepended allow(object).to receive(:value) { :stubbed } expect(object.value).to eq :stubbed reset object expect(object.value).to eq :original_prepended end end context "when a module with a method override is prepended after reset" do it "can still be stubbed again" do object = Object.new def object.value; :original; end object.singleton_class.send(:prepend, ToBePrepended) allow(object).to receive(:value) { :stubbed } RSpec::Mocks.teardown RSpec::Mocks.setup object.singleton_class.send(:prepend, Module.new { def value :"#{super}_extra_prepend" end }) allow(object).to receive(:value) { :stubbed_2 } expect(object.value).to eq(:stubbed_2) end end end describe "#rspec_reset" do it "removes stubbed methods that didn't exist" do allow(@instance).to receive(:non_existent_method) reset @instance expect(@instance).not_to respond_to(:non_existent_method) end it "restores existing instance methods" do # See bug reports 8302 and 7805 allow(@instance).to receive(:existing_instance_method) { :stub_value } reset @instance expect(@instance.existing_instance_method).to eq(:original_value) end it "restores existing singleton methods with the appropriate context" do klass = Class.new do def self.say_hello @hello if defined?(@hello) end end subclass = Class.new(klass) subclass.instance_variable_set(:@hello, "Hello") expect(subclass.say_hello).to eq("Hello") allow(klass).to receive(:say_hello) { "Howdy" } expect(subclass.say_hello).to eq("Howdy") reset klass expect(subclass.say_hello).to eq("Hello") end it "restores existing private instance methods" do # See bug reports 8302 and 7805 allow(@instance).to receive(:existing_private_instance_method) { :stub_value } reset @instance expect(@instance.send(:existing_private_instance_method)).to eq(:original_value) end it "restores existing class methods" do # See bug reports 8302 and 7805 allow(@class).to receive(:existing_class_method) { :stub_value } reset @class expect(@class.existing_class_method).to eq(:original_value) end it "restores existing aliased module_function methods" do m = Module.new do def mkdir_p :mkdir_p end module_function :mkdir_p alias mkpath mkdir_p module_function :mkpath end allow(m).to receive(:mkpath) { :stub_value } allow(m).to receive(:mkdir_p) { :stub_value } reset m expect(m.mkpath).to eq(:mkdir_p) expect(m.mkdir_p).to eq(:mkdir_p) end it "restores existing private class methods" do # See bug reports 8302 and 7805 allow(@class).to receive(:existing_private_class_method) { :stub_value } reset @class expect(@class.send(:existing_private_class_method)).to eq(:original_value) end it "does not remove existing methods that have been stubbed twice" do allow(@instance).to receive(:existing_instance_method) allow(@instance).to receive(:existing_instance_method) reset @instance expect(@instance.existing_instance_method).to eq(:original_value) end it "correctly restores the visibility of methods whose visibility has been tweaked on the singleton class" do # hello is a private method when mixed in, but public on the module # itself mod = Module.new { extend self def hello; :hello; end private :hello class << self; public :hello; end; } expect(mod.hello).to eq(:hello) allow(mod).to receive(:hello) { :stub } reset mod expect(mod.hello).to eq(:hello) end it "correctly handles stubbing inherited mixed in class methods" do mod = Module.new do def method_a raise "should not execute method_a" end def self.included(other) other.extend self end end a = Class.new { include mod } b = Class.new(a) do def self.method_b "executed method_b" end end allow(a).to receive(:method_a) allow(b).to receive(:method_b).and_return("stubbed method_b") expect(b.method_b).to eql("stubbed method_b") end if Support::RubyFeatures.module_prepends_supported? context "with a prepended module (ruby 2.0.0+)" do module ToBePrepended def existing_method "#{super}_prepended".to_sym end end before do @prepended_class = Class.new do prepend ToBePrepended def existing_method :original_value end def non_prepended_method :not_prepended end end @prepended_instance = @prepended_class.new end it "restores prepended instance methods" do allow(@prepended_instance).to receive(:existing_method) { :stubbed } expect(@prepended_instance.existing_method).to eq :stubbed reset @prepended_instance expect(@prepended_instance.existing_method).to eq :original_value_prepended end it "restores non-prepended instance methods" do allow(@prepended_instance).to receive(:non_prepended_method) { :stubbed } expect(@prepended_instance.non_prepended_method).to eq :stubbed reset @prepended_instance expect(@prepended_instance.non_prepended_method).to eq :not_prepended end it "restores prepended class methods" do klass = Class.new do class << self; prepend ToBePrepended; end def self.existing_method :original_value end end allow(klass).to receive(:existing_method) { :stubbed } expect(klass.existing_method).to eq :stubbed reset klass expect(klass.existing_method).to eq :original_value_prepended end it "restores prepended object singleton methods" do object = Object.new def object.existing_method; :original_value; end object.singleton_class.send(:prepend, ToBePrepended) allow(object).to receive(:existing_method) { :stubbed } expect(object.existing_method).to eq :stubbed reset object expect(object.existing_method).to eq :original_value_prepended end end end end it "returns values in order to consecutive calls" do allow(@instance).to receive(:msg).and_return("1", 2, :three) expect(@instance.msg).to eq("1") expect(@instance.msg).to eq(2) expect(@instance.msg).to eq(:three) end it "keeps returning last value in consecutive calls" do allow(@instance).to receive(:msg).and_return("1", 2, :three) expect(@instance.msg).to eq("1") expect(@instance.msg).to eq(2) expect(@instance.msg).to eq(:three) expect(@instance.msg).to eq(:three) expect(@instance.msg).to eq(:three) end it "yields a specified object" do allow(@instance).to receive(:method_that_yields).and_yield(:yielded_obj) current_value = :value_before @instance.method_that_yields { |val| current_value = val } expect(current_value).to eq :yielded_obj verify @instance end it "yields multiple times with multiple calls to and_yield" do allow(@instance).to receive(:method_that_yields_multiple_times).and_yield(:yielded_value). and_yield(:another_value) current_value = [] @instance.method_that_yields_multiple_times { |val| current_value << val } expect(current_value).to eq [:yielded_value, :another_value] verify @instance end it "yields a specified object and return another specified object" do yielded_obj = double("my mock") expect(yielded_obj).to receive(:foo).with(:bar) allow(@instance).to receive(:method_that_yields_and_returns).and_yield(yielded_obj).and_return(:baz) expect(@instance.method_that_yields_and_returns { |o| o.foo :bar }).to eq :baz end it "throws when told to" do allow(@stub).to receive(:something).and_throw(:up) expect { @stub.something }.to throw_symbol(:up) end it "throws with argument when told to" do allow(@stub).to receive(:something).and_throw(:up, 'high') expect { @stub.something }.to throw_symbol(:up, 'high') end it "overrides a pre-existing method" do allow(@stub).to receive(:existing_instance_method).and_return(:updated_stub_value) expect(@stub.existing_instance_method).to eq :updated_stub_value end it "overrides a pre-existing stub" do allow(@stub).to receive(:foo) { 'bar' } allow(@stub).to receive(:foo) { 'baz' } expect(@stub.foo).to eq 'baz' end it "allows a stub and an expectation" do allow(@stub).to receive(:foo).with("bar") expect(@stub).to receive(:foo).with("baz") @stub.foo("bar") @stub.foo("baz") end end RSpec.describe "A method stub with args" do before(:each) do @stub = Object.new allow(@stub).to receive(:foo).with("bar") end it "does not complain if not called" do end it "does not complain if called with arg" do @stub.foo("bar") end it "complains if called with no arg" do expect { @stub.foo }.to raise_error(/received :foo with unexpected arguments/) end it "complains if called with other arg", :github_issue => [123, 147] do expect { @stub.foo("other") }.to raise_error(/received :foo with unexpected arguments.*Please stub a default value/m) end it "does not complain if also mocked w/ different args" do expect(@stub).to receive(:foo).with("baz") @stub.foo("bar") @stub.foo("baz") end it "complains if also mocked w/ different args AND called w/ a 3rd set of args" do expect(@stub).to receive(:foo).with("baz") @stub.foo("bar") @stub.foo("baz") expect { @stub.foo("other") }.to fail end it 'uses the correct stubbed response when responding to a mock expectation' do allow(@stub).to receive(:bar) { 15 } allow(@stub).to receive(:bar).with(:eighteen) { 18 } allow(@stub).to receive(:bar).with(:thirteen) { 13 } expect(@stub).to receive(:bar).exactly(4).times expect(@stub.bar(:blah)).to eq(15) expect(@stub.bar(:thirteen)).to eq(13) expect(@stub.bar(:eighteen)).to eq(18) expect(@stub.bar).to eq(15) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/diffing_spec.rb0000664000000000000000000003017114557670305025156 0ustar rootrootrequire "spec_helper" require "pp" RSpec.describe "Diffs printed when arguments don't match" do include RSpec::Support::Spec::DiffHelpers before do allow(RSpec::Mocks.configuration).to receive(:color?).and_return(false) end context "with a non matcher object" do it "does not print a diff when single line arguments are mismatched" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string") expect { d.foo("this other string") }.to fail_with(a_string_excluding("Diff:")) end end it "does not print a diff when differ returns a string of only whitespace" do differ = instance_double(RSpec::Support::Differ, :diff => " \n \t ") allow(RSpec::Support::Differ).to receive_messages(:new => differ) with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string\nline2") expect { d.foo("this other string") }.to fail_with(a_string_excluding("Diff:")) end end it "does not print a diff when differ returns a string of only whitespace when colour is enabled" do allow(RSpec::Mocks.configuration).to receive(:color?) { true } differ = instance_double(RSpec::Support::Differ, :diff => "\e[0m\n \t\e[0m") allow(RSpec::Support::Differ).to receive_messages(:new => differ) with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string\nline2") expect { d.foo("this other string") }.to fail_with(a_string_excluding("Diff:")) end end it "prints a diff of the strings for individual mismatched multi-line string arguments" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string\nline2") expect { d.foo("this other string") }.to fail_with("# received :foo with unexpected arguments\n" \ " expected: (\"some string\\nline2\")\n got: (\"this other string\")\n" \ "Diff:\n@@ -1,3 +1,2 @@\n-some string\n-line2\n+this other string\n") end end it "prints a diff of the args lists for multiple mismatched string arguments" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string\nline2", "some other string") expect { d.foo("this other string") }.to fail_with("# received :foo with unexpected arguments\n" \ " expected: (\"some string\\nline2\", \"some other string\")\n" \ " got: (\"this other string\")\nDiff:\n@@ -1,3 +1,2 @@\n-some string\\nline2\n-some other string\n+this other string\n") end end it "does not print a diff when multiple single-line string arguments are mismatched" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with("some string", "some other string") expect { d.foo("this other string", "a fourth string") }.to fail_with(a_string_excluding("Diff:")) end end let(:expected_hash) { {:baz => :quz, :foo => :bar } } let(:actual_hash) { {:bad => :hash} } it "prints a diff with hash args" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with(expected_hash) expect { d.foo({:bad => :hash}) }.to fail_with(/\A# received :foo with unexpected arguments\n expected: \(#{hash_regex_inspect expected_hash}\)\n got: \(#{hash_regex_inspect actual_hash}\)\nDiff:\n@@ #{Regexp.escape one_line_header} @@\n\-\[#{hash_regex_inspect expected_hash}\]\n\+\[#{hash_regex_inspect actual_hash}\]\n\z/) end end it "prints a diff with an expected hash arg and a non-hash actual arg" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with(expected_hash) expect { d.foo(Object.new) }.to fail_with(/-\[#{hash_regex_inspect expected_hash}\].*\+\[#\]/m) end end context 'with keyword arguments on normal doubles' do if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when keyword argument were expected but got an option hash (using splat)" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with(**expected_hash) expect { d.foo(expected_hash) }.to fail_with( "# received :foo with unexpected arguments\n" \ " expected: ({:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ " got: ({:baz=>:quz, :foo=>:bar}) (options hash)" ) end end RUBY eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when keyword argument were expected but got an option hash (literal)" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with(:positional, keyword: 1) expect { options = { keyword: 1 } d.foo(:positional, options) }.to fail_with( "# received :foo with unexpected arguments\n" \ " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ " got: (:positional, {:keyword=>1}) (options hash)" ) end end RUBY eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when the positional argument doesnt match" do with_unfulfilled_double do |d| input = Class.new expected_input = input.new() actual_input = input.new() expect(d).to receive(:foo).with(expected_input, one: 1) expect { options = { one: 1 } d.foo(actual_input, options) }.to fail_with( "# received :foo with unexpected arguments\n" \ " expected: (#{expected_input.inspect}, {:one=>1}) (keyword arguments)\n" \ " got: (#{actual_input.inspect}, {:one=>1}) (options hash)\n" \ "Diff:\n" \ "@@ -1 +1 @@\n" \ "-[#{expected_input.inspect}, {:one=>1}]\n" \ "+[#{actual_input.inspect}, {:one=>1}]\n" ) end end RUBY end end context 'with keyword arguments on partial doubles' do include_context "with isolated configuration" let(:d) { Class.new { def foo(a, b); end }.new } before(:example) do RSpec::Mocks.configuration.verify_partial_doubles = true allow(RSpec.configuration).to receive(:color_enabled?) { false } end after(:example) { reset d } if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when keyword argument were expected but got an option hash (using splat)" do expect(d).to receive(:foo).with(:positional, **expected_hash) expect { d.foo(:positional, expected_hash) }.to fail_with( "#{d.inspect} received :foo with unexpected arguments\n" \ " expected: (:positional, {:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ " got: (:positional, {:baz=>:quz, :foo=>:bar}) (options hash)" ) end RUBY eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when keyword argument were expected but got an option hash (literal)" do expect(d).to receive(:foo).with(:positional, keyword: 1) expect { options = { keyword: 1 } d.foo(:positional, options) }.to fail_with( "#{d.inspect} received :foo with unexpected arguments\n" \ " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ " got: (:positional, {:keyword=>1}) (options hash)" ) end RUBY eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 it "prints a diff when the positional argument doesnt match" do input = Class.new expected_input = input.new() actual_input = input.new() expect(d).to receive(:foo).with(expected_input, one: 1) expect { options = { one: 1 } d.foo(actual_input, options) }.to fail_with( "#{d.inspect} received :foo with unexpected arguments\n" \ " expected: (#{expected_input.inspect}, {:one=>1}) (keyword arguments)\n" \ " got: (#{actual_input.inspect}, {:one=>1}) (options hash)\n" \ "Diff:\n" \ "@@ -1 +1 @@\n" \ "-[#{expected_input.inspect}, {:one=>1}]\n" \ "+[#{actual_input.inspect}, {:one=>1}]\n" ) end RUBY end end if RUBY_VERSION.to_f < 1.9 # Ruby 1.8 hashes are not ordered, but `#inspect` on a particular unchanged # hash instance should return consistent output. However, on Travis that does # not always seem to be true and we have no idea why. Somehow, the travis build # has occasionally failed due to the output ordering varying between `inspect` # calls to the same hash. This regex allows us to work around that. def hash_regex_inspect(hash) "\\{(#{hash.map { |key, value| "#{key.inspect}=>#{value.inspect}.*" }.join "|"}){#{hash.size}}\\}" end else def hash_regex_inspect(hash) Regexp.escape(hash.inspect) end end it "prints a diff with array args" do with_unfulfilled_double do |d| expect(d).to receive(:foo).with([:a, :b, :c]) expect { d.foo([]) }.to fail_with("# received :foo with unexpected arguments\n expected: ([:a, :b, :c])\n got: ([])\nDiff:\n@@ #{one_line_header} @@\n-[[:a, :b, :c]]\n+[[]]\n") end end context "that defines #description" do it "does not use the object's description for a non-matcher object that implements #description" do with_unfulfilled_double do |d| collab = double(:collab, :description => "This string") collab_inspect = collab.inspect expect(d).to receive(:foo).with(collab) expect { d.foo([]) }.to fail_with("# received :foo with unexpected arguments\n" \ " expected: (#{collab_inspect})\n" \ " got: ([])\nDiff:\n@@ #{one_line_header} @@\n-[#{collab_inspect}]\n+[[]]\n") end end end end context "with a matcher object" do context "that defines #description" do it "uses the object's description" do with_unfulfilled_double do |d| collab = fake_matcher(Object.new) collab_description = collab.description expect(d).to receive(:foo).with(collab) expect { d.foo([:a, :b]) }.to fail_with("# received :foo with unexpected arguments\n" \ " expected: (#{collab_description})\n" \ " got: ([:a, :b])\nDiff:\n@@ #{one_line_header} @@\n-[\"#{collab_description}\"]\n+[[:a, :b]]\n") end end end context "that does not define #description" do it "for a matcher object that does not implement #description" do with_unfulfilled_double do |d| collab = Class.new do def self.name "RSpec::Mocks::ArgumentMatchers::" end def inspect "#" end end.new expect(RSpec::Support.is_a_matcher?(collab)).to be true collab_inspect = collab.inspect collab_pp = PP.pp(collab, "".dup).strip expect(d).to receive(:foo).with(collab) expect { d.foo([:a, :b]) }.to fail_with("# received :foo with unexpected arguments\n" \ " expected: (#{collab_inspect})\n" \ " got: ([:a, :b])\nDiff:\n@@ #{one_line_header} @@\n-[#{collab_pp}]\n+[[:a, :b]]\n") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/twice_counts_spec.rb0000664000000000000000000000650414557670305026261 0ustar rootrootmodule RSpec module Mocks RSpec.describe "#twice" do before(:each) do @double = double("test double") end it "passes when called twice" do expect(@double).to receive(:do_something).twice @double.do_something @double.do_something verify @double end it "passes when called twice with specified args" do expect(@double).to receive(:do_something).twice.with("1", 1) @double.do_something("1", 1) @double.do_something("1", 1) verify @double end it "passes when called twice with unspecified args" do expect(@double).to receive(:do_something).twice @double.do_something("1") @double.do_something(1) verify @double end it "fails fast when call count is higher than expected" do expect(@double).to receive(:do_something).twice @double.do_something @double.do_something expect_fast_failure_from(@double) do @double.do_something end end it "fails when call count is lower than expected" do expect(@double).to receive(:do_something).twice @double.do_something expect { verify @double }.to fail end it "fails when called with wrong args on the first call" do expect(@double).to receive(:do_something).twice.with("1", 1) expect { @double.do_something(1, "1") }.to fail reset @double end it "fails when called with wrong args on the second call" do expect(@double).to receive(:do_something).twice.with("1", 1) @double.do_something("1", 1) expect { @double.do_something(1, "1") }.to fail reset @double end context "when called with the wrong number of times with the specified args and also called with different args" do it "mentions the wrong call count in the failure message rather than the different args" do allow(@double).to receive(:do_something) # allow any args... expect(@double).to receive(:do_something).with(:args, 1).twice @double.do_something(:args, 2) @double.do_something(:args, 1) @double.do_something(:args, 2) @double.do_something(:args, 1) expect { # we've grouped these lines because it should probably fail fast # on the first line (since our expectation above only allows one # call with these args), but currently it fails with a confusing # message on verification, and ultimately we care more about # what the message is than when it is raised. Still, it would be # preferrable for the error to be triggered on the first line, # so it'd be good to update this spec to enforce that once we # get the failure message right. @double.do_something(:args, 1) verify @double }.to fail_with(a_string_including("expected: 2 times", "received: 3 times")) end end context "when called with negative expectation" do it "raises an error" do expect { expect(@double).not_to receive(:do_something).twice }.to raise_error(/`count` is not supported with negative message expectations/) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/multiple_invoke_handler_spec.rb0000664000000000000000000001023714557670305030454 0ustar rootrootmodule RSpec module Mocks RSpec.describe "a message expectation with multiple invoke handlers and no specified count" do let(:a_double) { double } before(:each) do expect(a_double).to receive(:do_something).and_invoke(lambda { 1 }, lambda { raise "2" }, lambda { 3 }) end it "invokes procs in order" do expect(a_double.do_something).to eq 1 expect { a_double.do_something }.to raise_error("2") expect(a_double.do_something).to eq 3 verify a_double end it "falls back to a previously stubbed value" do allow(a_double).to receive_messages :do_something => :stub_result expect(a_double.do_something).to eq 1 expect { a_double.do_something }.to raise_error("2") expect(a_double.do_something).to eq 3 expect(a_double.do_something).to eq :stub_result end it "fails when there are too few calls (if there is no stub)" do a_double.do_something expect { a_double.do_something }.to raise_error("2") expect { verify a_double }.to fail end it "fails when there are too many calls (if there is no stub)" do a_double.do_something expect { a_double.do_something }.to raise_error("2") a_double.do_something a_double.do_something expect { verify a_double }.to fail end end RSpec.describe "a message expectation with multiple invoke handlers with a specified count equal to the number of values" do let(:a_double) { double } before(:each) do expect(a_double).to receive(:do_something).exactly(3).times.and_invoke(lambda { 1 }, lambda { raise "2" }, lambda { 3 }) end it "returns values in order to consecutive calls" do expect(a_double.do_something).to eq 1 expect { a_double.do_something }.to raise_error("2") expect(a_double.do_something).to eq 3 verify a_double end end RSpec.describe "a message expectation with multiple invoke handlers specifying at_least less than the number of values" do let(:a_double) { double } before { expect(a_double).to receive(:do_something).at_least(:twice).with(no_args).and_invoke(lambda { 11 }, lambda { 22 }) } it "uses the last return value for subsequent calls" do expect(a_double.do_something).to equal(11) expect(a_double.do_something).to equal(22) expect(a_double.do_something).to equal(22) verify a_double end it "fails when called less than the specified number" do expect(a_double.do_something).to equal(11) expect { verify a_double }.to fail end context "when method is stubbed too" do before { allow(a_double).to receive(:do_something).and_invoke lambda { :stub_result } } it "uses the last value for subsequent calls" do expect(a_double.do_something).to equal(11) expect(a_double.do_something).to equal(22) expect(a_double.do_something).to equal(22) verify a_double end it "fails when called less than the specified number" do expect(a_double.do_something).to equal(11) expect { verify a_double }.to fail end end end RSpec.describe "a message expectation with multiple invoke handlers with a specified count larger than the number of values" do let(:a_double) { double } before { expect(a_double).to receive(:do_something).exactly(3).times.and_invoke(lambda { 11 }, lambda { 22 }) } it "uses the last return value for subsequent calls" do expect(a_double.do_something).to equal(11) expect(a_double.do_something).to equal(22) expect(a_double.do_something).to equal(22) verify a_double end it "fails when called less than the specified number" do a_double.do_something a_double.do_something expect { verify a_double }.to fail end it "fails fast when called greater than the specified number" do a_double.do_something a_double.do_something a_double.do_something expect_fast_failure_from(a_double) do a_double.do_something end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/block_return_value_spec.rb0000664000000000000000000000444314557670305027440 0ustar rootrootRSpec.describe "a double declaration with a block handed to:" do describe "expect(...).to receive" do it "returns the value of executing the block" do obj = Object.new expect(obj).to receive(:foo) { 'bar' } expect(obj.foo).to eq('bar') end it "works when a multi-return stub has already been set" do obj = Object.new return_value = Object.new allow(obj).to receive(:foo).and_return(return_value, nil) expect(obj).to receive(:foo) { return_value } expect(obj.foo).to be(return_value) end end describe "allow(...).to receive" do it "returns the value of executing the block" do obj = Object.new allow(obj).to receive(:foo) { 'bar' } expect(obj.foo).to eq('bar') end # The "receives a block" part is important: 1.8.7 has a bug that reports the # wrong arity when a block receives a block. it 'forwards all given args to the block, even when it receives a block' do obj = Object.new yielded_args = [] allow(obj).to receive(:foo) { |*args, &_| yielded_args << args } obj.foo(1, 2, 3) expect(yielded_args).to eq([[1, 2, 3]]) end end describe "with" do it "returns the value of executing the block" do obj = Object.new allow(obj).to receive(:foo).with('baz') { 'bar' } expect(obj.foo('baz')).to eq('bar') end it "returns the value of executing the block with given argument" do obj = Object.new allow(obj).to receive(:foo).with('baz') { |x| 'bar' + x } expect(obj.foo('baz')).to eq('barbaz') end end %w[once twice].each do |method| describe method do it "returns the value of executing the block" do obj = Object.new allow(obj).to receive(:foo).send(method) { 'bar' } expect(obj.foo).to eq('bar') end end end describe 'ordered' do it "returns the value of executing the block" do obj = Object.new expect_warning_with_call_site(__FILE__, __LINE__ + 1) allow(obj).to receive(:foo).ordered { 'bar' } expect(obj.foo).to eq('bar') end end describe "times" do it "returns the value of executing the block" do obj = Object.new allow(obj).to receive(:foo).at_least(1).time { 'bar' } expect(obj.foo('baz')).to eq('bar') end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/multiple_return_value_spec.rb0000664000000000000000000001114414557670305030175 0ustar rootrootmodule RSpec module Mocks RSpec.describe "a double stubbed with multiple return values" do let(:a_double) { double } before do allow(a_double).to receive(:foo).and_return(:val_1, nil) end it 'can still set a message expectation with a single return value' do expect(a_double).to receive(:foo).once.and_return(:val_1) expect(a_double.foo).to eq(:val_1) end end RSpec.describe "a message expectation with multiple return values and no specified count" do before(:each) do @double = double @return_values = [1, 2, 3] expect(@double).to receive(:do_something).and_return(@return_values[0], @return_values[1], @return_values[2]) end it "returns values in order" do expect(@double.do_something).to eq @return_values[0] expect(@double.do_something).to eq @return_values[1] expect(@double.do_something).to eq @return_values[2] verify @double end it "falls back to a previously stubbed value" do allow(@double).to receive_messages :do_something => :stub_result expect(@double.do_something).to eq @return_values[0] expect(@double.do_something).to eq @return_values[1] expect(@double.do_something).to eq @return_values[2] expect(@double.do_something).to eq :stub_result end it "fails when there are too few calls (if there is no stub)" do @double.do_something @double.do_something expect { verify @double }.to fail end it "fails when there are too many calls (if there is no stub)" do @double.do_something @double.do_something @double.do_something @double.do_something expect { verify @double }.to fail end end RSpec.describe "a message expectation with multiple return values with a specified count equal to the number of values" do before(:each) do @double = double @return_values = [1, 2, 3] expect(@double).to receive(:do_something).exactly(3).times.and_return(@return_values[0], @return_values[1], @return_values[2]) end it "returns values in order to consecutive calls" do expect(@double.do_something).to eq @return_values[0] expect(@double.do_something).to eq @return_values[1] expect(@double.do_something).to eq @return_values[2] verify @double end end RSpec.describe "a message expectation with multiple return values specifying at_least less than the number of values" do before(:each) do @double = double expect(@double).to receive(:do_something).at_least(:twice).with(no_args).and_return(11, 22) end it "uses the last return value for subsequent calls" do expect(@double.do_something).to equal(11) expect(@double.do_something).to equal(22) expect(@double.do_something).to equal(22) verify @double end it "fails when called less than the specified number" do expect(@double.do_something).to equal(11) expect { verify @double }.to fail end context "when method is stubbed too" do before { allow(@double).to receive(:do_something).and_return :stub_result } it "uses the last value for subsequent calls" do expect(@double.do_something).to equal(11) expect(@double.do_something).to equal(22) expect(@double.do_something).to equal(22) verify @double end it "fails when called less than the specified number" do expect(@double.do_something).to equal(11) expect { verify @double }.to fail end end end RSpec.describe "a message expectation with multiple return values with a specified count larger than the number of values" do before(:each) do @double = RSpec::Mocks::Double.new("double") expect(@double).to receive(:do_something).exactly(3).times.and_return(11, 22) end it "uses the last return value for subsequent calls" do expect(@double.do_something).to equal(11) expect(@double.do_something).to equal(22) expect(@double.do_something).to equal(22) verify @double end it "fails when called less than the specified number" do @double.do_something @double.do_something expect { verify @double }.to fail end it "fails fast when called greater than the specified number" do @double.do_something @double.do_something @double.do_something expect_fast_failure_from(@double) do @double.do_something end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/once_counts_spec.rb0000664000000000000000000000541114557670305026066 0ustar rootrootmodule RSpec module Mocks RSpec.describe "#once" do before(:each) do @double = double end it "passes when called once" do expect(@double).to receive(:do_something).once @double.do_something verify @double end it "passes when called once with specified args" do expect(@double).to receive(:do_something).once.with("a", "b", "c") @double.do_something("a", "b", "c") verify @double end it "passes when called once with unspecified args" do expect(@double).to receive(:do_something).once @double.do_something("a", "b", "c") verify @double end it "fails when called with wrong args" do expect(@double).to receive(:do_something).once.with("a", "b", "c") expect { @double.do_something("d", "e", "f") }.to fail reset @double end it "fails fast when called twice" do expect(@double).to receive(:do_something).once @double.do_something expect_fast_failure_from(@double) do @double.do_something end end it "fails when not called" do expect(@double).to receive(:do_something).once expect { verify @double }.to fail end context "when called with the wrong number of times with the specified args and also called with different args" do it "mentions the wrong call count in the failure message rather than the different args" do allow(@double).to receive(:do_something) # allow any args... expect(@double).to receive(:do_something).with(:args, 1).once @double.do_something(:args, 2) @double.do_something(:args, 1) expect { # we've grouped these lines because it should probably fail fast # on the first line (since our expectation above only allows one # call with these args), but currently it fails with a confusing # message on verification, and ultimately we care more about # what the message is than when it is raised. Still, it would be # preferrable for the error to be triggered on the first line, # so it'd be good to update this spec to enforce that once we # get the failure message right. @double.do_something(:args, 1) verify @double }.to fail_with(a_string_including("expected: 1 time", "received: 2 times")) end end context "when called with negative expectation" do it "raises an error" do expect { expect(@double).not_to receive(:do_something).once }.to raise_error(/`count` is not supported with negative message expectations/) end end end end end ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/combining_implementation_instructions_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/combining_implementation_instructions_sp0000664000000000000000000001521714557670305032540 0ustar rootrootmodule RSpec module Mocks RSpec.describe "Combining implementation instructions" do it 'can combine and_yield and and_return' do dbl = double allow(dbl).to receive(:foo).and_yield(5).and_return(3) expect { |b| expect(dbl.foo(&b)).to eq(3) }.to yield_with_args(5) end describe "combining and_yield, a block implementation and and_return" do def verify_combined_implementation dbl = double (yield dbl).and_yield(5).and_return(3) expect { |b| expect(dbl.foo(:arg, &b)).to eq(3) }.to yield_with_args(5) expect(@block_called).to be_truthy end it 'works when passing a block to `stub`' do verify_combined_implementation do |dbl| allow(dbl).to receive(:foo) { @block_called = true } end end it 'works when passing a block to `with`' do verify_combined_implementation do |dbl| allow(dbl).to receive(:foo).with(:arg) { @block_called = true } end end it 'works when passing a block to `exactly`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).exactly(:once) { @block_called = true } end end it 'works when passing a block to `at_least`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).at_least(:once) { @block_called = true } end end it 'works when passing a block to `at_most`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).at_most(:once) { @block_called = true } end end it 'works when passing a block to `times`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).exactly(1).time { @block_called = true } end end it 'works when passing a block to `once`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).once { @block_called = true } end end it 'works when passing a block to `twice`' do the_double = nil verify_combined_implementation do |dbl| the_double = dbl expect(dbl).to receive(:foo).twice { @block_called = true } end the_double.foo { |_| } # to ensure it is called twice end it 'works when passing a block to `ordered`' do verify_combined_implementation do |dbl| expect(dbl).to receive(:foo).ordered { @block_called = true } end end end it 'can combine and_yield and and_raise' do dbl = double allow(dbl).to receive(:foo).and_yield(5).and_raise("boom") expect { |b| expect { dbl.foo(&b) }.to raise_error("boom") }.to yield_with_args(5) end it 'can combine and_yield, a block implementation and and_raise' do dbl = double block_called = false allow(dbl).to receive(:foo) { block_called = true }.and_yield(5).and_raise("boom") expect { |b| expect { dbl.foo(&b) }.to raise_error("boom") }.to yield_with_args(5) expect(block_called).to be_truthy end it 'can combine and_yield and and_throw' do dbl = double allow(dbl).to receive(:foo).and_yield(5).and_throw(:bar) expect { |b| expect { dbl.foo(&b) }.to throw_symbol(:bar) }.to yield_with_args(5) end it 'can combine and_yield, a block implementation and and_throw' do dbl = double block_called = false allow(dbl).to receive(:foo) { block_called = true }.and_yield(5).and_throw(:bar) expect { |b| expect { dbl.foo(&b) }.to throw_symbol(:bar) }.to yield_with_args(5) expect(block_called).to be_truthy end describe "a double that already has a terminal `and_return(x)` action" do let(:the_dbl) { double } let(:stubbed_double) { allow(the_dbl).to receive(:foo) } before { stubbed_double.and_return(1) } it 'allows the terminal action to be overridden to `and_return(y)`' do stubbed_double.and_return(3) expect(the_dbl.foo).to eq(3) end it 'allows the terminal action to be overridden to `and_raise(y)`' do stubbed_double.and_raise("boom") expect { the_dbl.foo }.to raise_error("boom") end it 'allows the terminal action to be overridden to `and_throw(y)`' do stubbed_double.and_throw(:bar) expect { the_dbl.foo }.to throw_symbol(:bar) end end describe "a double that already has a terminal block action" do let(:the_dbl) { double } let(:stubbed_double) { allow(the_dbl).to receive(:foo) } it "allows the block action to be overridden" do allow(RSpec).to receive(:warning) stubbed_double.with(:arg) { :with_block } stubbed_double.at_least(:once) { :at_least_block } expect(the_dbl.foo(:arg)).to eq(:at_least_block) end end it 'warns when the inner implementation block is overridden' do expect(RSpec).to receive(:warning).with(/overriding a previous stub implementation of `foo`.*#{__FILE__}:#{__LINE__ + 1}/) allow(double).to receive(:foo).with(:arg) { :with_block }.at_least(:once) { :at_least_block } end it "does not warn about overriding the stub when `:with` is chained off the block" do expect(RSpec).not_to receive(:warning) obj = Object.new stub = allow(obj).to receive(:foo) {} stub.with(1) end it 'can combine and_call_original, with, and_return' do obj = Struct.new(:value).new('original') allow(obj).to receive(:value).and_call_original allow(obj).to receive(:value).with(:arg).and_return('value') expect(obj.value).to eq 'original' expect(obj.value(:arg)).to eq 'value' end it 'raises an error if `and_call_original` is followed by any other instructions' do allow(RSpec).to receive(:warning) dbl = [1, 2, 3] stubbed = allow(dbl).to receive(:size) stubbed.and_call_original msg_fragment = /cannot be modified further/ expect { stubbed.and_yield }.to raise_error(msg_fragment) expect { stubbed.and_return(1) }.to raise_error(msg_fragment) expect { stubbed.and_raise("a") }.to raise_error(msg_fragment) expect { stubbed.and_throw(:bar) }.to raise_error(msg_fragment) expect { stubbed.once {} }.to raise_error(msg_fragment) expect(dbl.size).to eq(3) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/mutate_const_spec.rb0000664000000000000000000006043214557670305026260 0ustar rootrootTOP_LEVEL_VALUE_CONST = 7 class TestClass M = :m N = :n class Nested class NestedEvenMore end end end class TestClassThatDefinesSend C = :c def self.send end end class TestSubClass < TestClass P = :p end module RSpec module Mocks RSpec.describe "Constant Mutating" do include RSpec::Support::RecursiveConstMethods def reset_rspec_mocks ::RSpec::Mocks.space.reset_all end shared_context "constant example methods" do |const_name| define_method :const do recursive_const_get(const_name) end define_method :parent_const do recursive_const_get("Object::" + const_name.sub(/(::)?[^:]+\z/, '')) end define_method :last_const_part do const_name.split('::').last end end shared_examples "loaded constant stubbing" do |const_name| include_context "constant example methods", const_name let!(:original_const_value) { const } after { change_const_value_to(original_const_value) } def change_const_value_to(value) parent_const.__send__(:remove_const, last_const_part) parent_const.const_set(last_const_part, value) end it 'allows it to be stubbed' do expect(const).not_to eq(7) stub_const(const_name, 7) expect(const).to eq(7) end it 'resets it to its original value when rspec clears its mocks' do original_value = const expect(original_value).not_to eq(:a) stub_const(const_name, :a) reset_rspec_mocks expect(const).to be(original_value) end it 'returns the stubbed value' do expect(stub_const(const_name, 7)).to eq(7) end end shared_examples "loaded constant hiding" do |const_name| before do expect(recursive_const_defined?(const_name)).to be_truthy end it 'allows it to be hidden' do hide_const(const_name) expect(recursive_const_defined?(const_name)).to be_falsey end it 'resets the constant when rspec clear its mocks' do hide_const(const_name) reset_rspec_mocks expect(recursive_const_defined?(const_name)).to be_truthy end it 'returns nil' do expect(hide_const(const_name)).to be_nil end end shared_examples "unloaded constant stubbing" do |const_name| include_context "constant example methods", const_name before do expect(recursive_const_defined?(const_name)).to be_falsey end it 'allows it to be stubbed' do stub_const(const_name, 7) expect(const).to eq(7) end it 'removes the constant when rspec clears its mocks' do stub_const(const_name, 7) reset_rspec_mocks expect(recursive_const_defined?(const_name)).to be_falsey end it 'returns the stubbed value' do expect(stub_const(const_name, 7)).to eq(7) end it 'ignores the :transfer_nested_constants option if passed' do stub = Module.new stub_const(const_name, stub, :transfer_nested_constants => true) expect(stub.constants).to eq([]) end end shared_examples "unloaded constant hiding" do |const_name| include_context "constant example methods", const_name before do expect(recursive_const_defined?(const_name)).to be_falsey end it 'allows it to be hidden, though the operation has no effect' do hide_const(const_name) expect(recursive_const_defined?(const_name)).to be_falsey end it 'remains undefined after rspec clears its mocks' do hide_const(const_name) reset_rspec_mocks expect(recursive_const_defined?(const_name)).to be_falsey end it 'returns nil' do expect(hide_const(const_name)).to be_nil end end describe "#hide_const" do context "for a loaded constant nested in a module that redefines `send`" do it_behaves_like "loaded constant hiding", "TestClassThatDefinesSend::C" end context 'for a loaded nested constant' do it_behaves_like "loaded constant hiding", "TestClass::Nested" end context 'for a loaded constant prefixed with ::' do it_behaves_like 'loaded constant hiding', "::TestClass" end context 'for an unloaded constant with nested name that matches a top-level constant' do it_behaves_like "unloaded constant hiding", "TestClass::Hash" it 'does not hide the top-level constant' do top_level_hash = ::Hash hide_const("TestClass::Hash") expect(::Hash).to equal(top_level_hash) end it 'does not affect the ability to access the top-level constant from nested contexts', :silence_warnings, :if => RUBY_VERSION < '2.5' do top_level_hash = ::Hash hide_const("TestClass::Hash") expect(TestClass::Hash).to equal(top_level_hash) end end context 'for a loaded deeply nested constant' do it_behaves_like "loaded constant hiding", "TestClass::Nested::NestedEvenMore" end context 'for an unloaded unnested constant' do it_behaves_like "unloaded constant hiding", "X" end context 'for an unloaded nested constant' do it_behaves_like "unloaded constant hiding", "X::Y" end it 'can be hidden multiple times but still restores the original value properly' do orig_value = TestClass hide_const("TestClass") hide_const("TestClass") reset_rspec_mocks expect(TestClass).to be(orig_value) end it 'allows a constant to be hidden, then stubbed, restoring it to its original value properly' do orig_value = TOP_LEVEL_VALUE_CONST hide_const("TOP_LEVEL_VALUE_CONST") expect(recursive_const_defined?("TOP_LEVEL_VALUE_CONST")).to be_falsey stub_const("TOP_LEVEL_VALUE_CONST", 12_345) expect(TOP_LEVEL_VALUE_CONST).to eq 12_345 reset_rspec_mocks expect(TOP_LEVEL_VALUE_CONST).to eq orig_value end end describe "#stub_const" do context "for a loaded constant nested in a module that redefines `send`" do it_behaves_like "loaded constant stubbing", "TestClassThatDefinesSend::C" end it "requires a string argument" do expect { stub_const(10, 1) }.to raise_error(ArgumentError, /requires a String/i) end context 'for a loaded unnested constant' do it_behaves_like "loaded constant stubbing", "TestClass" it 'can be stubbed multiple times but still restores the original value properly' do orig_value = TestClass stub1, stub2 = Module.new, Module.new stub_const("TestClass", stub1) stub_const("TestClass", stub2) reset_rspec_mocks expect(TestClass).to be(orig_value) end it 'allows nested constants to be transferred to a stub module' do tc_nested = TestClass::Nested stub = Module.new stub_const("TestClass", stub, :transfer_nested_constants => true) expect(stub::M).to eq(:m) expect(stub::N).to eq(:n) expect(stub::Nested).to be(tc_nested) end it 'removes the transferred constants on reset' do stub = Module.new stub_const("TestClass", stub, :transfer_nested_constants => true) expect { reset_all }.to change { stub.constants }.to([]) end it 'does not transfer nested constants that are inherited from a superclass' do stub = Module.new stub_const("TestSubClass", stub, :transfer_nested_constants => true) expect(stub::P).to eq(:p) expect(defined?(stub::M)).to be_falsey expect(defined?(stub::N)).to be_falsey end it 'raises an error when asked to transfer a nested inherited constant' do original_tsc = TestSubClass expect { stub_const("TestSubClass", Module.new, :transfer_nested_constants => [:M]) }.to raise_error(ArgumentError) expect(TestSubClass).to be(original_tsc) end it 'allows nested constants to be selectively transferred to a stub module' do stub = Module.new stub_const("TestClass", stub, :transfer_nested_constants => [:M, :N]) expect(stub::M).to eq(:m) expect(stub::N).to eq(:n) expect(defined?(stub::Nested)).to be_falsey end it 'raises an error if asked to transfer nested constants but given an object that does not support them' do original_tc = TestClass stub = Object.new expect { stub_const("TestClass", stub, :transfer_nested_constants => true) }.to raise_error(ArgumentError) expect(TestClass).to be(original_tc) expect { stub_const("TestClass", stub, :transfer_nested_constants => [:M]) }.to raise_error(ArgumentError) expect(TestClass).to be(original_tc) end it 'raises an error if asked to transfer nested constants on a constant that does not support nested constants' do stub = Module.new expect { stub_const("TOP_LEVEL_VALUE_CONST", stub, :transfer_nested_constants => true) }.to raise_error(ArgumentError) expect(TOP_LEVEL_VALUE_CONST).to eq(7) expect { stub_const("TOP_LEVEL_VALUE_CONST", stub, :transfer_nested_constants => [:M]) }.to raise_error(ArgumentError) expect(TOP_LEVEL_VALUE_CONST).to eq(7) end it 'raises an error if asked to transfer a nested constant that is not defined' do original_tc = TestClass expect(defined?(TestClass::V)).to be_falsey stub = Module.new expect { stub_const("TestClass", stub, :transfer_nested_constants => [:V]) }.to raise_error(/cannot transfer nested constant.*V/i) expect(TestClass).to be(original_tc) end describe 'with global transfer_nested_constant option set' do include_context "with isolated configuration" before do RSpec::Mocks.configuration.transfer_nested_constants = true end it 'allows nested constants to be transferred to a stub module' do tc_nested = TestClass::Nested stub = Module.new stub_const("TestClass", stub) expect(stub::M).to eq(:m) expect(stub::N).to eq(:n) expect(stub::Nested).to be(tc_nested) end context "when stubbing a constant that is not a module or a class" do it 'does not attempt to transfer constants' do stub_const("TOP_LEVEL_VALUE_CONST", 4) expect(TOP_LEVEL_VALUE_CONST).to eq(4) end it 'still raises an error when the `:transfer_nested_constants` option is provided' do expect { stub_const("TOP_LEVEL_VALUE_CONST", 4, :transfer_nested_constants => true) }.to raise_error(/cannot transfer nested constant/i) end end end end context 'for a loaded nested constant' do it_behaves_like "loaded constant stubbing", "TestClass::Nested" end context 'for a loaded constant prefixed with ::' do it_behaves_like 'loaded constant stubbing', "::TestClass" end context 'for an unloaded constant prefixed with ::' do it_behaves_like 'unloaded constant stubbing', "::SomeUndefinedConst" end context "for an unloaded constant nested in a module that redefines `send`" do it_behaves_like 'unloaded constant stubbing', "TestClassThatDefinesSend::SomeUndefinedConst" end context 'for an unloaded constant with nested name that matches a top-level constant' do it_behaves_like "unloaded constant stubbing", "TestClass::Hash" end context 'for a loaded deeply nested constant' do it_behaves_like "loaded constant stubbing", "TestClass::Nested::NestedEvenMore" end context 'for an unloaded unnested constant' do it_behaves_like "unloaded constant stubbing", "X" end context 'for an unloaded nested constant' do it_behaves_like "unloaded constant stubbing", "X::Y" it 'removes the root constant when rspec clears its mocks' do expect(defined?(X)).to be_falsey stub_const("X::Y", 7) reset_rspec_mocks expect(defined?(X)).to be_falsey end end context 'for an unloaded deeply nested constant' do it_behaves_like "unloaded constant stubbing", "X::Y::Z" it 'removes the root constant when rspec clears its mocks' do expect(defined?(X)).to be_falsey stub_const("X::Y::Z", 7) reset_rspec_mocks expect(defined?(X)).to be_falsey end end context 'for an unloaded constant nested within a loaded constant' do it_behaves_like "unloaded constant stubbing", "TestClass::X" it 'removes the unloaded constant but leaves the loaded constant when rspec resets its mocks' do expect(defined?(TestClass)).to be_truthy expect(defined?(TestClass::X)).to be_falsey stub_const("TestClass::X", 7) reset_rspec_mocks expect(defined?(TestClass)).to be_truthy expect(defined?(TestClass::X)).to be_falsey end it 'raises a helpful error if it cannot be stubbed due to an intermediary constant that is not a module' do expect(TestClass::M).to be_a(Symbol) expect { stub_const("TestClass::M::X", 5) }.to raise_error(/cannot stub/i) end end context 'for an unloaded constant nested deeply within a deeply nested loaded constant' do it_behaves_like "unloaded constant stubbing", "TestClass::Nested::NestedEvenMore::X::Y::Z" it 'removes the first unloaded constant but leaves the loaded nested constant when rspec resets its mocks' do expect(defined?(TestClass::Nested::NestedEvenMore)).to be_truthy expect(defined?(TestClass::Nested::NestedEvenMore::X)).to be_falsey stub_const("TestClass::Nested::NestedEvenMore::X::Y::Z", 7) reset_rspec_mocks expect(defined?(TestClass::Nested::NestedEvenMore)).to be_truthy expect(defined?(TestClass::Nested::NestedEvenMore::X)).to be_falsey end end end end RSpec.describe Constant do describe ".original" do context 'for a previously defined unstubbed constant' do let(:const) { Constant.original("TestClass::M") } it("exposes its name") { expect(const.name).to eq("TestClass::M") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously defined") { expect(const).to be_previously_defined } it("indicates it has not been mutated") { expect(const).not_to be_mutated } it("indicates it has not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("exposes its original value") { expect(const.original_value).to eq(:m) } end context 'for a previously defined stubbed constant' do before { stub_const("TestClass::M", :other) } let(:const) { Constant.original("TestClass::M") } it("exposes its name") { expect(const.name).to eq("TestClass::M") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously defined") { expect(const).to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has been stubbed") { expect(const).to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("exposes its original value") { expect(const.original_value).to eq(:m) } end context 'for a previously undefined stubbed constant' do before { stub_const("TestClass::Undefined", :other) } let(:const) { Constant.original("TestClass::Undefined") } it("exposes its name") { expect(const.name).to eq("TestClass::Undefined") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was not previously defined") { expect(const).not_to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has been stubbed") { expect(const).to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for the original value") { expect(const.original_value).to be_nil } end context 'for a previously undefined parent of a stubbed constant' do before { stub_const("TestClass::UndefinedModule::Undefined", :other) } let(:const) { Constant.original("TestClass::UndefinedModule") } it("exposes its name") { expect(const.name).to eq("TestClass::UndefinedModule") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was not previously defined") { expect(const).not_to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has been stubbed") { expect(const).to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for the original value") { expect(const.original_value).to be_nil } end context 'for a previously undefined unstubbed constant' do let(:const) { Constant.original("TestClass::Undefined") } it("exposes its name") { expect(const.name).to eq("TestClass::Undefined") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was not previously defined") { expect(const).not_to be_previously_defined } it("indicates it has not been mutated") { expect(const).not_to be_mutated } it("indicates it has not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for the original value") { expect(const.original_value).to be_nil } end context 'for a previously defined constant that has been stubbed twice' do before { stub_const("TestClass::M", 1) } before { stub_const("TestClass::M", 2) } let(:const) { Constant.original("TestClass::M") } it("exposes its name") { expect(const.name).to eq("TestClass::M") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously defined") { expect(const).to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has been stubbed") { expect(const).to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("exposes its original value") { expect(const.original_value).to eq(:m) } end context 'for a previously undefined constant that has been stubbed twice' do before { stub_const("TestClass::Undefined", 1) } before { stub_const("TestClass::Undefined", 2) } let(:const) { Constant.original("TestClass::Undefined") } it("exposes its name") { expect(const.name).to eq("TestClass::Undefined") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was not previously defined") { expect(const).not_to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has been stubbed") { expect(const).to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for the original value") { expect(const.original_value).to be_nil } end context 'for a previously undefined hidden constant' do before { hide_const("SomeUndefinedConst") } let(:const) { Constant.original("SomeUndefinedConst") } it("exposes its name") { expect(const.name).to eq("SomeUndefinedConst") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously undefined") { expect(const).not_to be_previously_defined } it("indicates it has not been mutated") { expect(const).not_to be_mutated } it("indicates it has not not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for the original value") { expect(const.original_value).to be_nil } end context 'for a previously defined hidden constant' do before { hide_const("TestClass::M") } let(:const) { Constant.original("TestClass::M") } it("exposes its name") { expect(const.name).to eq("TestClass::M") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously defined") { expect(const).to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has been hidden") { expect(const).to be_hidden } it("exposes its original value") { expect(const.original_value).to eq(:m) } end context 'for a previously defined constant that has been hidden twice' do before { hide_const("TestClass::M") } before { hide_const("TestClass::M") } let(:const) { Constant.original("TestClass::M") } it("exposes its name") { expect(const.name).to eq("TestClass::M") } it("indicates the name is valid") { expect(const).to be_valid_name } it("indicates it was previously defined") { expect(const).to be_previously_defined } it("indicates it has been mutated") { expect(const).to be_mutated } it("indicates it has not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has been hidden") { expect(const).to be_hidden } it("exposes its original value") { expect(const.original_value).to eq(:m) } end context "for an invalid const name (such as an anonymous module's `inspect` output)" do let(:mod) { Module.new } let(:const) { Constant.original(mod.inspect) } it("exposes the provided string as the name") { expect(const.name).to eq(mod.inspect) } it("indicates the name is invalid") { expect(const).not_to be_valid_name } it("indicates it was not previously defined") { expect(const).not_to be_previously_defined } it("indicates it has not been mutated") { expect(const).not_to be_mutated } it("indicates it has not been stubbed") { expect(const).not_to be_stubbed } it("indicates it has not been hidden") { expect(const).not_to be_hidden } it("returns nil for its original value") { expect(const.original_value).to be_nil } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/thrice_counts_spec.rb0000664000000000000000000000453214557670305026423 0ustar rootrootmodule RSpec module Mocks RSpec.describe "#thrice" do before(:each) do @double = double("test double") end it "passes when called thrice" do expect(@double).to receive(:do_something).thrice 3.times { @double.do_something } verify @double end it "passes when called thrice with specified args" do expect(@double).to receive(:do_something).thrice.with("1", 1) 3.times { @double.do_something("1", 1) } verify @double end it "passes when called thrice with unspecified args" do expect(@double).to receive(:do_something).thrice @double.do_something("1") @double.do_something(1) @double.do_something(nil) verify @double end it "fails fast when call count is higher than expected" do expect(@double).to receive(:do_something).thrice 3.times { @double.do_something } expect_fast_failure_from(@double) do @double.do_something end end it "fails when call count is lower than expected" do expect(@double).to receive(:do_something).thrice @double.do_something expect { verify @double }.to fail end it "fails when called with wrong args on the first call" do expect(@double).to receive(:do_something).thrice.with("1", 1) expect { @double.do_something(1, "1") }.to fail reset @double end it "fails when called with wrong args on the second call" do expect(@double).to receive(:do_something).thrice.with("1", 1) @double.do_something("1", 1) expect { @double.do_something(1, "1") }.to fail reset @double end it "fails when called with wrong args on the third call" do expect(@double).to receive(:do_something).thrice.with("1", 1) @double.do_something("1", 1) @double.do_something("1", 1) expect { @double.do_something(1, "1") }.to fail reset @double end context "when called with negative expectation" do it "raises an error" do expect { expect(@double).not_to receive(:do_something).thrice }.to raise_error(/`count` is not supported with negative message expectations/) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/array_including_matcher_spec.rb0000664000000000000000000000514314557670305030426 0ustar rootrootmodule RSpec module Mocks module ArgumentMatchers RSpec.describe ArrayIncludingMatcher do it "describes itself properly" do expect(ArrayIncludingMatcher.new([1, 2, 3]).description).to eq "array_including(1, 2, 3)" end it "describes passed matchers" do description = array_including(fake_matcher(Object.new)).description expect(description).to include(MatcherHelpers.fake_matcher_description) end context "passing" do it "matches the same array" do expect(array_including([1, 2, 3])).to be === [1, 2, 3] end it "matches the same array, specified without square brackets" do expect(array_including(1, 2, 3)).to be === [1, 2, 3] end it "matches the same array, specified without square brackets" do expect(array_including(1, 2, 3)).to be === [1, 2, 3] end it "matches the same array, which includes nested arrays" do expect(array_including([1, 2], 3, 4)).to be === [[1, 2], 3, 4] end it "works with duplicates in expected" do expect(array_including(1, 1, 2, 3)).to be === [1, 2, 3] end it "works with duplicates in actual" do expect(array_including(1, 2, 3)).to be === [1, 1, 2, 3] end it "is composable with other matchers" do klass = Class.new dbl = double expect(dbl).to receive(:a_message).with(3, array_including(instance_of(klass))) dbl.a_message(3, [1, klass.new, 4]) end # regression check it "is composable when nested" do expect(array_including(1, array_including(2, 3), 4)).to be === [1, [2, 3], 4] expect([[1, 2], 3, 4]).to match array_including(array_including(1, 2), 3, 4) expect([1,[1,2]]).to match array_including(1, array_including(1,2)) end end context "failing" do it "fails when not all the entries in the expected are present" do expect(array_including(1, 2, 3, 4, 5)).not_to be === [1, 2] end it "fails when passed a composed matcher is passed and not satisfied" do with_unfulfilled_double do |dbl| expect { klass = Class.new expect(dbl).to receive(:a_message).with(3, array_including(instance_of(klass))) dbl.a_message(3, [1, 4]) }.to fail_with(/expected: \(3, array_including\(an_instance_of\(\)\)\)/) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/and_yield_spec.rb0000664000000000000000000001241114557670305025475 0ustar rootrootRSpec.describe RSpec::Mocks::Double do let(:obj) { double } describe "#and_yield" do context 'when the method double has been constrained by `with`' do it 'uses the default stub if the provided args do not match' do allow(obj).to receive(:foo) { 15 } allow(obj).to receive(:foo).with(:yield).and_yield # should_receive is required to trigger the bug: # https://github.com/rspec/rspec-mocks/issues/127 expect(obj).to receive(:foo) expect(obj.foo(:dont_yield)).to eq(15) end end context "with eval context as block argument" do it "evaluates the supplied block as it is read" do evaluated = false allow(obj).to receive(:method_that_accepts_a_block).and_yield do |_eval_context| evaluated = true end expect(evaluated).to be_truthy end it "passes an eval context object to the supplied block" do allow(obj).to receive(:method_that_accepts_a_block).and_yield do |eval_context| expect(eval_context).not_to be_nil end end it "evaluates the block passed to the stubbed method in the context of the supplied eval context" do expected_eval_context = nil actual_eval_context = nil allow(obj).to receive(:method_that_accepts_a_block).and_yield do |eval_context| expected_eval_context = eval_context end obj.method_that_accepts_a_block do actual_eval_context = self end expect(actual_eval_context).to equal(expected_eval_context) end context "and no yielded arguments" do it "passes when expectations set on the eval context are met" do configured_eval_context = nil allow(obj).to receive(:method_that_accepts_a_block).and_yield do |eval_context| configured_eval_context = eval_context expect(configured_eval_context).to receive(:foo) end obj.method_that_accepts_a_block do foo end verify configured_eval_context end it "fails when expectations set on the eval context are not met" do configured_eval_context = nil allow(obj).to receive(:method_that_accepts_a_block).and_yield do |eval_context| configured_eval_context = eval_context expect(configured_eval_context).to receive(:foo) end obj.method_that_accepts_a_block do # foo is not called here end expect { verify configured_eval_context }.to fail end end context "and yielded arguments" do it "passes when expectations set on the eval context and yielded arguments are met" do configured_eval_context = nil yielded_arg = Object.new allow(obj).to receive(:method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context| configured_eval_context = eval_context expect(configured_eval_context).to receive(:foo) expect(yielded_arg).to receive(:bar) end obj.method_that_accepts_a_block do |object| object.bar foo end verify configured_eval_context verify yielded_arg end context "that are optional", :if => RSpec::Support::RubyFeatures.optional_and_splat_args_supported? do it "yields the default argument when the argument is not given" do pending "Not sure how to achieve this yet. See rspec/rspec-mocks#714 and rspec/rspec-support#85." default_arg = Object.new object = Object.new allow(object).to receive(:a_message).and_yield expect(default_arg).to receive(:bar) eval("object.a_message { |receiver=default_arg| receiver.bar }") end it "yields given argument when the argument is given" do default_arg = Object.new allow(default_arg).to receive(:bar) given_arg = Object.new object = Object.new allow(object).to receive(:a_message).and_yield(given_arg) expect(given_arg).to receive(:bar) eval("object.a_message { |receiver=default_arg| receiver.bar }") end end it 'can yield to a block that uses `super`' do klass = Class.new { def foo; 13; end } subklass = Class.new(klass) { def foo(arg); arg.bar { super() }; end } arg = double expect(arg).to receive(:bar).and_yield instance = subklass.new instance.foo(arg) end it "fails when expectations set on the eval context and yielded arguments are not met" do configured_eval_context = nil yielded_arg = Object.new allow(obj).to receive(:method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context| configured_eval_context = eval_context expect(configured_eval_context).to receive(:foo) expect(yielded_arg).to receive(:bar) end obj.method_that_accepts_a_block do |_obj| # _obj.bar is not called here # foo is not called here end expect { verify configured_eval_context }.to fail expect { verify yielded_arg }.to fail end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/reraising_eager_raises_spec.rb0000664000000000000000000001214614557670305030246 0ustar rootrootrequire "spec_helper" RSpec.describe "Reraising eager raises during the verify step" do it "does not reraise when a double receives a message that hasn't been allowed/expected" do with_unfulfilled_double do |dbl| expect { dbl.foo }.to fail expect { verify_all }.not_to raise_error end end context "when a negative expectation receives a call" do it "reraises during verification" do with_unfulfilled_double do |dbl| expect(dbl).not_to receive(:foo) expect { dbl.foo }.to fail expect { verify_all }.to fail_with(/expected: 0 times with any arguments/) end end it 'notifies both exceptions using the same `:source_id` so `aggregate_failures` can de-dup' do with_unfulfilled_double do |dbl| expect(dbl).not_to receive(:foo) expect { dbl.foo }.to notify_with_same_source_id_as_later_verification end end it 'notifies with a different `source_id` than that for the same double and a different message' do with_unfulfilled_double do |dbl| expect(dbl).not_to receive(:foo) expect { dbl.foo # should trigger first source_id reset(dbl) # Prepare a failing expectation for a different message expect(dbl).not_to receive(:bar) RSpec::Support.with_failure_notifier(Proc.new {}) { dbl.bar } }.not_to notify_with_same_source_id_as_later_verification end end it 'notifies with a different `source_id` than a different double expecting that message' do with_unfulfilled_double do |dbl_1| with_unfulfilled_double do |dbl_2| expect(dbl_1).not_to receive(:foo) expect(dbl_2).not_to receive(:foo) expect { dbl_2.foo }.to fail expect { dbl_1.foo; reset(dbl_1) }.not_to notify_with_same_source_id_as_later_verification end end end end context "when an expectation with a count is exceeded" do def prepare(dbl) expect(dbl).to receive(:foo).exactly(2).times dbl.foo dbl.foo end it "reraises during verification" do with_unfulfilled_double do |dbl| prepare dbl expect { dbl.foo }.to fail expect { verify_all }.to fail_with(/expected: 2 times with any arguments/) end end it 'notifies both exceptions using the same `:source_id` so `aggregate_failures` can de-dup' do with_unfulfilled_double do |dbl| prepare dbl expect { dbl.foo }.to notify_with_same_source_id_as_later_verification end end end context "when an expectation is called with the wrong arguments" do it "reraises during verification" do with_unfulfilled_double do |dbl| expect(dbl).to receive(:foo).with(1, 2, 3) expect { dbl.foo(1, 2, 4) }.to fail expect { verify_all }.to fail_with(/expected: 1 time with arguments: \(1, 2, 3\)/) end end it 'notifies both exceptions using the same `:source_id` so `aggregate_failures` can de-dup' do with_unfulfilled_double do |dbl| expect(dbl).to receive(:foo).with(1, 2, 3) expect { dbl.foo(1, 2, 4) }.to notify_with_same_source_id_as_later_verification end end end context "when an expectation is called out of order", :pending => "Says bar was called 0 times when it was, see: http://git.io/pjTq" do it "reraises during verification" do with_unfulfilled_double do |dbl| expect(dbl).to receive(:foo).ordered expect(dbl).to receive(:bar).ordered expect { dbl.bar }.to fail dbl.foo # satisfy the `foo` expectation so that only the bar one fails below expect { verify_all }.to fail_with(/received :bar out of order/) end end end RSpec::Matchers.define :notify_with_same_source_id_as_later_verification do attr_reader :block match do |block| @block = block block_source_id == verify_all_source_id && block_source_id end match_when_negated do |block| @block = block block_source_id && verify_all_source_id && ( block_source_id != verify_all_source_id ) end supports_block_expectations failure_message do if block_source_id.nil? "expected it to notify with a non-nil source id" else "expected `verify_all` to notify with source_id: #{block_source_id.inspect} but notified with source_id: #{verify_all_source_id.inspect}" end end failure_message_when_negated do if block_source_id.nil? "expected it to notify with a non-nil source id" else "expected `verify_all` to notify with a different source_id but got the same one: #{block_source_id.inspect} / #{verify_all_source_id.inspect}" end end def block_source_id @block_source_id ||= capture_notified_source_id(&block) end def verify_all_source_id @verify_all_source_id ||= capture_notified_source_id { verify_all } end def capture_notified_source_id(&block) source_id = nil notifier = Proc.new { |_err, opt| source_id = opt.fetch(:source_id) } RSpec::Support.with_failure_notifier(notifier, &block) source_id end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/nil_expectation_warning_spec.rb0000664000000000000000000000534314557670305030465 0ustar rootrootmodule RSpec module Mocks RSpec.describe "an expectation set on nil" do it "issues a warning with file and line number information" do expect { expect(nil).to receive(:foo) }.to output(a_string_including( "An expectation of `:foo` was set on `nil`", "#{__FILE__}:#{__LINE__ - 3}" )).to_stderr nil.foo end it "issues a warning when the expectation is negative" do expect { expect(nil).not_to receive(:foo) }.to output(a_string_including( "An expectation of `:foo` was set on `nil`", "#{__FILE__}:#{__LINE__ - 3}" )).to_stderr end it 'does not issue a warning when expectations are set to be allowed' do allow_message_expectations_on_nil expect { expect(nil).to receive(:foo) expect(nil).to_not receive(:bar) }.not_to output.to_stderr nil.foo end context 'configured to allow expectation on nil' do include_context 'with isolated configuration' it 'does not issue a warning when expectations are set to be allowed' do RSpec::Mocks.configuration.allow_message_expectations_on_nil = true expect { expect(nil).to receive(:foo) expect(nil).not_to receive(:bar) }.not_to output.to_stderr nil.foo end end context 'configured to disallow expectations on nil' do include_context 'with isolated configuration' it "raises an error when expectations on nil are disallowed" do RSpec::Mocks.configuration.allow_message_expectations_on_nil = false expect { expect(nil).to receive(:foo) }.to raise_error(RSpec::Mocks::MockExpectationError) expect { expect(nil).not_to receive(:bar) }.to raise_error(RSpec::Mocks::MockExpectationError) end end it 'does not call #nil? on a double extra times' do dbl = double expect(dbl).to receive(:nil?).once.and_return(false) dbl.nil? end end RSpec.describe "#allow_message_expectations_on_nil" do include_context "with monkey-patched marshal" it "does not affect subsequent examples" do allow_message_expectations_on_nil RSpec::Mocks.teardown RSpec::Mocks.setup expect { expect(nil).to receive(:foo) }.to output(a_string_including( "An expectation of `:foo` was set on `nil`", "#{__FILE__}:#{__LINE__ - 3}" )).to_stderr nil.foo end it 'doesnt error when marshalled' do allow_message_expectations_on_nil expect(Marshal.dump(nil)).to eq Marshal.dump_without_rspec_mocks(nil) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/hash_including_matcher_spec.rb0000664000000000000000000000717714557670305030244 0ustar rootrootmodule RSpec module Mocks module ArgumentMatchers RSpec.describe HashIncludingMatcher do it "describes itself properly" do expect(HashIncludingMatcher.new(:a => 1).description).to eq "hash_including(:a=>1)" end it "describes passed matchers" do description = hash_including(:foo => fake_matcher(Object.new)).description expect(description).to include(MatcherHelpers.fake_matcher_description) end describe "passing" do it "matches the same hash" do expect(hash_including(:a => 1)).to be === {:a => 1} end it "matches a hash with extra stuff" do expect(hash_including(:a => 1)).to be === {:a => 1, :b => 2} end it "matches against classes inheriting from Hash" do expect(hash_including(Class.new(Hash)[:a, 1])).to be === {:a => 1} end describe "when matching against other matchers" do it "matches an int against anything()" do expect(hash_including(:a => anything, :b => 2)).to be === {:a => 1, :b => 2} end it "matches a string against anything()" do expect(hash_including(:a => anything, :b => 2)).to be === {:a => "1", :b => 2} end it 'can match against arbitrary objects that implement #===' do expect(hash_including(:a => /foo/)).to be === { :a => "foobar" } end end describe "when passed only keys or keys mixed with key/value pairs" do it "matches if the key is present" do expect(hash_including(:a)).to be === {:a => 1, :b => 2} end it "matches if more keys are present" do expect(hash_including(:a, :b)).to be === {:a => 1, :b => 2, :c => 3} end it "matches a string against a given key" do expect(hash_including(:a)).to be === {:a => "1", :b => 2} end it "matches if passed one key and one key/value pair" do expect(hash_including(:a, :b => 2)).to be === {:a => 1, :b => 2} end it "matches if passed many keys and one key/value pair" do expect(hash_including(:a, :b, :c => 3)).to be === {:a => 1, :b => 2, :c => 3, :d => 4} end it "matches if passed many keys and many key/value pairs" do expect(hash_including(:a, :b, :c => 3, :e => 5)).to be === {:a => 1, :b => 2, :c => 3, :d => 4, :e => 5} end end end describe "failing" do it "does not match a non-hash" do expect(hash_including(:a => 1)).not_to be === 1 end it "does not match a hash with a missing key" do expect(hash_including(:a => 1)).not_to be === { :b => 2 } end it "does not match a hash with a missing key" do expect(hash_including(:a)).not_to be === { :b => 2 } end it "does not match an empty hash with a given key" do expect(hash_including(:a)).not_to be === {} end it "does not match a hash with a missing key when one pair is matching" do expect(hash_including(:a, :b => 2)).not_to be === { :b => 2 } end it "does not match a hash with an incorrect value" do expect(hash_including(:a => 1, :b => 2)).not_to be === { :a => 1, :b => 3 } end it "does not match when values are nil but keys are different" do expect(hash_including(:a => nil)).not_to be === { :b => nil } end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/expiration_spec.rb0000664000000000000000000000475614557670305025744 0ustar rootrootmodule RSpec module Mocks RSpec.describe "After a test double has been torn down" do RSpec.shared_examples_for "expiration" do before do expect(dbl).to receive(:foo).at_least(:once) allow(dbl).to receive(:bar) dbl.foo RSpec::Mocks.verify RSpec::Mocks.teardown RSpec::Mocks.setup end it 'disallows previously mocked methods' do expect { dbl.foo }.to raise_error(ExpiredTestDoubleError) end it 'disallows previously stubbed methods' do expect { dbl.bar }.to raise_error(ExpiredTestDoubleError) end it 'disallows stubbing new methods (with receive)' do expect { allow(dbl).to receive(:bazz) }.to raise_error(ExpiredTestDoubleError) end it 'disallows stubbing new methods (with receive_messages)' do expect { allow(dbl).to receive_messages(:bazz => 3) }.to raise_error(ExpiredTestDoubleError) end it 'disallows stubbing new message chains' do expect { allow(dbl).to receive_message_chain(:bazz, :bam, :goo) }.to raise_error(ExpiredTestDoubleError) end it 'disallows mocking new methods' do expect { expect(dbl).to receive(:bazz) }.to raise_error(ExpiredTestDoubleError) end it 'disallows being turned into a null object' do expect { dbl.as_null_object }.to raise_error(ExpiredTestDoubleError) end it 'disallows being checked for nullness' do expect { dbl.null_object? }.to raise_error(ExpiredTestDoubleError) end end context "for a plain double" do let(:dbl) { double } include_examples "expiration" end class ExpiredInstanceInterface def foo; end def bar; end def bazz; end end class ExpiredClassInterface def self.foo; end def self.bar; end def self.bazz; end end context "for an instance_double" do let(:dbl) { instance_double(ExpiredInstanceInterface) } include_examples "expiration" end context "for a class_double" do let(:dbl) { class_double(ExpiredClassInterface) } include_examples "expiration" end context "for an object_double" do let(:dbl) { object_double(ExpiredInstanceInterface.new) } include_examples "expiration" end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/configuration_spec.rb0000664000000000000000000001452714557670305026426 0ustar rootrootmodule RSpec module Mocks RSpec.describe Configuration do let(:config) { Configuration.new } let(:mod_1) { Module.new } let(:mod_2) { Module.new } def instance_methods_of(_mod) mod_1.instance_methods.map(&:to_sym) end it 'adds stub and should_receive to the given modules' do expect(instance_methods_of(mod_1)).not_to include(:stub, :should_receive) expect(instance_methods_of(mod_2)).not_to include(:stub, :should_receive) config.add_stub_and_should_receive_to(mod_1, mod_2) expect(instance_methods_of(mod_1)).to include(:stub, :should_receive) expect(instance_methods_of(mod_2)).to include(:stub, :should_receive) end shared_examples "configuring the syntax" do def sandboxed orig_syntax = RSpec::Mocks.configuration.syntax yield ensure configure_syntax(orig_syntax) end around(:each) { |ex| sandboxed(&ex) } let(:dbl) { double } let(:should_methods) { [:should_receive, :stub, :should_not_receive] } let(:should_class_methods) { [:any_instance] } let(:expect_methods) { [:receive, :allow, :expect_any_instance_of, :allow_any_instance_of] } it 'defaults to enabling both the :should and :expect syntaxes' do # This is kinda a hack, but since we want to enforce use of # the expect syntax within our specs here, we have modified the # config setting, which makes it hard to get at the original # default value. in spec_helper.rb we store the default value # in $default_rspec_mocks_syntax so we can use it here. RSpec::Mocks.configuration.syntax = $default_rspec_mocks_syntax expect(dbl).to respond_to(*should_methods) expect(self).to respond_to(*expect_methods) end context 'when configured to :expect' do before { configure_syntax :expect } it 'removes the should methods from every object' do expect(dbl).not_to respond_to(*should_methods) end it 'removes `any_instance` from every class' do expect(Class.new).not_to respond_to(*should_class_methods) end it 'adds the expect methods to the example group context' do expect(self).to respond_to(*expect_methods) end it 'reports that the syntax is :expect' do expect(configured_syntax).to eq([:expect]) end it 'is a no-op when configured a second time' do expect(Syntax.default_should_syntax_host).not_to receive(:method_undefined) expect(::RSpec::Mocks::ExampleMethods).not_to receive(:method_added) configure_syntax :expect end end context 'when configured to :should' do before { configure_syntax :should } it 'adds the should methods to every object' do expect(dbl).to respond_to(*should_methods) end it 'adds `any_instance` to every class' do expect(Class.new).to respond_to(*should_class_methods) end it 'removes the expect methods from the example group context' do expect(self).not_to respond_to(*expect_methods) end it 'reports that the syntax is :should' do expect(configured_syntax).to eq([:should]) end it "does not warn about the should syntax" do RSpec.should_not_receive(:deprecate) Object.new.should_not_receive(:bees) end it 'is a no-op when configured a second time' do Syntax.default_should_syntax_host.should_not_receive(:method_added) ::RSpec::Mocks::ExampleMethods.should_not_receive(:method_undefined) configure_syntax :should end end context 'when configured to [:should, :expect]' do before { configure_syntax [:should, :expect] } it 'adds the should methods to every object' do expect(dbl).to respond_to(*should_methods) end it 'adds `any_instance` to every class' do expect(Class.new).to respond_to(*should_class_methods) end it 'adds the expect methods to the example group context' do expect(self).to respond_to(*expect_methods) end it 'reports that both syntaxes are enabled' do expect(configured_syntax).to eq([:should, :expect]) end it "does not warn about the should syntax" do expect(RSpec).not_to receive(:deprecate) expect(Object.new).not_to receive(:bees) end end end describe "configuring rspec-mocks directly" do it_behaves_like "configuring the syntax" do def configure_syntax(syntax) RSpec::Mocks.configuration.syntax = syntax end def configured_syntax RSpec::Mocks.configuration.syntax end def configure_default_syntax RSpec::Mocks.configuration.reset_syntaxes_to_default end end end describe "configuring using the rspec-core config API" do it_behaves_like "configuring the syntax" do def configure_syntax(syntax) RSpec.configure do |rspec| rspec.mock_with :rspec do |c| c.syntax = syntax end end end def configured_syntax RSpec.configure do |rspec| rspec.mock_with :rspec do |c| return c.syntax end end end def configure_default_syntax RSpec.configure do |rspec| rspec.mock_with :rspec do |c| c.reset_syntaxes_to_default end end end end end describe "#when_declaring_verifying_double" do include_context 'with isolated configuration' it "captures the supplied blocks" do block = proc { |ref| ref } block2 = proc { |ref| ref } RSpec.configuration.mock_with :rspec do |config| config.before_verifying_doubles(&block) config.when_declaring_verifying_double(&block2) expect(config.verifying_double_callbacks).to eq [block, block2] end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/at_least_spec.rb0000664000000000000000000001222114557670305025340 0ustar rootrootmodule RSpec module Mocks RSpec.describe "at_least" do before(:each) { @double = double } it "fails if method is never called" do expect(@double).to receive(:do_something).at_least(4).times expect { verify @double }.to raise_error(/expected: at least 4 times.*received: 0 times/m) end it "fails when called less than n times" do expect(@double).to receive(:do_something).at_least(4).times @double.do_something @double.do_something @double.do_something expect { verify @double }.to raise_error(/expected: at least 4 times.*received: 3 times/m) end it "fails when at least once method is never called" do expect(@double).to receive(:do_something).at_least(:once) expect { verify @double }.to raise_error(/expected: at least 1 time.*received: 0 times/m) end it "fails when at least twice method is called once" do expect(@double).to receive(:do_something).at_least(:twice) @double.do_something expect { verify @double }.to raise_error(/expected: at least 2 times.*received: 1 time/m) end it "fails when at least twice method is never called" do expect(@double).to receive(:do_something).at_least(:twice) expect { verify @double }.to raise_error(/expected: at least 2 times.*received: 0 times/m) end it "fails when at least thrice method is called less than three times" do expect(@double).to receive(:do_something).at_least(:thrice) @double.do_something @double.do_something expect { verify @double }.to raise_error(/expected: at least 3 times.*received: 2 times/m) end it "passes when at least n times method is called exactly n times" do expect(@double).to receive(:do_something).at_least(4).times @double.do_something @double.do_something @double.do_something @double.do_something verify @double end it "passes when at least n times method is called n plus 1 times" do expect(@double).to receive(:do_something).at_least(4).times @double.do_something @double.do_something @double.do_something @double.do_something @double.do_something verify @double end it "passes when at least once method is called once" do expect(@double).to receive(:do_something).at_least(:once) @double.do_something verify @double end it "passes when at least once method is called twice" do expect(@double).to receive(:do_something).at_least(:once) @double.do_something @double.do_something verify @double end it "passes when at least twice method is called three times" do expect(@double).to receive(:do_something).at_least(:twice) @double.do_something @double.do_something @double.do_something verify @double end it "passes when at least twice method is called twice" do expect(@double).to receive(:do_something).at_least(:twice) @double.do_something @double.do_something verify @double end it "passes when at least thrice method is called three times" do expect(@double).to receive(:do_something).at_least(:thrice) @double.do_something @double.do_something @double.do_something verify @double end it "passes when at least thrice method is called four times" do expect(@double).to receive(:do_something).at_least(:thrice) @double.do_something @double.do_something @double.do_something @double.do_something verify @double end it "returns the value given by a block when the at least once method is called" do expect(@double).to receive(:to_s).at_least(:once) { "testing" } expect(@double.to_s).to eq "testing" verify @double end context "when sent with 0" do it "outputs a removal message" do expect { expect(@double).to receive(:do_something).at_least(0).times }.to raise_error(/has been removed/) end end it "uses a stub value if no value set" do allow(@double).to receive_messages(:do_something => 'foo') expect(@double).to receive(:do_something).at_least(:once) expect(@double.do_something).to eq 'foo' expect(@double.do_something).to eq 'foo' end it "prefers its own return value over a stub" do allow(@double).to receive_messages(:do_something => 'foo') expect(@double).to receive(:do_something).at_least(:once).and_return('bar') expect(@double.do_something).to eq 'bar' expect(@double.do_something).to eq 'bar' end context "when called with negative expectation" do it "raises an error" do expect { expect(@double).not_to receive(:do_something).at_least(:thrice) }.to raise_error(/`count` is not supported with negative message expectations/) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/matchers/0000775000000000000000000000000014557670305024015 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/matchers/receive_spec.rb0000664000000000000000000006436114557670305027010 0ustar rootrootmodule RSpec module Mocks RSpec.describe Matchers::Receive do include_context "with syntax", :expect describe "expectations/allowances on any instance recorders" do include_context "with syntax", [:expect, :should] it "warns about allow(Klass.any_instance).to receive..." do expect(RSpec).to receive(:warning).with(/allow.*any_instance.*is probably not what you meant.*allow_any_instance_of.*instead/) allow(Object.any_instance).to receive(:foo) end it "includes the correct call site in the allow warning" do expect_warning_with_call_site(__FILE__, __LINE__ + 1) allow(Object.any_instance).to receive(:foo) end it "warns about expect(Klass.any_instance).to receive..." do expect(RSpec).to receive(:warning).with(/expect.*any_instance.*is probably not what you meant.*expect_any_instance_of.*instead/) any_instance_proxy = Object.any_instance expect(any_instance_proxy).to receive(:foo) any_instance_proxy.foo end it "includes the correct call site in the expect warning" do any_instance_proxy = Object.any_instance expect_warning_with_call_site(__FILE__, __LINE__ + 1) expect(any_instance_proxy).to receive(:foo) any_instance_proxy.foo end end # FIXME: this is defined here to prevent # "warning: method redefined; discarding old kw_args_method" # because shared examples are evaluated several times. # When we flatten those shared examples in RSpec 4 because # of no "should" syntax, it will become possible to put this # class definition closer to examples that use it. if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) class TestObject def kw_args_method(a:, b:); end end RUBY end shared_examples "a receive matcher" do |*options| it 'allows the caller to configure how the subject responds' do wrapped.to receive(:foo).and_return(5) expect(receiver.foo).to eq(5) end it 'allows the caller to constrain the received arguments' do wrapped.to receive(:foo).with(:a) receiver.foo(:a) expect { receiver.foo(:b) }.to raise_error(/received :foo with unexpected arguments/) end it 'allows the caller to constrain the received arguments by matcher' do wrapped.to receive(:foo).with an_instance_of Float expect { receiver.foo(1) }.to raise_error(/expected.*\(an instance of Float\)/) receiver.foo(1.1) end context 'without yielding receiver' do # when `yield_receiver_to_any_instance_implementation_blocks` is `true` # the block arguments are different for `expect` and `expect_any_instance_of` around do |example| previous_value = RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks? RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks = false example.run RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks = previous_value end it 'allows a `do...end` block implementation to be provided' do wrapped.to receive(:foo) do 4 end expect(receiver.foo).to eq(4) end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) it 'allows a `do...end` block implementation with keyword args to be provided' do wrapped.to receive(:foo) do |**kwargs| kwargs[:kw] end expect(receiver.foo(kw: :arg)).to eq(:arg) end it 'allows a `do...end` block implementation with optional keyword args to be provided' do wrapped.to receive(:foo) do |kw: :arg| kw end expect(receiver.foo(kw: 1)).to eq(1) end it 'allows a `do...end` block implementation with optional keyword args to be provided' do wrapped.to receive(:foo) do |kw: :arg| kw end expect(receiver.foo).to eq(:arg) end RUBY end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) it 'allows a `do...end` block implementation with required keyword args' do wrapped.to receive(:foo) do |kw:| kw end expect(receiver.foo(kw: :arg)).to eq(:arg) end it "expects to receive keyword args" do dbl = instance_double(TestObject) expect(dbl).to receive(:kw_args_method).with(a: 1, b: 2) dbl.kw_args_method(a: 1, b: 2) end if RUBY_VERSION >= '3.0' it "fails to expect to receive hash with keyword args" do expect { dbl = instance_double(TestObject) expect(dbl).to receive(:kw_args_method).with(a: 1, b: 2) dbl.kw_args_method({a: 1, b: 2}) }.to fail_with do |failure| reset_all expect(failure.message) .to include('expected: ({:a=>1, :b=>2}) (keyword arguments)') .and include('got: ({:a=>1, :b=>2}) (options hash)') end end else it "expects to receive hash with keyword args" do dbl = instance_double(TestObject) expect(dbl).to receive(:kw_args_method).with(a: 1, b: 2) dbl.kw_args_method({a: 1, b: 2}) end end it "expects to receive hash with a hash" do dbl = instance_double(TestObject) expect(dbl).to receive(:kw_args_method).with({a: 1, b: 2}) dbl.kw_args_method({a: 1, b: 2}) end it "expects to receive keyword args with a hash" do dbl = instance_double(TestObject) expect(dbl).to receive(:kw_args_method).with({a: 1, b: 2}) dbl.kw_args_method(a: 1, b: 2) end RUBY end end it 'allows chaining off a `do...end` block implementation to be provided' do wrapped.to receive(:foo) do 4 end.and_return(6) expect(receiver.foo).to eq(6) end it 'allows a `{ ... }` block implementation to be provided' do wrapped.to receive(:foo) { 5 } expect(receiver.foo).to eq(5) end it 'gives precedence to a `{ ... }` block when both forms are provided ' \ 'since that form actually binds to `receive`' do wrapped.to receive(:foo) { :curly } do :do_end end expect(receiver.foo).to eq(:curly) end it 'does not support other matchers', :unless => options.include?(:allow_other_matchers) do expect { wrapped.to eq(3) }.to raise_error(UnsupportedMatcherError) end it 'does support inherited matchers', :unless => options.include?(:allow_other_matchers) do receive_foo = Class.new(RSpec::Mocks::Matchers::Receive).new(:foo, nil) wrapped.to receive_foo receiver.foo end it 'does not get confused by messages being passed as strings and symbols' do wrapped.to receive(:foo).with(1) { :a } wrapped.to receive("foo").with(2) { :b } expect(receiver.foo(1)).to eq(:a) expect(receiver.foo(2)).to eq(:b) end it 'allows do...end blocks to be passed to the fluent interface methods without getting a warning' do expect(RSpec).not_to receive(:warning) wrapped.to receive(:foo).with(1) do :a end expect(receiver.foo(1)).to eq(:a) end it 'makes { } blocks trump do...end blocks when passed to a fluent interface method' do wrapped.to receive(:foo).with(1) { :curly } do :do_end end expect(receiver.foo(1)).to eq(:curly) end end shared_examples "an expect syntax allowance" do |*options| it_behaves_like "a receive matcher", *options it 'does not expect the message to be received' do wrapped.to receive(:foo) expect { verify_all }.not_to raise_error end end shared_examples "an expect syntax negative allowance" do it 'is disabled since this expression is confusing' do expect { wrapped.not_to receive(:foo) }.to raise_error(/not_to receive` is not supported/) expect { wrapped.to_not receive(:foo) }.to raise_error(/to_not receive` is not supported/) end end shared_examples "an expect syntax expectation" do |*options| it_behaves_like "a receive matcher", *options it 'sets up a message expectation that passes if the message is received' do wrapped.to receive(:foo) receiver.foo verify_all end it 'sets up a message expectation that fails if the message is not received' do wrapped.to receive(:foo) expect { verify_all }.to fail end it "reports the line number of expectation of unreceived message", :pending => options.include?(:does_not_report_line_num) do expected_error_line = __LINE__; wrapped.to receive(:foo) expect { verify_all }.to raise_error { |e| expect(e.backtrace.first).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/) } end it "provides a useful matcher description" do matcher = receive(:foo).with(:bar).once wrapped.to matcher receiver.foo(:bar) expect(matcher.description).to start_with("receive foo") end end shared_examples "an expect syntax negative expectation" do it 'sets up a negative message expectation that passes if the message is not received' do wrapped.not_to receive(:foo) verify_all end it 'sets up a negative message expectation that fails if the message is received' do wrapped.not_to receive(:foo) expect_fast_failure_from(receiver, /expected: 0 times.*received: 1 time/m) do receiver.foo end end it 'supports `to_not` as an alias for `not_to`' do wrapped.to_not receive(:foo) expect_fast_failure_from(receiver, /expected: 0 times.*received: 1 time/m) do receiver.foo end end it 'allows the caller to constrain the received arguments' do wrapped.not_to receive(:foo).with(:a) def receiver.method_missing(*); end # a poor man's stub... expect { receiver.foo(:b) }.not_to raise_error expect_fast_failure_from(receiver, /expected: 0 times.*received: 1 time/m) do receiver.foo(:a) end end it 'prevents confusing double-negative expressions involving `never`' do expect { wrapped.not_to receive(:foo).never }.to raise_error(/trying to negate it again/) expect { wrapped.to_not receive(:foo).never }.to raise_error(/trying to negate it again/) end end shared_examples "resets partial mocks cleanly" do let(:klass) { Struct.new(:foo) } let(:object) { klass.new :bar } it "removes the method double" do target.to receive(:foo).and_return(:baz) expect { reset object }.to change { object.foo }.from(:baz).to(:bar) end end shared_examples "resets partial mocks of any instance cleanly" do let(:klass) { Struct.new(:foo) } let(:object) { klass.new :bar } it "removes the method double" do target.to receive(:foo).and_return(:baz) expect { verify_all }.to change { object.foo }.from(:baz).to(:bar) end end shared_examples "handles frozen objects cleanly" do let(:klass) { Struct.new(:foo) } let(:object) { klass.new :bar } context "when adding the method double" do it "raises clear error" do object.freeze expect { target.to receive(:foo).and_return(:baz) }.to raise_error(ArgumentError, /Cannot proxy frozen objects/) end end context "when removing the method double" do before do if RUBY_VERSION < "2.2" && RUBY_VERSION >= "2.0" && RSpec::Support::Ruby.mri? pending "Does not work on 2.0-2.1 because frozen structs can have methods restored" end end it "warns about being unable to remove the method double" do target.to receive(:foo).and_return(:baz) expect_warning_without_call_site(/rspec-mocks was unable to restore the original `foo` method on #{object.inspect}/) object.freeze reset object end it "includes the spec location in the warning" do line = __LINE__ - 1 target.to receive(:foo).and_return(:baz) expect_warning_without_call_site(/#{RSpec::Core::Metadata.relative_path(__FILE__)}:#{line}/) object.freeze reset object end end context "with fake frozen object" do let(:klass) { Struct.new(:foo, :frozen?, :freeze) } let(:object) { klass.new :bar, true } it "allows the caller to configure how the subject responds" do object.freeze target.to receive(:foo).and_return(5) expect(object.foo).to eq(5) expect { reset object }.to change { object.foo }.from(5).to(:bar) end end end describe "allow(...).to receive" do it_behaves_like "an expect syntax allowance" do let(:receiver) { double } let(:wrapped) { allow(receiver) } end it_behaves_like "resets partial mocks cleanly" do let(:target) { allow(object) } end it_behaves_like "handles frozen objects cleanly" do let(:target) { allow(object) } end context 'ordered with receive counts' do specify 'is not supported' do a_dbl = double expect_warning_with_call_site(__FILE__, __LINE__ + 1) allow(a_dbl).to receive(:one).ordered end end context 'on a class method, from a class with subclasses' do let(:superclass) { Class.new { def self.foo; "foo"; end }} let(:subclass_redef) { Class.new(superclass) { def self.foo; ".foo."; end }} let(:subclass_deleg) { Class.new(superclass) { def self.foo; super.upcase; end }} let(:subclass_asis) { Class.new(superclass) } context 'if the method is redefined in the subclass' do it 'does not stub the method in the subclass' do allow(superclass).to receive(:foo) { "foo!!" } expect(superclass.foo).to eq "foo!!" expect(subclass_redef.foo).to eq ".foo." end end context 'if the method is not redefined in the subclass' do it 'stubs the method in the subclass' do allow(superclass).to receive(:foo) { "foo!!" } expect(superclass.foo).to eq "foo!!" expect(subclass_asis.foo).to eq "foo!!" end end it 'creates stub which can be called using `super` in a subclass' do allow(superclass).to receive(:foo) { "foo!!" } expect(subclass_deleg.foo).to eq "FOO!!" end it 'can stub the same method simultaneously in the superclass and subclasses' do allow(subclass_redef).to receive(:foo) { "__foo__" } allow(superclass).to receive(:foo) { "foo!!" } allow(subclass_deleg).to receive(:foo) { "$$foo$$" } expect(subclass_redef.foo).to eq "__foo__" expect(superclass.foo).to eq "foo!!" expect(subclass_deleg.foo).to eq "$$foo$$" end end end describe "allow(...).not_to receive" do it_behaves_like "an expect syntax negative allowance" do let(:wrapped) { allow(double) } end end describe "allow_any_instance_of(...).to receive" do it_behaves_like "an expect syntax allowance" do let(:klass) { Class.new } let(:wrapped) { allow_any_instance_of(klass) } let(:receiver) { klass.new } end it_behaves_like "resets partial mocks of any instance cleanly" do let(:target) { allow_any_instance_of(klass) } end end describe "allow_any_instance_of(...).not_to receive" do it_behaves_like "an expect syntax negative allowance" do let(:wrapped) { allow_any_instance_of(Class.new) } end end describe "expect(...).to receive" do it_behaves_like "an expect syntax expectation", :allow_other_matchers do let(:receiver) { double } let(:wrapped) { expect(receiver) } context "when a message is not received" do it 'sets up a message expectation that formats argument matchers correctly' do wrapped.to receive(:foo).with an_instance_of Float expect { verify_all }.to( raise_error(/expected: 1 time with arguments: \(an instance of Float\)\n\s+received: 0 times$/) ) end end context "when a message is received the wrong number of times" do it "sets up a message expectation that formats argument matchers correctly" do wrapped.to receive(:foo).with(anything, hash_including(:bar => anything)) receiver.foo(1, :bar => 2) receiver.foo(1, :bar => 3) expect { verify_all }.to( raise_error(/received: 2 times with arguments: \(anything, hash_including\(:bar=>"anything"\)\)$/) ) end end end it_behaves_like "resets partial mocks cleanly" do let(:target) { expect(object) } end it_behaves_like "handles frozen objects cleanly" do let(:target) { expect(object) } end context "ordered with receive counts" do let(:dbl) { double(:one => 1, :two => 2) } it "passes with exact receive counts when the ordering is correct" do expect(dbl).to receive(:one).twice.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.one dbl.two end it "fails with exact receive counts when the ordering is incorrect" do expect { expect(dbl).to receive(:one).twice.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.two dbl.one }.to raise_error(/out of order/) reset_all end it "passes with at least when the ordering is correct" do expect(dbl).to receive(:one).at_least(2).times.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.one dbl.one dbl.two end it "fails with at least when the ordering is incorrect", :ordered_and_vague_counts_unsupported do expect { expect(dbl).to receive(:one).at_least(2).times.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.two }.to fail reset_all end it "passes with at most when the ordering is correct" do expect(dbl).to receive(:one).at_most(2).times.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.two end it "fails with at most when the ordering is incorrect", :ordered_and_vague_counts_unsupported do expect { expect(dbl).to receive(:one).at_most(2).times.ordered expect(dbl).to receive(:two).once.ordered dbl.one dbl.one dbl.one dbl.two }.to fail reset_all end it 'does not result in infinite recursion when `respond_to?` is stubbed' do # Setting a method expectation causes the method to be proxied # RSpec may call #respond_to? when processing a failed expectation # If those internal calls go to the proxied method, that could # result in another failed expectation error, causing infinite loop expect { obj = Object.new expect(obj).to receive(:respond_to?).with('something highly unlikely') obj.respond_to?(:not_what_we_wanted) }.to raise_error(/received :respond_to\? with unexpected arguments/) reset_all end end end describe "expect_any_instance_of(...).to receive" do it_behaves_like "an expect syntax expectation", :does_not_report_line_num do let(:klass) { Class.new } let(:wrapped) { expect_any_instance_of(klass) } let(:receiver) { klass.new } it 'sets up a message expectation that formats argument matchers correctly' do wrapped.to receive(:foo).with an_instance_of Float expect { verify_all }.to raise_error(/should have received the following message\(s\) but didn't/) end end it_behaves_like "resets partial mocks of any instance cleanly" do let(:target) { expect_any_instance_of(klass) } end end describe "expect(...).not_to receive" do it_behaves_like "an expect syntax negative expectation" do let(:receiver) { double } let(:wrapped) { expect(receiver) } end end describe "expect_any_instance_of(...).not_to receive" do it_behaves_like "an expect syntax negative expectation" do let(:klass) { Class.new } let(:wrapped) { expect_any_instance_of(klass) } let(:receiver) { klass.new } end end it 'has a description before being matched' do matcher = receive(:foo) expect(matcher.description).to eq("receive foo") end shared_examples "using rspec-mocks in another test framework" do it 'can use the `expect` syntax' do dbl = double framework.new.instance_exec do expect(dbl).to receive(:foo).and_return(3) end expect(dbl.foo).to eq(3) end it 'expects the method to be called when `expect` is used' do dbl = double framework.new.instance_exec do expect(dbl).to receive(:foo) end expect { verify dbl }.to fail end it 'supports `expect(...).not_to receive`' do expect_fast_failure_from(double) do |dbl| framework.new.instance_exec do expect(dbl).not_to receive(:foo) end dbl.foo end end it 'supports `expect(...).to_not receive`' do expect_fast_failure_from(double) do |dbl| framework.new.instance_exec do expect(dbl).to_not receive(:foo) end dbl.foo end end end context "when used in a test framework without rspec-expectations" do let(:framework) do Class.new do include RSpec::Mocks::ExampleMethods def eq(_) double("MyMatcher") end end end it_behaves_like "using rspec-mocks in another test framework" it 'cannot use `expect` with another matcher' do expect { framework.new.instance_exec do expect(3).to eq(3) end }.to raise_error(/only the `receive`, `have_received` and `receive_messages` matchers are supported with `expect\(...\).to`/) end it 'can toggle the available syntax' do expect(framework.new).to respond_to(:expect) RSpec::Mocks.configuration.syntax = :should expect(framework.new).not_to respond_to(:expect) RSpec::Mocks.configuration.syntax = :expect expect(framework.new).to respond_to(:expect) end after { RSpec::Mocks.configuration.syntax = :expect } end context "when rspec-expectations is included in the test framework first" do before do # the examples here assume `expect` is define in RSpec::Matchers... expect(RSpec::Matchers.method_defined?(:expect)).to be_truthy end let(:framework) do Class.new do include RSpec::Matchers include RSpec::Mocks::ExampleMethods end end it_behaves_like "using rspec-mocks in another test framework" it 'can use `expect` with any matcher' do framework.new.instance_exec do expect(3).to eq(3) end end it 'with a nonsense allowance it fails with a reasonable error message' do expect { allow(true).not_to be_nil }.to raise_error(start_with("`allow(...).not_to be_nil` is not supported since it doesn't really make sense")) end end context "when rspec-expectations is included in the test framework last" do before do # the examples here assume `expect` is define in RSpec::Matchers... expect(RSpec::Matchers.method_defined?(:expect)).to be_truthy end let(:framework) do Class.new do include RSpec::Mocks::ExampleMethods include RSpec::Matchers end end it_behaves_like "using rspec-mocks in another test framework" it 'can use `expect` with any matcher' do framework.new.instance_exec do expect(3).to eq(3) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/matchers/have_received_spec.rb0000664000000000000000000006743014557670305030157 0ustar rootrootmodule RSpec module Mocks # This shared example group is highly unusual as it is used to test how # `have_received` works in two situations: # # * With rspec-mocks as a standalone library. # * Together with rspec-expectations. # # To simulate the former, we've had to hack things a bit. Special care must be taken: # # * Only define examples with `it`, (not `fit`, `xit`, `specify`, etc). We redefine # `it` below to make it support our needs here but that definition isn't applied to # the other forms. # * All normal expectations must use `_expect`, not `expect`. Expectations # for `have_received` should use `expect`. RSpec.shared_examples_for Matchers::HaveReceived do # Make rspec-expectations' `expect` available via an alias so that when # this group is included below in a context that simulates rspec-expectations # not being loaded by using rspec-mocks' `expect` instead of rspec-expectations' # `expect`, we still have a way to use the expectations one for normal expectations. # In this group, all normal expectations should use `_expect` instead of `expect`. alias _expect expect describe "expect(...).to have_received" do it 'passes when the double has received the given message' do dbl = double_with_met_expectation(:expected_method) expect(dbl).to have_received(:expected_method) end it 'passes when a null object has received the given message' do dbl = null_object_with_met_expectation(:expected_method) expect(dbl).to have_received(:expected_method) end it 'fails when the double has not received the given message' do dbl = double_with_unmet_expectation(:expected_method) _expect { expect(dbl).to have_received(:expected_method) }.to raise_error(/expected: 1 time/) end it "notifies failures via rspec-support's failure notification system" do dbl = double_with_unmet_expectation(:expected_method) captured = nil RSpec::Support.with_failure_notifier(Proc.new { |e, _opt| captured = e }) do expect(dbl).to have_received(:expected_method) end _expect(captured.message).to include("expected: 1 time") end it 'fails when a null object has not received the given message' do dbl = double.as_null_object _expect { expect(dbl).to have_received(:expected_method) }.to raise_error(/expected: 1 time/) end it 'fails when the method has not been previously stubbed' do dbl = double _expect { expect(dbl).to have_received(:expected_method) }.to raise_error(/method has not been stubbed/) end it 'fails when the method has been mocked' do dbl = double expect(dbl).to receive(:expected_method) dbl.expected_method _expect { expect(dbl).to have_received(:expected_method) }.to raise_error(/method has been mocked instead of stubbed/) end it "takes a curly-bracket block and yields the arguments given to the stubbed method call" do dbl = double(:foo => nil) yielded = [] dbl.foo(:a, :b, :c) expect(dbl).to have_received(:foo) { |*args| yielded << args } _expect(yielded).to include([:a, :b, :c]) end it "takes a do-end block and yields the arguments given to the stubbed method call" do dbl = double(:foo => nil) yielded = [] dbl.foo(:a, :b, :c) expect(dbl).to have_received(:foo) do |*args| yielded << args end _expect(yielded).to include([:a, :b, :c]) end it "passes if expectations against the yielded arguments pass" do dbl = double(:foo => nil) dbl.foo(42) _expect { expect(dbl).to have_received(:foo) { |arg| _expect(arg).to eq(42) } }.to_not raise_error end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "passes if expectations against yielded keyword arguments pass" do binding.eval(<<-RUBY, __FILE__, __LINE__) dbl = double(:foo => nil) yielded = [] dbl.foo(a: 1) expect(dbl).to have_received(:foo) do |a:| yielded << a end _expect(yielded).to eq([1]) RUBY end end it "fails if expectations against the yielded arguments fail" do dbl = double(:foo => nil) dbl.foo(43) _expect { expect(dbl).to have_received(:foo) { |arg| _expect(arg).to eq(42) } }.to raise_error(RSpec::Expectations::ExpectationNotMetError) end it 'gives precedence to a `{ ... }` block when both forms are provided ' \ 'since that form actually binds to `receive`' do dbl = double(:foo => nil) called = [] dbl.foo expect(dbl).to have_received(:foo) { called << :curly } do called << :do_end end _expect(called).to include(:curly) _expect(called).not_to include(:do_end) end it 'forwards any block passed during method invocation to the `have_received` block' do dbl = spy block = lambda {} dbl.foo(&block) expect(dbl).to have_received(:foo) do |&passed_block| _expect(passed_block).to be block end end it 'resets expectations on class methods when mocks are reset' do dbl = Object allow(dbl).to receive(:expected_method) dbl.expected_method reset dbl allow(dbl).to receive(:expected_method) _expect { expect(dbl).to have_received(:expected_method) }.to raise_error(/0 times/) end context "with" do it 'passes when the given args match the args used with the message' do dbl = double_with_met_expectation(:expected_method, :expected, :args) expect(dbl).to have_received(:expected_method).with(:expected, :args) end it 'fails when the given args do not match the args used with the message' do dbl = double_with_met_expectation(:expected_method, :expected, :args) _expect { expect(dbl).to have_received(:expected_method).with(:unexpected, :args) }.to raise_error(/with unexpected arguments/) end end it 'generates a useful description' do matcher = have_received(:expected_method).with(:expected_args).once _expect(matcher.description).to eq 'have received expected_method(:expected_args) 1 time' end it 'can generate a description after mocks have been torn down (e.g. when rspec-core requests it)' do matcher = have_received(:expected_method).with(:expected_args).once matcher.matches?(double(:expected_method => 1)) RSpec::Mocks.teardown _expect(matcher.description).to eq 'have received expected_method(:expected_args) 1 time' end it 'produces an error message that matches the expected method if another method was called' do my_spy = spy my_spy.foo(1) my_spy.bar(3) _expect { expect(my_spy).to have_received(:foo).with(3) }.to fail_including("received :foo with unexpected arguments", "expected: (3)", "got: (1)") end context "counts" do let(:the_dbl) { double(:expected_method => nil) } before do the_dbl.expected_method(:one) the_dbl.expected_method(:two) the_dbl.expected_method(:one) end context "when constrained by `with`" do it 'only considers the calls with matching args' do expect(the_dbl).to have_received(:expected_method).with(:one).twice expect(the_dbl).to have_received(:expected_method).with(:two).once end context "when the message is received without any args matching" do it 'includes unmatched args in the error message' do _expect { expect(the_dbl).to have_received(:expected_method).with(:three).once }.to fail_including("expected: (:three)", "got:", "(:one) (2 times)", "(:two) (1 time)") end end context "when the message is received too many times" do it 'includes the counts of calls with matching args in the error message' do _expect { expect(the_dbl).to have_received(:expected_method).with(:one).once }.to fail_including("expected: 1 time", "received: 2 times") end end context "when the message is received too few times" do it 'includes the counts of calls with matching args in the error message' do _expect { expect(the_dbl).to have_received(:expected_method).with(:two).twice }.to fail_including("expected: 2 times", "received: 1 time") end end context "when constrained with grouped arguments `with`" do it 'groups the "got" arguments based on the method call that included them' do dbl = double(:expected_method => nil) dbl.expected_method(:one, :four) dbl.expected_method(:two, :four) dbl.expected_method(:three, :four) dbl.expected_method(:one, :four) dbl.expected_method(:three, :four) dbl.expected_method(:three, :four) _expect { expect(dbl).to have_received(:expected_method).with(:four, :four).once }.to fail_including("expected: (:four, :four)", "got:", "(:one, :four) (2 times)", "(:two, :four) (1 time)", "(:three, :four) (3 times)") end it 'includes single arguments based on the method call that included them' do dbl = double(:expected_method => nil) dbl.expected_method(:one, :four) _expect { expect(dbl).to have_received(:expected_method).with(:three, :four).once }.to fail_including("expected: (:three, :four)", "got: (:one, :four)") end it 'keeps the array combinations distinguished in the group' do dbl = double(:expected_method => nil) dbl.expected_method([:one], :four) dbl.expected_method(:one, [:four]) _expect { expect(dbl).to have_received(:expected_method).with(:one, :four).once }.to fail_including("expected: (:one, :four)", "got:", "([:one], :four)", "(:one, [:four])") end it 'does not group counts on repeated arguments for a single message' do dbl = double(:expected_method => nil) dbl.expected_method(:one, :one, :two) _expect { expect(dbl).to have_received(:expected_method).with(:one, :two, :three).once }.to fail_including("expected: (:one, :two, :three)", "got:", "(:one, :one, :two)") end end end context "exactly" do it 'passes when the message was received the given number of times' do expect(the_dbl).to have_received(:expected_method).exactly(3).times end it 'fails when the message was received more times than expected' do _expect { expect(the_dbl).to have_received(:expected_method).exactly(1).time }.to raise_error(/expected: 1 time.*received: 3 times/m) _expect { expect(the_dbl).to have_received(:expected_method).exactly(2).times }.to raise_error(/expected: 2 times.*received: 3 times/m) _expect { the_dbl.expected_method the_dbl.expected_method expect(the_dbl).to have_received(:expected_method).exactly(2).times }.to raise_error(/expected: 2 times.*received: 5 times/m) end it 'fails when the message was received fewer times' do _expect { expect(the_dbl).to have_received(:expected_method).exactly(4).times }.to raise_error(/expected: 4 times.*received: 3 times/m) end end context 'at_least' do it 'passes when the message was received the given number of times' do expect(the_dbl).to have_received(:expected_method).at_least(3).times end it 'passes when the message was received more times' do expect(the_dbl).to have_received(:expected_method).at_least(2).times end it 'fails when the message was received fewer times' do _expect { expect(the_dbl).to have_received(:expected_method).at_least(4).times }.to raise_error(/expected: at least 4 times.*received: 3 times/m) end end context 'at_most' do it 'passes when the message was received the given number of times' do expect(the_dbl).to have_received(:expected_method).at_most(3).times end it 'passes when the message was received fewer times' do expect(the_dbl).to have_received(:expected_method).at_most(4).times end it 'fails when the message was received more times' do _expect { expect(the_dbl).to have_received(:expected_method).at_most(2).times }.to raise_error(/expected: at most 2 times.*received: 3 times/m) end end context 'once' do it 'passes when the message was received once' do dbl = double(:expected_method => nil) dbl.expected_method expect(dbl).to have_received(:expected_method).once end it 'fails when the message was never received' do dbl = double(:expected_method => nil) _expect { expect(dbl).to have_received(:expected_method).once }.to raise_error(/expected: 1 time.*received: 0 times/m) end it 'fails when the message was received twice' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method _expect { expect(dbl).to have_received(:expected_method).once }.to raise_error(/expected: 1 time.*received: 2 times/m) end end context 'twice' do it 'passes when the message was received twice' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method expect(dbl).to have_received(:expected_method).twice end it 'fails when the message was received once' do dbl = double(:expected_method => nil) dbl.expected_method _expect { expect(dbl).to have_received(:expected_method).twice }.to raise_error(/expected: 2 times.*received: 1 time/m) end it 'fails when the message was received thrice' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method dbl.expected_method _expect { expect(dbl).to have_received(:expected_method).twice }.to raise_error(/expected: 2 times.*received: 3 times/m) end end context 'thrice' do it 'passes when the message was received thrice' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method dbl.expected_method expect(dbl).to have_received(:expected_method).thrice end it 'fails when the message was received less than three times' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method _expect { expect(dbl).to have_received(:expected_method).thrice }.to raise_error(/expected: 3 times.*received: 2 times/m) end it 'fails when the message was received more than three times' do dbl = double(:expected_method => nil) dbl.expected_method dbl.expected_method dbl.expected_method dbl.expected_method _expect { expect(dbl).to have_received(:expected_method).thrice }.to raise_error(/expected: 3 times.*received: 4 times/m) end end end context 'ordered' do let(:the_dbl) { double :one => 1, :two => 2, :three => 3 } it 'passes when the messages were received in order' do the_dbl.one the_dbl.two expect(the_dbl).to have_received(:one).ordered expect(the_dbl).to have_received(:two).ordered end it 'passes with exact receive counts when received in order' do 3.times { the_dbl.one } 2.times { the_dbl.two } the_dbl.three expect(the_dbl).to have_received(:one).thrice.ordered expect(the_dbl).to have_received(:two).twice.ordered expect(the_dbl).to have_received(:three).once.ordered end it 'passes with at most receive counts when received in order', :ordered_and_vague_counts_unsupported do the_dbl.one the_dbl.one the_dbl.two expect(the_dbl).to have_received(:one).at_most(3).times.ordered expect(the_dbl).to have_received(:one).at_most(:thrice).times.ordered expect(the_dbl).to have_received(:two).once.ordered end it 'passes with at least receive counts when received in order', :ordered_and_vague_counts_unsupported do the_dbl.one the_dbl.one the_dbl.two expect(the_dbl).to have_received(:one).at_least(1).time.ordered expect(the_dbl).to have_received(:two).once.ordered end it 'fails with exact receive counts when received out of order' do the_dbl.one the_dbl.two the_dbl.one _expect { expect(the_dbl).to have_received(:one).twice.ordered expect(the_dbl).to have_received(:two).once.ordered }.to raise_error(/received :two out of order/m) end it "fails with at most receive counts when received out of order", :ordered_and_vague_counts_unsupported do the_dbl.one the_dbl.two the_dbl.one _expect { expect(the_dbl).to have_received(:one).at_most(2).times.ordered expect(the_dbl).to have_received(:two).once.ordered }.to raise_error(/received :two out of order/m) end it "fails with at least receive counts when received out of order", :ordered_and_vague_counts_unsupported do the_dbl.one the_dbl.two the_dbl.one _expect { expect(the_dbl).to have_received(:one).at_least(1).time.ordered expect(the_dbl).to have_received(:two).once.ordered }.to raise_error(/received :two out of order/m) end it 'fails when the messages are received out of order' do the_dbl.two the_dbl.one _expect { expect(the_dbl).to have_received(:one).ordered expect(the_dbl).to have_received(:two).ordered }.to raise_error(/received :two out of order/m) end context "when used with `with`" do before do the_dbl.one(1) the_dbl.one(2) end it "passes when the order lines up" do expect(the_dbl).to have_received(:one).with(1).ordered expect(the_dbl).to have_received(:one).with(2).ordered end it "fails when the order is not matched" do _expect { expect(the_dbl).to have_received(:one).with(2).ordered expect(the_dbl).to have_received(:one).with(1).ordered }.to fail_with(/received :one out of order/m) end end context "when used on individually allowed messages" do before do allow(the_dbl).to receive(:foo) allow(the_dbl).to receive(:bar) the_dbl.foo the_dbl.bar end it 'passes when the messages were received in order' do expect(the_dbl).to have_received(:foo).ordered expect(the_dbl).to have_received(:bar).ordered end it 'fails when the messages are received out of order' do _expect { expect(the_dbl).to have_received(:bar).ordered expect(the_dbl).to have_received(:foo).ordered }.to raise_error(/received :foo out of order/m) end end end end describe "expect(...).not_to have_received" do it 'passes when the double has not received the given message' do dbl = double_with_unmet_expectation(:expected_method) expect(dbl).not_to have_received(:expected_method) end it 'fails when the double has received the given message' do dbl = double_with_met_expectation(:expected_method) _expect { expect(dbl).not_to have_received(:expected_method) }.to raise_error(/expected: 0 times.*received: 1 time/m) end it "notifies failures via rspec-support's failure notification system" do dbl = double_with_met_expectation(:expected_method) captured = nil RSpec::Support.with_failure_notifier(Proc.new { |e, _opt| captured = e }) do expect(dbl).not_to have_received(:expected_method) end _expect(captured.message).to match(/expected: 0 times.*received: 1 time/m) end it 'fails when the method has not been previously stubbed' do dbl = double _expect { expect(dbl).not_to have_received(:expected_method) }.to raise_error(/method has not been stubbed/) end context "with" do it 'passes when the given args do not match the args used with the message' do dbl = double_with_met_expectation(:expected_method, :expected, :args) expect(dbl).not_to have_received(:expected_method).with(:unexpected, :args) end it 'fails when the given args match the args used with the message' do dbl = double_with_met_expectation(:expected_method, :expected, :args) _expect { expect(dbl).not_to have_received(:expected_method).with(:expected, :args) }.to raise_error(/expected: 0 times.*received: 1 time/m) # TODO: better message end end %w[exactly at_least at_most times once twice].each do |constraint| it "does not allow #{constraint} to be used because it creates confusion" do dbl = double_with_unmet_expectation(:expected_method) _expect { expect(dbl).not_to have_received(:expected_method).send(constraint) }.to raise_error(/can't use #{constraint} when negative/) end end end describe "allow(...).to have_received" do it "fails because it's nonsensical" do _expect { allow(double).to have_received(:some_method) }.to fail_with("Using allow(...) with the `have_received` matcher is not supported as it would have no effect.") end end describe "allow_any_instance_of(...).to have_received" do it "fails because it's nonsensical" do _expect { allow_any_instance_of(double).to have_received(:some_method) }.to fail_with("Using allow_any_instance_of(...) with the `have_received` matcher is not supported.") end end describe "expect_any_instance_of(...).to have_received" do it "fails because we dont want to support it" do _expect { expect_any_instance_of(double).to have_received(:some_method) }.to fail_with("Using expect_any_instance_of(...) with the `have_received` matcher is not supported.") end end describe "expect_any_instance_of(...).not_to have_received" do it "fails because we dont want to support it" do _expect { expect_any_instance_of(double).not_to have_received(:some_method) }.to fail_with("Using expect_any_instance_of(...) with the `have_received` matcher is not supported.") end end def double_with_met_expectation(method_name, *args) double = double_with_unmet_expectation(method_name) meet_expectation(double, method_name, *args) end def null_object_with_met_expectation(method_name, *args) meet_expectation(double.as_null_object, method_name, *args) end def meet_expectation(double, method_name, *args) double.send(method_name, *args) double end def double_with_unmet_expectation(method_name) double('double', method_name => true) end end RSpec.describe Matchers::HaveReceived, "when used in a context that has rspec-mocks and rspec-expectations available" do include_examples Matchers::HaveReceived do # Override `fail_including` for this context, since `have_received` is a normal # rspec-expectations matcher, the error class is different. def fail_including(*snippets) raise_error(RSpec::Expectations::ExpectationNotMetError, a_string_including(*snippets)) end end end RSpec.describe Matchers::HaveReceived, "when used in a context that has only rspec-mocks available" do # We use a delegator here so that matchers can still be created # via the `RSpec::Matchers` methods. This works because we # instantiate `MocksScope` with the example group instance, so # all undefined methods (including matcher methods) forward to it. # However, `RSpec::Mocks::ExampleMethods` defines `expect` so instances # of this class use the version of `expect` defined in rspec-mocks, not # the one from rspec-expectations. class MocksScope include RSpec::Mocks::ExampleMethods def initialize(example_group) @example_group = example_group end def method_missing(*args, &block) @example_group.__send__(*args, &block) end end # Redefine `it` so that we can eval each example in a special scope # to simulate rspec-expectations not being loaded. def self.it(*args, &block) # Necessary so line-number filtering works... args << {} unless Hash === args.last args.last[:caller] = caller # delegate to the normal `it`... super(*args) do # ...but eval the block in a special scope that has `expect` # from rspec-mocks, not from rspec-expectations. MocksScope.new(self).instance_exec(&block) end end include_examples Matchers::HaveReceived end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/matchers/receive_message_chain_spec.rb0000664000000000000000000002102214557670305031641 0ustar rootrootmodule RSpec::Mocks::Matchers RSpec.describe "receive_message_chain" do let(:object) { double(:object) } context "with only the expect syntax enabled" do include_context "with syntax", :expect it "errors with a negative allowance" do expect { allow(object).not_to receive_message_chain(:to_a) }.to raise_error(RSpec::Mocks::NegationUnsupportedError) end it "errors with a negative expectation" do expect { expect(object).not_to receive_message_chain(:to_a) }.to raise_error(RSpec::Mocks::NegationUnsupportedError) end it "errors with a negative any_instance expectation" do expect { expect_any_instance_of(Object).not_to receive_message_chain(:to_a) }.to raise_error(RSpec::Mocks::NegationUnsupportedError) end it "errors with a negative any_instance allowance" do expect { allow_any_instance_of(Object).not_to receive_message_chain(:to_a) }.to raise_error(RSpec::Mocks::NegationUnsupportedError) end it "works with a do block" do allow(object).to receive_message_chain(:to_a, :length) do 3 end expect(object.to_a.length).to eq(3) end it "works with a {} block" do allow(object).to receive_message_chain(:to_a, :length) { 3 } expect(object.to_a.length).to eq(3) end it "gives the { } block precedence over the do block" do allow(object).to receive_message_chain(:to_a, :length) { 3 } do 4 end expect(object.to_a.length).to eq(3) end it "works with and_return" do allow(object).to receive_message_chain(:to_a, :length).and_return(3) expect(object.to_a.length).to eq(3) end it "works with and_invoke" do allow(object).to receive_message_chain(:to_a, :length).and_invoke(lambda { raise "error" }) expect { object.to_a.length }.to raise_error("error") end it "can constrain the return value by the argument to the last call" do allow(object).to receive_message_chain(:one, :plus).with(1) { 2 } allow(object).to receive_message_chain(:one, :plus).with(2) { 3 } expect(object.one.plus(1)).to eq(2) expect(object.one.plus(2)).to eq(3) end it "works with and_call_original", :pending => "See https://github.com/rspec/rspec-mocks/pull/467#issuecomment-28631621" do list = [1, 2, 3] expect(list).to receive_message_chain(:to_a, :length).and_call_original expect(list.to_a.length).to eq(3) end it "fails with and_call_original when the entire chain is not called", :pending => "See https://github.com/rspec/rspec-mocks/pull/467#issuecomment-28631621" do list = [1, 2, 3] expect(list).to receive_message_chain(:to_a, :length).and_call_original expect(list.to_a).to eq([1, 2, 3]) end it "works with and_raise" do allow(object).to receive_message_chain(:to_a, :length).and_raise(StandardError.new("hi")) expect { object.to_a.length }.to raise_error(StandardError, "hi") end it "works with and_throw" do allow(object).to receive_message_chain(:to_a, :length).and_throw(:nope) expect { object.to_a.length }.to throw_symbol(:nope) end it "works with and_yield" do allow(object).to receive_message_chain(:to_a, :length).and_yield(3) expect { |blk| object.to_a.length(&blk) }.to yield_with_args(3) end it "works with a string of messages to chain" do allow(object).to receive_message_chain("to_a.length").and_yield(3) expect { |blk| object.to_a.length(&blk) }.to yield_with_args(3) end it "works with a hash return as the last argument in the chain" do allow(object).to receive_message_chain(:to_a, :length => 3) expect(object.to_a.length).to eq(3) end it "accepts any number of arguments to the stubbed messages" do allow(object).to receive_message_chain(:msg1, :msg2).and_return(:return_value) expect(object.msg1("nonsense", :value).msg2("another", :nonsense, 3.0, "value")).to eq(:return_value) end it "accepts any number of arguments to the stubbed messages with an inline hash return value" do allow(object).to receive_message_chain(:msg1, :msg2 => :return_value) expect(object.msg1("nonsense", :value).msg2("another", :nonsense, 3.0, "value")).to eq(:return_value) end it "raises when expect is used and some of the messages in the chain aren't called" do expect { expect(object).to receive_message_chain(:to_a, :farce, :length => 3) object.to_a verify_all }.to fail end it "raises when expect is used and all but the last message in the chain are called" do expect { expect(object).to receive_message_chain(:foo, :bar, :baz) object.foo.bar verify_all }.to fail end it "does not raise when expect is used and the entire chain is called" do expect { expect(object).to receive_message_chain(:to_a, :length => 3) object.to_a.length verify_all }.not_to raise_error end it "works with allow_any_instance" do o = Object.new allow_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3) expect(o.to_a.length).to eq(3) end it "stubs already stubbed instances when using `allow_any_instance_of`" do o = Object.new allow(o).to receive(:foo).and_return(dbl = double) expect(o.foo).to be(dbl) allow_any_instance_of(Object).to receive_message_chain(:foo, :bar).and_return("bazz") expect(o.foo.bar).to eq("bazz") end it "fails when with expect_any_instance_of is used and the entire chain is not called" do expect { expect_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3) verify_all }.to fail end it "affects previously stubbed instances when `expect_any_instance_of` is called" do o = Object.new allow(o).to receive(:foo).and_return(double) expect_any_instance_of(Object).to receive_message_chain(:foo, :bar => 3) expect(o.foo.bar).to eq(3) end it "passes when with expect_any_instance_of is used and the entire chain is called" do o = Object.new expect_any_instance_of(Object).to receive_message_chain(:to_a, :length => 3) o.to_a.length end it "works with expect where the first level of the chain is already expected" do o = Object.new expect(o).to receive(:foo).and_return(double) expect(o).to receive_message_chain(:foo, :bar, :baz) o.foo.bar.baz end it "works with allow where the first level of the chain is already expected" do o = Object.new expect(o).to receive(:foo).and_return(double) allow(o).to receive_message_chain(:foo, :bar, :baz).and_return(3) expect(o.foo.bar.baz).to eq(3) end it "works with expect where the first level of the chain is already stubbed" do o = Object.new allow(o).to receive(:foo).and_return(double) expect(o).to receive_message_chain(:foo, :bar, :baz) o.foo.bar.baz end it "works with allow where the first level of the chain is already stubbed" do o = Object.new allow(o).to receive(:foo).and_return(double) allow(o).to receive_message_chain(:foo, :bar, :baz).and_return(3) expect(o.foo.bar.baz).to eq(3) end it "provides a matcher description (when passing a string)" do matcher = receive_message_chain("foo.bar.bazz") expect(matcher.description).to eq("receive message chain foo.bar.bazz") end it "provides a matcher description (when passing symbols)" do matcher = receive_message_chain(:foo, :bar, :bazz) expect(matcher.description).to eq("receive message chain foo.bar.bazz") end it "provides a matcher description (when passing symbols and a hash)" do matcher = receive_message_chain(:foo, :bar, :bazz => 3) expect(matcher.description).to eq("receive message chain foo.bar.bazz") end end context "when the expect and should syntaxes are enabled" do include_context "with syntax", [:expect, :should] it "stubs the message correctly" do allow(object).to receive_message_chain(:to_a, :length) expect { object.to_a.length }.not_to raise_error end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/matchers/receive_messages_spec.rb0000664000000000000000000001261014557670305030665 0ustar rootrootmodule RSpec module Mocks RSpec.shared_examples "complains when given blocks" do it "complains if a { } block is given" do expect { target.to receive_messages(:a => 1) { "implementation" } }.to raise_error "Implementation blocks aren't supported with `receive_messages`" end it "complains if a do; end; block is given" do expect { target.to receive_messages(:a => 1) do "implementation" end }.to raise_error "Implementation blocks aren't supported with `receive_messages`" end end RSpec.shared_examples "handles partially mocked objects correctly" do let(:obj) { Struct.new(:a).new('original') } it "resets partially mocked objects correctly" do target.to receive_messages(:a => 1, :b => 2) expect { reset obj }.to change { obj.a }.from(1).to("original") end end RSpec.describe "allow(...).to receive_messages(:a => 1, :b => 2)" do let(:obj) { double "Object" } let(:target) { allow(obj) } it "allows the object to respond to multiple messages" do allow(obj).to receive_messages(:a => 1, :b => 2) expect(obj.a).to eq 1 expect(obj.b).to eq 2 end it_behaves_like "complains when given blocks" it_behaves_like "handles partially mocked objects correctly" end RSpec.describe "allow_any_instance_of(...).to receive_messages(:a => 1, :b => 2)" do let(:obj) { Object.new } let(:target) { allow_any_instance_of(Object) } it "allows the object to respond to multiple messages" do allow_any_instance_of(Object).to receive_messages(:a => 1, :b => 2) expect(obj.a).to eq 1 expect(obj.b).to eq 2 end it "updates stubs on instances with existing stubs" do allow(obj).to receive(:a).and_return(3) expect(obj.a).to eq(3) allow_any_instance_of(Object).to receive_messages(:a => 1, :b => 2) expect(obj.a).to eq 1 expect(obj.b).to eq 2 end it_behaves_like "complains when given blocks" end RSpec.describe "expect(...).to receive_messages(:a => 1, :b => 2)" do let(:obj) { double "Object" } let(:target) { expect(obj) } let(:expectation_error) do failure = nil begin verify_all rescue RSpec::Mocks::MockExpectationError => error failure = error end failure end it "sets up multiple expectations" do expect(obj).to receive_messages(:a => 1, :b => 2) obj.a expect { verify_all }.to fail end it 'fails with a sensible message' do expect(obj).to receive_messages(:a => 1, :b => 2) obj.b expect(expectation_error.to_s).to eq %Q{(Double "Object").a(no args)\n expected: 1 time with any arguments\n received: 0 times} end it 'fails with the correct location' do expect(obj).to receive_messages(:a => 1, :b => 2); line = __LINE__ expect(expectation_error.backtrace[0]).to match(/#{__FILE__}:#{line}/) end it_behaves_like "complains when given blocks" it_behaves_like "handles partially mocked objects correctly" it "provides a matcher description" do messages = { :a => 1, :b => 2 } matcher = receive_messages(messages) expect(matcher.description).to eq("receive messages: #{messages.inspect}") end end RSpec.describe "expect_any_instance_of(...).to receive_messages(:a => 1, :b => 2)" do let(:obj) { Object.new } let(:target) { expect_any_instance_of(Object) } it "sets up multiple expectations" do expect_any_instance_of(Object).to receive_messages(:a => 1, :b => 2) obj.a expect { RSpec::Mocks.space.verify_all }.to fail RSpec::Mocks.space.reset_all end it_behaves_like "complains when given blocks" end RSpec.describe "negative expectation failure" do let(:obj) { Object.new } example "allow(...).to_not receive_messages(:a => 1, :b => 2)" do expect { allow(obj).to_not receive_messages(:a => 1, :b => 2) }.to( raise_error "`allow(...).to_not receive_messages` is not supported " \ "since it doesn't really make sense. What would it even mean?" ) end example "allow_any_instance_of(...).to_not receive_messages(:a => 1, :b => 2)" do expect { allow_any_instance_of(obj).to_not receive_messages(:a => 1, :b => 2) }.to( raise_error "`allow_any_instance_of(...).to_not receive_messages` is not supported " \ "since it doesn't really make sense. What would it even mean?" ) end example "expect(...).to_not receive_messages(:a => 1, :b => 2)" do expect { expect(obj).to_not receive_messages(:a => 1, :b => 2) }.to( raise_error "`expect(...).to_not receive_messages` is not supported " \ "since it doesn't really make sense. What would it even mean?" ) end example "expect_any_instance_of(...).to_not receive_messages(:a => 1, :b => 2)" do expect { expect_any_instance_of(obj).to_not receive_messages(:a => 1, :b => 2) }.to( raise_error "`expect_any_instance_of(...).to_not receive_messages` is not supported " \ "since it doesn't really make sense. What would it even mean?" ) end end end end ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/partial_double_using_mocks_directly_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/partial_double_using_mocks_directly_spec0000664000000000000000000000474714557670305032446 0ustar rootrootmodule RSpec::Mocks RSpec.describe "PartialDoubleUsingMocksDirectly" do let(:klass) do Class.new do module MethodMissing remove_method :method_missing rescue nil def method_missing(m, *a, &b) if m == :captured_by_method_missing "response generated by method missing" else super(m, *a, &b) end end end extend MethodMissing include MethodMissing def existing_method :original_value end end end let(:obj) { klass.new } it "fails when expected message is not received" do expect(obj).to receive(:msg) expect { verify obj }.to fail end it "fails when message is received with incorrect args" do expect(obj).to receive(:msg).with(:correct_arg) expect { obj.msg(:incorrect_arg) }.to fail obj.msg(:correct_arg) end it "passes when expected message is received" do expect(obj).to receive(:msg) obj.msg verify obj end it "passes when message is received with correct args" do expect(obj).to receive(:msg).with(:correct_arg) obj.msg(:correct_arg) verify obj end it "restores the original method if it existed" do expect(obj.existing_method).to equal(:original_value) expect(obj).to receive(:existing_method).and_return(:mock_value) expect(obj.existing_method).to equal(:mock_value) verify obj expect(obj.existing_method).to equal(:original_value) end context "with an instance method handled by method_missing" do it "restores the original behavior" do expect(obj.captured_by_method_missing).to eq("response generated by method missing") allow(obj).to receive(:captured_by_method_missing) { "foo" } expect(obj.captured_by_method_missing).to eq("foo") reset obj expect(obj.captured_by_method_missing).to eq("response generated by method missing") end end context "with a class method handled by method_missing" do it "restores the original behavior" do expect(klass.captured_by_method_missing).to eq("response generated by method missing") allow(klass).to receive(:captured_by_method_missing) { "foo" } expect(klass.captured_by_method_missing).to eq("foo") reset klass expect(klass.captured_by_method_missing).to eq("response generated by method missing") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/precise_counts_spec.rb0000664000000000000000000000402414557670305026573 0ustar rootrootmodule RSpec module Mocks RSpec.describe "PreciseCounts" do before(:each) do @double = double("test double") end it "fails when exactly n times method is called less than n times" do expect(@double).to receive(:do_something).exactly(3).times @double.do_something @double.do_something expect { verify @double }.to fail end it "fails fast when exactly n times method is called more than n times" do expect(@double).to receive(:do_something).exactly(3).times @double.do_something @double.do_something @double.do_something expect_fast_failure_from(@double) do @double.do_something end end it "fails when exactly n times method is never called" do expect(@double).to receive(:do_something).exactly(3).times expect { verify @double }.to fail end it "passes if exactly n times method is called exactly n times" do expect(@double).to receive(:do_something).exactly(3).times @double.do_something @double.do_something @double.do_something verify @double end it "returns the value given by a block when the exactly once method is called" do expect(@double).to receive(:to_s).exactly(:once) { "testing" } expect(@double.to_s).to eq "testing" verify @double end it "passes multiple calls with different args" do expect(@double).to receive(:do_something).once.with(1) expect(@double).to receive(:do_something).once.with(2) @double.do_something(1) @double.do_something(2) verify @double end it "passes multiple calls with different args and counts" do expect(@double).to receive(:do_something).twice.with(1) expect(@double).to receive(:do_something).once.with(2) @double.do_something(1) @double.do_something(2) @double.do_something(1) verify @double end end end end ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/message_expectation_string_representation_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/message_expectation_string_representatio0000664000000000000000000000260414557670305032515 0ustar rootrootmodule RSpec module Mocks RSpec.describe MessageExpectation, "has a nice string representation" do let(:test_double) { double } example "for a raw message expectation on a test double" do expect(allow(test_double).to receive(:foo)).to have_string_representation( "#.foo(any arguments)>" ) end example "for a raw message expectation on a partial double" do expect(allow("partial double".dup).to receive(:foo)).to have_string_representation( '#' ) end example "for a message expectation constrained by `with`" do expect(allow(test_double).to receive(:foo).with(1, a_kind_of(String), any_args)).to have_string_representation( "#.foo(1, a kind of String, *(any args))>" ) end RSpec::Matchers.define :have_string_representation do |expected_representation| match do |object| values_match?(expected_representation, object.to_s) && object.to_s == object.inspect end failure_message do |object| "expected string representation: #{expected_representation}\n" \ " but got string representation: #{object.to_s}" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/and_call_original_spec.rb0000664000000000000000000003142314557670305027172 0ustar rootrootrequire 'delegate' RSpec.describe "and_call_original" do context "on a partial double" do let(:klass) do Class.new do def meth_1 :original end def meth_2(x) yield x, :additional_yielded_arg end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) def meth_3(**kwargs) kwargs end def meth_4(x: 1) x end RUBY end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) def meth_5(x:) x end RUBY end def self.new_instance new end end end let(:instance) { klass.new } context "when a method that exists has been stubbed previously" do before { allow(instance).to receive(:meth_1).and_return(:override) } it 'restores the original behavior' do expect { allow(instance).to receive(:meth_1).and_call_original }.to change(instance, :meth_1).from(:override).to(:original) end end context "when a non-existent method has been stubbed previously" do it 'restores the original NameError behavior' do expect { instance.abcd }.to raise_error(NameError).with_message(/abcd/) allow(instance).to receive(:abcd).and_return(:override) expect(instance.abcd).to eq(:override) allow(instance).to receive(:abcd).and_call_original expect { instance.abcd }.to raise_error(NameError).with_message(/abcd/) end end it 'passes the received message through to the original method' do expect(instance).to receive(:meth_1).and_call_original expect(instance.meth_1).to eq(:original) end it 'ignores prior declared stubs' do allow(instance).to receive(:meth_1).and_return(:stubbed_value) expect(instance).to receive(:meth_1).and_call_original expect(instance.meth_1).to eq(:original) end it 'passes args and blocks through to the original method' do expect(instance).to receive(:meth_2).and_call_original value = instance.meth_2(:submitted_arg) { |a, b| [a, b] } expect(value).to eq([:submitted_arg, :additional_yielded_arg]) end it 'errors when you pass through the wrong number of args' do expect(instance).to receive(:meth_1).and_call_original expect(instance).to receive(:meth_2).twice.and_call_original expect { instance.meth_1 :a }.to raise_error ArgumentError expect { instance.meth_2 {} }.to raise_error ArgumentError expect { instance.meth_2(:a, :b) {} }.to raise_error ArgumentError end it 'warns when you override an existing implementation' do expect(RSpec).to receive(:warning).with(/overriding a previous stub implementation of `meth_1`.*#{__FILE__}:#{__LINE__ + 1}/) expect(instance).to receive(:meth_1) { true }.and_call_original instance.meth_1 end context "for singleton methods" do it 'works' do def instance.foo; :bar; end expect(instance).to receive(:foo).and_call_original expect(instance.foo).to eq(:bar) end it 'works for SimpleDelegator subclasses', :if => (RUBY_VERSION.to_f > 1.8) do inst = Class.new(SimpleDelegator).new(1) def inst.foo; :bar; end expect(inst).to receive(:foo).and_call_original expect(inst.foo).to eq(:bar) end end it 'works for methods added through an extended module' do instance.extend Module.new { def foo; :bar; end } expect(instance).to receive(:foo).and_call_original expect(instance.foo).to eq(:bar) end it "works for method added through an extended module onto a class's ancestor" do sub_sub_klass = Class.new(Class.new(klass)) klass.extend Module.new { def foo; :bar; end } expect(sub_sub_klass).to receive(:foo).and_call_original expect(sub_sub_klass.foo).to eq(:bar) end it "finds the method on the most direct ancestor even if the method " \ "is available on more distant ancestors" do klass.extend Module.new { def foo; :klass_bar; end } sub_klass = Class.new(klass) sub_klass.extend Module.new { def foo; :sub_klass_bar; end } expect(sub_klass).to receive(:foo).and_call_original expect(sub_klass.foo).to eq(:sub_klass_bar) end it "finds the method on the most direct singleton class ancestors even if the method " \ "is available on more distant ancestors" do klass.extend Module.new { def foo; :klass_bar; end } sub_klass = Class.new(klass) { def self.foo; :sub_klass_bar; end } sub_sub_klass = Class.new(sub_klass) expect(sub_sub_klass).to receive(:foo).and_call_original expect(sub_sub_klass.foo).to eq(:sub_klass_bar) end context 'when using any_instance' do it 'works for instance methods defined on the class' do expect_any_instance_of(klass).to receive(:meth_1).and_call_original expect(klass.new.meth_1).to eq(:original) end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) it 'works for instance methods that use double splat' do expect_any_instance_of(klass).to receive(:meth_3).and_call_original expect(klass.new.meth_3(x: :kwarg)).to eq({x: :kwarg}) end it 'works for instance methods that use optional keyword arguments' do expect_any_instance_of(klass).to receive(:meth_4).and_call_original expect(klass.new.meth_4).to eq(1) end it 'works for instance methods that use optional keyword arguments with an argument supplied' do expect_any_instance_of(klass).to receive(:meth_4).and_call_original expect(klass.new.meth_4(x: :kwarg)).to eq(:kwarg) end RUBY end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) it 'works for instance methods that use required keyword arguments' do expect_any_instance_of(klass).to receive(:meth_5).and_call_original expect(klass.new.meth_5(x: :kwarg)).to eq(:kwarg) end RUBY end it 'works for instance methods defined on the superclass of the class' do subclass = Class.new(klass) expect_any_instance_of(subclass).to receive(:meth_1).and_call_original expect(subclass.new.meth_1).to eq(:original) end it 'works when mocking the method on one class and calling the method on an instance of a subclass' do expect_any_instance_of(klass).to receive(:meth_1).and_call_original expect(Class.new(klass).new.meth_1).to eq(:original) end end it 'works for class methods defined on a superclass' do subclass = Class.new(klass) expect(subclass).to receive(:new_instance).and_call_original expect(subclass.new_instance).to be_a(subclass) end context 'when a class method is stubbed in the superclass' do it 'still works for class methods defined on a superclass' do superclass = Class.new { def self.foo; "foo"; end } subclass = Class.new(superclass) allow(superclass).to receive(:foo).and_return(:fake) expect(subclass).to receive(:foo).and_call_original expect(superclass.foo).to be :fake expect(subclass.foo).to eq "foo" end end it 'works for class methods defined on a grandparent class' do sub_subclass = Class.new(Class.new(klass)) expect(sub_subclass).to receive(:new_instance).and_call_original expect(sub_subclass.new_instance).to be_a(sub_subclass) end it 'works for class methods defined on the Class class' do expect(klass).to receive(:new).and_call_original expect(klass.new).to be_an_instance_of(klass) end it "works for instance methods defined on the object's class's superclass" do subclass = Class.new(klass) inst = subclass.new expect(inst).to receive(:meth_1).and_call_original expect(inst.meth_1).to eq(:original) end it 'works for aliased methods' do klazz = Class.new do class << self alias alternate_new new end end expect(klazz).to receive(:alternate_new).and_call_original expect(klazz.alternate_new).to be_an_instance_of(klazz) end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it "works for methods that accept keyword arguments" do def instance.foo(bar: nil); bar; end expect(instance).to receive(:foo).and_call_original expect(instance.foo(bar: "baz")).to eq("baz") end CODE end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-RUBY, __FILE__, __LINE__) context 'on an object with a method propagated by method_missing' do before do klass.class_exec do private def call_method_with_kwarg(arg, kwarg:) [arg, kwarg] end def method_missing(name, *args, **kwargs) if name.to_s == "method_with_kwarg" call_method_with_kwarg(*args, **kwargs) else super end end end end it 'works for the method propagated by method missing' do expect(instance).to receive(:method_with_kwarg).with(:arg, kwarg: 1).and_call_original expect(instance.method_with_kwarg(:arg, kwarg: 1)).to eq([:arg, 1]) end it 'works for the method of any_instance mock propagated by method missing' do expect_any_instance_of(klass).to receive(:method_with_kwarg).with(:arg, kwarg: 1).and_call_original expect(instance.method_with_kwarg(:arg, kwarg: 1)).to eq([:arg, 1]) end end RUBY end context 'on an object that defines method_missing' do before do klass.class_exec do private def method_missing(name, *args) if name.to_s == "greet_jack" "Hello, jack" else super end end end end it 'works when the method_missing definition handles the message' do expect(instance).to receive(:greet_jack).and_call_original expect(instance.greet_jack).to eq("Hello, jack") end it 'works for an any_instance partial mock' do expect_any_instance_of(klass).to receive(:greet_jack).and_call_original expect(instance.greet_jack).to eq("Hello, jack") end it 'raises an error for an unhandled message for an any_instance partial mock' do expect_any_instance_of(klass).to receive(:not_a_handled_message).and_call_original expect { instance.not_a_handled_message }.to raise_error(NameError, /not_a_handled_message/) end it 'raises an error on invocation if method_missing does not handle the message' do expect(instance).to receive(:not_a_handled_message).and_call_original # Note: it should raise a NoMethodError (and usually does), but # due to a weird rspec-expectations issue (see #183) it sometimes # raises a `NameError` when a `be_xxx` predicate matcher has been # recently used. `NameError` is the superclass of `NoMethodError` # so this example will pass regardless. # If/when we solve the rspec-expectations issue, this can (and should) # be changed to `NoMethodError`. expect { instance.not_a_handled_message }.to raise_error(NameError, /not_a_handled_message/) end end end context "on a partial double that overrides #method" do let(:request_klass) do Struct.new(:method, :url) do def perform :the_response end def self.method :some_method end end end let(:request) { request_klass.new(:get, "http://foo.com/bar") } it 'still works even though #method has been overridden' do expect(request).to receive(:perform).and_call_original expect(request.perform).to eq(:the_response) end it 'works for a singleton method' do def request.perform :a_response end expect(request).to receive(:perform).and_call_original expect(request.perform).to eq(:a_response) end end context "on a pure test double" do let(:instance) { double } it 'raises an error even if the double object responds to the message' do expect(instance.to_s).to be_a(String) mock_expectation = expect(instance).to receive(:to_s) instance.to_s # to satisfy the expectation expect { mock_expectation.and_call_original }.to raise_error(/pure test double.*and_call_original.*partial double/i) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/space_spec.rb0000664000000000000000000002017414557670305024645 0ustar rootroot module RSpec::Mocks RSpec.describe Space do let(:space) { Space.new } let(:dbl_1) { Object.new } let(:dbl_2) { Object.new } describe "#verify_all" do it "verifies all mocks within" do verifies = [] allow(space.proxy_for(dbl_1)).to receive(:verify) { verifies << :dbl_1 } allow(space.proxy_for(dbl_2)).to receive(:verify) { verifies << :dbl_2 } space.verify_all expect(verifies).to match_array([:dbl_1, :dbl_2]) end def define_singleton_method_on_recorder_for(klass, name, &block) recorder = space.any_instance_recorder_for(klass) (class << recorder; self; end).send(:define_method, name, &block) end it 'verifies all any_instance recorders within' do klass_1, klass_2 = Class.new, Class.new verifies = [] # We can't `stub` a method on the recorder because it defines its own `stub`... define_singleton_method_on_recorder_for(klass_1, :verify) { verifies << :klass_1 } define_singleton_method_on_recorder_for(klass_2, :verify) { verifies << :klass_2 } space.verify_all expect(verifies).to match_array([:klass_1, :klass_2]) end it 'does not reset the proxies (as that should be delayed until reset_all)' do proxy = space.proxy_for(dbl_1) reset = false (class << proxy; self; end).__send__(:define_method, :reset) { reset = true } space.verify_all expect(reset).to eq(false) end end describe "#reset_all" do it "resets all mocks within" do resets = [] allow(space.proxy_for(dbl_1)).to receive(:reset) { resets << :dbl_1 } allow(space.proxy_for(dbl_2)).to receive(:reset) { resets << :dbl_2 } space.reset_all expect(resets).to match_array([:dbl_1, :dbl_2]) end it "allows Array#reverse to be stubbed" do # This is a regression check solved in rspec/rspec-mocks#1533 previously # this was not possible without a change to the implementation expect_any_instance_of(Array).to_not receive(:reverse) end end describe "#proxies_of(klass)" do it 'returns proxies' do space.proxy_for("") expect(space.proxies_of(String).map(&:class)).to eq([PartialDoubleProxy]) end def create_generations grandparent_class = Class.new parent_class = Class.new(grandparent_class) child_class = Class.new(parent_class) grandparent = grandparent_class.new parent = parent_class.new child = child_class.new return grandparent, parent, child end it 'returns only the proxies whose object is an instance of the given class' do grandparent, parent, child = create_generations space.proxy_for(grandparent) parent_proxy = space.proxy_for(parent) child_proxy = space.proxy_for(child) expect(space.proxies_of(parent.class)).to contain_exactly(parent_proxy, child_proxy) end it 'looks in the parent space for matching proxies' do _, parent, child = create_generations parent_proxy = space.proxy_for(parent) subspace = space.new_scope child_proxy = subspace.proxy_for(child) expect(subspace.proxies_of(parent.class)).to contain_exactly(parent_proxy, child_proxy) end end it 'tracks proxies in parent and child space separately' do proxy1 = space.proxy_for(Object.new) subspace = space.new_scope proxy2 = subspace.proxy_for(Object.new) expect(space.proxies.values).to include(proxy1) expect(space.proxies.values).not_to include(proxy2) expect(subspace.proxies.values).to include(proxy2) expect(subspace.proxies.values).not_to include(proxy1) end it "only adds an instance once" do m1 = double("mock1") expect { space.ensure_registered(m1) }.to change { space.proxies } expect { space.ensure_registered(m1) }.not_to change { space.proxies } end [:ensure_registered, :proxy_for].each do |method| describe "##{method}" do define_method :get_proxy do |the_space, object| the_space.__send__(method, object) end it 'returns the proxy for the given object' do obj1 = Object.new obj2 = Object.new expect(get_proxy(space, obj1)).to equal(get_proxy(space, obj1)) expect(get_proxy(space, obj2)).to equal(get_proxy(space, obj2)) expect(get_proxy(space, obj1)).not_to equal(get_proxy(space, obj2)) end it 'can still return a proxy from a parent context' do proxy = get_proxy(space, Object) subspace = space.new_scope expect(get_proxy(subspace, Object)).to equal(proxy) end it "does not store a parent's proxy in the child space" do get_proxy(space, Object) subspace = space.new_scope expect { get_proxy(subspace, Object) }.not_to change { subspace.proxies }.from({}) end end end describe "#registered?" do it 'returns true if registered in this space' do space.ensure_registered(Object) expect(space).to be_registered(Object) end it 'returns true if registered in a parent space' do space.ensure_registered(Object) expect(space.new_scope).to be_registered(Object) end it 'returns false if not registered in this or a parent space' do expect(space.new_scope).not_to be_registered(Object) end end describe "#constant_mutator_for" do it 'returns the mutator for the given const name' do the_space = RSpec::Mocks.space stub_const("Foo", 3) stub_const("Bar", 4) expect(the_space.constant_mutator_for("Foo")).to equal(the_space.constant_mutator_for("Foo")) expect(the_space.constant_mutator_for("Bar")).to equal(the_space.constant_mutator_for("Bar")) expect(the_space.constant_mutator_for("Foo")).not_to equal(the_space.constant_mutator_for("Bar")) end it 'can still return a mutator from a parent context' do the_space = RSpec::Mocks.space stub_const("Foo", 3) mutator = the_space.constant_mutator_for("Foo") in_new_space_scope do subspace = RSpec::Mocks.space expect(subspace.constant_mutator_for("Foo")).to equal(mutator) end end end describe "#any_instance_recorder_for" do it 'returns the recorder for the given class' do expect(space.any_instance_recorder_for(String)).to equal(space.any_instance_recorder_for(String)) expect(space.any_instance_recorder_for(Symbol)).to equal(space.any_instance_recorder_for(Symbol)) expect(space.any_instance_recorder_for(String)).not_to equal(space.any_instance_recorder_for(Symbol)) end it 'can still return a recorder from a parent context' do recorder = space.any_instance_recorder_for(String) subspace = space.new_scope expect(subspace.any_instance_recorder_for(String)).to equal(recorder) end it "does not store a parent's proxy in the child space" do space.any_instance_recorder_for(String) subspace = space.new_scope expect { subspace.any_instance_recorder_for(String) }.not_to change { subspace.any_instance_recorders }.from({}) end end it 'can be diffed in a failure when it has references to an error generator via a proxy' do space1 = Space.new space2 = Space.new space1.proxy_for("") space2.proxy_for("") expect { expect(space1).to eq(space2) }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /Diff/) end it 'raises ArgumentError with message if object is symbol' do space1 = Space.new object = :subject expected_message = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed." expect { space1.proxy_for(object) }.to raise_error(ArgumentError, expected_message) end def in_new_space_scope RSpec::Mocks.setup yield ensure RSpec::Mocks.teardown end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/failure_notification_spec.rb0000664000000000000000000000501614557670305027745 0ustar rootrootRSpec.describe "Failure notification" do def capture_errors(&block) errors = [] RSpec::Support.with_failure_notifier(Proc.new { |e, _opts| errors << e }, &block) errors end it "uses the rspec-support notifier to support `aggregate_failures`" do dbl = double("Foo") expect(capture_errors { dbl.some_unallowed_method }).to match [an_object_having_attributes( :message => a_string_including(dbl.inspect, "some_unallowed_method") )] end it "includes the line of future expectation in the notification for an unreceived message" do dbl = double("Foo") expect(dbl).to receive(:wont_happen); expected_from_line = __LINE__ error = capture_errors { verify dbl }.first expect(error.backtrace.first).to match(/#{File.basename(__FILE__)}:#{expected_from_line}/) end it "does not allow a double to miscount the number of times a message was received when a failure is notified in an alternate way" do dbl = double("Foo") expect(dbl).not_to receive(:bar) capture_errors { dbl.bar } expect { verify dbl }.to fail_including("expected: 0 times", "received: 1 time") end context "when using `aggregate_failures`" do specify 'spy failures for unreceived messages are reported correctly' do expect { aggregate_failures do expect(spy).to have_received(:foo) end }.to raise_error(RSpec::Expectations::ExpectationNotMetError) do |e| expect(e).not_to be_a(RSpec::Expectations::MultipleExpectationsNotMetError) expect(e.message).to include("expected: 1 time", "received: 0 times") end end specify 'spy failures for messages received with unexpected args are reported correctly' do expect { aggregate_failures do the_spy = spy the_spy.foo(1) expect(the_spy).to have_received(:foo).with(2) end }.to raise_error(RSpec::Expectations::ExpectationNotMetError) do |e| expect(e).not_to be_a(RSpec::Expectations::MultipleExpectationsNotMetError) expect(e.message).to include("expected: (2)", "got: (1)") end end specify "failing negative expectations are only notified once" do expect { aggregate_failures do dbl = double expect(dbl).not_to receive(:foo) expect(dbl).not_to receive(:bar) dbl.foo dbl.bar verify_all end }.to raise_error(RSpec::Expectations::MultipleExpectationsNotMetError) do |e| expect(e.failures.count).to eq(2) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/partial_double_spec.rb0000664000000000000000000005146514557670305026547 0ustar rootrootmodule RSpec module Mocks RSpec.describe "A partial double" do let(:object) { Object.new } it 'does not create an any_instance recorder when a message is allowed' do expect { allow(object).to receive(:foo) }.not_to change { RSpec::Mocks.space.any_instance_recorders }.from({}) end it "names the class in the failure message" do expect(object).to receive(:foo) expect do verify object end.to fail_with(/\(#\).foo/) end it "names the class in the failure message when expectation is on class" do expect(Object).to receive(:foo) expect { verify Object }.to fail_with(/Object \(class\)/) end it "does not conflict with @options in the object" do object.instance_exec { @options = Object.new } expect(object).to receive(:blah) object.blah end it 'allows `class` to be stubbed even when `any_instance` has already been used' do # See https://github.com/rspec/rspec-mocks/issues/687 # The infinite recursion code path was only triggered when there were # active any instance recorders in the current example, so we make one here. allow_any_instance_of(Object).to receive(:bar).and_return(2) expect(object.class).not_to eq(String) allow(object).to receive_messages(:foo => 1, :class => String) expect(object.foo).to eq(1) expect(object.class).to eq(String) expect(object.bar).to eq(2) end it 'allows `respond_to?` to be stubbed' do the_klass = Class.new do def call(name) if respond_to?(name) send(name) end end end an_object = the_klass.new expect(an_object).to receive(:respond_to?). with(:my_method).at_least(:once) { true } expect(an_object).to receive(:my_method) an_object.call :my_method end it "can disallow messages from being received" do expect(object).not_to receive(:fuhbar) expect_fast_failure_from( object, /expected\: 0 times with any arguments\n received\: 1 time/ ) do object.fuhbar end end it "can expect a message and set a return value" do expect(object).to receive(:foobar).with(:test_param).and_return(1) expect(object.foobar(:test_param)).to equal(1) end it "can accept a hash as a message argument" do expect(object).to receive(:foobar).with(:key => "value").and_return(1) expect(object.foobar(:key => "value")).to equal(1) end if RSpec::Support::RubyFeatures.required_kw_args_supported? # Use eval to avoid syntax error on 1.8 and 1.9 binding.eval(<<-CODE, __FILE__, __LINE__) it "can accept an inner hash as a message argument" do hash = {:a => {:key => "value"}} expect(object).to receive(:foobar).with(:key => "value").and_return(1) expect(object.foobar(**hash[:a])).to equal(1) end CODE end it "can create a positive message expectation" do expect(expect(object).to receive(:foobar)).not_to be_negative object.foobar end it 'allows a class and a subclass to both be stubbed' do pending "Does not work on 1.8.7 due to singleton method restrictions" if RUBY_VERSION == "1.8.7" && RSpec::Support::Ruby.mri? the_klass = Class.new the_subklass = Class.new(the_klass) allow(the_klass).to receive(:foo).and_return(1) allow(the_subklass).to receive(:foo).and_return(2) expect(the_klass.foo).to eq(1) expect(the_subklass.foo).to eq(2) end it "verifies the method was called when expecting a message" do expect(object).to receive(:foobar).with(:test_param).and_return(1) expect { verify object }.to fail end it "can accept the string form of a message for a positive message expectation" do expect(object).to receive('foobar') object.foobar end it "can accept the string form of a message for a negative message expectation" do expect(object).not_to receive('foobar') expect_fast_failure_from(object) do object.foobar end end it "uses reports nil in the error message" do allow_message_expectations_on_nil nil_var = nil expect(nil_var).to receive(:foobar) expect { verify nil_var }.to raise_error( RSpec::Mocks::MockExpectationError, %Q|(nil).foobar(*(any args))\n expected: 1 time with any arguments\n received: 0 times with any arguments| ) end it "includes the class name in the error when mocking a class method that is called an extra time with the wrong args" do klazz = Class.new do def self.inspect "MyClass" end end expect(klazz).to receive(:bar).with(1) klazz.bar(1) expect { klazz.bar(2) }.to fail_with(/MyClass/) end it "shares message expectations with clone" do expect(object).to receive(:foobar) twin = object.clone twin.foobar expect { verify twin }.not_to raise_error expect { verify object }.not_to raise_error end it "clears message expectations when `dup`ed" do expect(object).to receive(:foobar) duplicate = object.dup expect { duplicate.foobar }.to raise_error(NoMethodError, /foobar/) expect { verify object }.to fail_with(/foobar/) end end RSpec.describe "Using a reopened file object as a partial mock" do let(:file_1) { File.open(File.join("tmp", "file_1"), "w").tap { |f| f.sync = true } } let(:file_2) { File.open(File.join("tmp", "file_2"), "w").tap { |f| f.sync = true } } def read_file(file) File.open(file.path, "r", &:read) end after do file_1.close file_2.close end def expect_output_warning_on_ruby_lt_2 if RUBY_VERSION >= '2.0' yield else expect { yield }.to output(a_string_including( "RSpec could not fully restore", file_1.inspect, "write" )).to_stderr end end it "allows `write` to be stubbed and reset", :unless => Support::Ruby.jruby? do allow(file_1).to receive(:write) file_1.reopen(file_2) expect_output_warning_on_ruby_lt_2 { reset file_1 } expect { # Writing to a file that's been reopened to a 2nd file writes to both files. file_1.write("foo") }.to change { read_file(file_1) }.from("").to("foo"). and change { read_file(file_2) }.from("").to("foo") end end RSpec.describe "Using a partial mock on a proxy object", :if => defined?(::BasicObject) do let(:proxy_class) do Class.new(::BasicObject) do def initialize(target) @target = target end def proxied? true end def respond_to?(name, include_all=false) super || name == :proxied? || @target.respond_to?(name, include_all) end def method_missing(*a) @target.send(*a) end end end let(:wrapped_object) { Object.new } let(:proxy) { proxy_class.new(wrapped_object) } it 'works properly' do expect(proxy).to receive(:proxied?).and_return(false) expect(proxy).not_to be_proxied end it 'does not confuse the proxy and the proxied object' do allow(proxy).to receive(:foo).and_return(:proxy_foo) allow(wrapped_object).to receive(:foo).and_return(:wrapped_foo) expect(proxy.foo).to eq(:proxy_foo) expect(wrapped_object.foo).to eq(:wrapped_foo) end end RSpec.describe "Partially mocking an object that defines ==, after another mock has been defined" do before(:each) do double("existing mock", :foo => :foo) end let(:klass) do Class.new do attr_reader :val def initialize(val) @val = val end def ==(other) @val == other.val end end end it "does not raise an error when stubbing the object" do o = klass.new :foo expect { allow(o).to receive(:bar) }.not_to raise_error end end RSpec.describe "A partial class mock that has been subclassed" do let(:klass) { Class.new } let(:subklass) { Class.new(klass) } it "cleans up stubs during #reset to prevent leakage onto subclasses between examples" do allow(klass).to receive(:new).and_return(:new_foo) expect(subklass.new).to eq :new_foo reset(klass) expect(subklass.new).to be_a(subklass) end describe "stubbing a base class class method" do before do allow(klass).to receive(:find).and_return "stubbed_value" end it "returns the value for the stub on the base class" do expect(klass.find).to eq "stubbed_value" end it "returns the value for the descendent class" do expect(subklass.find).to eq "stubbed_value" end end end RSpec.describe "Method visibility when using partial mocks" do let(:klass) do Class.new do def public_method private_method protected_method end protected def protected_method; end private def private_method; end end end let(:object) { klass.new } it 'keeps public methods public' do expect(object).to receive(:public_method) expect(object.public_methods).to include_method(:public_method) object.public_method end it 'keeps private methods private' do expect(object).to receive(:private_method) expect(object.private_methods).to include_method(:private_method) object.public_method end it 'keeps protected methods protected' do expect(object).to receive(:protected_method) expect(object.protected_methods).to include_method(:protected_method) object.public_method end end RSpec.describe 'when verify_partial_doubles configuration option is set' do include_context "with isolated configuration" let(:klass) do Class.new do def implemented "works" end def initialize(_a, _b) end def respond_to?(method_name, include_all=false) method_name.to_s == "dynamic_method" || super end def method_missing(method_name, *args) if respond_to?(method_name) method_name else super end end private def defined_private_method "works" end end end let(:object) { klass.new(1, 2) } before do RSpec::Mocks.configuration.verify_partial_doubles = true end it 'allows valid methods to be expected' do expect(object).to receive(:implemented).and_call_original expect(object.implemented).to eq("works") end it 'allows private methods to be expected' do expect(object).to receive(:defined_private_method).and_call_original expect(object.send(:defined_private_method)).to eq("works") end it 'can be temporarily supressed' do without_partial_double_verification do expect(object).to receive(:fictitious_method) { 'works' } expect_any_instance_of(klass).to receive(:other_fictitious_method) { 'works' } end expect(object.fictitious_method).to eq 'works' expect(object.other_fictitious_method).to eq 'works' expect { expect(object).to receive(:another_fictitious_method) { 'works' } }.to raise_error RSpec::Mocks::MockExpectationError end it 'can be temporarily supressed and nested' do without_partial_double_verification do without_partial_double_verification do expect(object).to receive(:fictitious_method) { 'works' } end expect(object).to receive(:other_fictitious_method) { 'works' } end expect(object.fictitious_method).to eq 'works' expect(object.other_fictitious_method).to eq 'works' expect { expect(object).to receive(:another_fictitious_method) { 'works' } }.to raise_error RSpec::Mocks::MockExpectationError end specify 'temporarily supressing partial doubles does not affect normal verifying doubles' do without_partial_double_verification do expect { instance_double(Class.new, :fictitious_method => 'works') }.to raise_error RSpec::Mocks::MockExpectationError end end it 'runs the before_verifying_double callbacks before verifying an expectation' do expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles(&probe) end expect(object).to receive(:implemented) }.to yield_with_args(have_attributes :target => object) object.implemented end it 'runs the before_verifying_double callbacks before verifying an allowance' do expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles(&probe) end allow(object).to receive(:implemented) }.to yield_with_args(have_attributes :target => object) object.implemented end it 'avoids deadlocks when a proxy is accessed from within a `before_verifying_doubles` callback' do msg_klass = Class.new { def message; end; } called_for = [] RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles do |ref| unless called_for.include? ref.target called_for << ref.target ::RSpec::Mocks.space.proxy_for(ref.target) end end end expect { allow(msg_klass.new).to receive(:message) }.to_not raise_error end context "for a class" do let(:subclass) { Class.new(klass) } it "only runs the `before_verifying_doubles` callback for the class (not for superclasses)" do expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles(&probe) end allow(subclass).to receive(:new) }.to yield_successive_args( an_object_having_attributes(:target => subclass) ) end it 'can be temporarily supressed' do without_partial_double_verification do expect(subclass).to receive(:fictitious_method) { 'works' } end expect(subclass.fictitious_method).to eq 'works' expect { expect(subclass).to receive(:another_fictitious_method) { 'works' } }.to raise_error RSpec::Mocks::MockExpectationError end end it 'does not allow a non-existing method to be expected' do prevents { expect(object).to receive(:unimplemented) } end it 'does not allow a spy on unimplemented method' do prevents(/does not implement/) { expect(object).to have_received(:unimplemented) } end it 'verifies arity range when matching arguments' do prevents { expect(object).to receive(:implemented).with('bogus') } reset object end it 'allows a method defined with method_missing to be expected' do expect(object).to receive(:dynamic_method).with('a').and_call_original expect(object.dynamic_method('a')).to eq(:dynamic_method) end it 'allows valid methods to be expected on any_instance' do expect_any_instance_of(klass).to receive(:implemented) object.implemented end it 'allows private methods to be expected on any_instance expectation' do expect_any_instance_of(klass).to receive(:defined_private_method).and_call_original object.send(:defined_private_method) end it 'runs the before_verifying_double callbacks on any_instance before verifying a double allowance' do expect_any_instance_of(klass).to receive(:implemented) expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles(&probe) end object.implemented }.to yield_with_args(have_attributes :target => klass) end it 'runs the before_verifying_double callbacks on any_instance before verifying a double' do allow_any_instance_of(klass).to receive(:implemented) expect { |probe| RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles(&probe) end object.implemented }.to yield_with_args(have_attributes :target => klass) end it 'does not allow a non-existing method to be called on any_instance' do prevents(/does not implement/) { expect_any_instance_of(klass).to receive(:unimplemented) } end it 'does not allow missing methods to be called on any_instance' do # This is potentially surprising behaviour, but there is no way for us # to know that this method is valid since we only have class and not an # instance. prevents(/does not implement/) { expect_any_instance_of(klass).to receive(:dynamic_method) } end it 'verifies arity range when receiving a message' do allow(object).to receive(:implemented) expect { object.implemented('bogus') }.to raise_error( ArgumentError, a_string_including("Wrong number of arguments. Expected 0, got 1.") ) end it 'allows the mock to raise an error with yield' do sample_error = Class.new(StandardError) expect(object).to receive(:implemented) { raise sample_error } expect { object.implemented }.to raise_error(sample_error) end it 'allows stubbing and calls the stubbed implementation' do allow(object).to receive(:implemented) { :value } expect(object.implemented).to eq(:value) end context "when `.new` is stubbed" do before do expect(klass.instance_method(:initialize).arity).to eq(2) end it 'uses the method signature from `#initialize` for arg verification' do prevents(/arguments/) { allow(klass).to receive(:new).with(1) } allow(klass).to receive(:new).with(1, 2) end context "on a class that has redefined `new`" do it "uses the method signature of the redefined `new` for arg verification" do subclass = Class.new(klass) do def self.new(_); end end prevents(/arguments/) { allow(subclass).to receive(:new).with(1, 2) } allow(subclass).to receive(:new).with(1) end end context "on a class that has undefined `new`" do it "prevents it from being stubbed" do subclass = Class.new(klass) do class << self undef new end end prevents(/does not implement/) { allow(subclass).to receive(:new).with(1, 2) } end end context "on a class with a private `new`" do it 'uses the method signature from `#initialize` for arg verification' do if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version < '9.2.1.0' pending "Failing on JRuby due to https://github.com/jruby/jruby/issues/2565" end subclass = Class.new(klass) do private_class_method :new end prevents(/arguments/) { allow(subclass).to receive(:new).with(1) } allow(subclass).to receive(:new).with(1, 2) end end context "on a class with a twice-aliased `new`" do it 'uses the method signature from `#initialize` for arg verification', :if => (RUBY_VERSION.to_i >= 3) do subclass = Class.new(klass) do class << self alias_method :_new, :new alias_method :new, :_new end end prevents(/arguments/) { allow(subclass).to receive(:new).with(1) } allow(subclass).to receive(:new).with(1, 2) end end context 'on a class that has redefined `self.method`' do it 'allows the stubbing of :new' do subclass = Class.new(klass) do def self.method(*); end end allow(subclass).to receive(:new) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/modifying_invoked_expectations_spec.rb0000664000000000000000000000242314557670305032041 0ustar rootrootrequire "spec_helper" RSpec.describe "Modifying invoked expectations" do shared_examples_for "a customization on an invoked expectation" do |customization_method, *args| it "raises when the #{customization_method} method is called, indicating the expectation has already been invoked" do dbl = double msg_expectation = expect(dbl).to receive(:foo) expect(dbl.foo).to eq(nil) expect { msg_expectation.__send__(customization_method, *args) }.to raise_error( RSpec::Mocks::MockExpectationAlreadyInvokedError, a_string_including(dbl.inspect, "foo", customization_method.to_s) ) end end it_behaves_like "a customization on an invoked expectation", :with, :some_arg it_behaves_like "a customization on an invoked expectation", :and_return, 1 it_behaves_like "a customization on an invoked expectation", :and_raise, "boom" it_behaves_like "a customization on an invoked expectation", :and_throw, :symbol it_behaves_like "a customization on an invoked expectation", :and_yield, 1 it_behaves_like "a customization on an invoked expectation", :exactly, :once it_behaves_like "a customization on an invoked expectation", :at_least, :once it_behaves_like "a customization on an invoked expectation", :at_most, :once end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/stash_spec.rb0000664000000000000000000000216414557670305024673 0ustar rootrootmodule RSpec module Mocks RSpec.describe "only stashing the original method" do let(:klass) do Class.new do def self.foo(_) :original_value end end end it "keeps the original method intact after multiple expectations are added on the same method" do expect(klass).to receive(:foo).with(:fizbaz).and_return(:wowwow) expect(klass).to receive(:foo).with(:bazbar).and_return(:okay) klass.foo(:fizbaz) klass.foo(:bazbar) verify klass reset klass expect(klass.foo(:yeah)).to equal(:original_value) end end RSpec.describe "when a class method is aliased on a subclass and the method is mocked" do it "restores the original aliased public method" do klass = Class.new do class << self alias alternate_new new end end expect(klass).to receive(:alternate_new) expect(klass.alternate_new).to be_nil verify klass reset klass expect(klass.alternate_new).to be_an_instance_of(klass) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/error_generator_spec.rb0000664000000000000000000000545114557670305026752 0ustar rootrootrequire "spec_helper" module RSpec module Mocks RSpec.describe ErrorGenerator do context "when inserting a backtrace line" do def has_java_frames? yield rescue RSpec::Mocks::MockExpectationError => e e.backtrace.grep(/\.java:/).any? else raise "got no exception" end it "produces stacktraces that match how `raise` produces stacktraces (on JRuby `caller` and `raise` can differ about the presence of java frames)" do raise_has_java_frames = has_java_frames? { raise RSpec::Mocks::MockExpectationError } eg_has_java_frames = has_java_frames? do ErrorGenerator.new.send(:__raise, "message", "foo.rb:1") end expect(raise_has_java_frames).to eq eg_has_java_frames end end def unexpected_failure_message_for(object_description) /received unexpected message :bees with \(#{object_description}\)/ end describe "formatting arguments" do it 'formats time objects with increased precision' do time = Time.utc(1969, 12, 31, 19, 01, 40, 101) expected_output = "1969-12-31 19:01:40.000101" o = double(:double) expect { o.bees(time) }.to fail_including(expected_output) end context "on non-matcher objects that define #description" do it "does not use the object's description" do o = double(:double, :description => "Friends") expect { o.bees(o) }.to fail_with(unexpected_failure_message_for(o.inspect)) end end context "on matcher objects" do context "that define description" do it "uses the object's description" do d = double(:double) o = fake_matcher(Object.new) expect { d.bees(o) }.to raise_error(unexpected_failure_message_for(o.description)) end end context "that do not define description" do it "does not use the object's description" do d = double(:double) o = Class.new do def self.name "RSpec::Mocks::ArgumentMatchers::" end end.new expect(RSpec::Support.is_a_matcher?(o)).to be true expect { d.bees(o) }.to fail_with(unexpected_failure_message_for(o.inspect)) end end context "on default method stub" do it "error message display starts in new line" do d = double(:double) allow(d).to receive(:foo).with({}) expect { d.foo([]) }.to fail_with(/\nDiff/) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks/order_group_spec.rb0000664000000000000000000000146714557670305026105 0ustar rootrootRSpec.describe 'OrderGroup' do let(:order_group) { ::RSpec::Mocks::OrderGroup.new } describe '#consume' do let(:ordered_1) { double :ordered? => true } let(:ordered_2) { double :ordered? => true } let(:unordered) { double :ordered? => false } before do order_group.register unordered order_group.register ordered_1 order_group.register unordered order_group.register ordered_2 order_group.register unordered order_group.register unordered end it 'returns the first ordered? expectation' do expect(order_group.consume).to eq ordered_1 end it 'keeps returning ordered? expectation until all are returned' do expectations = 3.times.map { order_group.consume } expect(expectations).to eq [ordered_1, ordered_2, nil] end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/rspec/mocks_spec.rb0000664000000000000000000001567614557670305023565 0ustar rootrootrequire 'rspec/support/spec/library_wide_checks' RSpec.describe RSpec::Mocks do lib_preamble = [ # We define minitest constants because rspec/mocks/minitest_integration # expects these constants to already be defined. "module Minitest; class Assertion; end; module Test; end; end", 'require "rspec/mocks"', # Must be required before other files due to how our autoloads are setup. # (Users won't hit this problem because they won't require all the files # individually in whatever order the file system returns) 'require "rspec/mocks/any_instance"' ] # On 1.9.2 we load securerandom to get around the lack of `BasicObject#__id__. # Loading securerandom loads many other stdlibs it depends on. Rather than # declaring it (and all the stdlibs it loads) as allowed, it's easier just # to prevent the loading of securerandom by faking out `BasicObject#__id__ lib_preamble.unshift "class BasicObject; def __id__; end; end" if RUBY_VERSION == '1.9.2' it_behaves_like 'library wide checks', 'rspec-mocks', :preamble_for_lib => lib_preamble, :allowed_loaded_feature_regexps => [ /rbconfig/ # loaded by rspec-support ] do if RSpec::Support::Ruby.jruby? && JRUBY_VERSION =~ /9\.1\.7\.0/ before(:example, :description => /spec files/) do pending "JRuby 9.1.7.0 currently generates a circular warning which" \ " is unrelated to our suite." end end if RUBY_VERSION == '1.9.2' before(:example, :description => /spec files/) do pending "Loading psych and syck on 1.9.2 (as our test suite does) triggers warnings" end end end describe ".verify" do it "delegates to the space" do foo = double expect(foo).to receive(:bar) expect do RSpec::Mocks.verify end.to fail RSpec::Mocks.teardown # so the mocks aren't re-verified after this example end end describe ".teardown" do it "resets method stubs" do string = "foo".dup allow(string).to receive(:bar) RSpec::Mocks.teardown expect { string.bar }.to raise_error(NoMethodError) end it "does not put rspec-mocks into an inconsistent state when called extra times" do RSpec::Mocks.teardown RSpec::Mocks.teardown RSpec::Mocks.teardown string = "foo".dup expect { allow(string).to receive(:bar) }.to raise_error(RSpec::Mocks::OutsideOfExampleError) RSpec::Mocks.setup allow(string).to receive(:bar).and_return(:baz) expect(string.bar).to eq(:baz) end end describe ".setup" do it 'starts a new space scope that is later removed by .teardown' do old_space = RSpec::Mocks.space RSpec::Mocks.setup new_space = RSpec::Mocks.space expect(new_space).not_to equal(old_space) RSpec::Mocks.teardown expect(RSpec::Mocks.space).to equal(old_space) end end describe ".configuration" do it 'returns a memoized configuration instance' do expect(RSpec::Mocks.configuration).to be_a(RSpec::Mocks::Configuration) expect(RSpec::Mocks.configuration).to be(RSpec::Mocks.configuration) end end describe ".with_temporary_scope" do context "in a before(:all) with a stubbed double" do before(:all) do RSpec::Mocks.with_temporary_scope do @calculator = double allow(@calculator).to receive(:add) { |a, b| a + b } @sum = @calculator.add(3, 4) end capture_error { @calculator.add(1, 10) } end it 'allows the stubbed double to be used' do expect(@sum).to eq(7) end it 'does not allow the double to be used in the examples' do expect { @calculator.add(1, 2) }.to raise_error(RSpec::Mocks::ExpiredTestDoubleError) end it 'does not allow the double to be used after the scope in before(:all)' do expect(@error).to be_a(RSpec::Mocks::OutsideOfExampleError) end end context "in a before(:all) with a stubbed const" do before(:all) do RSpec::Mocks.with_temporary_scope do stub_const("ValueX", 3) stub_const("ValueY", 4) @sum = ValueX + ValueY end capture_error { ValueX + ValueY } end it 'allows the stubbed constants to be used' do expect(@sum).to eq(7) end it 'does not allow the stubbed constants to be used in the examples' do expect(defined?(ValueX)).to be_falsey expect(defined?(ValueY)).to be_falsey end it 'does not allow the stubbed constants to be used after the scope in before(:all)' do expect(@error).to be_a(NameError) expect(@error.message).to include("ValueX") end end context "in a before(:all) with an unmet mock expectation" do before(:all) do capture_error do RSpec::Mocks.with_temporary_scope do calculator = double expect(calculator).to receive(:add) end end end it 'fails with a mock expectation error' do expect(@error).to be_a(RSpec::Mocks::MockExpectationError) end end context "in a before(:all) with an any_instance stub" do before(:all) do RSpec::Mocks.with_temporary_scope do allow_any_instance_of(String).to receive(:sum_with) { |val, x| val + x } @sum = "foo".dup.sum_with("bar") end capture_error { "you".dup.sum_with("me") } end it 'allows the stub to be used' do expect(@sum).to eq("foobar") end it 'does not allow the double to be used in the examples' do expect { "foo".sum_with("baz") }.to raise_error(NameError, /sum_with/) end it 'does not allow the double to be used after the scope in before(:all)' do expect(@error).to be_a(NameError) expect(@error.message).to include("sum_with") end end it 'tears down even if an error occurs' do foo = Object.new expect { RSpec::Mocks.with_temporary_scope do allow(foo).to receive(:bar) raise "boom" end }.to raise_error("boom") expect(foo).not_to respond_to(:bar) end it 'does not verify if an error occurs before the block completes' do expect { RSpec::Mocks.with_temporary_scope do foo = Object.new expect(foo).to receive(:bar) raise "boom" end }.to raise_error("boom") # rather than MockExpectationError end it 'returns the result of the passed block' do expect(RSpec::Mocks.with_temporary_scope { 5 }).to eq 5 end def capture_error yield rescue Exception => @error end end context "when there is a `let` declaration that overrides an argument matcher" do let(:boolean) { :from_let } before do expect(RSpec::Mocks::ArgumentMatchers.method_defined?(:boolean)).to be true end it 'allows the `let` definition to win' do expect(boolean).to eq(:from_let) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/support/0000775000000000000000000000000014557670305021473 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/support/doubled_classes.rb0000664000000000000000000000270314557670305025155 0ustar rootrootclass LoadedClass extend RSpec::Support::RubyFeatures M = :m N = :n INSTANCE = LoadedClass.new def initialize(_a, _b) end class << self def respond_to?(method_name, include_all=false) return true if method_name == :dynamic_class_method super end def defined_class_method end def send # fake out! end def defined_instance_and_class_method end protected def defined_protected_class_method end private def defined_private_class_method end end def defined_instance_method end def instance_method_with_two_args(_a, _b) end def instance_method_with_only_defaults(_a=1, _b=2) end def defined_instance_and_class_method end if required_kw_args_supported? # Need to eval this since it is invalid syntax on earlier rubies. eval <<-RUBY def kw_args_method(foo, optional_arg:'hello', required_arg:) end def mixed_args_method(foo, bar, optional_arg_1:1, optional_arg_2:2) end RUBY end def send(*) end def respond_to?(method_name, include_all=false) return true if method_name == :dynamic_instance_method super end class Nested; end protected def defined_protected_method end private def defined_private_method "wink wink ;)" end end class LoadedClassWithOverriddenName < LoadedClass def self.name "Overriding name is not a good idea but we can't count on users not doing this" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/support/matchers.rb0000664000000000000000000000061314557670305023626 0ustar rootrootmodule RSpec module Matchers def fail(&block) raise_error(RSpec::Mocks::MockExpectationError, &block) end def fail_with(*args, &block) raise_error(RSpec::Mocks::MockExpectationError, *args, &block) end def fail_including(*snippets) raise_error( RSpec::Mocks::MockExpectationError, a_string_including(*snippets) ) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/support/before_all_shared_example_group.rb0000664000000000000000000000070714557670305030373 0ustar rootrootRSpec.shared_examples "fails in a before(:all) block" do the_error = nil before(:all) do begin use_rspec_mocks rescue the_error = $! end end it "raises an error with a useful message" do expect(the_error).to be_a_kind_of(RSpec::Mocks::OutsideOfExampleError) expect(the_error.message).to match(/The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported./) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/support/aruba.rb0000664000000000000000000000111514557670305023110 0ustar rootrootbegin require 'aruba/rspec' Aruba.configure do |config| if RUBY_PLATFORM =~ /java/ || defined?(Rubinius) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'truffleruby') config.exit_timeout = 60 else config.exit_timeout = 5 end end rescue NameError => e # This silences a name error on unsupported version of JRuby raise e unless RSpec::Support::Ruby.jruby? && JRUBY_VERSION =~ /9\.1\.17\.0/ rescue LoadError => e # This silences a load error on unsupported version of JRuby raise e unless RSpec::Support::Ruby.jruby? && JRUBY_VERSION =~ /9\.1\.17\.0/ end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/integration/0000775000000000000000000000000014557670305022302 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/integration/rails_support_spec.rb0000664000000000000000000000314014557670305026545 0ustar rootrootrequire File.expand_path('../../support/aruba', __FILE__) RSpec.describe "Supporting Rails monkey patches", :type => :aruba do before do if RSpec::Support::OS.windows? && RUBY_VERSION.to_f < 2.4 skip "Aruba on windows is broken on Ruby 2.3 and below" end end it "works when Rails has monkey patched #with" do write_file( "spec/with_monkey_patch_spec.rb", """ class Object # Rails monkey patches in **kwargs but this is a good analogy def with end end RSpec.describe do specify do mock = instance_double(\"Hash\") allow(mock).to receive(:key?).with(:x) { 1 } expect(mock.key?(:x)).to eq 1 end end """ ) run_command("bundle exec rspec spec/with_monkey_patch_spec.rb") expect(last_command_started).to have_output(/0 failures/) expect(last_command_started).to have_exit_status(0) end it "works mocking any instance when Rails has monkey patched #with" do write_file( "spec/with_monkey_patch_spec.rb", """ class Object # Rails monkey patches in **kwargs but this is a good analogy def with end end RSpec.describe do specify do klass = Class.new allow_any_instance_of(klass).to receive(:bar).with(:y) { 2 } expect(klass.new.bar(:y)).to eq 2 end end """ ) run_command("bundle exec rspec spec/with_monkey_patch_spec.rb") expect(last_command_started).to have_output(/0 failures/) expect(last_command_started).to have_exit_status(0) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/spec/spec_helper.rb0000664000000000000000000001025014557670305022573 0ustar rootrootrequire 'rspec/support/spec' require 'rspec/support/ruby_features' RSpec::Support::Spec.setup_simplecov do minimum_coverage 93 end require 'yaml' begin require 'psych' rescue LoadError end RSpec::Matchers.define :include_method do |expected| match do |actual| actual.map { |m| m.to_s }.include?(expected.to_s) end end require 'support/matchers' module VerifyAndResetHelpers def verify(object) proxy = RSpec::Mocks.space.proxy_for(object) proxy.verify ensure proxy.reset # so it doesn't fail the verify after the example completes end def reset(object) RSpec::Mocks.space.proxy_for(object).reset end def verify_all RSpec::Mocks.space.verify_all ensure reset_all end def reset_all RSpec::Mocks.space.reset_all end def with_unfulfilled_double d = double("double") yield d ensure reset d end def expect_fast_failure_from(double, *fail_with_args, &blk) expect { blk.call(double) }.to fail_with(*fail_with_args) reset double end end module VerificationHelpers def prevents(msg=//, &block) expect(&block).to fail_with msg end end module MatcherHelpers def self.fake_matcher_description "fake_matcher_description" end extend RSpec::Matchers::DSL matcher :fake_matcher do |expected| match { |actual| actual == expected } description do MatcherHelpers.fake_matcher_description end end end require 'rspec/support/spec' RSpec.configure do |config| config.expose_dsl_globally = false config.mock_with :rspec config.color = true config.order = :random config.expect_with :rspec do |expectations| expectations.syntax = :expect end config.mock_with :rspec do |mocks| $default_rspec_mocks_syntax = mocks.syntax mocks.syntax = :expect end old_verbose = nil config.before(:each, :silence_warnings) do old_verbose = $VERBOSE $VERBOSE = nil end config.after(:each, :silence_warnings) do $VERBOSE = old_verbose end config.include VerifyAndResetHelpers config.include MatcherHelpers config.include VerificationHelpers config.extend RSpec::Support::RubyFeatures config.include RSpec::Support::RubyFeatures config.define_derived_metadata :ordered_and_vague_counts_unsupported do |meta| meta[:pending] = "`.ordered` combined with a vague count (e.g. `at_least` or `at_most`) is not yet supported (see #713)" end # We have yet to try to address this issue, and it's just noise in our output, # so skip it locally. However, on CI we want it to still run them so that if # we do something that makes these specs pass, we are notified. config.filter_run_excluding :ordered_and_vague_counts_unsupported unless ENV['CI'] # We don't want rspec-core to look in our `lib` for failure snippets. # When it does that, it inevitably finds this line: # `RSpec::Support.notify_failure(*args)` # ...which isn't very helpful. Far better for it to find the expectation # call site in the spec. config.project_source_dirs -= %w[ lib ] RSpec::Matchers.define_negated_matcher :a_string_excluding, :include end RSpec.shared_context "with syntax" do |syntax| orig_syntax = nil before(:all) do orig_syntax = RSpec::Mocks.configuration.syntax RSpec::Mocks.configuration.syntax = syntax end after(:all) do RSpec::Mocks.configuration.syntax = orig_syntax end end RSpec.shared_context "with isolated configuration" do orig_configuration = nil before do orig_configuration = RSpec::Mocks.configuration RSpec::Mocks.instance_variable_set(:@configuration, RSpec::Mocks::Configuration.new) end after do RSpec::Mocks.instance_variable_set(:@configuration, orig_configuration) end end RSpec.shared_context "with monkey-patched marshal" do before do RSpec::Mocks.configuration.patch_marshal_to_support_partial_doubles = true end after do RSpec::Mocks.configuration.patch_marshal_to_support_partial_doubles = false end end RSpec.shared_context "with the default mocks syntax" do orig_syntax = nil before(:all) do orig_syntax = RSpec::Mocks.configuration.syntax RSpec::Mocks.configuration.reset_syntaxes_to_default end after(:all) do RSpec::Mocks.configuration.syntax = orig_syntax end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/cucumber.yml0000664000000000000000000000043414557670305021356 0ustar rootroot<% USE_TILDE_TAGS = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') NOT_WIP_TAG = USE_TILDE_TAGS ? '~@wip' : '"not @wip"' %> default: --require features --tags <%= NOT_WIP_TAG %> features --format progress wip: --require features --tags @wip:3 --wip features ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.github/0000775000000000000000000000000014557670305020365 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.github/workflows/0000775000000000000000000000000014557670305022422 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.github/workflows/ci.yml0000664000000000000000000001143014557670305023537 0ustar rootroot# This file was generated on 2023-12-26T21:12:38+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. name: RSpec CI on: push: branches: - 'main' - '*-maintenance' - '*-dev' pull_request: branches: - '*' permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: RSPEC_CI: true # This tells rspec-rails what branch to run in ci RSPEC_VERSION: '~> 3.13.0' jobs: rubocop: name: Rubocop runs-on: 'ubuntu-20.04' steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.0' - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_rubocop test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} runs-on: ${{ matrix.os || 'ubuntu-20.04' }} strategy: matrix: ruby: - '3.3' - '3.2' - '3.1' - '3.0' - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 env: - DIFF_LCS_VERSION: "> 1.4.3" include: - ruby: ruby-head env: RUBY_HEAD: true - ruby: jruby-9.2.13.0 env: JRUBY_OPTS: "--dev" - ruby: 2.7 name_extra: "with diff-lcs 1.3" env: DIFF_LCS_VERSION: "~> 1.3.0" - ruby: 2.7 name_extra: "with diff-lcs 1.4.3" env: DIFF_LCS_VERSION: "1.4.3" fail-fast: false continue-on-error: ${{ matrix.allow_failure || endsWith(matrix.ruby, 'head') }} env: ${{ matrix.env }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: ${{ matrix.bundler || '2.2.22' }} ruby-version: ${{ matrix.ruby }} - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_build legacy: name: Legacy Ruby Builds (${{ matrix.container.version }}) runs-on: ubuntu-20.04 container: image: ${{ matrix.container.tag }} options: ${{ matrix.container.options || '--add-host github-complains-if-this-is-empty.com:127.0.0.1' }} strategy: fail-fast: false matrix: container: - version: "2.1.9" tag: ghcr.io/rspec/docker-ci:2.1.9 post: git config --global --add safe.directory `pwd` - version: "2.0" tag: ghcr.io/rspec/docker-ci:2.0.0 - version: "1.9.3" tag: ghcr.io/rspec/docker-ci:1.9.3 - version: "1.9.2" tag: ghcr.io/rspec/docker-ci:1.9.2 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "1.8.7" tag: ghcr.io/rspec/docker-ci:1.8.7 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "REE" tag: ghcr.io/rspec/docker-ci:ree options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 1.7" tag: ghcr.io/rspec/docker-ci:jruby-1.7 - version: "JRuby 1.7 1.8 mode" tag: ghcr.io/rspec/docker-ci:jruby-1.7 jruby_opts: '--dev --1.8' pre: gem uninstall jruby-openssl options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 9.1.17.0" tag: ghcr.io/rspec/docker-ci:jruby-9.1.17.0 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" env: LEGACY_CI: true JRUBY_OPTS: ${{ matrix.container.jruby_opts || '--dev' }} steps: - uses: actions/checkout@v3 - run: ${{ matrix.container.pre }} - run: script/legacy_setup.sh - run: ${{ matrix.container.post }} - run: bundle exec bin/rspec - run: bundle exec script/cucumber.sh windows: name: Ruby ${{ matrix.ruby }} (Windows) runs-on: windows-latest strategy: matrix: ruby: - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 fail-fast: false steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: '2.2.22' ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: choco install ansicon - run: bundle exec rspec --backtrace ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.github/dependabot.yml0000664000000000000000000000043714557670305023221 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.github/FUNDING.yml0000664000000000000000000000033514557670305022203 0ustar rootroot# This file was generated on 2023-04-16T20:53:23+01: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, benoittgt] open_collective: rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/DEV-README.md0000664000000000000000000000125614557670305020724 0ustar rootroot## Set up the dev environment git clone https://github.com/rspec/rspec-mocks.git cd rspec-mocks gem install bundler bundle install Now you should be able to run any of: rake rake spec rake cucumber Or, if you prefer to use the rspec and cucumber commands directly, you can either: bundle exec rspec Or ... bundle install --binstubs bin/rspec ## Customize the dev environment The Gemfile includes the gems you'll need to be able to run specs. If you want to customize your dev environment with additional tools like guard or ruby-debug, add any additional gem declarations to Gemfile-custom (see Gemfile-custom.sample for some examples). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/CONTRIBUTING.md0000664000000000000000000001032414557670305021256 0ustar rootroot # Contributing RSpec is a community-driven project that has benefited from improvements from over *500* contributors. We welcome contributions from *everyone*. While contributing, please follow the project [code of conduct](CODE_OF_CONDUCT.md), so that everyone can be included. If you'd like to help make RSpec better, here are some ways you can contribute: - by running RSpec HEAD to help us catch bugs before new releases - by [reporting bugs you encounter](https://github.com/rspec/rspec-mocks/issues/new) with [report template](#report-template) - by [suggesting new features](https://github.com/rspec/rspec-mocks/issues/new) - by improving RSpec's Feature or API [documentation](https://rspec.info/documentation/) - by improving [RSpec's website](https://rspec.info/) ([source](https://github.com/rspec/rspec.github.io)) - by taking part in [feature and issue discussions](https://github.com/rspec/rspec-mocks/issues) - by adding a failing test for reproducible [reported bugs](https://github.com/rspec/rspec-mocks/issues) - by reviewing [pull requests](https://github.com/rspec/rspec-mocks/pulls) and suggesting improvements - by [writing code](DEVELOPMENT.md) (no patch is too small! fix typos or bad whitespace) If you need help getting started, check out the [DEVELOPMENT](DEVELOPMENT.md) file for steps that will get you up and running. Thanks for helping us make RSpec better! ## `Small` issues These issue are ones that we be believe are best suited for new contributors to get started with. They represent a meaningful contribution to the project that should not be too hard to pull off. ## Report template Having a way to reproduce your issue will be very helpful for others to help confirm, investigate and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared one basic [bug report templates](REPORT_TEMPLATE.md) for you to use as a starting point. ## Maintenance branches Maintenance branches are how we manage the different supported point releases of RSpec. As such, while they might look like good candidates to merge into main, please do not open pull requests to merge them. ## Working on multiple RSpec gems at the same time RSpec is composed of multiple gems (`rspec-core`, `rspec-mocks`, etc). Sometimes you have to work on a combination of them at the same time. When submitting your code for review, we ask that you get a passing build (green CI). If you are working across the repositories, please add a commit that temporarily pins your PR to the right branch of the other repository you depend on. For example, if we wanted a change in `rspec-expectations` that relied on a change for on `rspec-mocks`. We add a commit with the title: >[WIP] Use rspec-mocks with "custom-failure-message" branch And content: ```diff diff --git a/Gemfile b/Gemfile -%w[rspec rspec-core rspec-mocks rspec-support].each do |lib| +%w[rspec rspec-core rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path @@ -11,6 +11,7 @@ branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end +gem 'rspec-mocks', :git => "https://github.com/rspec/rspec-mocks.git", :branch => "custom-failure-message" ``` In general the process is: 1. Create PRs explaining what you are trying to achieve. 2. Pin the repositories to each other. 3. Check they pass (go green). 4. Await review if appropriate. 5. Remove the commit from step 2. We will merge ignoring the failure. 6. Remove the commit from the other, check it passes with the other commit now on `main`. 7. Merge the other. 8. We will trigger builds for the `main` branch of affected repositories to check if everything is in order. Steps 5-8 should happen continuously (e.g. one after another but within a short timespan) so that we don't leave a broken main around. It is important to triage that build process and revert if necessary. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/BUILD_DETAIL.md0000664000000000000000000001244114557670305021232 0ustar rootroot # The CI build, in detail The [Travis CI build](https://travis-ci.org/rspec/rspec-mocks) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` It can be useful to run the build steps individually to repro a failing part of a Travis build. Let's break the build down into the individual steps. ## Specs RSpec dogfoods itself. Its primary defense against regressions is its spec suite. Run with: ``` $ bundle exec rspec # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rspec ``` The spec suite performs a couple extra checks that are worth noting: * *That all the code is warning-free.* Any individual example that produces output to `stderr` will fail. We also have a spec that loads all the `lib` and `spec` files in a newly spawned process to detect load-time warnings and fail if there are any. RSpec must be warning-free so that users who enable Ruby warnings will not get warnings from our code. * *That only a minimal set of stdlibs are loaded.* Since Ruby makes loaded libraries available for use in any context, we want to minimize how many bits of the standard library we load and use. Otherwise, RSpec's use of part of the standard library could mask a problem where a gem author forgets to load a part of the standard library they rely on. The spec suite contains a spec that defines a list of allowed loaded stdlibs. In addition, we use [SimpleCov](https://github.com/colszowka/simplecov) to measure and enforce test coverage. If the coverage falls below a project-specific threshold, the build will fail. ## Cukes RSpec uses [cucumber](https://cucumber.io/) for both acceptance testing and [documentation](https://rspec.info/documentation). Since we publish our cukes as documentation, please limit new cucumber scenarios to user-facing examples that help demonstrate usage. Any tests that exist purely to prevent regressions should be written as specs, even if they are written in an acceptance style. Duplication between our YARD API docs and the cucumber documentation is fine. Run with: ``` $ bundle exec cucumber # or, if you installed your bundle with `--standalone --binstubs`: $ bin/cucumber ``` ## YARD documentation RSpec uses [YARD](https://yardoc.org/) for API documentation on the [rspec.info site](https://rspec.info/). Our commitment to [SemVer](https://semver.org) requires that we explicitly declare our public API, and our build uses YARD to ensure that every class, module and method has either been labeled `@private` or has at least some level of documentation. For new APIs, this forces us to make an intentional decision about whether or not it should be part of RSpec's public API or not. To run the YARD documentation coverage check, run: ``` $ bundle exec yard stats --list-undoc # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard stats --list-undoc ``` We also want to prevent YARD errors or warnings when actually generating the docs. To check for those, run: ``` $ bundle exec yard doc --no-cache # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard doc --no-cache ``` ## RuboCop We use [RuboCop](https://github.com/rubocop-hq/rubocop) to enforce style conventions on the project so that the code has stylistic consistency throughout. Run with: ``` $ bundle exec rubocop lib # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rubocop lib ``` Our RuboCop configuration is a work-in-progress, so if you get a failure due to a RuboCop default, feel free to ask about changing the configuration. Otherwise, you'll need to address the RuboCop failure, or, as a measure of last resort, by wrapping the offending code in comments like `# rubocop:disable SomeCheck` and `# rubocop:enable SomeCheck`. ## Run spec files one-by-one A fast TDD cycle depends upon being able to run a single spec file, without the rest of the test suite. While rare, it's fairly easy to create a situation where a spec passes when the entire suite runs but fails when its individual file is run. To guard against this, our CI build runs each spec file individually, using a bit of bash like: ``` for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done ``` Since this step boots RSpec so many times, it runs much, much faster when we can avoid the overhead of bundler. This is a main reason our CI build installs the bundle with `--standalone --binstubs` and runs RSpec via `bin/rspec` rather than `bundle exec rspec`. ## Running the spec suite for each of the other repos While each of the RSpec repos is an independent gem (generally designed to be usable on its own), there are interdependencies between the gems, and the specs for each tend to use features from the other gems. We don't want to merge a pull request for one repo that might break the build for another repo, so our CI build includes a spec that runs the spec suite of each of the _other_ project repos. Note that we only run the spec suite, not the full build, of the other projects, as the spec suite runs very quickly compared to the full build. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/Guardfile0000664000000000000000000000042114557670305020647 0ustar rootroot# A sample Guardfile # More info at http://github.com/guard/guard#readme guard 'rspec', :version => 2 do watch(/^spec\/(.*)_spec.rb/) watch(/^lib\/(.*)\.rb/) { "spec" } watch(/^spec\/spec_helper.rb/) { "spec" } end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/0000775000000000000000000000000014557670305020643 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/working_with_legacy_code/0000775000000000000000000000000014557670305025674 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/working_with_legacy_code/any_instance.feature0000664000000000000000000001412514557670305031727 0ustar rootrootFeature: Any Instance rspec-mocks provides two methods, `allow_any_instance_of` and `expect_any_instance_of`, that will allow you to stub or mock any instance of a class. They are used in place of [`allow`](../basics/allowing-messages) or [`expect`](../basics/expecting-messages): ```ruby allow_any_instance_of(Widget).to receive(:name).and_return("Wibble") expect_any_instance_of(Widget).to receive(:name).and_return("Wobble") ``` These methods add the appropriate stub or expectation to all instances of `Widget`. You can also [configure the responses](../configuring-responses) in the same manner. This feature is sometimes useful when working with legacy code, though in general we discourage its use for a number of reasons: * The `rspec-mocks` API is designed for individual object instances, but this feature operates on entire classes of objects. As a result there are some semantically confusing edge cases. For example, in `expect_any_instance_of(Widget).to receive(:name).twice` it isn't clear whether a specific instance is expected to receive `name` twice, or if two receives total are expected. (It's the former.) * Using this feature is often a design smell. It may be that your test is trying to do too much or that the object under test is too complex. * It is the most complicated feature of `rspec-mocks`, and has historically received the most bug reports. (None of the core team actively use it, which doesn't help.) Scenario: Use `allow_any_instance_of` to stub a method Given a file named "example_spec.rb" with: """ruby RSpec.describe "allow_any_instance_of" do it "returns the specified value on any instance of the class" do allow_any_instance_of(Object).to receive(:foo).and_return(:return_value) o = Object.new expect(o.foo).to eq(:return_value) end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Use `allow_any_instance_of` to stub multiple methods Given a file named "example_spec.rb" with: """ruby RSpec.describe "allow_any_instance_of" do context "with receive_messages" do it "stubs multiple methods" do allow_any_instance_of(Object).to receive_messages(:foo => 'foo', :bar => 'bar') o = Object.new expect(o.foo).to eq('foo') expect(o.bar).to eq('bar') end end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Stubbing any instance of a class with specific arguments Given a file named "example_spec.rb" with: """ruby RSpec.describe "allow_any_instance_of" do context "with arguments" do it "returns the stubbed value when arguments match" do allow_any_instance_of(Object).to receive(:foo).with(:param_one, :param_two).and_return(:result_one) allow_any_instance_of(Object).to receive(:foo).with(:param_three, :param_four).and_return(:result_two) o = Object.new expect(o.foo(:param_one, :param_two)).to eq(:result_one) expect(o.foo(:param_three, :param_four)).to eq(:result_two) end end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Block implementation is passed the receiver as first arg Given a file named "example_spec.rb" with: """ruby RSpec.describe "allow_any_instance_of" do it 'yields the receiver to the block implementation' do allow_any_instance_of(String).to receive(:slice) do |instance, start, length| instance[start, length] end expect('string'.slice(2, 3)).to eq('rin') end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Use `expect_any_instance_of` to set a message expectation on any instance Given a file named "example_spec.rb" with: """ruby RSpec.describe "expect_any_instance_of" do before do expect_any_instance_of(Object).to receive(:foo) end it "passes when an instance receives the message" do Object.new.foo end it "fails when no instance receives the message" do Object.new.to_s end end """ When I run `rspec example_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | Exactly one instance should have received the following message(s) but didn't: foo | Scenario: Specify different return values for multiple calls in combination with allow_any_instance_of Using the multiple calls feature with `allow_any_instance_of` results in the behaviour where multiple calls are configured on every instance. Therefore, each individual instance will return the configured return values in the order specified, and then begin to repeat the last value. Given a file named "multiple_calls_spec_with_allow_any_instance_of.rb" with: """ruby class SomeClass end RSpec.describe "When the method is called multiple times on different instances with allow_any_instance_of" do it "demonstrates the mocked behavior on each instance individually" do allow_any_instance_of(SomeClass).to receive(:foo).and_return(1, 2, 3) first = SomeClass.new second = SomeClass.new third = SomeClass.new expect(first.foo).to eq(1) expect(second.foo).to eq(1) expect(first.foo).to eq(2) expect(second.foo).to eq(2) expect(first.foo).to eq(3) expect(first.foo).to eq(3) # repeats last value from here expect(second.foo).to eq(3) expect(second.foo).to eq(3) # repeats last value from here expect(third.foo).to eq(1) expect(third.foo).to eq(2) expect(third.foo).to eq(3) expect(third.foo).to eq(3) # repeats last value from here end end """ When I run `rspec multiple_calls_spec_with_allow_any_instance_of.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/working_with_legacy_code/message_chains.feature0000664000000000000000000000714514557670305032231 0ustar rootrootFeature: Message Chains You can use `receive_message_chain` in place of `receive` in certain circumstances to stub a chain of messages: ```ruby allow(double).to receive_message_chain("foo.bar") { :baz } allow(double).to receive_message_chain(:foo, :bar => :baz) allow(double).to receive_message_chain(:foo, :bar) { :baz } ```` Given any of these three forms: ```ruby double.foo.bar # => :baz ``` Common use in Rails/ActiveRecord: ```ruby allow(Article).to receive_message_chain("recent.published") { [Article.new] } ``` `receive_message_chain` is designed to be used with evaluating a response like `and_return`, `and_yield` etc. For legacy reasons, parity with `stub_chain` is supported but its uses are not considered good practice. Support for `stub_chain` parity may be removed in future versions. Customisations like `exactly` (i.e. `exactly(2).times`) are not supported. Warning: ======== Chains can be arbitrarily long, which makes it quite painless to violate the Law of Demeter in violent ways, so you should consider any use of `receive_message_chain` a code smell. Even though not all code smells indicate real problems (think fluent interfaces), `receive_message_chain` still results in brittle examples. For example, if you write `allow(foo).to receive_message_chain(:bar, :baz => 37)` in a spec and then the implementation calls `foo.baz.bar`, the stub will not work. Chaining with `receive_message_chain` creates ambiguity in how the chains should be applied and applies design pressure on complex interactions in the implementation code. As such `receive_message_chain` is not a perfect replacement for `receive`. (see [Issue 921](https://github.com/rspec/rspec-mocks/issues/921) for a more detailed explanation). Other mocking methods like `double` and `instance_double` provide a better way of testing code with these interactions. Scenario: Use `receive_message_chain` on a double Given a file named "receive_message_chain_spec.rb" with: """ruby RSpec.describe "Using receive_message_chain on a double" do let(:dbl) { double } example "using a string and a block" do allow(dbl).to receive_message_chain("foo.bar") { :baz } expect(dbl.foo.bar).to eq(:baz) end example "using symbols and a hash" do allow(dbl).to receive_message_chain(:foo, :bar => :baz) expect(dbl.foo.bar).to eq(:baz) end example "using symbols and a block" do allow(dbl).to receive_message_chain(:foo, :bar) { :baz } expect(dbl.foo.bar).to eq(:baz) end end """ When I run `rspec receive_message_chain_spec.rb` Then the examples should all pass Scenario: Use `receive_message_chain` on any instance of a class Given a file named "receive_message_chain_spec.rb" with: """ruby RSpec.describe "Using receive_message_chain on any instance of a class" do example "using a string and a block" do allow_any_instance_of(Object).to receive_message_chain("foo.bar") { :baz } expect(Object.new.foo.bar).to eq(:baz) end example "using symbols and a hash" do allow_any_instance_of(Object).to receive_message_chain(:foo, :bar => :baz) expect(Object.new.foo.bar).to eq(:baz) end example "using symbols and a block" do allow_any_instance_of(Object).to receive_message_chain(:foo, :bar) { :baz } expect(Object.new.foo.bar).to eq(:baz) end end """ When I run `rspec receive_message_chain_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/working_with_legacy_code/README.md0000664000000000000000000000036214557670305027154 0ustar rootroot# Working with legacy code RSpec provides a few features that, while not generally recommended, can be useful when you are getting legacy code under test (or in similar situations). Usage of these features should be considered a code smell. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/.nav0000664000000000000000000000224614557670305021434 0ustar rootroot- basics: - test_doubles.feature - allowing_messages.feature - expecting_messages.feature - partial_test_doubles.feature - null_object_doubles.feature - spies.feature - scope.feature - verifying_doubles: - instance_doubles.feature - class_doubles.feature - object_doubles.feature - dynamic_classes.feature - partial_doubles.feature - configuring_responses: - returning_a_value.feature - raising_an_error.feature - throwing.feature - yielding.feature - calling_the_original_implementation.feature - wrapping_the_original_implementation.feature - block_implementation.feature - setting_constraints: - matching_arguments.feature - receive_counts.feature - message_order.feature - mutating_constants: - stub_defined_constant.feature - stub_undefined_constant.feature - hide_defined_constant.feature - hide_undefined_constant.feature - working_with_legacy_code: - any_instance.feature - message_chains.feature - old_syntax: - stub.feature - should_receive.feature - any_instance.feature - stub_chain.feature - unstub.feature - outside_rspec: - minitest.feature - any_test_framework.feature - standalone.feature - Changelog ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/step_definitions/0000775000000000000000000000000014557670305024211 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/step_definitions/additional_cli_steps.rb0000664000000000000000000000153214557670305030714 0ustar rootrootThen /^the example(?:s)? should(?: all)? pass$/ do step %q(the output should contain "0 failures") step %q(the exit status should be 0) end Then /^the examples should all fail, producing the following output:$/ do |table| step %q(the exit status should be 1) examples, failures = all_output.match(/(\d+) examples?, (\d+) failures?/).captures.map(&:to_i) expect(examples).to be > 0 expect(examples).to eq(failures) lines = table.raw.flatten.reject(&:empty?) expect(all_output).to include(*lines) end RSpec::Matchers.define :match_table do |lines| match do |all_output| lines.all? { |line| all_output.include?(line) } end diffable end Then /^it should fail with the following output:$/ do |table| step %q(the exit status should be 1) lines = table.raw.flatten.reject(&:empty?) expect(all_output).to match_table(lines) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/0000775000000000000000000000000014557670305025256 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/throwing.feature0000664000000000000000000000171714557670305030502 0ustar rootrootFeature: Throwing Use `and_throw` to make the test double throw the provided symbol, optionally with the provided argument. * `and_throw(:symbol)` * `and_throw(:symbol, argument)` Scenario: Throw a symbol Given a file named "and_throw_spec.rb" with: """ruby RSpec.describe "Making it throw a symbol" do it "throws the provided symbol" do dbl = double allow(dbl).to receive(:foo).and_throw(:hello) catch :hello do dbl.foo fail "should not get here" end end it "includes the provided argument when throwing" do dbl = double allow(dbl).to receive(:foo).and_throw(:hello, "world") arg = catch :hello do dbl.foo fail "should not get here" end expect(arg).to eq("world") end end """ When I run `rspec and_throw_spec.rb` Then the examples should all pass ././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/wrapping_the_original_implementation.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/wrapping_the_original_impl0000664000000000000000000000572714557670305032610 0ustar rootrootFeature: Wrapping the original implementation Use `and_wrap_original` to modify a partial double's original response. This can be useful when you want to utilise an external object but mutate its response. For example if an API returns a large amount of data and for test purposes you'd like to trim it down. You can also use it to configure the default response for most arguments, and then override that for specific arguments using `with`. Note: `and_wrap_original` is only supported on partial doubles, as normal test doubles do not have an original implementation. Background: Given a file named "lib/api.rb" with: """ruby class API def self.solve_for(x) (1..x).to_a end end """ Scenario: `and_wrap_original` wraps the original partial double response Given a file named "spec/and_wrap_original_spec.rb" with: """ruby require 'api' RSpec.describe "and_wrap_original" do it "responds as it normally would, modified by the block" do expect(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) } expect(API.solve_for(100)).to eq [1,2,3,4,5] end end """ When I run `rspec spec/and_wrap_original_spec.rb` Then the examples should all pass Scenario: `and_wrap_original` can configure a default response that can be overridden for specific args Given a file named "spec/and_wrap_original_spec.rb" with: """ruby require 'api' RSpec.describe "and_wrap_original" do it "can be overridden for specific arguments using #with" do allow(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) } allow(API).to receive(:solve_for).with(2).and_return([3]) expect(API.solve_for(20)).to eq [1,2,3,4,5] expect(API.solve_for(2)).to eq [3] end end """ When I run `rspec spec/and_wrap_original_spec.rb` Then the examples should all pass @kw-arguments Scenario: `and_wrap_original` can configure a default response that can be overridden for specific keyword arguments Given a file named "lib/kw_api.rb" with: """ruby class API def self.solve_for(x: 1, y: 2) (x..y).to_a end end """ Given a file named "spec/and_wrap_original_spec.rb" with: """ruby require 'kw_api' RSpec.describe "and_wrap_original" do it "can be overridden for specific arguments using #with" do allow(API).to receive(:solve_for).and_wrap_original { |m, **kwargs| m.call(**kwargs).first(5) } allow(API).to receive(:solve_for).with(x: 3, y: 4).and_return([3]) expect(API.solve_for(x: 1, y: 20)).to eq [1,2,3,4,5] expect(API.solve_for(y: 20)).to eq [1,2,3,4,5] expect(API.solve_for(x: 3, y: 4)).to eq [3] end end """ When I run `rspec spec/and_wrap_original_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/mixed_responses.feature0000664000000000000000000000205514557670305032044 0ustar rootrootFeature: Mixed responses Use `and_invoke` to invoke a callable when a message is received. Pass `and_invoke` multiple callables to have different behavior for consecutive calls. The final callable will continue to be called if the message is received additional times. Note: The invoked callable will be invoked with the calls arguments, so it is recommended to use a `lambda` or similar with the same arity as your method but you can use a `proc` if you do not care about arity (e.g. when raising). Scenario: Mixed responses Given a file named "raises_and_then_returns.rb" with: """ruby RSpec.describe "when the method is called multiple times" do it "raises and then later returns a value" do dbl = double allow(dbl).to receive(:foo).and_invoke(lambda { raise "failure" }, lambda { true }) expect { dbl.foo }.to raise_error("failure") expect(dbl.foo).to eq(true) end end """ When I run `rspec raises_and_then_returns.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/README.md0000664000000000000000000000200714557670305026534 0ustar rootroot# Configuring responses When [allowing](./basics/allowing-messages) or [expecting](./basics/expecting-messages) messages, the default response is to return `nil`. Several methods are provided to configure how the test double responds to the message. * `and_return` * `and_raise` * `and_invoke` * `and_throw` * `and_yield` * `and_call_original` * `and_wrap_original` In addition, you can provide a [block implementation](./configuring-responses/block-implementation) to respond in any manner you wish. Note: for simplicity, the examples here use `allow` rather than `expect`, but these APIs apply equally to both cases. ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/block_implementation.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/block_implementation.featu0000664000000000000000000001074014557670305032505 0ustar rootrootFeature: Block implementation When you pass a block, RSpec will use your block as the implementation of the method. Any arguments (or a block) provided by the caller will be yielded to your block implementation. This feature is extremely flexible, and supports many use cases that are not directly supported by the more declarative fluent interface. You can pass a block to any of the fluent interface methods: * `allow(dbl).to receive(:foo) { do_something }` * `allow(dbl).to receive(:foo).with("args") { do_something }` * `allow(dbl).to receive(:foo).once { do_something }` * `allow(dbl).to receive(:foo).ordered { do_something }` Some of the more common use cases for block implementations are shown below, but this is not an exhaustive list. Scenario: Use a block to specify a return value with a terser syntax Given a file named "return_value_spec.rb" with: """ruby RSpec.describe "Specifying a return value using a block" do it "returns the block's return value" do dbl = double allow(dbl).to receive(:foo) { 14 } expect(dbl.foo).to eq(14) end end """ When I run `rspec return_value_spec.rb` Then the examples should all pass Scenario: Use a block to verify arguments Given a file named "verify_arguments_spec.rb" with: """ruby RSpec.describe "Verifying arguments using a block" do it "fails when the arguments do not meet the expectations set in the block" do dbl = double allow(dbl).to receive(:foo) do |arg| expect(arg).to eq("bar") end dbl.foo(nil) end end """ When I run `rspec verify_arguments_spec.rb` Then it should fail with: """ Failure/Error: expect(arg).to eq("bar") """ Scenario: Use a block to perform a calculation Given a file named "perform_calculation_spec.rb" with: """ruby RSpec.describe "Performing a calculation using a block" do it "returns the block's return value" do loan = double("Loan", :amount => 100) allow(loan).to receive(:required_payment_for_rate) do |rate| loan.amount * rate end expect(loan.required_payment_for_rate(0.05)).to eq(5) expect(loan.required_payment_for_rate(0.1)).to eq(10) end end """ When I run `rspec perform_calculation_spec.rb` Then the examples should all pass Scenario: Yield to the caller's block Given a file named "yield_to_caller_spec.rb" with: """ruby RSpec.describe "When the caller passes a block" do it "can be yielded to from your implementation block" do dbl = double allow(dbl).to receive(:foo) { |&block| block.call(14) } expect { |probe| dbl.foo(&probe) }.to yield_with_args(14) end end """ When I run `rspec yield_to_caller_spec.rb` Then the examples should all pass Scenario: Delegate to partial double's original implementation within the block Given a file named "delegate_to_original_spec.rb" with: """ruby class Calculator def self.add(x, y) x + y end end RSpec.describe "When using a block implementation on a partial double" do it "supports delegating to the original implementation" do original_add = Calculator.method(:add) allow(Calculator).to receive(:add) do |x, y| original_add.call(x, y) * 2 end expect(Calculator.add(2, 5)).to eq(14) end end """ When I run `rspec delegate_to_original_spec.rb` Then the examples should all pass Scenario: Simulating a transient network failure Given a file named "simulate_transient_network_failure_spec.rb" with: """ruby RSpec.describe "An HTTP API client" do it "can simulate transient network failures" do client = double("MyHTTPClient") call_count = 0 allow(client).to receive(:fetch_data) do call_count += 1 call_count.odd? ? raise("timeout") : { :count => 15 } end expect { client.fetch_data }.to raise_error("timeout") expect(client.fetch_data).to eq(:count => 15) expect { client.fetch_data }.to raise_error("timeout") expect(client.fetch_data).to eq(:count => 15) end end """ When I run `rspec simulate_transient_network_failure_spec.rb` Then the examples should all pass ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/calling_the_original_implementation.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/calling_the_original_imple0000664000000000000000000000351414557670305032527 0ustar rootrootFeature: Calling the original implementation Use `and_call_original` to make a partial double response as it normally would. This can be useful when you want to expect a message without interfering with how it responds. You can also use it to configure the default response for most arguments, and then override that for specific arguments using `with`. Note: `and_call_original` is only supported on partial doubles, as normal test doubles do not have an original implementation. Background: Given a file named "lib/calculator.rb" with: """ruby class Calculator def self.add(x, y) x + y end end """ Scenario: `and_call_original` makes the partial double respond as it normally would Given a file named "spec/and_call_original_spec.rb" with: """ruby require 'calculator' RSpec.describe "and_call_original" do it "responds as it normally would" do expect(Calculator).to receive(:add).and_call_original expect(Calculator.add(2, 3)).to eq(5) end end """ When I run `rspec spec/and_call_original_spec.rb` Then the examples should all pass Scenario: `and_call_original` can configure a default response that can be overridden for specific args Given a file named "spec/and_call_original_spec.rb" with: """ruby require 'calculator' RSpec.describe "and_call_original" do it "can be overridden for specific arguments using #with" do allow(Calculator).to receive(:add).and_call_original allow(Calculator).to receive(:add).with(2, 3).and_return(-5) expect(Calculator.add(2, 2)).to eq(4) expect(Calculator.add(2, 3)).to eq(-5) end end """ When I run `rspec spec/and_call_original_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/yielding.feature0000664000000000000000000000471214557670305030443 0ustar rootrootFeature: Yielding Use `and_yield` to make the test double yield the provided arguments when it receives the message. If the caller does not provide a block, or the caller's block does not accept the provided arguments, an error will be raised. If you want to yield multiple times, chain multiple `and_yield` calls together. Scenario: Yield an argument Given a file named "yield_arguments_spec.rb" with: """ruby RSpec.describe "Making it yield arguments" do it "yields the provided args" do dbl = double allow(dbl).to receive(:foo).and_yield(2, 3) x = y = nil dbl.foo { |a, b| x, y = a, b } expect(x).to eq(2) expect(y).to eq(3) end end """ When I run `rspec yield_arguments_spec.rb` Then the examples should all pass Scenario: It fails when the caller does not provide a block Given a file named "no_caller_block_spec.rb" with: """ruby RSpec.describe "Making it yield" do it "fails when the caller does not provide a block" do dbl = double allow(dbl).to receive(:foo).and_yield(2, 3) dbl.foo end end """ When I run `rspec no_caller_block_spec.rb` Then it should fail with: """ # asked to yield |[2, 3]| but no block was passed """ Scenario: It fails when the caller's block does not accept the provided arguments Given a file named "arg_mismatch_spec.rb" with: """ruby RSpec.describe "Making it yield" do it "fails when the caller's block does not accept the provided arguments" do dbl = double allow(dbl).to receive(:foo).and_yield(2, 3) dbl.foo { |x| } end end """ When I run `rspec arg_mismatch_spec.rb` Then it should fail with: """ # yielded |2, 3| to block with arity of 1 """ Scenario: Yield multiple times Given a file named "yield_multiple_times_spec.rb" with: """ RSpec.describe "Making it yield multiple times" do it "yields the specified args in succession" do yielded = [] dbl = double allow(dbl).to receive(:foo).and_yield(1).and_yield(2).and_yield(3) dbl.foo { |x| yielded << x } expect(yielded).to eq([1, 2, 3]) end end """ When I run `rspec yield_multiple_times_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/returning_a_value.feature0000664000000000000000000000373714557670305032356 0ustar rootrootFeature: Returning a value Use `and_return` to specify a return value. Pass `and_return` multiple values to specify different return values for consecutive calls. The final value will continue to be returned if the message is received additional times. Note - If you are looking for documentation for configuring responses from `allow_any_instance_of`, please see the [working with legacy code](../working-with-legacy-code/any-instance) documentation. Scenario: Nil is returned by default Given a file named "returns_nil_spec.rb" with: """ruby RSpec.describe "The default response" do it "returns nil when no response has been configured" do dbl = double allow(dbl).to receive(:foo) expect(dbl.foo).to be_nil end end """ When I run `rspec returns_nil_spec.rb` Then the examples should all pass Scenario: Specify a return value Given a file named "and_return_spec.rb" with: """ruby RSpec.describe "Specifying a return value" do it "returns the specified return value" do dbl = double allow(dbl).to receive(:foo).and_return(14) expect(dbl.foo).to eq(14) end end """ When I run `rspec and_return_spec.rb` Then the examples should all pass Scenario: Specify different return values for multiple calls Given a file named "multiple_calls_spec.rb" with: """ruby RSpec.describe "When the method is called multiple times" do it "returns the specified values in order, then keeps returning the last value" do dbl = double allow(dbl).to receive(:foo).and_return(1, 2, 3) expect(dbl.foo).to eq(1) expect(dbl.foo).to eq(2) expect(dbl.foo).to eq(3) expect(dbl.foo).to eq(3) # begins to repeat last value expect(dbl.foo).to eq(3) end end """ When I run `rspec multiple_calls_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/configuring_responses/raising_an_error.feature0000664000000000000000000000156314557670305032163 0ustar rootrootFeature: Raising an error Use `and_raise` to make the test double raise an error when it receives the message. Any of the following forms are supported: * `and_raise(ExceptionClass)` * `and_raise("message")` * `and_raise(ExceptionClass, "message")` * `and_raise(instance_of_an_exception_class)` Scenario: Raising an error Given a file named "raises_an_error_spec.rb" with: """ruby RSpec.describe "Making it raise an error" do it "raises the provided exception" do dbl = double allow(dbl).to receive(:foo).and_raise("boom") dbl.foo end end """ When I run `rspec raises_an_error_spec.rb` Then it should fail with: """ 1) Making it raise an error raises the provided exception Failure/Error: dbl.foo RuntimeError: boom """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/0000775000000000000000000000000014557670305024362 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/partial_doubles.feature0000664000000000000000000000214014557670305031105 0ustar rootrootFeature: Partial doubles When the `verify_partial_doubles` configuration option is set, the same argument and method existence checks that are performed for [`object_double`](./object-doubles) are also performed on [partial doubles](../basics/partial-test-doubles). You should set this unless you have a good reason not to. It defaults to off only for backwards compatibility. Scenario: Doubling an existing object Given a file named "spec/user_spec.rb" with: """ruby class User def save; false; end end def save_user(user) "saved!" if user.save end RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end end RSpec.describe '#save_user' do it 'renders message on success' do user = User.new expect(user).to receive(:wave).and_return(true) # Typo in name expect(save_user(user)).to eq("saved!") end end """ When I run `rspec spec/user_spec.rb` Then the output should contain "1 example, 1 failure" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/dynamic_classes.feature0000664000000000000000000000635114557670305031105 0ustar rootrootFeature: Dynamic classes Verifying instance doubles do not support methods which the class reports to not exist since an actual instance of the class would be required to verify against. This is commonly the case when `method_missing` is used. There are a few ways to work around this. If the object has already been loaded you may consider using an [`object_double`](./object-doubles), but that cannot work if you are testing in isolation. Alternatively you could implement the methods directly (calling `super` to return the `method_missing` definition). Some of these classes may have methods to define these methods on the objects at runtime. (For example, `ActiveRecord` does this to define methods from database columns.) For these cases we provide an API which can be used to customise verifying doubles on creation. We use this ourselves in `rspec-rails` to set up some niceties for you. These types of methods are supported at class level (with `class_double`) however, since `respond_to?` can be queried directly on the class. Background: Given a file named "lib/fake_active_record.rb" with: """ruby class FakeActiveRecord COLUMNS = %w[name email] def respond_to_missing?(method_name) COLUMNS.include?(method_name.to_s) || super end def method_missing(method_name, *args) if respond_to?(method_name) instance_variable_get("@#{method_name}") else super end end def self.define_attribute_methods COLUMNS.each do |name| define_method(name) { instance_variable_get("@#{name}") } end end end """ Given a file named "spec/user_spec.rb" with: """ruby require 'user' RSpec.describe User do it 'can be doubled' do instance_double("User", :name => "Don") end end """ Scenario: Fails with method missing Given a file named "lib/user.rb" with: """ruby require 'fake_active_record' class User < FakeActiveRecord end """ When I run `rspec spec/user_spec.rb` Then the output should contain "1 example, 1 failure" Scenario: Workaround with explicit definitions Given a file named "lib/user.rb" with: """ruby require 'fake_active_record' class User < FakeActiveRecord def name; super end def email; super end end """ When I run `rspec spec/user_spec.rb` Then the examples should all pass Scenario: Workaround using callback Given a file named "lib/user.rb" with: """ruby require 'fake_active_record' class User < FakeActiveRecord end """ And a file named "spec/fake_record_helper.rb" with: """ruby RSpec.configuration.mock_with(:rspec) do |config| config.before_verifying_doubles do |reference| reference.target.define_attribute_methods end end # # or you can use: # # RSpec::Mocks.configuration.before_verifying_doubles do |reference| # reference.target.define_attribute_methods # end """ When I run `rspec -r fake_record_helper spec/user_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/instance_doubles.feature0000664000000000000000000000651114557670305031263 0ustar rootrootFeature: Using an instance double An `instance_double` is the most common type of verifying double. It takes a class name or object as its first argument, then verifies that any methods being stubbed would be present on an _instance_ of that class. In addition, when it receives messages, it verifies that the provided arguments are supported by the method signature, both in terms of arity and allowed or required keyword arguments, if any. The same argument verification happens when you [constrain the arguments](../setting-constraints/matching-arguments) using `with`. For methods handled by `method_missing`, see [dynamic classes](./dynamic-classes). Background: Given a file named "app/models/user.rb" with: """ruby class User < Struct.new(:notifier) def suspend! notifier.notify("suspended as") end end """ Given a file named "spec/unit_helper.rb" with: """ruby $LOAD_PATH.unshift("app/models") """ Given a file named "spec/spec_helper.rb" with: """ruby require 'unit_helper' require 'user' require 'console_notifier' RSpec.configure do |config| config.mock_with :rspec do |mocks| # This option should be set when all dependencies are being loaded # before a spec run, as is the case in a typical spec helper. It will # cause any verifying double instantiation for a class that does not # exist to raise, protecting against incorrectly spelt names. mocks.verify_doubled_constant_names = true end end """ Given a file named "spec/unit/user_spec.rb" with: """ruby require 'unit_helper' require 'user' RSpec.describe User, '#suspend!' do it 'notifies the console' do notifier = instance_double("ConsoleNotifier") expect(notifier).to receive(:notify).with("suspended as") user = User.new(notifier) user.suspend! end end """ Scenario: Spec passes in isolation When I run `rspec spec/unit/user_spec.rb` Then the examples should all pass Scenario: Spec passes with dependencies loaded and method implemented Given a file named "app/models/console_notifier.rb" with: """ruby class ConsoleNotifier def notify(msg) puts message end end """ When I run `rspec -r./spec/spec_helper spec/unit/user_spec.rb` Then the examples should all pass Scenario: Spec fails with dependencies loaded and method unimplemented Given a file named "app/models/console_notifier.rb" with: """ruby class ConsoleNotifier end """ When I run `rspec -r./spec/spec_helper spec/unit/user_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "ConsoleNotifier class does not implement the instance method:" Scenario: Spec fails with dependencies loaded and incorrect arity Given a file named "app/models/console_notifier.rb" with: """ruby class ConsoleNotifier def notify(msg, color) puts color + message end end """ When I run `rspec -r./spec/spec_helper spec/unit/user_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "Wrong number of arguments." ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/class_doubles.feature0000664000000000000000000000424414557670305030565 0ustar rootrootFeature: Using a class double `class_double` is provided as a complement to [`instance_double`](./instance-doubles) with the difference that it verifies _class_ methods on the given class rather than instance methods. In addition, it also provides a convenience method `as_stubbed_const` to replace concrete classes with the defined double. See [mutating constants](../mutating-constants) for more details. Note: `class_double` can be used for modules as well. We chose to stick with the `class_double` terminology because the methods a `class_double` verifies against are commonly called "class methods", not "module methods", even when working with a module. Background: Given a file named "lib/user.rb" with: """ruby class User def suspend! ConsoleNotifier.notify("suspended as") end end """ Given a file named "lib/console_notifier.rb" with: """ruby class ConsoleNotifier MAX_WIDTH = 80 def self.notify(message) puts message end end """ Given a file named "spec/user_spec.rb" with: """ruby require 'user' require 'console_notifier' RSpec.describe User, '#suspend!' do it 'notifies the console' do notifier = class_double("ConsoleNotifier"). as_stubbed_const(:transfer_nested_constants => true) expect(notifier).to receive(:notify).with("suspended as") expect(ConsoleNotifier::MAX_WIDTH).to eq(80) user = User.new user.suspend! end end """ Scenario: Replacing existing constants When I run `rspec spec/user_spec.rb` Then the examples should all pass Scenario: Renaming `ConsoleNotifier.notify` to `send_notification` Given a file named "lib/console_notifier.rb" with: """ruby class ConsoleNotifier MAX_WIDTH = 80 def self.send_notification(message) puts message end end """ When I run `rspec spec/user_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "the ConsoleNotifier class does not implement the class method:" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/README.md0000664000000000000000000000163514557670305025646 0ustar rootroot# Verifying doubles Verifying doubles are a stricter alternative to [normal doubles](./basics/test-doubles) that provide guarantees about what is being verified. When using verifying doubles, RSpec will check that the methods being stubbed are actually present on the underlying object if it is available. Prefer using verifying doubles over normal doubles. No checking will happen if the underlying object or class is not defined, but when run with it present (either as a full spec run or by explicitly preloading collaborators) a failure will be triggered if an invalid method is being stubbed or a method is called with an invalid number of arguments. This dual approach allows you to move very quickly and test components in isolation, while giving you confidence that your doubles are not a complete fiction. Testing in isolation is optional but recommended for classes that do not depend on third-party components. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/verifying_doubles/object_doubles.feature0000664000000000000000000000425414557670305030727 0ustar rootrootFeature: Using an object double `object_double` can be used to create a double from an existing "template" object, from which it verifies that any stubbed methods on the double also exist on the template. This is useful for objects that are readily constructable, but may have far-reaching side-effects such as talking to a database or external API. In this case, using a double rather than the real thing allows you to focus on the communication patterns of the object's interface without having to worry about accidentally causing side-effects. Object doubles can also be used to verify methods defined on an object using `method_missing`, which is not possible with [`instance_double`](./instance-doubles). In addition, `object_double` can be used with specific constant values, as shown below. This is for niche situations, such as when dealing with singleton objects. Scenario: Doubling an existing object Given a file named "spec/user_spec.rb" with: """ruby class User # Don't want to accidentally trigger this! def save; sleep 100; end end def save_user(user) "saved!" if user.save end RSpec.describe '#save_user' do it 'renders message on success' do user = object_double(User.new, :save => true) expect(save_user(user)).to eq("saved!") end end """ When I run `rspec spec/user_spec.rb` Then the examples should all pass Scenario: Doubling a constant object Given a file named "spec/email_spec.rb" with: """ruby require 'logger' module MyApp LOGGER = Logger.new("myapp") end class Email def self.send_to(recipient) MyApp::LOGGER.info("Sent to #{recipient}") # other emailing logic end end RSpec.describe Email do it 'logs a message when sending' do logger = object_double("MyApp::LOGGER", :info => nil).as_stubbed_const Email.send_to('hello@foo.com') expect(logger).to have_received(:info).with("Sent to hello@foo.com") end end """ When I run `rspec spec/email_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/setting_constraints/0000775000000000000000000000000014557670305024747 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/setting_constraints/matching_arguments.feature0000664000000000000000000002525614557670305032215 0ustar rootrootFeature: Matching arguments Use `with` to specify the expected arguments. A [message expectation](../basics/expecting-messages) constrained by `with` will only be satisfied when called with matching arguments. A canned response for an [allowed message](../basics/allowing-messages) will only be used when the arguments match. | To match... | ...use an expression like: | ...which matches calls like: | |-----------------------------------------------------|------------------------------------|-----------------------------------------------------| | Literal arguments | `with(1, true)` | `foo(1, true)` | | Literal arguments where one is a hash | `with(1, {x: 1, y: 2})` | `foo(1, x: 1, y: 2) (where last argument is a hash) | | Keyword arguments | `with(x: 1, y: 2)` | `foo(x: 1, y: 2)` (where x and y are keywords) | | Anything that supports case equality (`===`) | `with(/bar/)` | `foo("barn")` | | Any list of args | `with(any_args)` | `foo()`
`foo(1)`
`foo(:bar, 2)` | | Any sublist of args (like an arg splat) | `with(1, any_args)` | `foo(1)`
`foo(1, :bar, :bazz)` | | An empty list of args | `with(no_args)` | `foo()` | | Anything for a given positional arg | `with(3, anything)` | `foo(3, nil)`
`foo(3, :bar)` | | Against an interface | `with(duck_type(:each))` | `foo([])` | | A boolean | `with(3, boolean)` | `foo(3, true)`
`foo(3, false)` | | A subset of a hash | `with(hash_including(:a => 1))` | `foo(:a => 1, :b => 2)` | | An excluded subset of a hash | `with(hash_excluding(:a => 1))` | `foo(:b => 2)` | | A subset of an array | `with(array_including(:a, :b))` | `foo([:a, :b, :c])` | | An excluded subset of an array | `with(array_excluding(:a, :b))` | `foo([:c, :d])` | | An instance of a specific class | `with(instance_of(Integer))` | `foo(3)` | | An object with a given module in its ancestors list | `with(kind_of(Numeric))` | `foo(3)` | | An object with matching attributes | `with(having_attributes(:a => 1))` | `foo(:a => 1, :b => 2)` | | Any RSpec matcher | `with()` | `foo()` | Scenario: Basic example Given a file named "basic_example_spec.rb" with: """ruby RSpec.describe "Constraining a message expectation using with" do let(:dbl) { double } before { expect(dbl).to receive(:foo).with(1, anything, /bar/) } it "passes when the args match" do dbl.foo(1, nil, "barn") end it "fails when the args do not match" do dbl.foo(1, nil, "other") end end """ When I run `rspec basic_example_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | Failure/Error: dbl.foo(1, nil, "other") | | # received :foo with unexpected arguments | | expected: (1, anything, /bar/) | | got: (1, nil, "other") | @kw-arguments Scenario: Using keyword arguments Given a file named "keyword_example_spec.rb" with: """ruby class WithKeywords def foo(bar: "") end end RSpec.describe "Constraining a message expectation using with" do let(:dbl) { instance_double(WithKeywords) } before { expect(dbl).to receive(:foo).with(bar: "baz") } it "passes when the args match" do dbl.foo(bar: "baz") end it "fails when the args do not match" do dbl.foo(bar: "incorrect") end end """ When I run `rspec keyword_example_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | Failure/Error: dbl.foo(bar: "incorrect") | | # received :foo with unexpected arguments | | expected: ({:bar=>"baz"}) | | got: ({:bar=>"incorrect"}) | @distincts_kw_args_from_positional_hash Scenario: Using keyword arguments on Rubies that differentiate hashes from keyword arguments Given a file named "keyword_example_spec.rb" with: """ruby class WithKeywords def foo(bar: "") end end RSpec.describe "Constraining a message expectation using with" do let(:dbl) { instance_double(WithKeywords) } before { expect(dbl).to receive(:foo).with(bar: "baz") } it "fails when the args do not match due to a hash" do dbl.foo({bar: "also incorrect"}) end end """ When I run `rspec keyword_example_spec.rb` Then it should fail with the following output: | 1 example, 1 failure | | | | Failure/Error: dbl.foo({bar: "also incorrect"}) | | # received :foo with unexpected arguments | | expected: ({:bar=>"baz"}) (keyword arguments) | | got: ({:bar=>"also incorrect"}) (options hash) | Scenario: Using a RSpec matcher Given a file named "rspec_matcher_spec.rb" with: """ruby RSpec.describe "Using a RSpec matcher" do let(:dbl) { double } before { expect(dbl).to receive(:foo).with(a_collection_containing_exactly(1, 2)) } it "passes when the args match" do dbl.foo([2, 1]) end it "fails when the args do not match" do dbl.foo([1, 3]) end end """ When I run `rspec rspec_matcher_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | Failure/Error: dbl.foo([1, 3]) | | # received :foo with unexpected arguments | | expected: (a collection containing exactly 1 and 2) | | got: ([1, 3]) | @ripper Scenario: Using satisfy for complex custom expecations Given a file named "rspec_satisfy_spec.rb" with: """ruby RSpec.describe "Using satisfy for complex custom expecations" do let(:dbl) { double } def a_b_c_equals_5 satisfy { |data| data[:a][:b][:c] == 5 } end it "passes when the expectation is true" do expect(dbl).to receive(:foo).with(a_b_c_equals_5) dbl.foo({ :a => { :b => { :c => 5 } } }) end it "fails when the expectation is false" do expect(dbl).to receive(:foo).with(a_b_c_equals_5) dbl.foo({ :a => { :b => { :c => 3 } } }) end end """ When I run `rspec rspec_satisfy_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | Failure/Error: dbl.foo({ :a => { :b => { :c => 3 } } }) | | # received :foo with unexpected arguments | | expected: (satisfy expression `data[:a][:b][:c] == 5`) | | got: ({:a=>{:b=>{:c=>3}}}) | Scenario: Using a custom matcher Given a file named "custom_matcher_spec.rb" with: """ruby RSpec::Matchers.define :a_multiple_of do |x| match { |actual| (actual % x).zero? } end RSpec.describe "Using a custom matcher" do let(:dbl) { double } before { expect(dbl).to receive(:foo).with(a_multiple_of(3)) } it "passes when the args match" do dbl.foo(12) end it "fails when the args do not match" do dbl.foo(13) end end """ When I run `rspec custom_matcher_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | Failure/Error: dbl.foo(13) | | # received :foo with unexpected arguments | | expected: (a multiple of 3) | | got: (13) | Scenario: Responding differently based on the arguments Given a file named "responding_differently_spec.rb" with: """ruby RSpec.describe "Using #with to constrain responses" do specify "its response depends on the arguments" do dbl = double # Set a default for any unmatched args allow(dbl).to receive(:foo).and_return(:default) allow(dbl).to receive(:foo).with(1).and_return(1) allow(dbl).to receive(:foo).with(2).and_return(2) expect(dbl.foo(0)).to eq(:default) expect(dbl.foo(1)).to eq(1) expect(dbl.foo(2)).to eq(2) end end """ When I run `rspec responding_differently_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/setting_constraints/receive_counts.feature0000664000000000000000000001467414557670305031355 0ustar rootrootFeature: Receive Counts When [expecting a message](../basics/expecting-messages), you can specify how many times you expect the message to be received: * `expect(...).to receive(...).once` * `expect(...).to receive(...).twice` * `expect(...).to receive(...).exactly(n).time` * `expect(...).to receive(...).exactly(n).times` * `expect(...).to receive(...).at_least(:once)` * `expect(...).to receive(...).at_least(:twice)` * `expect(...).to receive(...).at_least(n).time` * `expect(...).to receive(...).at_least(n).times` * `expect(...).to receive(...).at_most(:once)` * `expect(...).to receive(...).at_most(:twice)` * `expect(...).to receive(...).at_most(n).time` * `expect(...).to receive(...).at_most(n).times` If you don't specify an expected receive count, it defaults to `once`. Background: Given a file named "lib/account.rb" with: """ruby class Account def initialize(logger) @logger = logger end def open @logger.account_opened end end """ Scenario: Passing examples Given a file named "spec/account_spec.rb" with: """ruby require 'account' RSpec.describe Account do let(:logger) { double("Logger") } let(:account) { Account.new(logger) } example "once" do expect(logger).to receive(:account_opened).once account.open end example "twice" do expect(logger).to receive(:account_opened).twice account.open account.open end example "exactly(n).time" do expect(logger).to receive(:account_opened).exactly(1).time account.open end example "exactly(n).times" do expect(logger).to receive(:account_opened).exactly(3).times account.open account.open account.open end example "at_least(:once)" do expect(logger).to receive(:account_opened).at_least(:once) account.open account.open end example "at_least(:twice)" do expect(logger).to receive(:account_opened).at_least(:twice) account.open account.open account.open end example "at_least(n).time" do expect(logger).to receive(:account_opened).at_least(1).time account.open end example "at_least(n).times" do expect(logger).to receive(:account_opened).at_least(3).times account.open account.open account.open account.open end example "at_most(:once)" do expect(logger).to receive(:account_opened).at_most(:once) end example "at_most(:twice)" do expect(logger).to receive(:account_opened).at_most(:twice) account.open end example "at_most(n).time" do expect(logger).to receive(:account_opened).at_most(1).time account.open end example "at_most(n).times" do expect(logger).to receive(:account_opened).at_most(3).times account.open account.open end end """ When I run `rspec spec/account_spec.rb` Then the examples should all pass Scenario: Failing examples Given a file named "spec/account_spec.rb" with: """ruby require 'account' RSpec.describe Account do let(:logger) { double("Logger") } let(:account) { Account.new(logger) } example "once" do expect(logger).to receive(:account_opened).once account.open account.open end example "twice" do expect(logger).to receive(:account_opened).twice account.open end example "exactly(n).times" do expect(logger).to receive(:account_opened).exactly(3).times account.open account.open end example "at_least(:once)" do expect(logger).to receive(:account_opened).at_least(:once) end example "at_least(:twice)" do expect(logger).to receive(:account_opened).at_least(:twice) account.open end example "at_least(n).times" do expect(logger).to receive(:account_opened).at_least(3).times account.open account.open end example "at_most(:once)" do expect(logger).to receive(:account_opened).at_most(:once) account.open account.open end example "at_most(:twice)" do expect(logger).to receive(:account_opened).at_most(:twice) account.open account.open account.open end example "at_most(n).times" do expect(logger).to receive(:account_opened).at_most(3).times account.open account.open account.open account.open end end """ When I run `rspec spec/account_spec.rb --order defined` Then the examples should all fail, producing the following output: | expected: 1 time with any arguments | | received: 2 times | | | | expected: 2 times with any arguments | | received: 1 time with any arguments | | | | expected: 3 times with any arguments | | received: 2 times with any arguments | | | | expected: at least 1 time with any arguments | | received: 0 times with any arguments | | | | expected: at least 2 times with any arguments | | received: 1 time with any arguments | | | | expected: at least 3 times with any arguments | | received: 2 times with any arguments | | | | expected: at most 1 time with any arguments | | received: 2 times | | | | expected: at most 2 times with any arguments | | received: 3 times | | | | expected: at most 3 times with any arguments | | received: 4 times | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/setting_constraints/message_order.feature0000664000000000000000000000541314557670305031146 0ustar rootrootFeature: Message Order You can use `ordered` to constrain the order of multiple message expectations. This is not generally recommended because in most situations the order doesn't matter and using `ordered` would make your spec brittle, but it's occasionally useful. When you use `ordered`, the example will only pass if the messages are received in the declared order. Scenario: Passing example Given a file named "passing_example_spec.rb" with: """ruby RSpec.describe "Constraining order" do it "passes when the messages are received in declared order" do collaborator_1 = double("Collaborator 1") collaborator_2 = double("Collaborator 2") expect(collaborator_1).to receive(:step_1).ordered expect(collaborator_2).to receive(:step_2).ordered expect(collaborator_1).to receive(:step_3).ordered collaborator_1.step_1 collaborator_2.step_2 collaborator_1.step_3 end end """ When I run `rspec passing_example_spec.rb` Then the examples should all pass Scenario: Failing examples Given a file named "failing_examples_spec.rb" with: """ruby RSpec.describe "Constraining order" do it "fails when messages are received out of order on one collaborator" do collaborator_1 = double("Collaborator 1") expect(collaborator_1).to receive(:step_1).ordered expect(collaborator_1).to receive(:step_2).ordered collaborator_1.step_2 collaborator_1.step_1 end it "fails when messages are received out of order between collaborators" do collaborator_1 = double("Collaborator 1") collaborator_2 = double("Collaborator 2") expect(collaborator_1).to receive(:step_1).ordered expect(collaborator_2).to receive(:step_2).ordered collaborator_2.step_2 collaborator_1.step_1 end end """ When I run `rspec failing_examples_spec.rb --order defined` Then the examples should all fail, producing the following output: | 1) Constraining order fails when messages are received out of order on one collaborator | | Failure/Error: collaborator_1.step_2 | | # received :step_2 out of order | | | | 2) Constraining order fails when messages are received out of order between collaborators | | Failure/Error: collaborator_2.step_2 | | # received :step_2 out of order | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/setting_constraints/README.md0000664000000000000000000000053214557670305026226 0ustar rootroot# Setting Constraints RSpec provides a fluent interface off of `expect(...).to receive(...)` that allows you to further constrain what you expect: the arguments, the number of times, and the ordering of multiple messages. Although not shown here, this fluent interface is also supported by [spies](./basics/spies), off of `have_received(...)`. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/0000775000000000000000000000000014557670305022107 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/null_object_doubles.feature0000664000000000000000000000260114557670305027500 0ustar rootrootFeature: Null object doubles [Test doubles](./test-doubles) are strict by default, raising errors when they receive messages that have not been allowed or expected. You can chain `as_null_object` off of `double` in order to make the double "loose". For any message that has not explicitly allowed or expected, the double will return itself. It acts as a black hole null object, allowing arbitrarily deep method chains. Scenario: `as_null_object` allows arbitrarily deep message chains and returns itself Given a file named "as_null_object_spec.rb" with: """ruby RSpec.describe "as_null_object" do it "returns itself" do dbl = double("Some Collaborator").as_null_object expect(dbl.foo.bar.bazz).to be(dbl) end end """ When I run `rspec as_null_object_spec.rb` Then the examples should all pass Scenario: Individual methods can still be allowed or expected Given a file named "as_null_object_spec.rb" with: """ruby RSpec.describe "as_null_object" do it "can allow individual methods" do dbl = double("Some Collaborator", :foo => 3).as_null_object allow(dbl).to receive(:bar).and_return(4) expect(dbl.foo).to eq(3) expect(dbl.bar).to eq(4) end end """ When I run `rspec as_null_object_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/test_doubles.feature0000664000000000000000000000320514557670305026160 0ustar rootrootFeature: Test Doubles _Test double_ is a generic term for any object that stands in for a real object during a test (think "stunt double"). You create one using the `double` method. Doubles are "strict" by default -- any message you have not allowed or expected will trigger an error -- but you can [switch a double to being "loose"](./null-object-doubles). When creating a double, you can allow messages (and set their return values) by passing a hash. Once you have a test double, you can [allow](./allowing-messages) or [expect](./expecting-messages) messages on it. We recommend you use [verifying doubles](../verifying-doubles) whenever possible. Scenario: Doubles are strict by default Given a file named "double_spec.rb" with: """ruby RSpec.describe "A test double" do it "raises errors when messages not allowed or expected are received" do dbl = double("Some Collaborator") dbl.foo end end """ When I run `rspec double_spec.rb` Then it should fail with: """ # received unexpected message :foo with (no args) """ Scenario: A hash can be used to define allowed messages and return values Given a file named "double_spec.rb" with: """ruby RSpec.describe "A test double" do it "returns canned responses from the methods named in the provided hash" do dbl = double("Some Collaborator", :foo => 3, :bar => 4) expect(dbl.foo).to eq(3) expect(dbl.bar).to eq(4) end end """ When I run `rspec double_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/spies.feature0000664000000000000000000001327414557670305024616 0ustar rootrootFeature: Spies [Message expectations](./expecting-messages) put an example's expectation at the start, before you've invoked the code-under-test. Many developers prefer using an arrange-act-assert (or given-when-then) pattern for structuring tests. Spies are an alternate type of test double that support this pattern by allowing you to expect that a message has been received after the fact, using `have_received`. You can use any test double (or partial double) as a spy, but the double must be setup to spy on the messages you care about. Spies automatically spy on all messages, or you can [allow a message](./allowing-messages) to spy on it. `have_received` supports the same fluent interface for [setting constraints](../setting-constraints) that normal message expectations do. Note: The `have_received` API shown here will only work if you are using rspec-expectations. Note: `have_received(...).with(...)` is unable to work properly when passed arguments are mutated after the spy records the received message. Scenario: Using a spy Given a file named "spy_spec.rb" with: """ruby RSpec.describe "have_received" do it "passes when the message has been received" do invitation = spy('invitation') invitation.deliver expect(invitation).to have_received(:deliver) end end """ When I run `rspec spy_spec.rb` Then the examples should all pass Scenario: Spy on a method on a partial double Given a file named "partial_double_spy_spec.rb" with: """ruby class Invitation def self.deliver; end end RSpec.describe "have_received" do it "passes when the expectation is met" do allow(Invitation).to receive(:deliver) Invitation.deliver expect(Invitation).to have_received(:deliver) end end """ When I run `rspec partial_double_spy_spec.rb` Then the examples should all pass Scenario: Failure when the message has not been received Given a file named "failure_spec.rb" with: """ruby class Invitation def self.deliver; end end RSpec.describe "failure when the message has not been received" do example "for a spy" do invitation = spy('invitation') expect(invitation).to have_received(:deliver) end example "for a partial double" do allow(Invitation).to receive(:deliver) expect(Invitation).to have_received(:deliver) end end """ When I run `rspec failure_spec.rb --order defined` Then it should fail with: """ 1) failure when the message has not been received for a spy Failure/Error: expect(invitation).to have_received(:deliver) (Double "invitation").deliver(*(any args)) expected: 1 time with any arguments received: 0 times with any arguments """ And it should fail with: """ 2) failure when the message has not been received for a partial double Failure/Error: expect(Invitation).to have_received(:deliver) (Invitation (class)).deliver(*(any args)) expected: 1 time with any arguments received: 0 times with any arguments """ Scenario: Set constraints using the fluent interface Given a file named "setting_constraints_spec.rb" with: """ruby RSpec.describe "An invitation" do let(:invitation) { spy("invitation") } before do invitation.deliver("foo@example.com") invitation.deliver("bar@example.com") end it "passes when a count constraint is satisfied" do expect(invitation).to have_received(:deliver).twice end it "passes when an order constraint is satisfied" do expect(invitation).to have_received(:deliver).with("foo@example.com").ordered expect(invitation).to have_received(:deliver).with("bar@example.com").ordered end it "fails when a count constraint is not satisfied" do expect(invitation).to have_received(:deliver).at_least(3).times end it "fails when an order constraint is not satisfied" do expect(invitation).to have_received(:deliver).with("bar@example.com").ordered expect(invitation).to have_received(:deliver).with("foo@example.com").ordered end end """ When I run `rspec setting_constraints_spec.rb --order defined` Then it should fail with the following output: | 4 examples, 2 failures | | | | 1) An invitation fails when a count constraint is not satisfied | | Failure/Error: expect(invitation).to have_received(:deliver).at_least(3).times | | (Double "invitation").deliver(*(any args)) | | expected: at least 3 times with any arguments | | received: 2 times with any arguments | | | | 2) An invitation fails when an order constraint is not satisfied | | Failure/Error: expect(invitation).to have_received(:deliver).with("foo@example.com").ordered | | # received :deliver out of order | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/scope.feature0000664000000000000000000000726114557670305024603 0ustar rootrootFeature: Scope All rspec-mocks constructs have a per-example lifecycle. Message expectations are verified after each example. Doubles, method stubs, stubbed constants, etc. are all cleaned up after each example. This ensures that each example can be run in isolation, and in any order. It is perfectly fine to set up doubles, stubs, and message expectations in a `before(:example)` hook, as that hook is executed in the scope of the example: ```ruby before(:example) do allow(MyClass).to receive(:foo) end ``` Since `before(:context)` runs outside the scope of any individual example, usage of rspec-mocks features is not supported there. You can, however, create a temporary scope in _any_ arbitrary context, including in a `before(:context)` hook, using `RSpec::Mocks.with_temporary_scope { }`. Scenario: Cannot create doubles in a `before(:context)` hook Given a file named "before_context_spec.rb" with: """ruby RSpec.describe "Creating a double in a before(:context) hook" do before(:context) do @dbl = double(:foo => 13) end it "fails before it gets to the examples" do expect(@dbl.foo).to eq(13) end end """ When I run `rspec before_context_spec.rb` Then it should fail with: """ The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported. """ Scenario: Use `with_temporary_scope` to create and use a double in a `before(:context)` hook Given a file named "with_temporary_scope_spec.rb" with: """ruby RSpec.describe "Creating a double in a before(:context) hook" do before(:context) do RSpec::Mocks.with_temporary_scope do dbl = double(:foo => 13) @result = dbl.foo end end it "allows a double to be created and used from within a with_temporary_scope block" do expect(@result).to eq(13) end end """ When I run `rspec with_temporary_scope_spec.rb` Then the examples should all pass Scenario: Doubles cannot be reused in another example Given a file named "leak_test_double_spec.rb" with: """ruby class Account class << self attr_accessor :logger end def initialize @balance = 0 end attr_reader :balance def credit(amount) @balance += amount self.class.logger.log("Credited $#{amount}") end end RSpec.describe Account do it "logs each credit" do Account.logger = logger = double("Logger") expect(logger).to receive(:log).with("Credited $15") account = Account.new account.credit(15) end it "keeps track of the balance" do account = Account.new expect { account.credit(10) }.to change { account.balance }.by(10) end end """ When I run `rspec leak_test_double_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | | | 1) Account keeps track of the balance | | Failure/Error: self.class.logger.log("Credited $#{amount}") | | # was originally created in one example but has leaked into another example and can no longer be used. | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/allowing_messages.feature0000664000000000000000000000253214557670305027171 0ustar rootrootFeature: Allowing messages [Test doubles](./test-doubles) are "strict" by default -- messages that have not been specifically allowed or expected will trigger an error. Use `allow(...).to receive(...)` to configure which messages the double is allowed to receive. You can also use `allow(...).to receive_messages(...)` to configure allowed messages (and return values) in bulk. Scenario: Allowed messages return nil by default Given a file named "allow_message_spec.rb" with: """ruby RSpec.describe "allow" do it "returns nil from allowed messages" do dbl = double("Some Collaborator") allow(dbl).to receive(:foo) expect(dbl.foo).to be_nil end end """ When I run `rspec allow_message_spec.rb` Then the examples should all pass Scenario: Messages can be allowed in bulk using `receive_messages` Given a file named "receive_messages_spec.rb" with: """ruby RSpec.describe "receive_messages" do it "configures return values for the provided messages" do dbl = double("Some Collaborator") allow(dbl).to receive_messages(:foo => 2, :bar => 3) expect(dbl.foo).to eq(2) expect(dbl.bar).to eq(3) end end """ When I run `rspec receive_messages_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/expecting_messages.feature0000664000000000000000000000773114557670305027351 0ustar rootrootFeature: Expecting messages Use `expect(...).to receive(...)` to expect a message on a [test double](./test-doubles). Unfulfilled message expectations trigger failures when the example completes. You can also use `expect(...).not_to receive(...)` to set a negative message expectation. Scenario: Failing positive message expectation Given a file named "unfulfilled_message_expectation_spec.rb" with: """ruby RSpec.describe "An unfulfilled positive message expectation" do it "triggers a failure" do dbl = double("Some Collaborator") expect(dbl).to receive(:foo) end end """ When I run `rspec unfulfilled_message_expectation_spec.rb` Then it should fail with: """ 1) An unfulfilled positive message expectation triggers a failure Failure/Error: expect(dbl).to receive(:foo) (Double "Some Collaborator").foo(*(any args)) expected: 1 time with any arguments received: 0 times with any arguments """ Scenario: Passing positive message expectation Given a file named "fulfilled_message_expectation_spec.rb" with: """ruby RSpec.describe "A fulfilled positive message expectation" do it "passes" do dbl = double("Some Collaborator") expect(dbl).to receive(:foo) dbl.foo end end """ When I run `rspec fulfilled_message_expectation_spec.rb` Then the examples should all pass Scenario: Failing negative message expectation Given a file named "negative_message_expectation_spec.rb" with: """ruby RSpec.describe "A negative message expectation" do it "fails when the message is received" do dbl = double("Some Collaborator").as_null_object expect(dbl).not_to receive(:foo) dbl.foo end end """ When I run `rspec negative_message_expectation_spec.rb` Then it should fail with: """ 1) A negative message expectation fails when the message is received Failure/Error: dbl.foo (Double "Some Collaborator").foo(no args) expected: 0 times with any arguments received: 1 time """ Scenario: Passing negative message expectation Given a file named "negative_message_expectation_spec.rb" with: """ruby RSpec.describe "A negative message expectation" do it "passes if the message is never received" do dbl = double("Some Collaborator").as_null_object expect(dbl).not_to receive(:foo) end end """ When I run `rspec negative_message_expectation_spec.rb` Then the examples should all pass Scenario: Failing positive message expectation with a custom failure message Given a file named "example_spec.rb" with: """ruby RSpec.describe "An unfulfilled positive message expectation" do it "triggers a failure" do dbl = double expect(dbl).to receive(:foo), "dbl never calls :foo" end end """ When I run `rspec example_spec.rb --format documentation` Then the output should contain: """ 1) An unfulfilled positive message expectation triggers a failure Failure/Error: expect(dbl).to receive(:foo), "dbl never calls :foo" dbl never calls :foo """ Scenario: Failing negative message expectation with a custom failure message Given a file named "example_spec.rb" with: """ruby RSpec.describe "A negative message expectation" do it "fails when the message is received" do dbl = double expect(dbl).not_to receive(:foo), "dbl called :foo but is not supposed to" dbl.foo end end """ When I run `rspec example_spec.rb --format documentation` Then the output should contain: """ 1) A negative message expectation fails when the message is received Failure/Error: dbl.foo dbl called :foo but is not supposed to """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/basics/partial_test_doubles.feature0000664000000000000000000000464214557670305027702 0ustar rootrootFeature: Partial test doubles A _partial test double_ is an extension of a real object in a system that is instrumented with test-double like behaviour in the context of a test. This technique is very common in Ruby because we often see class objects acting as global namespaces for methods. For example, in Rails: ```ruby person = double("person") allow(Person).to receive(:find) { person } ``` In this case we're instrumenting Person to return the person object we've defined whenever it receives the `find` message. We can also set a message expectation so that the example fails if `find` is not called: ```ruby person = double("person") expect(Person).to receive(:find) { person } ``` RSpec replaces the method we're stubbing or mocking with its own test-double like method. At the end of the example, RSpec verifies any message expectations, and then restores the original methods. Note: we recommend enabling the [`verify_partial_doubles`](../verifying-doubles/partial-doubles) config option. Scenario: Only the specified methods are redefined Given a file named "partial_double_spec.rb" with: """ruby RSpec.describe "A partial double" do # Note: stubbing a string like this is a terrible idea. # This is just for demonstration purposes. let(:string) { "a string" } before { allow(string).to receive(:length).and_return(500) } it "redefines the specified methods" do expect(string.length).to eq(500) end it "does not effect other methods" do expect(string.reverse).to eq("gnirts a") end end """ When I run `rspec partial_double_spec.rb` Then the examples should all pass Scenario: The original method is restored when the example completes Given a file named "partial_double_spec.rb" with: """ruby class User def self.find(id) :original_return_value end end RSpec.describe "A partial double" do it "redefines a method" do allow(User).to receive(:find).and_return(:redefined) expect(User.find(3)).to eq(:redefined) end it "restores the redefined method after the example completes" do expect(User.find(3)).to eq(:original_return_value) end end """ When I run `rspec partial_double_spec.rb --order defined` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/README.md0000664000000000000000000000542214557670305022125 0ustar rootroot# RSpec Mocks rspec-mocks helps to control the context in a code example by letting you set known return values, fake implementations of methods, and even set expectations that specific messages are received by an object. You can do these three things on test doubles that rspec-mocks creates for you on the fly, or you can do them on objects that are part of your system. ## Messages and Methods _Message_ and _method_ are metaphors that we use somewhat interchangeably, but they are subtly different. In Object Oriented Programming, objects communicate by sending _messages_ to one another. When an object receives a message, it invokes a _method_ with the same name as the message. ## Test Doubles A test double is an object that stands in for another object in your system during a code example. Use the `double` method, passing in an optional identifier, to create one: ```ruby book = double("book") ``` Most of the time you will want some confidence that your doubles resemble an existing object in your system. Verifying doubles are provided for this purpose. If the existing object is available, they will prevent you from adding stubs and expectations for methods that do not exist or that have invalid arguments. ```ruby book = instance_double("Book", :pages => 250) ``` [Verifying doubles](./rspec-mocks/verifying-doubles) have some clever tricks to enable you to both test in isolation without your dependencies loaded while still being able to validate them against real objects. ## Method Stubs A method stub is an instruction to an object (real or test double) to return a known value in response to a message: ```ruby allow(die).to receive(:roll) { 3 } ``` This tells the `die` object to return the value `3` when it receives the `roll` message. ## Message Expectations A message expectation is an expectation that an object should receive a specific message during the course of a code example: ```ruby describe Account do context "when closed" do it "logs an 'account closed' message" do logger = double() account = Account.new account.logger = logger expect(logger).to receive(:account_closed).with(account) account.close end end end ``` This example specifies that the `account` object sends the `logger` the `account_closed` message (with itself as an argument) when it receives the `close` message. ## Issues The documentation for rspec-mocks is a work in progress. We'll be adding Cucumber features over time, and clarifying existing ones. If you have specific features you'd like to see added, find the existing documentation incomplete or confusing, or, better yet, wish to write a missing Cucumber feature yourself, please [submit an issue](http://github.com/rspec/rspec-mocks/issues) or a [pull request](http://github.com/rspec/rspec-mocks). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/support/0000775000000000000000000000000014557670305022357 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/support/env.rb0000664000000000000000000000271014557670305023474 0ustar rootrootrequire 'aruba/cucumber' require 'rspec/expectations' Aruba.configure do |config| if RUBY_PLATFORM =~ /java/ || defined?(Rubinius) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'truffleruby') config.exit_timeout = 60 else config.exit_timeout = 5 end end Before do if RUBY_PLATFORM == 'java' # disable JIT since these processes are so short lived set_environment_variable('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") end if defined?(Rubinius) # disable JIT since these processes are so short lived set_environment_variable('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") end end Before('@ripper') do |scenario| unless RSpec::Support::RubyFeatures.ripper_supported? warn "Skipping scenario due to lack of Ripper support" if Cucumber::VERSION.to_f >= 3.0 skip_this_scenario else scenario.skip_invoke! end end end Before('@kw-arguments') do |scenario| unless RSpec::Support::RubyFeatures.kw_args_supported? warn "Skipping scenario due to lack of keyword argument support" if Cucumber::VERSION.to_f >= 3.0 skip_this_scenario else scenario.skip_invoke! end end end Before('@distincts_kw_args_from_positional_hash') do |scenario| unless RSpec::Support::RubyFeatures. distincts_kw_args_from_positional_hash? warn "Skipping scenario due to not applicable to this ruby" if Cucumber::VERSION.to_f >= 3.0 skip_this_scenario else scenario.skip_invoke! end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/support/rubinius.rb0000664000000000000000000000034214557670305024543 0ustar rootroot# Required until https://github.com/rubinius/rubinius/issues/2430 is resolved ENV['RBXOPT'] = "#{ENV["RBXOPT"]} -Xcompiler.no_rbc" Around "@unsupported-on-rbx" do |_scenario, block| block.call unless defined?(Rubinius) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/support/disallow_certain_apis.rb0000664000000000000000000000132514557670305027244 0ustar rootroot# This file is designed to prevent the use of certain APIs that # we don't want used from our cukes, since they function as documentation. if defined?(Cucumber) require 'shellwords' tag = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') ? '~@allow-old-syntax' : 'not @allow-old-syntax' Before(tag) do set_environment_variable('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}") end else module DisallowOneLinerShould def should(*) raise "one-liner should is not allowed" end def should_not(*) raise "one-liner should_not is not allowed" end end RSpec.configure do |rspec| rspec.disable_monkey_patching! rspec.include DisallowOneLinerShould end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/outside_rspec/0000775000000000000000000000000014557670305023513 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/outside_rspec/minitest.feature0000664000000000000000000002371314557670305026732 0ustar rootrootFeature: Integrating with Minitest To use rspec-mocks with minitest, simply require `rspec/mocks/minitest_integration`. Scenario: Use rspec-mocks with Minitest::Test Given a file named "test/rspec_mocks_test.rb" with: """ruby require 'minitest/autorun' require 'rspec/mocks/minitest_integration' class RSpecMocksTest < Minitest::Test def test_passing_positive_expectation dbl = double expect(dbl).to receive(:message) dbl.message end def test_failing_positive_expectation dbl = double expect(dbl).to receive(:message) end def test_passing_negative_expectation dbl = double expect(dbl).to_not receive(:message) end def test_failing_negative_expectation dbl = double expect(dbl).to_not receive(:message) dbl.message end def test_passing_positive_spy_expectation bond = spy bond.james expect(bond).to have_received(:james) end def test_failing_positive_spy_expectation bond = spy expect(bond).to have_received(:james) end def test_passing_negative_spy_expectation bond = spy expect(bond).not_to have_received(:james) end def test_failing_negative_spy_expectation bond = spy bond.james expect(bond).not_to have_received(:james) end end """ When I run `ruby test/rspec_mocks_test.rb --seed 0` Then it should fail with the following output: | 1) Failure: | | RSpecMocksTest#test_failing_positive_expectation | | (Double (anonymous)).message(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 2) Failure: | | RSpecMocksTest#test_failing_negative_expectation | | (Double (anonymous)).message(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 3) Failure: | | RSpecMocksTest#test_failing_positive_spy_expectation | | (Double (anonymous)).james(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 4) Failure: | | RSpecMocksTest#test_failing_negative_spy_expectation | | (Double (anonymous)).james(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 8 runs, 0 assertions, 4 failures, 0 errors, 0 skips | Scenario: Use rspec-mocks with Minitest::Spec Given a file named "spec/rspec_mocks_spec.rb" with: """ruby require 'minitest/autorun' require 'minitest/spec' require 'rspec/mocks/minitest_integration' describe "Minitest Spec integration" do it 'passes a positive expectation' do dbl = double expect(dbl).to receive(:message) dbl.message end it 'fails a positive expectation' do dbl = double expect(dbl).to receive(:message) end it 'passes a negative expectation (using to_not)' do dbl = double expect(dbl).to_not receive(:message) end it 'fails a negative expectation (using not_to)' do dbl = double expect(dbl).not_to receive(:message) dbl.message end end """ When I run `ruby spec/rspec_mocks_spec.rb --seed 0` Then it should fail with the following output: | 1) Failure: | | Minitest Spec integration#test_0002_fails a positive expectation | | (Double (anonymous)).message(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 2) Failure: | | Minitest Spec integration#test_0004_fails a negative expectation (using not_to) | | (Double (anonymous)).message(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 4 runs, 4 assertions, 2 failures, 0 errors, 0 skips | Scenario: Load rspec-mocks before rspec-expectations, with Minitest::Spec Given a file named "spec/rspec_mocks_spec.rb" with: """ruby require 'minitest/autorun' require 'minitest/spec' require 'rspec/mocks/minitest_integration' require 'rspec/expectations/minitest_integration' describe "Minitest Spec integration" do it 'passes a positive expectation' do dbl = double expect(dbl).to receive(:message) dbl.message end it 'fails a positive expectation' do dbl = double expect(dbl).to receive(:message) end it 'passes a negative expectation (using to_not)' do dbl = double expect(dbl).to_not receive(:message) end it 'fails a negative expectation (using not_to)' do dbl = double expect(dbl).not_to receive(:message) dbl.message end it 'can use both minitest and rspec expectations' do expect(1 + 3).must_equal 4 expect(1 + 3).to eq 4 end end """ When I run `ruby spec/rspec_mocks_spec.rb --seed 0` Then it should fail with the following output: | 1) Failure: | | Minitest Spec integration#test_0002_fails a positive expectation | | (Double (anonymous)).message(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 2) Failure: | | Minitest Spec integration#test_0004_fails a negative expectation (using not_to) | | (Double (anonymous)).message(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 5 runs, 6 assertions, 2 failures, 0 errors, 0 skips | Scenario: Load rspec-mocks after rspec-expectations, with Minitest::Spec Given a file named "spec/rspec_mocks_spec.rb" with: """ruby require 'minitest/autorun' require 'minitest/spec' require 'rspec/expectations/minitest_integration' require 'rspec/mocks/minitest_integration' describe "Minitest Spec integration" do it 'passes a positive expectation' do dbl = double expect(dbl).to receive(:message) dbl.message end it 'fails a positive expectation' do dbl = double expect(dbl).to receive(:message) end it 'passes a negative expectation (using to_not)' do dbl = double expect(dbl).to_not receive(:message) end it 'fails a negative expectation (using not_to)' do dbl = double expect(dbl).not_to receive(:message) dbl.message end it 'can use both minitest and rspec expectations' do expect(1 + 3).must_equal 4 expect(1 + 3).to eq 4 end end """ When I run `ruby spec/rspec_mocks_spec.rb --seed 0` Then it should fail with the following output: | 1) Failure: | | Minitest Spec integration#test_0002_fails a positive expectation | | (Double (anonymous)).message(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 2) Failure: | | Minitest Spec integration#test_0004_fails a negative expectation (using not_to) | | (Double (anonymous)).message(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 5 runs, 6 assertions, 2 failures, 0 errors, 0 skips | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/outside_rspec/any_test_framework.feature0000664000000000000000000001207114557670305030774 0ustar rootrootFeature: Integrating with any test framework rspec-mocks is a stand-alone gem that can be integrated with any test framework. The example below demonstrates using rspec-mocks with [minitest](http://docs.seattlerb.org/minitest/), but these steps would apply when integrating rspec-mocks with any library or framework: * Include `RSpec::Mocks::ExampleMethods` in your test context. This provides rspec-mocks' API. * Call `RSpec::Mocks.setup` before a test begins. * Call `RSpec::Mocks.verify` after a test completes to verify message expectations. Note that this step is optional; rspec-core, for example, skips this when an example has already failed. * Call `RSpec::Mocks.teardown` after a test completes (and after `verify`) to cleanup. This _must_ be called, even if an error has occurred, so it generally goes in an `ensure` clause. Note: if you are using minitest, you'll probably want to use the built-in [minitest integration](./minitest). Scenario: Use rspec-mocks with Minitest Given a file named "test/test_helper.rb" with: """ruby require 'minitest/autorun' require 'rspec/mocks' module MinitestRSpecMocksIntegration include ::RSpec::Mocks::ExampleMethods def before_setup ::RSpec::Mocks.setup super end def after_teardown super ::RSpec::Mocks.verify ensure ::RSpec::Mocks.teardown end end Minitest::Test.send(:include, MinitestRSpecMocksIntegration) """ And a file named "test/rspec_mocks_test.rb" with: """ruby require 'test_helper' class RSpecMocksTest < Minitest::Test def test_passing_positive_expectation dbl = double expect(dbl).to receive(:message) dbl.message end def test_failing_positive_expectation dbl = double expect(dbl).to receive(:message) end def test_passing_negative_expectation dbl = double expect(dbl).to_not receive(:message) end def test_failing_negative_expectation dbl = double expect(dbl).to_not receive(:message) dbl.message end def test_passing_positive_spy_expectation bond = spy bond.james expect(bond).to have_received(:james) end def test_failing_positive_spy_expectation bond = spy expect(bond).to have_received(:james) end def test_passing_negative_spy_expectation bond = spy expect(bond).not_to have_received(:james) end def test_failing_negative_spy_expectation bond = spy bond.james expect(bond).not_to have_received(:james) end end """ When I run `ruby -Itest test/rspec_mocks_test.rb` Then it should fail with the following output: | 1) Error: | | RSpecMocksTest#test_failing_negative_expectation: | | RSpec::Mocks::MockExpectationError: (Double (anonymous)).message(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 2) Error: | | RSpecMocksTest#test_failing_positive_expectation: | | RSpec::Mocks::MockExpectationError: (Double (anonymous)).message(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 3) Error: | | RSpecMocksTest#test_failing_positive_spy_expectation: | | RSpec::Mocks::MockExpectationError: (Double (anonymous)).james(*(any args)) | | expected: 1 time with any arguments | | received: 0 times with any arguments | | | | 4) Error: | | RSpecMocksTest#test_failing_negative_spy_expectation: | | RSpec::Mocks::MockExpectationError: (Double (anonymous)).james(no args) | | expected: 0 times with any arguments | | received: 1 time | | | | 8 runs, 0 assertions, 0 failures, 4 errors, 0 skips | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/outside_rspec/standalone.feature0000664000000000000000000000212614557670305027221 0ustar rootrootFeature: Using `rspec-mocks` on its own outside of RSpec (standalone mode) `require "rspec/mocks/standalone"` to expose the API at the top level (e.g. `main`) outside the RSpec environment in a REPL like IRB or in a one-off script. Scenario: Allow a message outside RSpec Given a file named "example.rb" with: """ruby require "rspec/mocks/standalone" greeter = double("greeter") allow(greeter).to receive(:say_hi) { "Hello!" } puts greeter.say_hi """ When I run `ruby example.rb` Then the output should contain "Hello!" Scenario: Expect a message outside RSpec Given a file named "example.rb" with: """ruby require "rspec/mocks/standalone" greeter = double("greeter") expect(greeter).to receive(:say_hi) RSpec::Mocks.verify """ When I run `ruby example.rb` Then it should fail with the following output: | (Double "greeter").say_hi(*(any args)) | | RSpec::Mocks::MockExpectationError | | expected: 1 time with any arguments | | received: 0 times with any arguments | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/0000775000000000000000000000000014557670305024567 5ustar rootroot././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/stub_undefined_constant.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/stub_undefined_constant.featu0000664000000000000000000000315214557670305032525 0ustar rootrootFeature: Stub Undefined Constant Use `stub_const` to stub constants. When the constant is not already defined, all the necessary intermediary modules will be dynamically created. When the example completes, the intermediary module constants will be removed to return the constant state to how it started. Scenario: Stub top-level constant Given a file named "stub_const_spec.rb" with: """ruby RSpec.describe "stubbing FOO" do it "can stub undefined constant FOO" do stub_const("FOO", 5) expect(FOO).to eq(5) end it "undefines the constant when the example completes" do expect { FOO }.to raise_error(NameError) end end """ When I run `rspec stub_const_spec.rb` Then the examples should all pass Scenario: Stub nested constant Given a file named "stub_const_spec.rb" with: """ruby module MyGem class SomeClass end end module MyGem RSpec.describe SomeClass do it "can stub an arbitrarily deep constant that is undefined" do expect(defined?(SomeClass::A)).to be_falsey stub_const("MyGem::SomeClass::A::B::C", 3) expect(SomeClass::A::B::C).to eq(3) expect(SomeClass::A).to be_a(Module) end it 'undefines the intermediary constants that were dynamically created' do expect(defined?(SomeClass)).to be_truthy expect(defined?(SomeClass::A)).to be_falsey end end end """ When I run `rspec stub_const_spec.rb` Then the examples should all pass ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/hide_undefined_constant.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/hide_undefined_constant.featu0000664000000000000000000000153414557670305032463 0ustar rootrootFeature: Hide Undefined Constant Hiding a constant that is already undefined is a no-op. This can be useful when a spec file may run in either an isolated environment (e.g. when running one spec file) or in a full environment with all parts of your code base loaded (e.g. when running your entire suite). Scenario: Hiding undefined constant Given a file named "hide_const_spec.rb" with: """ruby RSpec.describe "hiding UNDEFINED_CONSTANT" do it "has no effect" do hide_const("UNDEFINED_CONSTANT") expect { UNDEFINED_CONSTANT }.to raise_error(NameError) end it "is still undefined after the example completes" do expect { UNDEFINED_CONSTANT }.to raise_error(NameError) end end """ When I run `rspec hide_const_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/README.md0000664000000000000000000000404414557670305026050 0ustar rootroot# Mutating Constants ### Stubbing Support is provided for stubbing constants. Like with method stubs, the stubbed constants will be restored to their original state when an example completes. ``` ruby stub_const("Foo", fake_foo) Foo # => fake_foo ``` Stubbed constant names must be fully qualified; the current module nesting is not considered. ``` ruby module MyGem class SomeClass; end end module MyGem describe "Something" do let(:fake_class) { Class.new } it "accidentally stubs the wrong constant" do # this stubs ::SomeClass (in the top-level namespace), # not MyGem::SomeClass like you probably mean. stub_const("SomeClass", fake_class) end it "stubs the right constant" do stub_const("MyGem::SomeClass", fake_class) end end end ``` When you stub a constant that is a module or a class, nested constants on the original module or class are not transferred by default, but you can use the `:transfer_nested_constants` option to tell rspec-mocks to transfer them: ``` ruby class CardDeck SUITS = [:Spades, :Diamonds, :Clubs, :Hearts] NUM_CARDS = 52 end fake_class = Class.new stub_const("CardDeck", fake_class) CardDeck # => fake_class CardDeck::SUITS # => raises uninitialized constant error CardDeck::NUM_CARDS # => raises uninitialized constant error stub_const("CardDeck", fake_class, :transfer_nested_constants => true) CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts] CardDeck::NUM_CARDS # => 52 stub_const("CardDeck", fake_class, :transfer_nested_constants => [:SUITS]) CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts] CardDeck::NUM_CARDS # => raises uninitialized constant error ``` ### Hiding Support is also provided for hiding constants. Hiding a constant temporarily removes it; it is restored to its original value after the test completes. ```ruby FOO = 42 hide_const("FOO") FOO # => NameError: uninitialized constant FOO ``` Like stubbed constants, names must be fully qualified. Hiding constants that are already undefined has no effect. ```ruby hide_const("NO_OP") ``` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/stub_defined_constant.feature0000664000000000000000000000434314557670305032514 0ustar rootrootFeature: Stub Defined Constant Use `stub_const` to stub constants. When the constant is already defined, the stubbed value will replace the original value for the duration of the example. Scenario: Stub top-level constant Given a file named "stub_const_spec.rb" with: """ruby FOO = 7 RSpec.describe "stubbing FOO" do it "can stub FOO with a different value" do stub_const("FOO", 5) expect(FOO).to eq(5) end it "restores the stubbed constant when the example completes" do expect(FOO).to eq(7) end end """ When I run `rspec stub_const_spec.rb` Then the examples should all pass Scenario: Stub nested constant Given a file named "stub_const_spec.rb" with: """ruby module MyGem class SomeClass FOO = 7 end end module MyGem RSpec.describe SomeClass do it "stubs the nested constant when it is fully qualified" do stub_const("MyGem::SomeClass::FOO", 5) expect(SomeClass::FOO).to eq(5) end end end """ When I run `rspec stub_const_spec.rb` Then the examples should all pass Scenario: Transfer nested constants Given a file named "stub_const_spec.rb" with: """ruby module MyGem class SomeClass FOO = 7 end end module MyGem RSpec.describe SomeClass do let(:fake_class) { Class.new } it "does not transfer nested constants by default" do stub_const("MyGem::SomeClass", fake_class) expect { SomeClass::FOO }.to raise_error(NameError) end it "transfers nested constants when using :transfer_nested_constants => true" do stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => true) expect(SomeClass::FOO).to eq(7) end it "can specify a list of nested constants to transfer" do stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => [:FOO]) expect(SomeClass::FOO).to eq(7) end end end """ When I run `rspec stub_const_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/mutating_constants/hide_defined_constant.feature0000664000000000000000000000343714557670305032453 0ustar rootrootFeature: Hide Defined Constant Use `hide_const` to remove a constant for the duration of a test. Scenario: Hide top-level constant Given a file named "hide_const_spec.rb" with: """ruby FOO = 7 RSpec.describe "hiding FOO" do it "can hide FOO" do hide_const("FOO") expect { FOO }.to raise_error(NameError) end it "restores the hidden constant when the example completes" do expect(FOO).to eq(7) end end """ When I run `rspec hide_const_spec.rb` Then the examples should all pass Scenario: Hide nested constant Given a file named "hide_const_spec.rb" with: """ruby module MyGem class SomeClass FOO = 7 end end module MyGem RSpec.describe SomeClass do it "hides the nested constant when it is fully qualified" do hide_const("MyGem::SomeClass::FOO") expect { SomeClass::FOO }.to raise_error(NameError) end it "restores the hidden constant when the example completes" do expect(MyGem::SomeClass::FOO).to eq(7) end end end """ When I run `rspec hide_const_spec.rb` Then the examples should all pass Scenario: Hiding undefined constant Given a file named "hide_const_spec.rb" with: """ruby RSpec.describe "hiding UNDEFINED_CONSTANT" do it "has no effect" do hide_const("UNDEFINED_CONSTANT") expect { UNDEFINED_CONSTANT }.to raise_error(NameError) end it "is still undefined after the example completes" do expect { UNDEFINED_CONSTANT }.to raise_error(NameError) end end """ When I run `rspec hide_const_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/0000775000000000000000000000000014557670305023027 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/any_instance.feature0000664000000000000000000000706014557670305027062 0ustar rootroot@allow-old-syntax Feature: `any_instance` `any_instance` is the old way to stub or mock any instance of a class but carries the baggage of a global monkey patch on all classes. Note that we [generally recommend against](../working-with-legacy-code/any-instance) using this feature. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ And a file named ".rspec" with: """ --require spec_helper """ Scenario: Stub a method on any instance of a class Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "Stubbing a method with any_instance" do it "returns the specified value on any instance of the class" do Object.any_instance.stub(:foo).and_return(:return_value) o = Object.new expect(o.foo).to eq(:return_value) end end """ When I run `rspec spec/example_spec.rb` Then the examples should all pass Scenario: Stub multiple methods on any instance of a class Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "Stubbing multiple methods with any_instance" do it "returns the specified values for the given messages" do Object.any_instance.stub(:foo => 'foo', :bar => 'bar') o = Object.new expect(o.foo).to eq('foo') expect(o.bar).to eq('bar') end end """ When I run `rspec spec/example_spec.rb` Then the examples should all pass Scenario: Stubbing any instance of a class with specific arguments Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "Stubbing any instance with arguments" do it "returns the stubbed value when arguments match" do Object.any_instance.stub(:foo).with(:param_one, :param_two).and_return(:result_one) Object.any_instance.stub(:foo).with(:param_three, :param_four).and_return(:result_two) o = Object.new expect(o.foo(:param_one, :param_two)).to eq(:result_one) expect(o.foo(:param_three, :param_four)).to eq(:result_two) end end """ When I run `rspec spec/example_spec.rb` Then the examples should all pass Scenario: Block implementation is passed the receiver as first arg Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "Stubbing any instance of a class" do it 'yields the receiver to the block implementation' do String.any_instance.stub(:slice) do |value, start, length| value[start, length] end expect('string'.slice(2, 3)).to eq('rin') end end """ When I run `rspec spec/example_spec.rb` Then the examples should all pass Scenario: Expect a message on any instance of a class Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "Expecting a message on any instance of a class" do before do Object.any_instance.should_receive(:foo) end it "passes when an instance receives the message" do Object.new.foo end it "fails when no instance receives the message" do Object.new.to_s end end """ When I run `rspec spec/example_spec.rb` Then it should fail with the following output: | 2 examples, 1 failure | | Exactly one instance should have received the following message(s) but didn't: foo | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/should_receive.feature0000664000000000000000000000616414557670305027413 0ustar rootroot@allow-old-syntax Feature: `should_receive` `should_receive` is the old way to [expect messages](../basics/expecting-messages) but carries the baggage of a global monkey patch on all objects. It supports the same fluent interface for [setting constraints](../setting-constraints) and [configuring responses](../configuring-responses). Similarly, you can use `should_not_receive` to set a negative message expectation. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ And a file named ".rspec" with: """ --require spec_helper """ Scenario: Failing positive message expectation Given a file named "spec/unfulfilled_message_expectation_spec.rb" with: """ruby RSpec.describe "An unfulfilled message expectation" do it "triggers a failure" do dbl = double("Some Collaborator") dbl.should_receive(:foo) end end """ When I run `rspec spec/unfulfilled_message_expectation_spec.rb` Then it should fail with: """ 1) An unfulfilled message expectation triggers a failure Failure/Error: dbl.should_receive(:foo) (Double "Some Collaborator").foo(*(any args)) expected: 1 time with any arguments received: 0 times with any arguments """ Scenario: Passing positive message expectation Given a file named "spec/fulfilled_message_expectation_spec.rb" with: """ruby RSpec.describe "A fulfilled message expectation" do it "passes" do dbl = double("Some Collaborator") dbl.should_receive(:foo) dbl.foo end end """ When I run `rspec spec/fulfilled_message_expectation_spec.rb` Then the examples should all pass Scenario: Failing negative message expectation Given a file named "spec/negative_message_expectation_spec.rb" with: """ruby RSpec.describe "A negative message expectation" do it "fails when the message is received" do dbl = double("Some Collaborator").as_null_object dbl.should_not_receive(:foo) dbl.foo end end """ When I run `rspec spec/negative_message_expectation_spec.rb` Then it should fail with: """ 1) A negative message expectation fails when the message is received Failure/Error: dbl.foo (Double "Some Collaborator").foo(no args) expected: 0 times with any arguments received: 1 time """ Scenario: Passing negative message expectation Given a file named "spec/negative_message_expectation_spec.rb" with: """ruby RSpec.describe "A negative message expectation" do it "passes if the message is never received" do dbl = double("Some Collaborator").as_null_object dbl.should_not_receive(:foo) end end """ When I run `rspec spec/negative_message_expectation_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/unstub.feature0000664000000000000000000000312514557670305025725 0ustar rootroot@allow-old-syntax Feature: Using `unstub` `unstub` removes a method stub, essentially cleaning up the method stub early, rather than waiting for the cleanup that runs at the end of the example. The newer non-monkey-patching syntax does not have a direct equivalent but in most situations you can achieve the same behavior using [`and_call_original`](../configuring-responses/calling-the-original-implementation). The difference is that `obj.unstub(:foo)` completely cleans up the `foo` method stub, whereas `allow(obj).to receive(:foo).and_call_original` continues to observe calls to the method (important when you are using [spies](../basics/spies)), which could affect the method's behavior if it does anything with `caller` as it will include additional rspec stack frames. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ And a file named ".rspec" with: """ --require spec_helper """ Scenario: Unstub a method Given a file named "spec/unstub_spec.rb" with: """ruby RSpec.describe "Unstubbing a method" do it "restores the original behavior" do string = "hello world" string.stub(:reverse) { "hello dlrow" } expect { string.unstub(:reverse) }.to change { string.reverse }.from("hello dlrow").to("dlrow olleh") end end """ When I run `rspec spec/unstub_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/README.md0000664000000000000000000000270014557670305024305 0ustar rootroot# Old Syntax Historically, rspec-mocks has used a monkey-patched syntax to allow you to mock or stub any object: ```ruby obj.stub(:foo).and_return(15) obj.should_receive(:bar) ``` Unfortunately, this is prone to weird, confusing failures when applied to [delegate/proxy objects](https://rspec.info/blog/2012/06/rspecs-new-expectation-syntax#delegation_issues). For a method like `stub` to work properly, it must be defined on every object in the system, but RSpec does not own every object in the system and cannot ensure that it always works consistently. For this reason, in RSpec 2.14, we introduced a new syntax that avoids monkey patching altogether. It's the syntax shown in all examples of this documentation outside of this directory. As of RSpec 3, we consider this to be the main, recommended syntax of rspec- mocks. The old monkey-patched syntax continues to work, but you will get a deprecation warning if you use it without explicitly opting-in to it: ```ruby # If you're using rspec-core: RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end # Or, if you're using rspec-mocks in another context: RSpec::Mocks.configuration.syntax = :should ``` We have no plans to ever kill the old syntax, but we may extract it into an external gem in RSpec 4. If you have an old project that uses the old syntax and you want to update it to the current syntax, checkout [transpec](http://yujinakayama.me/transpec/). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/stub.feature0000664000000000000000000000331014557670305025356 0ustar rootroot@allow-old-syntax Feature: `stub` `stub` is the old way to [allow messages](../basics/allowing-messages) but carries the baggage of a global monkey patch on all objects. It supports the same fluent interface for [setting constraints](../setting-constraints) and [configuring responses](../configuring-responses). You can also pass `stub` a hash of message/return-value pairs, which acts like `allow(obj).to receive_messages(hash)`, but does not support further customization through the fluent interface. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ And a file named ".rspec" with: """ --require spec_helper """ Scenario: Stub a method Given a file named "spec/stub_spec.rb" with: """ruby RSpec.describe "Stubbing a method" do it "configures how the object responds" do dbl = double dbl.stub(:foo).and_return(13) expect(dbl.foo).to eq(13) end end """ When I run `rspec spec/stub_spec.rb` Then the examples should all pass Scenario: Stub multiple methods by passing a hash Given a file named "spec/stub_multiple_methods_spec.rb" with: """ruby RSpec.describe "Stubbing multiple methods" do it "stubs each named method with the given return value" do dbl = double dbl.stub(:foo => 13, :bar => 10) expect(dbl.foo).to eq(13) expect(dbl.bar).to eq(10) end end """ When I run `rspec spec/stub_multiple_methods_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/features/old_syntax/stub_chain.feature0000664000000000000000000000416714557670305026533 0ustar rootroot@allow-old-syntax Feature: `stub_chain` `stub_chain` is the old way to [allow a message chain](../working-with-legacy-code/message-chains) but carries the baggage of a global monkey patch on all objects. As with `receive_message_chain`, use with care; we recommend treating usage of `stub_chain` as a code smell. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ And a file named ".rspec" with: """ --require spec_helper """ Scenario: Use `stub_chain` on a double Given a file named "spec/stub_chain_spec.rb" with: """ruby RSpec.describe "Using stub_chain on a double" do let(:dbl) { double } example "using a string and a block" do dbl.stub_chain("foo.bar") { :baz } expect(dbl.foo.bar).to eq(:baz) end example "using symbols and a hash" do dbl.stub_chain(:foo, :bar => :baz) expect(dbl.foo.bar).to eq(:baz) end example "using symbols and a block" do dbl.stub_chain(:foo, :bar) { :baz } expect(dbl.foo.bar).to eq(:baz) end end """ When I run `rspec spec/stub_chain_spec.rb` Then the examples should all pass Scenario: Use `stub_chain` on any instance of a class Given a file named "spec/stub_chain_spec.rb" with: """ruby RSpec.describe "Using any_instance.stub_chain" do example "using a string and a block" do Object.any_instance.stub_chain("foo.bar") { :baz } expect(Object.new.foo.bar).to eq(:baz) end example "using symbols and a hash" do Object.any_instance.stub_chain(:foo, :bar => :baz) expect(Object.new.foo.bar).to eq(:baz) end example "using symbols and a block" do Object.any_instance.stub_chain(:foo, :bar) { :baz } expect(Object.new.foo.bar).to eq(:baz) end end """ When I run `rspec spec/stub_chain_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/.gitignore0000664000000000000000000000024514557670305021016 0ustar rootroot*.sw? .DS_Store coverage rdoc pkg doc tmp rerun.txt Gemfile.lock .bundle .idea *.rbc .yardoc bin Gemfile-custom bundle .rbx .rspec-local spec/examples.txt specs.out ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/0000775000000000000000000000000014557670305017573 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/0000775000000000000000000000000014557670305020707 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/0000775000000000000000000000000014557670305022023 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/order_group.rb0000664000000000000000000000347514557670305024710 0ustar rootrootmodule RSpec module Mocks # @private class OrderGroup def initialize @expectations = [] @invocation_order = [] @index = 0 end # @private def register(expectation) @expectations << expectation end def invoked(message) @invocation_order << message end # @private def ready_for?(expectation) remaining_expectations.find(&:ordered?) == expectation end # @private def consume remaining_expectations.each_with_index do |expectation, index| next unless expectation.ordered? @index += index + 1 return expectation end nil end # @private def handle_order_constraint(expectation) return unless expectation.ordered? && remaining_expectations.include?(expectation) return consume if ready_for?(expectation) expectation.raise_out_of_order_error end def verify_invocation_order(expectation) expectation.raise_out_of_order_error unless expectations_invoked_in_order? true end def clear @index = 0 @invocation_order.clear @expectations.clear end def empty? @expectations.empty? end private def remaining_expectations @expectations[@index..-1] || [] end def expectations_invoked_in_order? invoked_expectations == expected_invocations end def invoked_expectations @expectations.select { |e| e.ordered? && @invocation_order.include?(e) } end def expected_invocations @invocation_order.map { |invocation| expectation_for(invocation) }.compact end def expectation_for(message) @expectations.find { |e| message == e } end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/targets.rb0000664000000000000000000000660014557670305024023 0ustar rootrootmodule RSpec module Mocks # @private module TargetDelegationClassMethods def delegate_to(matcher_method) define_method(:to) do |matcher, &block| unless matcher_allowed?(matcher) raise_unsupported_matcher(:to, matcher) end define_matcher(matcher, matcher_method, &block) end end def delegate_not_to(matcher_method, options={}) method_name = options.fetch(:from) define_method(method_name) do |matcher, &block| case matcher when Matchers::Receive, Matchers::HaveReceived define_matcher(matcher, matcher_method, &block) when Matchers::ReceiveMessages, Matchers::ReceiveMessageChain raise_negation_unsupported(method_name, matcher) else raise_unsupported_matcher(method_name, matcher) end end end def disallow_negation(method_name) define_method(method_name) do |matcher, *_args| raise_negation_unsupported(method_name, matcher) end end end # @private module TargetDelegationInstanceMethods attr_reader :target private def matcher_allowed?(matcher) Matchers::Matcher === matcher end def define_matcher(matcher, name, &block) matcher.__send__(name, target, &block) end def raise_unsupported_matcher(method_name, matcher) raise UnsupportedMatcherError, "only the `receive`, `have_received` and `receive_messages` matchers are supported " \ "with `#{expression}(...).#{method_name}`, but you have provided: #{matcher}" end def raise_negation_unsupported(method_name, matcher) raise NegationUnsupportedError, "`#{expression}(...).#{method_name} #{matcher.matcher_name}` is not supported since it " \ "doesn't really make sense. What would it even mean?" end end # @private class TargetBase def initialize(target) @target = target end extend TargetDelegationClassMethods include TargetDelegationInstanceMethods end # @private module ExpectationTargetMethods extend TargetDelegationClassMethods include TargetDelegationInstanceMethods delegate_to :setup_expectation delegate_not_to :setup_negative_expectation, :from => :not_to delegate_not_to :setup_negative_expectation, :from => :to_not def expression :expect end end # @private class ExpectationTarget < TargetBase include ExpectationTargetMethods end # @private class AllowanceTarget < TargetBase def expression :allow end delegate_to :setup_allowance disallow_negation :not_to disallow_negation :to_not end # @private class AnyInstanceAllowanceTarget < TargetBase def expression :allow_any_instance_of end delegate_to :setup_any_instance_allowance disallow_negation :not_to disallow_negation :to_not end # @private class AnyInstanceExpectationTarget < TargetBase def expression :expect_any_instance_of end delegate_to :setup_any_instance_expectation delegate_not_to :setup_any_instance_negative_expectation, :from => :not_to delegate_not_to :setup_any_instance_negative_expectation, :from => :to_not end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/minitest_integration.rb0000664000000000000000000000347514557670305026620 0ustar rootrootrequire 'rspec/mocks' module RSpec module Mocks # @private module MinitestIntegration include ::RSpec::Mocks::ExampleMethods def before_setup ::RSpec::Mocks.setup super end def after_teardown super # Only verify if there's not already an error. Otherwise # we risk getting the same failure twice, since negative # expectation violations raise both when the message is # unexpectedly received, and also during `verify` (in case # the first failure was caught by user code via a # `rescue Exception`). ::RSpec::Mocks.verify unless failures.any? ensure ::RSpec::Mocks.teardown end end end end Minitest::Test.send(:include, RSpec::Mocks::MinitestIntegration) if defined?(::Minitest::Expectation) if defined?(::RSpec::Expectations) && ::Minitest::Expectation.method_defined?(:to) # rspec/expectations/minitest_integration has already been loaded and # has defined `to`/`not_to`/`to_not` on `Minitest::Expectation` so we do # not want to here (or else we would interfere with rspec-expectations' definition). else # ...otherwise, define those methods now. If `rspec/expectations/minitest_integration` # is loaded after this file, it'll override the definition here. Minitest::Expectation.class_eval do include RSpec::Mocks::ExpectationTargetMethods def to(*args) ctx.assertions += 1 super end def not_to(*args) ctx.assertions += 1 super end def to_not(*args) ctx.assertions += 1 super end end end end module RSpec module Mocks remove_const :MockExpectationError # Raised when a message expectation is not satisfied. MockExpectationError = ::Minitest::Assertion end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/proxy.rb0000664000000000000000000004171214557670305023536 0ustar rootrootmodule RSpec module Mocks # @private class Proxy # @private SpecificMessage = Struct.new(:object, :message, :args) do def ==(expectation) expectation.orig_object == object && expectation.matches?(message, *args) end end unless defined?(Mutex) Support.require_rspec_support 'mutex' Mutex = Support::Mutex end # @private def ensure_implemented(*_args) # noop for basic proxies, see VerifyingProxy for behaviour. end # @private def initialize(object, order_group, options={}) ensure_can_be_proxied!(object) @object = object @order_group = order_group @error_generator = ErrorGenerator.new(object) @messages_received = [] @messages_received_mutex = Mutex.new @options = options @null_object = false @method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) } end # @private def ensure_can_be_proxied!(object) return unless object.is_a?(Symbol) msg = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed." raise ArgumentError, msg end # @private attr_reader :object # @private def null_object? @null_object end # @private # Tells the object to ignore any messages that aren't explicitly set as # stubs or message expectations. def as_null_object @null_object = true @object end # @private def original_method_handle_for(_message) nil end DEFAULT_MESSAGE_EXPECTATION_OPTS = {}.freeze # @private def add_message_expectation(method_name, opts=DEFAULT_MESSAGE_EXPECTATION_OPTS, &block) location = opts.fetch(:expected_from) { CallerFilter.first_non_rspec_line } meth_double = method_double_for(method_name) if null_object? && !block meth_double.add_default_stub(@error_generator, @order_group, location, opts) do @object end end meth_double.add_expectation @error_generator, @order_group, location, opts, &block end # @private def add_simple_expectation(method_name, response, location) method_double_for(method_name).add_simple_expectation method_name, response, @error_generator, location end # @private def build_expectation(method_name) meth_double = method_double_for(method_name) meth_double.build_expectation( @error_generator, @order_group ) end # @private def replay_received_message_on(expectation, &block) expected_method_name = expectation.message meth_double = method_double_for(expected_method_name) if meth_double.expectations.any? @error_generator.raise_expectation_on_mocked_method(expected_method_name) end unless null_object? || meth_double.stubs.any? @error_generator.raise_expectation_on_unstubbed_method(expected_method_name) end @messages_received_mutex.synchronize do @messages_received.each do |(actual_method_name, args, received_block)| next unless expectation.matches?(actual_method_name, *args) expectation.safe_invoke(nil) block.call(*args, &received_block) if block end end end # @private def check_for_unexpected_arguments(expectation) @messages_received_mutex.synchronize do return if @messages_received.empty? return if @messages_received.any? { |method_name, args, _| expectation.matches?(method_name, *args) } name_but_not_args, others = @messages_received.partition do |(method_name, args, _)| expectation.matches_name_but_not_args(method_name, *args) end return if name_but_not_args.empty? && !others.empty? expectation.raise_unexpected_message_args_error(name_but_not_args.map { |args| args[1] }) end end # @private def add_stub(method_name, opts={}, &implementation) location = opts.fetch(:expected_from) { CallerFilter.first_non_rspec_line } method_double_for(method_name).add_stub @error_generator, @order_group, location, opts, &implementation end # @private def add_simple_stub(method_name, response) method_double_for(method_name).add_simple_stub method_name, response end # @private def remove_stub(method_name) method_double_for(method_name).remove_stub end # @private def remove_stub_if_present(method_name) method_double_for(method_name).remove_stub_if_present end # @private def verify @method_doubles.each_value { |d| d.verify } end # @private def reset @messages_received_mutex.synchronize do @messages_received.clear end end # @private def received_message?(method_name, *args, &block) @messages_received_mutex.synchronize do @messages_received.any? { |array| array == [method_name, args, block] } end end # @private def messages_arg_list @messages_received_mutex.synchronize do @messages_received.map { |_, args, _| args } end end # @private def has_negative_expectation?(message) method_double_for(message).expectations.find { |expectation| expectation.negative_expectation_for?(message) } end # @private def record_message_received(message, *args, &block) @order_group.invoked SpecificMessage.new(object, message, args) @messages_received_mutex.synchronize do @messages_received << [message, args, block] end end ruby2_keywords :record_message_received if respond_to?(:ruby2_keywords, true) # @private def message_received(message, *args, &block) record_message_received message, *args, &block expectation = find_matching_expectation(message, *args) stub = find_matching_method_stub(message, *args) if (stub && expectation && expectation.called_max_times?) || (stub && !expectation) expectation.increase_actual_received_count! if expectation && expectation.actual_received_count_matters? if (expectation = find_almost_matching_expectation(message, *args)) expectation.advise(*args) unless expectation.expected_messages_received? end stub.invoke(nil, *args, &block) elsif expectation expectation.unadvise(messages_arg_list) expectation.invoke(stub, *args, &block) elsif (expectation = find_almost_matching_expectation(message, *args)) expectation.advise(*args) if null_object? unless expectation.expected_messages_received? if null_object? || !has_negative_expectation?(message) expectation.raise_unexpected_message_args_error([args]) end elsif (stub = find_almost_matching_stub(message, *args)) stub.advise(*args) raise_missing_default_stub_error(stub, [args]) elsif Class === @object @object.superclass.__send__(message, *args, &block) else @object.__send__(:method_missing, message, *args, &block) end end ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true) # @private def raise_unexpected_message_error(method_name, args) @error_generator.raise_unexpected_message_error method_name, args end # @private def raise_missing_default_stub_error(expectation, args_for_multiple_calls) @error_generator.raise_missing_default_stub_error(expectation, args_for_multiple_calls) end # @private def visibility_for(_method_name) # This is the default (for test doubles). Subclasses override this. :public end if Support::RubyFeatures.module_prepends_supported? def self.prepended_modules_of(klass) ancestors = klass.ancestors # `|| 0` is necessary for Ruby 2.0, where the singleton class # is only in the ancestor list when there are prepended modules. singleton_index = ancestors.index(klass) || 0 ancestors[0, singleton_index] end def prepended_modules_of_singleton_class @prepended_modules_of_singleton_class ||= RSpec::Mocks::Proxy.prepended_modules_of(@object.singleton_class) end end # @private def method_double_if_exists_for_message(message) method_double_for(message) if @method_doubles.key?(message.to_sym) end private def method_double_for(message) @method_doubles[message.to_sym] end def find_matching_expectation(method_name, *args) find_best_matching_expectation_for(method_name) do |expectation| expectation.matches?(method_name, *args) end end ruby2_keywords :find_matching_expectation if respond_to?(:ruby2_keywords, true) def find_almost_matching_expectation(method_name, *args) find_best_matching_expectation_for(method_name) do |expectation| expectation.matches_name_but_not_args(method_name, *args) end end ruby2_keywords :find_almost_matching_expectation if respond_to?(:ruby2_keywords, true) def find_best_matching_expectation_for(method_name) first_match = nil method_double_for(method_name).expectations.each do |expectation| next unless yield expectation return expectation unless expectation.called_max_times? first_match ||= expectation end first_match end def find_matching_method_stub(method_name, *args) method_double_for(method_name).stubs.find { |stub| stub.matches?(method_name, *args) } end ruby2_keywords :find_matching_method_stub if respond_to?(:ruby2_keywords, true) def find_almost_matching_stub(method_name, *args) method_double_for(method_name).stubs.find { |stub| stub.matches_name_but_not_args(method_name, *args) } end ruby2_keywords :find_almost_matching_stub if respond_to?(:ruby2_keywords, true) end # @private class TestDoubleProxy < Proxy def reset @method_doubles.clear object.__disallow_further_usage! super end end # @private class PartialDoubleProxy < Proxy def original_method_handle_for(message) if any_instance_class_recorder_observing_method?(@object.class, message) message = ::RSpec::Mocks.space. any_instance_recorder_for(@object.class). build_alias_method_name(message) end ::RSpec::Support.method_handle_for(@object, message) rescue NameError nil end # @private def add_simple_expectation(method_name, response, location) method_double_for(method_name).configure_method super end # @private def add_simple_stub(method_name, response) method_double_for(method_name).configure_method super end # @private def visibility_for(method_name) # We fall back to :public because by default we allow undefined methods # to be stubbed, and when we do so, we make them public. MethodReference.method_visibility_for(@object, method_name) || :public end def reset @method_doubles.each_value { |d| d.reset } super end def message_received(message, *args, &block) RSpec::Mocks.space.any_instance_recorders_from_ancestry_of(object).each do |subscriber| subscriber.notify_received_message(object, message, args, block) end super end ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true) private def any_instance_class_recorder_observing_method?(klass, method_name) only_return_existing = true recorder = ::RSpec::Mocks.space.any_instance_recorder_for(klass, only_return_existing) return true if recorder && recorder.already_observing?(method_name) superklass = klass.superclass return false if superklass.nil? any_instance_class_recorder_observing_method?(superklass, method_name) end end # @private # When we mock or stub a method on a class, we have to treat it a bit different, # because normally singleton method definitions only affect the object on which # they are defined, but on classes they affect subclasses, too. As a result, # we need some special handling to get the original method. module PartialClassDoubleProxyMethods def initialize(source_space, *args) @source_space = source_space super(*args) end # Consider this situation: # # class A; end # class B < A; end # # allow(A).to receive(:new) # expect(B).to receive(:new).and_call_original # # When getting the original definition for `B.new`, we cannot rely purely on # using `B.method(:new)` before our redefinition is defined on `B`, because # `B.method(:new)` will return a method that will execute the stubbed version # of the method on `A` since singleton methods on classes are in the lookup # hierarchy. # # To do it properly, we need to find the original definition of `new` from `A` # from _before_ `A` was stubbed, and we need to rebind it to `B` so that it will # run with the proper `self`. # # That's what this method (together with `original_unbound_method_handle_from_ancestor_for`) # does. def original_method_handle_for(message) unbound_method = superclass_proxy && superclass_proxy.original_unbound_method_handle_from_ancestor_for(message.to_sym) return super unless unbound_method unbound_method.bind(object) # :nocov: rescue TypeError if RUBY_VERSION == '1.8.7' # In MRI 1.8.7, a singleton method on a class cannot be rebound to its subclass if unbound_method && unbound_method.owner.ancestors.first != unbound_method.owner # This is a singleton method; we can't do anything with it # But we can work around this using a different implementation double = method_double_from_ancestor_for(message) return object.method(double.method_stasher.stashed_method_name) end end raise # :nocov: end protected def original_unbound_method_handle_from_ancestor_for(message) double = method_double_from_ancestor_for(message) double && double.original_method.unbind end def method_double_from_ancestor_for(message) @method_doubles.fetch(message) do # The fact that there is no method double for this message indicates # that it has not been redefined by rspec-mocks. We need to continue # looking up the ancestor chain. return superclass_proxy && superclass_proxy.method_double_from_ancestor_for(message) end end def superclass_proxy return @superclass_proxy if defined?(@superclass_proxy) if (superclass = object.superclass) @superclass_proxy = @source_space.superclass_proxy_for(superclass) else @superclass_proxy = nil end end end # @private class PartialClassDoubleProxy < PartialDoubleProxy include PartialClassDoubleProxyMethods end # @private class ProxyForNil < PartialDoubleProxy def initialize(order_group) set_expectation_behavior super(nil, order_group) end attr_accessor :disallow_expectations attr_accessor :warn_about_expectations def add_message_expectation(method_name, opts={}, &block) warn_or_raise!(method_name) super end def add_stub(method_name, opts={}, &implementation) warn_or_raise!(method_name) super end private def set_expectation_behavior case RSpec::Mocks.configuration.allow_message_expectations_on_nil when false @warn_about_expectations = false @disallow_expectations = true when true @warn_about_expectations = false @disallow_expectations = false else @warn_about_expectations = true @disallow_expectations = false end end def warn_or_raise!(method_name) # This method intentionally swallows the message when # neither disallow_expectations nor warn_about_expectations # are set to true. if disallow_expectations raise_error(method_name) elsif warn_about_expectations warn(method_name) end end def warn(method_name) warning_msg = @error_generator.expectation_on_nil_message(method_name) RSpec.warning(warning_msg) end def raise_error(method_name) @error_generator.raise_expectation_on_nil_error(method_name) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/object_reference.rb0000664000000000000000000001105314557670305025634 0ustar rootrootmodule RSpec module Mocks # @private class ObjectReference # Returns an appropriate Object or Module reference based # on the given argument. def self.for(object_module_or_name, allow_direct_object_refs=false) case object_module_or_name when Module if anonymous_module?(object_module_or_name) DirectObjectReference.new(object_module_or_name) else # Use a `NamedObjectReference` if it has a name because this # will use the original value of the constant in case it has # been stubbed. NamedObjectReference.new(name_of(object_module_or_name)) end when String NamedObjectReference.new(object_module_or_name) else if allow_direct_object_refs DirectObjectReference.new(object_module_or_name) else raise ArgumentError, "Module or String expected, got #{object_module_or_name.inspect}" end end end if Module.new.name.nil? def self.anonymous_module?(mod) !name_of(mod) end else # 1.8.7 def self.anonymous_module?(mod) name_of(mod) == "" end end private_class_method :anonymous_module? def self.name_of(mod) MODULE_NAME_METHOD.bind(mod).call end private_class_method :name_of # @private MODULE_NAME_METHOD = Module.instance_method(:name) end # An implementation of rspec-mocks' reference interface. # Used when an object is passed to {ExampleMethods#object_double}, or # an anonymous class or module is passed to {ExampleMethods#instance_double} # or {ExampleMethods#class_double}. # Represents a reference to that object. # @see NamedObjectReference class DirectObjectReference # @param object [Object] the object to which this refers def initialize(object) @object = object end # @return [String] the object's description (via `#inspect`). def description @object.inspect end # Defined for interface parity with the other object reference # implementations. Raises an `ArgumentError` to indicate that `as_stubbed_const` # is invalid when passing an object argument to `object_double`. def const_to_replace raise ArgumentError, "Can not perform constant replacement with an anonymous object." end # The target of the verifying double (the object itself). # # @return [Object] def target @object end # Always returns true for an object as the class is defined. # # @return [true] def defined? true end # Yields if the reference target is loaded, providing a generic mechanism # to optionally run a bit of code only when a reference's target is # loaded. # # This specific implementation always yields because direct references # are always loaded. # # @yield [Object] the target of this reference. def when_loaded yield @object end end # An implementation of rspec-mocks' reference interface. # Used when a string is passed to {ExampleMethods#object_double}, # and when a string, named class or named module is passed to # {ExampleMethods#instance_double}, or {ExampleMethods#class_double}. # Represents a reference to the object named (via a constant lookup) # by the string. # @see DirectObjectReference class NamedObjectReference # @param const_name [String] constant name def initialize(const_name) @const_name = const_name end # @return [Boolean] true if the named constant is defined, false otherwise. def defined? !!object end # @return [String] the constant name to replace with a double. def const_to_replace @const_name end alias description const_to_replace # @return [Object, nil] the target of the verifying double (the named object), or # nil if it is not defined. def target object end # Yields if the reference target is loaded, providing a generic mechanism # to optionally run a bit of code only when a reference's target is # loaded. # # @yield [Object] the target object def when_loaded yield object if object end private def object return @object if defined?(@object) @object = Constant.original(@const_name).original_value end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/test_double.rb0000664000000000000000000001176614557670305024674 0ustar rootrootmodule RSpec module Mocks # Implements the methods needed for a pure test double. RSpec::Mocks::Double # includes this module, and it is provided for cases where you want a # pure test double without subclassing RSpec::Mocks::Double. module TestDouble # Creates a new test double with a `name` (that will be used in error # messages only) def initialize(name=nil, stubs={}) @__expired = false if Hash === name && stubs.empty? stubs = name @name = nil else @name = name end assign_stubs(stubs) end # Tells the object to respond to all messages. If specific stub values # are declared, they'll work as expected. If not, the receiver is # returned. def as_null_object __mock_proxy.as_null_object end # Returns true if this object has received `as_null_object` def null_object? __mock_proxy.null_object? end # This allows for comparing the mock to other objects that proxy such as # ActiveRecords belongs_to proxy objects. By making the other object run # the comparison, we're sure the call gets delegated to the proxy # target. def ==(other) other == __mock_proxy end # @private def inspect TestDoubleFormatter.format(self) end # @private def to_s inspect.tr('<', '[').tr('>', ']') end # @private def respond_to?(message, incl_private=false) __mock_proxy.null_object? ? true : super end # @private def __build_mock_proxy_unless_expired(order_group) __raise_expired_error || __build_mock_proxy(order_group) end # @private def __disallow_further_usage! @__expired = true end # Override for default freeze implementation to prevent freezing of test # doubles. def freeze RSpec.warn_with("WARNING: you attempted to freeze a test double. This is explicitly a no-op as freezing doubles can lead to undesired behaviour when resetting tests.") self end private def method_missing(message, *args, &block) proxy = __mock_proxy proxy.record_message_received(message, *args, &block) if proxy.null_object? case message when :to_int then return 0 when :to_a, :to_ary then return nil when :to_str then return to_s else return self end end # Defined private and protected methods will still trigger `method_missing` # when called publicly. We want ruby's method visibility error to get raised, # so we simply delegate to `super` in that case. # ...well, we would delegate to `super`, but there's a JRuby # bug, so we raise our own visibility error instead: # https://github.com/jruby/jruby/issues/1398 visibility = proxy.visibility_for(message) if visibility == :private || visibility == :protected ErrorGenerator.new(self).raise_non_public_error( message, visibility ) end # Required wrapping doubles in an Array on Ruby 1.9.2 raise NoMethodError if [:to_a, :to_ary].include? message proxy.raise_unexpected_message_error(message, args) end def assign_stubs(stubs) stubs.each_pair do |message, response| __mock_proxy.add_simple_stub(message, response) end end def __mock_proxy ::RSpec::Mocks.space.proxy_for(self) end def __build_mock_proxy(order_group) TestDoubleProxy.new(self, order_group) end def __raise_expired_error return false unless @__expired ErrorGenerator.new(self).raise_expired_test_double_error end def initialize_copy(other) as_null_object if other.null_object? super end end # A generic test double object. `double`, `instance_double` and friends # return an instance of this. class Double include TestDouble end # @private module TestDoubleFormatter def self.format(dbl, unwrap=false) format = "#{type_desc(dbl)}#{verified_module_desc(dbl)} #{name_desc(dbl)}" return format if unwrap "#<#{format}>" end class << self private def type_desc(dbl) case dbl when InstanceVerifyingDouble then "InstanceDouble" when ClassVerifyingDouble then "ClassDouble" when ObjectVerifyingDouble then "ObjectDouble" else "Double" end end # @private IVAR_GET = Object.instance_method(:instance_variable_get) def verified_module_desc(dbl) return nil unless VerifyingDouble === dbl "(#{IVAR_GET.bind(dbl).call(:@doubled_module).description})" end def name_desc(dbl) return "(anonymous)" unless (name = IVAR_GET.bind(dbl).call(:@name)) name.inspect end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/syntax.rb0000664000000000000000000002670014557670305023703 0ustar rootrootmodule RSpec module Mocks # @api private # Provides methods for enabling and disabling the available syntaxes # provided by rspec-mocks. module Syntax # @private def self.warn_about_should! @warn_about_should = true end # @private def self.warn_unless_should_configured(method_name , replacement="the new `:expect` syntax or explicitly enable `:should`") if @warn_about_should RSpec.deprecate( "Using `#{method_name}` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax", :replacement => replacement ) @warn_about_should = false end end # @api private # Enables the should syntax (`dbl.stub`, `dbl.should_receive`, etc). def self.enable_should(syntax_host=default_should_syntax_host) @warn_about_should = false if syntax_host == default_should_syntax_host return if should_enabled?(syntax_host) syntax_host.class_exec do def should_receive(message, opts={}, &block) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) ::RSpec::Mocks.expect_message(self, message, opts, &block) end def should_not_receive(message, &block) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) ::RSpec::Mocks.expect_message(self, message, {}, &block).never end def stub(message_or_hash, opts={}, &block) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) if ::Hash === message_or_hash message_or_hash.each { |message, value| stub(message).and_return value } else ::RSpec::Mocks.allow_message(self, message_or_hash, opts, &block) end end def unstub(message) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__, "`allow(...).to receive(...).and_call_original` or explicitly enable `:should`") ::RSpec::Mocks.space.proxy_for(self).remove_stub(message) end def stub_chain(*chain, &blk) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) ::RSpec::Mocks::StubChain.stub_chain_on(self, *chain, &blk) end def as_null_object ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) @_null_object = true ::RSpec::Mocks.space.proxy_for(self).as_null_object end def null_object? ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) defined?(@_null_object) end def received_message?(message, *args, &block) ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) ::RSpec::Mocks.space.proxy_for(self).received_message?(message, *args, &block) end unless Class.respond_to? :any_instance Class.class_exec do def any_instance ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__) ::RSpec::Mocks.space.any_instance_proxy_for(self) end end end end end # @api private # Disables the should syntax (`dbl.stub`, `dbl.should_receive`, etc). def self.disable_should(syntax_host=default_should_syntax_host) return unless should_enabled?(syntax_host) syntax_host.class_exec do undef should_receive undef should_not_receive undef stub undef unstub undef stub_chain undef as_null_object undef null_object? undef received_message? end Class.class_exec do undef any_instance end end # @api private # Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). def self.enable_expect(syntax_host=::RSpec::Mocks::ExampleMethods) return if expect_enabled?(syntax_host) syntax_host.class_exec do def receive(method_name, &block) Matchers::Receive.new(method_name, block) end def receive_messages(message_return_value_hash) matcher = Matchers::ReceiveMessages.new(message_return_value_hash) matcher.warn_about_block if block_given? matcher end def receive_message_chain(*messages, &block) Matchers::ReceiveMessageChain.new(messages, &block) end def allow(target) AllowanceTarget.new(target) end def expect_any_instance_of(klass) AnyInstanceExpectationTarget.new(klass) end def allow_any_instance_of(klass) AnyInstanceAllowanceTarget.new(klass) end end RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do def expect(target) ExpectationTarget.new(target) end end end # @api private # Disables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). def self.disable_expect(syntax_host=::RSpec::Mocks::ExampleMethods) return unless expect_enabled?(syntax_host) syntax_host.class_exec do undef receive undef receive_messages undef receive_message_chain undef allow undef expect_any_instance_of undef allow_any_instance_of end RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do undef expect end end # @api private # Indicates whether or not the should syntax is enabled. def self.should_enabled?(syntax_host=default_should_syntax_host) syntax_host.method_defined?(:should_receive) end # @api private # Indicates whether or not the expect syntax is enabled. def self.expect_enabled?(syntax_host=::RSpec::Mocks::ExampleMethods) syntax_host.method_defined?(:allow) end # @api private # Determines where the methods like `should_receive`, and `stub` are added. def self.default_should_syntax_host # JRuby 1.7.4 introduces a regression whereby `defined?(::BasicObject) => nil` # yet `BasicObject` still exists and patching onto ::Object breaks things # e.g. SimpleDelegator expectations won't work # # See: https://github.com/jruby/jruby/issues/814 if defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4' && RUBY_VERSION.to_f > 1.8 return ::BasicObject end # On 1.8.7, Object.ancestors.last == Kernel but # things blow up if we include `RSpec::Mocks::Methods` # into Kernel...not sure why. return Object unless defined?(::BasicObject) # MacRuby has BasicObject but it's not the root class. return Object unless Object.ancestors.last == ::BasicObject ::BasicObject end end end end if defined?(BasicObject) # The legacy `:should` syntax adds the following methods directly to # `BasicObject` so that they are available off of any object. Note, however, # that this syntax does not always play nice with delegate/proxy objects. # We recommend you use the non-monkeypatching `:expect` syntax instead. # @see Class class BasicObject # @method should_receive # Sets an expectation that this object should receive a message before # the end of the example. # # @example # logger = double('logger') # thing_that_logs = ThingThatLogs.new(logger) # logger.should_receive(:log) # thing_that_logs.do_something_that_logs_a_message # # @note This is only available when you have enabled the `should` syntax. # @see RSpec::Mocks::ExampleMethods#expect # @method should_not_receive # Sets and expectation that this object should _not_ receive a message # during this example. # @see RSpec::Mocks::ExampleMethods#expect # @method stub # Tells the object to respond to the message with the specified value. # # @example # counter.stub(:count).and_return(37) # counter.stub(:count => 37) # counter.stub(:count) { 37 } # # @note This is only available when you have enabled the `should` syntax. # @see RSpec::Mocks::ExampleMethods#allow # @method unstub # Removes a stub. On a double, the object will no longer respond to # `message`. On a real object, the original method (if it exists) is # restored. # # This is rarely used, but can be useful when a stub is set up during a # shared `before` hook for the common case, but you want to replace it # for a special case. # # @note This is only available when you have enabled the `should` syntax. # @method stub_chain # @overload stub_chain(method1, method2) # @overload stub_chain("method1.method2") # @overload stub_chain(method1, method_to_value_hash) # # Stubs a chain of methods. # # ## Warning: # # Chains can be arbitrarily long, which makes it quite painless to # violate the Law of Demeter in violent ways, so you should consider any # use of `stub_chain` a code smell. Even though not all code smells # indicate real problems (think fluent interfaces), `stub_chain` still # results in brittle examples. For example, if you write # `foo.stub_chain(:bar, :baz => 37)` in a spec and then the # implementation calls `foo.baz.bar`, the stub will not work. # # @example # double.stub_chain("foo.bar") { :baz } # double.stub_chain(:foo, :bar => :baz) # double.stub_chain(:foo, :bar) { :baz } # # # Given any of ^^ these three forms ^^: # double.foo.bar # => :baz # # # Common use in Rails/ActiveRecord: # Article.stub_chain("recent.published") { [Article.new] } # # @note This is only available when you have enabled the `should` syntax. # @see RSpec::Mocks::ExampleMethods#receive_message_chain # @method as_null_object # Tells the object to respond to all messages. If specific stub values # are declared, they'll work as expected. If not, the receiver is # returned. # # @note This is only available when you have enabled the `should` syntax. # @method null_object? # Returns true if this object has received `as_null_object` # # @note This is only available when you have enabled the `should` syntax. end end # The legacy `:should` syntax adds the `any_instance` to `Class`. # We generally recommend you use the newer `:expect` syntax instead, # which allows you to stub any instance of a class using # `allow_any_instance_of(klass)` or mock any instance using # `expect_any_instance_of(klass)`. # @see BasicObject class Class # @method any_instance # Used to set stubs and message expectations on any instance of a given # class. Returns a [Recorder](Recorder), which records messages like # `stub` and `should_receive` for later playback on instances of the # class. # # @example # Car.any_instance.should_receive(:go) # race = Race.new # race.cars << Car.new # race.go # assuming this delegates to all of its cars # # this example would pass # # Account.any_instance.stub(:balance) { Money.new(:USD, 25) } # Account.new.balance # => Money.new(:USD, 25)) # # @return [Recorder] # # @note This is only available when you have enabled the `should` syntax. # @see RSpec::Mocks::ExampleMethods#expect_any_instance_of # @see RSpec::Mocks::ExampleMethods#allow_any_instance_of end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/instance_method_stasher.rb0000664000000000000000000001103514557670305027245 0ustar rootrootmodule RSpec module Mocks # @private class InstanceMethodStasher def initialize(object, method) @object = object @method = method @klass = (class << object; self; end) @original_method = nil @method_is_stashed = false end attr_reader :original_method if RUBY_VERSION.to_f < 1.9 # @private def method_is_stashed? @method_is_stashed end # @private def stash return if !method_defined_directly_on_klass? || @method_is_stashed @klass.__send__(:alias_method, stashed_method_name, @method) @method_is_stashed = true end # @private def stashed_method_name "obfuscated_by_rspec_mocks__#{@method}" end # @private def restore return unless @method_is_stashed if @klass.__send__(:method_defined?, @method) @klass.__send__(:undef_method, @method) end @klass.__send__(:alias_method, @method, stashed_method_name) @klass.__send__(:remove_method, stashed_method_name) @method_is_stashed = false end else # @private def method_is_stashed? !!@original_method end # @private def stash return unless method_defined_directly_on_klass? @original_method ||= ::RSpec::Support.method_handle_for(@object, @method) @klass.__send__(:undef_method, @method) end # @private def restore return unless @original_method if @klass.__send__(:method_defined?, @method) @klass.__send__(:undef_method, @method) end handle_restoration_failures do @klass.__send__(:define_method, @method, @original_method) end @original_method = nil end end if RUBY_DESCRIPTION.include?('2.0.0p247') || RUBY_DESCRIPTION.include?('2.0.0p195') # ruby 2.0.0-p247 and 2.0.0-p195 both have a bug that we can't work around :(. # https://bugs.ruby-lang.org/issues/8686 def handle_restoration_failures yield rescue TypeError RSpec.warn_with( "RSpec failed to properly restore a partial double (#{@object.inspect}) " \ "to its original state due to a known bug in MRI 2.0.0-p195 & p247 " \ "(https://bugs.ruby-lang.org/issues/8686). This object may remain " \ "screwed up for the rest of this process. Please upgrade to 2.0.0-p353 or above.", :call_site => nil, :use_spec_location_as_call_site => true ) end else def handle_restoration_failures # No known reasons for restoration to fail on other rubies. yield end end private # @private def method_defined_directly_on_klass? method_defined_on_klass? && method_owned_by_klass? end # @private def method_defined_on_klass?(klass=@klass) MethodReference.method_defined_at_any_visibility?(klass, @method) end def method_owned_by_klass? owner = @klass.instance_method(@method).owner # On Ruby 2.0.0+ the owner of a method on a class which has been # `prepend`ed may actually be an instance, e.g. # `#`, rather than the expected `MyClass`. owner = owner.class unless Module === owner # On some 1.9s (e.g. rubinius) aliased methods # can report the wrong owner. Example: # class MyClass # class << self # alias alternate_new new # end # end # # MyClass.owner(:alternate_new) returns `Class` when incorrect, # but we need to consider the owner to be `MyClass` because # it is not actually available on `Class` but is on `MyClass`. # Hence, we verify that the owner actually has the method defined. # If the given owner does not have the method defined, we assume # that the method is actually owned by @klass. # # On 1.8, aliased methods can also report the wrong owner. Example: # module M # def a; end # module_function :a # alias b a # module_function :b # end # The owner of M.b is the raw Module object, instead of the expected # singleton class of the module return true if RUBY_VERSION < '1.9' && owner == @object owner == @klass || !(method_defined_on_klass?(owner)) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/version.rb0000664000000000000000000000030614557670305024034 0ustar rootrootmodule RSpec module Mocks # Version information for RSpec mocks. module Version # Version of RSpec mocks currently in use in SemVer format. STRING = '3.13.0' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/0000775000000000000000000000000014557670305024476 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/proxy.rb0000664000000000000000000001124314557670305026205 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private # The `AnyInstance::Recorder` is responsible for redefining the klass's # instance method in order to add any stubs/expectations the first time # the method is called. It's not capable of updating a stub on an instance # that's already been previously stubbed (either directly, or via # `any_instance`). # # This proxy sits in front of the recorder and delegates both to it # and to the `RSpec::Mocks::Proxy` for each already mocked or stubbed # instance of the class, in order to propagates changes to the instances. # # Note that unlike `RSpec::Mocks::Proxy`, this proxy class is stateless # and is not persisted in `RSpec::Mocks.space`. # # Proxying for the message expectation fluent interface (typically chained # off of the return value of one of these methods) is provided by the # `FluentInterfaceProxy` class below. class Proxy def initialize(recorder, target_proxies) @recorder = recorder @target_proxies = target_proxies end def klass @recorder.klass end def stub(method_name_or_method_map, &block) if Hash === method_name_or_method_map method_name_or_method_map.each do |method_name, return_value| stub(method_name).and_return(return_value) end else perform_proxying(__method__, [method_name_or_method_map], block) do |proxy| proxy.add_stub(method_name_or_method_map, &block) end end end def unstub(method_name) perform_proxying(__method__, [method_name], nil) do |proxy| proxy.remove_stub_if_present(method_name) end end def stub_chain(*chain, &block) perform_proxying(__method__, chain, block) do |proxy| Mocks::StubChain.stub_chain_on(proxy.object, *chain, &block) end end def expect_chain(*chain, &block) perform_proxying(__method__, chain, block) do |proxy| Mocks::ExpectChain.expect_chain_on(proxy.object, *chain, &block) end end def should_receive(method_name, &block) perform_proxying(__method__, [method_name], block) do |proxy| # Yeah, this is a bit odd...but if we used `add_message_expectation` # then it would act like `expect_every_instance_of(klass).to receive`. # The any_instance recorder takes care of validating that an instance # received the message. proxy.add_stub(method_name, &block) end end def should_not_receive(method_name, &block) perform_proxying(__method__, [method_name], block) do |proxy| proxy.add_message_expectation(method_name, &block).never end end private def perform_proxying(method_name, args, block, &target_proxy_block) recorder_value = @recorder.__send__(method_name, *args, &block) proxy_values = @target_proxies.map(&target_proxy_block) FluentInterfaceProxy.new([recorder_value] + proxy_values) end end unless defined?(BasicObject) class BasicObject # Remove all methods except those expected to be defined on BasicObject (instance_methods.map(&:to_sym) - [:__send__, :"!", :instance_eval, :==, :instance_exec, :"!=", :equal?, :__id__, :__binding__, :object_id]).each do |method| undef_method method end end end # @private # Delegates messages to each of the given targets in order to # provide the fluent interface that is available off of message # expectations when dealing with `any_instance`. # # `targets` will typically contain 1 of the `AnyInstance::Recorder` # return values and N `MessageExpectation` instances (one per instance # of the `any_instance` klass). class FluentInterfaceProxy < BasicObject def initialize(targets) @targets = targets end if ::RUBY_VERSION.to_f > 1.8 def respond_to_missing?(method_name, include_private=false) super || @targets.first.respond_to?(method_name, include_private) end else def respond_to?(method_name, include_private=false) super || @targets.first.respond_to?(method_name, include_private) end end def method_missing(*args, &block) return_values = @targets.map { |t| t.__send__(*args, &block) } FluentInterfaceProxy.new(return_values) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/stub_chain_chain.rb0000664000000000000000000000075014557670305030306 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class StubChainChain < StubChain def initialize(*args) super @expectation_fulfilled = false end private def create_message_expectation_on(instance) ::RSpec::Mocks::StubChain.stub_chain_on(instance, *@expectation_args, &@expectation_block) end def invocation_order EmptyInvocationOrder end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/message_chains.rb0000664000000000000000000000461614557670305030003 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class MessageChains def initialize @chains_by_method_name = Hash.new { |h, k| h[k] = [] } end # @private def [](method_name) @chains_by_method_name[method_name] end # @private def add(method_name, chain) @chains_by_method_name[method_name] << chain chain end # @private def remove_stub_chains_for!(method_name) @chains_by_method_name[method_name].reject! do |chain| StubChain === chain end end # @private def has_expectation?(method_name) @chains_by_method_name[method_name].find do |chain| ExpectationChain === chain end end # @private def each_unfulfilled_expectation_matching(method_name, *args) @chains_by_method_name[method_name].each do |chain| yield chain if !chain.expectation_fulfilled? && chain.matches_args?(*args) end end # @private def all_expectations_fulfilled? @chains_by_method_name.all? do |_method_name, chains| chains.all? { |chain| chain.expectation_fulfilled? } end end # @private def unfulfilled_expectations @chains_by_method_name.map do |method_name, chains| method_name.to_s if ExpectationChain === chains.last && !chains.last.expectation_fulfilled? end.compact end # @private def received_expected_message!(method_name) @chains_by_method_name[method_name].each do |chain| chain.expectation_fulfilled! end end # @private def playback!(instance, method_name) raise_if_second_instance_to_receive_message(instance) @chains_by_method_name[method_name].each do |chain| chain.playback!(instance) end end private def raise_if_second_instance_to_receive_message(instance) @instance_with_expectation ||= instance if ExpectationChain === instance return unless ExpectationChain === instance return if @instance_with_expectation.equal?(instance) AnyInstance.error_generator.raise_second_instance_received_message_error(unfulfilled_expectations) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/expect_chain_chain.rb0000664000000000000000000000124214557670305030616 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class ExpectChainChain < StubChain def initialize(*args) super @expectation_fulfilled = false end def expectation_fulfilled? @expectation_fulfilled end def playback!(instance) super.tap { @expectation_fulfilled = true } end private def create_message_expectation_on(instance) ::RSpec::Mocks::ExpectChain.expect_chain_on(instance, *@expectation_args, &@expectation_block) end def invocation_order EmptyInvocationOrder end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/chain.rb0000664000000000000000000000566514557670305026121 0ustar rootrootmodule RSpec module Mocks # @private module AnyInstance # @private class Chain def initialize(recorder, *args, &block) @recorder = recorder @expectation_args = args @expectation_block = block @argument_list_matcher = ArgumentListMatcher::MATCH_ALL end # @private # # Provides convenience methods for recording customizations on message # expectations. module Customizations # @macro [attach] record # @method $1(*args, &block) # Records the `$1` message for playback against an instance that # invokes a method stubbed or mocked using `any_instance`. # # @see RSpec::Mocks::MessageExpectation#$1 # def self.record(method_name) define_method(method_name) do |*args, &block| record(method_name, *args, &block) end end record :and_return record :and_raise record :and_throw record :and_yield record :and_call_original record :and_wrap_original record :with record :once record :twice record :thrice record :exactly record :times record :time record :never record :at_least record :at_most end include Customizations # @private def playback!(instance) message_expectation = create_message_expectation_on(instance) messages.inject(message_expectation) do |object, message| object.__send__(*message.first, &message.last) end end # @private def constrained_to_any_of?(*constraints) constraints.any? do |constraint| messages.any? do |message| message.first.first == constraint end end end # @private def matches_args?(*args) @argument_list_matcher.args_match?(*args) end # @private def expectation_fulfilled! @expectation_fulfilled = true end def never AnyInstance.error_generator.raise_double_negation_error("expect_any_instance_of(MyClass)") if negated? super end def with(*args, &block) @argument_list_matcher = ArgumentListMatcher.new(*args) super end private def negated? messages.any? { |(message, *_), _| message == :never } end def messages @messages ||= [] end def last_message messages.last.first.first unless messages.empty? end def record(rspec_method_name, *args, &block) verify_invocation_order(rspec_method_name, *args, &block) messages << [args.unshift(rspec_method_name), block] self end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb0000664000000000000000000002611414557670305026634 0ustar rootrootmodule RSpec module Mocks module AnyInstance # Given a class `TheClass`, `TheClass.any_instance` returns a `Recorder`, # which records stubs and message expectations for later playback on # instances of `TheClass`. # # Further constraints are stored in instances of [Chain](Chain). # # @see AnyInstance # @see Chain class Recorder # @private attr_reader :message_chains, :stubs, :klass def initialize(klass) @message_chains = MessageChains.new @stubs = Hash.new { |hash, key| hash[key] = [] } @observed_methods = [] @played_methods = {} @backed_up_method_owner = {} @klass = klass @expectation_set = false return unless RSpec::Mocks.configuration.verify_partial_doubles? RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| block.call(ObjectReference.for(klass)) end end # Initializes the recording a stub to be played back against any # instance of this object that invokes the submitted method. # # @see Methods#stub def stub(method_name, &block) observe!(method_name) message_chains.add(method_name, StubChain.new(self, method_name, &block)) end # Initializes the recording a stub chain to be played back against any # instance of this object that invokes the method matching the first # argument. # # @see Methods#stub_chain def stub_chain(*method_names_and_optional_return_values, &block) normalize_chain(*method_names_and_optional_return_values) do |method_name, args| observe!(method_name) message_chains.add(method_name, StubChainChain.new(self, *args, &block)) end end # @private def expect_chain(*method_names_and_optional_return_values, &block) @expectation_set = true normalize_chain(*method_names_and_optional_return_values) do |method_name, args| observe!(method_name) message_chains.add(method_name, ExpectChainChain.new(self, *args, &block)) end end # Initializes the recording a message expectation to be played back # against any instance of this object that invokes the submitted # method. # # @see Methods#should_receive def should_receive(method_name, &block) @expectation_set = true observe!(method_name) message_chains.add(method_name, PositiveExpectationChain.new(self, method_name, &block)) end # The opposite of `should_receive` # # @see Methods#should_not_receive def should_not_receive(method_name, &block) should_receive(method_name, &block).never end # Removes any previously recorded stubs, stub_chains or message # expectations that use `method_name`. # # @see Methods#unstub def unstub(method_name) unless @observed_methods.include?(method_name.to_sym) AnyInstance.error_generator.raise_method_not_stubbed_error(method_name) end message_chains.remove_stub_chains_for!(method_name) stubs[method_name].clear stop_observing!(method_name) unless message_chains.has_expectation?(method_name) end # @api private # # Used internally to verify that message expectations have been # fulfilled. def verify return unless @expectation_set return if message_chains.all_expectations_fulfilled? AnyInstance.error_generator.raise_second_instance_received_message_error(message_chains.unfulfilled_expectations) end # @private def stop_all_observation! @observed_methods.each { |method_name| restore_method!(method_name) } end # @private def playback!(instance, method_name) RSpec::Mocks.space.ensure_registered(instance) message_chains.playback!(instance, method_name) @played_methods[method_name] = instance received_expected_message!(method_name) if message_chains.has_expectation?(method_name) end # @private def instance_that_received(method_name) @played_methods[method_name] end # @private def build_alias_method_name(method_name) "__#{method_name}_without_any_instance__" end # @private def already_observing?(method_name) @observed_methods.include?(method_name) || super_class_observing?(method_name) end # @private def notify_received_message(_object, message, args, _blk) has_expectation = false message_chains.each_unfulfilled_expectation_matching(message, *args) do |expectation| has_expectation = true expectation.expectation_fulfilled! end return unless has_expectation restore_method!(message) mark_invoked!(message) end protected def stop_observing!(method_name) restore_method!(method_name) @observed_methods.delete(method_name) super_class_observers_for(method_name).each do |ancestor| ::RSpec::Mocks.space. any_instance_recorder_for(ancestor).stop_observing!(method_name) end end private def ancestor_is_an_observer?(ancestor, method_name) return if ancestor == @klass ::RSpec::Mocks.space. any_instance_recorder_for(ancestor).already_observing?(method_name) end def super_class_observers_for(method_name) @klass.ancestors.select do |ancestor| ancestor_is_an_observer?(ancestor, method_name) end end def super_class_observing?(method_name) @klass.ancestors.any? do |ancestor| ancestor_is_an_observer?(ancestor, method_name) end end def normalize_chain(*args) args.shift.to_s.split('.').map { |s| s.to_sym }.reverse.each { |a| args.unshift a } yield args.first, args end def received_expected_message!(method_name) message_chains.received_expected_message!(method_name) restore_method!(method_name) mark_invoked!(method_name) end def restore_method!(method_name) if public_protected_or_private_method_defined?(build_alias_method_name(method_name)) restore_original_method!(method_name) else remove_dummy_method!(method_name) end end def restore_original_method!(method_name) return unless @klass.instance_method(method_name).owner == @klass alias_method_name = build_alias_method_name(method_name) @klass.class_exec(@backed_up_method_owner) do |backed_up_method_owner| remove_method method_name # A @klass can have methods implemented (see Method#owner) in @klass # or inherited from a superclass. In ruby 2.2 and earlier, we can copy # a method regardless of the 'owner' and restore it to @klass after # because a call to 'super' from @klass's copied method would end up # calling the original class's superclass's method. # # With the commit below, available starting in 2.3.0, ruby changed # this behavior and a call to 'super' from the method copied to @klass # will call @klass's superclass method, which is the original # implementer of this method! This leads to very strange errors # if @klass's copied method calls 'super', since it would end up # calling itself, the original method implemented in @klass's # superclass. # # For ruby 2.3 and above, we need to only restore methods that # @klass originally owned. # # https://github.com/ruby/ruby/commit/c8854d2ca4be9ee6946e6d17b0e17d9ef130ee81 if RUBY_VERSION < "2.3" || backed_up_method_owner[method_name.to_sym] == self alias_method method_name, alias_method_name end remove_method alias_method_name end end def remove_dummy_method!(method_name) @klass.class_exec do remove_method method_name end end def backup_method!(method_name) return unless public_protected_or_private_method_defined?(method_name) alias_method_name = build_alias_method_name(method_name) @backed_up_method_owner[method_name.to_sym] ||= @klass.instance_method(method_name).owner @klass.class_exec do alias_method alias_method_name, method_name end end def public_protected_or_private_method_defined?(method_name) MethodReference.method_defined_at_any_visibility?(@klass, method_name) end def observe!(method_name) allow_no_prepended_module_definition_of(method_name) if RSpec::Mocks.configuration.verify_partial_doubles? && !Mocks.configuration.temporarily_suppress_partial_double_verification unless public_protected_or_private_method_defined?(method_name) AnyInstance.error_generator.raise_does_not_implement_error(@klass, method_name) end end stop_observing!(method_name) if already_observing?(method_name) @observed_methods << method_name backup_method!(method_name) recorder = self @klass.__send__(:define_method, method_name) do |*args, &blk| recorder.playback!(self, method_name) __send__(method_name, *args, &blk) end @klass.__send__(:ruby2_keywords, method_name) if @klass.respond_to?(:ruby2_keywords, true) end def mark_invoked!(method_name) backup_method!(method_name) recorder = self @klass.__send__(:define_method, method_name) do |*_args, &_blk| invoked_instance = recorder.instance_that_received(method_name) inspect = "#<#{self.class}:#{object_id} #{instance_variables.map { |name| "#{name}=#{instance_variable_get name}" }.join(', ')}>" AnyInstance.error_generator.raise_message_already_received_by_other_instance_error( method_name, inspect, invoked_instance ) end end if Support::RubyFeatures.module_prepends_supported? def allow_no_prepended_module_definition_of(method_name) prepended_modules = RSpec::Mocks::Proxy.prepended_modules_of(@klass) problem_mod = prepended_modules.find { |mod| mod.method_defined?(method_name) } return unless problem_mod AnyInstance.error_generator.raise_not_supported_with_prepend_error(method_name, problem_mod) end else def allow_no_prepended_module_definition_of(_method_name) # nothing to do; prepends aren't supported on this version of ruby end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/expectation_chain.rb0000664000000000000000000000241514557670305030512 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class ExpectationChain < Chain def expectation_fulfilled? @expectation_fulfilled || constrained_to_any_of?(:never) end def initialize(*args, &block) @expectation_fulfilled = false super end private def verify_invocation_order(_rspec_method_name, *_args, &_block) end end # @private class PositiveExpectationChain < ExpectationChain private def create_message_expectation_on(instance) proxy = ::RSpec::Mocks.space.proxy_for(instance) method_name, opts = @expectation_args opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE) me = proxy.add_message_expectation(method_name, opts, &@expectation_block) if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks? me.and_yield_receiver_to_implementation end me end ExpectationInvocationOrder = { :and_return => [:with, nil], :and_raise => [:with, nil], }.freeze def invocation_order ExpectationInvocationOrder end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/error_generator.rb0000664000000000000000000000226014557670305030222 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class ErrorGenerator < ::RSpec::Mocks::ErrorGenerator def raise_second_instance_received_message_error(unfulfilled_expectations) __raise "Exactly one instance should have received the following " \ "message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}" end def raise_does_not_implement_error(klass, method_name) __raise "#{klass} does not implement ##{method_name}" end def raise_message_already_received_by_other_instance_error(method_name, object_inspect, invoked_instance) __raise "The message '#{method_name}' was received by #{object_inspect} " \ "but has already been received by #{invoked_instance}" end def raise_not_supported_with_prepend_error(method_name, problem_mod) __raise "Using `any_instance` to stub a method (#{method_name}) that has been " \ "defined on a prepended module (#{problem_mod}) is not supported." end end def self.error_generator @error_generator ||= ErrorGenerator.new end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance/stub_chain.rb0000664000000000000000000000266014557670305027146 0ustar rootrootmodule RSpec module Mocks module AnyInstance # @private class StubChain < Chain # @private def expectation_fulfilled? true end private def create_message_expectation_on(instance) proxy = ::RSpec::Mocks.space.proxy_for(instance) method_name, opts = @expectation_args opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE) stub = proxy.add_stub(method_name, opts, &@expectation_block) @recorder.stubs[stub.message] << stub if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks? stub.and_yield_receiver_to_implementation end stub end InvocationOrder = { :and_return => [:with, nil], :and_raise => [:with, nil], :and_yield => [:with, :and_yield, nil], :and_throw => [:with, nil], :and_call_original => [:with, nil], :and_wrap_original => [:with, nil] }.freeze EmptyInvocationOrder = {}.freeze def invocation_order InvocationOrder end def verify_invocation_order(rspec_method_name, *_args, &_block) return if invocation_order.fetch(rspec_method_name, [nil]).include?(last_message) raise NoMethodError, "Undefined method #{rspec_method_name}" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/standalone.rb0000664000000000000000000000011514557670305024475 0ustar rootrootrequire 'rspec/mocks' extend RSpec::Mocks::ExampleMethods RSpec::Mocks.setup ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/argument_list_matcher.rb0000664000000000000000000001124414557670305026732 0ustar rootroot# We intentionally do not use the `RSpec::Support.require...` methods # here so that this file can be loaded individually, as documented # below. require 'rspec/mocks/argument_matchers' require 'rspec/support/fuzzy_matcher' module RSpec module Mocks # Wrapper for matching arguments against a list of expected values. Used by # the `with` method on a `MessageExpectation`: # # expect(object).to receive(:message).with(:a, 'b', 3) # object.message(:a, 'b', 3) # # Values passed to `with` can be literal values or argument matchers that # match against the real objects .e.g. # # expect(object).to receive(:message).with(hash_including(:a => 'b')) # # Can also be used directly to match the contents of any `Array`. This # enables 3rd party mocking libs to take advantage of rspec's argument # matching without using the rest of rspec-mocks. # # require 'rspec/mocks/argument_list_matcher' # include RSpec::Mocks::ArgumentMatchers # # arg_list_matcher = RSpec::Mocks::ArgumentListMatcher.new(123, hash_including(:a => 'b')) # arg_list_matcher.args_match?(123, :a => 'b') # # This class is immutable. # # @see ArgumentMatchers class ArgumentListMatcher # @private attr_reader :expected_args # @api public # @param [Array] expected_args a list of expected literals and/or argument matchers # # Initializes an `ArgumentListMatcher` with a collection of literal # values and/or argument matchers. # # @see ArgumentMatchers # @see #args_match? def initialize(*expected_args) @expected_args = expected_args ensure_expected_args_valid! end ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true) # @api public # @param [Array] actual_args # # Matches each element in the `expected_args` against the element in the same # position of the arguments passed to `new`. # # @see #initialize def args_match?(*actual_args) expected_args = resolve_expected_args_based_on(actual_args) return false if expected_args.size != actual_args.size if RUBY_VERSION >= "3" # If the expectation was set with keywords, while the actual method was called with a positional hash argument, they don't match. # If the expectation was set without keywords, e.g., with({a: 1}), then it fine to call it with either foo(a: 1) or foo({a: 1}). # This corresponds to Ruby semantics, as if the method was def foo(options). if Hash === expected_args.last && Hash === actual_args.last if !Hash.ruby2_keywords_hash?(actual_args.last) && Hash.ruby2_keywords_hash?(expected_args.last) return false end end end Support::FuzzyMatcher.values_match?(expected_args, actual_args) end ruby2_keywords :args_match? if respond_to?(:ruby2_keywords, true) # @private # Resolves abstract arg placeholders like `no_args` and `any_args` into # a more concrete arg list based on the provided `actual_args`. def resolve_expected_args_based_on(actual_args) return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] == expected_args any_args_index = expected_args.index { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } return expected_args unless any_args_index replace_any_args_with_splat_of_anything(any_args_index, actual_args.count) end private def replace_any_args_with_splat_of_anything(before_count, actual_args_count) any_args_count = actual_args_count - expected_args.count + 1 after_count = expected_args.count - before_count - 1 any_args = 1.upto(any_args_count).map { ArgumentMatchers::AnyArgMatcher::INSTANCE } expected_args.first(before_count) + any_args + expected_args.last(after_count) end def ensure_expected_args_valid! if expected_args.count { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } > 1 raise ArgumentError, "`any_args` can only be passed to " \ "`with` once but you have passed it multiple times." elsif expected_args.count > 1 && expected_args.any? { |a| ArgumentMatchers::NoArgsMatcher::INSTANCE == a } raise ArgumentError, "`no_args` can only be passed as a " \ "singleton argument to `with` (i.e. `with(no_args)`), " \ "but you have passed additional arguments." end end # Value that will match all argument lists. # # @private MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher::INSTANCE) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/marshal_extension.rb0000664000000000000000000000222214557670305026071 0ustar rootrootmodule RSpec module Mocks # Support for `patch_marshal_to_support_partial_doubles` configuration. # # @private class MarshalExtension def self.patch! return if Marshal.respond_to?(:dump_with_rspec_mocks) Marshal.instance_eval do class << self def dump_with_rspec_mocks(object, *rest) if !::RSpec::Mocks.space.registered?(object) || NilClass === object dump_without_rspec_mocks(object, *rest) else dump_without_rspec_mocks(object.dup, *rest) end end alias_method :dump_without_rspec_mocks, :dump undef_method :dump alias_method :dump, :dump_with_rspec_mocks end end end def self.unpatch! return unless Marshal.respond_to?(:dump_with_rspec_mocks) Marshal.instance_eval do class << self undef_method :dump_with_rspec_mocks undef_method :dump alias_method :dump, :dump_without_rspec_mocks undef_method :dump_without_rspec_mocks end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/configuration.rb0000664000000000000000000001612314557670305025222 0ustar rootrootmodule RSpec module Mocks # Provides configuration options for rspec-mocks. class Configuration def initialize @allow_message_expectations_on_nil = nil @yield_receiver_to_any_instance_implementation_blocks = true @verify_doubled_constant_names = false @transfer_nested_constants = false @verify_partial_doubles = false @temporarily_suppress_partial_double_verification = false @color = false end # Sets whether RSpec will warn, ignore, or fail a test when # expectations are set on nil. # By default, when this flag is not set, warning messages are issued when # expectations are set on nil. This is to prevent false-positives and to # catch potential bugs early on. # When set to `true`, warning messages are suppressed. # When set to `false`, it will raise an error. # # @example # RSpec.configure do |config| # config.mock_with :rspec do |mocks| # mocks.allow_message_expectations_on_nil = false # end # end attr_accessor :allow_message_expectations_on_nil def yield_receiver_to_any_instance_implementation_blocks? @yield_receiver_to_any_instance_implementation_blocks end # Sets whether or not RSpec will yield the receiving instance of a # message to blocks that are used for any_instance stub implementations. # When set, the first yielded argument will be the receiving instance. # Defaults to `true`. # # @example # RSpec.configure do |rspec| # rspec.mock_with :rspec do |mocks| # mocks.yield_receiver_to_any_instance_implementation_blocks = false # end # end attr_writer :yield_receiver_to_any_instance_implementation_blocks # Adds `stub` and `should_receive` to the given # modules or classes. This is usually only necessary # if you application uses some proxy classes that # "strip themselves down" to a bare minimum set of # methods and remove `stub` and `should_receive` in # the process. # # @example # RSpec.configure do |rspec| # rspec.mock_with :rspec do |mocks| # mocks.add_stub_and_should_receive_to Delegator # end # end # def add_stub_and_should_receive_to(*modules) modules.each do |mod| Syntax.enable_should(mod) end end # Provides the ability to set either `expect`, # `should` or both syntaxes. RSpec uses `expect` # syntax by default. This is needed if you want to # explicitly enable `should` syntax and/or explicitly # disable `expect` syntax. # # @example # RSpec.configure do |rspec| # rspec.mock_with :rspec do |mocks| # mocks.syntax = [:expect, :should] # end # end # def syntax=(*values) syntaxes = values.flatten if syntaxes.include?(:expect) Syntax.enable_expect else Syntax.disable_expect end if syntaxes.include?(:should) Syntax.enable_should else Syntax.disable_should end end # Returns an array with a list of syntaxes # that are enabled. # # @example # unless RSpec::Mocks.configuration.syntax.include?(:expect) # raise "this RSpec extension gem requires the rspec-mocks `:expect` syntax" # end # def syntax syntaxes = [] syntaxes << :should if Syntax.should_enabled? syntaxes << :expect if Syntax.expect_enabled? syntaxes end def verify_doubled_constant_names? !!@verify_doubled_constant_names end # When this is set to true, an error will be raised when # `instance_double` or `class_double` is given the name of an undefined # constant. You probably only want to set this when running your entire # test suite, with all production code loaded. Setting this for an # isolated unit test will prevent you from being able to isolate it! attr_writer :verify_doubled_constant_names # Provides a way to perform customisations when verifying doubles. # # @example # RSpec::Mocks.configuration.before_verifying_doubles do |ref| # ref.some_method! # end def before_verifying_doubles(&block) verifying_double_callbacks << block end alias :when_declaring_verifying_double :before_verifying_doubles # @api private # Returns an array of blocks to call when verifying doubles def verifying_double_callbacks @verifying_double_callbacks ||= [] end def transfer_nested_constants? !!@transfer_nested_constants end # Sets the default for the `transfer_nested_constants` option when # stubbing constants. attr_writer :transfer_nested_constants # When set to true, partial mocks will be verified the same as object # doubles. Any stubs will have their arguments checked against the original # method, and methods that do not exist cannot be stubbed. def verify_partial_doubles=(val) @verify_partial_doubles = !!val end def verify_partial_doubles? @verify_partial_doubles end # @private # Used to track wether we are temporarily suppressing verifying partial # doubles with `without_partial_double_verification { ... }` attr_accessor :temporarily_suppress_partial_double_verification if ::RSpec.respond_to?(:configuration) def color? ::RSpec.configuration.color_enabled? end else # Indicates whether or not diffs should be colored. # Delegates to rspec-core's color option if rspec-core # is loaded; otherwise you can set it here. attr_writer :color # Indicates whether or not diffs should be colored. # Delegates to rspec-core's color option if rspec-core # is loaded; otherwise you can set it here. def color? @color end end # Monkey-patch `Marshal.dump` to enable dumping of mocked or stubbed # objects. By default this will not work since RSpec mocks works by # adding singleton methods that cannot be serialized. This patch removes # these singleton methods before serialization. Setting to falsey removes # the patch. # # This method is idempotent. def patch_marshal_to_support_partial_doubles=(val) if val RSpec::Mocks::MarshalExtension.patch! else RSpec::Mocks::MarshalExtension.unpatch! end end # @api private # Resets the configured syntax to the default. def reset_syntaxes_to_default self.syntax = [:should, :expect] RSpec::Mocks::Syntax.warn_about_should! end end # Mocks specific configuration, as distinct from `RSpec.configuration` # which is core RSpec configuration. def self.configuration @configuration ||= Configuration.new end configuration.reset_syntaxes_to_default end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/mutate_const.rb0000664000000000000000000002502414557670305025060 0ustar rootrootRSpec::Support.require_rspec_support 'recursive_const_methods' module RSpec module Mocks # Provides information about constants that may (or may not) # have been mutated by rspec-mocks. class Constant extend Support::RecursiveConstMethods # @api private def initialize(name) @name = name @previously_defined = false @stubbed = false @hidden = false @valid_name = true yield self if block_given? end # @return [String] The fully qualified name of the constant. attr_reader :name # @return [Object, nil] The original value (e.g. before it # was mutated by rspec-mocks) of the constant, or # nil if the constant was not previously defined. attr_accessor :original_value # @private attr_writer :previously_defined, :stubbed, :hidden, :valid_name # @return [Boolean] Whether or not the constant was defined # before the current example. def previously_defined? @previously_defined end # @return [Boolean] Whether or not rspec-mocks has mutated # (stubbed or hidden) this constant. def mutated? @stubbed || @hidden end # @return [Boolean] Whether or not rspec-mocks has stubbed # this constant. def stubbed? @stubbed end # @return [Boolean] Whether or not rspec-mocks has hidden # this constant. def hidden? @hidden end # @return [Boolean] Whether or not the provided constant name # is a valid Ruby constant name. def valid_name? @valid_name end # The default `to_s` isn't very useful, so a custom version is provided. def to_s "#<#{self.class.name} #{name}>" end alias inspect to_s # @private def self.unmutated(name) previously_defined = !!recursive_const_defined?(name) rescue NameError new(name) do |c| c.valid_name = false end else new(name) do |const| const.previously_defined = previously_defined const.original_value = recursive_const_get(name) if previously_defined end end # Queries rspec-mocks to find out information about the named constant. # # @param [String] name the name of the constant # @return [Constant] an object containing information about the named # constant. def self.original(name) mutator = ::RSpec::Mocks.space.constant_mutator_for(name) mutator ? mutator.to_constant : unmutated(name) end end # Provides a means to stub constants. class ConstantMutator extend Support::RecursiveConstMethods # Stubs a constant. # # @param (see ExampleMethods#stub_const) # @option (see ExampleMethods#stub_const) # @return (see ExampleMethods#stub_const) # # @see ExampleMethods#stub_const # @note It's recommended that you use `stub_const` in your # examples. This is an alternate public API that is provided # so you can stub constants in other contexts (e.g. helper # classes). def self.stub(constant_name, value, options={}) unless String === constant_name raise ArgumentError, "`stub_const` requires a String, but you provided a #{constant_name.class.name}" end mutator = if recursive_const_defined?(constant_name, &raise_on_invalid_const) DefinedConstantReplacer else UndefinedConstantSetter end mutate(mutator.new(constant_name, value, options[:transfer_nested_constants])) value end # Hides a constant. # # @param (see ExampleMethods#hide_const) # # @see ExampleMethods#hide_const # @note It's recommended that you use `hide_const` in your # examples. This is an alternate public API that is provided # so you can hide constants in other contexts (e.g. helper # classes). def self.hide(constant_name) mutate(ConstantHider.new(constant_name, nil, {})) nil end # Contains common functionality used by all of the constant mutators. # # @private class BaseMutator include Support::RecursiveConstMethods attr_reader :original_value, :full_constant_name def initialize(full_constant_name, mutated_value, transfer_nested_constants) @full_constant_name = normalize_const_name(full_constant_name) @mutated_value = mutated_value @transfer_nested_constants = transfer_nested_constants @context_parts = @full_constant_name.split('::') @const_name = @context_parts.pop @reset_performed = false end def to_constant const = Constant.new(full_constant_name) const.original_value = original_value const end def idempotently_reset reset unless @reset_performed @reset_performed = true end end # Hides a defined constant for the duration of an example. # # @private class ConstantHider < BaseMutator def mutate return unless (@defined = recursive_const_defined?(full_constant_name)) @context = recursive_const_get(@context_parts.join('::')) @original_value = get_const_defined_on(@context, @const_name) @context.__send__(:remove_const, @const_name) end def to_constant return Constant.unmutated(full_constant_name) unless @defined const = super const.hidden = true const.previously_defined = true const end def reset return unless @defined @context.const_set(@const_name, @original_value) end end # Replaces a defined constant for the duration of an example. # # @private class DefinedConstantReplacer < BaseMutator def initialize(*args) super @constants_to_transfer = [] end def mutate @context = recursive_const_get(@context_parts.join('::')) @original_value = get_const_defined_on(@context, @const_name) @constants_to_transfer = verify_constants_to_transfer! @context.__send__(:remove_const, @const_name) @context.const_set(@const_name, @mutated_value) transfer_nested_constants end def to_constant const = super const.stubbed = true const.previously_defined = true const end def reset @constants_to_transfer.each do |const| @mutated_value.__send__(:remove_const, const) end @context.__send__(:remove_const, @const_name) @context.const_set(@const_name, @original_value) end def transfer_nested_constants @constants_to_transfer.each do |const| @mutated_value.const_set(const, get_const_defined_on(original_value, const)) end end def verify_constants_to_transfer! return [] unless should_transfer_nested_constants? { @original_value => "the original value", @mutated_value => "the stubbed value" }.each do |value, description| next if value.respond_to?(:constants) raise ArgumentError, "Cannot transfer nested constants for #{@full_constant_name} " \ "since #{description} is not a class or module and only classes " \ "and modules support nested constants." end if Array === @transfer_nested_constants @transfer_nested_constants = @transfer_nested_constants.map(&:to_s) if RUBY_VERSION == '1.8.7' undefined_constants = @transfer_nested_constants - constants_defined_on(@original_value) if undefined_constants.any? available_constants = constants_defined_on(@original_value) - @transfer_nested_constants raise ArgumentError, "Cannot transfer nested constant(s) #{undefined_constants.join(' and ')} " \ "for #{@full_constant_name} since they are not defined. Did you mean " \ "#{available_constants.join(' or ')}?" end @transfer_nested_constants else constants_defined_on(@original_value) end end def should_transfer_nested_constants? return true if @transfer_nested_constants return false unless RSpec::Mocks.configuration.transfer_nested_constants? @original_value.respond_to?(:constants) && @mutated_value.respond_to?(:constants) end end # Sets an undefined constant for the duration of an example. # # @private class UndefinedConstantSetter < BaseMutator def mutate @parent = @context_parts.inject(Object) do |klass, name| if const_defined_on?(klass, name) get_const_defined_on(klass, name) else ConstantMutator.stub(name_for(klass, name), Module.new) end end @parent.const_set(@const_name, @mutated_value) end def to_constant const = super const.stubbed = true const.previously_defined = false const end def reset @parent.__send__(:remove_const, @const_name) end private def name_for(parent, name) root = if parent == Object '' else parent.name end root + '::' + name end end # Uses the mutator to mutate (stub or hide) a constant. Ensures that # the mutator is correctly registered so it can be backed out at the end # of the test. # # @private def self.mutate(mutator) ::RSpec::Mocks.space.register_constant_mutator(mutator) mutator.mutate end # Used internally by the constant stubbing to raise a helpful # error when a constant like "A::B::C" is stubbed and A::B is # not a module (and thus, it's impossible to define "A::B::C" # since only modules can have nested constants). # # @api private def self.raise_on_invalid_const lambda do |const_name, failed_name| raise "Cannot stub constant #{failed_name} on #{const_name} " \ "since #{const_name} is not a module." end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/message_expectation.rb0000664000000000000000000006761614557670305026417 0ustar rootrootRSpec::Support.require_rspec_support 'mutex' module RSpec module Mocks # A message expectation that only allows concrete return values to be set # for a message. While this same effect can be achieved using a standard # MessageExpectation, this version is much faster and so can be used as an # optimization. # # @private class SimpleMessageExpectation def initialize(message, response, error_generator, backtrace_line=nil) @message, @response, @error_generator, @backtrace_line = message.to_sym, response, error_generator, backtrace_line @received = false end def invoke(*_) @received = true @response end def matches?(message, *_) @message == message.to_sym end def called_max_times? false end def verify_messages_received return if @received @error_generator.raise_expectation_error( @message, 1, ArgumentListMatcher::MATCH_ALL, 0, nil, [], @backtrace_line ) end def unadvise(_) end end # Represents an individual method stub or message expectation. The methods # defined here can be used to configure how it behaves. The methods return # `self` so that they can be chained together to form a fluent interface. class MessageExpectation # @!group Configuring Responses # @overload and_return(value) # @overload and_return(first_value, second_value) # # Tells the object to return a value when it receives the message. Given # more than one value, the first value is returned the first time the # message is received, the second value is returned the next time, etc, # etc. # # If the message is received more times than there are values, the last # value is returned for every subsequent call. # # @return [nil] No further chaining is supported after this. # @example # allow(counter).to receive(:count).and_return(1) # counter.count # => 1 # counter.count # => 1 # # allow(counter).to receive(:count).and_return(1,2,3) # counter.count # => 1 # counter.count # => 2 # counter.count # => 3 # counter.count # => 3 # counter.count # => 3 # # etc def and_return(first_value, *values) raise_already_invoked_error_if_necessary(__method__) if negative? raise "`and_return` is not supported with negative message expectations" end if block_given? raise ArgumentError, "Implementation blocks aren't supported with `and_return`" end values.unshift(first_value) @expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least) self.terminal_implementation_action = AndReturnImplementation.new(values) nil end # Tells the object to invoke a Proc when it receives the message. Given # more than one value, the result of the first Proc is returned the first # time the message is received, the result of the second Proc is returned # the next time, etc, etc. # # If the message is received more times than there are Procs, the result of # the last Proc is returned for every subsequent call. # # @return [nil] No further chaining is supported after this. # @example # allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }) # api.get_foo # => raises ApiTimeout # api.get_foo # => raises ApiTimeout # # allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }, -> { raise ApiTimeout }, -> { :a_foo }) # api.get_foo # => raises ApiTimeout # api.get_foo # => rasies ApiTimeout # api.get_foo # => :a_foo # api.get_foo # => :a_foo # api.get_foo # => :a_foo # # etc def and_invoke(first_proc, *procs) raise_already_invoked_error_if_necessary(__method__) if negative? raise "`and_invoke` is not supported with negative message expectations" end if block_given? raise ArgumentError, "Implementation blocks aren't supported with `and_invoke`" end procs.unshift(first_proc) if procs.any? { |p| !p.respond_to?(:call) } raise ArgumentError, "Arguments to `and_invoke` must be callable." end @expected_received_count = [@expected_received_count, procs.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least) self.terminal_implementation_action = AndInvokeImplementation.new(procs) nil end # Tells the object to delegate to the original unmodified method # when it receives the message. # # @note This is only available on partial doubles. # # @return [nil] No further chaining is supported after this. # @example # expect(counter).to receive(:increment).and_call_original # original_count = counter.count # counter.increment # expect(counter.count).to eq(original_count + 1) def and_call_original block = lambda do |original, *args, &b| original.call(*args, &b) end block = block.ruby2_keywords if block.respond_to?(:ruby2_keywords) wrap_original(__method__, &block) end # Decorates the stubbed method with the supplied block. The original # unmodified method is passed to the block along with any method call # arguments so you can delegate to it, whilst still being able to # change what args are passed to it and/or change the return value. # # @note This is only available on partial doubles. # # @return [nil] No further chaining is supported after this. # @example # expect(api).to receive(:large_list).and_wrap_original do |original_method, *args, &block| # original_method.call(*args, &block).first(10) # end def and_wrap_original(&block) wrap_original(__method__, &block) end # @overload and_raise # @overload and_raise(ExceptionClass) # @overload and_raise(ExceptionClass, message) # @overload and_raise(exception_instance) # # Tells the object to raise an exception when the message is received. # # @return [nil] No further chaining is supported after this. # @note # When you pass an exception class, the MessageExpectation will raise # an instance of it, creating it with `exception` and passing `message` # if specified. If the exception class initializer requires more than # one parameters, you must pass in an instance and not the class, # otherwise this method will raise an ArgumentError exception. # # @example # allow(car).to receive(:go).and_raise # allow(car).to receive(:go).and_raise(OutOfGas) # allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive") # allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz)) def and_raise(*args) raise_already_invoked_error_if_necessary(__method__) self.terminal_implementation_action = Proc.new { raise(*args) } nil end # @overload and_throw(symbol) # @overload and_throw(symbol, object) # # Tells the object to throw a symbol (with the object if that form is # used) when the message is received. # # @return [nil] No further chaining is supported after this. # @example # allow(car).to receive(:go).and_throw(:out_of_gas) # allow(car).to receive(:go).and_throw(:out_of_gas, :level => 0.1) def and_throw(*args) raise_already_invoked_error_if_necessary(__method__) self.terminal_implementation_action = Proc.new { throw(*args) } nil end # Tells the object to yield one or more args to a block when the message # is received. # # @return [MessageExpectation] self, to support further chaining. # @example # stream.stub(:open).and_yield(StringIO.new) def and_yield(*args, &block) raise_already_invoked_error_if_necessary(__method__) yield @eval_context = Object.new if block # Initialize args to yield now that it's being used, see also: comment # in constructor. @args_to_yield ||= [] @args_to_yield << args self.initial_implementation_action = AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator) self end # @!endgroup # @!group Constraining Receive Counts # Constrain a message expectation to be received a specific number of # times. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(dealer).to receive(:deal_card).exactly(10).times def exactly(n, &block) raise_already_invoked_error_if_necessary(__method__) self.inner_implementation_action = block set_expected_received_count :exactly, n self end # Constrain a message expectation to be received at least a specific # number of times. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(dealer).to receive(:deal_card).at_least(9).times def at_least(n, &block) raise_already_invoked_error_if_necessary(__method__) set_expected_received_count :at_least, n if n == 0 raise "at_least(0) has been removed, use allow(...).to receive(:message) instead" end self.inner_implementation_action = block self end # Constrain a message expectation to be received at most a specific # number of times. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(dealer).to receive(:deal_card).at_most(10).times def at_most(n, &block) raise_already_invoked_error_if_necessary(__method__) self.inner_implementation_action = block set_expected_received_count :at_most, n self end # Syntactic sugar for `exactly`, `at_least` and `at_most` # # @return [MessageExpectation] self, to support further chaining. # @example # expect(dealer).to receive(:deal_card).exactly(10).times # expect(dealer).to receive(:deal_card).at_least(10).times # expect(dealer).to receive(:deal_card).at_most(10).times def times(&block) self.inner_implementation_action = block self end alias time times # Expect a message not to be received at all. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(car).to receive(:stop).never def never error_generator.raise_double_negation_error("expect(obj)") if negative? @expected_received_count = 0 self end # Expect a message to be received exactly one time. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(car).to receive(:go).once def once(&block) self.inner_implementation_action = block set_expected_received_count :exactly, 1 self end # Expect a message to be received exactly two times. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(car).to receive(:go).twice def twice(&block) self.inner_implementation_action = block set_expected_received_count :exactly, 2 self end # Expect a message to be received exactly three times. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(car).to receive(:go).thrice def thrice(&block) self.inner_implementation_action = block set_expected_received_count :exactly, 3 self end # @!endgroup # @!group Other Constraints # Constrains a stub or message expectation to invocations with specific # arguments. # # With a stub, if the message might be received with other args as well, # you should stub a default value first, and then stub or mock the same # message using `with` to constrain to specific arguments. # # A message expectation will fail if the message is received with different # arguments. # # @return [MessageExpectation] self, to support further chaining. # @example # allow(cart).to receive(:add) { :failure } # allow(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success } # cart.add(Book.new(:isbn => 1234567890)) # # => :failure # cart.add(Book.new(:isbn => 1934356379)) # # => :success # # expect(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success } # cart.add(Book.new(:isbn => 1234567890)) # # => failed expectation # cart.add(Book.new(:isbn => 1934356379)) # # => passes def with(*args, &block) raise_already_invoked_error_if_necessary(__method__) if args.empty? raise ArgumentError, "`with` must have at least one argument. Use `no_args` matcher to set the expectation of receiving no arguments." end self.inner_implementation_action = block @argument_list_matcher = ArgumentListMatcher.new(*args) self end ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true) # Expect messages to be received in a specific order. # # @return [MessageExpectation] self, to support further chaining. # @example # expect(api).to receive(:prepare).ordered # expect(api).to receive(:run).ordered # expect(api).to receive(:finish).ordered def ordered(&block) if type == :stub RSpec.warning( "`allow(...).to receive(..).ordered` is not supported and will " \ "have no effect, use `and_return(*ordered_values)` instead." ) end self.inner_implementation_action = block additional_expected_calls.times do @order_group.register(self) end @ordered = true self end # @return [String] a nice representation of the message expectation def to_s args_description = error_generator.method_call_args_description(@argument_list_matcher.expected_args, "", "") { true } args_description = "(#{args_description})" unless args_description.start_with?("(") "#<#{self.class} #{error_generator.intro}.#{message}#{args_description}>" end alias inspect to_s # @private # Contains the parts of `MessageExpectation` that aren't part of # rspec-mocks' public API. The class is very big and could really use # some collaborators it delegates to for this stuff but for now this was # the simplest way to split the public from private stuff to make it # easier to publish the docs for the APIs we want published. module ImplementationDetails attr_accessor :error_generator, :implementation attr_reader :message attr_reader :orig_object attr_writer :expected_received_count, :expected_from, :argument_list_matcher protected :expected_received_count=, :expected_from=, :error_generator=, :implementation= # @private attr_reader :type # rubocop:disable Metrics/ParameterLists def initialize(error_generator, expectation_ordering, expected_from, method_double, type=:expectation, opts={}, &implementation_block) @type = type @error_generator = error_generator @error_generator.opts = error_generator.opts.merge(opts) @expected_from = expected_from @method_double = method_double @orig_object = @method_double.object @message = @method_double.method_name @actual_received_count = 0 @actual_received_count_write_mutex = Support::Mutex.new @expected_received_count = type == :expectation ? 1 : :any @argument_list_matcher = ArgumentListMatcher::MATCH_ALL @order_group = expectation_ordering @order_group.register(self) unless type == :stub @expectation_type = type @ordered = false @at_least = @at_most = @exactly = nil # Initialized to nil so that we don't allocate an array for every # mock or stub. See also comment in `and_yield`. @args_to_yield = nil @eval_context = nil @yield_receiver_to_implementation_block = false @implementation = Implementation.new self.inner_implementation_action = implementation_block end # rubocop:enable Metrics/ParameterLists def expected_args @argument_list_matcher.expected_args end def and_yield_receiver_to_implementation @yield_receiver_to_implementation_block = true self end def yield_receiver_to_implementation_block? @yield_receiver_to_implementation_block end def matches?(message, *args) @message == message && @argument_list_matcher.args_match?(*args) end ruby2_keywords :matches? if respond_to?(:ruby2_keywords, true) def safe_invoke(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block) end ruby2_keywords :safe_invoke if respond_to?(:ruby2_keywords, true) def invoke(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block) end ruby2_keywords :invoke if respond_to?(:ruby2_keywords, true) def invoke_without_incrementing_received_count(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block) end ruby2_keywords :invoke_without_incrementing_received_count if respond_to?(:ruby2_keywords, true) def negative? @expected_received_count == 0 && !@at_least end def called_max_times? @expected_received_count != :any && !@at_least && @expected_received_count > 0 && @actual_received_count >= @expected_received_count end def matches_name_but_not_args(message, *args) @message == message && !@argument_list_matcher.args_match?(*args) end def verify_messages_received return if expected_messages_received? generate_error end def expected_messages_received? ignoring_args? || matches_exact_count? || matches_at_least_count? || matches_at_most_count? end def ensure_expected_ordering_received! @order_group.verify_invocation_order(self) if @ordered true end def ignoring_args? @expected_received_count == :any end def matches_at_least_count? @at_least && @actual_received_count >= @expected_received_count end def matches_at_most_count? @at_most && @actual_received_count <= @expected_received_count end def matches_exact_count? @expected_received_count == @actual_received_count end def similar_messages @similar_messages ||= [] end def advise(*args) similar_messages << args end def unadvise(args) similar_messages.delete_if { |message| args.include?(message) } end def generate_error if similar_messages.empty? @error_generator.raise_expectation_error( @message, @expected_received_count, @argument_list_matcher, @actual_received_count, expectation_count_type, expected_args, @expected_from, exception_source_id ) else @error_generator.raise_similar_message_args_error( self, @similar_messages, @expected_from ) end end def raise_unexpected_message_args_error(args_for_multiple_calls) @error_generator.raise_unexpected_message_args_error(self, args_for_multiple_calls, exception_source_id) end def expectation_count_type return :at_least if @at_least return :at_most if @at_most nil end def description_for(verb) @error_generator.describe_expectation( verb, @message, @expected_received_count, @actual_received_count, expected_args ) end def raise_out_of_order_error @error_generator.raise_out_of_order_error @message end def additional_expected_calls return 0 if @expectation_type == :stub || !@exactly @expected_received_count - 1 end def ordered? @ordered end def negative_expectation_for?(message) @message == message && negative? end def actual_received_count_matters? @at_least || @at_most || @exactly end def increase_actual_received_count! @actual_received_count_write_mutex.synchronize do @actual_received_count += 1 end end private def exception_source_id @exception_source_id ||= "#{self.class.name} #{__id__}" end def invoke_incrementing_actual_calls_by(increment, allowed_to_fail, parent_stub, *args, &block) args.unshift(orig_object) if yield_receiver_to_implementation_block? if negative? || (allowed_to_fail && (@exactly || @at_most) && (@actual_received_count == @expected_received_count)) # args are the args we actually received, @argument_list_matcher is the # list of args we were expecting @error_generator.raise_expectation_error( @message, @expected_received_count, @argument_list_matcher, @actual_received_count + increment, expectation_count_type, args, nil, exception_source_id ) end @order_group.handle_order_constraint self if implementation.present? implementation.call(*args, &block) elsif parent_stub parent_stub.invoke(nil, *args, &block) end ensure @actual_received_count_write_mutex.synchronize do @actual_received_count += increment end end ruby2_keywords :invoke_incrementing_actual_calls_by if respond_to?(:ruby2_keywords, true) def has_been_invoked? @actual_received_count > 0 end def raise_already_invoked_error_if_necessary(calling_customization) return unless has_been_invoked? error_generator.raise_already_invoked_error(message, calling_customization) end def set_expected_received_count(relativity, n) raise "`count` is not supported with negative message expectations" if negative? @at_least = (relativity == :at_least) @at_most = (relativity == :at_most) @exactly = (relativity == :exactly) @expected_received_count = case n when Numeric then n when :once then 1 when :twice then 2 when :thrice then 3 end end def initial_implementation_action=(action) implementation.initial_action = action end def inner_implementation_action=(action) return unless action warn_about_stub_override if implementation.inner_action implementation.inner_action = action end def terminal_implementation_action=(action) implementation.terminal_action = action end def warn_about_stub_override RSpec.warning( "You're overriding a previous stub implementation of `#{@message}`. " \ "Called from #{CallerFilter.first_non_rspec_line}." ) end def wrap_original(method_name, &block) if RSpec::Mocks::TestDouble === @method_double.object @error_generator.raise_only_valid_on_a_partial_double(method_name) else warn_about_stub_override if implementation.inner_action @implementation = AndWrapOriginalImplementation.new(@method_double.original_implementation_callable, block) @yield_receiver_to_implementation_block = false end nil end end include ImplementationDetails end # Handles the implementation of an `and_yield` declaration. # @private class AndYieldImplementation def initialize(args_to_yield, eval_context, error_generator) @args_to_yield = args_to_yield @eval_context = eval_context @error_generator = error_generator end def call(*_args_to_ignore, &block) return if @args_to_yield.empty? && @eval_context.nil? @error_generator.raise_missing_block_error @args_to_yield unless block value = nil block_signature = Support::BlockSignature.new(block) @args_to_yield.each do |args| unless Support::StrictSignatureVerifier.new(block_signature, args).valid? @error_generator.raise_wrong_arity_error(args, block_signature) end value = @eval_context ? @eval_context.instance_exec(*args, &block) : yield(*args) end value end end # Handles the implementation of an `and_return` implementation. # @private class AndReturnImplementation def initialize(values_to_return) @values_to_return = values_to_return end def call(*_args_to_ignore, &_block) if @values_to_return.size > 1 @values_to_return.shift else @values_to_return.first end end end # Handles the implementation of an `and_invoke` implementation. # @private class AndInvokeImplementation def initialize(procs_to_invoke) @procs_to_invoke = procs_to_invoke end def call(*args, &block) proc = if @procs_to_invoke.size > 1 @procs_to_invoke.shift else @procs_to_invoke.first end proc.call(*args, &block) end end # Represents a configured implementation. Takes into account # any number of sub-implementations. # @private class Implementation attr_accessor :initial_action, :inner_action, :terminal_action def call(*args, &block) actions.map do |action| action.call(*args, &block) end.last end ruby2_keywords :call if respond_to?(:ruby2_keywords, true) def present? actions.any? end private def actions [initial_action, inner_action, terminal_action].compact end end # Represents an `and_call_original` implementation. # @private class AndWrapOriginalImplementation def initialize(method, block) @method = method @block = block end CannotModifyFurtherError = Class.new(StandardError) def initial_action=(_value) raise cannot_modify_further_error end def inner_action=(_value) raise cannot_modify_further_error end def terminal_action=(_value) raise cannot_modify_further_error end def present? true end def inner_action true end def call(*args, &block) @block.call(@method, *args, &block) end ruby2_keywords :call if respond_to?(:ruby2_keywords, true) private def cannot_modify_further_error CannotModifyFurtherError.new "This method has already been configured " \ "to call the original implementation, and cannot be modified further." end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/method_double.rb0000664000000000000000000002574314557670305025175 0ustar rootrootmodule RSpec module Mocks # @private class MethodDouble # @private TODO: drop in favor of FrozenError in ruby 2.5+ FROZEN_ERROR_MSG = /can't modify frozen/ # @private attr_reader :method_name, :object, :expectations, :stubs, :method_stasher # @private def initialize(object, method_name, proxy) @method_name = method_name @object = object @proxy = proxy @original_visibility = nil @method_stasher = InstanceMethodStasher.new(object, method_name) @method_is_proxied = false @expectations = [] @stubs = [] end def original_implementation_callable # If original method is not present, uses the `method_missing` # handler of the object. This accounts for cases where the user has not # correctly defined `respond_to?`, and also 1.8 which does not provide # method handles for missing methods even if `respond_to?` is correct. @original_implementation_callable ||= original_method || method_missing_block end alias_method :save_original_implementation_callable!, :original_implementation_callable def original_method @original_method ||= @method_stasher.original_method || @proxy.original_method_handle_for(method_name) end # @private def method_missing_block block = Proc.new do |*args, &b| @object.__send__(:method_missing, @method_name, *args, &b) end block.ruby2_keywords if block.respond_to?(:ruby2_keywords) block end # @private def visibility @proxy.visibility_for(@method_name) end # @private def object_singleton_class class << @object; self; end end # @private def configure_method @original_visibility = visibility @method_stasher.stash unless @method_is_proxied define_proxy_method end # @private def define_proxy_method return if @method_is_proxied save_original_implementation_callable! definition_target.class_exec(self, method_name, @original_visibility || visibility) do |method_double, method_name, visibility| define_method(method_name) do |*args, &block| method_double.proxy_method_invoked(self, *args, &block) end # This can't be `if respond_to?(:ruby2_keywords, true)`, # see https://github.com/rspec/rspec-mocks/pull/1385#issuecomment-755340298 ruby2_keywords(method_name) if Module.private_method_defined?(:ruby2_keywords) __send__(visibility, method_name) end @method_is_proxied = true rescue RuntimeError, TypeError => e # TODO: drop in favor of FrozenError in ruby 2.5+ # RuntimeError (and FrozenError) for ruby 2.x # TypeError for ruby 1.x if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message raise ArgumentError, "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations." end raise end # The implementation of the proxied method. Subclasses may override this # method to perform additional operations. # # @private def proxy_method_invoked(_obj, *args, &block) @proxy.message_received method_name, *args, &block end ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true) # @private def restore_original_method return unless @method_is_proxied remove_method_from_definition_target @method_stasher.restore if @method_stasher.method_is_stashed? restore_original_visibility @method_is_proxied = false rescue RuntimeError, TypeError => e # TODO: drop in favor of FrozenError in ruby 2.5+ # RuntimeError (and FrozenError) for ruby 2.x # TypeError for ruby 1.x if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message return show_frozen_warning end raise end # @private def show_frozen_warning RSpec.warn_with( "WARNING: rspec-mocks was unable to restore the original `#{@method_name}` " \ "method on #{@object.inspect} because it has been frozen. If you reuse this " \ "object, `#{@method_name}` will continue to respond with its stub implementation.", :call_site => nil, :use_spec_location_as_call_site => true ) end # @private def restore_original_visibility return unless @original_visibility && MethodReference.method_defined_at_any_visibility?(object_singleton_class, @method_name) object_singleton_class.__send__(@original_visibility, method_name) end # @private def verify expectations.each { |e| e.verify_messages_received } end # @private def reset restore_original_method clear end # @private def clear expectations.clear stubs.clear end # The type of message expectation to create has been extracted to its own # method so that subclasses can override it. # # @private def message_expectation_class MessageExpectation end # @private def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation) configure_method expectation = message_expectation_class.new(error_generator, expectation_ordering, expected_from, self, :expectation, opts, &implementation) expectations << expectation expectation end # @private def build_expectation(error_generator, expectation_ordering) expected_from = IGNORED_BACKTRACE_LINE message_expectation_class.new(error_generator, expectation_ordering, expected_from, self) end # @private def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation) configure_method stub = message_expectation_class.new(error_generator, expectation_ordering, expected_from, self, :stub, opts, &implementation) stubs.unshift stub stub end # A simple stub can only return a concrete value for a message, and # cannot match on arguments. It is used as an optimization over # `add_stub` / `add_expectation` where it is known in advance that this # is all that will be required of a stub, such as when passing attributes # to the `double` example method. They do not stash or restore existing method # definitions. # # @private def add_simple_stub(method_name, response) setup_simple_method_double method_name, response, stubs end # @private def add_simple_expectation(method_name, response, error_generator, backtrace_line) setup_simple_method_double method_name, response, expectations, error_generator, backtrace_line end # @private def setup_simple_method_double(method_name, response, collection, error_generator=nil, backtrace_line=nil) define_proxy_method me = SimpleMessageExpectation.new(method_name, response, error_generator, backtrace_line) collection.unshift me me end # @private def add_default_stub(*args, &implementation) return if stubs.any? add_stub(*args, &implementation) end # @private def remove_stub raise_method_not_stubbed_error if stubs.empty? remove_stub_if_present end # @private def remove_stub_if_present expectations.empty? ? reset : stubs.clear end # @private def raise_method_not_stubbed_error RSpec::Mocks.error_generator.raise_method_not_stubbed_error(method_name) end # In Ruby 2.0.0 and above prepend will alter the method lookup chain. # We use an object's singleton class to define method doubles upon, # however if the object has had its singleton class (as opposed to # its actual class) prepended too then the the method lookup chain # will look in the prepended module first, **before** the singleton # class. # # This code works around that by providing a mock definition target # that is either the singleton class, or if necessary, a prepended module # of our own. # if Support::RubyFeatures.module_prepends_supported? private # We subclass `Module` in order to be able to easily detect our prepended module. RSpecPrependedModule = Class.new(Module) def definition_target @definition_target ||= usable_rspec_prepended_module || object_singleton_class end def usable_rspec_prepended_module @proxy.prepended_modules_of_singleton_class.each do |mod| # If we have one of our modules prepended before one of the user's # modules that defines the method, use that, since our module's # definition will take precedence. return mod if RSpecPrependedModule === mod # If we hit a user module with the method defined first, # we must create a new prepend module, even if one exists later, # because ours will only take precedence if it comes first. return new_rspec_prepended_module if mod.method_defined?(method_name) end nil end def new_rspec_prepended_module RSpecPrependedModule.new.tap do |mod| object_singleton_class.__send__ :prepend, mod end end else private def definition_target object_singleton_class end end private def remove_method_from_definition_target definition_target.__send__(:remove_method, @method_name) rescue NameError # This can happen when the method has been monkeyed with by # something outside RSpec. This happens, for example, when # `file.write` has been stubbed, and then `file.reopen(other_io)` # is later called, as `File#reopen` appears to redefine `write`. # # Note: we could avoid rescuing this by checking # `definition_target.instance_method(@method_name).owner == definition_target`, # saving us from the cost of the expensive exception, but this error is # extremely rare (it was discovered on 2014-12-30, only happens on # RUBY_VERSION < 2.0 and our spec suite only hits this condition once), # so we'd rather avoid the cost of that check for every method double, # and risk the rare situation where this exception will get raised. RSpec.warn_with( "WARNING: RSpec could not fully restore #{@object.inspect}." \ "#{@method_name}, possibly because the method has been redefined " \ "by something outside of RSpec." ) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/message_chain.rb0000664000000000000000000000440614557670305025142 0ustar rootrootmodule RSpec module Mocks # @private class MessageChain attr_reader :object, :chain, :block def initialize(object, *chain, &blk) @object = object @chain, @block = format_chain(*chain, &blk) end # @api private def setup_chain if chain.length > 1 if (matching_stub = find_matching_stub) chain.shift chain_on(matching_stub.invoke(nil), *chain, &@block) elsif (matching_expectation = find_matching_expectation) chain.shift chain_on(matching_expectation.invoke_without_incrementing_received_count(nil), *chain, &@block) else next_in_chain = Double.new expectation(object, chain.shift) { next_in_chain } chain_on(next_in_chain, *chain, &@block) end else expectation(object, chain.shift, &@block) end end private def chain_on(object, *chain, &block) initialize(object, *chain, &block) setup_chain end def format_chain(*chain, &blk) if Hash === chain.last hash = chain.pop hash.each do |k, v| chain << k blk = Proc.new { v } end end return chain.join('.').split('.'), blk end def find_matching_stub ::RSpec::Mocks.space.proxy_for(object). __send__(:find_matching_method_stub, chain.first.to_sym) end def find_matching_expectation ::RSpec::Mocks.space.proxy_for(object). __send__(:find_matching_expectation, chain.first.to_sym) end end # @private class ExpectChain < MessageChain # @api private def self.expect_chain_on(object, *chain, &blk) new(object, *chain, &blk).setup_chain end private def expectation(object, message, &return_block) ::RSpec::Mocks.expect_message(object, message, {}, &return_block) end end # @private class StubChain < MessageChain def self.stub_chain_on(object, *chain, &blk) new(object, *chain, &blk).setup_chain end private def expectation(object, message, &return_block) ::RSpec::Mocks.allow_message(object, message, {}, &return_block) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/verifying_proxy.rb0000664000000000000000000001620414557670305025616 0ustar rootrootRSpec::Support.require_rspec_mocks 'verifying_message_expectation' RSpec::Support.require_rspec_mocks 'method_reference' module RSpec module Mocks # @private class CallbackInvocationStrategy def call(doubled_module) RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| block.call doubled_module end end end # @private class NoCallbackInvocationStrategy def call(_doubled_module) end end # @private module VerifyingProxyMethods def add_stub(method_name, opts={}, &implementation) ensure_implemented(method_name) super end def add_simple_stub(method_name, *args) ensure_implemented(method_name) super end def add_message_expectation(method_name, opts={}, &block) ensure_implemented(method_name) super end def ensure_implemented(method_name) return unless method_reference[method_name].unimplemented? @error_generator.raise_unimplemented_error( @doubled_module, method_name, @object ) end def ensure_publicly_implemented(method_name, _object) ensure_implemented(method_name) visibility = method_reference[method_name].visibility return if visibility == :public @error_generator.raise_non_public_error(method_name, visibility) end end # A verifying proxy mostly acts like a normal proxy, except that it # contains extra logic to try and determine the validity of any expectation # set on it. This includes whether or not methods have been defined and the # validity of arguments on method calls. # # In all other ways this behaves like a normal proxy. It only adds the # verification behaviour to specific methods then delegates to the parent # implementation. # # These checks are only activated if the doubled class has already been # loaded, otherwise they are disabled. This allows for testing in # isolation. # # @private class VerifyingProxy < TestDoubleProxy include VerifyingProxyMethods def initialize(object, order_group, doubled_module, method_reference_class) super(object, order_group) @object = object @doubled_module = doubled_module @method_reference_class = method_reference_class # A custom method double is required to pass through a way to lookup # methods to determine their parameters. This is only relevant if the doubled # class is loaded. @method_doubles = Hash.new do |h, k| h[k] = VerifyingMethodDouble.new(@object, k, self, method_reference[k]) end end def method_reference @method_reference ||= Hash.new do |h, k| h[k] = @method_reference_class.for(@doubled_module, k) end end def visibility_for(method_name) method_reference[method_name].visibility end def validate_arguments!(method_name, args) @method_doubles[method_name].validate_arguments!(args) end end # @private DEFAULT_CALLBACK_INVOCATION_STRATEGY = CallbackInvocationStrategy.new # @private class VerifyingPartialDoubleProxy < PartialDoubleProxy include VerifyingProxyMethods def initialize(object, expectation_ordering, optional_callback_invocation_strategy=DEFAULT_CALLBACK_INVOCATION_STRATEGY) super(object, expectation_ordering) @doubled_module = DirectObjectReference.new(object) # A custom method double is required to pass through a way to lookup # methods to determine their parameters. @method_doubles = Hash.new do |h, k| h[k] = VerifyingExistingMethodDouble.for(object, k, self) end optional_callback_invocation_strategy.call(@doubled_module) end def ensure_implemented(_method_name) return if Mocks.configuration.temporarily_suppress_partial_double_verification super end def method_reference @method_doubles end end # @private class VerifyingPartialClassDoubleProxy < VerifyingPartialDoubleProxy include PartialClassDoubleProxyMethods end # @private class VerifyingMethodDouble < MethodDouble def initialize(object, method_name, proxy, method_reference) super(object, method_name, proxy) @method_reference = method_reference end def message_expectation_class VerifyingMessageExpectation end def add_expectation(*args, &block) # explicit params necessary for 1.8.7 see #626 super(*args, &block).tap { |x| x.method_reference = @method_reference } end def add_stub(*args, &block) # explicit params necessary for 1.8.7 see #626 super(*args, &block).tap { |x| x.method_reference = @method_reference } end def proxy_method_invoked(obj, *args, &block) validate_arguments!(args) super end ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true) def validate_arguments!(actual_args) @method_reference.with_signature do |signature| verifier = Support::StrictSignatureVerifier.new(signature, actual_args) raise ArgumentError, verifier.error_message unless verifier.valid? end end end # A VerifyingMethodDouble fetches the method to verify against from the # original object, using a MethodReference. This works for pure doubles, # but when the original object is itself the one being modified we need to # collapse the reference and the method double into a single object so that # we can access the original pristine method definition. # # @private class VerifyingExistingMethodDouble < VerifyingMethodDouble def initialize(object, method_name, proxy) super(object, method_name, proxy, self) @valid_method = object.respond_to?(method_name, true) # Trigger an eager find of the original method since if we find it any # later we end up getting a stubbed method with incorrect arity. save_original_implementation_callable! end def with_signature yield Support::MethodSignature.new(original_implementation_callable) end def unimplemented? !@valid_method end def self.for(object, method_name, proxy) if ClassNewMethodReference.applies_to?(method_name) { object } VerifyingExistingClassNewMethodDouble elsif Mocks.configuration.temporarily_suppress_partial_double_verification MethodDouble else self end.new(object, method_name, proxy) end end # Used in place of a `VerifyingExistingMethodDouble` for the specific case # of mocking or stubbing a `new` method on a class. In this case, we substitute # the method signature from `#initialize` since new's signature is just `*args`. # # @private class VerifyingExistingClassNewMethodDouble < VerifyingExistingMethodDouble def with_signature yield Support::MethodSignature.new(object.instance_method(:initialize)) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/verifying_double.rb0000664000000000000000000000670714557670305025716 0ustar rootrootRSpec::Support.require_rspec_mocks 'verifying_proxy' module RSpec module Mocks # @private module VerifyingDouble def respond_to?(message, include_private=false) return super unless null_object? method_ref = __mock_proxy.method_reference[message] case method_ref.visibility when :public then true when :private then include_private when :protected then include_private || RUBY_VERSION.to_f < 2.0 else !method_ref.unimplemented? end end def method_missing(message, *args, &block) # Null object conditional is an optimization. If not a null object, # validity of method expectations will have been checked at definition # time. if null_object? if @__sending_message == message __mock_proxy.ensure_implemented(message) else __mock_proxy.ensure_publicly_implemented(message, self) end __mock_proxy.validate_arguments!(message, args) end super end # Redefining `__send__` causes ruby to issue a warning. old, $VERBOSE = $VERBOSE, nil def __send__(name, *args, &block) @__sending_message = name super ensure @__sending_message = nil end ruby2_keywords :__send__ if respond_to?(:ruby2_keywords, true) $VERBOSE = old def send(name, *args, &block) __send__(name, *args, &block) end ruby2_keywords :send if respond_to?(:ruby2_keywords, true) def initialize(doubled_module, *args) @doubled_module = doubled_module possible_name = args.first name = if String === possible_name || Symbol === possible_name args.shift end super(name, *args) @__sending_message = nil end end # A mock providing a custom proxy that can verify the validity of any # method stubs or expectations against the public instance methods of the # given class. # # @private class InstanceVerifyingDouble include TestDouble include VerifyingDouble def __build_mock_proxy(order_group) VerifyingProxy.new(self, order_group, @doubled_module, InstanceMethodReference ) end end # An awkward module necessary because we cannot otherwise have # ClassVerifyingDouble inherit from Module and still share these methods. # # @private module ObjectVerifyingDoubleMethods include TestDouble include VerifyingDouble def as_stubbed_const(options={}) ConstantMutator.stub(@doubled_module.const_to_replace, self, options) self end private def __build_mock_proxy(order_group) VerifyingProxy.new(self, order_group, @doubled_module, ObjectMethodReference ) end end # Similar to an InstanceVerifyingDouble, except that it verifies against # public methods of the given object. # # @private class ObjectVerifyingDouble include ObjectVerifyingDoubleMethods end # Effectively the same as an ObjectVerifyingDouble (since a class is a type # of object), except with Module in the inheritance chain so that # transferring nested constants to work. # # @private class ClassVerifyingDouble < Module include ObjectVerifyingDoubleMethods end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/method_reference.rb0000664000000000000000000001611514557670305025652 0ustar rootrootRSpec::Support.require_rspec_support 'comparable_version' module RSpec module Mocks # Represents a method on an object that may or may not be defined. # The method may be an instance method on a module or a method on # any object. # # @private class MethodReference def self.for(object_reference, method_name) new(object_reference, method_name) end def initialize(object_reference, method_name) @object_reference = object_reference @method_name = method_name end # A method is implemented if sending the message does not result in # a `NoMethodError`. It might be dynamically implemented by # `method_missing`. def implemented? @object_reference.when_loaded do |m| method_implemented?(m) end end # Returns true if we definitively know that sending the method # will result in a `NoMethodError`. # # This is not simply the inverse of `implemented?`: there are # cases when we don't know if a method is implemented and # both `implemented?` and `unimplemented?` will return false. def unimplemented? @object_reference.when_loaded do |_m| return !implemented? end # If it's not loaded, then it may be implemented but we can't check. false end # A method is defined if we are able to get a `Method` object for it. # In that case, we can assert against metadata like the arity. def defined? @object_reference.when_loaded do |m| method_defined?(m) end end def with_signature return unless (original = original_method) yield Support::MethodSignature.new(original) end def visibility @object_reference.when_loaded do |m| return visibility_from(m) end # When it's not loaded, assume it's public. We don't want to # wrongly treat the method as private. :public end def self.instance_method_visibility_for(klass, method_name) if klass.public_method_defined?(method_name) :public elsif klass.private_method_defined?(method_name) :private elsif klass.protected_method_defined?(method_name) :protected end end class << self alias method_defined_at_any_visibility? instance_method_visibility_for end def self.method_visibility_for(object, method_name) vis = instance_method_visibility_for(class << object; self; end, method_name) # If the method is not defined on the class, `instance_method_visibility_for` # returns `nil`. However, it may be handled dynamically by `method_missing`, # so here we check `respond_to` (passing false to not check private methods). # # This only considers the public case, but I don't think it's possible to # write `method_missing` in such a way that it handles a dynamic message # with private or protected visibility. Ruby doesn't provide you with # the caller info. return vis unless vis.nil? proxy = RSpec::Mocks.space.proxy_for(object) respond_to = proxy.method_double_if_exists_for_message(:respond_to?) visible = respond_to && respond_to.original_method.call(method_name) || object.respond_to?(method_name) return :public if visible end private def original_method @object_reference.when_loaded do |m| self.defined? && find_method(m) end end end # @private class InstanceMethodReference < MethodReference private def method_implemented?(mod) MethodReference.method_defined_at_any_visibility?(mod, @method_name) end # Ideally, we'd use `respond_to?` for `method_implemented?` but we need a # reference to an instance to do that and we don't have one. Note that # we may get false negatives: if the method is implemented via # `method_missing`, we'll return `false` even though it meets our # definition of "implemented". However, it's the best we can do. alias method_defined? method_implemented? # works around the fact that repeated calls for method parameters will # falsely return empty arrays on JRuby in certain circumstances, this # is necessary here because we can't dup/clone UnboundMethods. # # This is necessary due to a bug in JRuby prior to 1.7.5 fixed in: # https://github.com/jruby/jruby/commit/99a0613fe29935150d76a9a1ee4cf2b4f63f4a27 if RUBY_PLATFORM == 'java' && RSpec::Support::ComparableVersion.new(JRUBY_VERSION) < '1.7.5' def find_method(mod) mod.dup.instance_method(@method_name) end else def find_method(mod) mod.instance_method(@method_name) end end def visibility_from(mod) MethodReference.instance_method_visibility_for(mod, @method_name) end end # @private class ObjectMethodReference < MethodReference def self.for(object_reference, method_name) if ClassNewMethodReference.applies_to?(method_name) { object_reference.when_loaded { |o| o } } ClassNewMethodReference.new(object_reference, method_name) else super end end private def method_implemented?(object) object.respond_to?(@method_name, true) end def method_defined?(object) (class << object; self; end).method_defined?(@method_name) end def find_method(object) object.method(@method_name) end def visibility_from(object) MethodReference.method_visibility_for(object, @method_name) end end # When a class's `.new` method is stubbed, we want to use the method # signature from `#initialize` because `.new`'s signature is a generic # `def new(*args)` and it simply delegates to `#initialize` and forwards # all args...so the method with the actually used signature is `#initialize`. # # This method reference implementation handles that specific case. # @private class ClassNewMethodReference < ObjectMethodReference def self.applies_to?(method_name) return false unless method_name == :new klass = yield return false unless ::Class === klass && klass.respond_to?(:new, true) # We only want to apply our special logic to normal `new` methods. # Methods that the user has monkeyed with should be left as-is. uses_class_new?(klass) end if RUBY_VERSION.to_i >= 3 CLASS_NEW = ::Class.instance_method(:new) def self.uses_class_new?(klass) ::RSpec::Support.method_handle_for(klass, :new) == CLASS_NEW.bind(klass) end else # Ruby 2's Method#== is too strict def self.uses_class_new?(klass) ::RSpec::Support.method_handle_for(klass, :new).owner == ::Class end end def with_signature @object_reference.when_loaded do |klass| yield Support::MethodSignature.new(klass.instance_method(:initialize)) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/any_instance.rb0000664000000000000000000000046514557670305025030 0ustar rootroot%w[ any_instance/chain any_instance/error_generator any_instance/stub_chain any_instance/stub_chain_chain any_instance/expect_chain_chain any_instance/expectation_chain any_instance/message_chains any_instance/recorder any_instance/proxy ].each { |f| RSpec::Support.require_rspec_mocks(f) } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/0000775000000000000000000000000014557670305023631 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/have_received.rb0000664000000000000000000000731014557670305026750 0ustar rootrootmodule RSpec module Mocks module Matchers # @private class HaveReceived include Matcher COUNT_CONSTRAINTS = %w[exactly at_least at_most times time once twice thrice] ARGS_CONSTRAINTS = %w[with] CONSTRAINTS = COUNT_CONSTRAINTS + ARGS_CONSTRAINTS + %w[ordered] def initialize(method_name, &block) @method_name = method_name @block = block @constraints = [] @subject = nil end def matcher_name "have_received" end def matches?(subject, &block) @block ||= block @subject = subject @expectation = expect mock_proxy.ensure_implemented(@method_name) expected_messages_received_in_order? end def does_not_match?(subject) @subject = subject ensure_count_unconstrained @expectation = expect.never mock_proxy.ensure_implemented(@method_name) expected_messages_received_in_order? end def failure_message capture_failure_message end def failure_message_when_negated capture_failure_message end def description (@expectation ||= expect).description_for("have received") end CONSTRAINTS.each do |expectation| define_method expectation do |*args| @constraints << [expectation, *args] self end end def setup_expectation(subject, &block) notify_failure_message unless matches?(subject, &block) end def setup_negative_expectation(subject, &block) notify_failure_message unless does_not_match?(subject, &block) end def setup_allowance(_subject, &_block) disallow("allow", " as it would have no effect") end def setup_any_instance_allowance(_subject, &_block) disallow("allow_any_instance_of") end def setup_any_instance_expectation(_subject, &_block) disallow("expect_any_instance_of") end def setup_any_instance_negative_expectation(_subject, &_block) disallow("expect_any_instance_of") end private def disallow(type, reason="") RSpec::Mocks.error_generator.raise_have_received_disallowed(type, reason) end def expect expectation = mock_proxy.build_expectation(@method_name) apply_constraints_to expectation expectation end def apply_constraints_to(expectation) @constraints.each do |constraint| expectation.send(*constraint) end end def ensure_count_unconstrained return unless count_constraint RSpec::Mocks.error_generator.raise_cant_constrain_count_for_negated_have_received_error(count_constraint) end def count_constraint @constraints.map(&:first).find do |constraint| COUNT_CONSTRAINTS.include?(constraint) end end def capture_failure_message RSpec::Support.with_failure_notifier(Proc.new { |err, _opt| return err.message }) do notify_failure_message end end def notify_failure_message mock_proxy.check_for_unexpected_arguments(@expectation) @expectation.generate_error end def expected_messages_received_in_order? mock_proxy.replay_received_message_on @expectation, &@block @expectation.expected_messages_received? && @expectation.ensure_expected_ordering_received! end def mock_proxy RSpec::Mocks.space.proxy_for(@subject) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/receive_messages.rb0000664000000000000000000000442514557670305027474 0ustar rootrootmodule RSpec module Mocks module Matchers # @private class ReceiveMessages include Matcher def initialize(message_return_value_hash) @message_return_value_hash = message_return_value_hash @backtrace_line = CallerFilter.first_non_rspec_line end def matcher_name "receive_messages" end def description "receive messages: #{@message_return_value_hash.inspect}" end def setup_expectation(subject) warn_about_block if block_given? each_message_on(proxy_on(subject)) do |host, message, return_value| host.add_simple_expectation(message, return_value, @backtrace_line) end end alias matches? setup_expectation def setup_negative_expectation(_subject) raise NegationUnsupportedError, "`expect(...).to_not receive_messages` is not supported since it " \ "doesn't really make sense. What would it even mean?" end alias does_not_match? setup_negative_expectation def setup_allowance(subject) warn_about_block if block_given? each_message_on(proxy_on(subject)) do |host, message, return_value| host.add_simple_stub(message, return_value) end end def setup_any_instance_expectation(subject) warn_about_block if block_given? each_message_on(any_instance_of(subject)) do |host, message, return_value| host.should_receive(message).and_return(return_value) end end def setup_any_instance_allowance(subject) warn_about_block if block_given? any_instance_of(subject).stub(@message_return_value_hash) end def warn_about_block raise "Implementation blocks aren't supported with `receive_messages`" end private def proxy_on(subject) ::RSpec::Mocks.space.proxy_for(subject) end def any_instance_of(subject) ::RSpec::Mocks.space.any_instance_proxy_for(subject) end def each_message_on(host) @message_return_value_hash.each do |message, value| yield host, message, value end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/expectation_customization.rb0000664000000000000000000000066114557670305031474 0ustar rootrootmodule RSpec module Mocks module Matchers # @private class ExpectationCustomization attr_accessor :block def initialize(method_name, args, block) @method_name = method_name @args = args @block = block end def playback_onto(expectation) expectation.__send__(@method_name, *@args, &@block) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/receive.rb0000664000000000000000000001060414557670305025601 0ustar rootrootRSpec::Support.require_rspec_mocks 'matchers/expectation_customization' module RSpec module Mocks module Matchers # @private class Receive include Matcher def initialize(message, block) @message = message @block = block @recorded_customizations = [] end def matcher_name "receive" end def description describable.description_for("receive") end def setup_expectation(subject, &block) warn_if_any_instance("expect", subject) @describable = setup_mock_proxy_method_substitute(subject, :add_message_expectation, block) end alias matches? setup_expectation def setup_negative_expectation(subject, &block) # ensure `never` goes first for cases like `never.and_return(5)`, # where `and_return` is meant to raise an error @recorded_customizations.unshift ExpectationCustomization.new(:never, [], nil) warn_if_any_instance("expect", subject) setup_expectation(subject, &block) end alias does_not_match? setup_negative_expectation def setup_allowance(subject, &block) warn_if_any_instance("allow", subject) setup_mock_proxy_method_substitute(subject, :add_stub, block) end def setup_any_instance_expectation(subject, &block) setup_any_instance_method_substitute(subject, :should_receive, block) end def setup_any_instance_negative_expectation(subject, &block) setup_any_instance_method_substitute(subject, :should_not_receive, block) end def setup_any_instance_allowance(subject, &block) setup_any_instance_method_substitute(subject, :stub, block) end own_methods = (instance_methods - superclass.instance_methods) MessageExpectation.public_instance_methods(false).each do |method| next if own_methods.include?(method) define_method(method) do |*args, &block| @recorded_customizations << ExpectationCustomization.new(method, args, block) self end ruby2_keywords(method) if respond_to?(:ruby2_keywords, true) end private def describable @describable ||= DefaultDescribable.new(@message) end def warn_if_any_instance(expression, subject) return unless AnyInstance::Proxy === subject RSpec.warning( "`#{expression}(#{subject.klass}.any_instance).to` " \ "is probably not what you meant, it does not operate on " \ "any instance of `#{subject.klass}`. " \ "Use `#{expression}_any_instance_of(#{subject.klass}).to` instead." ) end def setup_mock_proxy_method_substitute(subject, method, block) proxy = ::RSpec::Mocks.space.proxy_for(subject) setup_method_substitute(proxy, method, block) end def setup_any_instance_method_substitute(subject, method, block) proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) setup_method_substitute(proxy, method, block) end def setup_method_substitute(host, method, block, *args) args << @message.to_sym block = move_block_to_last_customization(block) expectation = host.__send__(method, *args, &(@block || block)) @recorded_customizations.each do |customization| customization.playback_onto(expectation) end expectation end def move_block_to_last_customization(block) last = @recorded_customizations.last return block unless last last.block ||= block nil end # MessageExpectation objects are able to describe themselves in detail. # We use this as a fall back when a MessageExpectation is not available. # @private class DefaultDescribable def initialize(message) @message = message end # This is much simpler for the `any_instance` case than what the # user may want, but I'm not up for putting a bunch of effort # into full descriptions for `any_instance` expectations at this point :(. def description_for(verb) "#{verb} #{@message}" end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/matchers/receive_message_chain.rb0000664000000000000000000000463314557670305030454 0ustar rootrootRSpec::Support.require_rspec_mocks 'matchers/expectation_customization' module RSpec module Mocks module Matchers # @private class ReceiveMessageChain include Matcher def initialize(chain, &block) @chain = chain @block = block @recorded_customizations = [] end [:with, :and_return, :and_invoke, :and_throw, :and_raise, :and_yield, :and_call_original].each do |msg| define_method(msg) do |*args, &block| @recorded_customizations << ExpectationCustomization.new(msg, args, block) self end end def matcher_name "receive_message_chain" end def description "receive message chain #{formatted_chain}" end def setup_allowance(subject, &block) chain = StubChain.stub_chain_on(subject, *@chain, &(@block || block)) replay_customizations(chain) end def setup_any_instance_allowance(subject, &block) proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) chain = proxy.stub_chain(*@chain, &(@block || block)) replay_customizations(chain) end def setup_any_instance_expectation(subject, &block) proxy = ::RSpec::Mocks.space.any_instance_proxy_for(subject) chain = proxy.expect_chain(*@chain, &(@block || block)) replay_customizations(chain) end def setup_expectation(subject, &block) chain = ExpectChain.expect_chain_on(subject, *@chain, &(@block || block)) replay_customizations(chain) end def setup_negative_expectation(*_args) raise NegationUnsupportedError, "`expect(...).not_to receive_message_chain` is not supported " \ "since it doesn't really make sense. What would it even mean?" end alias matches? setup_expectation alias does_not_match? setup_negative_expectation private def replay_customizations(chain) @recorded_customizations.each do |customization| customization.playback_onto(chain) end end def formatted_chain @formatted_chain ||= @chain.map do |part| if Hash === part part.keys.first.to_s else part.to_s end end.join(".") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/verifying_message_expectation.rb0000664000000000000000000000370414557670305030465 0ustar rootrootRSpec::Support.require_rspec_support 'method_signature_verifier' module RSpec module Mocks # A message expectation that knows about the real implementation of the # message being expected, so that it can verify that any expectations # have the valid arguments. # @api private class VerifyingMessageExpectation < MessageExpectation # A level of indirection is used here rather than just passing in the # method itself, since method look up is expensive and we only want to # do it if actually needed. # # Conceptually the method reference makes more sense as a constructor # argument since it should be immutable, but it is significantly more # straight forward to build the object in pieces so for now it stays as # an accessor. attr_accessor :method_reference def initialize(*args) super end # @private def with(*args, &block) super(*args, &block).tap do validate_expected_arguments! do |signature| example_call_site_args = [:an_arg] * signature.min_non_kw_args example_call_site_args << :kw_args_hash if signature.required_kw_args.any? @argument_list_matcher.resolve_expected_args_based_on(example_call_site_args) end end end ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true) private def validate_expected_arguments! return if method_reference.nil? method_reference.with_signature do |signature| args = yield signature verifier = Support::LooseSignatureVerifier.new(signature, args) unless verifier.valid? # Fail fast is required, otherwise the message expectation will fail # as well ("expected method not called") and clobber this one. @failed_fast = true @error_generator.raise_invalid_arguments_error(verifier) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/error_generator.rb0000664000000000000000000003473614557670305025564 0ustar rootrootRSpec::Support.require_rspec_support "object_formatter" module RSpec module Mocks # Raised when a message expectation is not satisfied. MockExpectationError = Class.new(Exception) # Raised when a test double is used after it has been torn # down (typically at the end of an rspec-core example). ExpiredTestDoubleError = Class.new(MockExpectationError) # Raised when doubles or partial doubles are used outside of the per-test lifecycle. OutsideOfExampleError = Class.new(StandardError) # Raised when an expectation customization method (e.g. `with`, # `and_return`) is called on a message expectation which has already been # invoked. MockExpectationAlreadyInvokedError = Class.new(Exception) # Raised for situations that RSpec cannot support due to mutations made # externally on arguments that RSpec is holding onto to use for later # comparisons. # # @deprecated We no longer raise this error but the constant remains until # RSpec 4 for SemVer reasons. CannotSupportArgMutationsError = Class.new(StandardError) # @private UnsupportedMatcherError = Class.new(StandardError) # @private NegationUnsupportedError = Class.new(StandardError) # @private VerifyingDoubleNotDefinedError = Class.new(StandardError) # @private class ErrorGenerator attr_writer :opts def initialize(target=nil) @target = target end # @private def opts @opts ||= {} end # @private def raise_unexpected_message_error(message, args) __raise "#{intro} received unexpected message :#{message} with #{format_args(args)}" end # @private def raise_unexpected_message_args_error(expectation, args_for_multiple_calls, source_id=nil) __raise error_message(expectation, args_for_multiple_calls), nil, source_id end # @private def raise_missing_default_stub_error(expectation, args_for_multiple_calls) __raise( error_message(expectation, args_for_multiple_calls) + "\n Please stub a default value first if message might be received with other args as well. \n" ) end # @private def raise_similar_message_args_error(expectation, args_for_multiple_calls, backtrace_line=nil) __raise error_message(expectation, args_for_multiple_calls), backtrace_line end def default_error_message(expectation, expected_args, actual_args) "#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}".dup end # rubocop:disable Metrics/ParameterLists # @private def raise_expectation_error(message, expected_received_count, argument_list_matcher, actual_received_count, expectation_count_type, args, backtrace_line=nil, source_id=nil) expected_part = expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher) received_part = received_part_of_expectation_error(actual_received_count, args) __raise "(#{intro(:unwrapped)}).#{message}#{format_args(args)}\n #{expected_part}\n #{received_part}", backtrace_line, source_id end # rubocop:enable Metrics/ParameterLists # @private def raise_unimplemented_error(doubled_module, method_name, object) message = case object when InstanceVerifyingDouble "the %s class does not implement the instance method: %s".dup << if ObjectMethodReference.for(doubled_module, method_name).implemented? ". Perhaps you meant to use `class_double` instead?" else "" end when ClassVerifyingDouble "the %s class does not implement the class method: %s".dup << if InstanceMethodReference.for(doubled_module, method_name).implemented? ". Perhaps you meant to use `instance_double` instead?" else "" end else "%s does not implement: %s" end __raise message % [doubled_module.description, method_name] end # @private def raise_non_public_error(method_name, visibility) raise NoMethodError, "%s method `%s' called on %s" % [ visibility, method_name, intro ] end # @private def raise_invalid_arguments_error(verifier) __raise verifier.error_message end # @private def raise_expired_test_double_error raise ExpiredTestDoubleError, "#{intro} was originally created in one example but has leaked into " \ "another example and can no longer be used. rspec-mocks' doubles are " \ "designed to only last for one example, and you need to create a new " \ "one in each example you wish to use it for." end # @private def describe_expectation(verb, message, expected_received_count, _actual_received_count, args) "#{verb} #{message}#{format_args(args)} #{count_message(expected_received_count)}" end # @private def raise_out_of_order_error(message) __raise "#{intro} received :#{message} out of order" end # @private def raise_missing_block_error(args_to_yield) __raise "#{intro} asked to yield |#{arg_list(args_to_yield)}| but no block was passed" end # @private def raise_wrong_arity_error(args_to_yield, signature) __raise "#{intro} yielded |#{arg_list(args_to_yield)}| to block with #{signature.description}" end # @private def raise_only_valid_on_a_partial_double(method) __raise "#{intro} is a pure test double. `#{method}` is only " \ "available on a partial double." end # @private def raise_expectation_on_unstubbed_method(method) __raise "#{intro} expected to have received #{method}, but that " \ "object is not a spy or method has not been stubbed." end # @private def raise_expectation_on_mocked_method(method) __raise "#{intro} expected to have received #{method}, but that " \ "method has been mocked instead of stubbed or spied." end # @private def raise_double_negation_error(wrapped_expression) __raise "Isn't life confusing enough? You've already set a " \ "negative message expectation and now you are trying to " \ "negate it again with `never`. What does an expression like " \ "`#{wrapped_expression}.not_to receive(:msg).never` even mean?" end # @private def raise_verifying_double_not_defined_error(ref) notify(VerifyingDoubleNotDefinedError.new( "#{ref.description.inspect} is not a defined constant. " \ "Perhaps you misspelt it? " \ "Disable check with `verify_doubled_constant_names` configuration option." )) end # @private def raise_have_received_disallowed(type, reason) __raise "Using #{type}(...) with the `have_received` " \ "matcher is not supported#{reason}." end # @private def raise_cant_constrain_count_for_negated_have_received_error(count_constraint) __raise "can't use #{count_constraint} when negative" end # @private def raise_method_not_stubbed_error(method_name) __raise "The method `#{method_name}` was not stubbed or was already unstubbed" end # @private def raise_already_invoked_error(message, calling_customization) error_message = "The message expectation for #{intro}.#{message} has already been invoked " \ "and cannot be modified further (e.g. using `#{calling_customization}`). All message expectation " \ "customizations must be applied before it is used for the first time." notify MockExpectationAlreadyInvokedError.new(error_message) end def raise_expectation_on_nil_error(method_name) __raise expectation_on_nil_message(method_name) end def expectation_on_nil_message(method_name) "An expectation of `:#{method_name}` was set on `nil`. " \ "To allow expectations on `nil` and suppress this message, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `true`. " \ "To disallow expectations on `nil`, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `false`" end # @private def intro(unwrapped=false) case @target when TestDouble then TestDoubleFormatter.format(@target, unwrapped) when Class then formatted = "#{@target.inspect} (class)" return formatted if unwrapped "#<#{formatted}>" when NilClass then "nil" else @target.inspect end end # @private def method_call_args_description(args, generic_prefix=" with arguments: ", matcher_prefix=" with ") case args.first when ArgumentMatchers::AnyArgsMatcher then "#{matcher_prefix}any arguments" when ArgumentMatchers::NoArgsMatcher then "#{matcher_prefix}no arguments" else if yield "#{generic_prefix}#{format_args(args)}" else "" end end end private def received_part_of_expectation_error(actual_received_count, args) "received: #{count_message(actual_received_count)}" + method_call_args_description(args) do actual_received_count > 0 && args.length > 0 end end def expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher) "expected: #{count_message(expected_received_count, expectation_count_type)}" + method_call_args_description(argument_list_matcher.expected_args) do argument_list_matcher.expected_args.length > 0 end end def unexpected_arguments_message(expected_args_string, actual_args_string) "with unexpected arguments\n expected: #{expected_args_string}\n got: #{actual_args_string}" end def error_message(expectation, args_for_multiple_calls) expected_args = format_args(expectation.expected_args) actual_args = format_received_args(args_for_multiple_calls) if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? expected_hash = expectation.expected_args.last actual_hash = args_for_multiple_calls.last.last if Hash === expected_hash && Hash === actual_hash && (Hash.ruby2_keywords_hash?(expected_hash) != Hash.ruby2_keywords_hash?(actual_hash)) actual_description = Hash.ruby2_keywords_hash?(actual_hash) ? " (keyword arguments)" : " (options hash)" expected_description = Hash.ruby2_keywords_hash?(expected_hash) ? " (keyword arguments)" : " (options hash)" if actual_description != expected_description actual_args += actual_description expected_args += expected_description end end end message = default_error_message(expectation, expected_args, actual_args) if args_for_multiple_calls.one? diff = diff_message(expectation.expected_args, args_for_multiple_calls.first) if RSpec::Mocks.configuration.color? message << "\nDiff:#{diff}" unless diff.gsub(/\e\[\d+m/, '').strip.empty? else message << "\nDiff:#{diff}" unless diff.strip.empty? end end message end def diff_message(expected_args, actual_args) formatted_expected_args = expected_args.map do |x| RSpec::Support.rspec_description_for_object(x) end formatted_expected_args, actual_args = unpack_string_args(formatted_expected_args, actual_args) differ.diff(actual_args, formatted_expected_args) end def unpack_string_args(formatted_expected_args, actual_args) if [formatted_expected_args, actual_args].all? { |x| list_of_exactly_one_string?(x) } [formatted_expected_args.first, actual_args.first] else [formatted_expected_args, actual_args] end end def list_of_exactly_one_string?(args) Array === args && args.count == 1 && String === args.first end def differ RSpec::Support::Differ.new(:color => RSpec::Mocks.configuration.color?) end def __raise(message, backtrace_line=nil, source_id=nil) message = opts[:message] unless opts[:message].nil? exception = RSpec::Mocks::MockExpectationError.new(message) prepend_to_backtrace(exception, backtrace_line) if backtrace_line notify exception, :source_id => source_id end if RSpec::Support::Ruby.jruby? def prepend_to_backtrace(exception, line) raise exception rescue RSpec::Mocks::MockExpectationError => with_backtrace with_backtrace.backtrace.unshift(line) end else def prepend_to_backtrace(exception, line) exception.set_backtrace(caller.unshift line) end end def notify(*args) RSpec::Support.notify_failure(*args) end def format_args(args) return "(no args)" if args.empty? "(#{arg_list(args)})" end def arg_list(args) args.map { |arg| RSpec::Support::ObjectFormatter.format(arg) }.join(", ") end def format_received_args(args_for_multiple_calls) grouped_args(args_for_multiple_calls).map do |args_for_one_call, index| "#{format_args(args_for_one_call)}#{group_count(index, args_for_multiple_calls)}" end.join("\n ") end def count_message(count, expectation_count_type=nil) return "at least #{times(count.abs)}" if count < 0 || expectation_count_type == :at_least return "at most #{times(count)}" if expectation_count_type == :at_most times(count) end def times(count) "#{count} time#{count == 1 ? '' : 's'}" end def grouped_args(args) Hash[args.group_by { |x| x }.map { |k, v| [k, v.count] }] end def group_count(index, args) " (#{times(index)})" if args.size > 1 || index > 1 end end # @private def self.error_generator @error_generator ||= ErrorGenerator.new end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/argument_matchers.rb0000664000000000000000000002403114557670305026060 0ustar rootroot# This cannot take advantage of our relative requires, since this file is a # dependency of `rspec/mocks/argument_list_matcher.rb`. See comment there for # details. require 'rspec/support/matcher_definition' module RSpec module Mocks # ArgumentMatchers are placeholders that you can include in message # expectations to match arguments against a broader check than simple # equality. # # With the exception of `any_args` and `no_args`, they all match against # the arg in same position in the argument list. # # @see ArgumentListMatcher module ArgumentMatchers # Acts like an arg splat, matching any number of args at any point in an arg list. # # @example # expect(object).to receive(:message).with(1, 2, any_args) # # # matches any of these: # object.message(1, 2) # object.message(1, 2, 3) # object.message(1, 2, 3, 4) def any_args AnyArgsMatcher::INSTANCE end # Matches any argument at all. # # @example # expect(object).to receive(:message).with(anything) def anything AnyArgMatcher::INSTANCE end # Matches no arguments. # # @example # expect(object).to receive(:message).with(no_args) def no_args NoArgsMatcher::INSTANCE end # Matches if the actual argument responds to the specified messages. # # @example # expect(object).to receive(:message).with(duck_type(:hello)) # expect(object).to receive(:message).with(duck_type(:hello, :goodbye)) def duck_type(*args) DuckTypeMatcher.new(*args) end # Matches a boolean value. # # @example # expect(object).to receive(:message).with(boolean()) def boolean BooleanMatcher::INSTANCE end # Matches a hash that includes the specified key(s) or key/value pairs. # Ignores any additional keys. # # @example # expect(object).to receive(:message).with(hash_including(:key => val)) # expect(object).to receive(:message).with(hash_including(:key)) # expect(object).to receive(:message).with(hash_including(:key, :key2 => val2)) def hash_including(*args) HashIncludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args)) end # Matches a hash that doesn't include the specified key(s) or key/value. # # @example # expect(object).to receive(:message).with(hash_excluding(:key => val)) # expect(object).to receive(:message).with(hash_excluding(:key)) # expect(object).to receive(:message).with(hash_excluding(:key, :key2 => :val2)) def hash_excluding(*args) HashExcludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args)) end # Matches an array that includes the specified items at least once. # Ignores duplicates and additional values # # @example # expect(object).to receive(:message).with(array_including(1,2,3)) # expect(object).to receive(:message).with(array_including([1,2,3])) def array_including(*args) actually_an_array = Array === args.first && args.count == 1 ? args.first : args ArrayIncludingMatcher.new(actually_an_array) end # Matches an array that excludes the specified items. # # @example # expect(object).to receive(:message).with(array_excluding(1,2,3)) # expect(object).to receive(:message).with(array_excluding([1,2,3])) def array_excluding(*args) actually_an_array = Array === args.first && args.count == 1 ? args.first : args ArrayExcludingMatcher.new(actually_an_array) end alias_method :hash_not_including, :hash_excluding # Matches if `arg.instance_of?(klass)` # # @example # expect(object).to receive(:message).with(instance_of(Thing)) def instance_of(klass) InstanceOf.new(klass) end alias_method :an_instance_of, :instance_of # Matches if `arg.kind_of?(klass)` # # @example # expect(object).to receive(:message).with(kind_of(Thing)) def kind_of(klass) KindOf.new(klass) end alias_method :a_kind_of, :kind_of # @private def self.anythingize_lonely_keys(*args) hash = Hash === args.last ? args.delete_at(-1) : {} args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE } hash end # Intended to be subclassed by stateless, immutable argument matchers. # Provides a `::INSTANCE` constant for accessing a global # singleton instance of the matcher. There is no need to construct # multiple instance since there is no state. It also facilities the # special case logic we need for some of these matchers, by making it # easy to do comparisons like: `[klass::INSTANCE] == args` rather than # `args.count == 1 && klass === args.first`. # # @private class SingletonMatcher private_class_method :new def self.inherited(subklass) subklass.const_set(:INSTANCE, subklass.send(:new)) end end # @private class AnyArgsMatcher < SingletonMatcher def description "*(any args)" end end # @private class AnyArgMatcher < SingletonMatcher def ===(_other) true end def description "anything" end end # @private class NoArgsMatcher < SingletonMatcher def description "no args" end end # @private class BooleanMatcher < SingletonMatcher def ===(value) true == value || false == value end def description "boolean" end end # @private class BaseHashMatcher def initialize(expected) @expected = expected end def ===(predicate, actual) @expected.__send__(predicate) do |k, v| actual.key?(k) && Support::FuzzyMatcher.values_match?(v, actual[k]) end rescue NoMethodError false end def description(name) "#{name}(#{formatted_expected_hash.inspect.sub(/^\{/, "").sub(/\}$/, "")})" end private def formatted_expected_hash Hash[ @expected.map do |k, v| k = RSpec::Support.rspec_description_for_object(k) v = RSpec::Support.rspec_description_for_object(v) [k, v] end ] end end # @private class HashIncludingMatcher < BaseHashMatcher def ===(actual) super(:all?, actual) end def description super("hash_including") end end # @private class HashExcludingMatcher < BaseHashMatcher def ===(actual) super(:none?, actual) end def description super("hash_not_including") end end # @private class ArrayIncludingMatcher def initialize(expected) @expected = expected end def ===(actual) actual = actual.uniq return true if (actual & @expected).count >= @expected.count @expected.uniq.all? do |expected_element| actual.any? do |actual_element| RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element) end end rescue NoMethodError false end def description "array_including(#{formatted_expected_values})" end private def formatted_expected_values @expected.map do |x| RSpec::Support.rspec_description_for_object(x) end.join(", ") end end # @private class ArrayExcludingMatcher def initialize(unexpected) @unexpected = unexpected.uniq end def ===(actual) actual = actual.uniq return false unless (actual & @unexpected).empty? actual.none? do |actual_element| @unexpected.any? do |unexpected_element| RSpec::Support::FuzzyMatcher.values_match?(unexpected_element, actual_element) end end rescue NoMethodError false end def description "array_excluding(#{formatted_unexpected_values})" end private def formatted_unexpected_values @unexpected.map do |x| RSpec::Support.rspec_description_for_object(x) end.join(", ") end end # @private class DuckTypeMatcher def initialize(*methods_to_respond_to) @methods_to_respond_to = methods_to_respond_to end def ===(value) @methods_to_respond_to.all? { |message| value.respond_to?(message) } end def description "duck_type(#{@methods_to_respond_to.map(&:inspect).join(', ')})" end end # @private class InstanceOf def initialize(klass) @klass = klass end def ===(actual) actual.instance_of?(@klass) end def description "an_instance_of(#{@klass.name})" end end # @private class KindOf def initialize(klass) @klass = klass end def ===(actual) actual.kind_of?(@klass) end def description "kind of #{@klass.name}" end end matcher_namespace = name + '::' ::RSpec::Support.register_matcher_definition do |object| # This is the best we have for now. We should tag all of our matchers # with a module or something so we can test for it directly. # # (Note Module#parent in ActiveSupport is defined in a similar way.) begin object.class.name.include?(matcher_namespace) rescue NoMethodError # Some objects, like BasicObject, don't implement standard # reflection methods. false end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/space.rb0000664000000000000000000001531314557670305023446 0ustar rootrootRSpec::Support.require_rspec_support 'reentrant_mutex' module RSpec module Mocks # @private # Provides a default space implementation for outside # the scope of an example. Called "root" because it serves # as the root of the space stack. class RootSpace def proxy_for(*_args) raise_lifecycle_message end def any_instance_recorder_for(*_args) raise_lifecycle_message end def any_instance_proxy_for(*_args) raise_lifecycle_message end def register_constant_mutator(_mutator) raise_lifecycle_message end def any_instance_recorders_from_ancestry_of(_object) raise_lifecycle_message end def reset_all end def verify_all end def registered?(_object) false end def superclass_proxy_for(*_args) raise_lifecycle_message end def new_scope Space.new end private def raise_lifecycle_message raise OutsideOfExampleError, "The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported." end end # @private class Space attr_reader :proxies, :any_instance_recorders, :proxy_mutex, :any_instance_mutex def initialize @proxies = {} @any_instance_recorders = {} @constant_mutators = [] @expectation_ordering = OrderGroup.new @proxy_mutex = new_mutex @any_instance_mutex = new_mutex end def new_scope NestedSpace.new(self) end def verify_all proxies.values.each { |proxy| proxy.verify } any_instance_recorders.each_value { |recorder| recorder.verify } end def reset_all proxies.each_value { |proxy| proxy.reset } any_instance_recorders.each_value { |recorder| recorder.stop_all_observation! } any_instance_recorders.clear @constant_mutators.reverse.each { |mut| mut.idempotently_reset } end def register_constant_mutator(mutator) @constant_mutators << mutator end def constant_mutator_for(name) @constant_mutators.find { |m| m.full_constant_name == name } end def any_instance_recorder_for(klass, only_return_existing=false) any_instance_mutex.synchronize do id = klass.__id__ any_instance_recorders.fetch(id) do return nil if only_return_existing any_instance_recorder_not_found_for(id, klass) end end end def any_instance_proxy_for(klass) AnyInstance::Proxy.new(any_instance_recorder_for(klass), proxies_of(klass)) end def proxies_of(klass) proxies.values.select { |proxy| klass === proxy.object } end def proxy_for(object) proxy_mutex.synchronize do id = id_for(object) proxies.fetch(id) { proxy_not_found_for(id, object) } end end def superclass_proxy_for(klass) proxy_mutex.synchronize do id = id_for(klass) proxies.fetch(id) { superclass_proxy_not_found_for(id, klass) } end end alias ensure_registered proxy_for def registered?(object) proxies.key?(id_for object) end def any_instance_recorders_from_ancestry_of(object) # Optimization: `any_instance` is a feature we generally # recommend not using, so we can often early exit here # without doing an O(N) linear search over the number of # ancestors in the object's class hierarchy. return [] if any_instance_recorders.empty? # We access the ancestors through the singleton class, to avoid calling # `class` in case `class` has been stubbed. (class << object; ancestors; end).map do |klass| any_instance_recorders[klass.__id__] end.compact end private def new_mutex Support::ReentrantMutex.new end def proxy_not_found_for(id, object) proxies[id] = case object when NilClass then ProxyForNil.new(@expectation_ordering) when TestDouble then object.__build_mock_proxy_unless_expired(@expectation_ordering) when Class class_proxy_with_callback_verification_strategy(object, CallbackInvocationStrategy.new) else if RSpec::Mocks.configuration.verify_partial_doubles? VerifyingPartialDoubleProxy.new(object, @expectation_ordering) else PartialDoubleProxy.new(object, @expectation_ordering) end end end def superclass_proxy_not_found_for(id, object) raise "superclass_proxy_not_found_for called with something that is not a class" unless Class === object proxies[id] = class_proxy_with_callback_verification_strategy(object, NoCallbackInvocationStrategy.new) end def class_proxy_with_callback_verification_strategy(object, strategy) if RSpec::Mocks.configuration.verify_partial_doubles? VerifyingPartialClassDoubleProxy.new( self, object, @expectation_ordering, strategy ) else PartialClassDoubleProxy.new(self, object, @expectation_ordering) end end def any_instance_recorder_not_found_for(id, klass) any_instance_recorders[id] = AnyInstance::Recorder.new(klass) end if defined?(::BasicObject) && !::BasicObject.method_defined?(:__id__) # for 1.9.2 require 'securerandom' def id_for(object) id = object.__id__ return id if object.equal?(::ObjectSpace._id2ref(id)) # this suggests that object.__id__ is proxying through to some wrapped object object.instance_exec do @__id_for_rspec_mocks_space ||= ::SecureRandom.uuid end end else def id_for(object) object.__id__ end end end # @private class NestedSpace < Space def initialize(parent) @parent = parent super() end def proxies_of(klass) super + @parent.proxies_of(klass) end def constant_mutator_for(name) super || @parent.constant_mutator_for(name) end def registered?(object) super || @parent.registered?(object) end private def proxy_not_found_for(id, object) @parent.proxies[id] || super end def any_instance_recorder_not_found_for(id, klass) @parent.any_instance_recorders[id] || super end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks/example_methods.rb0000664000000000000000000004661114557670305025536 0ustar rootrootRSpec::Support.require_rspec_mocks 'object_reference' module RSpec module Mocks # Contains methods intended to be used from within code examples. # Mix this in to your test context (such as a test framework base class) # to use rspec-mocks with your test framework. If you're using rspec-core, # it'll take care of doing this for you. module ExampleMethods include RSpec::Mocks::ArgumentMatchers # @overload double() # @overload double(name) # @param name [String/Symbol] name or description to be used in failure messages # @overload double(stubs) # @param stubs (Hash) hash of message/return-value pairs # @overload double(name, stubs) # @param name [String/Symbol] name or description to be used in failure messages # @param stubs (Hash) hash of message/return-value pairs # @return (Double) # # Constructs an instance of [RSpec::Mocks::Double](RSpec::Mocks::Double) configured # with an optional name, used for reporting in failure messages, and an optional # hash of message/return-value pairs. # # @example # book = double("book", :title => "The RSpec Book") # book.title #=> "The RSpec Book" # # card = double("card", :suit => "Spades", :rank => "A") # card.suit #=> "Spades" # card.rank #=> "A" # def double(*args) ExampleMethods.declare_double(Double, *args) end # @overload instance_double(doubled_class) # @param doubled_class [String, Class] # @overload instance_double(doubled_class, name) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @overload instance_double(doubled_class, stubs) # @param doubled_class [String, Class] # @param stubs [Hash] hash of message/return-value pairs # @overload instance_double(doubled_class, name, stubs) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return InstanceVerifyingDouble # # Constructs a test double against a specific class. If the given class # name has been loaded, only instance methods defined on the class are # allowed to be stubbed. In all other ways it behaves like a # [double](double). def instance_double(doubled_class, *args) ref = ObjectReference.for(doubled_class) ExampleMethods.declare_verifying_double(InstanceVerifyingDouble, ref, *args) end # @overload class_double(doubled_class) # @param doubled_class [String, Module] # @overload class_double(doubled_class, name) # @param doubled_class [String, Module] # @param name [String/Symbol] name or description to be used in failure messages # @overload class_double(doubled_class, stubs) # @param doubled_class [String, Module] # @param stubs [Hash] hash of message/return-value pairs # @overload class_double(doubled_class, name, stubs) # @param doubled_class [String, Module] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return ClassVerifyingDouble # # Constructs a test double against a specific class. If the given class # name has been loaded, only class methods defined on the class are # allowed to be stubbed. In all other ways it behaves like a # [double](double). def class_double(doubled_class, *args) ref = ObjectReference.for(doubled_class) ExampleMethods.declare_verifying_double(ClassVerifyingDouble, ref, *args) end # @overload object_double(object_or_name) # @param object_or_name [String, Object] # @overload object_double(object_or_name, name) # @param object_or_name [String, Object] # @param name [String/Symbol] name or description to be used in failure messages # @overload object_double(object_or_name, stubs) # @param object_or_name [String, Object] # @param stubs [Hash] hash of message/return-value pairs # @overload object_double(object_or_name, name, stubs) # @param object_or_name [String, Object] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return ObjectVerifyingDouble # # Constructs a test double against a specific object. Only the methods # the object responds to are allowed to be stubbed. If a String argument # is provided, it is assumed to reference a constant object which is used # for verification. In all other ways it behaves like a [double](double). def object_double(object_or_name, *args) ref = ObjectReference.for(object_or_name, :allow_direct_object_refs) ExampleMethods.declare_verifying_double(ObjectVerifyingDouble, ref, *args) end # @overload spy() # @overload spy(name) # @param name [String/Symbol] name or description to be used in failure messages # @overload spy(stubs) # @param stubs (Hash) hash of message/return-value pairs # @overload spy(name, stubs) # @param name [String/Symbol] name or description to be used in failure messages # @param stubs (Hash) hash of message/return-value pairs # @return (Double) # # Constructs a test double that is optimized for use with # `have_received`. With a normal double one has to stub methods in order # to be able to spy them. A spy automatically spies on all methods. def spy(*args) double(*args).as_null_object end # @overload instance_spy(doubled_class) # @param doubled_class [String, Class] # @overload instance_spy(doubled_class, name) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @overload instance_spy(doubled_class, stubs) # @param doubled_class [String, Class] # @param stubs [Hash] hash of message/return-value pairs # @overload instance_spy(doubled_class, name, stubs) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return InstanceVerifyingDouble # # Constructs a test double that is optimized for use with `have_received` # against a specific class. If the given class name has been loaded, only # instance methods defined on the class are allowed to be stubbed. With # a normal double one has to stub methods in order to be able to spy # them. An instance_spy automatically spies on all instance methods to # which the class responds. def instance_spy(*args) instance_double(*args).as_null_object end # @overload object_spy(object_or_name) # @param object_or_name [String, Object] # @overload object_spy(object_or_name, name) # @param object_or_name [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @overload object_spy(object_or_name, stubs) # @param object_or_name [String, Object] # @param stubs [Hash] hash of message/return-value pairs # @overload object_spy(object_or_name, name, stubs) # @param object_or_name [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return ObjectVerifyingDouble # # Constructs a test double that is optimized for use with `have_received` # against a specific object. Only instance methods defined on the object # are allowed to be stubbed. With a normal double one has to stub # methods in order to be able to spy them. An object_spy automatically # spies on all methods to which the object responds. def object_spy(*args) object_double(*args).as_null_object end # @overload class_spy(doubled_class) # @param doubled_class [String, Module] # @overload class_spy(doubled_class, name) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @overload class_spy(doubled_class, stubs) # @param doubled_class [String, Module] # @param stubs [Hash] hash of message/return-value pairs # @overload class_spy(doubled_class, name, stubs) # @param doubled_class [String, Class] # @param name [String/Symbol] name or description to be used in failure messages # @param stubs [Hash] hash of message/return-value pairs # @return ClassVerifyingDouble # # Constructs a test double that is optimized for use with `have_received` # against a specific class. If the given class name has been loaded, # only class methods defined on the class are allowed to be stubbed. # With a normal double one has to stub methods in order to be able to spy # them. An class_spy automatically spies on all class methods to which the # class responds. def class_spy(*args) class_double(*args).as_null_object end # Disables warning messages about expectations being set on nil. # # By default warning messages are issued when expectations are set on # nil. This is to prevent false-positives and to catch potential bugs # early on. # @deprecated Use {RSpec::Mocks::Configuration#allow_message_expectations_on_nil} instead. def allow_message_expectations_on_nil RSpec::Mocks.space.proxy_for(nil).warn_about_expectations = false end # Stubs the named constant with the given value. # Like method stubs, the constant will be restored # to its original value (or lack of one, if it was # undefined) when the example completes. # # @param constant_name [String] The fully qualified name of the constant. The current # constant scoping at the point of call is not considered. # @param value [Object] The value to make the constant refer to. When the # example completes, the constant will be restored to its prior state. # @param options [Hash] Stubbing options. # @option options :transfer_nested_constants [Boolean, Array] Determines # what nested constants, if any, will be transferred from the original value # of the constant to the new value of the constant. This only works if both # the original and new values are modules (or classes). # @return [Object] the stubbed value of the constant # # @example # stub_const("MyClass", Class.new) # => Replaces (or defines) MyClass with a new class object. # stub_const("SomeModel::PER_PAGE", 5) # => Sets SomeModel::PER_PAGE to 5. # # class CardDeck # SUITS = [:Spades, :Diamonds, :Clubs, :Hearts] # NUM_CARDS = 52 # end # # stub_const("CardDeck", Class.new) # CardDeck::SUITS # => uninitialized constant error # CardDeck::NUM_CARDS # => uninitialized constant error # # stub_const("CardDeck", Class.new, :transfer_nested_constants => true) # CardDeck::SUITS # => our suits array # CardDeck::NUM_CARDS # => 52 # # stub_const("CardDeck", Class.new, :transfer_nested_constants => [:SUITS]) # CardDeck::SUITS # => our suits array # CardDeck::NUM_CARDS # => uninitialized constant error def stub_const(constant_name, value, options={}) ConstantMutator.stub(constant_name, value, options) end # Hides the named constant with the given value. The constant will be # undefined for the duration of the test. # # Like method stubs, the constant will be restored to its original value # when the example completes. # # @param constant_name [String] The fully qualified name of the constant. # The current constant scoping at the point of call is not considered. # # @example # hide_const("MyClass") # => MyClass is now an undefined constant def hide_const(constant_name) ConstantMutator.hide(constant_name) end # Verifies that the given object received the expected message during the # course of the test. On a spy objects or as null object doubles this # works for any method, on other objects the method must have # been stubbed beforehand in order for messages to be verified. # # Stubbing and verifying messages received in this way implements the # Test Spy pattern. # # @param method_name [Symbol] name of the method expected to have been # called. # # @example # invitation = double('invitation', accept: true) # user.accept_invitation(invitation) # expect(invitation).to have_received(:accept) # # # You can also use most message expectations: # expect(invitation).to have_received(:accept).with(mailer).once # # @note `have_received(...).with(...)` is unable to work properly when # passed arguments are mutated after the spy records the received message. def have_received(method_name, &block) Matchers::HaveReceived.new(method_name, &block) end # Turns off the verifying of partial doubles for the duration of the # block, this is useful in situations where methods are defined at run # time and you wish to define stubs for them but not turn off partial # doubles for the entire run suite. (e.g. view specs in rspec-rails). def without_partial_double_verification original_state = Mocks.configuration.temporarily_suppress_partial_double_verification Mocks.configuration.temporarily_suppress_partial_double_verification = true yield ensure Mocks.configuration.temporarily_suppress_partial_double_verification = original_state end # @method expect # Used to wrap an object in preparation for setting a mock expectation # on it. # # @example # expect(obj).to receive(:foo).with(5).and_return(:return_value) # # @note This method is usually provided by rspec-expectations. However, # if you use rspec-mocks without rspec-expectations, there's a definition # of it that is made available here. If you disable the `:expect` syntax # this method will be undefined. # @method allow # Used to wrap an object in preparation for stubbing a method # on it. # # @example # allow(dbl).to receive(:foo).with(5).and_return(:return_value) # # @note If you disable the `:expect` syntax this method will be undefined. # @method expect_any_instance_of # Used to wrap a class in preparation for setting a mock expectation # on instances of it. # # @example # expect_any_instance_of(MyClass).to receive(:foo) # # @note If you disable the `:expect` syntax this method will be undefined. # @method allow_any_instance_of # Used to wrap a class in preparation for stubbing a method # on instances of it. # # @example # allow_any_instance_of(MyClass).to receive(:foo) # # @note This is only available when you have enabled the `expect` syntax. # @method receive # Used to specify a message that you expect or allow an object # to receive. The object returned by `receive` supports the same # fluent interface that `should_receive` and `stub` have always # supported, allowing you to constrain the arguments or number of # times, and configure how the object should respond to the message. # # @example # expect(obj).to receive(:hello).with("world").exactly(3).times # # @note If you disable the `:expect` syntax this method will be undefined. # @method receive_messages # Shorthand syntax used to setup message(s), and their return value(s), # that you expect or allow an object to receive. The method takes a hash # of messages and their respective return values. Unlike with `receive`, # you cannot apply further customizations using a block or the fluent # interface. # # @example # allow(obj).to receive_messages(:speak => "Hello World") # allow(obj).to receive_messages(:speak => "Hello", :meow => "Meow") # # @note If you disable the `:expect` syntax this method will be undefined. # @method receive_message_chain # @overload receive_message_chain(method1, method2) # @overload receive_message_chain("method1.method2") # @overload receive_message_chain(method1, method_to_value_hash) # # stubs/mocks a chain of messages on an object or test double. # # ## Warning: # # Chains can be arbitrarily long, which makes it quite painless to # violate the Law of Demeter in violent ways, so you should consider any # use of `receive_message_chain` a code smell. Even though not all code smells # indicate real problems (think fluent interfaces), `receive_message_chain` still # results in brittle examples. For example, if you write # `allow(foo).to receive_message_chain(:bar, :baz => 37)` in a spec and then the # implementation calls `foo.baz.bar`, the stub will not work. # # @example # allow(double).to receive_message_chain("foo.bar") { :baz } # allow(double).to receive_message_chain(:foo, :bar => :baz) # allow(double).to receive_message_chain(:foo, :bar) { :baz } # # # Given any of ^^ these three forms ^^: # double.foo.bar # => :baz # # # Common use in Rails/ActiveRecord: # allow(Article).to receive_message_chain("recent.published") { [Article.new] } # # @note If you disable the `:expect` syntax this method will be undefined. # @private def self.included(klass) klass.class_exec do # This gets mixed in so that if `RSpec::Matchers` is included in # `klass` later, its definition of `expect` will take precedence. include ExpectHost unless method_defined?(:expect) end end # @private def self.extended(object) # This gets extended in so that if `RSpec::Matchers` is included in # `klass` later, its definition of `expect` will take precedence. object.extend ExpectHost unless object.respond_to?(:expect) end # @private def self.declare_verifying_double(type, ref, *args) if RSpec::Mocks.configuration.verify_doubled_constant_names? && !ref.defined? RSpec::Mocks.error_generator.raise_verifying_double_not_defined_error(ref) end RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| block.call(ref) end declare_double(type, ref, *args) end # @private def self.declare_double(type, *args) args << {} unless Hash === args.last type.new(*args) end # This module exists to host the `expect` method for cases where # rspec-mocks is used w/o rspec-expectations. module ExpectHost end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-mocks/lib/rspec/mocks.rb0000664000000000000000000001051214557670305022347 0ustar rootrootrequire 'rspec/support' RSpec::Support.require_rspec_support 'caller_filter' RSpec::Support.require_rspec_support 'warnings' RSpec::Support.require_rspec_support 'ruby_features' RSpec::Support.define_optimized_require_for_rspec(:mocks) { |f| require_relative f } %w[ instance_method_stasher method_double argument_matchers example_methods proxy test_double argument_list_matcher message_expectation order_group error_generator space mutate_const targets syntax configuration verifying_double version ].each { |name| RSpec::Support.require_rspec_mocks name } # Share the top-level RSpec namespace, because we are a core supported # extension. module RSpec # Contains top-level utility methods. While this contains a few # public methods, these are not generally meant to be called from # a test or example. They exist primarily for integration with # test frameworks (such as rspec-core). module Mocks # Performs per-test/example setup. This should be called before # an test or example begins. def self.setup @space_stack << (@space = space.new_scope) end # Verifies any message expectations that were set during the # test or example. This should be called at the end of an example. def self.verify space.verify_all end # Cleans up all test double state (including any methods that were # redefined on partial doubles). This _must_ be called after # each example, even if an error was raised during the example. def self.teardown space.reset_all @space_stack.pop @space = @space_stack.last || @root_space end # Adds an allowance (stub) on `subject` # # @param subject the subject to which the message will be added # @param message a symbol, representing the message that will be # added. # @param opts a hash of options, :expected_from is used to set the # original call site # @yield an optional implementation for the allowance # # @example Defines the implementation of `foo` on `bar`, using the passed block # x = 0 # RSpec::Mocks.allow_message(bar, :foo) { x += 1 } def self.allow_message(subject, message, opts={}, &block) space.proxy_for(subject).add_stub(message, opts, &block) end # Sets a message expectation on `subject`. # @param subject the subject on which the message will be expected # @param message a symbol, representing the message that will be # expected. # @param opts a hash of options, :expected_from is used to set the # original call site # @yield an optional implementation for the expectation # # @example Expect the message `foo` to receive `bar`, then call it # RSpec::Mocks.expect_message(bar, :foo) # bar.foo def self.expect_message(subject, message, opts={}, &block) space.proxy_for(subject).add_message_expectation(message, opts, &block) end # Call the passed block and verify mocks after it has executed. This allows # mock usage in arbitrary places, such as a `before(:all)` hook. # # @return [Object] the return value from the block def self.with_temporary_scope setup begin result = yield verify result ensure teardown end end class << self # @private attr_reader :space end @space_stack = [] @root_space = @space = RSpec::Mocks::RootSpace.new # @private IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored' # To speed up boot time a bit, delay loading optional or rarely # used features until their first use. autoload :AnyInstance, "rspec/mocks/any_instance" autoload :ExpectChain, "rspec/mocks/message_chain" autoload :StubChain, "rspec/mocks/message_chain" autoload :MarshalExtension, "rspec/mocks/marshal_extension" # Namespace for mock-related matchers. module Matchers # @private # just a "tag" for rspec-mock matchers detection module Matcher; end autoload :HaveReceived, "rspec/mocks/matchers/have_received" autoload :Receive, "rspec/mocks/matchers/receive" autoload :ReceiveMessageChain, "rspec/mocks/matchers/receive_message_chain" autoload :ReceiveMessages, "rspec/mocks/matchers/receive_messages" end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec/0000775000000000000000000000000014567461030015705 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec/LICENSE.md0000664000000000000000000000231014557700441017306 0ustar rootrootThe MIT License (MIT) ===================== Copyright © 2009 Chad Humphries, David Chelimsky Copyright © 2006 David Chelimsky, The RSpec Development Team Copyright © 2005 Steven Baker 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. ruby-rspec_3.13.0c0e0m0s1.orig/rspec/code_of_conduct.md0000664000000000000000000000544414557700441021354 0ustar rootroot # Contributor Code of Conduct For the purpose of building a welcoming, harassment-free community that values contributions from anyone, the RSpec project has adopted the following code of conduct. All contributors and participants (including maintainers!) are expected to abide by its terms. As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the project maintainers listed at https://rspec.info/about/. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/3/0/ ruby-rspec_3.13.0c0e0m0s1.orig/rspec/Gemfile0000664000000000000000000000027014557700441017200 0ustar rootrootsource "https://rubygems.org" gem "rake" %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| gem lib, :path => File.expand_path("../../#{lib}", __FILE__) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec/.document0000664000000000000000000000002514557700441017522 0ustar rootrootREADME.md LICENSE.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec/README.md0000664000000000000000000000331114557700441017163 0ustar rootroot# RSpec Behaviour Driven Development for Ruby **The rspec metagem repository has been renamed to rspec-metagem, please update any rspec/rspec Github references to rspec/rspec-metagem, this is in preparation for a new mono-repo approach to RSpec dev to unify issue tracking and PR management** ## Description rspec is a meta-gem, which depends on the [rspec-core](https://github.com/rspec/rspec-core), [rspec-expectations](https://github.com/rspec/rspec-expectations) and [rspec-mocks](https://github.com/rspec/rspec-mocks) gems. Each of these can be installed separately and loaded in isolation using `require`. Among other benefits, this allows you to use rspec-expectations, for example, in Test::Unit::TestCase if you happen to prefer that style. Conversely, if you like RSpec's approach to declaring example groups and examples (`describe` and `it`) but prefer Test::Unit assertions and [mocha](https://github.com/freerange/mocha), [rr](https://github.com/rr/rr) or [flexmock](https://github.com/jimweirich/flexmock) for mocking, you'll be able to do that without having to install or load the components of RSpec that you're not using. ## Documentation See http://rspec.info/documentation/ for links to documentation for all gems. ## Install gem install rspec ## Setup rspec --init ## Contribute * [http://github.com/rspec/rspec-dev](http://github.com/rspec/rspec-dev) ## Also see * [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core) * [https://github.com/rspec/rspec-expectations](https://github.com/rspec/rspec-expectations) * [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks) * [https://github.com/rspec/rspec-rails](https://github.com/rspec/rspec-rails) ruby-rspec_3.13.0c0e0m0s1.orig/rspec/Rakefile0000664000000000000000000000076714557700441017365 0ustar rootrootrequire "bundler" Bundler.setup Bundler::GemHelper.install_tasks require 'rake' require 'fileutils' require 'pathname' task :clobber do rm_rf 'pkg' end task :default do puts "Nothing to do for the default task" end task :verify_private_key_present do private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') unless File.exist?(private_key) raise "Your private key is not present. This gem should not be built without it." end end task :build => :verify_private_key_present ruby-rspec_3.13.0c0e0m0s1.orig/rspec/.github/0000775000000000000000000000000014557700441017246 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec/.github/FUNDING.yml0000664000000000000000000000033514557700441021064 0ustar rootroot# This file was generated on 2020-12-27T11:49:58+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, benoittgt] open_collective: rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec/rspec.gemspec0000664000000000000000000000326014557700441020370 0ustar rootroot# -*- encoding: utf-8 -*- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require "rspec/version" Gem::Specification.new do |s| s.name = "rspec" s.version = RSpec::Version::STRING s.platform = Gem::Platform::RUBY s.license = "MIT" s.authors = ["Steven Baker", "David Chelimsky", "Myron Marston"] s.email = "rspec@googlegroups.com" s.homepage = "http://github.com/rspec" s.summary = "rspec-#{RSpec::Version::STRING}" s.description = "BDD for Ruby" s.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-metagem/issues', 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-metagem', } s.files = `git ls-files -- lib/*`.split("\n") s.files += ["LICENSE.md"] s.test_files = `git ls-files -- {spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.extra_rdoc_files = [ "README.md" ] s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) s.signing_key = private_key s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')] end %w[core expectations mocks].each do |name| if RSpec::Version::STRING =~ /[a-zA-Z]+/ s.add_runtime_dependency "rspec-#{name}", "= #{RSpec::Version::STRING}" else s.add_runtime_dependency "rspec-#{name}", "~> #{RSpec::Version::STRING.split('.')[0..1].concat(['0']).join('.')}" end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec/.gitignore0000664000000000000000000000013114557700441017671 0ustar rootroot*.sw? .DS_Store coverage doc pkg Gemfile.lock .bundle *.rbc bin bundle .bundle specs.out ruby-rspec_3.13.0c0e0m0s1.orig/rspec/certs/0000775000000000000000000000000014557700441017026 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec/certs/rspec.pem0000664000000000000000000000404214557700441020645 0ustar rootroot-----BEGIN CERTIFICATE----- MIIF1TCCA72gAwIBAgIJAPXjfUbCjdXUMA0GCSqGSIb3DQEBBQUAMIGAMQswCQYD VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEO MAwGA1UECgwFUlNwZWMxEzARBgNVBAMMCnJzcGVjLmluZm8xJTAjBgkqhkiG9w0B CQEWFnJzcGVjQGdvb2dsZWdyb3Vwcy5jb20wHhcNMTQxMjIzMDkzNTIyWhcNMjQx MjIyMDkzNTIyWjCBgDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24x EDAOBgNVBAcMB1NlYXR0bGUxDjAMBgNVBAoMBVJTcGVjMRMwEQYDVQQDDApyc3Bl Yy5pbmZvMSUwIwYJKoZIhvcNAQkBFhZyc3BlY0Bnb29nbGVncm91cHMuY29tMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsSmjgcHaKlD0jizRJowi2bGI KMOHnJoExxRNHHxH+3w9kkl95YldvDRVX495b13ZCzwRe0AyqX24wq04tp0G5Z5C e/w2pnNK4ol1eECPwQu+YGpepeODlZICL5gwQspe0cDifbBnHx5QySMiPpvx6bC0 tQTox0ppDIaMhch8IPCwyoE4DQK5bpsdwnLSHTsQjUIb7IM8tUMpd/iKrJgNffwc 6gC1TmhIlzQoB26nCNh9uK7xZjUM+sGECzvcYuImchUaIgJA/ybrlZS+m/hxzvBo mLnn/xNEC6Vz5HG+3TR0Gb0cSUf6XUu2s51Jk/SJi3MhCZp2gs9OUg4EVZNzQVkZ efLBjAZG2Mxk14JyB4/Omc+Jk0ajprINCBbUNnxzCJrYDM3J9TVWIwyUGNX/U3MO s3tMAT+EVgx/mZMPnBO8EULlyF51MRUp3Wy9Mnw8AYLk30UnMG5AjqgO5JNyFlA7 Xeh3EVdWY3vMB1pkhPwlsenpcmj5gOzrd54lELOVbCGHCf48iSqeflY2Lhe0pvzK blXCJBDmtrebvus291rM/dHcbEfK1SVd5Wut/n131iouf6dnNCFskFygDcgBbthC gpEMqf80lEmhX59VUsm0Pv6OEo+ZPHBvXPiJA6DShQh9t3YtpwyA8uVDMbT/i32u 2FUsqZbbJcCmkBrGposCAwEAAaNQME4wHQYDVR0OBBYEFPPvQ5XT0Nvuhi6k+hrW Vv35J+TeMB8GA1UdIwQYMBaAFPPvQ5XT0Nvuhi6k+hrWVv35J+TeMAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggIBAIqbQSWH2aAF537DKwAMB8nMFsoe24MD gtuQAyjTtbH+QBE4N2RdQF/sU7Y3PYR7nqdrCsYc3RxyqM5XXi7I3IYdpfe1RuxY +pyPzVQsPPDhMlJlCrwJsADnxlpxZlAgxYSLKOan55ihscaAWA90wqRUrf/ZJM36 8LWCPVn5teIt5aaxZWX68RMxa+AXvpbtJOBwXLkIFk3apD8CX4DhelIdw67DbkUe ghUd/u62qrnqBTVgditt7OoWIZjzh24/Fda5d0MxZyvLILGOrf5bN4cTbe/q9Cid Xrik7Upm+mu3y3yQIfrw85xybHq6iNXyYHvCdSrFfCIKrGpd/0CAdmYnJlx59Fk/ UbD3Eyx4psBSkU+WKO0Uf+3zNI7N/nVeNIwU/Ft+l8l7/K+427656c+ZGWDO0Gt/ BeEOSTDKP7qQ1T+JvMrBcBQo+i0cnRT10J1aoV90BhxsvWTRizIbugbaqR6Tq3bj Akt00cIlNSplL6DenIAKSh5kF7s0tRD0tC3bNkZmNjNGkdoGEcUODEpTB3RHKKiu e6k2Jg6m00z5vGFQhOnROG/QaUzMA3A3mFBe1RHFo07xd0pFeoeWL3vF69Gx9Jwp ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ F3MdtaDehhjC -----END CERTIFICATE----- ruby-rspec_3.13.0c0e0m0s1.orig/rspec/certs/samphippen.asc0000664000000000000000000000153314557700441021664 0ustar rootroot-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 Comment: GPGTools - http://gpgtools.org iQIcBAABAgAGBQJUmVdPAAoJEKwl90pEDFVi6AwP/iFWdVaiWOHffXl2qZ7fi6QV 6Dl0aPFErES9rQoJQ6oa2IOdUBlKbyi2hWeHeExXpnDf2l+PCDZU8Jy/XDdvPXCH jdKup+un8GWPk1X1PijYlfBpRqiJ/j5xedMiw+G/LwV4Lh1ltGBKABoKKsnoLUD3 S1bY5636tvBxU6HkhLVutSKUFeiRuavX5rpQSlzp9rlbsdAOU0/codh81F2ENhJa TobfB4AhJGqVG7lrIFWzvcfyXakFMMYDPI6tIEHTXk1EaHjJyfLB7aI/4ri2vJdb OpHd/zrqTuIyc4Y/4+JVL/CyiNPZvPf27k8vjeIgRYvSiaXDsaysK4Ox/AqN51JL bZg7S39ARMI+LH/jvg+5Gb6hUyGnc+sIyceKktlze46TElZQo6QZOAO5v0EUWsH9 Wcj27hb+iZJ9gmmE46Ns+u/r2aT596eJxIe9NatoP/1A1d89vKYU1eGTijLk3L5A 4B+1lzofgcN3NWURu8zr6rRWLdoi39HfFRg0ETWArxgpKRpRIwK3Nkg6VlEHL+7+ AitAONGdgQkvy3DLtzR8952GqUmOby/kxct82wOo6DIs/IWsRSW9wcaSsXgOOyjJ Up3Z9POr5VfFINusyXT1FkGnolb6piuiPlKiwHAr4rySUglXKd0Tx7EboB2PwQSi 9KhkO7foz/VItBIEs+s8 =Ggk4 -----END PGP SIGNATURE----- ruby-rspec_3.13.0c0e0m0s1.orig/rspec/lib/0000775000000000000000000000000014557700441016454 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec/lib/rspec.rb0000664000000000000000000000005614557700441020116 0ustar rootrootrequire 'rspec/core' require 'rspec/version' ruby-rspec_3.13.0c0e0m0s1.orig/rspec/lib/rspec/0000775000000000000000000000000014557700441017570 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec/lib/rspec/version.rb0000664000000000000000000000012214557700441021575 0ustar rootrootmodule RSpec # :nodoc: module Version # :nodoc: STRING = '3.13.0' end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/0000775000000000000000000000000014567461030016633 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.rubocop_rspec_base.yml0000664000000000000000000001500514557677674023322 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. # This file contains defaults for RSpec projects. Individual projects # can customize by inheriting this file and overriding particular settings. Layout/AccessModifierIndentation: Enabled: false # "Use alias_method instead of alias" # We're fine with `alias`. Style/Alias: Enabled: false # "Avoid the use of the case equality operator ===" # We prefer using `Class#===` over `Object#is_a?` because `Class#===` # is less likely to be monkey patched than `is_a?` on a user object. Style/CaseEquality: Enabled: false # Warns when the class is excessively long. Metrics/ClassLength: Max: 100 Style/CollectionMethods: PreferredMethods: reduce: 'inject' # Over time we'd like to get this down, but this is what we're at now. Metrics/CyclomaticComplexity: Max: 10 # We use YARD to enforce documentation. It works better than rubocop's # enforcement...rubocop complains about the places we re-open # `RSpec::Expectations` and `RSpec::Matchers` w/o having doc commments. Style/Documentation: Enabled: false # We still support 1.8.7 which requires trailing dots Layout/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: Enabled: false # each_with_object is unavailable on 1.8.7 so we have to disable this one. Style/EachWithObject: Enabled: false Style/FormatString: EnforcedStyle: percent # As long as we support ruby 1.8.7 we have to use hash rockets. Style/HashSyntax: EnforcedStyle: hash_rockets # We can't use the new lambda syntax, since we still support 1.8.7. Style/Lambda: Enabled: false # Over time we'd like to get this down, but this is what we're at now. Layout/LineLength: Max: 100 # Over time we'd like to get this down, but this is what we're at now. Metrics/MethodLength: Max: 15 # Who cares what we call the argument for binary operator methods? Naming/BinaryOperatorParameterName: Enabled: false Style/PercentLiteralDelimiters: PreferredDelimiters: '%': () # double-quoted string '%i': '[]' # array of symbols '%q': () # single-quoted string '%Q': () # double-quoted string '%r': '{}' # regular expression pattern '%s': () # a symbol '%w': '[]' # array of single-quoted strings '%W': '[]' # array of double-quoted strings '%x': () # a shell command as a string # We have too many special cases where we allow generator methods or prefer a # prefixed predicate due to it's improved readability. Naming/PredicateName: Enabled: false # On 1.8 `proc` is `lambda`, so we use `Proc.new` to ensure we get real procs on all supported versions. # http://batsov.com/articles/2014/02/04/the-elements-of-style-in-ruby-number-12-proc-vs-proc-dot-new/ Style/Proc: Enabled: false # Exceptions should be rescued with `Support::AllExceptionsExceptOnesWeMustNotRescue` Lint/RescueException: Enabled: true # We haven't adopted the `fail` to signal exceptions vs `raise` for re-raises convention. Style/SignalException: Enabled: false # We've tended to use no space, so it's less of a change to stick with that. Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space # We don't care about single vs double qoutes. Style/StringLiterals: Enabled: false # This rule favors constant names from the English standard library which we don't load. Style/SpecialGlobalVars: Enabled: false Style/TrailingCommaInArrayLiteral: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingCommaInArguments: Enabled: false Style/TrivialAccessors: AllowDSLWriters: true AllowPredicates: true ExactNameMatch: true Style/ParallelAssignment: Enabled: false Layout/EmptyLineBetweenDefs: Enabled: false Layout/FirstParameterIndentation: Enabled: false Layout/ParameterAlignment: EnforcedStyle: with_first_parameter Layout/SpaceInsideBlockBraces: Enabled: false Layout/SpaceInsideParens: Enabled: false Naming/ConstantName: Enabled: false Style/ClassCheck: Enabled: false Style/ConditionalAssignment: Enabled: false Style/EmptyMethod: Enabled: false Style/FormatStringToken: Enabled: false Style/GuardClause: Enabled: false Style/IdenticalConditionalBranches: Enabled: false Style/IfUnlessModifier: Enabled: false Style/IfUnlessModifierOfIfUnless: Enabled: false Lint/MissingSuper: Enabled: false Style/MissingRespondToMissing: Enabled: false Style/MixinUsage: Enabled: false Style/MultipleComparison: Enabled: false Style/MutableConstant: Enabled: false Style/NestedModifier: Enabled: false Style/NestedParenthesizedCalls: Enabled: false Style/NumericPredicate: Enabled: false Style/RedundantParentheses: Enabled: false Style/StringLiteralsInInterpolation: Enabled: false Style/SymbolArray: Enabled: false Style/SymbolProc: Enabled: false Style/YodaCondition: Enabled: false Style/ZeroLengthPredicate: Enabled: false Layout/ClosingParenthesisIndentation: Enabled: false Layout/ExtraSpacing: Enabled: false Layout/MultilineMethodCallBraceLayout: Enabled: false Layout/MultilineMethodCallIndentation: Enabled: false Layout/MultilineOperationIndentation: Enabled: false Layout/SpaceAroundBlockParameters: Enabled: false Layout/SpaceAroundOperators: Enabled: false Layout/SpaceBeforeComma: Enabled: false Style/BlockDelimiters: Enabled: false Style/EmptyCaseCondition: Enabled: false Style/MultilineIfModifier: Enabled: false Style/RescueStandardError: Enabled: false Style/StderrPuts: Enabled: false Style/TernaryParentheses: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Layout/AssignmentIndentation: Enabled: false Layout/EmptyLineAfterMagicComment: Enabled: false Layout/FirstArrayElementIndentation: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/SpaceInsidePercentLiteralDelimiters: Enabled: false Style/EmptyElse: Enabled: false Style/IfInsideElse: Enabled: false Style/RedundantReturn: Enabled: false Style/StructInheritance: Enabled: false Naming/VariableNumber: Enabled: false Layout/SpaceInsideStringInterpolation: Enabled: false Style/DateTime: Enabled: false Style/ParenthesesAroundCondition: Enabled: false Layout/EmptyLinesAroundBlockBody: Enabled: false Lint/ImplicitStringConcatenation: Enabled: false Lint/NestedMethodDefinition: Enabled: false Style/RegexpLiteral: Enabled: false Style/TrailingUnderscoreVariable: Enabled: false Layout/EmptyLinesAroundAccessModifier: Enabled: false ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/ISSUE_TEMPLATE.md0000664000000000000000000000102614557677674021365 0ustar rootroot ### Subject of the issue ### Your environment * Ruby version: * rspec-core version: ### Steps to reproduce ### Expected behavior ### Actual behavior ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/DEVELOPMENT.md0000664000000000000000000001151114557677674020764 0ustar rootroot # Development Setup Generally speaking, you only need to clone the project and install the dependencies with [Bundler](https://bundler.io/). You can either get a full RSpec development environment using [rspec-dev](https://github.com/rspec/rspec-dev#README) or you can set this project up individually. ## Setting up rspec-core individually For most contributors, setting up the project individually will be simpler. Unless you have a specific reason to use rspec-dev, we recommend using this approach. Clone the repo: ``` $ git clone git@github.com:rspec/rspec-core.git ``` Install the dependencies using [Bundler](https://bundler.io/): ``` $ cd rspec-core $ bundle install ``` To minimize boot time and to ensure we don't depend upon any extra dependencies loaded by Bundler, our CI builds avoid loading Bundler at runtime by using Bundler's [`--standalone option`](https://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone). While not strictly necessary (many/most of our contributors do not do this!), if you want to exactly reproduce our CI builds you'll want to do the same: ``` $ bundle install --standalone --binstubs ``` The `--binstubs` option creates the `bin/rspec` file that, like `bundle exec rspec`, will load all the versions specified in `Gemfile.lock` without loading bundler at runtime! ## Using rspec-dev See the [rspec-dev README](https://github.com/rspec/rspec-dev#README) for setup instructions. The rspec-dev project contains many rake tasks for helping manage an RSpec development environment, making it easy to do things like: * Change branches across all repos * Update all repos with the latest code from `main` * Cut a new release across all repos * Push out updated build scripts to all repos These sorts of tasks are essential for the RSpec maintainers but will probably be unnecessary complexity if you're just contributing to one repository. If you are getting setup to make your first contribution, we recommend you take the simpler route of setting up rspec-core individually. ## Gotcha: Version mismatch from sibling repos The [Gemfile](Gemfile) is designed to be flexible and support using the other RSpec repositories either from a local sibling directory (e.g. `../rspec-`) or, if there is no such directory, directly from git. This generally does the "right thing", but can be a gotcha in some situations. For example, if you are setting up `rspec-core`, and you happen to have an old clone of `rspec-expectations` in a sibling directory, it'll be used even though it might be months or years out of date, which can cause confusing failures. To avoid this problem, you can either `export USE_GIT_REPOS=1` to force the use of `:git` dependencies instead of local dependencies, or update the code in the sibling directory. rspec-dev contains rake tasks to help you keep all repos in sync. ## Extra Gems If you need additional gems for any tasks---such as `benchmark-ips` for benchmarking or `byebug` for debugging---you can create a `Gemfile-custom` file containing those gem declarations. The `Gemfile` evaluates that file if it exists, and it is git-ignored. # Running the build The [Travis CI build](https://travis-ci.org/rspec/rspec-core) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` See [build detail](BUILD_DETAIL.md) for more detail. # What to Expect To ensure high, uniform code quality, all code changes (including changes from the maintainers!) are subject to a pull request code review. We'll often ask for clarification or suggest alternate ways to do things. Our code reviews are intended to be a two-way conversation. Here's a short, non-exhaustive checklist of things we typically ask contributors to do before PRs are ready to merge. It can help get your PR merged faster if you do these in advance! - [ ] New behavior is covered by tests and all tests are passing. - [ ] No Ruby warnings are issued by your changes. - [ ] Documentation reflects changes and renders as intended. - [ ] RuboCop passes (e.g. `bundle exec rubocop lib`). - [ ] Commits are squashed into a reasonable number of logical changesets that tell an easy-to-follow story. - [ ] No changelog entry is necessary (we'll add it as part of the merge process!) # Adding Docs RSpec uses [YARD](https://yardoc.org/) for its API documentation. To ensure the docs render well, we recommend running a YARD server and viewing your edits in a browser. To run a YARD server: ``` $ bundle exec yard server --reload # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard server --reload ``` Then navigate to `localhost:8808` to view the rendered docs. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/0000775000000000000000000000000014557677674020776 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/respond_to_v_defined.rb0000664000000000000000000000271414557677674025506 0ustar rootrootrequire 'benchmark' n = 1_000_000 puts "Kernel.respond_to?(:warn)" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Kernel.respond_to?(:warn) end end end end puts "defined?(warn)" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do defined?(warn) end end end end puts "Kernel.respond_to?(:foo)" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Kernel.respond_to?(:foo) end end end end puts "defined?(foo)" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do defined?(foo) end end end end # $ ruby benchmarks/respond_to_v_defined.rb # Kernel.respond_to?(:warn) # 0.190000 0.000000 0.190000 ( 0.206502) # 0.190000 0.000000 0.190000 ( 0.197547) # 0.190000 0.000000 0.190000 ( 0.189731) # defined?(warn) # 0.190000 0.000000 0.190000 ( 0.187334) # 0.180000 0.000000 0.180000 ( 0.201078) # 0.190000 0.000000 0.190000 ( 0.202295) # Kernel.respond_to?(:foo) # 0.250000 0.010000 0.260000 ( 0.255003) # 0.240000 0.000000 0.240000 ( 0.247376) # 0.250000 0.000000 0.250000 ( 0.251196) # defined?(foo) # 0.100000 0.000000 0.100000 ( 0.104748) # 0.110000 0.000000 0.110000 ( 0.107250) # 0.110000 0.000000 0.110000 ( 0.107990) # # defined is consistently faster, but it takes 1,000,000 x to have a meaningful # diff ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/shuffle_vs_sort_by_for_random_ordering.rb0000664000000000000000000000777414557677674031346 0ustar rootrootrequire 'benchmark/ips' require 'digest/md5' class Digest::Jenkins MAX_32_BIT = 4294967295 def self.digest(string) hash = 0 string.each_byte do |byte| hash += byte hash &= MAX_32_BIT hash += ((hash << 10) & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 6 end hash += (hash << 3 & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 11 hash += (hash << 15 & MAX_32_BIT) hash &= MAX_32_BIT hash end end Example = Struct.new(:id) $seed = Kernel.srand.to_s def shuffle_list(list) list.shuffle end def sort_using_id(list) list.sort_by(&:id) end def sort_using_md5(list) list.sort_by { |item| Digest::MD5.digest($seed + item.id) } end def sort_using_jenkins(list) list.sort_by { |item| Digest::Jenkins.digest($seed + item.id) } end [10, 100, 1000, 10000].each do |size| puts "Size: #{size}" list = Array.new(size) { |i| Example.new("./some_spec.rb[1:#{i}]") } Benchmark.ips do |x| x.report("shuffle") { shuffle_list(list) } x.report("use id") { sort_using_id(list) } x.report("use md5") { sort_using_md5(list) } x.report("use jenkins") { sort_using_md5(list) } x.compare! end end __END__ Size: 10 Calculating ------------------------------------- shuffle 71.860k i/100ms use id 22.562k i/100ms use md5 4.620k i/100ms use jenkins 4.644k i/100ms ------------------------------------------------- shuffle 1.594M (±12.4%) i/s - 7.905M use id 299.105k (± 7.1%) i/s - 1.489M use md5 49.663k (± 7.5%) i/s - 249.480k use jenkins 49.389k (± 7.5%) i/s - 246.132k Comparison: shuffle: 1593820.8 i/s use id: 299104.9 i/s - 5.33x slower use md5: 49662.9 i/s - 32.09x slower use jenkins: 49389.2 i/s - 32.27x slower Size: 100 Calculating ------------------------------------- shuffle 24.629k i/100ms use id 2.076k i/100ms use md5 477.000 i/100ms use jenkins 483.000 i/100ms ------------------------------------------------- shuffle 317.269k (±13.8%) i/s - 1.576M use id 20.958k (± 4.2%) i/s - 105.876k use md5 4.916k (± 7.5%) i/s - 24.804k use jenkins 4.824k (± 8.6%) i/s - 24.150k Comparison: shuffle: 317269.5 i/s use id: 20957.6 i/s - 15.14x slower use md5: 4916.5 i/s - 64.53x slower use jenkins: 4823.5 i/s - 65.78x slower Size: 1000 Calculating ------------------------------------- shuffle 3.862k i/100ms use id 134.000 i/100ms use md5 44.000 i/100ms use jenkins 44.000 i/100ms ------------------------------------------------- shuffle 40.104k (± 4.4%) i/s - 200.824k use id 1.424k (±13.5%) i/s - 6.968k use md5 450.556 (± 8.0%) i/s - 2.244k use jenkins 450.189 (± 7.6%) i/s - 2.244k Comparison: shuffle: 40104.2 i/s use id: 1423.9 i/s - 28.16x slower use md5: 450.6 i/s - 89.01x slower use jenkins: 450.2 i/s - 89.08x slower Size: 10000 Calculating ------------------------------------- shuffle 374.000 i/100ms use id 10.000 i/100ms use md5 3.000 i/100ms use jenkins 4.000 i/100ms ------------------------------------------------- shuffle 3.750k (± 5.4%) i/s - 18.700k use id 109.008 (± 4.6%) i/s - 550.000 use md5 40.614 (± 9.8%) i/s - 201.000 use jenkins 39.975 (± 7.5%) i/s - 200.000 Comparison: shuffle: 3750.0 i/s use id: 109.0 i/s - 34.40x slower use md5: 40.6 i/s - 92.33x slower use jenkins: 40.0 i/s - 93.81x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/flat_map_vs_inject.rb0000664000000000000000000000322314557677674025152 0ustar rootrootrequire 'benchmark/ips' words = %w[ foo bar bazz big small medium large tiny less more good bad mediocre ] def flat_map_using_yield(array) array.flat_map { |item| yield item } end def flat_map_using_block(array, &block) array.flat_map(&block) end Benchmark.ips do |x| x.report("flat_map") do words.flat_map(&:codepoints) end x.report("inject (+)") do words.inject([]) { |a, w| a + w.codepoints } end x.report("inject (concat)") do words.inject([]) { |a, w| a.concat w.codepoints } end x.report("flat_map_using_yield") do flat_map_using_yield(words, &:codepoints) end x.report("flat_map_using_block") do flat_map_using_block(words, &:codepoints) end end __END__ Surprisingly, `flat_map(&block)` appears to be faster than `flat_map { yield }` in spite of the fact that our array here is smaller than the break-even point of 20-25 measured in the `capture_block_vs_yield.rb` benchmark. In fact, the forwarded-block version remains faster in my benchmarks here no matter how small I shrink the `words` array. I'm not sure why! Calculating ------------------------------------- flat_map 10.594k i/100ms inject (+) 8.357k i/100ms inject (concat) 10.404k i/100ms flat_map_using_yield 10.081k i/100ms flat_map_using_block 11.683k i/100ms ------------------------------------------------- flat_map 136.442k (±10.4%) i/s - 678.016k inject (+) 98.024k (± 9.7%) i/s - 493.063k inject (concat) 119.822k (±10.5%) i/s - 593.028k flat_map_using_yield 112.284k (± 9.7%) i/s - 564.536k flat_map_using_block 134.533k (± 6.3%) i/s - 677.614k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/0000775000000000000000000000000014557677674026112 5ustar rootroot././@LongLink0000644000000000000000000000022300000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_config_hooks_module_inclusions_and_shared_context_inclusions.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_config_hooks_modu0000664000000000000000000000220614557677674032564 0ustar rootrootrequire_relative "helper" RSpec.configure do |c| 10.times do c.before(:context, :apply_it) { } c.after(:context, :apply_it) { } c.include Module.new, :apply_it end end 1.upto(10) do |i| RSpec.shared_context "context #{i}", :apply_it do end end BenchmarkHelpers.run_benchmarks __END__ No match -- without singleton group support 544.396 (±34.0%) i/s - 2.340k No match -- with singleton group support 451.635 (±31.0%) i/s - 1.935k Example match -- without singleton group support 538.788 (±23.8%) i/s - 2.450k Example match -- with singleton group support 342.990 (±22.4%) i/s - 1.440k Group match -- without singleton group support 509.969 (±26.7%) i/s - 2.070k Group match -- with singleton group support 405.284 (±20.5%) i/s - 1.518k Both match -- without singleton group support 513.344 (±24.0%) i/s - 1.927k Both match -- with singleton group support 406.111 (±18.5%) i/s - 1.760k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_config_hooks.rb0000664000000000000000000000203714557677674032144 0ustar rootrootrequire_relative "helper" RSpec.configure do |c| 10.times do c.before(:context, :apply_it) { } c.after(:context, :apply_it) { } end end BenchmarkHelpers.run_benchmarks __END__ No match -- without singleton group support 575.250 (±29.0%) i/s - 2.484k No match -- with singleton group support 503.671 (±21.8%) i/s - 2.250k Example match -- without singleton group support 544.191 (±25.7%) i/s - 2.160k Example match -- with singleton group support 413.538 (±22.2%) i/s - 1.715k Group match -- without singleton group support 517.998 (±28.2%) i/s - 2.058k Group match -- with singleton group support 431.554 (±15.3%) i/s - 1.960k Both match -- without singleton group support 525.306 (±25.1%) i/s - 2.107k in 5.556760s Both match -- with singleton group support 440.288 (±16.6%) i/s - 1.848k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/helper.rb0000664000000000000000000001103014557677674027711 0ustar rootrootrequire_relative "../../bundle/bundler/setup" # configures load paths require 'rspec/core' require 'stackprof' class << RSpec attr_writer :world end RSpec::Core::Example.class_eval do alias_method :new_with_around_and_singleton_context_hooks, :with_around_and_singleton_context_hooks alias_method :old_with_around_and_singleton_context_hooks, :with_around_example_hooks end RSpec::Core::Hooks::HookCollections.class_eval do def old_register_global_singleton_context_hooks(*) # no-op: this method didn't exist before end alias_method :new_register_global_singleton_context_hooks, :register_global_singleton_context_hooks end RSpec::Core::Configuration.class_eval do def old_configure_example(*) # no-op: this method didn't exist before end alias_method :new_configure_example, :configure_example end RSpec.configure do |c| c.output_stream = StringIO.new end require 'benchmark/ips' class BenchmarkHelpers def self.prepare_implementation(prefix) RSpec.world = RSpec::Core::World.new # clear our state RSpec::Core::Example.__send__ :alias_method, :with_around_and_singleton_context_hooks, :"#{prefix}_with_around_and_singleton_context_hooks" RSpec::Core::Hooks::HookCollections.__send__ :alias_method, :register_global_singleton_context_hooks, :"#{prefix}_register_global_singleton_context_hooks" RSpec::Core::Configuration.__send__ :alias_method, :configure_example, :"#{prefix}_configure_example" end @@runner = RSpec::Core::Runner.new(RSpec::Core::ConfigurationOptions.new([])) def self.define_and_run_examples(desc, count, group_meta: {}, example_meta: {}) groups = count.times.map do |i| RSpec.describe "Group #{desc} #{i}", group_meta do 10.times { |j| example("ex #{j}", example_meta) { } } end end @@runner.run_specs(groups) end def self.profile(count, meta = { example_meta: { apply_it: true } }) [:new, :old].map do |prefix| prepare_implementation(prefix) results = StackProf.run(mode: :cpu) do define_and_run_examples("No match/#{prefix}", count, meta) end format_profile_results(results, prefix) end end def self.format_profile_results(results, prefix) File.open("tmp/#{prefix}_stack_prof_results.txt", "w") do |f| StackProf::Report.new(results).print_text(false, nil, f) end system "open tmp/#{prefix}_stack_prof_results.txt" File.open("tmp/#{prefix}_stack_prof_results.graphviz", "w") do |f| StackProf::Report.new(results).print_graphviz(nil, f) end system "dot tmp/#{prefix}_stack_prof_results.graphviz -Tpdf > tmp/#{prefix}_stack_prof_results.pdf" system "open tmp/#{prefix}_stack_prof_results.pdf" end def self.run_benchmarks Benchmark.ips do |x| implementations = { :old => "without", :new => "with" } # Historically, many of our benchmarks have initially been order-sensitive, # where whichever implementation went first got favored because defining # more groups (or whatever) would cause things to slow down. To easily # check if we're having those problems, you can pass REVERSE=1 to try # it out in the opposite order. implementations = implementations.to_a.reverse.to_h if ENV['REVERSE'] implementations.each do |prefix, description| x.report("No match -- #{description} singleton group support") do |times| prepare_implementation(prefix) define_and_run_examples("No match/#{description}", times) end end implementations.each do |prefix, description| x.report("Example match -- #{description} singleton group support") do |times| prepare_implementation(prefix) define_and_run_examples("Example match/#{description}", times, example_meta: { apply_it: true }) end end implementations.each do |prefix, description| x.report("Group match -- #{description} singleton group support") do |times| prepare_implementation(prefix) define_and_run_examples("Group match/#{description}", times, group_meta: { apply_it: true }) end end implementations.each do |prefix, description| x.report("Both match -- #{description} singleton group support") do |times| prepare_implementation(prefix) define_and_run_examples("Both match/#{description}", times, example_meta: { apply_it: true }, group_meta: { apply_it: true }) end end end end end ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_shared_context_inclusions.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_shared_context_in0000664000000000000000000000204514557677674032571 0ustar rootrootrequire_relative "helper" 1.upto(10) do |i| RSpec.shared_context "context #{i}", :apply_it do end end BenchmarkHelpers.run_benchmarks # BenchmarkHelpers.profile(1000) __END__ No match -- without singleton group support 563.304 (±29.6%) i/s - 2.385k No match -- with singleton group support 538.738 (±22.3%) i/s - 2.209k Example match -- without singleton group support 546.605 (±25.6%) i/s - 2.450k Example match -- with singleton group support 421.111 (±23.5%) i/s - 1.845k Group match -- without singleton group support 536.267 (±27.4%) i/s - 2.050k Group match -- with singleton group support 508.644 (±17.7%) i/s - 2.268k Both match -- without singleton group support 538.047 (±27.7%) i/s - 2.067k in 5.431649s Both match -- with singleton group support 505.388 (±26.7%) i/s - 1.880k in 5.578614s ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_module_inclusions.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_module_inclusions0000664000000000000000000000203014557677674032616 0ustar rootrootrequire_relative "helper" RSpec.configure do |c| 1.upto(10) do c.include Module.new, :apply_it end end BenchmarkHelpers.run_benchmarks __END__ No match -- without singleton group support 555.498 (±27.0%) i/s - 2.496k No match -- with singleton group support 529.826 (±23.0%) i/s - 2.397k in 5.402305s Example match -- without singleton group support 541.845 (±29.0%) i/s - 2.208k Example match -- with singleton group support 465.440 (±20.4%) i/s - 2.091k Group match -- without singleton group support 530.976 (±24.1%) i/s - 2.303k Group match -- with singleton group support 505.291 (±18.8%) i/s - 2.226k Both match -- without singleton group support 542.168 (±28.4%) i/s - 2.067k in 5.414905s Both match -- with singleton group support 503.226 (±27.2%) i/s - 1.880k in 5.621210s ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_no_config_hooks_or_inclusions.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/singleton_example_groups/with_no_config_hooks_o0000664000000000000000000000166314557677674032560 0ustar rootrootrequire_relative "helper" BenchmarkHelpers.run_benchmarks __END__ No match -- without singleton group support 565.198 (±28.8%) i/s - 2.438k No match -- with singleton group support 539.781 (±18.9%) i/s - 2.496k Example match -- without singleton group support 539.287 (±28.2%) i/s - 2.450k in 5.555471s Example match -- with singleton group support 511.576 (±28.1%) i/s - 2.058k Group match -- without singleton group support 535.298 (±23.2%) i/s - 2.352k Group match -- with singleton group support 539.454 (±19.1%) i/s - 2.350k Both match -- without singleton group support 550.932 (±32.1%) i/s - 2.145k in 5.930432s Both match -- with singleton group support 540.183 (±19.6%) i/s - 2.300k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/eager_vs_lazy_metadata.rb0000664000000000000000000001553414557677674026025 0ustar rootrootrequire 'benchmark' # preload rspec since we don't want to benchmark that. require 'rspec/core' require 'rspec/mocks' require 'rspec/expectations' def run_benchmark(description, *args) Benchmark.benchmark do |bm| 3.times.each do bm.report(description) do pid = fork do RSpec::Core::Runner.run([ # This file defines 16250 examples at various levels of nesting. "./benchmarks/eager_vs_lazy_metadata/define_examples.rb", *args ], StringIO.new, StringIO.new) exit! end # writeme.close Process.wait(pid) end end end end puts "#{RUBY_VERSION} - #{RSpec::Core::Metadata < Hash ? "lazy" : "eager"}" run_benchmark("progress formatter, all", "-fp") run_benchmark("documentation formatter, all", "-fd") run_benchmark("progress formatter, filtering by example", "-fp", "-e", "nested") run_benchmark("documentation formatter, filtering by example", "-fd", "-e", "nested") __END__ On 2.1, precomputing metadata appears to be about 15% faster. 2.1.0 - eager progress formatter, all 0.000000 0.000000 1.690000 ( 1.700527) progress formatter, all 0.000000 0.000000 1.710000 ( 1.712091) progress formatter, all 0.000000 0.000000 1.690000 ( 1.694437) documentation formatter, all 0.000000 0.000000 1.740000 ( 1.752185) documentation formatter, all 0.000000 0.000000 1.740000 ( 1.743691) documentation formatter, all 0.000000 0.010000 1.760000 ( 1.752427) progress formatter, filtering by example 0.000000 0.000000 1.710000 ( 1.712782) progress formatter, filtering by example 0.000000 0.000000 1.690000 ( 1.695519) progress formatter, filtering by example 0.000000 0.000000 1.680000 ( 1.688278) documentation formatter, filtering by example 0.000000 0.000000 1.740000 ( 1.734581) documentation formatter, filtering by example 0.000000 0.000000 1.720000 ( 1.730275) documentation formatter, filtering by example 0.000000 0.000000 1.730000 ( 1.729879) 2.1.0 - lazy progress formatter, all 0.000000 0.010000 2.020000 ( 2.021899) progress formatter, all 0.000000 0.000000 2.010000 ( 2.013904) progress formatter, all 0.000000 0.000000 1.990000 ( 2.004857) documentation formatter, all 0.000000 0.000000 2.120000 ( 2.119586) documentation formatter, all 0.000000 0.000000 2.120000 ( 2.122598) documentation formatter, all 0.000000 0.000000 2.110000 ( 2.115573) progress formatter, filtering by example 0.000000 0.000000 2.080000 ( 2.081120) progress formatter, filtering by example 0.000000 0.000000 2.050000 ( 2.066418) progress formatter, filtering by example 0.000000 0.000000 2.090000 ( 2.085655) documentation formatter, filtering by example 0.000000 0.010000 2.160000 ( 2.166207) documentation formatter, filtering by example 0.000000 0.000000 2.200000 ( 2.196856) documentation formatter, filtering by example 0.000000 0.000000 2.170000 ( 2.172799) On 2.0, precomputing metadata appears to be about 20% faster. 2.0.0 - eager progress formatter, all 0.000000 0.000000 1.720000 ( 1.730478) progress formatter, all 0.000000 0.000000 1.710000 ( 1.708679) progress formatter, all 0.000000 0.000000 1.750000 ( 1.753906) documentation formatter, all 0.000000 0.000000 1.790000 ( 1.804745) documentation formatter, all 0.010000 0.010000 1.830000 ( 1.805737) documentation formatter, all 0.000000 0.000000 1.780000 ( 1.802866) progress formatter, filtering by example 0.000000 0.000000 1.720000 ( 1.714562) progress formatter, filtering by example 0.000000 0.000000 1.660000 ( 1.663136) progress formatter, filtering by example 0.000000 0.000000 1.710000 ( 1.716405) documentation formatter, filtering by example 0.000000 0.000000 1.760000 ( 1.756188) documentation formatter, filtering by example 0.000000 0.000000 1.760000 ( 1.779646) documentation formatter, filtering by example 0.000000 0.010000 1.780000 ( 1.766562) 2.0.0 - lazy progress formatter, all 0.000000 0.000000 2.140000 ( 2.144684) progress formatter, all 0.000000 0.000000 2.140000 ( 2.152171) progress formatter, all 0.000000 0.000000 2.150000 ( 2.156945) documentation formatter, all 0.000000 0.000000 2.270000 ( 2.276520) documentation formatter, all 0.000000 0.000000 2.270000 ( 2.271053) documentation formatter, all 0.000000 0.000000 2.280000 ( 2.274769) progress formatter, filtering by example 0.000000 0.000000 2.210000 ( 2.222937) progress formatter, filtering by example 0.000000 0.000000 2.190000 ( 2.195851) progress formatter, filtering by example 0.000000 0.000000 2.240000 ( 2.251092) documentation formatter, filtering by example 0.000000 0.010000 2.380000 ( 2.368707) documentation formatter, filtering by example 0.000000 0.000000 2.390000 ( 2.405561) documentation formatter, filtering by example 0.000000 0.000000 2.430000 ( 2.422848) On 1.9.3 it appears to be a wash. 1.9.3 - eager progress formatter, all 0.000000 0.000000 1.860000 ( 1.862991) progress formatter, all 0.000000 0.000000 1.930000 ( 1.940352) progress formatter, all 0.000000 0.010000 1.860000 ( 1.854856) documentation formatter, all 0.000000 0.000000 1.900000 ( 1.912110) documentation formatter, all 0.000000 0.000000 2.000000 ( 1.998096) documentation formatter, all 0.000000 0.000000 1.910000 ( 1.914563) progress formatter, filtering by example 0.000000 0.000000 1.800000 ( 1.800767) progress formatter, filtering by example 0.000000 0.000000 1.900000 ( 1.918205) progress formatter, filtering by example 0.000000 0.000000 1.830000 ( 1.824907) documentation formatter, filtering by example 0.000000 0.000000 1.850000 ( 1.855187) documentation formatter, filtering by example 0.000000 0.000000 1.940000 ( 1.945985) documentation formatter, filtering by example 0.000000 0.010000 1.880000 ( 1.879237) 1.9.3 - lazy progress formatter, all 0.000000 0.000000 1.950000 ( 1.953861) progress formatter, all 0.000000 0.000000 1.840000 ( 1.848092) progress formatter, all 0.000000 0.000000 1.920000 ( 1.930265) documentation formatter, all 0.000000 0.000000 1.920000 ( 1.922012) documentation formatter, all 0.000000 0.000000 2.010000 ( 2.012511) documentation formatter, all 0.000000 0.000000 1.920000 ( 1.921090) progress formatter, filtering by example 0.000000 0.010000 1.990000 ( 1.986591) progress formatter, filtering by example 0.000000 0.000000 1.990000 ( 1.986991) progress formatter, filtering by example 0.000000 0.000000 1.990000 ( 1.991256) documentation formatter, filtering by example 0.000000 0.000000 2.070000 ( 2.080637) documentation formatter, filtering by example 0.000000 0.000000 2.030000 ( 2.041768) documentation formatter, filtering by example 0.000000 0.000000 1.970000 ( 1.974151) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/eager_vs_lazy_metadata/0000775000000000000000000000000014557677674025470 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/eager_vs_lazy_metadata/define_examples.rb0000664000000000000000000000066214557677674031151 0ustar rootroottop_level_example_groups = 25 examples = 25 nested_groups = 25 nested_examples = 25 top_level_example_groups.times do |tlg| RSpec.describe "Top level group #{tlg}", :foo => 3 do examples.times do |e| it("example #{e}", :bar => 4) { } end nested_groups.times do |ng| context "nested #{ng}" do nested_examples.times do |ne| it("example #{ne}") { } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/index_v_take_while.rb0000664000000000000000000000152614557677674025157 0ustar rootrootrequire 'benchmark' n = 10000 list = 1.upto(10).to_a Benchmark.benchmark do |bm| puts "take_while" 3.times do bm.report do n.times do list. take_while {|i| i < 6}. map {|i| i}. compact end end end puts puts "list[0,n]" 3.times do bm.report do n.times do if index = list.index(6) list[0, index].map {|i| i.to_s} else list.map {|i| i}.compact end end end end end __END__ ruby benchmarks/index_v_take_while.rb take_while 0.020000 0.000000 0.020000 ( 0.020005) 0.010000 0.000000 0.010000 ( 0.015907) 0.010000 0.000000 0.010000 ( 0.015962) list[0,n] 0.020000 0.000000 0.020000 ( 0.023561) 0.020000 0.000000 0.020000 ( 0.018812) 0.030000 0.000000 0.030000 ( 0.022389) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/call_v_yield.rb0000664000000000000000000000245114557677674023753 0ustar rootrootrequire 'benchmark' n = 100_000 def call_block(&block) block.call end def yield_control yield end Benchmark.benchmark do |bm| puts "#{n} times - ruby #{RUBY_VERSION}" puts puts "eval" 3.times do bm.report do n.times do eval("2 + 3") end end end puts puts "call block" 3.times do bm.report do n.times do call_block { 2 + 3 } end end end puts puts "yield" 3.times do bm.report do n.times do yield_control { 2 + 3 } end end end puts puts "exec" 3.times do bm.report do n.times do 2 + 3 end end end end # 100000 times - ruby 1.9.3 # # eval # 0.870000 0.010000 0.880000 ( 0.877762) # 0.890000 0.000000 0.890000 ( 0.891142) # 0.890000 0.000000 0.890000 ( 0.896365) # # call block # 0.120000 0.010000 0.130000 ( 0.136322) # 0.130000 0.010000 0.140000 ( 0.138608) # 0.130000 0.000000 0.130000 ( 0.129931) # # yield # 0.020000 0.000000 0.020000 ( 0.020412) # 0.010000 0.000000 0.010000 ( 0.017926) # 0.020000 0.000000 0.020000 ( 0.025740) # # exec # 0.010000 0.000000 0.010000 ( 0.009935) # 0.010000 0.000000 0.010000 ( 0.011588) # 0.010000 0.000000 0.010000 ( 0.010613) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/0000775000000000000000000000000014557677674023306 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/running_1_group_1000_examples.rb0000664000000000000000000001042614557677674031310 0ustar rootrootrequire_relative "helper" RSpec.describe "one example group" do 1000.times do |i| example "example #{i}" do end end end benchmark_allocations(burn: 0) do RSpec::Core::Runner.run([]) end __END__ Original allocations: class_plus count ----------------------------------------------------------------------------------------------- ----- String 35018 Array 14030 Array 12075 RSpec::Core::Hooks::HookCollection 4000 Time 2002 Array 2000 RSpec::Core::Hooks::AroundHookCollection 2000 RSpec::Core::Notifications::ExampleNotification 2000 Proc 1065 RubyVM::Env 1018 Array 1006 Array 1005 RSpec::ExampleGroups::OneExampleGroup 1002 Array 67 RubyVM::InstructionSequence 41 Hash 35 Set 30 File 6 After my change: class_plus count ----------------------------------------------------------------------------------------------- ----- Array 14030 String 12967 Array 12075 RSpec::Core::Hooks::HookCollection 4000 Time 2002 RSpec::Core::Notifications::ExampleNotification 2000 Array 2000 RSpec::Core::Hooks::AroundHookCollection 2000 Proc 1065 RubyVM::Env 1018 Array 1006 Array 1005 RSpec::ExampleGroups::OneExampleGroup 1002 Array 67 RubyVM::InstructionSequence 41 Hash 35 Set 30 File 6 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/1_group_1000_examples.rb0000664000000000000000000000451314557677674027550 0ustar rootrootrequire_relative "helper" benchmark_allocations do RSpec.describe "one example group" do 1000.times do |i| example "example #{i}" do end end end end __END__ Original stats: class_plus count ---------------------------------------- ----- String 22046 Hash 3006 Array 3002 Proc 2007 RubyVM::Env 2007 Array 1013 Regexp 1001 RSpec::Core::Example::ExecutionResult 1001 Array 1001 RSpec::Core::Example 1000 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Hooks::HookCollection 6 MatchData 4 Array 2 Module 2 RSpec::Core::Metadata::ExampleGroupHash 1 RSpec::Core::Hooks::AroundHookCollection 1 Class 1 Array 1 RSpec::Core::Hooks::HookCollections 1 Array 1 After my fixes: class_plus count ---------------------------------------- ----- String 6030 Hash 3006 Array 3002 RubyVM::Env 2007 Proc 2007 Array 1013 RSpec::Core::Example::ExecutionResult 1001 Array 1001 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Example 1000 RSpec::Core::Hooks::HookCollection 6 MatchData 4 Module 2 Array 2 RSpec::Core::Hooks::HookCollections 1 Array 1 RSpec::Core::Hooks::AroundHookCollection 1 RSpec::Core::Metadata::ExampleGroupHash 1 Class 1 Array 1 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/helper.rb0000664000000000000000000000165014557677674025114 0ustar rootroot$LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__) require 'rspec/core' require 'allocation_stats' def benchmark_allocations(burn: 1, min_allocations: 0) stats = AllocationStats.new(burn: burn).trace do yield end columns = if ENV['DETAIL'] [:sourcefile, :sourceline, :class_plus] else [:class_plus] end results = stats.allocations(alias_paths: true).group_by(*columns).from_pwd.sort_by_size.to_text count_regex = /\s+(\d+)\z/ total_objects = results.split("\n").map { |line| line[count_regex, 1] }.compact.map { |c| Integer(c) }.inject(0, :+) filtered = results.split("\n").select do |line| count = line[count_regex, 1] count.nil? || Integer(count) >= min_allocations end puts filtered.join("\n") line_length = filtered.last.length puts "-" * line_length puts "Total:#{total_objects.to_s.rjust(line_length - "Total:".length)}" end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/1000_groups_1_example.rb0000664000000000000000000001116214557677674027546 0ustar rootrootrequire_relative "helper" benchmark_allocations do 1000.times do |i| RSpec.describe "group #{i}" do it "has one example" do end end end end __END__ Original allocations: class_plus count ---------------------------------------- ----- String 28000 Array 15000 RubyVM::Env 9000 Proc 9000 Hash 9000 RSpec::Core::Hooks::HookCollection 6000 Array 5000 MatchData 3000 Array 2000 Array 2000 Module 2000 RSpec::Core::Example::ExecutionResult 2000 RSpec::Core::Metadata::ExampleGroupHash 1000 Class 1000 Array 1000 RSpec::Core::Hooks::AroundHookCollection 1000 RSpec::Core::Hooks::HookCollections 1000 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Example 1000 Array 1000 After removing `:suite` support from `Hooks` module, it cut Array and RSpec::Core::Hooks::HookCollection allocations by 2000 each: class_plus count ---------------------------------------- ----- String 28000 Array 13000 Proc 9000 RubyVM::Env 9000 Hash 9000 Array 5000 RSpec::Core::Hooks::HookCollection 4000 MatchData 3000 Array 2000 RSpec::Core::Example::ExecutionResult 2000 Module 2000 Array 2000 RSpec::Core::Hooks::HookCollections 1000 RSpec::Core::Example 1000 Array 1000 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Hooks::AroundHookCollection 1000 RSpec::Core::Metadata::ExampleGroupHash 1000 Class 1000 Array 1000 .... Later, our allocations were: class_plus count --------------------------------------- ----- String 26000 Hash 19000 Array 18000 Set 10000 Proc 9000 RubyVM::Env 9000 RSpec::Core::Hooks::HookCollection 5000 RSpec::Core::FilterableItemRepository 5000 Array 5000 MatchData 3000 RSpec::Core::Example::ExecutionResult 2000 Array 2000 Module 2000 Array 2000 RSpec::Core::Metadata::ExampleGroupHash 1000 Class 1000 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Example 1000 Array 1000 Array 1000 RSpec::Core::Hooks::HookCollections 1000 After changing the hooks implementation to lazily instantiate `HookCollection` instances, it dropped our allocations by: - 8K hashes - 10K arrays - 10K sets - 5K FilterableItemRepository - 5K HookCollection class_plus count --------------------------------------- ----- String 26000 Hash 11000 Array 8000 Proc 5000 RubyVM::Env 5000 Array 5000 MatchData 3000 Array 2000 Array 2000 RSpec::Core::Example::ExecutionResult 2000 Module 2000 Array 1000 RSpec::Core::Metadata::ExampleGroupHash 1000 Class 1000 RSpec::Core::Metadata::ExampleHash 1000 RSpec::Core::Example 1000 Array 1000 RSpec::Core::Hooks::HookCollections 1000 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/allocations/running_1000_groups_1_example.rb0000664000000000000000000001775714557677674031326 0ustar rootrootrequire_relative "helper" 1000.times do |i| RSpec.describe "group #{i}" do it "has one example" do end end end benchmark_allocations(burn: 0, min_allocations: 50) do RSpec::Core::Runner.run([]) end __END__ Before optimization: class_plus count ----------------------------------------------------------------------------------------------- ----- Array 26021 String 21331 Array 19402 Array 6001 Array 6001 RSpec::Core::Hooks::HookCollection 4004 Array 4004 Hash 3098 Proc 3096 RubyVM::Env 3056 Time 2002 Random 2001 RSpec::Core::Hooks::AroundHookCollection 2000 RSpec::Core::Notifications::GroupNotification 2000 RSpec::Core::Notifications::ExampleNotification 2000 RSpec::Core::Hooks::GroupHookCollection 2000 Array 1003 Array 1002 Array 1002 RSpec::Core::Example::Procsy 1000 RubyVM::InstructionSequence 506 Array 391 Array 205 Array 52 After optimization, we allocate 2000 less arrays and 2000 less RSpec::Core::Hooks::HookCollection instances. That's 2 less of each per example group. class_plus count ----------------------------------------------------------------------------------------------- ----- Array 26021 String 21331 Array 17400 Array 6001 Array 6001 Array 4004 Hash 3098 Proc 3096 RubyVM::Env 3056 RSpec::Core::Hooks::HookCollection 2002 Time 2002 Random 2001 RSpec::Core::Notifications::ExampleNotification 2000 RSpec::Core::Notifications::GroupNotification 2000 RSpec::Core::Hooks::GroupHookCollection 2000 Array 1003 Array 1002 Array 1002 RSpec::Core::Example::Procsy 1000 RSpec::Core::Hooks::AroundHookCollection 1000 RubyVM::InstructionSequence 506 Array 391 Array 205 Array 52 After yet further optimization (where HookCollection instances are only created when hooks are added), we've reduced allocations significantly further: class_plus count ----------------------------------------------------------------------------------------------- ----- String 21332 Array 13412 Array 6021 Array 6001 Array 6001 Hash 3105 Array 3004 Proc 2101 RubyVM::Env 2061 Time 2002 Random 2001 RSpec::Core::Notifications::GroupNotification 2000 RSpec::Core::Notifications::ExampleNotification 2000 Array 1003 Array 1002 Array 1002 RubyVM::InstructionSequence 506 Array 391 Array 208 Array 52 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/boot_time_with_many_load_path_dirs.sh0000775000000000000000000000507014557677674030433 0ustar rootrootruby -v function run_benchmark_with_load_path_size { pushd tmp mkdir -p boot_time_benchmark local load_path_size=$1 for (( i=0; i < $load_path_size; i++ )); do mkdir -p "boot_time_benchmark/dir_$i" done local load_path=`ruby -e 'puts Array.new(Integer(ARGV.first)) { |i| "boot_time_benchmark/dir_#{i}" }.join(":")' $load_path_size` echo "3 runs with $load_path_size dirs on load path, booting 50 times, using $2" for i in {1..3}; do time (for i in {1..50}; do ruby -I$load_path:../lib:../../rspec-support/lib -e 'require "rspec/core"'; done) done popd } run_benchmark_with_load_path_size 10 "require" run_benchmark_with_load_path_size 100 "require" run_benchmark_with_load_path_size 1000 "require" export REQUIRE_RELATIVE=1 run_benchmark_with_load_path_size 10 "require_relative" run_benchmark_with_load_path_size 100 "require_relative" run_benchmark_with_load_path_size 1000 "require_relative" : <<'result_comment' ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0] ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 10 dirs on load path, booting 50 times, using require real 0m3.815s user 0m3.205s sys 0m0.519s real 0m3.850s user 0m3.234s sys 0m0.527s real 0m3.840s user 0m3.225s sys 0m0.525s ~/code/rspec-core ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 100 dirs on load path, booting 50 times, using require real 0m5.086s user 0m3.887s sys 0m1.107s real 0m5.063s user 0m3.870s sys 0m1.098s real 0m5.061s user 0m3.871s sys 0m1.097s ~/code/rspec-core ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 1000 dirs on load path, booting 50 times, using require real 0m18.850s user 0m11.057s sys 0m7.679s real 0m18.783s user 0m11.012s sys 0m7.657s real 0m18.747s user 0m10.992s sys 0m7.639s ~/code/rspec-core ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 10 dirs on load path, booting 50 times, using require_relative real 0m3.794s user 0m3.200s sys 0m0.506s real 0m3.769s user 0m3.180s sys 0m0.502s real 0m3.787s user 0m3.192s sys 0m0.502s ~/code/rspec-core ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 100 dirs on load path, booting 50 times, using require_relative real 0m4.626s user 0m3.620s sys 0m0.910s real 0m4.652s user 0m3.642s sys 0m0.915s real 0m4.678s user 0m3.662s sys 0m0.924s ~/code/rspec-core ~/code/rspec-core/tmp ~/code/rspec-core 3 runs with 1000 dirs on load path, booting 50 times, using require_relative real 0m14.400s user 0m8.615s sys 0m5.675s real 0m14.495s user 0m8.672s sys 0m5.711s real 0m14.541s user 0m8.705s sys 0m5.727s ~/code/rspec-core result_comment ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/map_then_flatten_vs_flat_map_benchmarks.rb0000664000000000000000000000353614557677674031412 0ustar rootrootrequire 'benchmark' $n = 10000 size = 100 puts "size: #{size}" puts def report reals = [] Benchmark.benchmark do |bm| 3.times do reals << bm.report { $n.times { yield } }.real end end reals.inject(&:+) / reals.count end avgs = [] puts "map then flatten" avgs << report { (1..size). map {|n| [n]}. flatten } puts puts "flat_map" avgs << report { (1..size). flat_map {|n| [n]} } puts avgs if avgs[0] < avgs[1] puts "map then flatten faster by #{((1.0 - avgs[0]/avgs[1]) * 100).round(2)} %" else puts "flat_map faster by #{((1.0 - avgs[1]/avgs[0]) * 100).round(2)} %" end __END__ for each size (10, 100, 1000) showing smallest diff between map-then-flatten and flat_map in at least 5 runs size: 10 map then flatten 0.550000 0.000000 0.550000 ( 0.547897) 0.570000 0.000000 0.570000 ( 0.565139) 0.550000 0.000000 0.550000 ( 0.557421) flat_map 0.320000 0.000000 0.320000 ( 0.316801) 0.320000 0.010000 0.330000 ( 0.325373) 0.330000 0.000000 0.330000 ( 0.325169) flat_map faster by 42.09 % ********************************************** size: 100 map then flatten 0.390000 0.000000 0.390000 ( 0.387307) 0.390000 0.000000 0.390000 ( 0.387630) 0.380000 0.000000 0.380000 ( 0.389421) flat_map 0.250000 0.000000 0.250000 ( 0.259444) 0.270000 0.000000 0.270000 ( 0.261972) 0.250000 0.000000 0.250000 ( 0.252584) flat_map faster by 33.53 % ********************************************** size: 1000 map then flatten 0.380000 0.000000 0.380000 ( 0.382788) 0.380000 0.000000 0.380000 ( 0.372447) 0.370000 0.000000 0.370000 ( 0.370065) flat_map 0.240000 0.000000 0.240000 ( 0.240357) 0.240000 0.000000 0.240000 ( 0.242325) 0.240000 0.000000 0.240000 ( 0.240985) flat_map faster by 35.69 % ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/several_regexps_v_one_big_one.rb0000664000000000000000000000327214557677674027375 0ustar rootrootrequire 'benchmark' $t = 3 $n = 100000 def report(header) puts header reals = [] Benchmark.bm do |bm| $t.times do reals << bm.report { $n.times { yield } }.real end end [header, (reals.inject(&:+) / reals.count).round(5)] end multi = [ /\/lib\d*\/ruby\//, /org\/jruby\//, /bin\//, %r|/gems/|, /lib\/rspec\/(core|expectations|matchers|mocks)/ ] union = [Regexp.union(multi)] avgs = [] avgs << report("multi w/ match") { multi.any? {|e| e =~ "lib/rspec/core"} } avgs << report("union w/ match") { union.any? {|e| e =~ "lib/rspec/core"} } avgs << report("multi w/ no match") { multi.any? {|e| e =~ "foo/bar"} } avgs << report("union w/ no match") { union.any? {|e| e =~ "foo/bar"} } puts avgs.each do |header, val| puts header, val puts end __END__ multi w/ match user system total real 0.400000 0.000000 0.400000 ( 0.405063) 0.410000 0.000000 0.410000 ( 0.402778) 0.430000 0.000000 0.430000 ( 0.435447) union w/ match user system total real 0.130000 0.000000 0.130000 ( 0.127526) 0.130000 0.000000 0.130000 ( 0.135529) 0.130000 0.000000 0.130000 ( 0.127866) multi w/ no match user system total real 0.320000 0.000000 0.320000 ( 0.318921) 0.330000 0.000000 0.330000 ( 0.328375) 0.340000 0.000000 0.340000 ( 0.341230) union w/ no match user system total real 0.170000 0.000000 0.170000 ( 0.175144) 0.170000 0.000000 0.170000 ( 0.168816) 0.170000 0.000000 0.170000 ( 0.168362) multi w/ match 0.41443 union w/ match 0.13031 multi w/ no match 0.32951 union w/ no match 0.17077 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/README.md0000664000000000000000000000014614557677674022256 0ustar rootroot## Benchmarks This directory contains various benchmarks we used to inform implementation decisions. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/threadsafe_let_block.rb0000664000000000000000000002437614557677674025463 0ustar rootrootrequire 'rspec/core' require 'rspec/expectations' # switches between these implementations - https://github.com/rspec/rspec-core/pull/1858/files # benchmark requested in this PR - https://github.com/rspec/rspec-core/pull/1858 # # I ran these from lib root by adding "gem 'benchmark-ips'" to ../Gemfile-custom # then ran `bundle install --standalone --binstubs bundle/bin` # then ran `ruby --disable-gems -I lib -I "$PWD/bundle" -r bundler/setup -S benchmarks/threadsafe_let_block.rb` # The old, non-thread safe implementation, imported from the `main` branch and pared down. module OriginalNonThreadSafeMemoizedHelpers def __memoized @__memoized ||= {} end module ClassMethods def let(name, &block) # We have to pass the block directly to `define_method` to # allow it to use method constructs like `super` and `return`. raise "#let or #subject called without a block" if block.nil? OriginalNonThreadSafeMemoizedHelpers.module_for(self).__send__(:define_method, name, &block) # Apply the memoization. The method has been defined in an ancestor # module so we can use `super` here to get the value. if block.arity == 1 define_method(name) { __memoized.fetch(name) { |k| __memoized[k] = super(RSpec.current_example, &nil) } } else define_method(name) { __memoized.fetch(name) { |k| __memoized[k] = super(&nil) } } end end end def self.module_for(example_group) get_constant_or_yield(example_group, :LetDefinitions) do mod = Module.new do include Module.new { example_group.const_set(:NamedSubjectPreventSuper, self) } end example_group.const_set(:LetDefinitions, mod) mod end end # @private def self.define_helpers_on(example_group) example_group.__send__(:include, module_for(example_group)) end def self.get_constant_or_yield(example_group, name) if example_group.const_defined?(name, (check_ancestors = false)) example_group.const_get(name, check_ancestors) else yield end end end class HostBase # wires the implementation # adds `let(:name) { nil }` # returns `Class.new(self) { let(:name) { super() } }` def self.prepare_using(memoized_helpers, options={}) include memoized_helpers extend memoized_helpers::ClassMethods memoized_helpers.define_helpers_on(self) define_method(:initialize, &options[:initialize]) if options[:initialize] let(:name) { nil } verify_memoizes memoized_helpers, options[:verify] Class.new(self) do memoized_helpers.define_helpers_on(self) let(:name) { super() } end end def self.verify_memoizes(memoized_helpers, additional_verification) # Since we're using custom code, ensure it actually memoizes as we expect... counter_class = Class.new(self) do include RSpec::Matchers memoized_helpers.define_helpers_on(self) counter = 0 let(:count) { counter += 1 } end extend RSpec::Matchers instance_1 = counter_class.new expect(instance_1.count).to eq(1) expect(instance_1.count).to eq(1) instance_2 = counter_class.new expect(instance_2.count).to eq(2) expect(instance_2.count).to eq(2) instance_3 = counter_class.new instance_3.instance_eval &additional_verification if additional_verification end end class OriginalNonThreadSafeHost < HostBase Subclass = prepare_using OriginalNonThreadSafeMemoizedHelpers end class ThreadSafeHost < HostBase Subclass = prepare_using RSpec::Core::MemoizedHelpers, :initialize => lambda { |*| @__memoized = ThreadsafeMemoized.new }, :verify => lambda { |*| expect(__memoized).to be_a_kind_of RSpec::Core::MemoizedHelpers::ThreadsafeMemoized } end class ConfigNonThreadSafeHost < HostBase Subclass = prepare_using RSpec::Core::MemoizedHelpers, :initialize => lambda { |*| @__memoized = NonThreadSafeMemoized.new }, :verify => lambda { |*| expect(__memoized).to be_a_kind_of RSpec::Core::MemoizedHelpers::NonThreadSafeMemoized } end def title(title) hr = "#" * (title.length + 6) blank = "# #{' ' * title.length} #" [hr, blank, "# #{title} #", blank, hr] end require 'benchmark/ips' puts title "versions" puts "RUBY_VERSION #{RUBY_VERSION}" puts "RUBY_PLATFORM #{RUBY_PLATFORM}" puts "RUBY_ENGINE #{RUBY_ENGINE}" puts "ruby -v #{`ruby -v`}" puts "Benchmark::IPS::VERSION #{Benchmark::IPS::VERSION}" puts "rspec-core SHA #{`git log --pretty=format:%H -1`}" puts puts title "1 call to let -- each sets the value" Benchmark.ips do |x| x.report("non-threadsafe (original)") { OriginalNonThreadSafeHost.new.name } x.report("non-threadsafe (config) ") { ConfigNonThreadSafeHost.new.name } x.report("threadsafe ") { ThreadSafeHost.new.name } x.compare! end puts title "10 calls to let -- 9 will find memoized value" Benchmark.ips do |x| x.report("non-threadsafe (original)") do i = OriginalNonThreadSafeHost.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.report("non-threadsafe (config) ") do i = ConfigNonThreadSafeHost.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.report("threadsafe ") do i = ThreadSafeHost.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.compare! end puts title "1 call to let which invokes super" Benchmark.ips do |x| x.report("non-threadsafe (original)") { OriginalNonThreadSafeHost::Subclass.new.name } x.report("non-threadsafe (config) ") { ConfigNonThreadSafeHost::Subclass.new.name } x.report("threadsafe ") { ThreadSafeHost::Subclass.new.name } x.compare! end puts title "10 calls to let which invokes super" Benchmark.ips do |x| x.report("non-threadsafe (original)") do i = OriginalNonThreadSafeHost::Subclass.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.report("non-threadsafe (config) ") do i = ConfigNonThreadSafeHost::Subclass.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.report("threadsafe ") do i = ThreadSafeHost::Subclass.new i.name; i.name; i.name; i.name; i.name i.name; i.name; i.name; i.name; i.name end x.compare! end __END__ ############## # # # versions # # # ############## RUBY_VERSION 2.2.0 RUBY_PLATFORM x86_64-darwin13 RUBY_ENGINE ruby ruby -v ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13] Benchmark::IPS::VERSION 2.1.1 rspec-core SHA 1ee7a8d8cde6ba2dd13d35e90e824e8e5ba7db76 ########################################## # # # 1 call to let -- each sets the value # # # ########################################## Calculating ------------------------------------- non-threadsafe (original) 53.722k i/100ms non-threadsafe (config) 44.998k i/100ms threadsafe 26.123k i/100ms ------------------------------------------------- non-threadsafe (original) 830.988k (± 6.3%) i/s - 4.190M non-threadsafe (config) 665.662k (± 6.7%) i/s - 3.330M threadsafe 323.575k (± 5.6%) i/s - 1.620M Comparison: non-threadsafe (original): 830988.5 i/s non-threadsafe (config) : 665661.9 i/s - 1.25x slower threadsafe : 323574.9 i/s - 2.57x slower ################################################### # # # 10 calls to let -- 9 will find memoized value # # # ################################################### Calculating ------------------------------------- non-threadsafe (original) 28.724k i/100ms non-threadsafe (config) 25.357k i/100ms threadsafe 18.349k i/100ms ------------------------------------------------- non-threadsafe (original) 346.302k (± 6.1%) i/s - 1.752M non-threadsafe (config) 309.970k (± 5.4%) i/s - 1.547M threadsafe 208.946k (± 5.2%) i/s - 1.046M Comparison: non-threadsafe (original): 346302.0 i/s non-threadsafe (config) : 309970.2 i/s - 1.12x slower threadsafe : 208946.3 i/s - 1.66x slower ####################################### # # # 1 call to let which invokes super # # # ####################################### Calculating ------------------------------------- non-threadsafe (original) 42.458k i/100ms non-threadsafe (config) 37.367k i/100ms threadsafe 21.088k i/100ms ------------------------------------------------- non-threadsafe (original) 591.906k (± 6.3%) i/s - 2.972M non-threadsafe (config) 511.295k (± 4.7%) i/s - 2.578M threadsafe 246.080k (± 5.8%) i/s - 1.244M Comparison: non-threadsafe (original): 591906.3 i/s non-threadsafe (config) : 511295.0 i/s - 1.16x slower threadsafe : 246079.6 i/s - 2.41x slower ######################################### # # # 10 calls to let which invokes super # # # ######################################### Calculating ------------------------------------- non-threadsafe (original) 24.282k i/100ms non-threadsafe (config) 22.762k i/100ms threadsafe 14.685k i/100ms ------------------------------------------------- non-threadsafe (original) 297.423k (± 5.0%) i/s - 1.505M non-threadsafe (config) 264.046k (± 5.6%) i/s - 1.320M threadsafe 170.853k (± 4.7%) i/s - 866.415k Comparison: non-threadsafe (original): 297422.6 i/s non-threadsafe (config) : 264045.8 i/s - 1.13x slower threadsafe : 170853.1 i/s - 1.74x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/check_inclusion.rb0000664000000000000000000000705714557677674024474 0ustar rootrootrequire 'benchmark' n = 10_000 num_modules = 1000 class Foo; end modules = num_modules.times.map { Module.new } modules.each {|m| Foo.send(:include, m) } Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Foo < modules.first end end end end Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Foo < modules.last end end end end Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Foo.included_modules.include?(modules.first) end end end end Benchmark.benchmark do |bm| 3.times do bm.report do n.times do Foo.included_modules.include?(modules.last) end end end end #### Ruby 1.9.3 # # 100 modules # < modules.first # 0.010000 0.000000 0.010000 ( 0.005104) # 0.000000 0.000000 0.000000 ( 0.005114) # 0.010000 0.000000 0.010000 ( 0.005076) # < modules.last # 0.000000 0.000000 0.000000 ( 0.002180) # 0.000000 0.000000 0.000000 ( 0.002199) # 0.000000 0.000000 0.000000 ( 0.002189) # < included_modules.include?(modules.first) # 0.110000 0.010000 0.120000 ( 0.110062) # 0.100000 0.000000 0.100000 ( 0.105343) # 0.100000 0.000000 0.100000 ( 0.102770) # < included_modules.include?(modules.last) # 0.050000 0.010000 0.060000 ( 0.048520) # 0.040000 0.000000 0.040000 ( 0.049013) # 0.050000 0.000000 0.050000 ( 0.050668) # 1000 modules # < modules.first # 0.080000 0.000000 0.080000 ( 0.079460) # 0.080000 0.000000 0.080000 ( 0.078765) # 0.080000 0.000000 0.080000 ( 0.079560) # < modules.last # 0.000000 0.000000 0.000000 ( 0.002195) # 0.000000 0.000000 0.000000 ( 0.002201) # 0.000000 0.000000 0.000000 ( 0.002199) # < included_modules.include?(modules.first) # 0.860000 0.010000 0.870000 ( 0.887684) # 0.870000 0.000000 0.870000 ( 0.875158) # 0.870000 0.000000 0.870000 ( 0.879216) # < included_modules.include?(modules.last) # 0.340000 0.000000 0.340000 ( 0.344011) # 0.350000 0.000000 0.350000 ( 0.346277) # 0.330000 0.000000 0.330000 ( 0.335607) #### Ruby 1.8.7 # # 100 modules # < modules.first # 0.010000 0.000000 0.010000 ( 0.007132) # 0.010000 0.000000 0.010000 ( 0.006869) # 0.000000 0.000000 0.000000 ( 0.005334) # < modules.last # 0.010000 0.000000 0.010000 ( 0.003438) # 0.000000 0.000000 0.000000 ( 0.003454) # 0.000000 0.000000 0.000000 ( 0.003408) # < included_modules.include?(modules.first) # 0.110000 0.010000 0.120000 ( 0.113255) # 0.110000 0.000000 0.110000 ( 0.112880) # 0.110000 0.000000 0.110000 ( 0.121003) # < included_modules.include?(modules.last) # 0.040000 0.010000 0.050000 ( 0.040736) # 0.040000 0.000000 0.040000 ( 0.039609) # 0.030000 0.000000 0.030000 ( 0.039888) # 1000 modules # < modules.first # 0.040000 0.000000 0.040000 ( 0.044124) # 0.050000 0.000000 0.050000 ( 0.046110) # 0.040000 0.000000 0.040000 ( 0.042603) # < modules.last # 0.000000 0.000000 0.000000 ( 0.003405) # 0.010000 0.000000 0.010000 ( 0.005510) # 0.000000 0.000000 0.000000 ( 0.003562) # < included_modules.include?(modules.first) # 0.990000 0.000000 0.990000 ( 1.096331) # 1.030000 0.010000 1.040000 ( 1.047791) # 0.990000 0.000000 0.990000 ( 1.019169) # < included_modules.include?(modules.last) # 0.260000 0.000000 0.260000 ( 0.265306) # 0.270000 0.000000 0.270000 ( 0.311985) # 0.270000 0.000000 0.270000 ( 0.277936) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/filter_object.rb0000664000000000000000000000104014557677674024131 0ustar rootrootrequire 'benchmark' require 'tmpdir' path = File.join(Dir.tmpdir, "benchmark_example_spec.rb") File.open(path, 'w') do |f| f.puts %q|describe "something" do| 100.times do |n| f.puts <<-TEXT it "does something #{n}", :focus => true do end TEXT end 100.times do |n| f.puts <<-TEXT it "does something else #{n}" do end TEXT end f.puts %q|end| end n = 1 Benchmark.benchmark do |bm| 3.times do bm.report do n.times do `bin/rspec --tag focus #{path}` end end end end File.delete(path) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/to_proc_v_not_to_proc.rb0000664000000000000000000002641314557677674025730 0ustar rootrootrequire 'benchmark' $n = 5000 puts def report(header) reals = [] Benchmark.benchmark do |bm| 3.times do reals << bm.report { $n.times { yield } }.real end end [header, reals.inject(&:+) / reals.count] end avgs = [] def a(&block) b(&block) end def b(&block) block.call end def c(&block) d(block) end def d(block) block.call end puts "#{$n} invocations" puts avgs << report("with &") { a { 100*100*100} } puts avgs << report("without &") { c { 100*100*100} } puts puts avgs puts __END__ ruby -e "10.times { system 'ruby benchmarks/to_proc_v_not_to_proc.rb' }" 1000 invocations 0.010000 0.000000 0.010000 ( 0.000958) 0.000000 0.000000 0.000000 ( 0.000917) 0.000000 0.000000 0.000000 ( 0.000893) 0.000000 0.000000 0.000000 ( 0.001660) 0.000000 0.000000 0.000000 ( 0.002686) 0.000000 0.000000 0.000000 ( 0.000686) with & 0.0009226666666666667 without & 0.0016773333333333334 1000 invocations 0.000000 0.000000 0.000000 ( 0.000898) 0.000000 0.000000 0.000000 ( 0.000868) 0.010000 0.000000 0.010000 ( 0.000768) 0.000000 0.000000 0.000000 ( 0.001615) 0.000000 0.000000 0.000000 ( 0.002917) 0.000000 0.000000 0.000000 ( 0.000996) with & 0.0008446666666666666 without & 0.0018426666666666667 1000 invocations 0.000000 0.000000 0.000000 ( 0.000884) 0.000000 0.000000 0.000000 ( 0.001217) 0.000000 0.000000 0.000000 ( 0.000877) 0.000000 0.000000 0.000000 ( 0.001617) 0.010000 0.000000 0.010000 ( 0.002718) 0.000000 0.000000 0.000000 ( 0.000772) with & 0.0009926666666666667 without & 0.0017023333333333335 1000 invocations 0.000000 0.000000 0.000000 ( 0.000868) 0.000000 0.000000 0.000000 ( 0.000874) 0.000000 0.000000 0.000000 ( 0.000829) 0.000000 0.000000 0.000000 ( 0.001394) 0.010000 0.000000 0.010000 ( 0.002330) 0.000000 0.000000 0.000000 ( 0.000712) with & 0.000857 without & 0.0014786666666666665 1000 invocations 0.000000 0.000000 0.000000 ( 0.000901) 0.000000 0.000000 0.000000 ( 0.000876) 0.010000 0.000000 0.010000 ( 0.000851) 0.000000 0.000000 0.000000 ( 0.001465) 0.000000 0.000000 0.000000 ( 0.002478) 0.000000 0.000000 0.000000 ( 0.000661) with & 0.000876 without & 0.0015346666666666668 1000 invocations 0.000000 0.000000 0.000000 ( 0.000907) 0.000000 0.000000 0.000000 ( 0.000810) 0.000000 0.000000 0.000000 ( 0.000796) 0.000000 0.000000 0.000000 ( 0.001407) 0.010000 0.000000 0.010000 ( 0.002549) 0.000000 0.000000 0.000000 ( 0.000652) with & 0.0008376666666666667 without & 0.001536 1000 invocations 0.000000 0.000000 0.000000 ( 0.000852) 0.000000 0.000000 0.000000 ( 0.000884) 0.000000 0.000000 0.000000 ( 0.000829) 0.010000 0.000000 0.010000 ( 0.001471) 0.000000 0.000000 0.000000 ( 0.002701) 0.000000 0.000000 0.000000 ( 0.000729) with & 0.000855 without & 0.001633666666666667 1000 invocations 0.000000 0.000000 0.000000 ( 0.001089) 0.010000 0.000000 0.010000 ( 0.000957) 0.000000 0.000000 0.000000 ( 0.000813) 0.000000 0.000000 0.000000 ( 0.001477) 0.000000 0.000000 0.000000 ( 0.002500) 0.000000 0.000000 0.000000 ( 0.000666) with & 0.000953 without & 0.0015476666666666666 1000 invocations 0.010000 0.000000 0.010000 ( 0.000839) 0.000000 0.000000 0.000000 ( 0.000846) 0.000000 0.000000 0.000000 ( 0.000812) 0.000000 0.000000 0.000000 ( 0.001497) 0.000000 0.000000 0.000000 ( 0.002415) 0.000000 0.000000 0.000000 ( 0.000729) with & 0.0008323333333333334 without & 0.0015470000000000004 1000 invocations 0.000000 0.000000 0.000000 ( 0.000904) 0.000000 0.000000 0.000000 ( 0.000928) 0.000000 0.000000 0.000000 ( 0.000904) 0.010000 0.000000 0.010000 ( 0.001649) 0.000000 0.000000 0.000000 ( 0.002838) 0.000000 0.000000 0.000000 ( 0.000799) with & 0.0009119999999999999 without & 0.001762 $ ruby -e "10.times { system 'ruby benchmarks/to_proc_v_not_to_proc.rb' }" 5000 invocations 0.000000 0.000000 0.000000 ( 0.007017) 0.010000 0.000000 0.010000 ( 0.005138) 0.000000 0.000000 0.000000 ( 0.005207) 0.010000 0.000000 0.010000 ( 0.005075) 0.000000 0.000000 0.000000 ( 0.005230) 0.010000 0.000000 0.010000 ( 0.006287) with & 0.005787333333333333 without & 0.005530666666666666 5000 invocations 0.010000 0.000000 0.010000 ( 0.006685) 0.010000 0.000000 0.010000 ( 0.006263) 0.000000 0.000000 0.000000 ( 0.005923) 0.010000 0.000000 0.010000 ( 0.005996) 0.000000 0.000000 0.000000 ( 0.005626) 0.010000 0.000000 0.010000 ( 0.006743) with & 0.006290333333333334 without & 0.006121666666666667 5000 invocations 0.010000 0.000000 0.010000 ( 0.007708) 0.010000 0.000000 0.010000 ( 0.005533) 0.000000 0.000000 0.000000 ( 0.005451) 0.010000 0.000000 0.010000 ( 0.005297) 0.000000 0.000000 0.000000 ( 0.005129) 0.010000 0.000000 0.010000 ( 0.006554) with & 0.0062306666666666665 without & 0.005659999999999999 5000 invocations 0.010000 0.000000 0.010000 ( 0.006615) 0.000000 0.000000 0.000000 ( 0.006449) 0.010000 0.000000 0.010000 ( 0.005974) 0.010000 0.000000 0.010000 ( 0.005291) 0.000000 0.000000 0.000000 ( 0.005502) 0.010000 0.000000 0.010000 ( 0.007272) with & 0.006346 without & 0.006021666666666667 5000 invocations 0.010000 0.000000 0.010000 ( 0.006719) 0.000000 0.000000 0.000000 ( 0.005280) 0.010000 0.000000 0.010000 ( 0.005472) 0.000000 0.000000 0.000000 ( 0.005319) 0.010000 0.000000 0.010000 ( 0.005174) 0.010000 0.000000 0.010000 ( 0.006049) with & 0.005823666666666667 without & 0.005513999999999999 5000 invocations 0.010000 0.000000 0.010000 ( 0.006857) 0.010000 0.000000 0.010000 ( 0.009484) 0.000000 0.000000 0.000000 ( 0.007458) 0.010000 0.000000 0.010000 ( 0.006191) 0.010000 0.000000 0.010000 ( 0.005341) 0.000000 0.000000 0.000000 ( 0.005976) with & 0.007933 without & 0.005836000000000001 5000 invocations 0.010000 0.000000 0.010000 ( 0.007637) 0.000000 0.000000 0.000000 ( 0.005701) 0.010000 0.000000 0.010000 ( 0.005383) 0.000000 0.000000 0.000000 ( 0.005185) 0.010000 0.000000 0.010000 ( 0.005211) 0.010000 0.000000 0.010000 ( 0.008762) with & 0.006240333333333333 without & 0.006386 5000 invocations 0.010000 0.000000 0.010000 ( 0.006861) 0.010000 0.000000 0.010000 ( 0.010632) 0.000000 0.000000 0.000000 ( 0.006004) 0.010000 0.000000 0.010000 ( 0.005384) 0.010000 0.000000 0.010000 ( 0.006040) 0.000000 0.000000 0.000000 ( 0.008638) with & 0.007832333333333334 without & 0.006687333333333333 5000 invocations 0.010000 0.000000 0.010000 ( 0.006673) 0.000000 0.000000 0.000000 ( 0.005332) 0.010000 0.000000 0.010000 ( 0.005348) 0.000000 0.000000 0.000000 ( 0.005212) 0.010000 0.000000 0.010000 ( 0.005176) 0.010000 0.000000 0.010000 ( 0.005989) with & 0.005784333333333333 without & 0.0054589999999999994 5000 invocations 0.010000 0.000000 0.010000 ( 0.006795) 0.000000 0.000000 0.000000 ( 0.005278) 0.010000 0.000000 0.010000 ( 0.005466) 0.010000 0.000000 0.010000 ( 0.006348) 0.000000 0.000000 0.000000 ( 0.007129) 0.010000 0.000000 0.010000 ( 0.009930) with & 0.005846333333333333 without & 0.007802333333333332 $ ruby -e "10.times { system 'ruby benchmarks/to_proc_v_not_to_proc.rb' }" 10000 invocations 0.010000 0.000000 0.010000 ( 0.012112) 0.010000 0.000000 0.010000 ( 0.010734) 0.020000 0.000000 0.020000 ( 0.013636) 0.010000 0.000000 0.010000 ( 0.014597) 0.010000 0.000000 0.010000 ( 0.011408) 0.020000 0.000000 0.020000 ( 0.011720) with & 0.012160666666666667 without & 0.012575000000000001 10000 invocations 0.020000 0.000000 0.020000 ( 0.012789) 0.010000 0.000000 0.010000 ( 0.010452) 0.010000 0.000000 0.010000 ( 0.012485) 0.010000 0.000000 0.010000 ( 0.011538) 0.010000 0.000000 0.010000 ( 0.010159) 0.010000 0.000000 0.010000 ( 0.011292) with & 0.011908666666666665 without & 0.010996333333333335 10000 invocations 0.020000 0.000000 0.020000 ( 0.015100) 0.010000 0.000000 0.010000 ( 0.011080) 0.010000 0.000000 0.010000 ( 0.016177) 0.020000 0.000000 0.020000 ( 0.013541) 0.010000 0.000000 0.010000 ( 0.010604) 0.010000 0.000000 0.010000 ( 0.011566) with & 0.014119000000000001 without & 0.011903666666666667 10000 invocations 0.010000 0.000000 0.010000 ( 0.013065) 0.020000 0.000000 0.020000 ( 0.011556) 0.010000 0.000000 0.010000 ( 0.012144) 0.010000 0.000000 0.010000 ( 0.009862) 0.010000 0.000000 0.010000 ( 0.011292) 0.010000 0.000000 0.010000 ( 0.014442) with & 0.012255 without & 0.011865333333333334 10000 invocations 0.010000 0.000000 0.010000 ( 0.015715) 0.010000 0.000000 0.010000 ( 0.011772) 0.020000 0.000000 0.020000 ( 0.014638) 0.010000 0.000000 0.010000 ( 0.015350) 0.010000 0.000000 0.010000 ( 0.011328) 0.020000 0.000000 0.020000 ( 0.013594) with & 0.014041666666666666 without & 0.013424 10000 invocations 0.010000 0.000000 0.010000 ( 0.013395) 0.020000 0.000000 0.020000 ( 0.012911) 0.010000 0.000000 0.010000 ( 0.012247) 0.010000 0.000000 0.010000 ( 0.011711) 0.010000 0.000000 0.010000 ( 0.013390) 0.020000 0.000000 0.020000 ( 0.013257) with & 0.012851000000000001 without & 0.012785999999999999 10000 invocations 0.020000 0.000000 0.020000 ( 0.014683) 0.010000 0.000000 0.010000 ( 0.012940) 0.010000 0.000000 0.010000 ( 0.012317) 0.020000 0.000000 0.020000 ( 0.015153) 0.010000 0.000000 0.010000 ( 0.014927) 0.020000 0.000000 0.020000 ( 0.015575) with & 0.013313333333333335 without & 0.015218333333333334 10000 invocations 0.020000 0.000000 0.020000 ( 0.016568) 0.010000 0.000000 0.010000 ( 0.014674) 0.020000 0.000000 0.020000 ( 0.013102) 0.010000 0.000000 0.010000 ( 0.010525) 0.010000 0.000000 0.010000 ( 0.012797) 0.010000 0.000000 0.010000 ( 0.013213) with & 0.014781333333333334 without & 0.012178333333333333 10000 invocations 0.010000 0.000000 0.010000 ( 0.015328) 0.020000 0.000000 0.020000 ( 0.017426) 0.020000 0.000000 0.020000 ( 0.020689) 0.010000 0.000000 0.010000 ( 0.014016) 0.010000 0.000000 0.010000 ( 0.011353) 0.020000 0.000000 0.020000 ( 0.017668) with & 0.01781433333333333 without & 0.014345666666666668 10000 invocations 0.020000 0.000000 0.020000 ( 0.015356) 0.010000 0.000000 0.010000 ( 0.015558) 0.020000 0.000000 0.020000 ( 0.012719) 0.010000 0.000000 0.010000 ( 0.011133) 0.010000 0.000000 0.010000 ( 0.010461) 0.010000 0.000000 0.010000 ( 0.013035) with & 0.014544333333333333 without & 0.011543 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/capture_block_vs_yield.rb0000664000000000000000000001405514557677674026043 0ustar rootrootrequire 'benchmark/ips' def yield_control yield end def capture_block_and_yield(&block) yield end def capture_block_and_call(&block) block.call end puts "Using the block directly" Benchmark.ips do |x| x.report("yield ") do yield_control { } end x.report("capture block and yield") do capture_block_and_yield { } end x.report("capture block and call ") do capture_block_and_call { } end end puts "Forwarding the block to another method" def tap_with_yield 5.tap { |i| yield i } end def tap_with_forwarded_block(&block) 5.tap(&block) end Benchmark.ips do |x| x.report("tap { |i| yield i }") do tap_with_yield { |i| } end x.report("tap(&block) ") do tap_with_forwarded_block { |i| } end end def yield_n_times(n) n.times { yield } end def forward_block_to_n_times(n, &block) n.times(&block) end def call_block_n_times(n, &block) n.times { block.call } end [10, 25, 50, 100, 1000, 10000].each do |count| puts "Invoking the block #{count} times" Benchmark.ips do |x| x.report("#{count}.times { yield } ") do yield_n_times(count) { } end x.report("#{count}.times(&block) ") do forward_block_to_n_times(count) { } end x.report("#{count}.times { block.call }") do call_block_n_times(count) { } end end end __END__ This benchmark demonstrates that capturing a block (e.g. `&block`) has a high constant cost, taking about 5x longer than a single `yield` (even if the block is never used!). However, forwarding a captured block can be faster than using `yield` if the block is used many times (the breakeven point is at about 20-25 invocations), so it appears that he per-invocation cost of `yield` is higher than that of a captured-and-forwarded block. Note that there is no circumstance where using `block.call` is faster. See also `flat_map_vs_inject.rb`, which appears to contradict these results a little bit. Using the block directly Calculating ------------------------------------- yield 91.539k i/100ms capture block and yield 50.945k i/100ms capture block and call 50.923k i/100ms ------------------------------------------------- yield 4.757M (± 6.0%) i/s - 23.709M capture block and yield 1.112M (±20.7%) i/s - 5.349M capture block and call 964.475k (±20.3%) i/s - 4.634M Forwarding the block to another method Calculating ------------------------------------- tap { |i| yield i } 74.620k i/100ms tap(&block) 51.382k i/100ms ------------------------------------------------- tap { |i| yield i } 3.213M (± 6.3%) i/s - 16.043M tap(&block) 970.418k (±18.6%) i/s - 4.727M Invoking the block 10 times Calculating ------------------------------------- 10.times { yield } 49.151k i/100ms 10.times(&block) 40.682k i/100ms 10.times { block.call } 27.576k i/100ms ------------------------------------------------- 10.times { yield } 908.673k (± 4.9%) i/s - 4.571M 10.times(&block) 674.565k (±16.1%) i/s - 3.336M 10.times { block.call } 385.056k (±10.3%) i/s - 1.930M Invoking the block 25 times Calculating ------------------------------------- 25.times { yield } 29.874k i/100ms 25.times(&block) 30.934k i/100ms 25.times { block.call } 17.119k i/100ms ------------------------------------------------- 25.times { yield } 416.342k (± 3.6%) i/s - 2.091M 25.times(&block) 446.108k (±10.6%) i/s - 2.227M 25.times { block.call } 201.264k (± 7.2%) i/s - 1.010M Invoking the block 50 times Calculating ------------------------------------- 50.times { yield } 17.690k i/100ms 50.times(&block) 21.760k i/100ms 50.times { block.call } 9.961k i/100ms ------------------------------------------------- 50.times { yield } 216.195k (± 5.7%) i/s - 1.079M 50.times(&block) 280.217k (± 9.9%) i/s - 1.393M 50.times { block.call } 112.754k (± 5.6%) i/s - 567.777k Invoking the block 100 times Calculating ------------------------------------- 100.times { yield } 10.143k i/100ms 100.times(&block) 13.688k i/100ms 100.times { block.call } 5.551k i/100ms ------------------------------------------------- 100.times { yield } 111.700k (± 3.6%) i/s - 568.008k 100.times(&block) 163.638k (± 7.7%) i/s - 821.280k 100.times { block.call } 58.472k (± 5.6%) i/s - 294.203k Invoking the block 1000 times Calculating ------------------------------------- 1000.times { yield } 1.113k i/100ms 1000.times(&block) 1.817k i/100ms 1000.times { block.call } 603.000 i/100ms ------------------------------------------------- 1000.times { yield } 11.156k (± 8.4%) i/s - 56.763k 1000.times(&block) 18.551k (±10.1%) i/s - 92.667k 1000.times { block.call } 6.206k (± 3.5%) i/s - 31.356k Invoking the block 10000 times Calculating ------------------------------------- 10000.times { yield } 113.000 i/100ms 10000.times(&block) 189.000 i/100ms 10000.times { block.call } 61.000 i/100ms ------------------------------------------------- 10000.times { yield } 1.150k (± 3.6%) i/s - 5.763k 10000.times(&block) 1.896k (± 6.9%) i/s - 9.450k 10000.times { block.call } 624.401 (± 3.0%) i/s - 3.172k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/require_relative_v_require.rb0000664000000000000000000000466514557677674026766 0ustar rootrootrequire 'benchmark' n = 20 Benchmark.benchmark do |bm| 3.times.each do bm.report do n.times do pid = fork do require 'rspec/core' end Process.wait(pid) end end end end # ################################### # Ruby 1.9.3 - 3 x 20 # require # $ bundle exec ruby benchmarks/require_relative_v_require.rb # 0.000000 0.020000 2.540000 ( 2.568784) # 0.000000 0.010000 2.550000 ( 2.580621) # 0.000000 0.020000 2.510000 ( 2.548631) # # require_relative # $ bundle exec ruby benchmarks/require_relative_v_require.rb # 0.000000 0.010000 2.220000 ( 2.288229) # 0.000000 0.010000 2.250000 ( 2.289886) # 0.000000 0.020000 2.260000 ( 2.296639) # # roughly 12% improvement # # ################################### # # Ruby 1.8.7 - 3 x 20 # before change (using require, but no conditional) # $ bundle exec ruby benchmarks/require_relative_v_require.rb # 0.000000 0.010000 1.210000 ( 1.242291) # 0.000000 0.010000 1.230000 ( 1.259518) # 0.000000 0.010000 1.230000 ( 1.250333) # # after change (still using require, but adding conditional) # $ bundle exec ruby benchmarks/require_relative_v_require.rb # 0.000000 0.010000 1.200000 ( 1.227249) # 0.000000 0.010000 1.230000 ( 1.257012) # 0.000000 0.010000 1.230000 ( 1.259278) # # virtually no penalty # # ################################### __END__ Ruby 2.0: ➜ rspec-core git:(benchmark-require-relative) REQUIRE_RELATIVE=1 bundle exec ruby benchmarks/require_relative_v_require.rb 0.000000 0.030000 1.470000 ( 1.481949) 0.000000 0.020000 1.440000 ( 1.462620) 0.000000 0.020000 1.470000 ( 1.491825) ➜ rspec-core git:(benchmark-require-relative) bundle exec ruby benchmarks/require_relative_v_require.rb 0.000000 0.010000 1.510000 ( 1.549906) 0.000000 0.010000 1.530000 ( 1.546252) 0.000000 0.020000 1.510000 ( 1.531644) Ruby 2.1: ➜ rspec-core git:(benchmark-require-relative) bundle exec ruby benchmarks/require_relative_v_require.rb 0.000000 0.020000 1.570000 ( 1.613217) 0.000000 0.020000 1.600000 ( 1.618540) 0.010000 0.020000 1.570000 ( 1.608205) ➜ rspec-core git:(benchmark-require-relative) REQUIRE_RELATIVE=1 bundle exec ruby benchmarks/require_relative_v_require.rb 0.000000 0.020000 1.480000 ( 1.515131) 0.000000 0.010000 1.480000 ( 1.527766) 0.000000 0.020000 1.490000 ( 1.515631) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/hash_functions.rb0000664000000000000000000000311214557677674024333 0ustar rootrootrequire 'benchmark/ips' require 'digest/md5' MAX_32_BIT = 4294967295 def jenkins_iterative(string) hash = 0 string.each_byte do |byte| hash += byte hash &= MAX_32_BIT hash += ((hash << 10) & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 6 end hash += (hash << 3 & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 11 hash += (hash << 15 & MAX_32_BIT) hash &= MAX_32_BIT hash end def jenkins_inject(string) hash = string.each_byte.inject(0) do |byte, hash| hash += byte hash &= MAX_32_BIT hash += ((hash << 10) & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 6 end hash += (hash << 3 & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 11 hash += (hash << 15 & MAX_32_BIT) hash &= MAX_32_BIT hash end require 'benchmark/ips' Benchmark.ips do |x| x.report("md5") do Digest::MD5.digest("string") end x.report("jenkins iterative") do jenkins_iterative("string") end x.report("jenkins inject") do jenkins_inject("string") end x.compare! end __END__ Calculating ------------------------------------- md5 39.416k i/100ms jenkins iterative 22.646k i/100ms jenkins inject 18.271k i/100ms ------------------------------------------------- md5 654.294k (±15.7%) i/s - 3.193M jenkins iterative 349.669k (±10.3%) i/s - 1.744M jenkins inject 286.774k (± 5.5%) i/s - 1.443M Comparison: md5: 654293.8 i/s jenkins iterative: 349668.8 i/s - 1.87x slower jenkins inject: 286774.4 i/s - 2.28x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/precalculate_absolute_file_path_or_not.rb0000664000000000000000000000153714557677674031266 0ustar rootrootrequire 'benchmark/ips' metadata = { :file_path => "some/path.rb" } meta_with_absolute = metadata.merge(:absolute_file_path => File.expand_path(metadata[:file_path])) Benchmark.ips do |x| x.report("fetch absolute path from hash") do meta_with_absolute[:absolute_file_path] end x.report("calculate absolute path") do File.expand_path(metadata[:file_path]) end end __END__ Precalculating the absolute file path is much, much faster! Calculating ------------------------------------- fetch absolute path from hash 102.164k i/100ms calculate absolute path 9.331k i/100ms ------------------------------------------------- fetch absolute path from hash 7.091M (±11.6%) i/s - 34.736M calculate absolute path 113.141k (± 8.6%) i/s - 569.191k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/keys_each_vs_each_key.rb0000664000000000000000000000244714557677674025625 0ustar rootrootrequire 'benchmark/ips' small_hash = { :key => true, :more_key => true, :other_key => true } large_hash = (1...100).inject({}) { |hash, key| hash["key_#{key}"] = true; hash } Benchmark.ips do |x| x.report('keys.each with small hash') do small_hash.keys.each { |value| value == true } end x.report('each_key with small hash') do small_hash.each_key { |value| value == true } end x.report('keys.each with large hash') do large_hash.keys.each { |value| value == true } end x.report('each_key with large hash') do large_hash.each_key { |value| value == true } end end __END__ Calculating ------------------------------------- keys.each with small hash 105.581k i/100ms each_key with small hash 112.045k i/100ms keys.each with large hash 7.625k i/100ms each_key with large hash 6.959k i/100ms ------------------------------------------------- keys.each with small hash 2.953M (± 3.8%) i/s - 14.781M each_key with small hash 2.917M (± 4.0%) i/s - 14.678M keys.each with large hash 79.349k (± 2.5%) i/s - 396.500k each_key with large hash 72.080k (± 2.1%) i/s - 361.868k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/define_method_v_attr_reader_v_def.rb0000664000000000000000000000246314557677674030166 0ustar rootrootrequire 'benchmark' n = 1_000_000 puts "each sample runs #{n} times" puts class Foo define_method :foo do @foo end attr_reader :bar def initialize @foo = 'foo' @bar = 'bar' @baz = 'baz' end def baz @baz end end foo = Foo.new puts "define_method" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do foo.foo end end end end puts puts "attr_reader" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do foo.bar end end end end puts puts "def" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do foo.baz end end end end # $ ruby -v # ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.0] # $ ruby benchmarks/define_method_v_attr_reader_v_def.rb # each sample runs 1000000 times # # define_method # 0.250000 0.000000 0.250000 ( 0.251552) # 0.250000 0.000000 0.250000 ( 0.261506) # 0.250000 0.000000 0.250000 ( 0.247398) # # attr_reader # 0.140000 0.000000 0.140000 ( 0.141782) # 0.140000 0.000000 0.140000 ( 0.142411) # 0.140000 0.000000 0.140000 ( 0.145876) # # def # 0.160000 0.000000 0.160000 ( 0.153261) # 0.150000 0.000000 0.150000 ( 0.158096) # 0.150000 0.000000 0.150000 ( 0.149472) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/benchmarks/module_inclusion_filtering.rb0000664000000000000000000000610014557677674026733 0ustar rootrootrequire_relative "../bundle/bundler/setup" # configures load paths require 'rspec/core' class << RSpec attr_writer :world end # Here we are restoring the old implementation of `configure_group`, so that # we can toggle the new vs old implementation in the benchmark by aliasing it. module RSpecConfigurationOverrides def initialize(*args) super @include_extend_or_prepend_modules = [] end def include(mod, *filters) meta = RSpec::Core::Metadata.build_hash_from(filters, :warn_about_example_group_filtering) @include_extend_or_prepend_modules << [:include, mod, meta] super end def old_configure_group(group) @include_extend_or_prepend_modules.each do |include_extend_or_prepend, mod, filters| next unless filters.empty? || RSpec::Core::MetadataFilter.apply?(:any?, filters, group.metadata) __send__("safe_#{include_extend_or_prepend}", mod, group) end end def self.prepare_implementation(prefix) RSpec.world = RSpec::Core::World.new # clear our state RSpec::Core::Configuration.class_eval do alias_method :configure_group, :"#{prefix}_configure_group" end end end RSpec::Core::Configuration.class_eval do prepend RSpecConfigurationOverrides alias new_configure_group configure_group end RSpec.configure do |c| 50.times { c.include Module.new, :include_it } end require 'benchmark/ips' Benchmark.ips do |x| x.report("Old linear search: non-matching metadata") do |times| RSpecConfigurationOverrides.prepare_implementation(:old) times.times { |i| RSpec.describe "Old linear search: non-matching metadata #{i}" } end x.report("New memoized search: non-matching metadata") do |times| RSpecConfigurationOverrides.prepare_implementation(:new) times.times { |i| RSpec.describe "New memoized search: non-matching metadata #{i}" } end x.report("Old linear search: matching metadata") do |times| RSpecConfigurationOverrides.prepare_implementation(:old) times.times { |i| RSpec.describe "Old linear search: matching metadata #{i}", :include_it } end x.report("New memoized search: matching metadata") do |times| RSpecConfigurationOverrides.prepare_implementation(:new) times.times { |i| RSpec.describe "New memoized search: matching metadata #{i}", :include_it } end end __END__ Calculating ------------------------------------- Old linear search: non-matching metadata 86.000 i/100ms New memoized search: non-matching metadata 93.000 i/100ms Old linear search: matching metadata 79.000 i/100ms New memoized search: matching metadata 90.000 i/100ms ------------------------------------------------- Old linear search: non-matching metadata 884.109 (±61.9%) i/s - 3.268k New memoized search: non-matching metadata 1.099k (±81.2%) i/s - 3.441k Old linear search: matching metadata 822.348 (±57.5%) i/s - 3.081k New memoized search: matching metadata 1.116k (±76.6%) i/s - 3.510k ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/0000775000000000000000000000000014557677674020165 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/cucumber.sh0000775000000000000000000000034214557677674022330 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh run_cukes ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/run_build0000775000000000000000000000151714557677674022102 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "binstub check" check_binstubs fold "specs" run_specs_and_record_done if additional_specs_available; then fold "additional specs" run_additional_specs fi fold "cukes" run_cukes if documentation_enforced; then fold "doc check" check_documentation_coverage fi if supports_cross_build_checks; then fold "one-by-one specs" run_specs_one_by_one export NO_COVERAGE=true run_all_spec_suites else echo "Skipping the rest of the build on non-MRI rubies" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/rspec_with_simplecov0000775000000000000000000000235014557677674024343 0ustar rootroot#!/usr/bin/env ruby # Turn on verbose to make sure we not generating any ruby warning $VERBOSE = true # So our "did they run the rspec command?" detection logic thinks # that we run `rspec`. $0 = "rspec" # This is necessary for when `--standalone` is being used. $:.unshift File.expand_path '../../bundle', __FILE__ # For the travis build we put the bundle directory up a directory # so it can be shared among the repos for faster bundle installs. $:.unshift File.expand_path '../../../bundle', __FILE__ require 'bundler/setup' # To use simplecov while running rspec-core's test suite, we must # load simplecov _before_ loading any of rspec-core's files. # So, this executable exists purely as a wrapper script that # first loads simplecov, and then loads rspec. begin # Simplecov emits some ruby warnings when loaded, so silence them. old_verbose, $VERBOSE = $VERBOSE, false unless ENV['NO_COVERAGE'] || RUBY_VERSION.to_f < 2.1 require 'simplecov' SimpleCov.start do add_filter "bundle/" add_filter "tmp/" add_filter "spec/" minimum_coverage(100) end end rescue LoadError # rubocop:disable Lint/SuppressedException ensure $VERBOSE = old_verbose end load File.expand_path("../../exe/rspec", __FILE__) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/console0000775000000000000000000000031614557677674021555 0ustar rootroot#!/usr/bin/env ruby require "irb" lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib") $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path) require 'rspec/core' IRB.start(__FILE__) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/update_rubygems_and_install_bundler0000775000000000000000000000122514557677674027375 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh if is_ruby_31_plus; then echo "Installing rubygems 3.3.6 / bundler 2.3.6" yes | gem update --system '3.3.6' yes | gem install bundler -v '2.3.6' elif is_ruby_23_plus; then echo "Installing rubygems 3.2.22 / bundler 2.2.22" yes | gem update --system '3.2.22' yes | gem install bundler -v '2.2.22' else echo "Warning installing older versions of Rubygems / Bundler" gem update --system '2.7.8' gem install bundler -v '1.17.3' fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/custom_build_functions.sh0000664000000000000000000000146614557677674025311 0ustar rootrootfunction run_cukes { if [ -d features ]; then echo "${PWD}/bin/cucumber" if is_mri_192; then # For some reason we get SystemStackError on 1.9.2 when using # the bin/cucumber approach below. That approach is faster # (as it avoids the bundler tax), so we use it on rubies where we can. bundle exec cucumber --strict elif is_jruby; then echo "WARNING: Cucumber is skipped on JRuby on rspec-core due to" \ "excessive build times (>45 minutes) causing timeouts on Travis" return 0 else # Prepare RUBYOPT for scenarios that are shelling out to ruby, # and PATH for those that are using `rspec` or `rake`. RUBYOPT="${RUBYOPT} -I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict fi fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/regen_fixtures.sh0000775000000000000000000000121214557677674023551 0ustar rootroot#!/bin/bash # This script likely won't work as is for you, but is a good template for # iterating over all rubies and regenerating HTML fixtures. set -e source /usr/local/share/chruby/chruby.sh function switch_ruby() { chruby $1 } function regen() { bundle check || bundle install GENERATE=1 bundle exec rspec ./spec/rspec/core/formatters/ || true } for ruby in \ jruby-1.7.9 \ 1.9.3-p392 \ 2.0.0-p247 \ 2.1.0-p0 \ rbx-2.2.3 \ ree-1.8.7-2012.02; do switch_ruby $ruby ruby -v if [ $(echo $ruby | grep jruby) ] then export JRUBY_OPTS=--1.8 regen export JRUBY_OPTS=--1.9 regen else regen fi done ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/functions.sh0000664000000000000000000001404014557677674022530 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source $SCRIPT_DIR/ci_functions.sh source $SCRIPT_DIR/predicate_functions.sh # If JRUBY_OPTS isn't set, use these. # see https://docs.travis-ci.com/user/ci-environment/ export JRUBY_OPTS=${JRUBY_OPTS:-"--server -Xcompile.invokedynamic=false"} SPECS_HAVE_RUN_FILE=specs.out MAINTENANCE_BRANCH=`cat maintenance-branch` # Don't allow rubygems to pollute what's loaded. Also, things boot faster # without the extra load time of rubygems. Only works on MRI Ruby 1.9+ if is_mri_192_plus; then export RUBYOPT="--disable=gem" fi function clone_repo { if [ ! -d $1 ]; then # don't clone if the dir is already there if [ -z "$2" ]; then BRANCH_TO_CLONE="${MAINTENANCE_BRANCH?}"; else BRANCH_TO_CLONE="$2"; fi; ci_retry eval "git clone https://github.com/rspec/$1 --depth 1 --branch ${BRANCH_TO_CLONE?}" fi; } function run_specs_and_record_done { local rspec_bin=bin/rspec # rspec-core needs to run with a special script that loads simplecov first, # so that it can instrument rspec-core's code before rspec-core has been loaded. if [ -f script/rspec_with_simplecov ] && is_mri; then rspec_bin=script/rspec_with_simplecov fi; echo "${PWD}/bin/rspec" $rspec_bin spec --backtrace --format progress --profile --format progress --out $SPECS_HAVE_RUN_FILE } function run_cukes { if [ -d features ]; then # 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 # # Note that we delay setting this until we run the cukes because we've seen # spec failures in our spec suite due to problems with this mode. export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "${PWD}/bin/cucumber" if is_mri_192; then # For some reason we get SystemStackError on 1.9.2 when using # the bin/cucumber approach below. That approach is faster # (as it avoids the bundler tax), so we use it on rubies where we can. bundle exec cucumber --strict elif is_jruby; then # For some reason JRuby doesn't like our improved bundler setup RUBYOPT="-I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict else # Prepare RUBYOPT for scenarios that are shelling out to ruby, # and PATH for those that are using `rspec` or `rake`. RUBYOPT="${RUBYOPT} -I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict fi fi } function run_specs_one_by_one { echo "Running each spec file, one-by-one..." for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done } function run_spec_suite_for { if [ ! -f ../$1/$SPECS_HAVE_RUN_FILE ]; then # don't rerun specs that have already run if [ -d ../$1 ]; then echo "Running specs for $1" pushd ../$1 unset BUNDLE_GEMFILE bundle_install_flags=`cat .github/workflows/ci.yml | grep "bundle install" | sed 's/.* bundle install//'` ci_retry eval "(unset RUBYOPT; exec bundle install $bundle_install_flags)" ci_retry eval "(unset RUBYOPT; exec bundle binstubs --all)" run_specs_and_record_done popd else echo "" echo "WARNING: The ../$1 directory does not exist. Usually the" echo "build cds into that directory and run the specs to ensure" echo "the specs still pass with your latest changes, but we are" echo "going to skip that step." echo "" fi; fi; } function check_binstubs { echo "Checking required binstubs" local success=0 local binstubs="" local gems="" if [ ! -x ./bin/rspec ]; then binstubs="$binstubs bin/rspec" gems="$gems rspec-core" success=1 fi if [ ! -x ./bin/rake ]; then binstubs="$binstubs bin/rake" gems="$gems rake" success=1 fi if [ -d features ]; then if [ ! -x ./bin/cucumber ]; then binstubs="$binstubs bin/cucumber" gems="$gems cucumber" success=1 fi fi if [ $success -eq 1 ]; then echo echo "Missing binstubs:$binstubs" echo "Install missing binstubs using one of the following:" echo echo " # Create the missing binstubs" echo " $ bundle binstubs$gems" echo echo " # To binstub all gems" echo " $ bundle binstubs --all" fi return $success } function check_documentation_coverage { echo "bin/yard stats --list-undoc" bin/yard stats --list-undoc | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') coverage ||= line[/([\d\.]+)% documented/, 1] puts line end unless Float(coverage) == 100 puts \"\n\nMissing documentation coverage (currently at #{coverage}%)\" exit(1) end if has_warnings puts \"\n\nYARD emitted documentation warnings.\" exit(1) end " # Some warnings only show up when generating docs, so do that as well. bin/yard doc --no-cache | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') has_errors ||= line.start_with?('[error]:') puts line end if has_warnings || has_errors puts \"\n\nYARD emitted documentation warnings or errors.\" exit(1) end " } function check_style_and_lint { echo "bin/rubocop lib" eval "(unset RUBYOPT; exec bin/rubocop lib)" } function run_all_spec_suites { fold "rspec-core specs" run_spec_suite_for "rspec-core" fold "rspec-expectations specs" run_spec_suite_for "rspec-expectations" fold "rspec-mocks specs" run_spec_suite_for "rspec-mocks" if rspec_rails_compatible; then if ! is_ruby_27_plus; then export RAILS_VERSION='~> 6.1.0' fi fold "rspec-rails specs" run_spec_suite_for "rspec-rails" fi if rspec_support_compatible; then fold "rspec-support specs" run_spec_suite_for "rspec-support" fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/legacy_setup.sh0000775000000000000000000000077214557677674023216 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh bundle install --standalone --binstubs --without coverage documentation if [ -x ./bin/rspec ]; then echo "RSpec bin detected" else if [ -x ./exe/rspec ]; then cp ./exe/rspec ./bin/rspec echo "RSpec restored from exe" else echo "No RSpec bin available" exit 1 fi fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/ci_functions.sh0000664000000000000000000000376314557677674023215 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. # Taken from: # https://github.com/travis-ci/travis-build/blob/e9314616e182a23e6a280199cd9070bfc7cae548/lib/travis/build/script/templates/header.sh#L34-L53 ci_retry() { local result=0 local count=1 while [ $count -le 3 ]; do [ $result -ne 0 ] && { echo -e "\n\033[33;1mThe command \"$@\" failed. Retrying, $count of 3.\033[0m\n" >&2 } "$@" result=$? [ $result -eq 0 ] && break count=$(($count + 1)) sleep 1 done [ $count -eq 3 ] && { echo "\n\033[33;1mThe command \"$@\" failed 3 times.\033[0m\n" >&2 } return $result } # Taken from https://github.com/vcr/vcr/commit/fa96819c92b783ec0c794f788183e170e4f684b2 # and https://github.com/vcr/vcr/commit/040aaac5370c68cd13c847c076749cd547a6f9b1 nano_cmd="$(type -p gdate date | head -1)" nano_format="+%s%N" [ "$(uname -s)" != "Darwin" ] || nano_format="${nano_format/%N/000000000}" travis_time_start() { travis_timer_id=$(printf %08x $(( RANDOM * RANDOM ))) travis_start_time=$($nano_cmd -u "$nano_format") printf "travis_time:start:%s\r\e[0m" $travis_timer_id } travis_time_finish() { local travis_end_time=$($nano_cmd -u "$nano_format") local duration=$(($travis_end_time-$travis_start_time)) printf "travis_time:end:%s:start=%s,finish=%s,duration=%s\r\e[0m" \ $travis_timer_id $travis_start_time $travis_end_time $duration } fold() { local name="$1" local status=0 shift 1 if [ -n "$TRAVIS" ]; then printf "travis_fold:start:%s\r\e[0m" "$name" travis_time_start else echo "============= Starting $name ===============" fi "$@" status=$? [ -z "$TRAVIS" ] || travis_time_finish if [ "$status" -eq 0 ]; then if [ -n "$TRAVIS" ]; then printf "travis_fold:end:%s\r\e[0m" "$name" else echo "============= Ending $name ===============" fi else STATUS="$status" fi return $status } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/predicate_functions.sh0000664000000000000000000000555114557677674024557 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. function is_mri { if ruby -e "exit(!defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_ruby_head { # This checks for the presence of our CI's ruby-head env variable if [ -z ${RUBY_HEAD+x} ]; then return 1 else return 0 fi; } function supports_cross_build_checks { if is_mri; then # We don't run cross build checks on ruby-head if is_ruby_head; then return 1 else return 0 fi else return 1 fi } function is_jruby { if ruby -e "exit(defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_mri_192 { if is_mri; then if ruby -e "exit(RUBY_VERSION == '1.9.2')"; then return 0 else return 1 fi else return 1 fi } function is_mri_192_plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 1.8)"; then return 0 else return 1 fi else return 1 fi } function is_mri_2plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 2.0)"; then return 0 else return 1 fi else return 1 fi } function is_ruby_23_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.3)"; then return 0 else return 1 fi } function is_ruby_25_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.5)"; then return 0 else return 1 fi } function is_ruby_27_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.7)"; then return 0 else return 1 fi } function is_ruby_31_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 3.1)"; then return 0 else return 1 fi } function rspec_rails_compatible { if is_ruby_25_plus; then # TODO remove when RSpec-Rails build is 3.1 safe by default if is_ruby_31_plus; then return 1 else return 0 fi else return 1 fi } function rspec_support_compatible { if [ "$MAINTENANCE_BRANCH" != "2-99-maintenance" ] && [ "$MAINTENANCE_BRANCH" != "2-14-maintenance" ]; then return 0 else return 1 fi } function additional_specs_available { type run_additional_specs > /dev/null 2>&1 return $? } function documentation_enforced { if [ -x ./bin/yard ]; then if is_mri_2plus; then return 0 else return 1 fi else return 1 fi } function style_and_lint_enforced { if is_ruby_head; then return 1 else if [ -x ./bin/rubocop ]; then return 0 else return 1 fi fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/prevent_runtime_method_cache_busters0000775000000000000000000000074714557677674027603 0ustar rootroot#!/usr/bin/env ruby method_cache_busters = `script/list_method_cache_busters.sh`.split("\n").map(&:chomp) if method_cache_busters.any? puts "=" * 80 puts "Found #{method_cache_busters.size} new constructs that bust the method cache." puts "These should be eliminated or added to the `ignores` file." puts puts "For more information, see https://charlie.bz/blog/things-that-clear-rubys-method-cache" puts puts method_cache_busters.join("\n") puts "=" * 80 exit(1) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/ignores0000664000000000000000000001156714557677674021570 0ustar rootroot# grep -v -f doesn't work properly when empty, so this line is here. # The `alias_method` calls below are only executed at file load time # (when the method cache will be busted by defining methods anyway). lib/rspec/core/configuration.rb: alias_method alias_name, name lib/rspec/core/configuration.rb: alias_method "#{alias_name}=", "#{name}=" lib/rspec/core/configuration.rb: names.each {|name| alias_method "#{name}?", name} lib/rspec/core/configuration.rb: alias_method :formatter=, :add_formatter lib/rspec/core/configuration.rb: alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to lib/rspec/core/configuration.rb: alias_method :filter_run, :filter_run_including lib/rspec/core/configuration.rb: alias_method :filter=, :inclusion_filter= lib/rspec/core/configuration.rb: alias_method :filter, :inclusion_filter lib/rspec/core/example.rb: alias_method :pending?, :pending lib/rspec/core/example_group.rb: alias_method :display_name, :description lib/rspec/core/example_group.rb: alias_method :describes, :described_class lib/rspec/core/example_group.rb: # Works like `alias_method :name, :example` with the added benefit of lib/rspec/core/example_group.rb: # Works like `alias_method :name, :it_behaves_like` with the added lib/rspec/core/example_group.rb: alias_method :context, :describe lib/rspec/core/hooks.rb: alias_method :append_before, :before lib/rspec/core/hooks.rb: alias_method :prepend_after, :after lib/rspec/core/shared_example_group.rb: alias_method :shared_context, :shared_examples lib/rspec/core/shared_example_group.rb: alias_method :share_examples_for, :shared_examples lib/rspec/core/shared_example_group.rb: alias_method :shared_examples_for, :shared_examples lib/rspec/core/shared_example_group.rb: alias_method :shared_context, :shared_examples lib/rspec/core/shared_example_group.rb: alias_method :share_examples_for, :shared_examples lib/rspec/core/shared_example_group.rb: alias_method :shared_examples_for, :shared_examples lib/rspec/core/example_group.rb: alias_method :describe, :example_group lib/rspec/core/example_group.rb: alias_method :context, :example_group # The `alias_method` calls below happen when users define a named let. # It happens at spec definition time, not spec run time. lib/rspec/core/memoized_helpers.rb: alias_method :subject, name # These `const_set` calls happen at spec definition time, # not at spec run time, so they are OK. lib/rspec/core/example_group.rb: const_scope.const_set(name, group) lib/rspec/core/memoized_helpers.rb: example_group.const_set(:NamedSubjectPreventSuper, self) lib/rspec/core/memoized_helpers.rb: example_group.const_set(:LetDefinitions, mod) # These mentions of `extend` get executed at spec definition time # (unless the user changes their RSpec config at spec run time, but # there's no way to work around that). lib/rspec/core/configuration.rb: def extend(mod, \*filters) lib/rspec/core/configuration.rb: include_or_extend_modules << \[:extend, mod, Metadata.build_hash_from(filters)\] lib/rspec/core/configuration.rb: host.extend(mod) unless host.singleton_class < mod lib/rspec/core/configuration.rb: host.extend(mod) unless (class << host; self; end).included_modules.include?(mod) lib/rspec/core/configuration.rb: extend RSpec::SharedContext lib/rspec/core/dsl.rb:extend RSpec::Core::DSL lib/rspec/core/example_group.rb: extend Hooks lib/rspec/core/example_group.rb: extend SharedExampleGroup lib/rspec/core/memoized_helpers.rb: mod.extend(ClassMethods) lib/rspec/core/shared_example_group.rb:extend RSpec::Core::SharedExampleGroup::TopLevelDSL # This use of `extend` only happens on 1.8.7, when a shared example group # is defined (to provide the Proc#source_location method on the provided # block). It should only happen at spec definition time (unless users are # defining shared example groups at spec run time). lib/rspec/core/shared_example_group.rb: block.extend Module.new { # This happens when an example group is defined, not at spec run time. lib/rspec/core/example_group.rb: subclass = Class.new(parent) # This happens at file load time. lib/rspec/core/formatters/deprecation_formatter.rb: DeprecationError = Class.new(StandardError) # This enables / disable monkey patching and only happens on demand lib/rspec/core/dsl.rb: change_global_dsl { undef_method method_name } lib/rspec/core/shared_example_group.rb: undef shared_examples lib/rspec/core/shared_example_group.rb: undef shared_context lib/rspec/core/shared_example_group.rb: undef share_examples_for lib/rspec/core/shared_example_group.rb: undef shared_examples_for lib/rspec/core/shared_example_group.rb: undef shared_example_groups ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/run_rubocop0000775000000000000000000000063614557677674022455 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "rubocop" check_style_and_lint ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/list_method_cache_busters.sh0000775000000000000000000000237014557677674025733 0ustar rootroot#!/bin/bash # set -x # This list is from https://charlie.bz/blog/things-that-clear-rubys-method-cache IGNORE_FILE=/tmp/cache_busters_ignore COMMENT_LINE_RE="^(\w|\/)+\.rb: +#" cat script/ignores | grep -v "^$" | ruby -ne 'puts $_.split(/\s+###/)[0]' > $IGNORE_FILE egrep 'def [a-z]*\..*' -R lib | grep -v "def self" | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep undef -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep alias_method -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep remove_method -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep const_set -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep remove_const -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" egrep '\bextend\b' -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep 'Class.new' -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep private_constant -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep public_constant -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep "Marshal.load" -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" grep "OpenStruct.new" -R lib | grep -v -f $IGNORE_FILE | egrep -v "$COMMENT_LINE_RE" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/script/clone_all_rspec_repos0000775000000000000000000000111014557677674024440 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:05:21+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. set -e source script/functions.sh if is_mri; then pushd .. clone_repo "rspec" clone_repo "rspec-core" clone_repo "rspec-expectations" clone_repo "rspec-mocks" clone_repo "rspec-rails" "6-1-maintenance" if rspec_support_compatible; then clone_repo "rspec-support" fi popd else echo "Not cloning all repos since we are not on MRI and they are only needed for the MRI build" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/LICENSE.md0000664000000000000000000000240514557677674020266 0ustar rootrootThe MIT License (MIT) ===================== * Copyright © 2012 Chad Humphries, David Chelimsky, Myron Marston * Copyright © 2009 Chad Humphries, David Chelimsky * Copyright © 2006 David Chelimsky, The RSpec Development Team * Copyright © 2005 Steven Baker 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. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.rubocop.yml0000664000000000000000000000441414557677674021136 0ustar rootrootinherit_from: - .rubocop_rspec_base.yml - .rubocop_todo.yml AllCops: Exclude: # This code was taken from the backports gem. We don't want to mess with it. - lib/rspec/core/backport_random.rb # This should go down over time. Metrics/ClassLength: Max: 330 # This can be addressed once Ruby 1.8 support is removed. Style/Encoding: Enabled: false # This should go down over time. Metrics/AbcSize: Max: 40 # This should go down over time. Layout/LineLength: Max: 130 Exclude: - features/**/* - spec/**/* # This should go down over time. Metrics/MethodLength: Max: 39 # This should go down over time. Metrics/CyclomaticComplexity: Max: 12 Metrics/PerceivedComplexity: Max: 15 Lint/SuppressedException: Exclude: - lib/rspec/core/example.rb - lib/rspec/core/mocking_adapters/mocha.rb - lib/rspec/core/runner.rb - lib/rspec/core/test_unit_assertions_adapter.rb Lint/LiteralInInterpolation: Enabled: false Lint/NonLocalExitFromIterator: Enabled: false # We don't care about single vs double quotes. Style/StringLiteralsInInterpolation: Enabled: false Style/SymbolProc: Enabled: false Layout/SpaceAroundOperators: AllowForAlignment: true Layout/AccessModifierIndentation: Enabled: false Style/RegexpLiteral: Enabled: false # This could change depending of the style used Layout/MultilineOperationIndentation: Enabled: false Style/BarePercentLiterals: Enabled: false # Exclude the default spec_helper to make it easier to uncomment out # default settings (for both users and the Cucumber suite). Style/BlockComments: Exclude: - lib/rspec/core/project_initializer/spec/spec_helper.rb # Not sure what to do with this rule yet. Style/ClassAndModuleChildren: Exclude: - lib/rspec/core/formatters.rb - lib/rspec/core/notifications.rb - lib/rspec/core/option_parser.rb - lib/rspec/core/reporter.rb Style/RaiseArgs: Exclude: - lib/rspec/core/configuration.rb - lib/rspec/core/hooks.rb - lib/rspec/core/option_parser.rb - lib/rspec/core/pending.rb - spec/rspec/core/formatters/base_text_formatter_spec.rb Lint/IneffectiveAccessModifier: Exclude: - lib/rspec/core/memoized_helpers.rb # Fixing this file was too much of a diff Metrics/BlockLength: Max: 206 Exclude: - spec/**/*.rb ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Changelog.md0000664000000000000000000032147114557677674021102 0ustar rootroot### Development [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.12.3...main) ### 3.13.0 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.12.3...v3.13.0) Enhancements: * Support the `--backtrace` flag when using the JSON formatter. (Matt Larraz, #2980) * Ignore commented out lines in CLI config files (e.g. `.rspec`). (Junichi Ito, #2984) * Add `pending_failure_output` config option to allow skipping backtraces or muting pending specs output. (Phil Pirozhkov, #2957) * Process `--dry-run` before configuration flags that read files so that introspecting it returns the correct value. (Xenor Chang, #3008) * Allow specifying custom ordering strategies via `--order`. (Jon Rowe, #3025) * Use the improved `syntax_suggest` output for `SyntaxError` when available. (Richard Schneeman, #3015, #3026) * Add config option (`RSpec::Core::Configuration#full_cause_backtrace`) to print the entire backtrace of an exception cause. (David Taylor, #3046) ### 3.12.3 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.12.2...v3.12.3) Bug fixes: * Use `__send__` in output wrapper to avoid issues with IO objects that implement `send` like `Socket`. (Richard Platel, #3045) ### 3.12.2 / 2023-04-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.12.1...v3.12.2) Bug fixes: * Remove link to outdated documentation in generated output. (Jon Rowe, #3035) ### 3.12.1 / 2023-02-03 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.12.0...v3.12.1) Bug fixes: * Prevent multiple calls to `extra_failure_lines` from adding additional whitespace around them when the lines already contain whitespace. (Jon Rowe, #3006) ### 3.12.0 / 2022-10-26 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.11.0...v3.12.0) * No changes, released to support other gems. ### 3.11.0 / 2022-02-09 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.2...v3.11.0) Enhancements: * Improve pluralisation of words ending with `s` (like process). (Joshua Pinter, #2779) * Add ordering by file modification time (most recent first). (Matheus Richard, #2778) * Add `to_s` to reserved names for #let and #subject. (Nick Flückiger, #2886) * Introduce `RSpec.current_scope` to expose the current scope in which RSpec is executing. e.g. `:before_example_hook`, `:example` etc. (@odinhb, #2895) * Add named bold colours as options for custom colours. (#2913, #2914) * Warn when (but not prevent) a `SystemExit` occurs. (Jared Beck, #2926) ### 3.10.2 / 2022-01-27 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.1...v3.10.2) Bug fixes: * Ensure bisect communication uses consistent encoding. (Mike Jarema, #2852) * Fix exception presenter when the root cause exception has nil backtrace. (Zinovyev Ivan, #2903) * Fix `inspect` output of `RSpec::Core::Example::Procsy` to namespace correctly. (Keiko Kaneko, #2915) * Ensure formatters not exposing `#output` will not crash duplicate check. (@niceking, #2916) ### 3.10.1 / 2020-12-27 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.0...v3.10.1) Bug fixes: * RSpec warning output was missing deprecations from Ruby, these are now included. (Jon Rowe, #2811) ### 3.10.0 / 2020-10-30 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.3...v3.10.0) Enhancements: * Memoize `RSpec::Core::Formatters::ExceptionPresenter#exception_lines` to improve performance with slow exception messages. (Maxime Lapointe, #2743) * Add configuration for an error exit code (to disambiguate errored builds from failed builds by exit status). (Dana Sherson, #2749) ### 3.9.3 / 2020-09-30 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.2...v3.9.3) Bug Fixes: * Declare `ruby2_keywords` on `method_missing` for other gems. (Jon Rowe, #2731) * Ensure custom error codes are returned from bisect runs. (Jon Rowe, #2732) * Ensure `RSpec::Core::Configuration` predicate config methods return booleans. (Marc-André Lafortune, #2736) * Prevent `rspec --bisect` from generating zombie processes while executing bisect runs. (Benoit Tigeot, Jon Rowe, #2739) * Predicates for pending examples, (in `RSpec::Core::Example`, `#pending?`, `#skipped?` and `#pending_fixed?`) now return boolean values rather than truthy values. (Marc-André Lafortune, #2756, #2758) * Exceptions which have a message which cannot be cast to a string will no longer cause a crash. (Jon Rowe, #2761) ### 3.9.2 / 2020-05-02 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.1...v3.9.2) Bug Fixes: * Emit a warning when `around` hook is used with `:context` scope (Phil Pirozhkov, #2687) * Prevent invalid implementations of `Exception#cause` from being treated as a valid cause (and causing strange errors) in `RSpec::Core::Formatters::ExceptionPresenter`. (Jon Rowe, #2703) * Correctly detect patterns when `rspec_opts` is an array in `RSpec::Core::RakeTask`. (Marc-André Lafortune, #2704) * Make `RSpec.clear_examples` reset example counts for example groups. This fixes an issue with re-running specs not matching ids. (Agis Anastasopoulos, #2723) ### 3.9.1 / 2019-12-28 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.9.0...v3.9.1) Bug Fixes: * Prevent bisect command from blocking when number of specs exceeds file descriptor limit on OSX or Linux. (Benoit Tigeot, #2669) * Prevent warnings being issued on Ruby 2.7.0. (Jon Rowe, #2680) ### 3.9.0 / 2019-10-07 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.2...v3.9.0) Enhancements: * Improve the handling of errors during loading support files, if a file errors before loading specs, RSpec will now skip loading the specs. (David Rodríguez, #2568) * Add support for --example-matches to run examples by regular expression. (Sam Joseph, Matt Rider, @okothkongo1, #2586) * Add `did_you_mean` suggestions for file names encountering a `LoadError` outside of examples. (@obromios, #2601) * Add a minimalist quick fix style formatter, only outputs failures as `file:line:message`. (Romain Tartière, #2614) * Convert string number values to integer when used for `RSpec::Configuration#fail_fast` (Viktor Fonic, #2634) * Issue warning when invalid values are used for `RSpec::Configuration#fail_fast` (Viktor Fonic, #2634) * Add support for running the Rake task in a clean environment. (Jon Rowe, #2632) * Indent messages by there example group / example in the documentation formatter. (Samuel Williams, #2649) ### 3.8.2 / 2019-06-29 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.1...v3.8.2) Bug Fixes: * Fix `config.define_derived_metadata` so that cascades are not triggered until metadata has been assigned to the example or example group (Myron Marston, #2635). ### 3.8.1 / 2019-06-13 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.0...v3.8.1) Bug Fixes: * Handle RSpec description(s) with japanese chars in CP932 encoded files. (Benoit Tigeot, #2575) * When defining `let` methods that overwrite an existing method, prevent a warning being issued by removing the old definition. (Jon Rowe, #2593) * Prevent warning on Ruby 2.6.0-rc1 (Keiji Yoshimi, #2582) * Fix `config.define_derived_metadata` so that it supports cascades. (Myron Marston, #2630). ### 3.8.0 / 2018-08-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0) Enhancements: * Improve shell escaping used by `RSpec::Core::RakeTask` and `--bisect` so that it works on `Pathname` objects. (Andrew Vit, #2479) * Nicely format errors encountered while loading files specified by `--require` option. (Myron Marston, #2504) * Significantly improve the performance of `--bisect` on platforms that support forking by replacing the shell-based runner with one that uses forking so that RSpec and the application environment can be booted only once, instead of once per spec run. (Myron Marston, #2511) * Provide a configuration API to pick which bisect runner is used for `--bisect`. Pick a runner via `config.bisect_runner = :shell` or `config.bisect_runner = :fork` in a file loaded by a `--require` option passed at the command line or set in `.rspec`. (Myron Marston, #2511) * Support the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/) for the global options file. `~/.rspec` is still supported when no options file is found in `$XDG_CONFIG_HOME/rspec/options` (Magnus Bergmark, #2538) * Extract `RSpec.world.prepare_example_filtering` that sets up the example filtering for custom RSpec runners. (Oleg Pudeyev, #2552) Bug Fixes: * Prevent an `ArgumentError` when truncating backtraces with two identical backtraces. (Systho, #2515, Benoit Tigeot, #2539) ### 3.7.1 / 2018-01-02 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.0...v3.7.1) Bug Fixes: * Work around duplicate config hook regression introduced by Ruby 2.5's lazy proc allocation. (Myron Marston, #2497) ### 3.7.0 / 2017-10-17 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.6.0...v3.7.0) Enhancements: * Add `-n` alias for `--next-failure`. (Ian Ker-Seymer, #2434) * Improve compatibility with `--enable-frozen-string-literal` option on Ruby 2.3+. (Pat Allan, #2425, #2427, #2437) * Do not run `:context` hooks for example groups that have been skipped. (Devon Estes, #2442) * Add `errors_outside_of_examples_count` to the JSON formatter. (Takeshi Arabiki, #2448) Bug Fixes: * Improve compatibility with frozen string literal flag. (#2425, Pat Allan) ### 3.6.0 / 2017-05-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.6.0.beta2...v3.6.0) Enhancements: * Add seed information to JSON formatter output. (#2388, Mitsutaka Mimura) * Include example id in the JSON formatter output. (#2369, Xavier Shay) * Respect changes to `config.output_stream` after formatters have been setup. (#2401, #2419, Ilya Lavrov) Bug Fixes: * Delay formatter loading until the last minute to allow accessing the reporter without triggering formatter setup. (Jon Rowe, #2243) * Ensure context hook failures running before an example can access the reporter. (Jon Jensen, #2387) * Multiple fixes to allow using the runner multiple times within the same process: `RSpec.clear_examples` resets the formatter and no longer clears shared examples, and streams can be used across multiple runs rather than being closed after the first. (#2368, Xavier Shay) * Prevent unexpected `example_group_finished` notifications causing an error. (#2396, VTJamie) * Fix bugs where `config.when_first_matching_example_defined` hooks would fire multiple times in some cases. (Yuji Nakayama, #2400) * Default `last_run_status` to "unknown" when the `status` field in the persistence file contains an unrecognized value. (#2360, matrinox) * Prevent `let` from defining an `initialize` method. (#2414, Jon Rowe) ### 3.6.0.beta2 / 2016-12-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.6.0.beta1...v3.6.0.beta2) Enhancements: * Include count of errors occurring outside examples in default summaries. (#2351, Jon Rowe) * Warn when including shared example groups recursively. (#2356, Jon Rowe) * Improve failure snippet syntax highlighting with CodeRay to highlight RSpec "keywords" like `expect`. (#2358, Myron Marston) ### 3.6.0.beta1 / 2016-10-09 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.4...v3.6.0.beta1) Enhancements: * Warn when duplicate shared examples definitions are loaded due to being defined in files matching the spec pattern (e.g. `_spec.rb`) (#2278, Devon Estes) * Improve metadata filtering so that it can match against any object that implements `===` instead of treating regular expressions as special. (Myron Marston, #2294) * Improve `rspec -v` so that it prints out the versions of each part of RSpec to prevent confusion. (Myron Marston, #2304) * Add `config.fail_if_no_examples` option which causes RSpec to fail if no examples are found. (Ewa Czechowska, #2302) * Nicely format errors encountered while loading spec files. (Myron Marston, #2323) * Improve the API for enabling and disabling color output (Josh Justice, #2321): * Automatically enable color if the output is a TTY, since color is nearly always desirable if the output can handle it. * Introduce new CLI flag to force color on (`--force-color`), even if the output is not a TTY. `--no-color` continues to work as well. * Introduce `config.color_mode` for configuring the color from Ruby. `:automatic` is the default and will produce color if the output is a TTY. `:on` forces it on and `:off` forces it off. ### 3.5.4 / 2016-09-30 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.3...v3.5.4) Bug Fixes: * Remove accumulated `ExampleGroup` constants when reseting RSpec, preventing a memory leak. (TravisSpangle, #2328) ### 3.5.3 / 2016-09-02 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.2...v3.5.3) Bug Fixes: * When applying shared group metadata to a host group, overwrite conflicting keys if the value in the host group was inherited from a parent group instead of being specified at that level. (Myron Marston, #2307) * Handle errors in `:suite` hooks and provide the same nicely formatted output as errors that happen in examples. (Myron Marston, #2316) * Set the exit status to non-zero when an error occurs in an `after(:context)` hook. (Myron Marston, #2320) ### 3.5.2 / 2016-07-28 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.1...v3.5.2) Bug Fixes: * Wait to report `example_finished` until the example's `execution_result` has been completely filled in. (Myron Marston, #2291) * Make sure example block is still available when using `duplicate_with` to clone examples. (bootstraponline, #2298) * Don't include the default `--pattern` in the Rake task when `rspec_opts` specifies its own. (Jon Rowe, #2305) ### 3.5.1 / 2016-07-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0...v3.5.1) Bug Fixes: * Ensure that config hooks that are added to existing example groups are added only once. (Eugene Kenny, #2280) ### 3.5.0 / 2016-07-01 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0.beta4...v3.5.0) Enhancements: * Include any `SPEC_OPTS` in reproduction command printed at the end of a bisect run. (Simon Coffey, #2274) Bug Fixes: * Handle `--bisect` in `SPEC_OPTS` environment variable correctly so as to avoid infinite recursion. (Simon Coffey, #2271) ### 3.5.0.beta4 / 2016-06-05 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0.beta3...v3.5.0.beta4) Enhancements: * Filter out bundler stackframes from backtraces by default, since Bundler 1.12 now includes its own frames in stack traces produced by using `bundle exec`. (Myron Marston, #2240) * HTML Formatter uses exception presenter to get failure message for consistency with other formatters. (@mrageh, #2222) * Load spec files in the order of the directories or files passed at the command line, making it easy to make some specs run before others in a one-off manner. For example, `rspec spec/unit spec/acceptance --order defined` will run unit specs before acceptance specs. (Myron Marston, #2253) * Add new `config.include_context` API for configuring global or filtered inclusion of shared contexts in example groups. (Myron Marston, #2256) * Add new `config.shared_context_metadata_behavior = :apply_to_host_groups` option, which causes shared context metadata to be inherited by the metadata hash of all host groups and examples instead of configuring implicit auto-inclusion based on the passed metadata. (Myron Marston, #2256) Bug Fixes: * Fix `--bisect` so it works on large spec suites that were previously triggering "Argument list too long errors" due to all the spec locations being passed as CLI args. (Matt Jones, #2223). * Fix deprecated `:example_group`-based filtering so that it properly applies to matching example groups. (Myron Marston, #2234) * Fix `NoMethodError` caused by Java backtraces on JRuby. (Michele Piccirillo, #2244) ### 3.5.0.beta3 / 2016-04-02 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0.beta2...v3.5.0.beta3) Enhancements: * Add new `config.filter_run_when_matching` API, intended to replace the combination of `config.filter_run` and `config.run_all_when_everything_filtered` (Myron Marston, #2206) Bug Fixes: * Use the encoded string logic for source extraction. (Jon Rowe, #2183) * Fix rounding issue in duration formatting helper. (Fabersky, Jon Rowe, #2208) * Fix failure snippet extraction so that `def-end` snippets ending with `end`-only line can be extracted properly. (Yuji Nakayama, #2215) ### 3.5.0.beta2 / 2016-03-10 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0.beta1...v3.5.0.beta2) Enhancements: * Remove unneeded `:execution_result` example group metadata, saving a bit of memory. (Myron Marston, #2172) * Apply hooks registered with `config` to previously defined groups. (Myron Marston, #2189) * `RSpec::Core::Configuration#reporter` is now public API under SemVer. (Jon Rowe, #2193) * Add new `config.when_first_matching_example_defined` hook. (Myron Marston, #2175) ### 3.5.0.beta1 / 2016-02-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.4...v3.5.0.beta1) Enhancements: * Add `RSpec::Core::ExampleGroup.currently_executing_a_context_hook?`, primarily for use by rspec-rails. (Sam Phippen, #2131) Bug Fixes: * Ensure `MultipleExceptionError` does not contain a recursive reference to itself. (Sam Phippen, #2133) ### 3.4.4 / 2016-03-09 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.3...v3.4.4) Bug Fixes: * Fix `RSpec::Core::RakeTask` so that it works with Rake 11. (Travis Grathwell, #2197) ### 3.4.3 / 2016-02-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.2...v3.4.3) Bug Fixes: * Prevent a `TypeError` from occurring when running via the rake task when Ruby crashes. (Patrik Wenger, #2161) * Only consider example and group declaration lines from a specific file when applying line number filtering, instead of considering all declaration lines from all spec files. (Myron Marston, #2170) * Fix failure snippet extraction so that snippets that contain `do-end` style block and end with `end`-only line can be extracted properly. (Yuji Nakayama, #2173) * Prevent infinite recursion when an exception is caused by itself. (Jon Rowe, #2128) ### 3.4.2 / 2016-01-26 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.1...v3.4.2) Bug Fixes: * Fix `rspec --profile` when an example calls `abort` or `exit`. (Bradley Schaefer, #2144) * Fix `--drb` so that when no DRb server is running, it prevents the DRb connection error from being listed as the cause of all expectation failures. (Myron Marston, #2156) * Fix syntax highlighter so that it works when the `coderay` gem is installed as a rubygem but not already available on your load path (as happens when you use bundler). (Myron Marston, #2159) ### 3.4.1 / 2015-11-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.0...v3.4.1) Bug Fixes: * Fix backtrace formatter to handle backtraces that are `nil`. (Myron Marston, #2118) ### 3.4.0 / 2015-11-11 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.3.2...v3.4.0) Enhancements: * Combine multiple `--pattern` arguments making them equivalent to `--pattern=1,2,...,n`. (Jon Rowe, #2002) * Improve `inspect` and `to_s` output for `RSpec::Core::Example` objects, replacing Ruby's excessively verbose output. (Gavin Miller, #1922) * Add `silence_filter_announcements` configuration option. (David Raffensperger, #2007) * Add optional `example_finished` notification to the reporter protocol for when you don't care about the example outcome. (Jon Rowe, #2013) * Switch `--bisect` to a recursion-based bisection algorithm rather than a permutation-based one. This better handles cases where an example depends upon multiple other examples instead of just one and minimizes the number of runs necessary to determine that an example set cannot be minimized further. (Simon Coffey, #1997) * Allow simple filters (e.g. `:symbol` key only) to be triggered by truthey values. (Tim Mertens, #2035) * Remove unneeded warning about need for `ansicon` on Windows when using RSpec's `--color` option. (Ashley Engelund, #2038) * Add option to configure RSpec to raise errors when issuing warnings. (Jon Rowe, #2052) * Append the root `cause` of a failure or error to the printed failure output when a `cause` is available. (Adam Magan) * Stop rescuing `NoMemoryError`, `SignalExcepetion`, `Interrupt` and `SystemExit`. It is dangerous to interfere with these. (Myron Marston, #2063) * Add `config.project_source_dirs` setting which RSpec uses to determine if a backtrace line comes from your project source or from some external library. It defaults to `spec`, `lib` and `app` but can be configured differently. (Myron Marston, #2088) * Improve failure line detection so that it looks for the failure line in any project source directory instead of just in the spec file. In addition, if no backtrace lines can be found from a project source file, we fall back to displaying the source of the first backtrace line. This should virtually eliminate the "Unable to find matching line from backtrace" messages. (Myron Marston, #2088) * Add support for `:extra_failure_lines` example metadata that will be appended to the failure output. (bootstraponline, #2092). * Add `RSpec::Core::Example#duplicate_with` to produce new examples with cloned metadata. (bootstraponline, #2098) * Add `RSpec::Core::Configuration#on_example_group_definition` to register hooks to be invoked when example groups are created. (bootstraponline, #2094) * Add `add_example` and `remove_example` to `RSpec::Core::ExampleGroup` to allow manipulating an example groups examples. (bootstraponline, #2095) * Display multiline failure source lines in failure output when Ripper is available (MRI >= 1.9.2, and JRuby >= 1.7.5 && < 9.0.0.0.rc1). (Yuji Nakayama, #2083) * Add `max_displayed_failure_line_count` configuration option (defaults to 10). (Yuji Nakayama, #2083) * Enhance `fail_fast` option so it can take a number (e.g. `--fail-fast=3`) to force the run to abort after the specified number of failures. (Jack Scotti, #2065) * Syntax highlight the failure snippets in text formatters when `color` is enabled and the `coderay` gem is installed on a POSIX system. (Myron Marston, #2109) Bug Fixes: * Lock `example_status_persistence_file` when reading from and writing to it to prevent race conditions when multiple processes try to use it. (Ben Woosley, #2029) * Fix regression in 3.3 that caused spec file names with square brackets in them (such as `1[]_spec.rb`) to not be loaded properly. (Myron Marston, #2041) * Fix output encoding issue caused by ASCII literal on 1.9.3 (Jon Rowe, #2072) * Fix requires in `rspec/core/rake_task.rb` to avoid double requires seen by some users. (Myron Marston, #2101) ### 3.3.2 / 2015-07-15 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.3.1...v3.3.2) Bug Fixes: * Fix formatters to handle exceptions for which `backtrace` returns `nil`. (Myron Marston, #2023) * Fix duplicate formatter detection so that it allows subclasses of formatters to be added. (Sebastián Tello, #2019) ### 3.3.1 / 2015-06-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.3.0...v3.3.1) Bug Fixes: * Correctly run `before(:suite)` (and friends) in the context of an example group instance, thus making the expected RSpec environment available. (Jon Rowe, #1986) ### 3.3.0 / 2015-06-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.3...v3.3.0) Enhancements: * Expose the reporter used to run examples via `RSpec::Core::Example#reporter`. (Jon Rowe, #1866) * Make `RSpec::Core::Reporter#message` a public supported API. (Jon Rowe, #1866) * Allow custom formatter events to be published via `RSpec::Core::Reporter#publish(event_name, hash_of_attributes)`. (Jon Rowe, #1869) * Remove dependency on the standard library `Set` and replace with `RSpec::Core::Set`. (Jon Rowe, #1870) * Assign a unique id to each example and group so that they can be uniquely identified, even for shared examples (and similar situations) where the location isn't unique. (Myron Marston, #1884) * Use the example id in the rerun command printed for failed examples when the location is not unique. (Myron Marston, #1884) * Add `config.example_status_persistence_file_path` option, which is used to persist the last run status of each example. (Myron Marston, #1888) * Add `:last_run_status` metadata to each example, which indicates what happened the last time an example ran. (Myron Marston, #1888) * Add `--only-failures` CLI option which filters to only the examples that failed the last time they ran. (Myron Marston, #1888) * Add `--next-failure` CLI option which allows you to repeatedly focus on just one of the currently failing examples, then move on to the next failure, etc. (Myron Marston, #1888) * Make `--order random` ordering stable, so that when you rerun a subset with a given seed, the examples will be order consistently relative to each other. (Myron Marston, #1908) * Set example group constant earlier so errors when evaluating the context include the example group name (Myron Marson, #1911) * Make `let` and `subject` threadsafe. (Josh Cheek, #1858) * Add version information into the JSON formatter. (Mark Swinson, #1883) * Add `--bisect` CLI option, which will repeatedly run your suite in order to isolate the failures to the smallest reproducible case. (Myron Marston, #1917) * For `config.include`, `config.extend` and `config.prepend`, apply the module to previously defined matching example groups. (Eugene Kenny, #1935) * When invalid options are parsed, notify users where they came from (e.g. `.rspec` or `~/.rspec` or `ENV['SPEC_OPTS']`) so they can easily find the source of the problem. (Myron Marston, #1940) * Add pending message contents to the json formatter output. (Jon Rowe, #1949) * Add shared group backtrace to the output displayed by the built-in formatters for pending examples that have been fixed. (Myron Marston, #1946) * Add support for `:aggregate_failures` metadata. Tag an example or group with this metadata and it'll use rspec-expectations' `aggregate_failures` feature to allow multiple failures in an example and list them all, rather than aborting on the first failure. (Myron Marston, #1946) * When no formatter implements #message add a fallback to prevent those messages being lost. (Jon Rowe, #1980) * Profiling examples now takes into account time spent in `before(:context)` hooks. (Denis Laliberté, Jon Rowe, #1971) * Improve failure output when an example has multiple exceptions, such as one from an `it` block and one from an `after` block. (Myron Marston, #1985) Bug Fixes: * Handle invalid UTF-8 strings within exception methods. (Benjamin Fleischer, #1760) * Fix Rake Task quoting of file names with quotes to work properly on Windows. (Myron Marston, #1887) * Fix `RSpec::Core::RakeTask#failure_message` so that it gets printed when the task failed. (Myron Marston, #1905) * Make `let` work properly when defined in a shared context that is applied to an individual example via metadata. (Myron Marston, #1912) * Ensure `rspec/autorun` respects configuration defaults. (Jon Rowe, #1933) * Prevent modules overriding example group defined methods when included, prepended or extended by config defined after an example group. (Eugene Kenny, #1935) * Fix regression which caused shared examples to be mistakenly run when specs where filtered to a particular location. (Ben Axnick, #1963) * Fix time formatting logic so that it displays 70 seconds as "1 minute, 10 seconds" rather than "1 minute, 1 second". (Paul Brennan, #1984) * Fix regression where the formatter loader would allow duplicate formatters. (Jon Rowe, #1990) ### 3.2.3 / 2015-04-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.2...v3.2.3) Bug Fixes: * Fix how the DSL methods are defined so that RSpec is compatible with gems that define methods of the same name on `Kernel` (such as the `its-it` gem). (Alex Kwiatkowski, Ryan Ong, #1907) * Fix `before(:context) { skip }` so that it does not wrongly cause the spec suite to exit with a non-zero status when no examples failed. (Myron Marston, #1926) ### 3.2.2 / 2015-03-11 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.1...v3.2.2) Bug Fixes: * Fix regression in 3.2.0 that allowed tag-filtered examples to run even if there was a location filter applied to the spec file that was intended to limit the file to other examples. (#1894, Myron Marston) ### 3.2.1 / 2015-02-23 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.2.0...v3.2.1) Bug Fixes: * Notify start-of-run seed _before_ `start` notification rather than _after_ so that formatters like Fuubar work properly. (Samuel Esposito, #1882) ### 3.2.0 / 2015-02-03 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.7...v3.2.0) Enhancements: * Improve the `inspect` output of example groups. (Mike Dalton, #1687) * When rake task fails, only output the command if `verbose` flag is set. (Ben Snape, #1704) * Add `RSpec.clear_examples` as a clear way to reset examples in between spec runs, whilst retaining user configuration. (Alexey Fedorov, #1706) * Reduce string allocations when defining and running examples by 70% and 50% respectively. (Myron Marston, #1738) * Removed dependency on pathname from stdlib. (Sam Phippen, #1703) * Improve the message presented when a user hits Ctrl-C. (Alex Chaffee #1717, #1742) * Improve shared example group inclusion backtrace displayed in failed example output so that it works for all methods of including shared example groups and shows all inclusion locations. (Myron Marston, #1763) * Issue seed notification at start (as well as the end) of the reporter run. (Arlandis Word, #1761) * Improve the documentation of around hooks. (Jim Kingdon, #1772) * Support prepending of modules into example groups from config and allow filtering based on metadata. (Arlandis Word, #1806) * Emit warnings when `:suite` hooks are registered on an example group (where it has always been ignored) or are registered with metadata (which has always been ignored). (Myron Marston, #1805) * Provide a friendly error message when users call RSpec example group APIs (e.g. `context`, `describe`, `it`, `let`, `before`, etc) from within an example where those APIs are unavailable. (Myron Marston, #1819) * Provide a friendly error message when users call RSpec example APIs (e.g. `expect`, `double`, `stub_const`, etc) from within an example group where those APIs are unavailable. (Myron Marston, #1819) * Add new `RSpec::Core::Sandbox.sandboxed { }` API that facilitates testing RSpec with RSpec, allowing you to define example groups and example from within an example without affecting the global `RSpec.world` state. (Tyler Ball, 1808) * Apply line-number filters only to the files they are scoped to, allowing you to mix filtered and unfiltered files. (Myron Marston, #1839) * When dumping pending examples, include the failure details so that you don't have to un-pend the example to see it. (Myron Marston, #1844) * Make `-I` option support multiple values when separated by `File::PATH_SEPARATOR`, such as `rspec -I foo:bar`. This matches the behavior of Ruby's `-I` option. (Fumiaki Matsushima, #1855). * Treat each example as having a singleton example group for the purposes of applying metadata-based features that normally apply to example groups to individually tagged examples. For example, `RSpec.shared_context "Uses redis", :uses_redis` will now apply to individual examples tagged with `:uses_redis`, as will `config.include RedisHelpers, :uses_redis`, and `config.before(:context, :uses_redis) { }`, etc. (Myron Marston, #1749) Bug Fixes: * When assigning generated example descriptions, surface errors raised by `matcher.description` in the example description. (Myron Marston, #1771) * Don't consider expectations from `after` hooks when generating example descriptions. (Myron Marston, #1771) * Don't apply metadata-filtered config hooks to examples in groups with matching metadata when those examples override the parent metadata value to not match. (Myron Marston, #1796) * Fix `config.expect_with :minitest` so that `skip` uses RSpec's implementation rather than Minitest's. (Jonathan Rochkind, #1822) * Fix `NameError` caused when duplicate example group aliases are defined and the DSL is not globally exposed. (Aaron Kromer, #1825) * When a shared example defined in an external file fails, use the host example group (from a loaded spec file) for the re-run command to ensure the command will actually work. (Myron Marston, #1835) * Fix location filtering to work properly for examples defined in a nested example group within a shared example group defined in an external file. (Bradley Schaefer, Xavier Shay, Myron Marston, #1837) * When a pending example fails (as expected) due to a mock expectation, set `RSpec::Core::Example::ExecutionResult#pending_exception` -- previously it was not being set but should have been. (Myron Marston, #1844) * Fix rake task to work when `rspec-core` is installed in a directory containing a space. (Guido Günther, #1845) * Fix regression in 3.1 that caused `describe Regexp` to raise errors. (Durran Jordan, #1853) * Fix regression in 3.x that caused the profile information to be printed after the summary. (Max Lincoln, #1857) * Apply `--seed` before loading `--require` files so that required files can access the provided seed. (Myron Marston, #1745) * Handle `RSpec::Core::Formatters::DeprecationFormatter::FileStream` being reopened with an IO stream, which sometimes happens with spring. (Kevin Mook, #1757) ### 3.1.7 / 2014-10-11 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.6...v3.1.7) Bug Fixes: * Fix `Metadata.relative_path` so that for a current directory of `/foo/bar`, `/foo/bar_1` is not wrongly converted to `._1`. (Akos Vandra, #1730) * Prevent constant lookup mistakenly finding `RSpec::ExampleGroups` generated constants on 1.9.2 by appending a trailing `_` to the generated names. (Jon Rowe, #1737) * Fix bug in `:pending` metadata. If it got set in any way besides passing it as part of the metadata literal passed to `it` (such as by using `define_derived_metadata`), it did not have the desired effect, instead marking the example as `:passed`. (Myron Marston, #1739) ### 3.1.6 / 2014-10-08 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.5...v3.1.6) Bug Fixes: * Fix regression in rake task pattern handling, that prevented patterns that were relative from the current directory rather than from `spec` from working properly. (Myron Marston, #1734) * Prevent rake task from generating duplicate load path entries. (Myron Marston, #1735) ### 3.1.5 / 2014-09-29 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.4...v3.1.5) Bug Fixes: * Fix issue with the rake task incorrectly escaping strings on Windows. (Jon Rowe #1718) * Support absolute path patterns. While this wasn't officially supported previously, setting `rake_task.pattern` to an absolute path pattern in RSpec 3.0 and before worked since it delegated to `FileList` internally (but now just forwards the pattern on to the `rspec` command). (Myron Marston, #1726) ### 3.1.4 / 2014-09-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.3...v3.1.4) Bug Fixes: * Fix implicit `subject` when using `describe false` or `describe nil` so that it returns the provided primitive rather than the string representation. (Myron Marston, #1710) * Fix backtrace filtering to allow code in subdirectories of your current working directory (such as vendor/bundle/...) to be filtered from backtraces. (Myron Marston, #1708) ### 3.1.3 / 2014-09-15 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.2...v3.1.3) Bug Fixes: * Fix yet another regression in rake task pattern handling, to allow `task.pattern = FileList["..."]` to work. That was never intended to be supported but accidentally worked in 3.0 and earlier. (Myron Marston, #1701) * Fix pattern handling so that files are normalized to absolute paths before subtracting the `--exclude-pattern` matched files from the `--pattern` matched files so that it still works even if the patterns are in slightly different forms (e.g. one starting with `./`). (Christian Nelson, #1698) ### 3.1.2 / 2014-09-08 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.1...v3.1.2) Bug Fixes: * Fix another regression in rake task pattern handling, so that patterns that start with `./` still work. (Christian Nelson, #1696) ### 3.1.1 / 2014-09-05 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.1.0...v3.1.1) Bug Fixes: * Fix a regression in rake task pattern handling, so that `rake_task.pattern = array` works again. While we never intended to support array values (or even knew that worked!), the implementation from 3.0 and earlier used `FileList` internally, which allows arrays. The fix restores the old behavior. (Myron Marston, #1694) ### 3.1.0 / 2014-09-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.4...v3.1.0) Enhancements: * Update files generated by `rspec --init` so that warnings are enabled in commented out section of `spec_helper` rather than `.rspec` so users have to consciously opt-in to the setting. (Andrew Hooker, #1572) * Update `spec_helper` generated by `rspec --init` so that it sets the new rspec-expectations `include_chain_clauses_in_custom_matcher_descriptions` config option (which will be on by default in RSpec 4) and also sets the rspec-mocks `verify_partial_doubles` option (which will also default to on in RSpec 4). (Myron Marston, #1647) * Provide an `inspect` output for example procsy objects (used in around hooks) that doesn't make them look like procs. (Jon Rowe, #1620) * Remove a few unneeded `require` statements from `rspec/core/rake_task.rb`, making it even more lighterweight. (Myron Marston, #1640) * Allow rspec-core to be used when neither rspec-mocks or rspec-expectations are installed, without requiring any user configuration. (Sam Phippen, Myron Marston, #1615) * Don't filter out gems from backtraces by default. (The RSpec gems will still be filtered). User feedback has indicated that including gems in default backtraces will be useful. (Myron Marston, #1641) * Add new `config.filter_gems_from_backtrace "rack", "rake"` API to easily filter the named gems from backtraces. (Myron Marston, #1682) * Fix default backtrace filters so that the RSpec binary is excluded when installing RSpec as a bundler `:git` dependency. (Myron Marston, #1648) * Simplify command generated by the rake task so that it no longer includes unnecessary `-S`. (Myron Marston, #1559) * Add `--exclude-pattern` CLI option, `config.exclude_pattern =` config option and `task.exclude_pattern =` rake task config option. Matching files will be excluded. (John Gesimondo, Myron Marston, #1651, #1671) * When an around hook fails to execute the example, mark it as pending (rather than passing) so the user is made aware of the fact that the example did not actually run. (Myron Marston, #1660) * Remove dependency on `FileUtils` from the standard library so that users do not get false positives where their code relies on it but they are not requiring it. (Sam Phippen, #1565) Bug Fixes: * Fix rake task `t.pattern =` option so that it does not run all specs when it matches no files, by passing along a `--pattern` option to the `rspec` command, rather than resolving the file list and passing along the files individually. (Evgeny Zislis, #1653) * Fix rake task default pattern so that it follows symlinks properly. (Myron Marston, #1672) * Fix default pattern used with `rspec` command so that it follows symlinks properly. (Myron Marston, #1672) * Change how we assign constant names to example group classes so that it avoids a problem with `describe "Core"`. (Daniela Wellisz, #1679) * Handle rendering exceptions that have a different encoding than that of their original source file. (Jon Rowe, #1681) * Allow access to message_lines without colour for failed examples even when they're part of a shared example group. (tomykaira, #1689) ### 3.0.4 / 2014-08-14 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.3...v3.0.4) Bug Fixes: * Fix processing order of CLI options so that if `config.files_to_run` is accessed from a file loaded by `--require`, `--pattern` is still applied. (Myron Marston, #1652) * Fix `config.pattern=` so that it still takes affect even if `config.files_to_run` has already been accessed. (Myron Marston, #1652) ### 3.0.3 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.2...v3.0.3) Bug Fixes: * Properly convert both parts of a description into strings before concatenation. (@nicklink483, #1636) * Exclude the working directory when figuring out folders to ignore. (Jon Rowe, Myron Marston, #1616) * Allow `::RSpec::Core::Notifications::FailedExampleNotification#message_lines` to be accessed without a colouriser. (@tomykaira, #1637) ### 3.0.2 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.1...v3.0.2) Bug Fixes: * Fix regression in CLI option handling that prevented `--tag slow` passed at the command line from overriding `--tag ~slow` in `.rspec`. (Colin Jones, #1602) * Fix metadata `:example_group` deprecation warning so that it gets issued at the call site of the configuration that specified it as a filter rather than later when an example group is defined. (Myron Marston, #1562) * Make the line that is printed when a shared example group fails indicating where the concrete example group is white, separating it from the stack trace that is produced for the failure. (Sam Phippen, Jon Rowe, #1606) ### 3.0.1 / 2014-06-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0...v3.0.1) Bug Fixes: * Fix a couple ruby warnings caused by rspec-core when loaded. (Prem Sichanugrist, #1584) * Example groups named `Config` will no longer cause a Ruby warning to be issued. (Jimmy Cuadra, #1580) ### 3.0.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.rc1...v3.0.0) Bug Fixes: * Fix `BaseTextFormatter` so that it does not re-close a closed output stream. (Myron Marston) * Fix regression in metadata that caused the metadata hash of a top-level example group to have a `:parent_example_group` key even though it has no parent example group. (Myron Marston) Enhancements: * Alter the default `spec_helper.rb` to no longer recommend `config.full_backtrace = true` see #1536 for discussion. (Jon Rowe) ### 3.0.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.beta2...v3.0.0.rc1) Breaking Changes for 3.0.0: * Change `described_class` so that in a nested group like `describe MyClass`, it returns `MyClass` rather than the outer group's described class. (Myron Marston) * Refactor filter manager so that it no longer subclasses Hash and has a tighter, more domain-specific interface. (Sergey Pchelincev) * Remove legacy colours definitions from `BaseTextFormatter`. (Jon Rowe) * Remove console color definitions from `BaseTextFormatter`. (Jon Rowe) * Restructure example group metadata so that the computed keys are exposed directly off of the metadata hash rather than being on a nested `:example_group` subhash. In addition, the parent example group metadata is now available as `[:parent_example_group]` rather than `[:example_group][:example_group]`. Deprecated access via the old key structure is still provided. (Myron Marston) * Remove `:describes` metadata key. It duplicates `:described_class` for no good reason. Deprecated access via `:describes` is still provided. (Myron Marston) * Rename `:example_group_block` metadata key to `:block`. (Myron Marston) * Remove deprecated `RSpec::Core::Example#options`. (Myron Marston) * Move `BaseTextFormatter#colorize_summary` to `SummaryNotification#colorize_with` (Jon Rowe). * `describe some_hash` treated `some_hash` as metadata in RSpec 2.x but will treat it as the described object in RSpec 3.0. Metadata must always come after the description args. (Myron Marston) * Remove deprecated `display_name` alias of `ExampleGroup.description`. (Myron Marston) * Remove deprecated `describes` alias of `ExampleGroup.described_class`. (Myron Marston) * Remove deprecated `RSpec::Core::ExampleGroup.alias_it_behaves_like_to`. Use `RSpec::Core::Configuration#alias_it_behaves_like_to` instead. (Myron Marston) * Remove deprecated `RSpec::Core::ExampleGroup.alias_example_to`. Use `RSpec::Core::Configuration#alias_example_to` instead. (Myron Marston) * Removed `focused` example alias and change example/group aliases `fit`, `focus`, `fcontext` and `fdescribe` to no longer include `:focused => true` metadata. They only contain `:focus => true` metadata now. This means that you will need to filter them with `filter_run :focus`, not `filter_run :focused`. (Myron Marston) * Remove `--line-number` filtering. It's semantically dubious since it's a global filter (potentially applied to multiple files) but there's no meaningful connection between the same line number in multiple files. Instead use the `rspec path/to/spec.rb:23:46` form, which is terser and makes more sense as it is scoped to a file. (Myron Marston) * Remove `--default_path` as an alias for `--default-path`. (Jon Rowe) * Remove deprecated `share_examples_for`. There's still `shared_examples` and `shared_examples_for`. (Myron Marston) * Rename `RSpec::Core::Configuration#warnings` to `RSpec::Core::Configuration#warnings?` since it's a boolean flag. (Myron Marston) * RSpec's global state is no longer reset after a spec run. This gives more flexibility to alternate runners to decide when and if they want the state reset. Alternate runners are now responsible for calling this (or doing a similar reset) if they are going to run the spec suite multiple times in the same process. (Sam Phippen) * Merge `RSpec::Core::CommandLine` (never formally declared public) into `RSpec::Core::Runner`. (Myron Marston) * Remove `color_enabled` as an alias of `color`. (Jon Rowe) * Remove `backtrace_cleaner` as an alias of `backtrace_formatter`. (Jon Rowe) * Remove `filename_pattern` as an alias of `pattern`. (Jon Rowe) * Extract support for legacy formatters to `rspec-legacy_formatters`. (Jon Rowe) * `RSpec::Configuration#formatters` now returns a dup to prevent mutation. (Jon Rowe) * Replace `stdlib` as an available expectation framework with `test_unit` and `minitest`. (Aaron Kromer) * Remove backtrace formatting helpers from `BaseTextFormatter`. (Jon Rowe) * Extract profiler support to `ProfileFormatter` and `ProfileNotification`. Formatters should implement `dump_profile` if they wish to respond to `--profile`. (Jon Rowe) * Extract remaining formatter state to reporter and notifications. Introduce `ExamplesNotification` to share information about examples that was previously held in `BaseFormatter`. (Jon Rowe) Enhancements: * Add `config.default_formatter` attribute, which can be used to set a formatter which will only be used if no other formatter is set (e.g. via `--formatter`). (Myron Marston) * Support legacy colour definitions in `LegacyFormatterAdaptor`. (Jon Rowe) * Migrate `execution_result` (exposed by metadata) from a hash to a first-class object with appropriate attributes. `status` is now stored and returned as a symbol rather than a string. It retains deprecated hash behavior for backwards compatibility. (Myron Marston) * Provide console code helper for formatters. (Jon Rowe) * Use raw ruby hashes for the metadata hashes rather than a subclass of a hash. Computed metadata entries are now computed in advance rather than being done lazily on first access. (Myron Marston) * Add `:block` metadata entry to the example metadata, bringing parity with `:block` in the example group metadata. (Myron Marston) * Add `fspecify` and `fexample` as aliases of `specify` and `example` with `:focus => true` metadata for parity with `fit`. (Myron Marston) * Add legacy support for `colorize_summary`. (Jon Rowe) * Restructure runner so it can be more easily customized in a subclass for an alternate runner. (Ben Hoskings) * Document `RSpec::Core::ConfigurationOptions` as an officially supported public API. (Myron Marston) * Add `--deprecation-out` CLI option which directs deprecation warnings to the named file. (Myron Marston) * Minitest 5 compatability for `expect_with :stdlib` (now available as `expect_with :minitest`). (Xavier Shay) * Reporter now notifies formatters of the load time of RSpec and your specs via `StartNotification` and `SummaryNotification`. (Jon Rowe) * Add `disable_monkey_patching!` config option that disables all monkey patching from whatever pieces of RSpec you use. (Alexey Fedorov) * Add `Pathname` support for setting all output streams. (Aaron Kromer) * Add `config.define_derived_metadata`, which can be used to apply additional metadata to all groups or examples that match a given filter. (Myron Marston) * Provide formatted and colorized backtraces via `FailedExampleNotification` and send `PendingExampleFixedNotifications` when the error is due to a passing spec you expect to fail. (Jon Rowe) * Add `dump_profile` to formatter API to allow formatters to implement support for `--profile`. (Jon Rowe) * Allow colourising text via `ConsoleCodes` with RSpec 'states' (e.g. `:success`, `:failure`) rather than direct colour codes. (Jon Rowe) * Expose `fully_formatted` methods off the formatter notification objects that make it easy for a custom formatter to produce formatted output like rspec-core's. (Myron Marston) Bug Fixes: * Fix `spec_helper.rb` file generated by `rspec --init` so that the recommended settings correctly use the documentation formatter when running one file. (Myron Marston) * Fix ordering problem where descriptions were generated after tearing down mocks, which resulted in unexpected exceptions. (Bradley Schaefer, Aaron Kromer, Andrey Savchenko) * Allow a symbol to be used as an implicit subject (e.g. `describe :foo`). (Myron Marston) * Prevent creating an isolated context (i.e. using `RSpec.describe`) when already inside a context. There is no reason to do this, and it could potentially cause unexpected bugs. (Xavier Shay) * Fix shared example group scoping so that when two shared example groups share the same name at different levels of nested contexts, the one in the nearest context is used. (Myron Marston) * Fix `--warnings` option so that it enables warnings immediately so that it applies to files loaded by `--require`. (Myron Marston) * Issue a warning when you set `config.deprecation_stream` too late for it to take effect because the reporter has already been setup. (Myron Marston) * Add the full `RSpec::Core::Example` interface to the argument yielded to `around` hooks. (Myron Marston) * Line number always takes precendence when running specs with filters. (Xavier Shay) * Ensure :if and :unless metadata filters are treated as a special case and are always in-effect. (Bradley Schaefer) * Ensure the currently running installation of RSpec is used when the rake task shells out to `rspec`, even if a newer version is also installed. (Postmodern) * Using a legacy formatter as default no longer causes an infinite loop. (Xavier Shay) ### 3.0.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.beta1...v3.0.0.beta2) Breaking Changes for 3.0.0: * Make `mock_with` option more strict. Strings are no longer supported (e.g. `mock_with "mocha"`) -- use a symbol instead. Also, unrecognized values will now result in an error rather than falling back to the null mocking adapter. If you want to use the null mocking adapter, use `mock_with :nothing` (as has been documented for a long time). (Myron Marston) * Remove support for overriding RSpec's built-in `:if` and `:unless` filters. (Ashish Dixit) * Custom formatters are now required to call `RSpec::Core::Formatters.register(formatter_class, *notifications)` where `notifications` is the list of events the formatter wishes to be notified about. Notifications are handled by methods matching the names on formatters. This allows us to add or remove notifications without breaking existing formatters. (Jon Rowe) * Change arguments passed to formatters. Rather than passing multiple arguments (which limits are ability to add additional arguments as doing so would break existing formatters), we now pass a notification value object that exposes the same data via attributes. This will allow us to add new bits of data to a notification event without breaking existing formatters. (Jon Rowe) * Remove support for deprecated `:alias` option for `RSpec.configuration.add_setting`. (Myron Marston) * Remove support for deprecated `RSpec.configuration.requires = [...]`. (Myron Marston) * Remove support for deprecated `--formatter` CLI option. (Myron Marston) * Remove support for deprecated `--configure` CLI option. (Myron Marston) * Remove support for deprecated `RSpec::Core::RakeTask#spec_opts=`. (Myron Marston) * An example group level `pending` block or `:pending` metadata now executes the example and cause a failure if it passes, otherwise it will be pending if it fails. The old "never run" behaviour is still used for `xexample`, `xit`, and `xspecify`, or via a new `skip` method or `:skip` metadata option. (Xavier Shay) * After calling `pending` inside an example, the remainder of the example will now be run. If it passes a failure is raised, otherwise the example is marked pending. The old "never run" behaviour is provided a by a new `skip` method. (Xavier Shay) * Pending blocks inside an example have been removed as a feature with no direct replacement. Use `skip` or `pending` without a block. (Xavier Shay) * Pending statement is no longer allowed in `before(:all)` hooks. Use `skip` instead. (Xavier Shay) * Remove `show_failures_in_pending_blocks` configuration option. (Xavier Shay) * Remove support for specifying the documentation formatter using 's', 'n', 'spec' or 'nested'. (Jon Rowe) Enhancements: * Add example run time to JSON formatter output. (Karthik Kastury) * Add more suggested settings to the files generated by `rspec --init`. (Myron Marston) * Add `config.alias_example_group_to`, which can be used to define a new method that defines an example group with the provided metadata. (Michi Huber) * Add `xdescribe` and `xcontext` as shortcuts to skip an example group. (Myron Marston) * Add `fdescribe` and `fcontext` as shortcuts to focus an example group. (Myron Marston) * Don't autorun specs via `#at_exit` by default. `require 'rspec/autorun'` is only needed when running specs via `ruby`, as it always has been. Running specs via `rake` or `rspec` are both unaffected. (Ben Hoskings) * Add `expose_dsl_globally` config option, defaulting to true. When disabled it will remove the monkey patches rspec-core adds to `main` and `Module` (e.g. `describe`, `shared_examples_for`, etc). (Jon Rowe) * Expose RSpec DSL entry point methods (`describe`, `shared_examples_for`, etc) on the `RSpec` constant. Intended for use when `expose_dsl_globally` is set to `false`. (Jon Rowe) * For consistency, expose all example group aliases (including `context`) on the `RSpec` constant. If `expose_dsl_globally` is set to `true`, also expose them on `main` and `Module`. Historically, only `describe` was exposed. (Jon Rowe, Michi Huber) * Add hook scope `:example` as an alias for `:each`, and `:context` as an alias for `:all`. (John Feminella) Bug Fixes: * Fix failure (undefined method `path`) in end-of-run summary when `raise_errors_for_deprecations!` is configured. (Myron Marston) * Issue error when attempting to use `-i` or `--I` on command line, too close to `-I` to be considered short hand for `--init`. (Jon Rowe) * Prevent adding formatters to an output target if the same formatter has already been added to that output. (Alex Peattie) * Allow a matcher-generated example description to be used when the example is pending. (Myron Marston) * Ensure the configured `failure_exit_code` is used by the rake task when there is a failure. (Jon Rowe) * Restore behaviour whereby system exclusion filters take priority over working directory (was broken in beta1). (Jon Rowe) * Prevent RSpec mangling file names that have substrings containing `line_number` or `default_path`. (Matijs van Zuijlen) * Fix failure line detection so that it handles relative file paths (which can happen when running specs through `ruby` using `rspec/autorun`). (Myron Marston, #1829) ### 3.0.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.1...v3.0.0.beta1) Breaking Changes for 3.0.0: * Remove explicit support for 1.8.6. (Jon Rowe) * Remove `RSpec::Core::ExampleGroup#example` and `RSpec::Core::ExampleGroup#running_example` methods. If you need access to the example (e.g. to get its metadata), use a block arg instead. (David Chelimsky) * Remove `TextMateFormatter`, it has been moved to `rspec-tmbundle`. (Aaron Kromer) * Remove RCov integration. (Jon Rowe) * Remove deprecated support for RSpec 1 constructs (Myron Marston): * The `Spec` and `Rspec` constants (rather than `RSpec`). * `Spec::Runner.configure` rather than `RSpec.configure`. * `Rake::SpecTask` rather than `RSpec::Core::RakeTask`. * Remove deprecated support for `share_as`. (Myron Marston) * Remove `--debug` option (and corresponding option on `RSpec::Core::Configuration`). Instead, use `-r` to load whichever debugger gem you wish to use (e.g. `ruby-debug`, `debugger`, or `pry`). (Myron Marston) * Extract Autotest support to a seperate gem. (Jon Rowe) * Raise an error when a `let` or `subject` declaration is accessed in a `before(:all)` or `after(:all)` hook. (Myron Marston) * Extract `its` support to a separate gem. (Peter Alfvin) * Disallow use of a shared example group from sibling contexts, making them fully isolated. 2.14 and 2.99 allowed this but printed a deprecation warning. (Jon Rowe) * Remove `RSpec::Core::Configuration#output` and `RSpec::Core::Configuration#out` aliases of `RSpec::Core::Configuration#output_stream`. (Myron Marston) * Remove legacy ordering APIs deprecated in 2.99.0.beta1. (Myron Marston) Enhancements: * Replace unmaintained syntax gem with coderay gem. (Xavier Shay) * Times in profile output are now bold instead of `failure_color`. (Matthew Boedicker) * Add `--no-fail-fast` command line option. (Gonzalo Rodríguez-Baltanás Díaz) * Runner now considers the local system ip address when running under Drb. (Adrian CB) * JsonFormatter now includes `--profile` information. (Alex / @MasterLambaster) * Always treat symbols passed as metadata args as hash keys with true values. RSpec 2 supported this with the `treat_symbols_as_metadata_keys_with_true_values` but now this behavior is always enabled. (Myron Marston) * Add `--dry-run` option, which prints the formatter output of your suite without running any examples or hooks. (Thomas Stratmann, Myron Marston) * Document the configuration options and default values in the `spec_helper.rb` file that is generated by RSpec. (Parker Selbert) * Give generated example group classes a friendly name derived from the docstring, rather than something like "Nested_2". (Myron Marston) * Avoid affecting randomization of user code when shuffling examples so that users can count on their own seeds working. (Travis Herrick) * Ordering is no longer a single global property of the test suite. Each group can pick an ordering using `:order` metadata. (Andy Lindeman, Sam Phippen, Myron Marston) * Allow named custom ordering strategies to be registered, which can then be used on individual example groups. (Andy Lindeman, Sam Phippen, Myron Marston) Deprecations: * `treat_symbols_as_metadata_keys_with_true_values` is deprecated and no longer has an affect now that the behavior it enabled is always enabled. (Myron Marston) ### 2.99.2 / 2014-08-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.1...v2.99.2) Enhancements: * Improve deprecation warning for RSpec 3 change in `describe ` behavior. (Jon Rowe, #1667) ### 2.99.1 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0...v2.99.1) Bug Fixes: * Add missing deprecation warning for when `RSpec::Core::Runner` is used multiple times in the same process. In 2.x RSpec's global state was automatically cleared between runs but in 3.0 you need to call `RSpec.reset` manually in these situations. (Sam Phippen, #1587) * Prevent deprecation being accidentally issues when doubles used with `be_` matchers due to automatically generated descriptions. (Jon Rowe, #1573) * Load `rspec/core` when loading `rspec/core/rake_task` to ensure we can issue deprecations correctly. (Jon Rowe, #1612) ### 2.99.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.rc1...v2.99.0) Bug Fixes: * Fix `BaseTextFormatter` so that it does not re-close a closed output stream. (Myron Marston) * Use `RSpec::Configuration#backtrace_exclusion_patterns` rather than the deprecated `RSpec::Configuration#backtrace_clean_patterns` when mocking with rr. (David Dollar) ### 2.99.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.beta2...v2.99.0.rc1) Enhancements: * Add `--deprecation-out` CLI option which directs deprecation warnings to the named file. (Myron Marston) * Backport support for `skip` in metadata to skip execution of an example. (Xavier Shay, #1472) * Add `Pathname` support for setting all output streams. (Aaron Kromer) * Add `test_unit` and `minitest` expectation frameworks. (Aaron Kromer) Deprecations: * Deprecate `RSpec::Core::Pending::PendingDeclaredInExample`, use `SkipDeclaredInExample` instead. (Xavier Shay) * Issue a deprecation when `described_class` is accessed from within a nested `describe ` example group, since `described_class` will return the innermost described class in RSpec 3 rather than the outermost described class, as it behaved in RSpec 2. (Myron Marston) * Deprecate `RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS`, `RSpec::Core::FilterManager::STANDALONE_FILTERS` and use of `#empty_without_conditional_filters?` on those filters. (Sergey Pchelincev) * Deprecate `RSpec::Core::Example#options` in favor of `RSpec::Core::Example#metadata`. (Myron Marston) * Issue warning when passing a symbol or hash to `describe` or `context` as the first argument. In RSpec 2.x this would be treated as metadata but in RSpec 3 it'll be treated as the described object. To continue having it treated as metadata, pass a description before the symbol or hash. (Myron Marston) * Deprecate `RSpec::Core::BaseTextFormatter::VT100_COLORS` and `RSpec::Core::BaseTextFormatter::VT100_COLOR_CODES` in favour of `RSpec::Core::BaseTextFormatter::ConsoleCodes::VT100_CODES` and `RSpec::Core::BaseTextFormatter::ConsoleCodes::VT100_CODE_VALUES`. (Jon Rowe) * Deprecate `RSpec::Core::ExampleGroup.display_name` in favor of `RSpec::Core::ExampleGroup.description`. (Myron Marston) * Deprecate `RSpec::Core::ExampleGroup.describes` in favor of `RSpec::Core::ExampleGroup.described_class`. (Myron Marston) * Deprecate `RSpec::Core::ExampleGroup.alias_example_to` in favor of `RSpec::Core::Configuration#alias_example_to`. (Myron Marston) * Deprecate `RSpec::Core::ExampleGroup.alias_it_behaves_like_to` in favor of `RSpec::Core::Configuration#alias_it_behaves_like_to`. (Myron Marston) * Deprecate `RSpec::Core::ExampleGroup.focused` in favor of `RSpec::Core::ExampleGroup.focus`. (Myron Marston) * Add deprecation warning for `config.filter_run :focused` since example aliases `fit` and `focus` will no longer include `:focused` metadata but will continue to include `:focus`. (Myron Marston) * Deprecate filtering by `:line_number` (e.g. `--line-number` from the CLI). Use location filtering instead. (Myron Marston) * Deprecate `--default_path` as an alternative to `--default-path`. (Jon Rowe) * Deprecate `RSpec::Core::Configuration#warnings` in favor of `RSpec::Core::Configuration#warnings?`. (Myron Marston) * Deprecate `share_examples_for` in favor of `shared_examples_for` or just `shared_examples`. (Myron Marston) * Deprecate `RSpec::Core::CommandLine` in favor of `RSpec::Core::Runner`. (Myron Marston) * Deprecate `#color_enabled`, `#color_enabled=` and `#color?` in favour of `#color`, `#color=` and `#color_enabled? output`. (Jon Rowe) * Deprecate `#filename_pattern` in favour of `#pattern`. (Jon Rowe) * Deprecate `#backtrace_cleaner` in favour of `#backtrace_formatter`. (Jon Rowe) * Deprecate mutating `RSpec::Configuration#formatters`. (Jon Rowe) * Deprecate `stdlib` as an available expectation framework in favour of `test_unit` and `minitest`. (Aaron Kromer) Bug Fixes: * Issue a warning when you set `config.deprecation_stream` too late for it to take effect because the reporter has already been setup. (Myron Marston) * `skip` with a block should not execute the block. (Xavier Shay) ### 2.99.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.99.0.beta1...v2.99.0.beta2) Enhancements: * Add `is_expected` for one-liners that read well with the `expect`-based syntax. `is_expected` is simply defined as `expect(subject)` and can be used in an expression like: `it { is_expected.to read_well }`. (Myron Marston) * Backport `skip` from RSpec 3, which acts like `pending` did in RSpec 2 when not given a block, since the behavior of `pending` is changing in RSpec 3. (Xavier Shay) Deprecations: * Deprecate inexact `mock_with` config options. RSpec 3 will only support the exact symbols `:rspec`, `:mocha`, `:flexmock`, `:rr` or `:nothing` (or any module that implements the adapter interface). RSpec 2 did fuzzy matching but this will not be supported going forward. (Myron Marston) * Deprecate `show_failures_in_pending_blocks` config option. To achieve the same behavior as the option enabled, you can use a custom formatter instead. (Xavier Shay) * Add a deprecation warning for the fact that the behavior of `pending` is changing in RSpec 3 -- rather than skipping the example (as it did in 2.x when no block was provided), it will run the example and mark it as failed if no exception is raised. Use `skip` instead to preserve the old behavior. (Xavier Shay) * Deprecate 's', 'n', 'spec' and 'nested' as aliases for documentation formatter. (Jon Rowe) * Deprecate `RSpec::Core::Reporter#abort` in favor of `RSpec::Core::Reporter#finish`. (Jon Rowe) Bug Fixes: * Fix failure (undefined method `path`) in end-of-run summary when `raise_errors_for_deprecations!` is configured. (Myron Marston) * Fix issue were overridding spec ordering from the command line wasn't fully recognised interally. (Jon Rowe) ### 2.99.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.7...v2.99.0.beta1) Enhancements * Block-based DSL methods that run in the context of an example (`it`, `before(:each)`, `after(:each)`, `let` and `subject`) now yield the example as a block argument. (David Chelimsky) * Warn when the name of more than one example group is submitted to `include_examples` and it's aliases. (David Chelimsky) * Add `expose_current_running_example_as` config option for use during the upgrade process when external gems use the deprecated `RSpec::Core::ExampleGroup#example` and `RSpec::Core::ExampleGroup#running_example` methods. (Myron Marston) * Limit spamminess of deprecation messages. (Bradley Schaefer, Loren Segal) * Add `config.raise_errors_for_deprecations!` option, which turns deprecations warnings into errors to surface the full backtrace of the call site. (Myron Marston) Deprecations * Deprecate `RSpec::Core::ExampleGroup#example` and `RSpec::Core::ExampleGroup#running_example` methods. If you need access to the example (e.g. to get its metadata), use a block argument instead. (David Chelimsky) * Deprecate use of `autotest/rspec2` in favour of `rspec-autotest`. (Jon Rowe) * Deprecate RSpec's built-in debugger support. Use a CLI option like `-rruby-debug` (for the ruby-debug gem) or `-rdebugger` (for the debugger gem) instead. (Myron Marston) * Deprecate `RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values = false`. RSpec 3 will not support having this option set to `false`. (Myron Marston) * Deprecate accessing a `let` or `subject` declaration in a `after(:all)` hook. (Myron Marston, Jon Rowe) * Deprecate built-in `its` usage in favor of `rspec-its` gem due to planned removal in RSpec 3. (Peter Alfvin) * Deprecate `RSpec::Core::PendingExampleFixedError` in favor of `RSpec::Core::Pending::PendingExampleFixedError`. (Myron Marston) * Deprecate `RSpec::Core::Configuration#out` and `RSpec::Core::Configuration#output` in favor of `RSpec::Core::Configuration#output_stream`. (Myron Marston) * Deprecate legacy ordering APIs. * You should use `register_ordering(:global)` instead of these: * `RSpec::Core::Configuration#order_examples` * `RSpec::Core::Configuration#order_groups` * `RSpec::Core::Configuration#order_groups_and_examples` * These are deprecated with no replacement because in RSpec 3 ordering is a property of individual example groups rather than just a global property of the entire test suite: * `RSpec::Core::Configuration#order` * `RSpec::Core::Configuration#randomize?` * `--order default` is deprecated in favor of `--order defined` (Myron Marston) ### 2.14.8 / 2014-02-27 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.7...v2.14.8) Bug fixes: * Fix regression with the `textmateformatter` that prevented backtrace links from being clickable. (Stefan Daschek) ### 2.14.7 / 2013-10-29 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.6...v2.14.7) Bug fixes: * Fix regression in 2.14.6 that broke the Fivemat formatter. It depended upon either `example.execution_result[:exception].pending_fixed?` (which was removed in 2.14.6 to fix an issue with frozen error objects) or `RSpec::Core::PendingExampleFixedError` (which was renamed to `RSpec::Core::Pending::PendingExampleFixedError` in 2.8. This fix makes a constant alias for the old error name. (Myron Marston) ### 2.14.6 / 2013-10-15 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.5...v2.14.6) Bug fixes: * Format stringified numbers correctly when mathn library is loaded. (Jay Hayes) * Fix an issue that prevented the use of frozen error objects. (Lars Gierth) ### 2.14.5 / 2013-08-13 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.4...v2.14.5) Bug fixes: * Fix a `NoMethodError` that was being raised when there were no shared examples or contexts declared and `RSpec.world.reset` is invoked. (thepoho, Jon Rowe, Myron Marston) * Fix a deprecation warning that was being incorrectly displayed when `shared_examples` are declared at top level in a `module` scope. (Jon Rowe) * Fix after(:all) hooks so consecutive (same context) scopes will run even if one raises an error. (Jon Rowe, Trejkaz) * JsonFormatter no longer dies if `dump_profile` isn't defined (Alex / @MasterLambaster, Jon Rowe) ### 2.14.4 / 2013-07-21 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.3...v2.14.4) Bug fixes * Fix regression in 2.14: ensure configured requires (via `-r` option) are loaded before spec files are loaded. This allows the spec files to programatically change the file pattern (Jon Rowe). * Autoload `RSpec::Mocks` and `RSpec::Expectations` when referenced if they are not already loaded (`RSpec::Matches` has been autoloaded for a while). In the `rspec` gem, we changed it recently to stop loading `rspec/mocks` and `rspec/expectations` by default, as some users reported problems where they were intending to use mocha, not rspec-mocks, but rspec-mocks was loaded and causing a conflict. rspec-core loads mocks and expectations at the appropriate time, so it seemed like a safe change -- but caused a problem for some authors of libraries that integrate with RSpec. This fixes that problem. (Myron Marston) * Gracefully handle a command like `rspec --profile path/to/spec.rb`: the `path/to/spec.rb` arg was being wrongly treated as the `profile` integer arg, which got cast `0` using `to_i`, causing no profiled examples to be printed. (Jon Rowe) ### 2.14.3 / 2013-07-13 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.2...v2.14.3) Bug fixes * Fix deprecation notices issued from `RSpec::Core::RakeTask` so that they work properly when all of rspec-core is not loaded. (This was a regression in 2.14) (Jon Rowe) ### 2.14.2 / 2013-07-09 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.1...v2.14.2) Bug fixes * Fix regression caused by 2.14.1 release: formatters that report that they `respond_to?` a notification, but had no corresponding method would raise an error when registered. The new fix is to just implement `start` on the deprecation formatter to fix the original JRuby/ruby-debug issue. (Jon Rowe) ### 2.14.1 / 2013-07-08 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.0...v2.14.1) Bug fixes * Address deprecation formatter failure when using `ruby-debug` on JRuby: fix `RSpec::Core::Reporter` to not send a notification when the formatter's implementation of the notification method comes from `Kernel` (Alex Portnov, Jon Rowe). ### 2.14.0 / 2013-07-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.14.0.rc1...v2.14.0) Enhancements * Apply focus to examples defined with `fit` (equivalent of `it "description", focus: true`) (Michael de Silva) Bug fix * Ensure methods defined by `let` take precedence over others when there is a name collision (e.g. from an included module). (Jon Rowe, Andy Lindeman and Myron Marston) ### 2.14.0.rc1 / 2013-05-27 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.13.1...v2.14.0.rc1) Enhancements * Improved Windows detection inside Git Bash, for better `--color` handling. * Add profiling of the slowest example groups to `--profile` option. The output is sorted by the slowest average example groups. * Don't show slow examples if there's a failure and both `--fail-fast` and `--profile` options are used (Paweł Gościcki). * Rather than always adding `spec` to the load path, add the configured `--default-path` to the load path (which defaults to `spec`). This better supports folks who choose to put their specs in a different directory (John Feminella). * Add some logic to test time duration precision. Make it a function of time, dropping precision as the time increases. (Aaron Kromer) * Add new `backtrace_inclusion_patterns` config option. Backtrace lines that match one of these patterns will _always_ be included in the backtrace, even if they match an exclusion pattern, too (Sam Phippen). * Support ERB trim mode using the `-` when parsing `.rspec` as ERB (Gabor Garami). * Give a better error message when let and subject are called without a block. (Sam Phippen). * List the precedence of `.rspec-local` in the configuration documentation (Sam Phippen) * Support `{a,b}` shell expansion syntax in `--pattern` option (Konstantin Haase). * Add cucumber documentation for --require command line option (Bradley Schaefer) * Expose configuration options via config: * `config.libs` returns the libs configured to be added onto the load path * `full_backtrace?` returns the state of the backtrace cleaner * `debug?` returns true when the debugger is loaded * `line_numbers` returns the line numbers we are filtering by (if any) * `full_description` returns the RegExp used to filter descriptions (Jon Rowe) * Add setters for RSpec.world and RSpec.configuration (Alex Soulim) * Configure ruby's warning behaviour with `--warnings` (Jon Rowe) * Fix an obscure issue on old versions of `1.8.7` where `Time.dup` wouldn't allow access to `Time.now` (Jon Rowe) * Make `shared_examples_for` context aware, so that keys may be safely reused in multiple contexts without colliding. (Jon Rowe) * Add a configurable `deprecation_stream` (Jon Rowe) * Publish deprecations through a formatter (David Chelimsky) Bug fixes * Make JSON formatter behave the same when it comes to `--profile` as the text formatter (Paweł Gościcki). * Fix named subjects so that if an inner group defines a method that overrides the named method, `subject` still retains the originally declared value (Myron Marston). * Fix random ordering so that it does not cause `rand` in examples in nested sibling contexts to return the same value (Max Shytikov). * Use the new `backtrace_inclusion_patterns` config option to ensure that folks who develop code in a directory matching one of the default exclusion patterns (e.g. `gems`) still get the normal backtrace filtering (Sam Phippen). * Fix ordering of `before` hooks so that `before` hooks declared in `RSpec.configure` run before `before` hooks declared in a shared context (Michi Huber and Tejas Dinkar). * Fix `Example#full_description` so that it gets filled in by the last matcher description (as `Example#description` already did) when no doc string has been provided (David Chelimsky). * Fix the memoized methods (`let` and `subject`) leaking `define_method` as a `public` method. (Thomas Holmes and Jon Rowe) (#873) * Fix warnings coming from the test suite. (Pete Higgins) Deprecations * Deprecate `Configuration#backtrace_clean_patterns` in favor of `Configuration#backtrace_exclusion_patterns` for greater consistency and symmetry with new `backtrace_inclusion_patterns` config option (Sam Phippen). * Deprecate `Configuration#requires=` in favor of using ruby's `require`. Requires specified by the command line can still be accessed by the `Configuration#require` reader. (Bradley Schaefer) * Deprecate calling `SharedExampleGroups` defined across sibling contexts (Jon Rowe) ### 2.13.1 / 2013-03-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.13.0...v2.13.1) Bug fixes * Use hook classes as proxies rather than extending hook blocks to support lambdas for before/after/around hooks. (David Chelimsky) * Fix regression in 2.13.0 that caused confusing behavior when overriding a named subject with an unnamed subject in an inner group and then referencing the outer group subject's name. The fix for this required us to disallow using `super` in a named subject (which is confusing, anyway -- named subjects create 2 methods, so which method on the parent example group are you `super`ing to?) but `super` in an unnamed subject continues to work (Myron Marston). * Do not allow a referenced `let` or `subject` in `before(:all)` to cause other `let` declarations to leak across examples (Myron Marston). * Work around odd ruby 1.9 bug with `String#match` that was triggered by passing it a regex from a `let` declaration. For more info, see http://bugs.ruby-lang.org/issues/8059 (Aaron Kromer). * Add missing `require 'set'` to `base_text_formatter.rb` (Tom Anderson). Deprecations * Deprecate accessing `let` or `subject` declarations in `before(:all)`. These were not intended to be called in a `before(:all)` hook, as they exist to define state that is reset between each example, while `before(:all)` exists to define state that is shared across examples in an example group (Myron Marston). ### 2.13.0 / 2013-02-23 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.2...v2.13.0) Enhancements * Allow `--profile` option to take a count argument that determines the number of slow examples to dump (Greggory Rothmeier). * Add `subject!` that is the analog to `let!`. It defines an explicit subject and sets a `before` hook that will invoke the subject (Zubin Henner). * Fix `let` and `subject` declaration so that `super` and `return` can be used in them, just like in a normal method. (Myron Marston) * Allow output colors to be configured individually. (Charlie Maffitt) * Always dump slow examples when `--profile` option is given, even when an example failed (Myron Marston). Bug fixes * Don't blow up when dumping error output for instances of anonymous error classes (Myron Marston). * Fix default backtrace filters so lines from projects containing "gems" in the name are not filtered, but lines from installed gems still are (Myron Marston). * Fix autotest command so that is uses double quotes rather than single quotes for windows compatibility (Jonas Tingeborn). * Fix `its` so that uses of `subject` in a `before` or `let` declaration in the parent group continue to reference the parent group's subject. (Olek Janiszewski) ### 2.12.2 / 2012-12-13 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.1...v2.12.2) Bug fixes * Fix `RSpec::Core::RakeTask` so that it is compatible with rake 0.8.7 on ruby 1.8.7. We had accidentally broke it in the 2.12 release (Myron Marston). * Fix `RSpec::Core::RakeTask` so it is tolerant of the `Rspec` constant for backwards compatibility (Patrick Van Stee) ### 2.12.1 / 2012-12-01 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.12.0...v2.12.1) Bug fixes * Specs are run even if another at\_exit hook calls `exit`. This allows Test::Unit and RSpec to run together. (Suraj N. Kurapati) * Fix full doc string concatenation so that it handles the case of a method string (e.g. "#foo") being nested under a context string (e.g. "when it is tuesday"), so that we get "when it is tuesday #foo" rather than "when it is tuesday#foo". (Myron Marston) * Restore public API I unintentionally broke in 2.12.0: `RSpec::Core::Formatters::BaseFormatter#format_backtrce(backtrace, example)` (Myron Marston). ### 2.12.0 / 2012-11-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.11.1...v2.12.0) Enhancements * Add support for custom ordering strategies for groups and examples. (Myron Marston) * JSON Formatter (Alex Chaffee) * Refactor rake task internals (Sam Phippen) * Refactor HtmlFormatter (Pete Hodgson) * Autotest supports a path to Ruby that contains spaces (dsisnero) * Provide a helpful warning when a shared example group is redefined. (Mark Burns). * `--default_path` can be specified as `--default-line`. `--line_number` can be specified as `--line-number`. Hyphens are more idiomatic command line argument separators (Sam Phippen). * A more useful error message is shown when an invalid command line option is used (Jordi Polo). * Add `format_docstrings { |str| }` config option. It can be used to apply formatting rules to example group and example docstrings. (Alex Tan) * Add support for an `.rspec-local` options file. This is intended to allow individual developers to set options in a git-ignored file that override the common project options in `.rspec`. (Sam Phippen) * Support for mocha 0.13.0. (Andy Lindeman) Bug fixes * Remove override of `ExampleGroup#ancestors`. This is a core ruby method that RSpec shouldn't override. Instead, define `ExampleGroup#parent_groups`. (Myron Marston) * Limit monkey patching of shared example/context declaration methods (`shared_examples_for`, etc.) to just the objects that need it rather than every object in the system (Myron Marston). * Fix Metadata#fetch to support computed values (Sam Goldman). * Named subject can now be referred to from within subject block in a nested group (tomykaira). * Fix `fail_fast` so that it properly exits when an error occurs in a `before(:all) hook` (Bradley Schaefer). * Make the order spec files are loaded consistent, regardless of the order of the files returned by the OS or the order passed at the command line (Jo Liss and Sam Phippen). * Ensure instance variables from `before(:all)` are always exposed from `after(:all)`, even if an error occurs in `before(:all)` (Sam Phippen). * `rspec --init` no longer generates an incorrect warning about `--configure` being deprecated (Sam Phippen). * Fix pluralization of `1 seconds` (Odin Dutton) * Fix ANSICON url (Jarmo Pertman) * Use dup of Time so reporting isn't clobbered by examples that modify Time without properly restoring it. (David Chelimsky) Deprecations * `share_as` is no longer needed. `shared_context` and/or `RSpec::SharedContext` provide better mechanisms (Sam Phippen). * Deprecate `RSpec.configuration` with a block (use `RSpec.configure`). ### 2.11.1 / 2012-07-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.11.0...v2.11.1) Bug fixes * Fix the way we autoload RSpec::Matchers so that custom matchers can be defined before rspec-core has been configured to definitely use rspec-expectations. (Myron Marston) * Fix typo in --help message printed for -e option. (Jo Liss) * Fix ruby warnings. (Myron Marston) * Ignore mock expectation failures when the example has already failed. Mock expectation failures have always been ignored in this situation, but due to my changes in 27059bf1 it was printing a confusing message. (Myron Marston). ### 2.11.0 / 2012-07-07 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.10.1...v2.11.0) Enhancements * Support multiple `--example` options. (Daniel Doubrovkine @dblock) * Named subject e.g. `subject(:article) { Article.new }` * see [http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/](http://blog.davidchelimsky.net/2012/05/13/spec-smell-explicit-use-of-subject/) for background. * thanks to Bradley Schaefer for suggesting it and Avdi Grimm for almost suggesting it. * `config.mock_with` and `config.expect_with` yield custom config object to a block if given * aids decoupling from rspec-core's configuation * `include_context` and `include_examples` support a block, which gets eval'd in the current context (vs the nested context generated by `it_behaves_like`). * Add `config.order = 'random'` to the `spec_helper.rb` generated by `rspec --init`. * Delay the loading of DRb (Myron Marston). * Limit monkey patching of `describe` onto just the objects that need it rather than every object in the system (Myron Marston). Bug fixes * Support alternative path separators. For example, on Windows, you can now do this: `rspec spec\subdir`. (Jarmo Pertman @jarmo) * When an example raises an error and an after or around hook does as well, print out the hook error. Previously, the error was silenced and the user got no feedback about what happened. (Myron Marston) * `--require` and `-I` are merged among different configuration sources (Andy Lindeman) * Delegate to mocha methods instead of aliasing them in mocha adapter. ### 2.10.1 / 2012-05-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.10.0...v2.10.1) Bug fixes * `RSpec.reset` properly reinits configuration and world * Call `to_s` before `split` on exception messages that might not always be Strings (slyphon) ### 2.10.0 / 2012-05-03 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.9.0...v2.10.0) Enhancements * Add `prepend_before` and `append_after` hooks (preethiramdev) * intended for extension libs * restores rspec-1 behavior * Reporting of profiled examples (moro) * Report the total amount of time taken for the top slowest examples. * Report what percentage the slowest examples took from the total runtime. Bug fixes * Properly parse `SPEC_OPTS` options. * `example.description` returns the location of the example if there is no explicit description or matcher-generated description. * RDoc fixes (Grzegorz Świrski) * Do not modify example ancestry when dumping errors (Michael Grosser) ### 2.9.0 / 2012-03-17 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0...v2.9.0) Enhancements * Support for "X minutes X seconds" spec run duration in formatter. (uzzz) * Strip whitespace from group and example names in doc formatter. * Removed spork-0.9 shim. If you're using spork-0.8.x, you'll need to upgrade to 0.9.0. Bug fixes * Restore `--full_backtrace` option * Ensure that values passed to `config.filter_run` are respected when running over DRb (using spork). * Ensure shared example groups are reset after a run (as example groups are). * Remove `rescue false` from calls to filters represented as Procs * Ensure `described_class` gets the closest constant (pyromaniac) * In "autorun", don't run the specs in the `at_exit` hook if there was an exception (most likely due to a SyntaxError). (sunaku) * Don't extend groups with modules already used to extend ancestor groups. * `its` correctly memoizes nil or false values (Yamada Masaki) ### 2.8.0 / 2012-01-04 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0.rc2...v2.8.0) Bug fixes * For metadata filtering, restore passing the entire array to the proc, rather than each item in the array (weidenfreak) * Ensure each spec file is loaded only once * Fixes a bug that caused all the examples in a file to be run when referenced twice with line numbers in a command, e.g. * `rspec path/to/file:37 path/to/file:42` ### 2.8.0.rc2 / 2011-12-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.8.0.rc1...v2.8.0.rc2) Enhancments * new `--init` command (Peter Schröder) * generates `spec/spec_helper.rb` * deletes obsolete files (on confirmation) * merged with and deprecates `--configure` command, which generated `.rspec` * use `require_relative` when available (Ian Leitch) * `include_context` and `include_examples` accept params (Calvin Bascom) * print the time for every example in the html formatter (Richie Vos) * several tasty refactoring niblets (Sasha) * `it "does something", :x => [:foo,'bar',/baz/] (Ivan Neverov) * supports matching n command line tag values with an example or group ### 2.8.0.rc1 / 2011-11-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.7.1...v2.8.0.rc1) Enhancements * `--order` (Justin Ko) * run examples in random order: `--order rand` * specify the seed: `--order rand:123` * `--seed SEED` * equivalent of `--order rand:SEED` * SharedContext supports `let` (David Chelimsky) * Filter improvements (David Chelimsky) * override opposing tags from the command line * override RSpec.configure tags from the command line * `--line_number 37` overrides all other filters * `path/to/file.rb:37` overrides all other filters * refactor: consolidate filter management in a FilterManger object * Eliminate Ruby warnings (Matijs van Zuijlen) * Make reporter.report an API (David Chelimsky) * supports extension tools like interative_rspec Changes * change `config.color_enabled` (getter/setter/predicate) to `color` to align with `--[no]-color` CLI option. * `color_enabled` is still supported for now, but will likley be deprecated in a 2.x release so we can remove it in 3.0. Bug fixes * Make sure the `bar` in `--tag foo:bar` makes it to DRb (Aaron Gibralter) * Fix bug where full descriptions of groups nested 3 deep were repeated. * Restore report of time to run to start after files are loaded. * fixes bug where run times were cumalitive in spork * fixes compatibility with time-series metrics * Don't error out when `config.mock_with` or `expect_with` is re-specifying the current config (Myron Marston) * Deprecations * :alias option on `configuration.add_setting`. Use `:alias_with` on the original setting declaration instead. ### 2.7.1 / 2011-10-20 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.7.0...v2.7.1) Bug fixes * tell autotest the correct place to find the rspec executable ### 2.7.0 / 2011-10-16 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.4...v2.7.0) NOTE: RSpec's release policy dictates that there should not be any backward incompatible changes in minor releases, but we're making an exception to release a change to how RSpec interacts with other command line tools. As of 2.7.0, you must explicity `require "rspec/autorun"` unless you use the `rspec` command (which already does this for you). Enhancements * Add `example.exception` (David Chelimsky) * `--default_path` command line option (Justin Ko) * support multiple `--line_number` options (David J. Hamilton) * also supports `path/to/file.rb:5:9` (runs examples on lines 5 and 9) * Allow classes/modules to be used as shared example group identifiers (Arthur Gunn) * Friendly error message when shared context cannot be found (Sławosz Sławiński) * Clear formatters when resetting config (John Bintz) * Add `xspecify` and xexample as temp-pending methods (David Chelimsky) * Add `--no-drb` option (Iain Hecker) * Provide more accurate run time by registering start time before code is loaded (David Chelimsky) * reverted in 2.8.0 * Rake task default pattern finds specs in symlinked dirs (Kelly Felkins) * Rake task no longer does anything to invoke bundler since Bundler already handles it for us. Thanks to Andre Arko for the tip. * Add `--failure-exit-code` option (Chris Griego) Bug fixes * Include `Rake::DSL` to remove deprecation warnings in Rake > 0.8.7 (Pivotal Casebook) * Only eval `let` block once even if it returns `nil` (Adam Meehan) * Fix `--pattern` option (wasn't being recognized) (David Chelimsky) * Only implicitly `require "rspec/autorun"` with the `rspec` command (David Chelimsky) * Ensure that rspec's `at_exit` defines the exit code (Daniel Doubrovkine) * Show the correct snippet in the HTML and TextMate formatters (Brian Faherty) ### 2.6.4 / 2011-06-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.3...v2.6.4) NOTE: RSpec's release policy dictates that there should not be new functionality in patch releases, but this minor enhancement slipped in by accident. As it doesn't add a new API, we decided to leave it in rather than roll back this release. Enhancements * Add summary of commands to run individual failed examples. Bug fixes * Support exclusion filters in DRb. (Yann Lugrin) * Fix --example escaping when run over DRb. (Elliot Winkler) * Use standard ANSI codes for color formatting so colors work in a wider set of color schemes. ### 2.6.3 / 2011-05-24 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.2...v2.6.3) Bug fixes * Explicitly convert exit code to integer, avoiding TypeError when return value of run is IO object proxied by `DRb::DRbObject` (Julian Scheid) * Clarify behavior of `--example` command line option * Build using a rubygems-1.6.2 to avoid downstream yaml parsing error ### 2.6.2 / 2011-05-21 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.1...v2.6.2) Bug fixes * Warn rather than raise when HOME env var is not defined * Properly merge command-line exclusions with default :if and :unless (joshcooper) ### 2.6.1 / 2011-05-19 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.6.0...v2.6.1) Bug fixes * Don't extend nil when filters are nil * `require 'rspec/autorun'` when running rcov. ### 2.6.0 / 2011-05-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.5.1...v2.6.0) Enhancements * `shared_context` (Damian Nurzynski) * extend groups matching specific metadata with: * method definitions * subject declarations * let/let! declarations * etc (anything you can do in a group) * `its([:key])` works for any subject with #[]. (Peter Jaros) * `treat_symbols_as_metadata_keys_with_true_values` (Myron Marston) * Print a deprecation warning when you configure RSpec after defining an example. All configuration should happen before any examples are defined. (Myron Marston) * Pass the exit status of a DRb run to the invoking process. This causes specs run via DRb to not just return true or false. (Ilkka Laukkanen) * Refactoring of `ConfigurationOptions#parse_options` (Rodrigo Rosenfeld Rosas) * Report excluded filters in runner output (tip from andyl) * Clean up messages for filters/tags. * Restore --pattern/-P command line option from rspec-1 * Support false as well as true in config.full_backtrace= (Andreas Tolf Tolfsen) Bug fixes * Don't stumble over an exception without a message (Hans Hasselberg) * Remove non-ascii characters from comments that were choking rcov (Geoffrey Byers) * Fixed backtrace so it doesn't include lines from before the autorun at_exit hook (Myron Marston) * Include RSpec::Matchers when first example group is defined, rather than just before running the examples. This works around an obscure bug in ruby 1.9 that can cause infinite recursion. (Myron Marston) * Don't send `example_group_[started|finished]` to formatters for empty groups. * Get specs passing on jruby (Sidu Ponnappa) * Fix bug where mixing nested groups and outer-level examples gave unpredictable :line_number behavior (Artur Małecki) * Regexp.escape the argument to --example (tip from Elliot Winkler) * Correctly pass/fail pending block with message expectations * CommandLine returns exit status (0/1) instead of true/false * Create path to formatter output file if it doesn't exist (marekj). ### 2.5.1 / 2011-02-06 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.5.0...v2.5.1) NOTE: this release breaks compatibility with rspec/autotest/bundler integration, but does so in order to greatly simplify it. With this release, if you want the generated autotest command to include 'bundle exec', require Autotest's bundler plugin in a .autotest file in the project's root directory or in your home directory: require "autotest/bundler" Now you can just type 'autotest' on the command line and it will work as you expect. If you don't want 'bundle exec', there is nothing you have to do. ### 2.5.0 / 2011-02-05 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.4.0...v2.5.0) Enhancements * Autotest::Rspec2 parses command line args passed to autotest after '--' * --skip-bundler option for autotest command * Autotest regexp fixes (Jon Rowe) * Add filters to html and textmate formatters (Daniel Quimper) * Explicit passing of block (need for JRuby 1.6) (John Firebaugh) Bug fixes * fix dom IDs in HTML formatter (Brian Faherty) * fix bug with --drb + formatters when not running in drb * include --tag options in drb args (monocle) * fix regression so now SPEC_OPTS take precedence over CLI options again (Roman Chernyatchik) * only call its(:attribute) once (failing example from Brian Dunn) * fix bizarre bug where rspec would hang after String.alias :to_int :to_i (Damian Nurzynski) Deprecations * implicit inclusion of 'bundle exec' when Gemfile present (use autotest's bundler plugin instead) ### 2.4.0 / 2011-01-02 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.3.1...v2.4.0) Enhancements * start the debugger on -d so the stack trace is visible when it stops (Clifford Heath) * apply hook filtering to examples as well as groups (Myron Marston) * support multiple formatters, each with their own output * show exception classes in failure messages unless they come from RSpec matchers or message expectations * before(:all) { pending } sets all examples to pending Bug fixes * fix bug due to change in behavior of reject in Ruby 1.9.3-dev (Shota Fukumori) * fix bug when running in jruby: be explicit about passing block to super (John Firebaugh) * rake task doesn't choke on paths with quotes (Janmejay Singh) * restore --options option from rspec-1 * require 'ostruct' to fix bug with its([key]) (Kim Burgestrand) * --configure option generates .rspec file instead of autotest/discover.rb ### 2.3.1 / 2010-12-16 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.3.0...v2.3.1) Bug fixes * send debugger warning message to $stdout if RSpec.configuration.error_stream has not been defined yet. * HTML Formatter _finally_ properly displays nested groups (Jarmo Pertman) * eliminate some warnings when running RSpec's own suite (Jarmo Pertman) ### 2.3.0 / 2010-12-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.2.1...v2.3.0) Enhancements * tell autotest to use "rspec2" if it sees a .rspec file in the project's root directory * replaces the need for ./autotest/discover.rb, which will not work with all versions of ZenTest and/or autotest * config.expect_with * :rspec # => rspec/expectations * :stdlib # => test/unit/assertions * :rspec, :stdlib # => both Bug fixes * fix dev Gemfile to work on non-mac-os machines (Lake Denman) * ensure explicit subject is only eval'd once (Laszlo Bacsi) ### 2.2.1 / 2010-11-28 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.2.0...v2.2.1) Bug fixes * alias_method instead of override Kernel#method_missing (John Wilger) * changed --autotest to --tty in generated command (MIKAMI Yoshiyuki) * revert change to debugger (had introduced conflict with Rails) * also restored --debugger/-debug option ### 2.2.0 / 2010-11-28 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.1.0...v2.2.0) Deprecations/changes * --debug/-d on command line is deprecated and now has no effect * win32console is now ignored; Windows users must use ANSICON for color support (Bosko Ivanisevic) Enhancements * When developing locally rspec-core now works with the rspec-dev setup or your local gems * Raise exception with helpful message when rspec-1 is loaded alongside rspec-2 (Justin Ko) * debugger statements _just work_ as long as ruby-debug is installed * otherwise you get warned, but not fired * Expose example.metadata in around hooks * Performance improvments (much faster now) Bug fixes * Make sure --fail-fast makes it across drb * Pass -Ilib:spec to rcov ### 2.1.0 / 2010-11-07 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.1...v2.1.0) Enhancments * Add skip_bundler option to rake task to tell rake task to ignore the presence of a Gemfile (jfelchner) * Add gemfile option to rake task to tell rake task what Gemfile to look for (defaults to 'Gemfile') * Allow passing caller trace into Metadata to support extensions (Glenn Vanderburg) * Add deprecation warning for Spec::Runner.configure to aid upgrade from RSpec-1 * Add deprecated Spec::Rake::SpecTask to aid upgrade from RSpec-1 * Add 'autospec' command with helpful message to aid upgrade from RSpec-1 * Add support for filtering with tags on CLI (Lailson Bandeira) * Add a helpful message about RUBYOPT when require fails in bin/rspec (slyphon) * Add "-Ilib" to the default rcov options (Tianyi Cui) * Make the expectation framework configurable (default rspec, of course) (Justin Ko) * Add 'pending' to be conditional (Myron Marston) * Add explicit support for :if and :unless as metadata keys for conditional run of examples (Myron Marston) * Add --fail-fast command line option (Jeff Kreeftmeijer) Bug fixes * Eliminate stack overflow with "subject { self }" * Require 'rspec/core' in the Raketask (ensures it required when running rcov) ### 2.0.1 / 2010-10-18 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0...v2.0.1) Bug fixes * Restore color when using spork + autotest * Pending examples without docstrings render the correct message (Josep M. Bach) * Fixed bug where a failure in a spec file ending in anything but _spec.rb would fail in a confusing way. * Support backtrace lines from erb templates in html formatter (Alex Crichton) ### 2.0.0 / 2010-10-10 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.rc...v2.0.0) RSpec-1 compatibility * Rake task uses ENV["SPEC"] as file list if present Bug fixes * Bug Fix: optparse --out foo.txt (Leonardo Bessa) * Suppress color codes for non-tty output (except autotest) ### 2.0.0.rc / 2010-10-05 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.beta.22...v2.0.0.rc) Enhancements * implicitly require unknown formatters so you don't have to require the file explicitly on the command line (Michael Grosser) * add --out/-o option to assign output target * added fail_fast configuration option to abort on first failure * support a Hash subject (its([:key]) { should == value }) (Josep M. Bach) Bug fixes * Explicitly require rspec version to fix broken rdoc task (Hans de Graaff) * Ignore backtrace lines that come from other languages, like Java or Javascript (Charles Lowell) * Rake task now does what is expected when setting (or not setting) fail_on_error and verbose * Fix bug in which before/after(:all) hooks were running on excluded nested groups (Myron Marston) * Fix before(:all) error handling so that it fails examples in nested groups, too (Myron Marston) ### 2.0.0.beta.22 / 2010-09-12 [Full Changelog](http://github.com/rspec/rspec-core/compare/v2.0.0.beta.20...v2.0.0.beta.22) Enhancements * removed at_exit hook * CTRL-C stops the run (almost) immediately * first it cleans things up by running the appropriate after(:all) and after(:suite) hooks * then it reports on any examples that have already run * cleaned up rake task * generate correct task under variety of conditions * options are more consistent * deprecated redundant options * run 'bundle exec autotest' when Gemfile is present * support ERB in .rspec options files (Justin Ko) * depend on bundler for development tasks (Myron Marston) * add example_group_finished to formatters and reporter (Roman Chernyatchik) Bug fixes * support paths with spaces when using autotest (Andreas Neuhaus) * fix module_exec with ruby 1.8.6 (Myron Marston) * remove context method from top-level * was conflicting with irb, for example * errors in before(:all) are now reported correctly (Chad Humphries) Removals * removed -o --options-file command line option * use ./.rspec and ~/.rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/CODE_OF_CONDUCT.md0000664000000000000000000000544414557677674021467 0ustar rootroot # Contributor Code of Conduct For the purpose of building a welcoming, harassment-free community that values contributions from anyone, the RSpec project has adopted the following code of conduct. All contributors and participants (including maintainers!) are expected to abide by its terms. As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the project maintainers listed at https://rspec.info/about/. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/3/0/ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Gemfile0000664000000000000000000000553614557677674020165 0ustar rootrootsource "https://rubygems.org" gemspec branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp %w[rspec rspec-expectations rspec-mocks rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path else gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end if RUBY_VERSION < '1.9.3' gem 'rake', '< 11.0.0' # rake 11 requires Ruby 1.9.3 or later elsif RUBY_VERSION < '2.0.0' gem 'rake', '< 12.0.0' # rake 12 requires Ruby 2.0.0 or later elsif RUBY_VERSION < '2.2.0' gem 'rake', '< 13.0.0' # rake 13 requires Ruby 2.2.0 or later else gem 'rake', '>= 13.0.0' end if ENV['DIFF_LCS_VERSION'] gem 'diff-lcs', ENV['DIFF_LCS_VERSION'] else gem 'diff-lcs', '~> 1.4', '>= 1.4.3' end ### deps for rdoc.info group :documentation do gem 'redcarpet', :platform => :mri gem 'github-markup', :platform => :mri gem 'yard', '~> 0.9.24', :require => false end if RUBY_VERSION < '2.0.0' gem 'thor', '< 1.0.0' else gem 'thor', '> 1.0.0' end if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java' gem 'json', '< 2.0.0' else gem 'json', '> 2.3.0' end if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.10' elsif RUBY_VERSION < '2.4.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.15' elsif RUBY_VERSION < '2.0' gem 'ffi', '< 1.9.19' # ffi dropped Ruby 1.8 support in 1.9.19 elsif RUBY_VERSION < '2.3.0' gem 'ffi', '~> 1.12.0' else gem 'ffi', '~> 1.15.0' end if RUBY_VERSION < '2.3.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.0.0' gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.3.0' gem "childprocess", "< 3.0.0" else gem "childprocess", ">= 3.0.0" end platforms :jruby do if RUBY_VERSION < '1.9.0' # Pin jruby-openssl on older J Ruby gem "jruby-openssl", "< 0.10.0" else gem "jruby-openssl" end end group :coverage do gem 'simplecov', '~> 0.8' end # No need to run rubocop on earlier versions if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' gem "rubocop", "~> 1.0", "< 1.12" end gem 'test-unit', '~> 3.0' if RUBY_VERSION.to_f >= 2.2 # Version 5.12 of minitest requires Ruby 2.4 if RUBY_VERSION < '2.4.0' gem 'minitest', '< 5.12.0' end if RUBY_VERSION < '2.0.0' gem 'cucumber', "<= 1.3.22" elsif !ENV['DIFF_LCS_VERSION'].to_s.empty? && ENV['DIFF_LCS_VERSION'].scan(/\d\.\d/).first.to_f < 1.5 # Older version of diff-lcs cause a downstream error with cucumber and modern rails gem "activesupport", "< 7" end gem 'contracts', '< 0.16' if RUBY_VERSION < '1.9.0' gem 'drb' if RUBY_VERSION >= '3.4' eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom') ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Gemfile-custom.sample0000664000000000000000000000051114557677674022741 0ustar rootrootgroup :development do gem 'interactive_rspec' gem 'guard-rspec', '~> 1.2.1' gem 'growl', '1.0.3' gem 'spork', '0.9.0' platform :mri do gem 'rb-fsevent', '~> 0.9.0' gem 'ruby-prof', '~> 0.13.0' case RUBY_VERSION when /^1.8/ gem 'ruby-debug' when /^1.9/ gem 'debugger' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/REPORT_TEMPLATE.md0000664000000000000000000000211714557677674021512 0ustar rootroot # Report template ```ruby # frozen_string_literal: true begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "rspec", "3.7.0" # Activate the gem and version you are reporting the issue against. end puts "Ruby version is: #{RUBY_VERSION}" require 'rspec/autorun' RSpec.describe 'additions' do it 'returns 2' do expect(1 + 1).to eq(2) end it 'returns 1' do expect(3 - 1).to eq(-1) end end ``` Simply copy the content of the appropriate template into a `.rb` file on your computer and make the necessary changes to demonstrate the issue. You can execute it by running `ruby rspec_report.rb` in your terminal. You can then share your executable test case as a [gist](https://gist.github.com), or simply paste the content into the issue description. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.document0000664000000000000000000000006014557677674020474 0ustar rootrootlib/**/*.rb - README.md LICENSE.md Changelog.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.yardopts0000664000000000000000000000015714557677674020532 0ustar rootroot--exclude features --no-private --markup markdown --default-return void - Filtering.md Changelog.md LICENSE.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.rspec0000664000000000000000000000005614557677674017777 0ustar rootroot--order rand --warnings --require spec_helper ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.rubocop_todo.yml0000664000000000000000000010062614557677674022165 0ustar rootroot# This configuration was generated by # `rubocop --auto-gen-config` # on 2022-01-09 17:19:16 UTC using RuboCop version 1.11.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: - 'Gemfile' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemspec Gemspec/OrderedDependencies: Exclude: - 'rspec-core.gemspec' # Offense count: 1 # Configuration parameters: Include. # Include: **/*.gemspec Gemspec/RequiredRubyVersion: Exclude: - 'rspec-core.gemspec' # Offense count: 20 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: with_first_argument, with_fixed_indentation Layout/ArgumentAlignment: Exclude: - 'benchmarks/threadsafe_let_block.rb' - 'features/step_definitions/additional_cli_steps.rb' - 'spec/rspec/core/backtrace_formatter_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/documentation_formatter_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/rake_task_spec.rb' - 'spec/rspec/core/reporter_spec.rb' - 'spec/rspec/core_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: with_first_element, with_fixed_indentation Layout/ArrayAlignment: Exclude: - 'spec/rspec/core/filter_manager_spec.rb' - 'spec/rspec/core/resources/formatter_specs.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyleAlignWith, Severity. # SupportedStylesAlignWith: start_of_line, begin Layout/BeginEndAlignment: Exclude: - 'lib/rspec/core/runner.rb' # Offense count: 6 # Cop supports --auto-correct. Layout/BlockEndNewline: Exclude: - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/metadata_filter_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentOneStep, IndentationWidth. # SupportedStyles: case, end Layout/CaseIndentation: Exclude: - 'spec/support/matchers.rb' # Offense count: 9 # Cop supports --auto-correct. Layout/ClosingHeredocIndentation: Exclude: - 'benchmarks/filter_object.rb' - 'lib/rspec/core/formatters/html_printer.rb' - 'lib/rspec/core/memoized_helpers.rb' - 'lib/rspec/core/option_parser.rb' - 'spec/rspec/core/notifications_spec.rb' # Offense count: 32 # Cop supports --auto-correct. Layout/CommentIndentation: Exclude: - 'benchmarks/check_inclusion.rb' # Offense count: 68 # Cop supports --auto-correct. Layout/EmptyLineAfterGuardClause: Enabled: false # Offense count: 3 # Cop supports --auto-correct. Layout/EmptyLines: Exclude: - 'spec/integration/persistence_failures_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/example_spec.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: AllowAliasSyntax, AllowedMethods. # AllowedMethods: alias_method, public, protected, private Layout/EmptyLinesAroundAttributeAccessor: Exclude: - 'lib/rspec/core/configuration.rb' - 'lib/rspec/core/minitest_assertions_adapter.rb' - 'spec/rspec/core/bisect/example_minimizer_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/resources/custom_example_group_runner.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines Layout/EmptyLinesAroundModuleBody: Exclude: - 'spec/rspec/core/world_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 21 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses Layout/FirstArgumentIndentation: Exclude: - 'lib/rspec/core/bisect/fork_runner.rb' - 'lib/rspec/core/formatters/base_bisect_formatter.rb' - 'spec/integration/bisect_runners_spec.rb' - 'spec/rspec/core/bisect/coordinator_spec.rb' - 'spec/rspec/core/bisect/example_minimizer_spec.rb' - 'spec/rspec/core/bisect/server_spec.rb' - 'spec/rspec/core/bisect/shell_command_spec.rb' - 'spec/rspec/core/bisect/utilities_spec.rb' - 'spec/rspec/core/configuration_options_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/hooks_spec.rb' - 'spec/rspec/core/notifications_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: IndentationWidth. # SupportedStyles: special_inside_parentheses, consistent, align_braces Layout/FirstHashElementIndentation: EnforcedStyle: consistent # Offense count: 65 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table # SupportedColonStyles: key, separator, table # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit Layout/HashAlignment: Enabled: false # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: normal, indented_internal_methods Layout/IndentationConsistency: Exclude: - 'spec/rspec/core/metadata_filter_spec.rb' - 'spec/support/aruba_support.rb' # Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: Width, IgnoredPatterns. Layout/IndentationWidth: Exclude: - 'benchmarks/respond_to_v_defined.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core_spec.rb' - 'spec/support/aruba_support.rb' - 'spec/support/formatter_support.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. Layout/LeadingCommentSpace: Exclude: - 'spec/rspec/core/formatters/progress_formatter_spec.rb' - 'spec/rspec/core/metadata_spec.rb' # Offense count: 68 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Layout/LineLength: Max: 172 # Offense count: 8 # Cop supports --auto-correct. Layout/MultilineBlockLayout: Exclude: - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/metadata_filter_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Layout/RescueEnsureAlignment: Exclude: - 'lib/rspec/core/runner.rb' # Offense count: 49 # Cop supports --auto-correct. Layout/SpaceAfterComma: Exclude: - 'spec/rspec/core/backtrace_formatter_spec.rb' - 'spec/rspec/core/configuration_options_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/drb_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/filter_manager_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/metadata_filter_spec.rb' - 'spec/rspec/core/option_parser_spec.rb' # Offense count: 12 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: space, no_space Layout/SpaceAroundEqualsInParameterDefault: Exclude: - 'benchmarks/singleton_example_groups/helper.rb' - 'spec/rspec/core/bisect/coordinator_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/example_status_persister_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 2 # Cop supports --auto-correct. Layout/SpaceAroundKeyword: Exclude: - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' # Offense count: 24 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceBeforeBlockBraces: Enabled: false # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AllowForAlignment. Layout/SpaceBeforeFirstArg: Exclude: - 'spec/rspec/core/drb_spec.rb' # Offense count: 58 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBrackets: space, no_space Layout/SpaceInsideArrayLiteralBrackets: Exclude: - 'spec/rspec/core/bisect/shell_command_spec.rb' - 'spec/rspec/core/configuration_options_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/example_status_persister_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/formatters/snippet_extractor_spec.rb' - 'spec/rspec/core/metadata_spec.rb' - 'spec/rspec/core/notifications_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' - 'spec/rspec/core/suite_hooks_spec.rb' # Offense count: 81 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideHashLiteralBraces: Exclude: - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/drb_spec.rb' - 'spec/rspec/core/filter_manager_spec.rb' - 'spec/rspec/core/hooks_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/metadata_filter_spec.rb' - 'spec/rspec/core/runner_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: final_newline, final_blank_line Layout/TrailingEmptyLines: Exclude: - 'benchmarks/eager_vs_lazy_metadata/define_examples.rb' - 'features/support/send_sigint_during_bisect.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/rspec_matchers_spec.rb' - 'spec/rspec/core_spec.rb' # Offense count: 16 Lint/AmbiguousBlockAssociation: Exclude: - 'benchmarks/threadsafe_let_block.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/example_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/formatters/syntax_highlighter_spec.rb' - 'spec/rspec/core/formatters_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/option_parser_spec.rb' - 'spec/rspec/core/world_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/AmbiguousOperator: Exclude: - 'benchmarks/threadsafe_let_block.rb' # Offense count: 15 # Cop supports --auto-correct. Lint/AmbiguousRegexpLiteral: Exclude: - 'features/step_definitions/additional_cli_steps.rb' # Offense count: 2 # Configuration parameters: AllowSafeAssignment. Lint/AssignmentInCondition: Exclude: - 'benchmarks/index_v_take_while.rb' - 'spec/rspec/core/metadata_spec.rb' # Offense count: 2 Lint/BinaryOperatorWithIdenticalOperands: Exclude: - 'spec/rspec/core/example_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Lint/BooleanSymbol: Exclude: - 'spec/rspec/core/example_group_spec.rb' # Offense count: 13 # Configuration parameters: AllowedMethods. # AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'spec/integration/bisect_spec.rb' - 'spec/rspec/core/bisect/example_minimizer_spec.rb' - 'spec/rspec/core/bisect/utilities_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/drb_spec.rb' - 'spec/rspec/core/filterable_item_repository_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/hooks_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' # Offense count: 1 Lint/DuplicateRequire: Exclude: - 'benchmarks/hash_functions.rb' # Offense count: 10 # Configuration parameters: AllowComments. Lint/EmptyFile: Exclude: - 'spec/rspec/core/resources/a_bar.rb' - 'spec/rspec/core/resources/a_foo.rb' - 'spec/rspec/core/resources/acceptance/bar.rb' - 'spec/rspec/core/resources/acceptance/foo_spec.rb' - 'spec/support/fake_libs/coderay.rb' - 'spec/support/fake_libs/drb/acl.rb' - 'spec/support/fake_libs/drb/drb.rb' - 'spec/support/fake_libs/json.rb' - 'spec/support/fake_libs/minitest.rb' - 'spec/support/fake_libs/rake.rb' # Offense count: 2 Lint/FloatComparison: Exclude: - 'features/support/ruby_27_support.rb' - 'lib/rspec/core/formatters/helpers.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: runtime_error, standard_error Lint/InheritException: Exclude: - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/support/fake_libs/rspec/expectations.rb' # Offense count: 2 # Cop supports --auto-correct. Lint/InterpolationCheck: Exclude: - 'spec/rspec/core/bisect/shell_command_spec.rb' - 'spec/rspec/core/rake_task_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Lint/RedundantCopDisableDirective: Exclude: - 'lib/rspec/core/formatters/html_snippet_extractor.rb' - 'lib/rspec/core/formatters/syntax_highlighter.rb' # Offense count: 2 # Cop supports --auto-correct. Lint/RedundantCopEnableDirective: Exclude: - 'lib/rspec/core/formatters/html_printer.rb' - 'lib/rspec/core/formatters/html_snippet_extractor.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/RedundantStringCoercion: Exclude: - 'spec/spec_helper.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/SendWithMixinArgument: Exclude: - 'lib/rspec/core/configuration.rb' # Offense count: 1 Lint/ShadowingOuterLocalVariable: Exclude: - 'benchmarks/hash_functions.rb' # Offense count: 1 Lint/StructNewOverride: Exclude: - 'lib/rspec/core/notifications.rb' # Offense count: 1 # Configuration parameters: AllowComments. Lint/SuppressedException: Exclude: - 'lib/rspec/core/example.rb' - 'lib/rspec/core/mocking_adapters/mocha.rb' - 'lib/rspec/core/runner.rb' - 'lib/rspec/core/test_unit_assertions_adapter.rb' - 'script/rspec_with_simplecov' # Offense count: 25 # Cop supports --auto-correct. # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: - 'features/support/env.rb' - 'features/support/jruby.rb' - 'features/support/rubinius.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/formatters/json_formatter_spec.rb' - 'spec/rspec/core/invocations_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/metadata_filter_spec.rb' - 'spec/rspec/core/metadata_spec.rb' - 'spec/rspec/core/notifications_spec.rb' - 'spec/rspec/core/rake_task_spec.rb' - 'spec/rspec/core/reporter_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: Exclude: - 'benchmarks/capture_block_vs_yield.rb' - 'spec/integration/filtering_spec.rb' - 'spec/rspec/core/formatters/snippet_extractor_spec.rb' # Offense count: 1 Lint/UselessAssignment: Exclude: - 'benchmarks/hash_functions.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowComments. Lint/UselessMethodDefinition: Exclude: - 'spec/rspec/core/rspec_matchers_spec.rb' # Offense count: 4 # Configuration parameters: CheckForMethodsWithNoSideEffects. Lint/Void: Exclude: - 'benchmarks/keys_each_vs_each_key.rb' - 'spec/rspec/core/example_group_spec.rb' # Offense count: 1 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 283 # Offense count: 32 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. # IgnoredMethods: refine Metrics/BlockLength: Max: 2373 # Offense count: 1 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: Max: 134 # Offense count: 32 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: Max: 2351 # Offense count: 1 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: Max: 6 # Offense count: 4 # Configuration parameters: AsciiConstants. Naming/AsciiIdentifiers: Exclude: - 'spec/rspec/core/resources/utf8_encoded.rb' # Offense count: 6 # Configuration parameters: EnforcedStyleForLeadingUnderscores. # SupportedStylesForLeadingUnderscores: disallowed, required, optional Naming/MemoizedInstanceVariableName: Exclude: - 'lib/rspec/core/example_group.rb' - 'lib/rspec/core/example_status_persister.rb' - 'lib/rspec/core/notifications.rb' - 'lib/rspec/core/ruby_project.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 1 # Configuration parameters: IgnoredPatterns. # SupportedStyles: snake_case, camelCase Naming/MethodName: EnforcedStyle: snake_case Exclude: - 'spec/rspec/core/drb_spec.rb' # Offense count: 14 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'benchmarks/capture_block_vs_yield.rb' - 'lib/rspec/core/example.rb' - 'lib/rspec/core/formatters/exception_presenter.rb' - 'spec/rspec/core/example_status_persister_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/hooks_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/ordering_spec.rb' - 'spec/support/formatter_support.rb' - 'spec/support/helper_methods.rb' # Offense count: 13 # Cop supports --auto-correct. # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: Exclude: - 'lib/rspec/core/configuration.rb' - 'lib/rspec/core/example.rb' - 'lib/rspec/core/example_group.rb' - 'lib/rspec/core/formatters/exception_presenter.rb' - 'lib/rspec/core/hooks.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/formatters/snippet_extractor_spec.rb' - 'spec/rspec/core/notifications_spec.rb' # Offense count: 1 Security/Eval: Exclude: - 'Gemfile' # Offense count: 7 # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Exclude: - 'lib/rspec/core/flat_map.rb' - 'lib/rspec/core/ruby_project.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: separated, grouped Style/AccessorGrouping: Exclude: - 'spec/rspec/core/bisect/example_minimizer_spec.rb' # Offense count: 1 # Configuration parameters: AllowedChars. # AllowedChars: © Style/AsciiComments: Exclude: - 'spec/rspec/core/formatters/exception_presenter_spec.rb' # Offense count: 4 # Cop supports --auto-correct. Style/CaseLikeIf: Exclude: - 'lib/rspec/core/hooks.rb' - 'lib/rspec/core/option_parser.rb' - 'spec/rspec/core/bisect/shell_runner_spec.rb' # Offense count: 43 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Enabled: false # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. # IgnoredMethods: ==, equal?, eql? Style/ClassEqualityComparison: Exclude: - 'lib/rspec/core/formatters.rb' # Offense count: 1 Style/ClassVars: Exclude: - 'benchmarks/singleton_example_groups/helper.rb' # Offense count: 7 # Cop supports --auto-correct. Style/ColonMethodCall: Exclude: - 'spec/rspec/core/drb_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' - 'spec/rspec/core_spec.rb' # Offense count: 3 Style/CombinableLoops: Exclude: - 'benchmarks/singleton_example_groups/helper.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: Keywords. # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE Style/CommentAnnotation: Exclude: - 'lib/rspec/core/shell_escape.rb' # Offense count: 2 # Cop supports --auto-correct. Style/Dir: Exclude: - 'spec/support/spec_files.rb' # Offense count: 7 # Cop supports --auto-correct. Style/Encoding: Exclude: - 'lib/rspec/core/formatters/exception_presenter.rb' - 'rspec-core.gemspec' - 'spec/rspec/core/example_group_constants_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/formatters/exception_presenter_spec.rb' - 'spec/rspec/core/formatters/html_formatter_spec.rb' - 'spec/rspec/core/resources/utf8_encoded.rb' # Offense count: 21 # Cop supports --auto-correct. Style/EvalWithLocation: Exclude: - 'benchmarks/call_v_yield.rb' - 'spec/rspec/core/filter_manager_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/metadata_spec.rb' - 'spec/rspec/core/world_spec.rb' # Offense count: 13 # Cop supports --auto-correct. Style/ExpandPathArguments: Exclude: - 'Gemfile' - 'benchmarks/allocations/helper.rb' - 'features/step_definitions/additional_cli_steps.rb' - 'lib/rspec/core.rb' - 'lib/rspec/core/project_initializer.rb' - 'lib/rspec/core/rake_task.rb' - 'rspec-core.gemspec' - 'script/rspec_with_simplecov' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/rake_task_spec.rb' - 'spec/rspec/core_spec.rb' # Offense count: 16 # Cop supports --auto-correct. Style/ExplicitBlockArgument: Exclude: - 'benchmarks/allocations/helper.rb' - 'benchmarks/capture_block_vs_yield.rb' - 'benchmarks/flat_map_vs_inject.rb' - 'benchmarks/map_then_flatten_vs_flat_map_benchmarks.rb' - 'benchmarks/several_regexps_v_one_big_one.rb' - 'benchmarks/to_proc_v_not_to_proc.rb' - 'lib/rspec/core/configuration.rb' - 'lib/rspec/core/example.rb' - 'lib/rspec/core/hooks.rb' - 'lib/rspec/core/ordering.rb' - 'spec/rspec/core/configuration/only_failures_support_spec.rb' - 'spec/rspec/core/drb_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: left_coerce, right_coerce, single_coerce, fdiv Style/FloatDivision: Exclude: - 'lib/rspec/core/formatters/html_formatter.rb' # Offense count: 224 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Enabled: false # Offense count: 1 # Cop supports --auto-correct. Style/GlobalStdStream: Exclude: - 'spec/rspec/core/configuration_spec.rb' # Offense count: 20 # Configuration parameters: AllowedVariables. Style/GlobalVars: Exclude: - 'benchmarks/map_then_flatten_vs_flat_map_benchmarks.rb' - 'benchmarks/several_regexps_v_one_big_one.rb' - 'benchmarks/shuffle_vs_sort_by_for_random_ordering.rb' - 'benchmarks/to_proc_v_not_to_proc.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/metadata_spec.rb' - 'spec/spec_helper.rb' # Offense count: 2 # Cop supports --auto-correct. Style/HashEachMethods: Exclude: - 'benchmarks/keys_each_vs_each_key.rb' # Offense count: 16 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys Style/HashSyntax: Exclude: - 'benchmarks/allocations/helper.rb' - 'benchmarks/allocations/running_1000_groups_1_example.rb' - 'benchmarks/allocations/running_1_group_1000_examples.rb' - 'benchmarks/singleton_example_groups/helper.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: InverseMethods, InverseBlocks. Style/InverseMethods: Exclude: - 'spec/spec_helper.rb' # Offense count: 9 # Cop supports --auto-correct. Style/LineEndConcatenation: Exclude: - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/option_parser_spec.rb' # Offense count: 37 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. Style/MethodCallWithoutArgsParentheses: Exclude: - 'spec/rspec/core/configuration_options_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/metadata_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline Style/MethodDefParentheses: Exclude: - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/json_formatter_spec.rb' - 'spec/rspec/core/formatters/profile_formatter_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 1 Style/MultilineBlockChain: Exclude: - 'spec/rspec/core/invocations_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: both, prefix, postfix Style/NegatedIf: Exclude: - 'features/step_definitions/additional_cli_steps.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedOctalStyle. # SupportedOctalStyles: zero_with_o, zero_only Style/NumericLiteralPrefix: Exclude: - 'spec/integration/persistence_failures_spec.rb' # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: Strict. Style/NumericLiterals: MinDigits: 11 # Offense count: 7 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/rspec/core/formatters/bisect_progress_formatter.rb' - 'lib/rspec/core/metadata.rb' - 'lib/rspec/core/option_parser.rb' - 'lib/rspec/core/output_wrapper.rb' - 'lib/rspec/core/runner.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/support/formatter_support.rb' # Offense count: 33 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'benchmarks/filter_object.rb' - 'benchmarks/several_regexps_v_one_big_one.rb' - 'features/step_definitions/additional_cli_steps.rb' - 'spec/rspec/core/drb_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/rake_task_spec.rb' # Offense count: 5 # Cop supports --auto-correct. Style/PerlBackrefs: Exclude: - 'features/step_definitions/additional_cli_steps.rb' - 'spec/spec_helper.rb' - 'spec/support/aruba_support.rb' - 'spec/support/formatter_support.rb' # Offense count: 2 # Cop supports --auto-correct. Style/RandomWithOffset: Exclude: - 'spec/integration/spec_file_load_errors_spec.rb' - 'spec/integration/suite_hooks_errors_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/RedundantAssignment: Exclude: - 'spec/rspec/core/resources/utf8_encoded.rb' # Offense count: 3 # Cop supports --auto-correct. Style/RedundantCapitalW: Exclude: - 'spec/integration/bisect_spec.rb' - 'spec/rspec/core/bisect/shell_command_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: SafeForConstants. Style/RedundantFetchBlock: Exclude: - 'spec/rspec/core/example_execution_result_spec.rb' - 'spec/rspec/core/ordering_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/RedundantInterpolation: Exclude: - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' # Offense count: 23 # Cop supports --auto-correct. Style/RedundantPercentQ: Exclude: - 'benchmarks/filter_object.rb' - 'features/step_definitions/additional_cli_steps.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/support/spec_files.rb' # Offense count: 11 # Cop supports --auto-correct. Style/RedundantRegexpEscape: Exclude: - 'features/step_definitions/additional_cli_steps.rb' - 'lib/rspec/core/configuration.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/formatters/profile_formatter_spec.rb' - 'spec/rspec/core/notifications_spec.rb' # Offense count: 11 # Cop supports --auto-correct. Style/RedundantSelf: Exclude: - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' # Offense count: 3 # Cop supports --auto-correct. Style/RescueModifier: Exclude: - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/reporter_spec.rb' # Offense count: 7 # Cop supports --auto-correct. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - 'lib/rspec/core/configuration_options.rb' - 'lib/rspec/core/drb.rb' - 'lib/rspec/core/example.rb' - 'lib/rspec/core/rake_task.rb' - 'lib/rspec/core/runner.rb' # Offense count: 1 # Cop supports --auto-correct. Style/SelfAssignment: Exclude: - 'spec/rspec/core/hooks_spec.rb' # Offense count: 59 # Cop supports --auto-correct. # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Exclude: - 'benchmarks/keys_each_vs_each_key.rb' - 'benchmarks/threadsafe_let_block.rb' - 'spec/rspec/core/aggregate_failures_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/example_spec.rb' - 'spec/rspec/core/filter_manager_spec.rb' - 'spec/rspec/core/formatters/json_formatter_spec.rb' - 'spec/rspec/core/hooks_filtering_spec.rb' - 'spec/rspec/core/hooks_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' # Offense count: 16 # Cop supports --auto-correct. # Configuration parameters: AllowIfMethodIsEmpty. Style/SingleLineMethods: Exclude: - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/shared_example_group_spec.rb' - 'spec/support/fake_libs/rspec/expectations.rb' - 'spec/support/fake_libs/rspec/mocks.rb' # Offense count: 42 # Cop supports --auto-correct. Style/StringConcatenation: Exclude: - 'features/step_definitions/additional_cli_steps.rb' - 'features/step_definitions/core_standalone_steps.rb' - 'lib/rspec/core/bisect/utilities.rb' - 'lib/rspec/core/did_you_mean.rb' - 'lib/rspec/core/example_group.rb' - 'lib/rspec/core/notifications.rb' - 'lib/rspec/core/option_parser.rb' - 'script/console' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/did_you_mean_spec.rb' - 'spec/rspec/core/formatters/base_text_formatter_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/option_parser_spec.rb' - 'spec/support/spec_files.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. # AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym Style/TrivialAccessors: Exclude: - 'benchmarks/define_method_v_attr_reader_v_def.rb' # Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, MinSize, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: Exclude: - 'spec/integration/order_spec.rb' - 'spec/rspec/core/configuration_options_spec.rb' - 'spec/rspec/core/configuration_spec.rb' - 'spec/rspec/core/example_group_spec.rb' - 'spec/rspec/core/formatters/snippet_extractor_spec.rb' - 'spec/rspec/core/memoized_helpers_spec.rb' - 'spec/rspec/core/shared_context_spec.rb' ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/rspec-core.gemspec0000664000000000000000000000463614557677674022301 0ustar rootroot# -*- encoding: utf-8 -*- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require "rspec/core/version" Gem::Specification.new do |s| s.name = "rspec-core" s.version = RSpec::Core::Version::STRING s.platform = Gem::Platform::RUBY s.license = "MIT" s.authors = ["Steven Baker", "David Chelimsky", "Chad Humphries", "Myron Marston"] s.email = "rspec@googlegroups.com" s.homepage = "https://github.com/rspec/rspec-core" s.summary = "rspec-core-#{RSpec::Core::Version::STRING}" s.description = "BDD for Ruby. RSpec runner and example groups." s.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-core/issues', 'changelog_uri' => "https://github.com/rspec/rspec-core/blob/v#{s.version}/Changelog.md", 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-core', } s.files = `git ls-files -- lib/*`.split("\n") s.files += %w[README.md LICENSE.md Changelog.md .yardopts .document] s.test_files = [] s.bindir = 'exe' s.executables = `git ls-files -- exe/*`.split("\n").map{ |f| File.basename(f) } s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" s.required_ruby_version = '>= 1.8.7' private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) s.signing_key = private_key s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')] end if RSpec::Core::Version::STRING =~ /[a-zA-Z]+/ # rspec-support is locked to our version when running pre,rc etc s.add_runtime_dependency "rspec-support", "= #{RSpec::Core::Version::STRING}" else # rspec-support must otherwise match our major/minor version s.add_runtime_dependency "rspec-support", "~> #{RSpec::Core::Version::STRING.split('.')[0..1].concat(['0']).join('.')}" end s.add_development_dependency "cucumber", ">= 1.3" s.add_development_dependency "minitest", "~> 5.3" s.add_development_dependency "aruba", "~> 0.14.9" s.add_development_dependency "coderay", "~> 1.1.1" s.add_development_dependency "mocha", "~> 0.13.0" s.add_development_dependency "rr", "~> 1.0.4" s.add_development_dependency "flexmock", "~> 0.9.0" s.add_development_dependency "thread_order", "~> 1.1.0" end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/maintenance-branch0000664000000000000000000000002114557677674022312 0ustar rootroot3-13-maintenance ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/README.md0000664000000000000000000002435714557677674020153 0ustar rootroot# rspec-core [![Build Status](https://github.com/rspec/rspec-core/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-core/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-core.svg)](https://codeclimate.com/github/rspec/rspec-core) rspec-core provides the structure for writing executable examples of how your code should behave, and an `rspec` command with tools to constrain which examples get run and tailor the output. ## Install gem install rspec # for rspec-core, rspec-expectations, rspec-mocks gem install rspec-core # for rspec-core only rspec --help Want to run against the `main` branch? You'll need to include the dependent RSpec repos as well. Add the following to your `Gemfile`: ```ruby %w[rspec rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main' end ``` ## Basic Structure RSpec uses the words "describe" and "it" so we can express concepts like a conversation: "Describe an order." "It sums the prices of its line items." ```ruby RSpec.describe Order do it "sums the prices of its line items" do order = Order.new order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(1.11, :USD) ))) order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(2.22, :USD), :quantity => 2 ))) expect(order.total).to eq(Money.new(5.55, :USD)) end end ``` The `describe` method creates an [ExampleGroup](http://rubydoc.info/gems/rspec-core/RSpec/Core/ExampleGroup). Within the block passed to `describe` you can declare examples using the `it` method. Under the hood, an example group is a class in which the block passed to `describe` is evaluated. The blocks passed to `it` are evaluated in the context of an _instance_ of that class. ## Nested Groups You can also declare nested groups using the `describe` or `context` methods: ```ruby RSpec.describe Order do context "with no items" do it "behaves one way" do # ... end end context "with one item" do it "behaves another way" do # ... end end end ``` Nested groups are subclasses of the outer example group class, providing the inheritance semantics you'd want for free. ## Aliases You can declare example groups using either `describe` or `context`. For a top level example group, `describe` and `context` are available off of `RSpec`. For backwards compatibility, they are also available off of the `main` object and `Module` unless you disable monkey patching. You can declare examples within a group using any of `it`, `specify`, or `example`. ## Shared Examples and Contexts Declare a shared example group using `shared_examples`, and then include it in any group using `include_examples`. ```ruby RSpec.shared_examples "collections" do |collection_class| it "is empty when first created" do expect(collection_class.new).to be_empty end end RSpec.describe Array do include_examples "collections", Array end RSpec.describe Hash do include_examples "collections", Hash end ``` Nearly anything that can be declared within an example group can be declared within a shared example group. This includes `before`, `after`, and `around` hooks, `let` declarations, and nested groups/contexts. You can also use the names `shared_context` and `include_context`. These are pretty much the same as `shared_examples` and `include_examples`, providing more accurate naming when you share hooks, `let` declarations, helper methods, etc, but no examples. If you want to reuse shared examples or contexts across your RSpec suite you can define them in a stand alone _*.rb_ files (_spec/support/shared_examples/definition.rb_ for example). But you will have to manually `require` them (there is no autoloading of _spec/support/_ directory unless you set it up yourself). ## Metadata rspec-core stores a metadata hash with every example and group, which contains their descriptions, the locations at which they were declared, etc, etc. This hash powers many of rspec-core's features, including output formatters (which access descriptions and locations), and filtering before and after hooks. Although you probably won't ever need this unless you are writing an extension, you can access it from an example like this: ```ruby it "does something" do |example| expect(example.metadata[:description]).to eq("does something") end ``` ### `described_class` When a class is passed to `describe`, you can access it from an example using the `described_class` method, which is a wrapper for `example.metadata[:described_class]`. ```ruby RSpec.describe Widget do example do expect(described_class).to equal(Widget) end end ``` This is useful in extensions or shared example groups in which the specific class is unknown. Taking the collections shared example group from above, we can clean it up a bit using `described_class`: ```ruby RSpec.shared_examples "collections" do it "is empty when first created" do expect(described_class.new).to be_empty end end RSpec.describe Array do include_examples "collections" end RSpec.describe Hash do include_examples "collections" end ``` ## A Word on Scope RSpec has two scopes: * **Example Group**: Example groups are defined by a `describe` or `context` block, which is eagerly evaluated when the spec file is loaded. The block is evaluated in the context of a subclass of `RSpec::Core::ExampleGroup`, or a subclass of the parent example group when you're nesting them. * **Example**: Examples -- typically defined by an `it` block -- and any other blocks with per-example semantics -- such as a `before(:example)` hook -- are evaluated in the context of an _instance_ of the example group class to which the example belongs. Examples are _not_ executed when the spec file is loaded; instead, RSpec waits to run any examples until all spec files have been loaded, at which point it can apply filtering, randomization, etc. To make this more concrete, consider this code snippet: ``` ruby RSpec.describe "Using an array as a stack" do def build_stack [] end before(:example) do @stack = build_stack end it 'is initially empty' do expect(@stack).to be_empty end context "after an item has been pushed" do before(:example) do @stack.push :item end it 'allows the pushed item to be popped' do expect(@stack.pop).to eq(:item) end end end ``` Under the covers, this is (roughly) equivalent to: ``` ruby class UsingAnArrayAsAStack < RSpec::Core::ExampleGroup def build_stack [] end def before_example_1 @stack = build_stack end def it_is_initially_empty expect(@stack).to be_empty end class AfterAnItemHasBeenPushed < self def before_example_2 @stack.push :item end def it_allows_the_pushed_item_to_be_popped expect(@stack.pop).to eq(:item) end end end ``` To run these examples, RSpec would (roughly) do the following: ``` ruby example_1 = UsingAnArrayAsAStack.new example_1.before_example_1 example_1.it_is_initially_empty example_2 = UsingAnArrayAsAStack::AfterAnItemHasBeenPushed.new example_2.before_example_1 example_2.before_example_2 example_2.it_allows_the_pushed_item_to_be_popped ``` ## The `rspec` Command When you install the rspec-core gem, it installs the `rspec` executable, which you'll use to run rspec. The `rspec` command comes with many useful options. Run `rspec --help` to see the complete list. ## Store Command Line Options `.rspec` You can store command line options in a `.rspec` file in the project's root directory, and the `rspec` command will read them as though you typed them on the command line. ## Get Started Start with a simple example of behavior you expect from your system. Do this before you write any implementation code: ```ruby # in spec/calculator_spec.rb RSpec.describe Calculator do describe '#add' do it 'returns the sum of its arguments' do expect(Calculator.new.add(1, 2)).to eq(3) end end end ``` Run this with the rspec command, and watch it fail: ``` $ rspec spec/calculator_spec.rb ./spec/calculator_spec.rb:1: uninitialized constant Calculator ``` Address the failure by defining a skeleton of the `Calculator` class: ```ruby # in lib/calculator.rb class Calculator def add(a, b) end end ``` Be sure to require the implementation file in the spec: ```ruby # in spec/calculator_spec.rb # - RSpec adds ./lib to the $LOAD_PATH require "calculator" ``` Now run the spec again, and watch the expectation fail: ``` $ rspec spec/calculator_spec.rb F Failures: 1) Calculator#add returns the sum of its arguments Failure/Error: expect(Calculator.new.add(1, 2)).to eq(3) expected: 3 got: nil (compared using ==) # ./spec/calculator_spec.rb:6:in `block (3 levels) in ' Finished in 0.00131 seconds (files took 0.10968 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/calculator_spec.rb:5 # Calculator#add returns the sum of its arguments ``` Implement the simplest solution, by changing the definition of `Calculator#add` to: ```ruby def add(a, b) a + b end ``` Now run the spec again, and watch it pass: ``` $ rspec spec/calculator_spec.rb . Finished in 0.000315 seconds 1 example, 0 failures ``` Use the `documentation` formatter to see the resulting spec: ``` $ rspec spec/calculator_spec.rb --format doc Calculator #add returns the sum of its arguments Finished in 0.000379 seconds 1 example, 0 failures ``` ## Contributing Once you've set up the environment, you'll need to cd into the working directory of whichever repo you want to work in. From there you can run the specs and cucumber features, and make patches. NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You can treat each RSpec repo as an independent project. * [Build details](BUILD_DETAIL.md) * [Code of Conduct](CODE_OF_CONDUCT.md) * [Detailed contributing guide](CONTRIBUTING.md) * [Development setup guide](DEVELOPMENT.md) ## Also see * [https://github.com/rspec/rspec](https://github.com/rspec/rspec) * [https://github.com/rspec/rspec-expectations](https://github.com/rspec/rspec-expectations) * [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks) * [https://github.com/rspec/rspec-rails](https://github.com/rspec/rspec-rails) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/exe/0000775000000000000000000000000014557677674017442 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/exe/rspec0000775000000000000000000000010514557677674020500 0ustar rootroot#!/usr/bin/env ruby require 'rspec/core' RSpec::Core::Runner.invoke ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Rakefile0000664000000000000000000000211614557677674020326 0ustar rootrootrequire "bundler" Bundler.setup Bundler::GemHelper.install_tasks require "rake" require "yaml" 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 namespace :spec do desc "Run ui examples" RSpec::Core::RakeTask.new(:ui) do |t| t.ruby_opts = %w[-w] t.rspec_opts = %w[--tag ui] end end desc 'Run RuboCop on the lib directory' task :rubocop do sh 'bundle exec rubocop lib' end desc "delete generated files" task :clobber do sh 'find . -name "*.rbc" | xargs rm' sh 'rm -rf pkg' sh 'rm -rf tmp' sh 'rm -rf coverage' sh 'rm -rf .yardoc' sh 'rm -rf doc' end desc "generate rdoc" task :rdoc do sh "yardoc" end task :default => [:spec, :cucumber, :rubocop] task :verify_private_key_present do private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') unless File.exist?(private_key) raise "Your private key is not present. This gem should not be built without it." end end task :build => :verify_private_key_present ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/0000775000000000000000000000000014557677674017613 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/0000775000000000000000000000000014557677674020727 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/0000775000000000000000000000000014557677674021657 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/warnings_spec.rb0000664000000000000000000000465514557677674025060 0ustar rootrootRSpec.describe "rspec warnings and deprecations" do describe "#deprecate" do it "passes the hash to the reporter" do expect(RSpec.configuration.reporter).to receive(:deprecation).with(hash_including :deprecated => "deprecated_method", :replacement => "replacement") RSpec.deprecate("deprecated_method", :replacement => "replacement") end it "adds the call site" do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) RSpec.deprecate("deprecated_method") end it "doesn't override a passed call site" do expect_deprecation_with_call_site("some_file.rb", 17) RSpec.deprecate("deprecated_method", :call_site => "/some_file.rb:17") end end describe "#warn_deprecation" do it "puts message in a hash" do expect(RSpec.configuration.reporter).to receive(:deprecation).with(hash_including :message => "this is the message") RSpec.warn_deprecation("this is the message") end it "passes along additional options" do expect(RSpec.configuration.reporter).to receive(:deprecation).with(hash_including :type => :tag) RSpec.warn_deprecation("this is the message", :type => :tag) end end describe "#warn_with" do context "when :use_spec_location_as_call_site => true is passed" do let(:options) do { :use_spec_location_as_call_site => true, :call_site => nil, } end it "adds the source location of spec" do line = __LINE__ - 1 file_path = RSpec::Core::Metadata.relative_path(__FILE__) expect(Kernel).to receive(:warn).with(/The warning. Warning generated from spec at `#{file_path}:#{line}`./) RSpec.warn_with("The warning.", options) end it "appends a period to the supplied message if one is not present" do line = __LINE__ - 1 file_path = RSpec::Core::Metadata.relative_path(__FILE__) expect(Kernel).to receive(:warn).with(/The warning. Warning generated from spec at `#{file_path}:#{line}`./) RSpec.warn_with("The warning", options) end context "when there is no current example" do before do allow(RSpec).to receive(:current_example).and_return(nil) end it "adds no message about the spec location" do expect(Kernel).to receive(:warn).with(/The warning\.$/) RSpec.warn_with("The warning.", options) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/example_group_constants_spec.rb0000664000000000000000000000073314557677674030164 0ustar rootroot# encoding: utf-8 RSpec.describe "::RSpec::Core::ExampleGroup" do context "does not cause problems when users reference a top level constant of the same name" do file_in_outer_group = File example { expect(File).to eq ::File } example { expect(file_in_outer_group).to be(::File) } describe "File" do file_in_inner_group = File example { expect(File).to eq ::File } example { expect(file_in_inner_group).to be(::File) } end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/notifications_spec.rb0000664000000000000000000004016414557677674026074 0ustar rootrootrequire 'rspec/core/notifications' # ANSI codes aren't easy to read in failure output, so use tags instead class TagColorizer def self.wrap(text, code_or_symbol) "<#{code_or_symbol}>#{text}" end end RSpec.describe "FailedExampleNotification" do include FormatterSupport let(:example) { new_example(:status => :failed) } exception_line = __LINE__ + 1 let(:exception) { instance_double(Exception, :backtrace => [ "#{__FILE__}:#{exception_line}"], :message => 'Test exception') } let(:notification) { ::RSpec::Core::Notifications::ExampleNotification.for(example) } before do example.execution_result.exception = exception example.metadata[:absolute_file_path] = __FILE__ end it 'provides a description' do expect(notification.description).to eq(example.full_description) end it 'provides `colorized_formatted_backtrace`, which formats the backtrace and colorizes it' do allow(exception).to receive(:cause) if RSpec::Support::RubyFeatures.supports_exception_cause? allow(RSpec.configuration).to receive(:color_enabled?).and_return(true) expect(notification.colorized_formatted_backtrace).to eq(["\e[36m# #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{exception_line}\e[0m"]) end describe "fully formatted failure output" do def fully_formatted(*args) notification.fully_formatted(1, *args) end def dedent(string) string.gsub(/^ +\|/, '') end context "when the exception is a MultipleExpectationsNotMetError" do RSpec::Matchers.define :fail_with_description do |desc| match { false } description { desc } failure_message { "expected pass, but #{desc}" } end def capture_and_normalize_aggregation_error yield rescue RSpec::Expectations::MultipleExpectationsNotMetError => failure normalize_backtraces(failure) failure end def normalize_backtraces(failure) failure.all_exceptions.each do |exception| if exception.is_a?(RSpec::Expectations::MultipleExpectationsNotMetError) normalize_backtraces(exception) end normalize_one_backtrace(exception) end normalize_one_backtrace(failure) end def normalize_one_backtrace(exception) line = exception.backtrace.find { |l| l.include?(__FILE__) } exception.set_backtrace([ line.sub(/:in .*$/, '') ]) end let(:aggregate_line) { __LINE__ + 3 } let(:exception) do capture_and_normalize_aggregation_error do aggregate_failures("multiple expectations") do expect(1).to fail_with_description("foo") expect(1).to fail_with_description("bar") end end end it 'provides a summary composed of example description, failure count and aggregate backtrace' do expect(fully_formatted.lines.first(5)).to eq(dedent(<<-EOS).lines.to_a) | | 1) Example | Got 2 failures from failure aggregation block "multiple expectations". | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line} | EOS end it 'lists each individual expectation failure, with a backtrace relative to the aggregation block' do expect(fully_formatted.lines.to_a.last(8)).to eq(dedent(<<-EOS).lines.to_a) | | 1.1) Failure/Error: expect(1).to fail_with_description("foo") | expected pass, but foo | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 1} | | 1.2) Failure/Error: expect(1).to fail_with_description("bar") | expected pass, but bar | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 2} EOS end it 'uses the `failure` color in the summary output' do expect(fully_formatted(TagColorizer)).to include( 'Got 2 failures from failure aggregation block "multiple expectations".' ) end it 'uses the `failure` color for the sub-failure messages' do expect(fully_formatted(TagColorizer)).to include( ' expected pass, but foo', ' expected pass, but bar' ) end context "due to using `:aggregate_failures` metadata" do let(:exception) do ex = nil RSpec.describe do ex = it "", :aggregate_failures do expect(1).to fail_with_description("foo") expect(1).to fail_with_description("bar") end end.run capture_and_normalize_aggregation_error { raise ex.execution_result.exception } end it 'uses an alternate format for the exception summary to avoid confusing references to the aggregation block or stack trace' do expect(fully_formatted.lines.first(4)).to eq(dedent(<<-EOS).lines.to_a) | | 1) Example | Got 2 failures: | EOS end end context "when the failure happened in a shared example group" do before do |ex| example.metadata[:shared_group_inclusion_backtrace] << RSpec::Core::SharedExampleGroupInclusionStackFrame.new( "Stuff", "./some_shared_group_file.rb:13" ) end it "includes the shared group backtrace as part of the aggregate failure backtrace" do expect(fully_formatted.lines.first(6)).to eq(dedent(<<-EOS).lines.to_a) | | 1) Example | Got 2 failures from failure aggregation block "multiple expectations". | Shared Example Group: "Stuff" called from ./some_shared_group_file.rb:13 | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line} | EOS end it "does not include the shared group backtrace in the sub-failure backtraces" do expect(fully_formatted.lines.to_a.last(8)).to eq(dedent(<<-EOS).lines.to_a) | | 1.1) Failure/Error: expect(1).to fail_with_description("foo") | expected pass, but foo | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 1} | | 1.2) Failure/Error: expect(1).to fail_with_description("bar") | expected pass, but bar | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 2} EOS end end context "when `aggregate_failures` is used in nested fashion" do let(:aggregate_line) { __LINE__ + 3 } let(:exception) do capture_and_normalize_aggregation_error do aggregate_failures("outer") do expect(1).to fail_with_description("foo") aggregate_failures("inner") do expect(2).to fail_with_description("bar") expect(3).to fail_with_description("baz") end expect(1).to fail_with_description("qux") end end end it 'recursively formats the nested aggregated failures' do expect(fully_formatted).to eq(dedent <<-EOS) | | 1) Example | Got 3 failures from failure aggregation block "outer". | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line} | | 1.1) Failure/Error: expect(1).to fail_with_description("foo") | expected pass, but foo | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 1} | | 1.2) Got 2 failures from failure aggregation block "inner". | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 3} | | 1.2.1) Failure/Error: expect(2).to fail_with_description("bar") | expected pass, but bar | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 4} | | 1.2.2) Failure/Error: expect(3).to fail_with_description("baz") | expected pass, but baz | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 5} | | 1.3) Failure/Error: expect(1).to fail_with_description("qux") | expected pass, but qux | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 8} EOS end end context "when there are failures and other errors" do let(:aggregate_line) { __LINE__ + 3 } let(:exception) do capture_and_normalize_aggregation_error do aggregate_failures("multiple expectations") do expect(1).to fail_with_description("foo") raise "boom" end end end it 'lists both types in the exception listing' do expect(fully_formatted.lines.to_a.last(10)).to eq(dedent(<<-EOS).lines.to_a) | | 1.1) Failure/Error: expect(1).to fail_with_description("foo") | expected pass, but foo | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 1} | | 1.2) Failure/Error: raise "boom" | | RuntimeError: | boom | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line + 2} EOS end end context "in a pending spec" do before do example.execution_result.status = :pending example.execution_result.pending_message = 'Some pending reason' example.execution_result.pending_exception = exception example.execution_result.exception = nil end it 'includes both the pending message and aggregate summary' do expect(fully_formatted.lines.first(6)).to eq(dedent(<<-EOS).lines.to_a) | | 1) Example | # Some pending reason | Got 2 failures from failure aggregation block "multiple expectations". | # #{RSpec::Core::Metadata.relative_path(__FILE__)}:#{aggregate_line} | EOS end it 'uses the `pending` color in the summary output' do expect(fully_formatted(TagColorizer)).to include( 'Got 2 failures from failure aggregation block "multiple expectations".' ) end it 'uses the `pending` color for the sub-failure messages' do expect(fully_formatted(TagColorizer)).to include( ' expected pass, but foo', ' expected pass, but bar' ) end end end context "when the exception is a MultipleExceptionError" do let(:sub_failure_1) { StandardError.new("foo").tap { |e| e.set_backtrace([]) } } let(:sub_failure_2) { StandardError.new("bar").tap { |e| e.set_backtrace([]) } } let(:exception) { RSpec::Core::MultipleExceptionError.new(sub_failure_1, sub_failure_2) } it "lists each sub-failure, just like with MultipleExpectationsNotMetError" do expect(fully_formatted.lines.to_a.last(10)).to eq(dedent(<<-EOS).lines.to_a) | | 1.1) Failure/Error: Unable to find matching line from backtrace | | StandardError: | foo | | 1.2) Failure/Error: Unable to find matching line from backtrace | | StandardError: | bar EOS end end end describe '#message_lines' do let(:example_group) { class_double(RSpec::Core::ExampleGroup, :metadata => {}, :parent_groups => [], :location => "#{__FILE__}:#{__LINE__}") } before do allow(example).to receive(:example_group) { example_group } end it 'should return failure_lines without color' do lines = notification.message_lines expect(lines[0]).to match %r{\AFailure\/Error} expect(lines[1]).to match %r{\A\s*Test exception\z} end it 'returns failures_lines without color when they are part of a shared example group' do example.metadata[:shared_group_inclusion_backtrace] << RSpec::Core::SharedExampleGroupInclusionStackFrame.new("foo", "bar") lines = notification.message_lines expect(lines[0]).to match %r{\AFailure\/Error} expect(lines[1]).to match %r{\A\s*Test exception\z} end if String.method_defined?(:encoding) it "returns failures_lines with invalid bytes replace by '?'" do message_with_invalid_byte_sequence = "\xEF \255 \xAD I have bad bytes".dup.force_encoding(Encoding::UTF_8) allow(exception).to receive(:message). and_return(message_with_invalid_byte_sequence) lines = notification.message_lines expect(lines[0]).to match %r{\AFailure\/Error} expect(lines[1].strip).to eq("? ? ? I have bad bytes") end end end end module RSpec::Core::Notifications RSpec.describe ExamplesNotification do include FormatterSupport describe "#notifications" do it 'returns an array of notification objects for all the examples' do reporter = RSpec::Core::Reporter.new(RSpec.configuration) example = new_example reporter.example_started(example) reporter.example_passed(example) notification = ExamplesNotification.new(reporter) expect(notification.notifications).to match [ an_instance_of(ExampleNotification) & an_object_having_attributes(:example => example) ] end end end end module RSpec::Core::Notifications RSpec.describe SummaryNotification do include FormatterSupport subject(:notification) do summary_notification( duration, examples, failed_examples, pending_examples, load_time, errors_outside_of_examples_count ) end let(:duration) do 1.23 end let(:examples) do [ new_example(:status => :passed), new_example(:status => :passed) ] end let(:failed_examples) do examples.select { |example| example.execution_result.status == :failed } end let(:pending_examples) do examples.select { |example| example.execution_result.status == :pending } end let(:load_time) do 0.1 end let(:errors_outside_of_examples_count) do 0 end describe '#fully_formatted' do subject(:fully_formatted) do notification.fully_formatted(TagColorizer) end context 'when all examples are passed' do let(:examples) do [ new_example(:status => :passed), new_example(:status => :passed) ] end it 'turns the summary line green' do expect(fully_formatted).to include('2 examples, 0 failures') end end context "when there're a pending example and no failed example" do let(:examples) do [ new_example(:status => :passed), new_example(:status => :pending) ] end it 'turns the summary line yellow' do expect(fully_formatted).to include('2 examples, 0 failures, 1 pending') end end context "when there're a pending example and a failed example" do let(:examples) do [ new_example(:status => :passed), new_example(:status => :pending), new_example(:status => :failed) ] end it 'turns the summary line red' do expect(fully_formatted).to include('3 examples, 1 failure, 1 pending') end end context "when there's an error outside of examples" do let(:errors_outside_of_examples_count) do 1 end it 'turns the summary line red' do expect(fully_formatted).to include('2 examples, 0 failures, 1 error occurred outside of examples') end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/metadata_spec.rb0000664000000000000000000007274714557677674025017 0ustar rootrootmodule RSpec module Core RSpec.describe Metadata do describe '.relative_path' do let(:here) { File.expand_path(".") } it "transforms absolute paths to relative paths" do expect(Metadata.relative_path(here)).to eq "." end it "transforms absolute paths to relative paths anywhere in its argument" do expect(Metadata.relative_path("foo #{here} bar")).to eq "foo . bar" end it "returns nil if passed an unparseable file:line combo" do expect(Metadata.relative_path("-e:1")).to be_nil end # I have no idea what line = line.sub(/\A([^:]+:\d+)$/, '\\1') is supposed to do it "gracefully returns nil if run in a secure thread" do # Ensure our call to `File.expand_path` is not cached as that is the insecure operation. Metadata.instance_eval { @relative_path_regex = nil } value = with_safe_set_to_level_that_triggers_security_errors do Metadata.relative_path(".") end # on some rubies, File.expand_path is not a security error, so accept "." as well expect([nil, "."]).to include(value) end it 'should not transform directories beginning with the same prefix' do #E.g. /foo/bar_baz is not relative to /foo/bar !! similar_directory = "#{File.expand_path(".")}_similar" expect(Metadata.relative_path(similar_directory)).to eq similar_directory end end specify 'RESERVED_KEYS contains all keys assigned by RSpec (and vice versa)' do group = RSpec.describe("group") example = group.example("example") { } nested_group = group.describe("nested") assigned_keys = group.metadata.keys | example.metadata.keys | nested_group.metadata.keys expect(RSpec::Core::Metadata::RESERVED_KEYS).to match_array(assigned_keys) end context "when created" do Metadata::RESERVED_KEYS.each do |key| it "prohibits :#{key} as a hash key for an example group" do expect { RSpec.describe("group", key => {}) }.to raise_error(/:#{key} is not allowed/) end it "prohibits :#{key} as a hash key for an example" do group = RSpec.describe("group") expect { group.example("example", key => {}) }.to raise_error(/:#{key} is not allowed/) end end it "uses :caller if passed as part of the user metadata" do m = nil RSpec.describe('group', :caller => ['example_file:42']) do m = metadata end expect(m[:location]).to eq("example_file:42") end end context "for an example" do let(:line_number) { __LINE__ + 3 } def metadata_for(*args) RSpec.describe("group description") do return example(*args).metadata end end alias example_metadata metadata_for RSpec::Matchers.define :have_value do |value| chain(:for) { |key| @key = key } match do |meta| expect(meta.fetch(@key)).to eq(value) expect(meta[@key]).to eq(value) end end it "stores the description args" do expect(metadata_for "example description").to have_value(["example description"]).for(:description_args) end it "ignores nil description args" do expect(example_metadata).to have_value([]).for(:description_args) end it "stores the full_description (group description + example description)" do expect(metadata_for "example description").to have_value("group description example description").for(:full_description) end it "creates an empty execution result" do expect(example_metadata[:execution_result].to_h.reject { |_, v| v.nil? } ).to eq({}) end it "extracts file path from caller" do expect(example_metadata).to have_value(relative_path(__FILE__)).for(:file_path) end it "extracts line number from caller" do expect(example_metadata).to have_value(line_number).for(:line_number) end it "extracts location from caller" do expect(example_metadata).to have_value("#{relative_path(__FILE__)}:#{line_number}").for(:location) end it "uses :caller if passed as an option" do example_metadata = metadata_for('example description', :caller => ['example_file:42']) expect(example_metadata).to have_value("example_file:42").for(:location) end it "merges arbitrary options" do expect(metadata_for("desc", :arbitrary => :options)).to have_value(:options).for(:arbitrary) end it "points :example_group to the same hash object as other examples in the same group" do a = b = nil RSpec.describe "group" do a = example("foo").metadata[:example_group] b = example("bar").metadata[:example_group] end a[:description] = "new description" pending "Cannot maintain this and provide full `:example_group` backwards compatibility (see GH #1490):(" expect(b[:description]).to eq("new description") end it 'does not include example-group specific keys' do example_meta = nil group_meta = nil RSpec.describe "group" do context "nested" do group_meta = metadata example_meta = example("foo").metadata end end expect(group_meta.keys - example_meta.keys).to contain_exactly(:parent_example_group) end end context "for an example group" do it 'does not include example specific keys' do example_meta = nil group_meta = nil RSpec.describe "group" do context "nested" do group_meta = metadata example_meta = example("foo").metadata end end expect(example_meta.keys - group_meta.keys).to contain_exactly( :execution_result, :last_run_status, :skip, :shared_group_inclusion_backtrace, :example_group ) end end describe ":block" do context "for example group metadata" do it "contains the example group block" do block = Proc.new { } group = RSpec.describe("group", &block) expect(group.metadata[:block]).to equal(block) end end context "for example metadata" do it "contains the example block" do block = Proc.new { } group = RSpec.describe("group") example = group.example("example", &block) expect(example.metadata[:block]).to equal(block) end end end describe ":last_run_status" do it 'assigns it by looking up configuration.last_run_statuses[id]' do looked_up_ids = [] last_run_statuses = Hash.new do |hash, id| looked_up_ids << id "some_status" end allow(RSpec.configuration).to receive(:last_run_statuses).and_return(last_run_statuses) example = RSpec.describe.example expect(example.metadata[:last_run_status]).to eq("some_status") expect(looked_up_ids).to eq [example.id] end end describe ":id" do define :have_id_with do |scoped_id| expected_id = "#{Metadata.relative_path(__FILE__)}[#{scoped_id}]" match do |group_or_example| group_or_example.metadata[:scoped_id] == scoped_id && group_or_example.id == expected_id end failure_message do |group_or_example| "expected #{group_or_example.inspect}\n" \ " to have id: #{expected_id}\n" \ " but had id: #{group_or_example.id}\n" \ " and have scoped id: #{scoped_id}\n" \ " but had scoped id: #{group_or_example.metadata[:scoped_id]}" end end context "on a top-level group" do it "is set to file[]" do expect(RSpec.describe).to have_id_with("1") expect(RSpec.describe).to have_id_with("2") end it "starts the count at 1 for each file" do instance_eval <<-EOS, "spec_1.rb", 1 $group_1 = RSpec.describe $group_2 = RSpec.describe EOS instance_eval <<-EOS, "spec_2.rb", 1 $group_3 = RSpec.describe $group_4 = RSpec.describe EOS expect($group_1.id).to end_with("spec_1.rb[1]") expect($group_2.id).to end_with("spec_1.rb[2]") expect($group_3.id).to end_with("spec_2.rb[1]") expect($group_4.id).to end_with("spec_2.rb[2]") end end context "on a nested group" do it "is set to file[:]" do top_level_group = RSpec.describe expect(top_level_group.describe).to have_id_with("1:1") expect(top_level_group.describe).to have_id_with("1:2") end end context "on an example" do it "is set to file[:]" do group = RSpec.describe expect(group.example).to have_id_with("1:1") expect(group.example).to have_id_with("1:2") end end context "when examples are interleaved with example groups" do it "counts both when assigning the index" do group = RSpec.describe expect(group.example ).to have_id_with("1:1") expect(group.describe).to have_id_with("1:2") expect(group.example ).to have_id_with("1:3") expect(group.example ).to have_id_with("1:4") expect(group.describe).to have_id_with("1:5") end end context "on an example defined in a shared group defined in a separate file" do it "uses the host group's file name as the prefix" do # Using eval in order to make ruby think this got defined in another file. instance_eval <<-EOS, "some/external/file.rb", 1 RSpec.shared_examples "shared" do example { } end EOS group = RSpec.describe { include_examples "shared" } expect(group.examples.first.id).to start_with(Metadata.relative_path(__FILE__)) end end end describe ":shared_group_inclusion_backtrace" do context "for an example group" do it "is not set since we do not yet need it internally (but we can add it in the future if needed)" do group = RSpec.describe("group") expect(group.metadata).not_to include(:shared_group_inclusion_backtrace) end end context "for an example" do context "not generated by a shared group" do it "is a blank array" do meta = nil RSpec.describe { meta = example { }.metadata } expect(meta).to include(:shared_group_inclusion_backtrace => []) end end context "generated by an unnested shared group included via metadata" do it "is an array containing an object with shared group name and inclusion location" do meta = nil RSpec.shared_examples_for("some shared behavior", :include_it => true) do meta = example { }.metadata end line = __LINE__ + 1 RSpec.describe("Group", :include_it => true) { } expect(meta[:shared_group_inclusion_backtrace]).to match [ an_object_having_attributes( :shared_group_name => "some shared behavior", :inclusion_location => a_string_including("#{Metadata.relative_path __FILE__}:#{line}") ) ] end end { :it_behaves_like => "generates a nested group", :include_examples => "adds the examples directly to the host group" }.each do |inclusion_method, description| context "generated by an unnested shared group using an inclusion method that #{description}" do it "is an array containing an object with shared group name and inclusion location" do meta = nil RSpec.shared_examples_for("some shared behavior") do meta = example { }.metadata end line = __LINE__ + 2 RSpec.describe do __send__ inclusion_method, "some shared behavior" end expect(meta[:shared_group_inclusion_backtrace]).to match [ an_object_having_attributes( :shared_group_name => "some shared behavior", :inclusion_location => a_string_including("#{Metadata.relative_path __FILE__}:#{line}") ) ] end end context "generated by a nested shared group using an inclusion method that #{description}" do it "contains a stack frame for each inclusion, in the same order as ruby backtraces" do meta = nil RSpec.shared_examples_for "inner" do meta = example { }.metadata end inner_line = __LINE__ + 2 RSpec.shared_examples_for "outer" do __send__ inclusion_method, "inner" end outer_line = __LINE__ + 2 RSpec.describe do __send__ inclusion_method, "outer" end expect(meta[:shared_group_inclusion_backtrace]).to match [ an_object_having_attributes( :shared_group_name => "inner", :inclusion_location => a_string_including("#{Metadata.relative_path __FILE__}:#{inner_line}") ), an_object_having_attributes( :shared_group_name => "outer", :inclusion_location => a_string_including("#{Metadata.relative_path __FILE__}:#{outer_line}") ), ] end end end end end describe ":described_class" do value_from = lambda do |group| group.metadata[:described_class] end context "in an outer group" do define_method :value_for do |arg| value_from[RSpec.describe(arg)] end context "with a String" do it "returns nil" do expect(value_for "group").to be_nil end end context "with a Symbol" do it "returns the symbol" do expect(value_for :group).to be(:group) end end context "with a class" do it "returns the class" do expect(value_for String).to be(String) end context "when the class is Regexp" do it "returns the class" do expect(value_for Regexp).to be(Regexp) end end end end context "in a nested group" do it "inherits the parent group's described class" do value = nil RSpec.describe(Hash) do describe "sub context" do value = value_from[self] end end expect(value).to be(Hash) end it "sets the described class when passing a class" do value = nil RSpec.describe(String) do describe Array do value = value_from[self] end end expect(value).to be(Array) end it 'does not override the :described_class when passing no describe args' do value = nil RSpec.describe(String) do describe do value = value_from[self] end end expect(value).to be(String) end it "can override a parent group's described class using metadata" do parent_value = child_value = grandchild_value = nil RSpec.describe(String) do parent_value = value_from[self] describe "sub context" do metadata[:described_class] = Hash child_value = value_from[self] describe "sub context" do grandchild_value = value_from[self] end end end expect(grandchild_value).to be(Hash) expect(child_value).to be(Hash) expect(parent_value).to be(String) end end end describe ":description" do context "on a example" do it "just has the example description" do value = nil RSpec.describe "group" do value = example("example").metadata[:description] end expect(value).to eq("example") end end context "on a group" do def group_value_for(*args) value = nil RSpec.describe(*args) do value = metadata[:description] end value end context "with a string" do it "provides the submitted description" do expect(group_value_for "group").to eq("group") end end context "with a non-string" do it "provides the string form of the submitted object" do expect(group_value_for Hash).to eq("Hash") end end context "with a non-string and a string" do it "concats the args" do expect(group_value_for Object, 'group').to eq("Object group") end end context "with a string and a non-string" do it "concats the args" do expect(group_value_for 'group', Object).to eq("group Object") end end context "with empty args" do it "returns empty string for [:description]" do expect(group_value_for()).to eq("") end end end end describe ":full_description" do context "on an example" do it "concats example group name and description" do value = nil RSpec.describe "group" do value = example("example").metadata[:full_description] end expect(value).to eq("group example") end end it "omits description from groups with a `nil` description" do value = nil RSpec.describe do value = example("example").metadata[:full_description] end expect(value).to eq("example") end it "omits description from groups with a description of `''`" do value = nil RSpec.describe "" do value = example("example").metadata[:full_description] end expect(value).to eq("example") end it "concats nested example group descriptions" do group_value = example_value = nil RSpec.describe "parent" do describe "child" do group_value = metadata[:full_description] example_value = example("example").metadata[:full_description] end end expect(group_value).to eq("parent child") expect(example_value).to eq("parent child example") end it "concats nested example group descriptions three deep" do grandparent_value = parent_value = child_value = example_value = nil RSpec.describe "grandparent" do grandparent_value = metadata[:full_description] describe "parent" do parent_value = metadata[:full_description] describe "child" do child_value = metadata[:full_description] example_value = example("example").metadata[:full_description] end end end expect(grandparent_value).to eq("grandparent") expect(parent_value).to eq("grandparent parent") expect(child_value).to eq("grandparent parent child") expect(example_value).to eq("grandparent parent child example") end %w[# . ::].each do |char| context "with a 2nd arg starting with #{char}" do it "removes the space" do value = nil RSpec.describe Array, "#{char}method" do value = metadata[:full_description] end expect(value).to eq("Array#{char}method") end end context "with a description starting with #{char} nested under a module" do it "removes the space" do value = nil RSpec.describe Object do describe "#{char}method" do value = metadata[:full_description] end end expect(value).to eq("Object#{char}method") end end context "with a description starting with #{char} nested under a context string" do it "does not remove the space" do value = nil RSpec.describe(Array) do context "with 2 items" do describe "#{char}method" do value = metadata[:full_description] end end end expect(value).to eq("Array with 2 items #{char}method") end end end end describe ":file_path" do it "finds the first non-rspec lib file in the caller array" do value = nil RSpec.describe(:caller => ["./lib/rspec/core/foo.rb", "#{__FILE__}:#{__LINE__}"]) do value = metadata[:file_path] end expect(value).to eq(relative_path(__FILE__)) end end describe ":line_number" do def value_for(*args) value = nil @describe_line = __LINE__ + 1 RSpec.describe("group", *args) do value = metadata[:line_number] end value end it "finds the line number with the first non-rspec lib file in the backtrace" do expect(value_for()).to eq(@describe_line) end it "finds the line number with the first spec file with drive letter" do expect(value_for(:caller => [ "C:/path/to/file_spec.rb:#{__LINE__}" ])).to eq(__LINE__) end it "uses the number after the first : for ruby 1.9" do expect(value_for(:caller => [ "#{__FILE__}:#{__LINE__}:999" ])).to eq(__LINE__) end end describe "child example group" do it "nests the parent's example group metadata" do child = parent = nil RSpec.describe Object, "parent" do parent = metadata describe { child = metadata } end expect(child[:parent_example_group]).to eq(parent) end end it 'does not have a `:parent_example_group` key for a top level group' do meta = RSpec.describe(Object).metadata expect(meta).not_to include(:parent_example_group) end describe "backwards compatibility" do before { allow_deprecation } describe ":example_group" do it 'issues a deprecation warning when the `:example_group` key is accessed' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /:example_group/) RSpec.describe(Object, "group") do metadata[:example_group] end end it 'does not issue a deprecation warning when :example_group is accessed while applying configured filterings' do RSpec.configuration.include Module.new, :example_group => { :file_path => /.*/ } expect_no_deprecation RSpec.describe(Object, "group") end it 'can still access the example group attributes via [:example_group]' do meta = nil RSpec.describe(Object, "group") { meta = metadata } expect(meta[:example_group][:line_number]).to eq(__LINE__ - 2) expect(meta[:example_group][:description]).to eq("Object group") end it 'can access the parent example group attributes via [:example_group][:example_group]' do child = nil parent_line = __LINE__ + 1 RSpec.describe(Object, "group", :foo => 3) do describe("nested") { child = metadata } end expect(child[:example_group][:example_group].to_h).to include( :foo => 3, :description => "Object group", :line_number => parent_line ) end it "works properly with deep nesting" do inner_metadata = nil RSpec.describe "Level 1" do describe "Level 2" do describe "Level 3" do inner_metadata = example("Level 4").metadata end end end expect(inner_metadata[:description]).to eq("Level 4") expect(inner_metadata[:example_group][:description]).to eq("Level 3") expect(inner_metadata[:example_group][:example_group][:description]).to eq("Level 2") expect(inner_metadata[:example_group][:example_group][:example_group][:description]).to eq("Level 1") expect(inner_metadata[:example_group][:example_group][:example_group][:example_group]).to be_nil end it "works properly with shallow nesting" do inner_metadata = nil RSpec.describe "Level 1" do inner_metadata = example("Level 2").metadata end expect(inner_metadata[:description]).to eq("Level 2") expect(inner_metadata[:example_group][:description]).to eq("Level 1") expect(inner_metadata[:example_group][:example_group]).to be_nil end it 'allows integration libraries like VCR to infer a fixture name from the example description by walking up nesting structure' do fixture_name_for = lambda do |meta| description = meta[:description] if example_group = meta[:example_group] [fixture_name_for[example_group], description].join('/') else description end end ex = inferred_fixture_name = nil RSpec.configure do |config| config.before(:example, :infer_fixture) { |e| inferred_fixture_name = fixture_name_for[e.metadata] } end RSpec.describe "Group", :infer_fixture do ex = example("ex") { } end.run raise ex.execution_result.exception if ex.execution_result.exception expect(inferred_fixture_name).to eq("Group/ex") end it 'can mutate attributes when accessing them via [:example_group]' do meta = nil RSpec.describe(String) do describe "sub context" do meta = metadata end end expect { meta[:example_group][:described_class] = Hash }.to change { meta[:described_class] }.from(String).to(Hash) end it 'can still be filtered via a nested key under [:example_group] as before' do meta = nil line = __LINE__ + 1 RSpec.describe("group") { meta = metadata } applies = MetadataFilter.apply?( :any?, { :example_group => { :line_number => line } }, meta ) expect(applies).to be true end end describe ":example_group_block" do it 'returns the block' do meta = nil RSpec.describe "group" do meta = metadata end expect(meta[:example_group_block]).to be_a(Proc).and eq(meta[:block]) end it 'issues a deprecation warning' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /:example_group_block/) RSpec.describe "group" do metadata[:example_group_block] end end end describe ":describes" do context "on an example group metadata hash" do it 'returns the described_class' do meta = nil RSpec.describe Hash do meta = metadata end expect(meta[:describes]).to be(Hash).and eq(meta[:described_class]) end it 'issues a deprecation warning' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /:describes/) RSpec.describe "group" do metadata[:describes] end end end context "on an example metadata hash" do it 'returns the described_class' do meta = nil RSpec.describe Hash do meta = example("ex").metadata end expect(meta[:describes]).to be(Hash).and eq(meta[:described_class]) end it 'issues a deprecation warning' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /:describes/) RSpec.describe "group" do example("ex").metadata[:describes] end end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/shared_example_group_spec.rb0000664000000000000000000005640514557677674027425 0ustar rootrootrequire 'rspec/support/spec/in_sub_process' module RandomTopLevelModule def self.setup! RSpec.shared_examples_for("top level in module") {} end end module RSpec module Core RSpec.describe SharedExampleGroup do include RSpec::Support::InSubProcess let(:registry) { RSpec.world.shared_example_group_registry } ExampleModule = Module.new ExampleClass = Class.new it 'does not add a bunch of private methods to Module' do seg_methods = RSpec::Core::SharedExampleGroup.private_instance_methods expect(Module.private_methods & seg_methods).to eq([]) end before do # this is a work around as SharedExampleGroup is not world safe RandomTopLevelModule.setup! end RSpec::Matchers.define :have_example_descriptions do |*descriptions| match do |example_group| example_group.examples.map(&:description) == descriptions end failure_message do |example_group| actual = example_group.examples.map(&:description) "expected #{example_group.name} to have descriptions: #{descriptions.inspect} but had #{actual.inspect}" end end %w[shared_examples shared_examples_for shared_context].each do |shared_method_name| describe shared_method_name do let(:group) { RSpec.describe('example group') } before do RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups end define_method :define_shared_group do |*args, &block| group.send(shared_method_name, *args, &block) end define_method :define_top_level_shared_group do |*args, &block| RSpec.send(shared_method_name, *args, &block) end def find_implementation_block(registry, scope, name) registry.find([scope], name).definition end it "is exposed to the global namespace when expose_dsl_globally is enabled" do in_sub_process do RSpec.configuration.expose_dsl_globally = true expect(Kernel).to respond_to(shared_method_name) end end it "is not exposed to the global namespace when monkey patching is disabled" do RSpec.configuration.expose_dsl_globally = false expect(RSpec.configuration.expose_dsl_globally?).to eq(false) expect(Kernel).to_not respond_to(shared_method_name) end # These keyword specs cover all 4 of the keyword / keyword like syntax varients # they should be warning free. if RSpec::Support::RubyFeatures.required_kw_args_supported? it 'supports required keyword arguments' do binding.eval(<<-CODE, __FILE__, __LINE__) group.__send__ shared_method_name, "shared context expects keywords" do |foo:| it "has an expected value" do expect(foo).to eq("bar") end end group.__send__ shared_method_name, "shared context expects hash" do |a_hash| it "has an expected value" do expect(a_hash[:foo]).to eq("bar") end end group.it_behaves_like "shared context expects keywords", foo: "bar" group.it_behaves_like "shared context expects keywords", { foo: "bar" } group.it_behaves_like "shared context expects hash", foo: "bar" group.it_behaves_like "shared context expects hash", { foo: "bar" } CODE expect(group.run).to eq true end end if RSpec::Support::RubyFeatures.kw_args_supported? it 'supports optional keyword arguments' do binding.eval(<<-CODE, __FILE__, __LINE__) group.__send__ shared_method_name, "shared context expects keywords" do |foo: nil| it "has an expected value" do expect(foo).to eq("bar") end end group.__send__ shared_method_name, "shared context expects hash" do |a_hash| it "has an expected value" do expect(a_hash[:foo]).to eq("bar") end end group.it_behaves_like "shared context expects keywords", foo: "bar" group.it_behaves_like "shared context expects keywords", { foo: "bar" } group.it_behaves_like "shared context expects hash", foo: "bar" group.it_behaves_like "shared context expects hash", { foo: "bar" } CODE expect(group.run).to eq true end end it "displays a warning when adding an example group without a block", :unless => RUBY_VERSION == '1.8.7' do expect_warning_with_call_site(__FILE__, __LINE__ + 1) group.send(shared_method_name, 'name but no block') end it "displays a warning when adding an example group without a block", :if => RUBY_VERSION == '1.8.7' do # In 1.8.7 this spec breaks unless we run it isolated like this in_sub_process do expect_warning_with_call_site(__FILE__, __LINE__ + 1) group.send(shared_method_name, 'name but no block') end end it 'displays a warning when adding a second shared example group with the same name' do group.send(shared_method_name, 'some shared group') {} original_declaration = [__FILE__, __LINE__ - 1].join(':') warning = nil allow(::Kernel).to receive(:warn) { |msg| warning = msg } group.send(shared_method_name, 'some shared group') {} second_declaration = [__FILE__, __LINE__ - 1].join(':') expect(warning).to include('some shared group', original_declaration, second_declaration) expect(warning).to_not include 'Called from' end it 'displays a helpful message when you define a shared example group in *_spec.rb file' do warning = nil allow(::Kernel).to receive(:warn) { |msg| warning = msg } declaration = nil 2.times do group.send(shared_method_name, 'some shared group') {} declaration = [__FILE__, __LINE__ - 1].join(':') RSpec.configuration.loaded_spec_files << declaration end better_error = 'was automatically loaded by RSpec because the file name' expect(warning).to include('some shared group', declaration, better_error) expect(warning).to_not include 'Called from' end it 'works with top level defined examples in modules' do expect(RSpec::configuration.reporter).to_not receive(:deprecation) RSpec.describe('example group') { include_context 'top level in module' } end it 'generates a named (rather than anonymous) module' do define_top_level_shared_group("shared behaviors") { } RSpec.configuration.include_context "shared behaviors", :include_it example_group = RSpec.describe("Group", :include_it) { } anonymous_module_regex = /#/ expect(Module.new.inspect).to match(anonymous_module_regex) include_a_named_rather_than_anonymous_module = ( include(a_string_including( "# :bar, &implementation) matching_group = RSpec.describe "Group", :foo => :bar non_matching_group = RSpec.describe "Group" expect(matching_group.bar).to eq("bar") expect(non_matching_group).not_to respond_to(:bar) end end context "given a string and a hash" do it "captures the given string and block in the World's collection of shared example groups" do implementation = lambda { } define_shared_group("name", :foo => :bar, &implementation) expect(find_implementation_block(registry, group, "name")).to eq implementation end it "delegates include on configuration" do implementation = Proc.new { def self.bar; 'bar'; end } define_shared_group("name", :foo => :bar, &implementation) matching_group = RSpec.describe "Group", :foo => :bar non_matching_group = RSpec.describe "Group" expect(matching_group.bar).to eq("bar") expect(non_matching_group).not_to respond_to(:bar) end end it "displays a warning when adding a second shared example group with the same name" do group.send(shared_method_name, 'some shared group') {} original_declaration = [__FILE__, __LINE__ - 1].join(':') warning = nil allow(::Kernel).to receive(:warn) { |msg| warning = msg } group.send(shared_method_name, 'some shared group') {} second_declaration = [__FILE__, __LINE__ - 1].join(':') expect(warning).to include('some shared group', original_declaration, second_declaration) expect(warning).to_not include 'Called from' end end context "when `config.shared_context_metadata_behavior == :apply_to_host_groups`" do before do RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups end it "does not auto-include the shared group based on passed metadata" do define_top_level_shared_group("name", :foo => :bar) do def self.bar; 'bar'; end end matching_group = RSpec.describe "Group", :foo => :bar expect(matching_group).not_to respond_to(:bar) end it "adds passed metadata to including groups and examples" do define_top_level_shared_group("name", :foo => :bar) { } group = RSpec.describe("outer") nested = group.describe("inner") example = group.example("ex") group.include_context "name" expect([group, nested, example]).to all have_attributes( :metadata => a_hash_including(:foo => :bar) ) end it "requires a valid name" do expect { define_shared_group(:foo => 1) { } }.to raise_error(ArgumentError, a_string_including( "Shared example group names", {:foo => 1}.inspect )) end it "does not overwrite existing metadata values set at that level when included via `include_context`" do shared_ex_metadata = nil host_ex_metadata = nil define_top_level_shared_group("name", :foo => :shared) do it { |ex| shared_ex_metadata = ex.metadata } end describe_successfully("Group", :foo => :host) do include_context "name" it { |ex| host_ex_metadata = ex.metadata } end expect(host_ex_metadata[:foo]).to eq :host expect(shared_ex_metadata[:foo]).to eq :host end it "overwrites existing metadata values set at a parent level when included via `include_context`" do shared_ex_metadata = nil host_ex_metadata = nil define_top_level_shared_group("name", :foo => :shared) do it { |ex| shared_ex_metadata = ex.metadata } end describe_successfully("Group", :foo => :host) do context "nested" do include_context "name" it { |ex| host_ex_metadata = ex.metadata } end end expect(host_ex_metadata[:foo]).to eq :shared expect(shared_ex_metadata[:foo]).to eq :shared end it "propagates conflicted metadata to examples defined in the shared group when included via `it_behaves_like` since it makes a nested group" do shared_ex_metadata = nil host_ex_metadata = nil define_top_level_shared_group("name", :foo => :shared) do it { |ex| shared_ex_metadata = ex.metadata } end describe_successfully("Group", :foo => :host) do it_behaves_like "name" it { |ex| host_ex_metadata = ex.metadata } end expect(host_ex_metadata[:foo]).to eq :host expect(shared_ex_metadata[:foo]).to eq :shared end it "applies metadata from the shared group to the including group, when the shared group itself is loaded and included via metadata" do RSpec.configure do |config| config.when_first_matching_example_defined(:controller) do define_top_level_shared_group("controller support", :capture_logging) { } config.include_context "controller support", :controller end end group = RSpec.describe("group", :controller) ex = group.it expect(ex.metadata).to include(:controller => true, :capture_logging => true) end end context "when the group is included via `config.include_context` and matching metadata" do before do # To ensure we don't accidentally include shared contexts the # old way in this context, we disable the option here. RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups end describe "when it has a `let` and applies to an individual example via metadata" do it 'defines the `let` method correctly' do define_top_level_shared_group("name") do let(:foo) { "bar" } end RSpec.configuration.include_context "name", :include_it ex = value = nil RSpec.describe "group" do ex = example("ex1", :include_it) { value = foo } end.run expect(ex.execution_result).to have_attributes(:status => :passed, :exception => nil) expect(value).to eq("bar") end end describe "hooks for individual examples that have matching metadata" do before do skip "These specs pass in 2.0 mode on JRuby 1.7.8 but fail on " \ "1.7.15 when the entire spec suite runs. They pass on " \ "1.7.15 when this one spec file is run or if we filter to " \ "just them. Given that 2.0 support on JRuby 1.7 is " \ "experimental, we're just skipping these specs." end if RUBY_VERSION == "2.0.0" && RSpec::Support::Ruby.jruby? it 'runs them' do sequence = [] define_top_level_shared_group("name") do before(:context) { sequence << :before_context } after(:context) { sequence << :after_context } before(:example) { sequence << :before_example } after(:example) { sequence << :after_example } around(:example) do |ex| sequence << :around_example_before ex.run sequence << :around_example_after end end RSpec.configuration.include_context "name", :include_it RSpec.describe "group" do example("ex1") { sequence << :unmatched_example_1 } example("ex2", :include_it) { sequence << :matched_example } example("ex3") { sequence << :unmatched_example_2 } end.run expect(sequence).to eq([ :unmatched_example_1, :before_context, :around_example_before, :before_example, :matched_example, :after_example, :around_example_after, :after_context, :unmatched_example_2 ]) end it 'runs the `after(:context)` hooks even if the `before(:context)` hook raises an error' do sequence = [] define_top_level_shared_group("name") do before(:context) do sequence << :before_context raise "boom" end after(:context) { sequence << :after_context } end RSpec.configuration.include_context "name", :include_it RSpec.describe "group" do example("ex", :include_it) { sequence << :example } end.run expect(sequence).to eq([ :before_context, :after_context ]) end end end context "when called at the top level" do before do RSpec.__send__(shared_method_name, "shared context") do example "shared spec" end end it 'is available for inclusion from a top level group' do group = RSpec.describe "group" do include_examples "shared context" end expect(group).to have_example_descriptions("shared spec") end it 'is available for inclusion from a nested example group' do group = nil RSpec.describe "parent" do context "child" do group = context("grand child") { include_examples "shared context" } end end expect(group).to have_example_descriptions("shared spec") end it 'is trumped by a shared group with the same name that is defined in the including context' do group = RSpec.describe "parent" do __send__ shared_method_name, "shared context" do example "a different spec" end include_examples "shared context" end expect(group).to have_example_descriptions("a different spec") end it 'is trumped by a shared group with the same name that is defined in a parent group' do group = nil RSpec.describe "parent" do __send__ shared_method_name, "shared context" do example "a different spec" end group = context("nested") { include_examples "shared context" } end expect(group).to have_example_descriptions("a different spec") end end context "when called from within an example group" do define_method :in_group_with_shared_group_def do |&block| RSpec.describe "an example group" do __send__ shared_method_name, "shared context" do example "shared spec" end module_exec(&block) end end it 'is available for inclusion within that group' do group = in_group_with_shared_group_def do include_examples "shared context" end expect(group).to have_example_descriptions("shared spec") end it 'is available for inclusion in a child group' do group = nil in_group_with_shared_group_def do group = context("nested") { include_examples "shared context" } end expect(group).to have_example_descriptions("shared spec") end it 'is not available for inclusion in a different top level group' do in_group_with_shared_group_def { } expect { RSpec.describe "another top level group" do include_examples "shared context" end }.to raise_error(/Could not find/) end it 'is not available for inclusion in a nested group of a different top level group' do in_group_with_shared_group_def { } expect { RSpec.describe "another top level group" do context("nested") { include_examples "shared context" } end }.to raise_error(/Could not find/) end it 'trumps a shared group with the same name defined at the top level' do RSpec.__send__(shared_method_name, "shared context") do example "a different spec" end group = in_group_with_shared_group_def do include_examples "shared context" end expect(group).to have_example_descriptions("shared spec") end it 'is trumped by a shared group with the same name that is defined in the including context' do group = nil in_group_with_shared_group_def do group = context "child" do __send__ shared_method_name, "shared context" do example "a different spec" end include_examples "shared context" end end expect(group).to have_example_descriptions("a different spec") end it 'is trumped by a shared group with the same name that is defined in nearer parent group' do group = nil in_group_with_shared_group_def do context "child" do __send__ shared_method_name, "shared context" do example "a different spec" end group = context("grandchild") { include_examples "shared context" } end end expect(group).to have_example_descriptions("a different spec") end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/set_spec.rb0000664000000000000000000000162214557677674024012 0ustar rootrootRSpec.describe 'RSpec::Core::Set' do let(:set) { RSpec::Core::Set.new([1, 2, 3]) } it 'takes an array of values' do expect(set).to include(1, 2, 3) end it 'can be appended to' do set << 4 expect(set).to include 4 end it 'can have more values merged in' do set.merge([4, 5]).merge([6]) expect(set).to include(4, 5, 6) end it 'is enumerable' do expect(set).to be_an Enumerable expect { |p| set.each(&p) }.to yield_successive_args(1, 2, 3) end it 'supports deletions' do expect { set.delete(1) }.to change { set.include?(1) }.from(true).to(false) end it 'indicates if it is empty' do set = RSpec::Core::Set.new expect { set << 1 }.to change { set.empty? }.from(true).to(false) end it 'can be cleared' do expect { set.clear }.to change { set.empty? }.from(false).to(true) expect(set.clear).to equal(set) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/failed_example_notification_spec.rb0000664000000000000000000000146414557677674030730 0ustar rootrootmodule RSpec::Core::Notifications RSpec.describe FailedExampleNotification do before do allow(RSpec.configuration).to receive(:color_enabled?).and_return(true) end it "uses the default color for the shared example backtrace line" do example = nil group = RSpec.describe "testing" do shared_examples_for "a" do example = it "fails" do expect(1).to eq(2) end end it_behaves_like "a" end group.run exception_presenter= RSpec::Core::Formatters::ExceptionPresenter.new(example.execution_result.exception, example) fne = FailedExampleNotification.new(example, exception_presenter) lines = fne.colorized_message_lines expect(lines).to include(match("\\e\\[37mShared Example Group:")) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/pending_spec.rb0000664000000000000000000000033214557677674024640 0ustar rootrootRSpec.describe RSpec::Core::Pending do it 'only defines methods that are part of the DSL' do expect(RSpec::Core::Pending.instance_methods(false).map(&:to_sym)).to \ match_array([:pending, :skip]) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/drb_spec.rb0000664000000000000000000002307614557677674023775 0ustar rootrootrequire 'rspec/core/drb' RSpec.describe RSpec::Core::DRbRunner, :isolated_directory => true, :isolated_home => true, :type => :drb, :unless => RUBY_PLATFORM == 'java' do let(:config) { RSpec::Core::Configuration.new } let(:out) { StringIO.new } let(:err) { StringIO.new } include_context "spec files" def runner(*args) RSpec::Core::DRbRunner.new(config_options(*args)) end def config_options(*args) RSpec::Core::ConfigurationOptions.new(args) end context "without server running" do it "raises an error" do expect { runner.run(err, out) }.to raise_error(DRb::DRbConnError) end after { DRb.stop_service } end describe "--drb-port" do def with_RSPEC_DRB_set_to(val) with_env_vars('RSPEC_DRB' => val) { yield } end context "without RSPEC_DRB environment variable set" do it "defaults to 8989" do with_RSPEC_DRB_set_to(nil) do expect(runner.drb_port).to eq(8989) end end it "sets the DRb port" do with_RSPEC_DRB_set_to(nil) do expect(runner("--drb-port", "1234").drb_port).to eq(1234) expect(runner("--drb-port", "5678").drb_port).to eq(5678) end end end context "with RSPEC_DRB environment variable set" do context "without config variable set" do it "uses RSPEC_DRB value" do with_RSPEC_DRB_set_to('9000') do expect(runner.drb_port).to eq("9000") end end end context "and config variable set" do it "uses configured value" do with_RSPEC_DRB_set_to('9000') do expect(runner(*%w[--drb-port 5678]).drb_port).to eq(5678) end end end end end context "with server running", :slow do class SimpleDRbSpecServer def self.run(argv, err, out) options = RSpec::Core::ConfigurationOptions.new(argv) config = RSpec::Core::Configuration.new RSpec.configuration = config RSpec::Core::Runner.new(options, config).run(err, out) end end before(:all) do @drb_port = '8990' DRb::start_service("druby://127.0.0.1:#{@drb_port}", SimpleDRbSpecServer) end after(:all) do DRb::stop_service end it "falls back to `druby://:0` when `druby://localhost:0` fails" do # see https://bugs.ruby-lang.org/issues/496 for background expect(::DRb).to receive(:start_service).with("druby://localhost:0").and_raise(SocketError) expect(::DRb).to receive(:start_service).with("druby://:0").and_call_original result = runner("--drb-port", @drb_port, passing_spec_filename).run(err, out) expect(result).to be(0) end it "returns 0 if spec passes" do result = runner("--drb-port", @drb_port, passing_spec_filename).run(err, out) expect(result).to be(0) end it "returns 1 if spec fails" do result = runner("--drb-port", @drb_port, failing_spec_filename).run(err, out) expect(result).to be(1) end it "outputs colorized text when running with --force-color option" do failure_symbol = "\e[#{RSpec::Core::Formatters::ConsoleCodes.console_code_for(:red)}mF" runner(failing_spec_filename, "--force-color", "--drb-port", @drb_port).run(err, out) expect(out.string).to include(failure_symbol) end end end RSpec.describe RSpec::Core::DRbOptions, :isolated_directory => true, :isolated_home => true do include ConfigOptionsHelper describe "DRB args" do def drb_argv_for(args) options = config_options_object(*args) RSpec::Core::DRbRunner.new(options, RSpec.configuration).drb_argv end def drb_filter_manager_for(args) configuration = RSpec::Core::Configuration.new RSpec::Core::DRbRunner.new(config_options_object(*args), configuration).drb_argv configuration.filter_manager end it "preserves extra arguments" do allow(File).to receive(:exist?) { false } expect(drb_argv_for(%w[ a --drb b --color c ])).to match_array %w[ --color a b c ] end %w(--color --force-color --no-color --fail-fast --profile --backtrace --tty).each do |option| it "includes #{option}" do expect(drb_argv_for([option])).to include(option) end end it "includes --failure-exit-code" do expect(drb_argv_for(%w[--failure-exit-code 2])).to include("--failure-exit-code", "2") end it "includes --options" do expect(drb_argv_for(%w[--options custom.opts])).to include("--options", "custom.opts") end it "includes --order" do expect(drb_argv_for(%w[--order random])).to include('--order', 'random') end context "with --example" do it "includes --example" do expect(drb_argv_for(%w[--example foo])).to include("--example", "foo") end it "unescapes characters which were escaped upon storing --example originally" do expect(drb_argv_for(["--example", "foo\\ bar"])).to include("--example", "foo bar") end end context "with tags" do it "includes the inclusion tags" do expect(drb_argv_for ["--tag", "tag"]).to eq(["--tag", "tag"]) end it "includes the inclusion tags with values" do expect(drb_argv_for ["--tag", "tag:foo"]).to eq(["--tag", "tag:foo"]) end it "leaves inclusion tags intact" do rules = drb_filter_manager_for(%w[ --tag tag ]).inclusions.rules expect(rules).to eq( {:tag=>true} ) end it "leaves inclusion tags with values intact" do rules = drb_filter_manager_for(%w[ --tag tag:foo ]).inclusions.rules expect(rules).to eq( {:tag=>'foo'} ) end it "includes the exclusion tags" do expect(drb_argv_for ["--tag", "~tag"]).to eq(["--tag", "~tag"]) end it "includes the exclusion tags with values" do expect(drb_argv_for ["--tag", "~tag:foo"]).to eq(["--tag", "~tag:foo"]) end it "leaves exclusion tags intact" do rules = drb_filter_manager_for(%w[ --tag ~tag ]).exclusions.rules expect(rules).to eq( {:tag => true} ) end it "leaves exclusion tags with values intact" do rules = drb_filter_manager_for(%w[ --tag ~tag:foo ]).exclusions.rules expect(rules).to eq( {:tag => 'foo'} ) end end context "with formatters" do it "includes the formatters" do expect(drb_argv_for ["--format", "d"]).to eq(["--format", "d"]) end it "leaves formatters intact" do coo = config_options_object("--format", "d") RSpec::Core::DRbRunner.new(coo, RSpec::Core::Configuration.new).drb_argv expect(coo.options[:formatters]).to eq([["d"]]) end it "leaves output intact" do coo = config_options_object("--format", "p", "--out", "foo.txt", "--format", "d") RSpec::Core::DRbRunner.new(coo, RSpec::Core::Configuration.new).drb_argv expect(coo.options[:formatters]).to eq([["p","foo.txt"],["d"]]) end end context "with --out" do it "combines with formatters" do argv = drb_argv_for(%w[--format h --out report.html]) expect(argv).to eq(%w[--format h --out report.html]) end end context "with -I libs" do it "includes -I" do expect(drb_argv_for(%w[-I a_dir])).to eq(%w[-I a_dir]) end it "includes multiple paths" do argv = drb_argv_for(%w[-I dir_1 -I dir_2 -I dir_3]) expect(argv).to eq(%w[-I dir_1 -I dir_2 -I dir_3]) end end context "with --require" do it "includes --require" do expect(drb_argv_for(%w[--require a_path])).to eq(%w[--require a_path]) end it "includes multiple paths" do argv = drb_argv_for(%w[--require dir/ --require file.rb]) expect(argv).to eq(%w[--require dir/ --require file.rb]) end end context "--drb specified in ARGV" do it "renders all the original arguments except --drb" do argv = drb_argv_for(%w[ --drb --color --format s --example pattern --profile --backtrace -I path/a -I path/b --require path/c --require path/d]) expect(argv).to eq(%w[ --color --profile --backtrace --example pattern --format s -I path/a -I path/b --require path/c --require path/d]) end end context "--drb specified in the options file" do it "renders all the original arguments except --drb" do File.open("./.rspec", "w") {|f| f << "--drb --color"} drb_argv = drb_argv_for(%w[ --tty --format s --example pattern --profile --backtrace ]) expect(drb_argv).to eq(%w[ --color --profile --backtrace --tty --example pattern --format s]) end end context "--drb specified in ARGV and the options file" do it "renders all the original arguments except --drb" do File.open("./.rspec", "w") {|f| f << "--drb --color"} argv = drb_argv_for(%w[ --drb --format s --example pattern --profile --backtrace]) expect(argv).to eq(%w[ --color --profile --backtrace --example pattern --format s]) end end context "--drb specified in ARGV and in as ARGV-specified --options file" do it "renders all the original arguments except --drb and --options" do File.open("./.rspec", "w") {|f| f << "--drb --color"} argv = drb_argv_for(%w[ --drb --format s --example pattern --profile --backtrace]) expect(argv).to eq(%w[ --color --profile --backtrace --example pattern --format s ]) end end describe "--drb, -X" do it "does not send --drb back to the parser after parsing options" do expect(drb_argv_for(%w[--drb --color])).not_to include("--drb") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/example_status_persister_spec.rb0000664000000000000000000003207114557677674030357 0ustar rootrootrequire 'rspec/core/example_status_persister' require 'tempfile' module RSpec::Core RSpec.describe "Example status persisting" do it 'can load a previously persisted set of example statuses from disk' do examples = [ { :example_id => "spec_1.rb[1:1]", :status => "passed" }, { :example_id => "spec_1.rb[1:2]", :status => "failed" } ] temp_file = Tempfile.new("example_statuses.txt") temp_file.write(ExampleStatusDumper.dump(examples)) temp_file.close loaded = ExampleStatusPersister.load_from(temp_file.path) expect(loaded).to eq(examples) end it 'returns `[]` from `load_from` when the named file does not exist' do expect(ExampleStatusPersister.load_from("./some/missing/path.txt")).to eq([]) end describe "persisting example statuses" do include FormatterSupport def new_example(id, metadata = {}) super(metadata).tap do |ex| allow(ex).to receive_messages(:id => id) end end let(:file) { Tempfile.new("example_statuses.txt") } let(:existing_spec_file) { Metadata.relative_path(__FILE__) } it 'writes the given example statuses to disk' do ex_1 = new_example("spec_1.rb[1:1]", :status => :passed) ex_2 = new_example("spec_1.rb[1:2]", :status => :failed) ExampleStatusPersister.persist([ex_1, ex_2], file.path) loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to contain_exactly( a_hash_including(:example_id => ex_1.id, :status => "passed"), a_hash_including(:example_id => ex_2.id, :status => "failed") ) end it 'creates any necessary intermediary directories' do path = File.join("#{file.path}-some", "subdirectory", "examples.txt") ex_1 = new_example("spec_1.rb[1:1]", :status => :passed) ExampleStatusPersister.persist([ex_1], path) loaded = ExampleStatusPersister.load_from(path) expect(loaded).to contain_exactly( a_hash_including(:example_id => ex_1.id, :status => "passed") ) end it 'prevents simultaneous access to the file' do # This tests whether a certain race condition is prevented: # - read 1 # - read 2 # - write 1 # - write 2 - write 1 is lost ex_1 = new_example("#{existing_spec_file}[1:1]", :status => :passed) ex_2 = new_example("spec_1.rb[1:1]", :status => :failed) persister_1 = ExampleStatusPersister.new([ex_1], file.path) persister_2 = ExampleStatusPersister.new([ex_2], file.path) persister_2_thread = nil # dumped_statuses is called after the file is locked but # before the output is written allow(persister_1).to receive(:dump_statuses).and_wrap_original do |m, *args| persister_2_thread = Thread.new { persister_2.persist } m.call(*args) end persister_1.persist persister_2_thread.join loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to contain_exactly( a_hash_including(:example_id => ex_1.id, :status => "passed"), a_hash_including(:example_id => ex_2.id, :status => "failed") ) end it 'merges the example statuses with the existing records in the named file' do ex_1 = new_example("#{existing_spec_file}[1:1]", :status => :passed) ex_2 = new_example("spec_1.rb[1:1]", :status => :failed) ExampleStatusPersister.persist([ex_1], file.path) ExampleStatusPersister.persist([ex_2], file.path) loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to contain_exactly( a_hash_including(:example_id => ex_1.id, :status => "passed"), a_hash_including(:example_id => ex_2.id, :status => "failed") ) end it 'includes the spec run times so users can use it for their own purposes' do ex_1 = new_example("spec_1.rb[1:1]", :status => :passed) allow(ex_1.execution_result).to receive(:run_time) { 3.0 } ExampleStatusPersister.persist([ex_1], file.path) loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to match [ a_hash_including(:run_time => "3 seconds") ] end it "persists a loaded but unexecuted example with an #{Configuration::UNKNOWN_STATUS} status" do ex_1 = RSpec.describe.example ExampleStatusPersister.persist([ex_1], file.path) loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to match [ a_hash_including( :example_id => ex_1.id, :status => Configuration::UNKNOWN_STATUS ) ] end it "persists a skipped example properly" do group = RSpec.describe ex_1 = group.example("foo", :skip) group.run ExampleStatusPersister.persist([ex_1], file.path) loaded = ExampleStatusPersister.load_from(file.path) expect(loaded).to match [ a_hash_including( :example_id => ex_1.id, :status => "pending") ] end end end RSpec.describe "Example status merging" do let(:existing_spec_file) { Metadata.relative_path(__FILE__) } context "when no examples from this or previous runs are given" do it "returns an empty array" do merged = merge(:this_run => [], :from_previous_runs => []) expect(merged).to eq([]) end end context "when there are no examples from previous runs" do it "returns the examples from this run" do this_run = [ example(existing_spec_file, "1:1", "passed"), example(existing_spec_file, "1:2", "failed") ] merged = merge(:this_run => this_run, :from_previous_runs => []) expect(merged).to match_array(this_run) end end context "when there are no examples from this run" do it "returns the examples from the previous runs" do from_previous_runs = [ example(existing_spec_file, "1:1", "passed"), example(existing_spec_file, "1:2", "failed") ] merged = merge(:this_run => [], :from_previous_runs => from_previous_runs) expect(merged).to match_array(from_previous_runs) end end context "for examples that are only in the set for this run" do it "takes them indiscriminately, even if they did not execute" do this_run = [ example(existing_spec_file, "1:1", Configuration::UNKNOWN_STATUS) ] merged = merge(:this_run => this_run, :from_previous_runs => []) expect(merged).to match_array(this_run) end end context "for examples that are only in the set for previous runs" do context "if there are other examples from this run for the same file " do it "deletes them since the examples must no longer exist" do this_run = [ example(existing_spec_file, "1:1", "passed") ] from_previous_runs = [ example(existing_spec_file, "1:2", "failed") ] merged = merge(:this_run => this_run, :from_previous_runs => from_previous_runs) expect(merged).to match_array(this_run) end end context "if there are no other examples from this run for the same file" do it "deletes them if the file no longer exist" do from_previous_runs = [ example("./some/deleted_path/foo_spec.rb", "1:2", "failed") ] merged = merge(:this_run => [], :from_previous_runs => from_previous_runs) expect(merged).to eq([]) end it "keeps them if the file exists because the examples may still exist" do from_previous_runs = [ example(existing_spec_file, "1:2", "failed") ] merged = merge(:this_run => [], :from_previous_runs => from_previous_runs) expect(merged).to eq(from_previous_runs) end end end context "for examples that are in both sets" do it "takes the status from this run as long as the example executed" do this_run = [ example("foo_spec.rb", "1:1", "passed") ] from_previous_runs = [ example("foo_spec.rb", "1:1", "failed") ] merged = merge(:this_run => this_run, :from_previous_runs => from_previous_runs) expect(merged).to match_array(this_run) end it "takes the status from previous runs if the example was loaded but did not execute" do this_run = [ example("foo_spec.rb", "1:1", Configuration::UNKNOWN_STATUS) ] from_previous_runs = [ example("foo_spec.rb", "1:1", "failed") ] merged = merge(:this_run => this_run, :from_previous_runs => from_previous_runs) expect(merged).to match_array(from_previous_runs) end end it 'sorts the returned examples to make the saved file more easily scannable' do this_run = [ ex_c_1_1 = example("c_spec.rb", "1:1", "passed"), ex_a_1_2 = example("a_spec.rb", "1:2", "failed"), ex_a_1_10 = example("a_spec.rb", "1:10", "failed"), ex_a_1_9 = example("a_spec.rb", "1:9", "failed"), ] merged = merge(:this_run => this_run, :from_previous_runs => []) expect(merged).to eq([ ex_a_1_2, ex_a_1_9, ex_a_1_10, ex_c_1_1 ]) end it "preserves any extra attributes include in the example hashes" do this_run = [ example(existing_spec_file, "1:1", "passed", :foo => 23), example(existing_spec_file, "1:2", "failed", :bar => 12) ] from_previous_runs = [ example(existing_spec_file, "1:1", "passed", :foo => -23), example(existing_spec_file, "1:2", "failed", :bar => -12) ] merged = merge(:this_run => this_run, :from_previous_runs => from_previous_runs) expect(merged).to contain_exactly( a_hash_including(:foo => 23), a_hash_including(:bar => 12) ) end def example(file, scoped_id, status, extras = {}) { :example_id => "#{file}[#{scoped_id}]", :status => status }.merge(extras) end def merge(options) ExampleStatusMerger.merge( options.fetch(:this_run), options.fetch(:from_previous_runs) ) end end RSpec.describe "Example status serialization" do it 'serializes the provided example statuses in a human readable format' do examples = [ { :example_id => "./spec/unit/foo_spec.rb[1:1]", :status => 'passed' }, { :example_id => "./spec/unit/foo_spec.rb[1:2]", :status => 'pending' }, { :example_id => "./spec/integration/foo_spec.rb[1:2]", :status => 'failed' } ] produce_expected_output = eq(unindent(<<-EOS)) example_id | status | ----------------------------------- | ------- | ./spec/unit/foo_spec.rb[1:1] | passed | ./spec/unit/foo_spec.rb[1:2] | pending | ./spec/integration/foo_spec.rb[1:2] | failed | EOS if RUBY_VERSION == '1.8.7' # unordered hashes :(. produce_expected_output |= eq(unindent(<<-EOS)) status | example_id | ------- | ----------------------------------- | passed | ./spec/unit/foo_spec.rb[1:1] | pending | ./spec/unit/foo_spec.rb[1:2] | failed | ./spec/integration/foo_spec.rb[1:2] | EOS end expect(dump(examples)).to produce_expected_output end it 'takes the column headers into account when sizing the columns' do examples = [ { :long_key => '12', :a => '20' }, { :long_key => '120', :a => '2' } ] produce_expected_output = eq(unindent(<<-EOS)) long_key | a | -------- | -- | 12 | 20 | 120 | 2 | EOS if RUBY_VERSION == '1.8.7' # unordered hashes :(. produce_expected_output |= eq(unindent(<<-EOS)) a | long_key | -- | -------- | 20 | 12 | 2 | 120 | EOS end expect(dump(examples)).to produce_expected_output end it 'can round trip through the dumper and parser' do examples = [ { :example_id => "./spec/unit/foo_spec.rb[1:1]", :status => 'passed' }, { :example_id => "./spec/unit/foo_spec.rb[1:2]", :status => 'pending' }, { :example_id => "./spec/integration/foo_spec.rb[1:2]", :status => 'failed' } ] round_tripped = parse(dump(examples)) expect(round_tripped).to eq(examples) end it 'can round trip blank values through the dumper and parser' do examples = [ { :example_id => "./spec/unit/foo_spec.rb[1:1]", :run_time => '1 second' }, { :example_id => "./spec/unit/foo_spec.rb[1:2]", :run_time => '' } ] round_tripped = parse(dump(examples)) expect(round_tripped).to eq(examples) end it 'produces nothing when given nothing' do expect(dump([])).to eq(nil) end # Intended for use with indented heredocs. # taken from Ruby Tapas: # https://rubytapas.dpdcart.com/subscriber/post?id=616#files def unindent(s) s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, "") end def dump(examples) ExampleStatusDumper.dump(examples) end def parse(string) ExampleStatusParser.parse(string) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/example_spec.rb0000664000000000000000000007712614557677674024666 0ustar rootrootrequire 'pp' require 'stringio' RSpec.describe RSpec::Core::Example, :parent_metadata => 'sample' do let(:example_group) do RSpec.describe('group description') end let(:example_instance) do example_group.example('example description') { } end it_behaves_like "metadata hash builder" do def metadata_hash(*args) example = example_group.example('example description', *args) example.metadata end end it "can be pretty printed" do expect { ignoring_warnings { pp example_instance }}.to output(/RSpec::Core::Example/).to_stdout end describe "human readable output" do it 'prints a human readable description when inspected' do expect(example_instance.inspect).to eq("#") end it 'prints a human readable description for #to_s' do expect(example_instance.to_s).to eq("#") end end describe "#rerun_argument" do it "returns the location-based rerun argument" do allow(RSpec.configuration).to receive_messages(:loaded_spec_files => [__FILE__]) example = RSpec.describe.example expect(example.rerun_argument).to eq("#{RSpec::Core::Metadata.relative_path(__FILE__)}:#{__LINE__ - 1}") end end describe "#update_inherited_metadata" do it "updates the example metadata with the provided hash" do example = RSpec.describe.example expect(example.metadata).not_to include(:foo => 1, :bar => 2) example.update_inherited_metadata(:foo => 1, :bar => 2) expect(example.metadata).to include(:foo => 1, :bar => 2) end it "does not overwrite existing metadata since example metadata takes precedence over inherited metadata" do example = RSpec.describe.example("ex", :foo => 1) expect { example.update_inherited_metadata(:foo => 2) }.not_to change { example.metadata[:foo] }.from(1) end it "does not replace the existing metadata object with a new one or change its default proc" do example = RSpec.describe.example expect { example.update_inherited_metadata(:foo => 1) }.to avoid_changing { example.metadata.__id__ }.and avoid_changing { example.metadata.default_proc } end it "applies new metadata-based config items based on the update" do sequence = [] RSpec.configure do |c| c.before(:example, :foo => true) { sequence << :global_before_hook } c.after(:example, :foo => true) { sequence << :global_after_hook } end describe_successfully do it "gets the before hook due to the update" do sequence << :example end.update_inherited_metadata(:foo => true) end expect(sequence).to eq [:global_before_hook, :example, :global_after_hook] end end describe '#duplicate_with' do it 'successfully duplicates an example' do error_string = 'first' example = example_group.example { raise error_string } example2 = example.duplicate_with({ :custom_key => :custom_value }) # ensure metadata is unique for each example expect(example.metadata.object_id).to_not eq(example2.metadata.object_id) expect(example.metadata[:custom_key]).to eq(nil) expect(&example.metadata[:block]).to raise_error(error_string) expect(example2.metadata[:custom_key]).to eq(:custom_value) expect(&example2.metadata[:block]).to raise_error(error_string) # cloned examples must have unique ids expect(example.id).to_not eq(example2.id) # cloned examples must both refer to the same example group (not a clone) expect(example.example_group.object_id).to eq(example2.example_group.object_id) end end it "captures example timing even for exceptions unhandled by RSpec" do unhandled = RSpec::Support::AllExceptionsExceptOnesWeMustNotRescue::AVOID_RESCUING.first example = example_group.example { raise unhandled } begin example_group.run rescue unhandled # no-op, prevent from bubbling up end expect(example.execution_result.finished_at).not_to be_nil end describe "#exception" do it "supplies the exception raised, if there is one" do example = example_group.example { raise "first" } example_group.run expect(example.exception.message).to eq("first") end it "returns nil if there is no exception" do example = example_group.example('example') { } example_group.run expect(example.exception).to be_nil end it 'provides a `MultipleExceptionError` if there are multiple exceptions (e.g. from `it`, `around` and `after`)' do the_example = nil after_ex = StandardError.new("after") around_ex = StandardError.new("around") example_ex = StandardError.new("example") RSpec.describe do the_example = example { raise example_ex } after { raise after_ex } around { |ex| ex.run; raise around_ex } end.run expect(the_example.exception).to have_attributes( :class => RSpec::Core::MultipleExceptionError, :all_exceptions => [example_ex, after_ex, around_ex] ) end end describe "when there is an explicit description" do context "when RSpec.configuration.format_docstrings is set to a block" do it "formats the description using the block" do RSpec.configuration.format_docstrings { |s| s.strip } example = example_group.example(' an example with whitespace ') {} example_group.run expect(example.description).to eql('an example with whitespace') end end end describe "when there is no explicit description" do def expect_with(*frameworks) if frameworks.include?(:stdlib) example_group.class_exec do def assert(val) raise "Expected #{val} to be true" unless val end end end end context "when RSpec.configuration.format_docstrings is set to a block" do it "formats the description using the block" do RSpec.configuration.format_docstrings { |s| s.upcase } example_group.example { } example_group.run pattern = /EXAMPLE AT #{relative_path(__FILE__).upcase}:#{__LINE__ - 2}/ expect(example_group.examples.first.description).to match(pattern) end end context "when `expect_with :rspec` is configured" do before(:each) { expect_with :rspec } it "uses the matcher-generated description" do example_group.example { expect(5).to eq(5) } example_group.run expect(example_group.examples.first.description).to eq("is expected to eq 5") end it "uses the matcher-generated description in the full description" do example_group.example { expect(5).to eq(5) } example_group.run expect(example_group.examples.first.full_description).to eq("group description is expected to eq 5") end it "uses the file and line number if there is no matcher-generated description" do example = example_group.example {} example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/) end it "uses the file and line number if there is an error before the matcher" do example = example_group.example { expect(5).to eq(5) } example_group.before { raise } example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 3}/) end context "if the example is pending" do it "still uses the matcher-generated description if a matcher ran" do example = example_group.example { pending; expect(4).to eq(5) } example_group.run expect(example.description).to eq("is expected to eq 5") end it "uses the file and line number of the example if no matcher ran" do example = example_group.example { pending; fail } example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/) end end context "when an `after(:example)` hook raises an error" do it 'still assigns the description' do ex = nil RSpec.describe do ex = example { expect(2).to eq(2) } after { raise "boom" } end.run expect(ex.description).to eq("is expected to eq 2") end end context "when the matcher's `description` method raises an error" do description_line = __LINE__ + 3 RSpec::Matchers.define :matcher_with_failing_description do match { true } description { raise ArgumentError, "boom" } end it 'allows the example to pass and surfaces the failing description in the example description' do ex = nil RSpec.describe do ex = example { expect(2).to matcher_with_failing_description } end.run expect(ex).to pass.and have_attributes(:description => a_string_including( "example at #{ex.location}", "ArgumentError", "boom", "#{__FILE__}:#{description_line}" )) end end context "when an `after(:example)` hook has an expectation" do it "assigns the description based on the example's last expectation, ignoring the `after` expectation since it can apply to many examples" do ex = nil RSpec.describe do ex = example { expect(nil).to be_nil } after { expect(true).to eq(true) } end.run expect(ex).to pass.and have_attributes(:description => "is expected to be nil") end end end context "when `expect_with :rspec, :stdlib` is configured" do before(:each) { expect_with :rspec, :stdlib } it "uses the matcher-generated description" do example_group.example { expect(5).to eq(5) } example_group.run expect(example_group.examples.first.description).to eq("is expected to eq 5") end it "uses the file and line number if there is no matcher-generated description" do example = example_group.example {} example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/) end it "uses the file and line number if there is an error before the matcher" do example = example_group.example { expect(5).to eq(5) } example_group.before { raise } example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 3}/) end end context "when `expect_with :stdlib` is configured" do around do |ex| # Prevent RSpec::Matchers from being autoloaded. orig_autoloads = RSpec::MODULES_TO_AUTOLOAD.dup RSpec::MODULES_TO_AUTOLOAD.clear ex.run RSpec::MODULES_TO_AUTOLOAD.replace(orig_autoloads) end before { expect_with :stdlib } it "does not attempt to get the generated description from RSpec::Matchers when not loaded" do # Hide the constant while the example runs to simulate it being unloaded. example_group.before { hide_const("RSpec::Matchers") } ex = example_group.example { assert 5 == 5 } example_group.run # We rescue errors that occur while generating the description and append it, # so this ensures that no error mentioning `RSpec::Matchers` occurred while # generating the description. expect(ex.description).not_to include("RSpec::Matchers") expect(ex).to pass end it "uses the file and line number" do example = example_group.example { assert 5 == 5 } example_group.run expect(example.description).to match(/example at #{relative_path(__FILE__)}:#{__LINE__ - 2}/) end end end describe "#described_class" do it "returns the class (if any) of the outermost example group" do expect(described_class).to eq(RSpec::Core::Example) end end describe "accessing metadata within a running example" do it "has a reference to itself when running" do |ex| expect(ex.description).to eq("has a reference to itself when running") end it "can access the example group's top level metadata as if it were its own" do |ex| expect(ex.example_group.metadata).to include(:parent_metadata => 'sample') expect(ex.metadata).to include(:parent_metadata => 'sample') end end describe "accessing options within a running example" do it "can look up option values by key", :demo => :data do |ex| expect(ex.metadata[:demo]).to eq(:data) end end describe "#run" do it "generates a description before tearing down mocks in case a mock object is used in the description" do group = RSpec.describe do example { test = double('Test'); expect(test).to eq test } end expect(RSpec::Matchers).to receive(:generated_description).and_call_original.ordered expect(RSpec::Mocks).to receive(:teardown).and_call_original.ordered group.run end it "runs after(:each) when the example passes" do after_run = false group = RSpec.describe do after(:each) { after_run = true } example('example') { expect(1).to eq(1) } end group.run expect(after_run).to be(true), "expected after(:each) to be run" end it "runs after(:each) when the example fails" do after_run = false group = RSpec.describe do after(:each) { after_run = true } example('example') { expect(1).to eq(2) } end group.run expect(after_run).to be(true), "expected after(:each) to be run" end it "runs after(:each) when the example raises an Exception" do after_run = false group = RSpec.describe do after(:each) { after_run = true } example('example') { raise "this error" } end group.run expect(after_run).to be(true), "expected after(:each) to be run" end context "with an after(:each) that raises" do it "runs subsequent after(:each)'s" do after_run = false group = RSpec.describe do after(:each) { after_run = true } after(:each) { raise "FOO" } example('example') { expect(1).to eq(1) } end group.run expect(after_run).to be(true), "expected after(:each) to be run" end it "stores the exception" do group = RSpec.describe group.after(:each) { raise "FOO" } example = group.example('example') { expect(1).to eq(1) } group.run expect(example.execution_result.exception.message).to eq("FOO") end end it "wraps before/after(:each) inside around" do results = [] group = RSpec.describe do around(:each) do |e| results << "around (before)" e.run results << "around (after)" end before(:each) { results << "before" } after(:each) { results << "after" } example { results << "example" } end group.run expect(results).to eq([ "around (before)", "before", "example", "after", "around (after)" ]) end context 'memory leaks, see GH-321, GH-1921' do def self.reliable_gc # older Rubies don't give us options to ensure a full GC # TruffleRuby GC.start arity matches but GC.disable and GC.enable are mock implementations 0 != GC.method(:start).arity && !(defined?(RUBY_ENGINE) && RUBY_ENGINE == "truffleruby") end def expect_gc(opts) get_all = opts.fetch :get_all begin GC.disable opts.fetch(:event).call expect(get_all.call).to eq(opts.fetch :pre_gc) ensure GC.enable end # See discussion on https://github.com/rspec/rspec-core/pull/1950 # for why it's necessary to do this multiple times 20.times do GC.start :full_mark => true, :immediate_sweep => true return if get_all.call == opts.fetch(:post_gc) end expect(get_all.call).to eq opts.fetch(:post_gc) end it 'releases references to the examples / their ivars', :if => reliable_gc do config = RSpec::Core::Configuration.new real_reporter = RSpec::Core::Reporter.new(config) # in case it is the cause of a leak garbage = Struct.new :defined_in group = RSpec.describe do before(:all) { @before_all = garbage.new :before_all } before(:each) { @before_each = garbage.new :before_each } after(:each) { @after_each = garbage.new :after_each } after(:all) { @after_all = garbage.new :after_all } example "passing" do @passing_example = garbage.new :passing_example expect(@passing_example).to be end example "failing" do @failing_example = garbage.new :failing_example expect(@failing_example).to_not be end end expect_gc :event => lambda { group.run real_reporter }, :get_all => lambda { ObjectSpace.each_object(garbage).map { |g| g.defined_in.to_s }.sort }, :pre_gc => %w[after_all after_each after_each before_all before_each before_each failing_example passing_example], :post_gc => [] end it 'can still be referenced by user code afterwards' do calls_a = nil describe_successfully 'saves a lambda that references its memoized helper' do let(:a) { 123 } example { calls_a = lambda { a } } end expect(calls_a.call).to eq 123 end end it "leaves raised exceptions unmodified (GH-1103)", :if => RUBY_VERSION < '2.5' do # set the backtrace, otherwise MRI will build a whole new object, # and thus mess with our expectations. Rubinius and JRuby are not # affected. exception = StandardError.new exception.set_backtrace([]) group = RSpec.describe do example { raise exception.freeze } end group.run actual = group.examples.first.execution_result.exception expect(actual.__id__).to eq(exception.__id__) end context "with --dry-run" do before { RSpec.configuration.dry_run = true } it "does not execute any examples or hooks" do executed = [] RSpec.configure do |c| c.before(:each) { executed << :before_each_config } c.before(:all) { executed << :before_all_config } c.after(:each) { executed << :after_each_config } c.after(:all) { executed << :after_all_config } c.around(:each) { |ex| executed << :around_each_config; ex.run } end group = RSpec.describe do before(:all) { executed << :before_all } before(:each) { executed << :before_each } after(:all) { executed << :after_all } after(:each) { executed << :after_each } around(:each) { |ex| executed << :around_each; ex.run } example { executed << :example } context "nested" do before(:all) { executed << :nested_before_all } before(:each) { executed << :nested_before_each } after(:all) { executed << :nested_after_all } after(:each) { executed << :nested_after_each } around(:each) { |ex| executed << :nested_around_each; ex.run } example { executed << :nested_example } end end group.run expect(executed).to eq([]) end end end describe "reporting example_finished" do let(:reporter) { RSpec::Core::Reporter.new(RSpec::Core::Configuration.new) } def capture_reported_execution_result_for_example(&block) reporter = RSpec::Core::Reporter.new(RSpec::Core::Configuration.new) reported_execution_result = nil listener = double("Listener") allow(listener).to receive(:example_finished) do |notification| reported_execution_result = notification.example.execution_result.dup end reporter.register_listener(listener, :example_finished) RSpec.describe(&block).run(reporter) reported_execution_result end shared_examples "when skipped or failed" do it "fills in the execution result details before reporting a failed example as finished" do execution_result = capture_reported_execution_result_for_example do expect(1).to eq 2 end expect(execution_result).to have_attributes( :status => :failed, :exception => RSpec::Expectations::ExpectationNotMetError, :finished_at => a_value_within(1).of(Time.now), :run_time => a_value >= 0 ) end it "fills in the execution result details before reporting a skipped example as finished" do execution_result = capture_reported_execution_result_for_example do skip "because" expect(1).to eq 2 end expect(execution_result).to have_attributes( :status => :pending, :pending_message => "because", :finished_at => a_value_within(1).of(Time.now), :run_time => a_value >= 0 ) end end context "from an example" do def capture_reported_execution_result_for_example(&block) super { it(&block) } end it "fills in the execution result details before reporting a passed example as finished" do execution_result = capture_reported_execution_result_for_example do expect(1).to eq 1 end expect(execution_result).to have_attributes( :status => :passed, :exception => nil, :finished_at => a_value_within(1).of(Time.now), :run_time => a_value >= 0 ) end it "fills in the execution result details before reporting a pending example as finished" do execution_result = capture_reported_execution_result_for_example do pending "because" expect(1).to eq 2 end expect(execution_result).to have_attributes( :status => :pending, :pending_message => "because", :pending_exception => RSpec::Expectations::ExpectationNotMetError, :finished_at => a_value_within(1).of(Time.now), :run_time => a_value >= 0 ) end include_examples "when skipped or failed" end context "from a context hook" do def capture_reported_execution_result_for_example(&block) super do before(:context, &block) it { will_never_run } end end include_examples "when skipped or failed" end end describe "#pending" do def expect_pending_result(example) expect(example).to be_pending expect(example.execution_result.status).to eq(:pending) expect(example.execution_result.pending_message).to be end context "in the example" do it "sets the example to pending" do group = describe_successfully do example { pending; fail } end expect_pending_result(group.examples.first) end it "allows post-example processing in around hooks (see https://github.com/rspec/rspec-core/issues/322)" do blah = nil describe_successfully do around do |example| example.run blah = :success end example { pending; fail } end expect(blah).to be(:success) end it 'sets the backtrace to the example definition so it can be located by the user' do file = RSpec::Core::Metadata.relative_path(__FILE__) expected = [file, __LINE__ + 2].map(&:to_s) group = RSpec.describe do example { pending } end group.run actual = group.examples.first.exception.backtrace.first.split(':')[0..1] expect(actual).to eq(expected) end end context "in before(:each)" do it "sets each example to pending" do group = describe_successfully do before(:each) { pending } example { fail } example { fail } end expect_pending_result(group.examples.first) expect_pending_result(group.examples.last) end it 'sets example to pending when failure occurs in before(:each)' do group = describe_successfully do before(:each) { pending; fail } example {} end expect_pending_result(group.examples.first) end end context "in before(:all)" do it "is forbidden" do group = RSpec.describe do before(:all) { pending } example { fail } example { fail } end group.run expect(group.examples.first.exception).to be expect(group.examples.first.exception.message).to \ match(/may not be used outside of examples/) end it "fails with an ArgumentError if a block is provided" do group = RSpec.describe('group') do before(:all) do pending { :no_op } end example { fail } end example = group.examples.first group.run expect(example).to fail_with ArgumentError expect(example.exception.message).to match( /Passing a block within an example is now deprecated./ ) end end context "in around(:each)" do it "sets the example to pending" do group = describe_successfully do around(:each) { pending } example { fail } end expect_pending_result(group.examples.first) end it 'sets example to pending when failure occurs in around(:each)' do group = describe_successfully do around(:each) { pending; fail } example {} end expect_pending_result(group.examples.first) end end context "in after(:each)" do it "sets each example to pending" do group = describe_successfully do after(:each) { pending; fail } example { } example { } end expect_pending_result(group.examples.first) expect_pending_result(group.examples.last) end end end describe "#pending?" do it "only returns true / false values" do group = describe_successfully do example("", :pending => "a message thats ignored") { fail } example { } end expect(group.examples[0].pending?).to eq true expect(group.examples[1].pending?).to eq false end end describe "#skip" do context "in the example" do it "sets the example to skipped" do group = describe_successfully do example { skip } end expect(group.examples.first).to be_skipped end it "allows post-example processing in around hooks (see https://github.com/rspec/rspec-core/issues/322)" do blah = nil describe_successfully do around do |example| example.run blah = :success end example { skip } end expect(blah).to be(:success) end context "with a message" do it "sets the example to skipped with the provided message" do group = describe_successfully do example { skip "lorem ipsum" } end expect(group.examples.first).to be_skipped_with("lorem ipsum") end end end context "in before(:each)" do it "sets each example to skipped" do group = describe_successfully do before(:each) { skip } example {} example {} end expect(group.examples.first).to be_skipped expect(group.examples.last).to be_skipped end end context "in before(:all)" do it "sets each example to skipped" do group = describe_successfully do before(:all) { skip("not done"); fail } example {} example {} end expect(group.examples.first).to be_skipped_with("not done") expect(group.examples.last).to be_skipped_with("not done") end end context "in around(:each)" do it "sets the example to skipped" do group = describe_successfully do around(:each) { skip } example {} end expect(group.examples.first).to be_skipped end end end describe "#skipped?" do it "only returns true / false values" do group = describe_successfully do example("", :skip => "a message thats ignored") { fail } example { } end expect(group.examples[0].skipped?).to eq true expect(group.examples[1].skipped?).to eq false end end describe "timing" do it "uses RSpec::Core::Time as to not be affected by changes to time in examples" do reporter = double(:reporter).as_null_object group = RSpec.describe example = group.example example.__send__ :start, reporter allow(Time).to receive_messages(:now => Time.utc(2012, 10, 1)) example.__send__ :finish, reporter expect(example.execution_result.run_time).to be < 0.2 end end it "does not interfere with per-example randomness when running examples in a random order" do values = [] RSpec.configuration.order = :random describe_successfully do # The bug was only triggered when the examples # were in nested contexts; see https://github.com/rspec/rspec-core/pull/837 context { example { values << rand } } context { example { values << rand } } end expect(values.uniq.count).to eq(2) end describe "optional block argument" do it "contains the example" do |ex| expect(ex).to be_an(RSpec::Core::Example) expect(ex.description).to match(/contains the example/) end end describe "setting the current example" do it "sets RSpec.current_example to the example that is currently running" do group = RSpec.describe("an example group") current_examples = [] example1 = group.example("example 1") { current_examples << RSpec.current_example } example2 = group.example("example 2") { current_examples << RSpec.current_example } group.run expect(current_examples).to eq([example1, example2]) end end describe "mock framework integration" do it 'verifies mock expectations after each example' do ex = nil RSpec.describe do let(:dbl) { double } ex = example do expect(dbl).to receive(:foo) end end.run expect(ex).to fail_with(RSpec::Mocks::MockExpectationError) end it 'skips mock verification if the example has already failed' do ex = nil boom = StandardError.new("boom") RSpec.describe do ex = example do dbl = double expect(dbl).to receive(:Foo) raise boom end end.run expect(ex.exception).to be boom end it 'allows `after(:example)` hooks to satisfy mock expectations, since examples are not complete until their `after` hooks run' do ex = nil RSpec.describe do let(:the_dbl) { double } ex = example do expect(the_dbl).to receive(:foo) end after { the_dbl.foo } end.run expect(ex).to pass end end describe "exposing the examples reporter" do it "returns a null reporter when the example has not run yet" do example = RSpec.describe.example expect(example.reporter).to be RSpec::Core::NullReporter end it "returns the reporter used to run the example when executed" do reporter = double(:reporter).as_null_object group = RSpec.describe example = group.example example.run group.new, reporter expect(example.reporter).to be reporter end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/aggregate_failures_spec.rb0000664000000000000000000001314014557677674027035 0ustar rootrootRSpec.describe "Aggregating failures" do shared_examples_for "failure aggregation" do |exception_attribute, example_meta| context "via the `aggregate_failures` method" do context 'when the example has an expectation failure, plus an `after` hook and an `around` hook failure' do it 'presents a flat list of three failures' do ex = nil RSpec.describe do ex = example "ex", example_meta do aggregate_failures { expect(1).to be_even } end after { raise "after" } around { |example| example.run; raise "around" } end.run expect(ex.execution_result.__send__(exception_attribute)).to have_attributes( :all_exceptions => [ an_object_having_attributes(:message => /expected.*even\?/), an_object_having_attributes(:message => 'after'), an_object_having_attributes(:message => 'around') ] ) end end context 'when the example has multiple expectation failures, plus an `after` hook and an `around` hook failure' do it 'nests the expectation failures so that they can be labeled with the aggregation block label' do ex = nil RSpec.describe do ex = example "ex", example_meta do aggregate_failures do expect(1).to be_even expect(2).to be_odd end end after { raise "after" } around { |example| example.run; raise "around" } end.run exception = ex.execution_result.__send__(exception_attribute) expect(exception).to have_attributes( :all_exceptions => [ an_object_having_attributes(:class => RSpec::Expectations::MultipleExpectationsNotMetError), an_object_having_attributes(:message => 'after'), an_object_having_attributes(:message => 'around') ] ) expect(exception.all_exceptions.first.all_exceptions).to match [ an_object_having_attributes(:message => /expected.*even\?/), an_object_having_attributes(:message => /expected.*odd\?/) ] end end end context "via `:aggregate_failures` metadata" do it 'applies `aggregate_failures` to examples or groups tagged with `:aggregate_failures`' do ex = nil RSpec.describe "Aggregate failures", :aggregate_failures do ex = it "has multiple failures", example_meta do expect(1).to be_even expect(2).to be_odd end end.run expect(ex.execution_result).not_to be_pending_fixed expect(ex.execution_result.status).to eq(:pending) if example_meta.key?(:pending) expect(ex.execution_result.__send__(exception_attribute)).to have_attributes( :all_exceptions => [ an_object_having_attributes(:message => /expected.*even\?/), an_object_having_attributes(:message => /expected.*odd\?/) ] ) end context 'when the example has an exception, plus another error' do it 'reports it as a multiple exception error' do ex = nil RSpec.describe "Aggregate failures", :aggregate_failures do ex = example "fail and raise", example_meta do expect(1).to be_even boom end end.run expect(ex.execution_result.__send__(exception_attribute)).to have_attributes( :all_exceptions => [ an_object_having_attributes(:message => /expected.*even\?/), an_object_having_attributes(:class => NameError, :message => /boom/) ] ) end end context 'when the example has multiple exceptions, plus another error' do it 'reports it as a flat multiple exception error' do ex = nil RSpec.describe "Aggregate failures", :aggregate_failures do ex = example "fail and raise", example_meta do expect(1).to be_even expect(2).to be_odd boom end end.run expect(ex.execution_result.__send__(exception_attribute)).to have_attributes( :all_exceptions => [ an_object_having_attributes(:message => /expected.*even\?/), an_object_having_attributes(:message => /expected.*odd\?/), an_object_having_attributes(:class => NameError, :message => /boom/) ] ) end end end end context "for a non-pending example" do include_examples "failure aggregation", :exception, {} it 'does not interfere with other `around` hooks' do events = [] RSpec.describe "Outer" do around do |ex| events << :outer_before ex.run events << :outer_after end context "aggregating failures", :aggregate_failures do context "inner" do around do |ex| events << :inner_before ex.run events << :inner_after end it "has multiple failures" do events << :example_before expect(1).to be_even expect(2).to be_odd events << :example_after end end end end.run expect(events).to eq([:outer_before, :inner_before, :example_before, :example_after, :inner_after, :outer_after]) end end context "for a pending example" do include_examples "failure aggregation", :pending_exception, :pending => true end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/hooks_spec.rb0000664000000000000000000003627714557677674024360 0ustar rootrootmodule RSpec::Core RSpec.describe Hooks do class HooksHost include Hooks def parent_groups [] end def register_hook(position, scope, *args, &block) block ||= Proc.new { } __send__(position, scope, *args, &block) hook_collection_for(position, scope).first end def hook_collection_for(position, scope) hooks.send(:all_hooks_for, position, scope) end end [:example, :context, :suite].each do |scope| describe "#before(#{scope})" do it "stops running subsequent hooks of the same type when an error is encountered" do sequence = [] RSpec.configure do |c| c.output_stream = StringIO.new c.before(scope) do sequence << :hook_1 raise "boom" end c.before(scope) do sequence << :hook_2 raise "boom" end end RSpec.configuration.with_suite_hooks do RSpec.describe do example { sequence << :example } end.run end expect(sequence).to eq [:hook_1] end end describe "#after(#{scope})" do it "runs subsequent hooks of the same type when an error is encountered so all cleanup can complete" do sequence = [] RSpec.configure do |c| c.output_stream = StringIO.new c.after(scope) do sequence << :hook_2 raise "boom" end c.after(scope) do sequence << :hook_1 raise "boom" end end RSpec.configuration.with_suite_hooks do RSpec.describe do example { sequence << :example } end.run end expect(sequence).to eq [:example, :hook_1, :hook_2] end end end [:before, :after, :around].each do |type| [:example, :context].each do |scope| next if type == :around && scope == :context describe "##{type}(#{scope})" do it_behaves_like "metadata hash builder" do define_method :metadata_hash do |*args| HooksHost.new.register_hook(type, scope, *args).options end end end end describe "##{type}(no scope)" do let(:instance) { HooksHost.new } it "defaults to :example scope if no arguments are given" do expect { instance.__send__(type) {} }.to change { instance.hook_collection_for(type, :example).count }.by(1) end it "defaults to :example scope if the only argument is a metadata hash" do expect { instance.__send__(type, :foo => :bar) {} }.to change { instance.hook_collection_for(type, :example).count }.by(1) end it "raises an error if only metadata symbols are given as arguments" do expect { instance.__send__(type, :foo, :bar) {} }.to raise_error(ArgumentError) end end end [:before, :after].each do |type| [:example, :context].each do |scope| describe "##{type}(#{scope.inspect})" do let(:instance) { HooksHost.new } let!(:hook) { instance.register_hook(type, scope) } it "does not make #{scope.inspect} a metadata key" do expect(hook.options).to be_empty end it "is scoped to #{scope.inspect}" do expect(instance.hook_collection_for(type, scope)).to include(hook) end it 'does not run when in dry run mode' do RSpec.configuration.dry_run = true expect { |b| instance.send(type, scope, &b) instance.hooks.run(type, scope, double("Example").as_null_object) }.not_to yield_control end if scope == :example it "yields the example as an argument to the hook" do group = RSpec.describe ex = group.example { } expect { |p| group.send(type, scope, &p); group.run }.to yield_with_args(ex) end end end end end describe "#around" do context "when it does not run the example" do context "for a hook declared in the group" do it 'converts the example to a skipped example so the user is made aware of it' do ex = nil group = RSpec.describe do around { } ex = example("not run") { } end group.run expect(ex.execution_result.status).to eq(:pending) end end context "for a hook declared in config" do it 'converts the example to a skipped example so the user is made aware of it' do RSpec.configuration.around { } ex = nil group = RSpec.describe do ex = example("not run") { } end group.run expect(ex.execution_result.status).to eq(:pending) end end if RUBY_VERSION.to_f < 1.9 def hook_desc(_) "around hook" end else def hook_desc(line) "around hook at #{Metadata.relative_path(__FILE__)}:#{line}" end end it 'indicates which around hook did not run the example in the pending message' do ex = nil line = __LINE__ + 3 group = RSpec.describe do around { |e| e.run } around { } around { |e| e.run } ex = example("not run") { } end group.run expect(ex.execution_result.pending_message).to eq("#{hook_desc(line)} did not execute the example") end end it 'considers the hook to have run when passed as a block to a method that yields' do ex = nil group = RSpec.describe do def transactionally yield end around { |e| transactionally(&e) } ex = example("run") { } end group.run expect(ex.execution_result.status).to eq(:passed) end it 'does not consider the hook to have run when passed as a block to a method that does not yield' do ex = nil group = RSpec.describe do def transactionally; end around { |e| transactionally(&e) } ex = example("not run") { } end group.run expect(ex.execution_result.status).to eq(:pending) end context "when not running the example within the around block" do it "does not run the example" do examples = [] group = RSpec.describe do around do end it "foo" do examples << self end end group.run expect(examples).to eq([]) end end context "when running the example within the around block" do it "runs the example" do examples = [] group = RSpec.describe do around do |example| example.run end it "foo" do examples << self end end group.run expect(examples.count).to eq(1) end it "exposes example metadata to each around hook" do foos = {} group = RSpec.describe do around do |ex| foos[:first] = ex.metadata[:foo] ex.run end around do |ex| foos[:second] = ex.metadata[:foo] ex.run end it "does something", :foo => :bar do end end group.run expect(foos).to eq({:first => :bar, :second => :bar}) end it "exposes the full example interface to each around hook" do data_1 = {} data_2 = {} ex = nil group = RSpec.describe do def self.data_from(ex) { :description => ex.description, :full_description => ex.full_description, :example_group => ex.example_group, :file_path => ex.file_path, :location => ex.location } end around do |example| data_1.update(self.class.data_from example) example.run end around do |example| data_2.update(self.class.data_from example) example.run end ex = example("the example") { } end group.run expected_data = group.data_from(ex) expect(data_1).to eq(expected_data) expect(data_2).to eq(expected_data) end it "exposes a sensible inspect value" do inspect_value = nil group = RSpec.describe do around do |ex| inspect_value = ex.inspect end it "does something" do end end group.run expect(inspect_value).to match(/Example::Procsy/) end end context "when running the example within a block passed to a method" do it "runs the example" do examples = [] group = RSpec.describe do def yielder yield end around do |example| yielder { example.run } end it "foo" do examples << self end end group.run expect(examples.count).to eq(1) end end end [:all, :each].each do |scope| describe "prepend_before(#{scope})" do it "adds to the front of the list of before(:#{scope}) hooks" do messages = [] RSpec.configure { |config| config.before(scope) { messages << "config 3" } } RSpec.configure { |config| config.prepend_before(scope) { messages << "config 2" } } RSpec.configure { |config| config.before(scope) { messages << "config 4" } } RSpec.configure { |config| config.prepend_before(scope) { messages << "config 1" } } group = RSpec.describe { example {} } group.before(scope) { messages << "group 3" } group.prepend_before(scope) { messages << "group 2" } group.before(scope) { messages << "group 4" } group.prepend_before(scope) { messages << "group 1" } group.run expect(messages).to eq([ 'group 1', 'group 2', 'config 1', 'config 2', 'config 3', 'config 4', 'group 3', 'group 4' ]) end end describe "append_before(#{scope})" do it "adds to the back of the list of before(:#{scope}) hooks (same as `before`)" do messages = [] RSpec.configure { |config| config.before(scope) { messages << "config 1" } } RSpec.configure { |config| config.append_before(scope) { messages << "config 2" } } RSpec.configure { |config| config.before(scope) { messages << "config 3" } } group = RSpec.describe { example {} } group.before(scope) { messages << "group 1" } group.append_before(scope) { messages << "group 2" } group.before(scope) { messages << "group 3" } group.run expect(messages).to eq([ 'config 1', 'config 2', 'config 3', 'group 1', 'group 2', 'group 3' ]) end end describe "prepend_after(#{scope})" do it "adds to the front of the list of after(:#{scope}) hooks (same as `after`)" do messages = [] RSpec.configure { |config| config.after(scope) { messages << "config 3" } } RSpec.configure { |config| config.prepend_after(scope) { messages << "config 2" } } RSpec.configure { |config| config.after(scope) { messages << "config 1" } } group = RSpec.describe { example {} } group.after(scope) { messages << "group 3" } group.prepend_after(scope) { messages << "group 2" } group.after(scope) { messages << "group 1" } group.run expect(messages).to eq([ 'group 1', 'group 2', 'group 3', 'config 1', 'config 2', 'config 3' ]) end end describe "append_after(#{scope})" do it "adds to the back of the list of after(:#{scope}) hooks" do messages = [] RSpec.configure { |config| config.after(scope) { messages << "config 2" } } RSpec.configure { |config| config.append_after(scope) { messages << "config 3" } } RSpec.configure { |config| config.after(scope) { messages << "config 1" } } RSpec.configure { |config| config.append_after(scope) { messages << "config 4" } } group = RSpec.describe { example {} } group.after(scope) { messages << "group 2" } group.append_after(scope) { messages << "group 3" } group.after(scope) { messages << "group 1" } group.append_after(scope) { messages << "group 4" } group.run expect(messages).to eq([ 'group 1', 'group 2', 'config 1', 'config 2', 'config 3', 'config 4', 'group 3', 'group 4' ]) end end end describe "lambda" do it "can be used as a hook" do messages = [] count = 0 hook = lambda {|e| messages << "hook #{count = count + 1}"; e.run } RSpec.configure do |c| c.around(:each, &hook) c.around(:each, &hook) end group = RSpec.describe { example { messages << "example" } } group.run expect(messages).to eq ["hook 1", "hook 2", "example"] end end it "only defines methods that are intended to be part of RSpec's public API (+ `hooks`)" do expect(Hooks.private_instance_methods).to eq([]) expect(Hooks.instance_methods.map(&:to_sym)).to match_array([ :before, :after, :around, :append_before, :append_after, :prepend_before, :prepend_after, :hooks ]) end it 'emits a warning for `around(:context)`' do expect(RSpec).to receive(:warn_with).with(a_string_including( '`around(:context)` hooks are not supported' )) RSpec.describe do around(:context) { } end end it 'emits a warning for `around(:context)` defined in `configure`' do expect(RSpec).to receive(:warn_with).with(a_string_including( '`around(:context)` hooks are not supported' )) RSpec.configure do |c| c.around(:context) { } end end [:before, :around, :after].each do |type| it "emits a warning for `#{type}(:suite)` hooks" do expect(RSpec).to receive(:warn_with).with(a_string_including( "`#{type}(:suite)` hooks are only supported on the RSpec configuration object." )) RSpec.describe do send(type, :suite) { } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/dsl_spec.rb0000664000000000000000000000606614557677674024010 0ustar rootrootrequire 'rspec/support/spec/in_sub_process' main = self RSpec.describe "The RSpec DSL" do include RSpec::Support::InSubProcess shared_examples_for "dsl methods" do |*method_names| context "when expose_dsl_globally is enabled" do def enable in_sub_process do changing_expose_dsl_globally do RSpec.configuration.expose_dsl_globally = true expect(RSpec.configuration.expose_dsl_globally?).to eq true end yield end end it 'makes them only available off of `RSpec`, `main` and modules' do enable do expect(::RSpec).to respond_to(*method_names) expect(main).to respond_to(*method_names) expect(Module.new).to respond_to(*method_names) expect(Object.new).not_to respond_to(*method_names) end end end context "when expose_dsl_globally is disabled" do def disable in_sub_process do changing_expose_dsl_globally do RSpec.configuration.expose_dsl_globally = false expect(RSpec.configuration.expose_dsl_globally?).to eq false end yield end end it 'makes them only available off of `RSpec`' do disable do expect(::RSpec).to respond_to(*method_names) expect(main).not_to respond_to(*method_names) expect(Module.new).not_to respond_to(*method_names) expect(Object.new).not_to respond_to(*method_names) end end end end describe "built in DSL methods" do include_examples "dsl methods", :describe, :context, :shared_examples, :shared_examples_for, :shared_context do def changing_expose_dsl_globally yield end end end describe "custom example group aliases" do context "when adding aliases before exposing the DSL globally" do include_examples "dsl methods", :detail do def changing_expose_dsl_globally RSpec.configuration.alias_example_group_to(:detail) yield end end end context "when adding aliases after exposing the DSL globally" do include_examples "dsl methods", :detail do def changing_expose_dsl_globally yield RSpec.configuration.alias_example_group_to(:detail) end end end context "when adding duplicate aliases" do it "only a single alias is created" do in_sub_process do RSpec.configuration.alias_example_group_to(:detail) RSpec.configuration.alias_example_group_to(:detail) expect(RSpec::Core::DSL.example_group_aliases.count(:detail)).to eq(1) end end it "does not undefine the alias multiple times", :issue => 1824 do in_sub_process do RSpec.configuration.expose_dsl_globally = true RSpec.configuration.alias_example_group_to(:detail) RSpec.configuration.alias_example_group_to(:detail) expect { RSpec.configuration.expose_dsl_globally = false }.not_to raise_error end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/ruby_project_spec.rb0000664000000000000000000000305214557677674025725 0ustar rootrootmodule RSpec module Core RSpec.describe RubyProject do describe "#determine_root" do context "with ancestor containing spec directory" do it "returns ancestor containing the spec directory" do allow(RubyProject).to receive(:ascend_until).and_return('foodir') expect(RubyProject.determine_root).to eq("foodir") end end context "without ancestor containing spec directory" do it "returns current working directory" do allow(RubyProject).to receive(:find_first_parent_containing).and_return(nil) expect(RubyProject.determine_root).to eq(".") end end end describe "#ascend_until" do subject { RubyProject } def expect_ascend(source_path, *yielded_paths) expect { |probe| allow(File).to receive(:expand_path).with('.') { source_path } subject.ascend_until(&probe) }.to yield_successive_args(*yielded_paths) end it "works with a normal path" do expect_ascend("/var/ponies", "/var/ponies", "/var", "/") end it "works with a path with a trailing slash" do expect_ascend("/var/ponies/", "/var/ponies", "/var", "/") end it "works with a path with double slashes" do expect_ascend("/var//ponies/", "/var/ponies", "/var", "/") end it "works with a path with escaped slashes" do expect_ascend("/var\\/ponies/", "/var\\/ponies", "/") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters_spec.rb0000664000000000000000000002117314557677674025410 0ustar rootrootrequire 'pathname' module RSpec::Core::Formatters RSpec.describe Loader do let(:output) { StringIO.new } let(:reporter) { instance_double "Reporter", :register_listener => nil } let(:loader) { Loader.new reporter } describe "#add(formatter)" do let(:path) { File.join(Dir.tmpdir, 'output.txt') } it "adds to the list of formatters" do loader.add :documentation, output expect(loader.formatters.first).to be_an_instance_of(DocumentationFormatter) end it "finds a formatter by name (w/ Symbol)" do loader.add :documentation, output expect(loader.formatters.first).to be_an_instance_of(DocumentationFormatter) end it "finds a formatter by name (w/ String)" do loader.add 'documentation', output expect(loader.formatters.first).to be_an_instance_of(DocumentationFormatter) end it "finds a formatter by class" do formatter_class = Class.new(BaseTextFormatter) Loader.formatters[formatter_class] = [] loader.add formatter_class, output expect(loader.formatters.first).to be_an_instance_of(formatter_class) end it "finds a formatter by class name" do stub_const("CustomFormatter", Class.new(BaseFormatter)) Loader.formatters[CustomFormatter] = [] loader.add "CustomFormatter", output expect(loader.formatters.first).to be_an_instance_of(CustomFormatter) end it "lets you pass a formatter instance, for when you need to instantiate it with some custom state" do instance = ProgressFormatter.new(StringIO.new) expect { loader.add(instance) }.to change { loader.formatters }.from([]).to([instance]) end context "when a legacy formatter is added with RSpec::LegacyFormatters" do formatter_class = Struct.new(:output) let(:formatter) { double "formatter", :notifications => notifications, :output => output } let(:notifications) { [:a, :b, :c] } before do class_double("RSpec::LegacyFormatters", :load_formatter => formatter).as_stubbed_const end it "loads formatters from the external gem" do loader.add formatter_class, output expect(loader.formatters).to eq [formatter] end it "subscribes the formatter to the notifications the adaptor implements" do expect(reporter).to receive(:register_listener).with(formatter, *notifications) loader.add formatter_class, output end it "will ignore duplicate legacy formatters" do loader.add formatter_class, output expect(reporter).to_not receive(:register_listener) expect { loader.add formatter_class, output }.not_to change { loader.formatters.length } end end context "when a legacy formatter is added without RSpec::LegacyFormatters" do formatter_class = Struct.new(:output) before do allow_deprecation end it "issues a deprecation" do expect_warn_deprecation( /The #{formatter_class} formatter uses the deprecated formatter interface.+#{__FILE__}:#{__LINE__ + 1}/) loader.add formatter_class, output end end it "finds a formatter by class fully qualified name" do stub_const("RSpec::CustomFormatter", (Class.new(BaseFormatter))) Loader.formatters[RSpec::CustomFormatter] = [] loader.add "RSpec::CustomFormatter", output expect(loader.formatters.first).to be_an_instance_of(RSpec::CustomFormatter) end it "requires a formatter file based on its fully qualified name" do expect(loader).to receive(:require).with('rspec/custom_formatter') do stub_const("RSpec::CustomFormatter", (Class.new(BaseFormatter))) Loader.formatters[RSpec::CustomFormatter] = [] end loader.add "RSpec::CustomFormatter", output expect(loader.formatters.first).to be_an_instance_of(RSpec::CustomFormatter) end it "raises NameError if class is unresolvable" do expect(loader).to receive(:require).with('rspec/custom_formatter3') expect { loader.add "RSpec::CustomFormatter3", output }.to raise_error(NameError) end it "raises ArgumentError if formatter is unknown" do expect { loader.add :nonexistent, output }.to raise_error(ArgumentError) end context "with a 2nd arg defining the output" do it "creates a file at that path and sets it as the output" do loader.add('doc', path) expect(loader.formatters.first.output).to be_a(File) expect(loader.formatters.first.output.path).to eq(path) end it "accepts Pathname objects for file paths" do pathname = Pathname.new(path) loader.add('doc', pathname) expect(loader.formatters.first.output).to be_a(File) expect(loader.formatters.first.output.path).to eq(path) end end context "when a duplicate formatter exists" do before { loader.add :documentation, output } it "doesn't add the formatter for the same output target" do expect(reporter).to_not receive(:register_listener) expect { loader.add :documentation, output }.not_to change { loader.formatters.length } end it "adds the formatter for different output targets" do expect { loader.add :documentation, path }.to change { loader.formatters.length } end plain_old_formatter = Class.new do RSpec::Core::Formatters.register self, :example_started def initialize(output) end end it "handles formatters which do not subclass our formatters" do expect { loader.add plain_old_formatter, output }.to change { loader.formatters.length } # deliberate duplicate to ensure we can check for them correctly expect { loader.add plain_old_formatter, output }.to_not change { loader.formatters.length } end end context "when a custom formatter exists" do specific_formatter = RSpec::Core::Formatters::JsonFormatter generic_formatter = specific_formatter.superclass before { loader.add generic_formatter, output } it "adds a subclass of that formatter for the same output target" do expect { loader.add specific_formatter, output }.to change { loader.formatters.length } end end end describe "#setup_default" do let(:setup_default) { loader.setup_default output, output } context "with a formatter that implements #message" do it 'doesnt add a fallback formatter' do allow(reporter).to receive(:registered_listeners).with(:message) { [:json] } setup_default expect(loader.formatters).to exclude( an_instance_of ::RSpec::Core::Formatters::FallbackMessageFormatter ) end end context "without a formatter that implements #message" do it 'adds a fallback for message output' do allow(reporter).to receive(:registered_listeners).with(:message) { [] } expect { setup_default }.to change { loader.formatters }. from( excluding an_instance_of ::RSpec::Core::Formatters::FallbackMessageFormatter ). to( including an_instance_of ::RSpec::Core::Formatters::FallbackMessageFormatter ) end end context "with profiling enabled" do before do allow(reporter).to receive(:registered_listeners).with(:message) { [:json] } allow(RSpec.configuration).to receive(:profile_examples?) { true } end context "without an existing profile formatter" do it "will add the profile formatter" do allow(reporter).to receive(:registered_listeners).with(:dump_profile) { [] } expect { setup_default }.to change { loader.formatters }. from( excluding an_instance_of ::RSpec::Core::Formatters::ProfileFormatter ). to( including an_instance_of ::RSpec::Core::Formatters::ProfileFormatter ) end end context "when a formatter that implement #dump_profile is added" do it "wont add the profile formatter" do allow(reporter).to receive(:registered_listeners).with(:dump_profile) { [:json] } setup_default expect( loader.formatters.map(&:class) ).to_not include ::RSpec::Core::Formatters::ProfileFormatter end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/ordering_spec.rb0000664000000000000000000001344414557677674025035 0ustar rootrootmodule RSpec module Core module Ordering RSpec.describe Identity do it "does not affect the ordering of the items" do expect(Identity.new.order([1, 2, 3])).to eq([1, 2, 3]) end end RSpec.describe Random do describe '.order' do subject { described_class.new(configuration) } def item(n) instance_double(Example, :id => "./some_spec.rb[1:#{n}]") end let(:configuration) { RSpec::Core::Configuration.new } let(:items) { 10.times.map { |n| item(n) } } let(:shuffled_items) { subject.order items } it 'shuffles the items randomly' do expect(shuffled_items).to match_array items expect(shuffled_items).to_not eq items end context 'given multiple calls' do it 'returns the items in the same order' do expect(subject.order(items)).to eq shuffled_items end end def order_with(seed) configuration.seed = seed subject.order(items) end it 'has a good distribution', :slow do orderings = 1.upto(1000).map do |seed| order_with(seed) end.uniq # Here we are making sure that our hash function used for ordering has a # good distribution. Each seed produces a deterministic order and we want # 99%+ of 1000 to be different. expect(orderings.count).to be > 990 end context "when given a subset of a list that was previously shuffled with the same seed" do it "orders that subset the same as it was ordered before" do all_items = 20.times.map { |n| item(n) } all_shuffled = subject.order(all_items) expect(all_shuffled).not_to eq(all_items) last_half = all_items[10, 10] last_half_shuffled = subject.order(last_half) last_half_from_all_shuffled = all_shuffled.select { |i| last_half.include?(i) } expect(last_half_from_all_shuffled.map(&:id)).to eq(last_half_shuffled.map(&:id)) end end context 'given randomization has been seeded explicitly' do before { @seed = srand } after { srand @seed } it "does not affect the global random number generator" do srand 123 val1, val2 = rand(1_000), rand(1_000) subject srand 123 subject.order items expect(rand(1_000)).to eq(val1) subject.order items expect(rand(1_000)).to eq(val2) end end end end RSpec.describe RecentlyModified do before do allow(File).to receive(:mtime).with('./file_1.rb').and_return(::Time.new) allow(File).to receive(:mtime).with('./file_2.rb').and_return(::Time.new + 1) end it 'orders list by file modification time' do file_1 = instance_double(Example, :metadata => { :absolute_file_path => './file_1.rb' }) file_2 = instance_double(Example, :metadata => { :absolute_file_path => './file_2.rb' }) strategy = RecentlyModified.new expect(strategy.order([file_1, file_2])).to eq([file_2, file_1]) end end RSpec.describe Custom do it 'uses the block to order the list' do strategy = Custom.new(proc { |list| list.reverse }) expect(strategy.order([1, 2, 3, 4])).to eq([4, 3, 2, 1]) end end RSpec.describe Delayed do let(:registry) { Registry.new(Configuration.new) } it 'looks up a strategy to order the list later on' do strategy = Delayed.new(registry, :reverse) expect { strategy.order([1, 2, 3, 4]) }.to raise_error("Undefined ordering strategy :reverse") registry.register(:reverse, Custom.new(proc { |list| list.reverse })) expect(strategy.order([1, 2, 3, 4])).to eq([4, 3, 2, 1]) end end RSpec.describe Registry do let(:configuration) { Configuration.new } subject(:registry) { Registry.new(configuration) } describe "#used_random_seed?" do it 'returns false if the random orderer has not been used' do expect(registry.used_random_seed?).to be false end it 'returns false if the random orderer has been fetched but not used' do expect(registry.fetch(:random)).to be_a(Random) expect(registry.used_random_seed?).to be false end it 'returns true if the random orderer has been used' do registry.fetch(:random).order([RSpec.describe, RSpec.describe]) expect(registry.used_random_seed?).to be true end end describe "#fetch" do it "gives the registered ordering when called with a symbol" do ordering = Object.new subject.register(:falcon, ordering) expect(subject.fetch(:falcon)).to be ordering end context "when given an unrecognized symbol" do it 'invokes the given block and returns its value' do expect(subject.fetch(:falcon) { :fallback }).to eq(:fallback) end it 'raises an error if no block is given' do expect { subject.fetch(:falcon) }.to raise_error(IndexError) end end end describe "#has_strategy?(name)" do it "returns true if the strategy was registered" do expect { registry.register(:reverse, Custom.new(proc { |list| list.reverse })) }.to change { registry.has_strategy?(:reverse) }.from(false).to(true) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/0000775000000000000000000000000014557677674023130 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/utilities_spec.rb0000664000000000000000000000410014557677674026475 0ustar rootrootrequire 'rspec/core/bisect/utilities' module RSpec::Core RSpec.describe Bisect::Notifier do class ExampleFormatterClass def foo(notification); end end let(:formatter) { instance_spy(ExampleFormatterClass) } let(:notifier) { Bisect::Notifier.new(formatter) } it 'publishes events to the wrapped formatter' do notifier.publish :foo, :length => 15, :width => 12 expect(formatter).to have_received(:foo).with(an_object_having_attributes( :length => 15, :width => 12 )) end it 'does not publish events the formatter does not recognize' do expect { notifier.publish :unrecognized_event, :length => 15, :width => 12 }.not_to raise_error end end RSpec.describe Bisect::Channel do include RSpec::Support::InSubProcess it "supports sending objects from a child process back to the parent" do channel = Bisect::Channel.new in_sub_process do channel.send(:value_from_child) end expect(channel.receive).to eq :value_from_child end describe "in a UTF-8 encoding context (where possible)" do if defined?(Encoding) around(:each) do |example| old_external = old_internal = nil ignoring_warnings do old_external, Encoding.default_external = Encoding.default_external, Encoding::UTF_8 old_internal, Encoding.default_internal = Encoding.default_internal, Encoding::UTF_8 end example.run ignoring_warnings do Encoding.default_external = old_external Encoding.default_internal = old_internal end end end it "successfully sends binary data within a process" do channel = Bisect::Channel.new expect { channel.send("\xF8") }.not_to raise_error end it "successfully sends binary data from a child process to its parent process" do channel = Bisect::Channel.new in_sub_process do channel.send("\xF8") end expect(channel.receive).to eq("\xF8") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/shell_runner_spec.rb0000664000000000000000000000756014557677674027177 0ustar rootrootrequire 'rspec/core/bisect/shell_command' require 'rspec/core/bisect/shell_runner' require 'rspec/core/bisect/utilities' module RSpec::Core RSpec.describe Bisect::ShellRunner do let(:server) { instance_double("RSpec::Core::Bisect::Server", :drb_port => 1234) } let(:shell_command) { Bisect::ShellCommand.new(original_cli_args) } let(:runner) { described_class.new(server, shell_command) } describe "#run" do let(:original_cli_args) { %w[ spec/1_spec.rb ] } let(:target_specs) { %w[ spec/1_spec.rb[1:1] spec/1_spec.rb[1:2] ] } it "passes the failed examples from the original run as the expected failures so the runs can abort early" do original_results = Bisect::ExampleSetDescriptor.new( [], %w[ spec/failure_spec.rb[1:1] spec/failure_spec.rb[1:2] ] ) expect(server).to receive(:capture_run_results). with(original_cli_args). ordered. and_return(original_results) expect(server).to receive(:capture_run_results). with(target_specs, original_results.failed_example_ids). ordered runner.run(target_specs) end end describe "#original_results" do let(:original_cli_args) { %w[spec/unit --seed 1234] } open3_method = Open3.respond_to?(:capture2e) ? :capture2e : :popen3 open3_method = :popen3 if RSpec::Support::Ruby.jruby? def called_environment @called_environment end if open3_method == :capture2e RSpec::Matchers.define :invoke_command_with_env do |command, environment| match do |block| block.call expect(Open3).to have_received(open3_method).with(environment, command) end supports_block_expectations end elsif open3_method == :popen3 RSpec::Matchers.define :invoke_command_with_env do |command, environment| match do |block| block.call expect(Open3).to have_received(open3_method).with(command) expect(called_environment).to include(environment) end supports_block_expectations end end before do allow(Open3).to receive(open3_method) do @called_environment = ENV.to_hash.dup [double("Exit Status"), double("Stdout/err")] end allow(server).to receive(:capture_run_results) do |&block| block.call "the results" end end it "runs the suite with the original CLI options" do expect { runner.original_results }.to invoke_command_with_env(a_string_including("--seed 1234"), {}) end context 'when --bisect is present in SPEC_OPTS' do it "runs the suite with --bisect removed from the environment" do expect { with_env_vars 'SPEC_OPTS' => '--bisect --fail-fast' do runner.original_results end }.to invoke_command_with_env( a_string_including("--seed 1234"), { 'SPEC_OPTS' => '--fail-fast' } ) end end context 'when --bisect=verbose is present in SPEC_OPTS' do it "runs the suite with --bisect removed from the environment" do expect { with_env_vars 'SPEC_OPTS' => '--bisect=verbose --fail-fast' do runner.original_results end }.to invoke_command_with_env( a_string_including("--seed 1234"), { 'SPEC_OPTS' => '--fail-fast' } ) end end it 'returns the run results' do expect(runner.original_results).to eq("the results") end it 'memoizes, since it is expensive to re-run the suite' do expect(runner.original_results).to be(runner.original_results) end end def uses_quoting_for_escaping? RSpec::Support::OS.windows? || RSpec::Support::Ruby.jruby? end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/server_spec.rb0000664000000000000000000001351514557677674026002 0ustar rootrootrequire 'rspec/core/bisect/server' require 'support/formatter_support' module RSpec::Core RSpec.describe Bisect::Server do RSpec::Matchers.define :have_running_server do match do |drb| begin drb.current_server.alive? rescue DRb::DRbServerNotFound false end end end it 'always stops the server, even if an error occurs while yielding' do skip "This test flaps on JRuby 1.8 mode for some reason" if RSpec::Support::Ruby.jruby? && RUBY_VERSION.to_f < 1.9 expect(DRb).not_to have_running_server expect { Bisect::Server.run do expect(DRb).to have_running_server raise "boom" end }.to raise_error("boom") expect(DRb).not_to have_running_server end context "when results are failed to be reported" do let(:server) { Bisect::Server.new } it "raises an error with the output" do expect { server.capture_run_results { "the output" } }.to raise_error(an_object_having_attributes( :class => Bisect::BisectFailedError, :message => a_string_including("Failed to get results", "the output") )) end end context "when used in combination with the BisectDRbFormatter", :slow do include FormatterSupport attr_reader :server around do |ex| Bisect::Server.run do |the_server| @server = the_server ex.run end end def run_formatter_specs RSpec.configuration.drb_port = server.drb_port run_rspec_with_formatter("bisect-drb") end it 'receives suite results' do results = server.capture_run_results(['spec/rspec/core/resources/formatter_specs.rb']) do run_formatter_specs end aggregate_failures "checking results" do expect(results.all_example_ids).to eq %w[ ./spec/rspec/core/resources/formatter_specs.rb[1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[3:1] ./spec/rspec/core/resources/formatter_specs.rb[3:2] ./spec/rspec/core/resources/formatter_specs.rb[4:1] ./spec/rspec/core/resources/formatter_specs.rb[4:2] ./spec/rspec/core/resources/formatter_specs.rb[5:1] ./spec/rspec/core/resources/formatter_specs.rb[5:2] ./spec/rspec/core/resources/formatter_specs.rb[5:3:1] ] expect(results.failed_example_ids).to eq %w[ ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[4:1] ./spec/rspec/core/resources/formatter_specs.rb[4:2] ./spec/rspec/core/resources/formatter_specs.rb[5:1] ./spec/rspec/core/resources/formatter_specs.rb[5:2] ./spec/rspec/core/resources/formatter_specs.rb[5:3:1] ] end end describe "aborting the run early" do it "aborts as soon as the last expected failure finishes, since we don't care about what happens after that" do expected_failures = %w[ ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[4:1] ] results = server.capture_run_results(['spec/rspec/core/resources/formatter_specs.rb'], expected_failures) do run_formatter_specs end expect(results).to have_attributes( :all_example_ids => %w[ ./spec/rspec/core/resources/formatter_specs.rb[1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[3:1] ./spec/rspec/core/resources/formatter_specs.rb[3:2] ./spec/rspec/core/resources/formatter_specs.rb[4:1] ], :failed_example_ids => %w[ ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[4:1] ] ) end it 'aborts after an expected failure passes instead, even when there are remaining failing examples' do passing_example = "./spec/rspec/core/resources/formatter_specs.rb[3:1]" later_failing_example = "./spec/rspec/core/resources/formatter_specs.rb[4:1]" results = server.capture_run_results(['spec/rspec/core/resources/formatter_specs.rb'], [passing_example, later_failing_example]) do run_formatter_specs end expect(results).to have_attributes( :all_example_ids => %w[ ./spec/rspec/core/resources/formatter_specs.rb[1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:1:1] ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ./spec/rspec/core/resources/formatter_specs.rb[3:1] ], :failed_example_ids => %w[ ./spec/rspec/core/resources/formatter_specs.rb[2:2:1] ] ) end it 'aborts after an expected failure is pending instead, even when there are remaining failing examples' do pending_example = "./spec/rspec/core/resources/formatter_specs.rb[1:1]" later_failing_example = "./spec/rspec/core/resources/formatter_specs.rb[4:1]" results = server.capture_run_results(['spec/rspec/core/resources/formatter_specs.rb'], [pending_example, later_failing_example]) do run_formatter_specs end expect(results).to have_attributes( :all_example_ids => %w[ ./spec/rspec/core/resources/formatter_specs.rb[1:1] ], :failed_example_ids => %w[] ) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/example_minimizer_spec.rb0000664000000000000000000001240614557677674030210 0ustar rootrootrequire 'rspec/core/bisect/example_minimizer' require 'rspec/core/bisect/server' require 'rspec/core/bisect/shell_command' require 'support/fake_bisect_runner' module RSpec::Core RSpec.describe Bisect::ExampleMinimizer do around do |ex| # so example ids do not have to be escaped with_env_vars('SHELL' => 'bash', &ex) end let(:fake_runner) do FakeBisectRunner.new( %w[ 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] 7.rb[1] 8.rb[1] ], %w[ 2.rb[1] ], { "5.rb[1]" => %w[ 4.rb[1] ] } ) end it 'repeatedly runs various subsets of the suite, removing examples that have no effect on the failing examples' do minimizer = new_minimizer(fake_runner) minimizer.find_minimal_repro expect(minimizer.repro_command_for_currently_needed_ids).to eq("rspec 2.rb[1] 4.rb[1] 5.rb[1]") end it 'reduces a failure where none of the passing examples are implicated' do no_dependents_runner = FakeBisectRunner.new( %w[ 1.rb[1] 2.rb[1] ], %w[ 2.rb[1] ], {} ) minimizer = new_minimizer(no_dependents_runner) minimizer.find_minimal_repro expect(minimizer.repro_command_for_currently_needed_ids).to eq("rspec 2.rb[1]") end it 'reduces a failure when more than 50% of examples are implicated' do fake_runner.always_failures = [] fake_runner.dependent_failures = { "8.rb[1]" => %w[ 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] ] } minimizer = new_minimizer(fake_runner) minimizer.find_minimal_repro expect(minimizer.repro_command_for_currently_needed_ids).to eq( "rspec 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] 8.rb[1]" ) end it 'reduces a failure with multiple dependencies' do fake_runner.always_failures = [] fake_runner.dependent_failures = { "8.rb[1]" => %w[ 1.rb[1] 3.rb[1] 5.rb[1] 7.rb[1] ] } minimizer = new_minimizer(fake_runner) minimizer.find_minimal_repro expect(minimizer.repro_command_for_currently_needed_ids).to eq( "rspec 1.rb[1] 3.rb[1] 5.rb[1] 7.rb[1] 8.rb[1]" ) end context 'with an unminimisable failure' do class RunCountingReporter < RSpec::Core::NullReporter attr_accessor :round_count attr_accessor :example_count def initialize @round_count = 0 end def publish(event, *args) send(event, *args) if respond_to? event end def bisect_individual_run_start(_notification) self.round_count += 1 end end let(:counting_reporter) { RunCountingReporter.new } let(:fake_runner) do FakeBisectRunner.new( %w[ 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] 7.rb[1] 8.rb[1] 9.rb[1] ], [], "9.rb[1]" => %w[ 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] 7.rb[1] 8.rb[1] ] ) end let(:counting_minimizer) do new_minimizer(fake_runner, counting_reporter) end it 'returns the full command if the failure can not be reduced' do counting_minimizer.find_minimal_repro expect(counting_minimizer.repro_command_for_currently_needed_ids).to eq( "rspec 1.rb[1] 2.rb[1] 3.rb[1] 4.rb[1] 5.rb[1] 6.rb[1] 7.rb[1] 8.rb[1] 9.rb[1]" ) end it 'detects an unminimisable failure in the minimum number of runs' do counting_minimizer.find_minimal_repro # The recursive bisection strategy should take 1 + 2 + 4 + 8 = 15 runs # to determine that a failure is fully dependent on 8 preceding # examples: # # 1 run to determine that any of the candidates are culprits # 2 runs to determine that each half contains a culprit # 4 runs to determine that each quarter contains a culprit # 8 runs to determine that each candidate is a culprit expect(counting_reporter.round_count).to eq(15) end end it 'ignores flapping examples that did not fail on the initial full run but fail on later runs' do def fake_runner.run(ids) super.tap do |results| @run_count ||= 0 if (@run_count += 1) > 1 results.failed_example_ids << "8.rb[1]" end end end minimizer = new_minimizer(fake_runner) minimizer.find_minimal_repro expect(minimizer.repro_command_for_currently_needed_ids).to eq("rspec 2.rb[1] 4.rb[1] 5.rb[1]") end it 'aborts early when no examples fail' do minimizer = new_minimizer(FakeBisectRunner.new( %w[ 1.rb[1] 2.rb[1] ], [], {} )) expect { minimizer.find_minimal_repro }.to raise_error(RSpec::Core::Bisect::BisectFailedError, /No failures found/i) end context "when the `repro_command_for_currently_needed_ids` is queried before it has sufficient information" do it 'returns an explanation that will be printed when the bisect run is aborted immediately' do minimizer = new_minimizer(FakeBisectRunner.new([], [], {})) expect(minimizer.repro_command_for_currently_needed_ids).to include("Not yet enough information") end end def new_minimizer(runner, reporter=RSpec::Core::NullReporter) shell_command = Bisect::ShellCommand.new([]) Bisect::ExampleMinimizer.new(shell_command, runner, reporter) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/coordinator_spec.rb0000664000000000000000000002257514557677674027025 0ustar rootrootrequire 'rspec/core/bisect/coordinator' require 'support/fake_bisect_runner' require 'support/formatter_support' module RSpec::Core RSpec.describe Bisect::Coordinator, :simulate_shell_allowing_unquoted_ids do include FormatterSupport let(:config) { instance_double(Configuration, :bisect_runner_class => fake_bisect_runner) } let(:spec_runner) { instance_double(RSpec::Core::Runner, :configuration => config) } let(:fake_bisect_runner) do FakeBisectRunner.new( 1.upto(8).map { |i| "#{i}.rb[1:1]" }, %w[ 2.rb[1:1] ], { "5.rb[1:1]" => %w[ 1.rb[1:1] 4.rb[1:1] ] } ) end def find_minimal_repro(output, formatter=Formatters::BisectProgressFormatter, bisect_runner = :fork) Bisect::Coordinator.bisect_with(spec_runner, [], formatter.new(output, bisect_runner)) end it 'notifies the bisect progress formatter of progress and closes the output' do tempfile = Tempfile.new("bisect") File.open(tempfile.path, "w") do |output_file| find_minimal_repro(output_file) output = normalize_durations(File.read(tempfile.path)).chomp expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" |Running suite to find failures... (n.nnnn seconds) |Starting bisect with 2 failing examples and 6 non-failing examples. |Checking that failure(s) are order-dependent... failure appears to be order-dependent | |Round 1: bisecting over non-failing examples 1-6 .. ignoring examples 4-6 (n.nnnn seconds) |Round 2: bisecting over non-failing examples 1-3 .. multiple culprits detected - splitting candidates (n.nnnn seconds) |Round 3: bisecting over non-failing examples 1-2 .. ignoring example 2 (n.nnnn seconds) |Bisect complete! Reduced necessary non-failing examples from 6 to 2 in n.nnnn seconds. | |The minimal reproduction command is: | rspec 1.rb[1:1] 2.rb[1:1] 4.rb[1:1] 5.rb[1:1] EOS end end it 'can use the bisect debug formatter to get detailed progress' do output = StringIO.new find_minimal_repro(output, Formatters::BisectDebugFormatter) output = normalize_durations(output.string) expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" and bisect runner: "FakeBisectRunner" |Running suite to find failures... (n.nnnn seconds) | - Failing examples (2): | - 2.rb[1:1] | - 5.rb[1:1] | - Non-failing examples (6): | - 1.rb[1:1] | - 3.rb[1:1] | - 4.rb[1:1] | - 6.rb[1:1] | - 7.rb[1:1] | - 8.rb[1:1] |Checking that failure(s) are order-dependent.. | - Running: rspec 2.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Failure appears to be order-dependent |Round 1: bisecting over non-failing examples 1-6 | - Running: rspec 2.rb[1:1] 5.rb[1:1] 6.rb[1:1] 7.rb[1:1] 8.rb[1:1] (n.nnnn seconds) | - Running: rspec 1.rb[1:1] 2.rb[1:1] 3.rb[1:1] 4.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Examples we can safely ignore (3): | - 6.rb[1:1] | - 7.rb[1:1] | - 8.rb[1:1] | - Remaining non-failing examples (3): | - 1.rb[1:1] | - 3.rb[1:1] | - 4.rb[1:1] |Round 2: bisecting over non-failing examples 1-3 | - Running: rspec 2.rb[1:1] 4.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Running: rspec 1.rb[1:1] 2.rb[1:1] 3.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Multiple culprits detected - splitting candidates |Round 3: bisecting over non-failing examples 1-2 | - Running: rspec 2.rb[1:1] 3.rb[1:1] 4.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Running: rspec 1.rb[1:1] 2.rb[1:1] 4.rb[1:1] 5.rb[1:1] (n.nnnn seconds) | - Examples we can safely ignore (1): | - 3.rb[1:1] | - Remaining non-failing examples (2): | - 1.rb[1:1] | - 4.rb[1:1] |Bisect complete! Reduced necessary non-failing examples from 6 to 2 in n.nnnn seconds. | |The minimal reproduction command is: | rspec 1.rb[1:1] 2.rb[1:1] 4.rb[1:1] 5.rb[1:1] EOS end context "with an order-independent failure" do it "detects the independent case and prints the minimal reproduction" do fake_bisect_runner.dependent_failures = {} output = StringIO.new find_minimal_repro(output, Formatters::BisectProgressFormatter, :shell) output = normalize_durations(output.string) expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" |Running suite to find failures... (n.nnnn seconds) |Starting bisect with 1 failing example and 7 non-failing examples. |Checking that failure(s) are order-dependent... failure(s) do not require any non-failures to run first | |Bisect complete! Reduced necessary non-failing examples from 7 to 0 in n.nnnn seconds. | |The minimal reproduction command is: | rspec 2.rb[1:1] EOS end it "also indicates that the :fork runner may be at fault when that was used" do fake_bisect_runner.dependent_failures = {} output = StringIO.new find_minimal_repro(output, Formatters::BisectProgressFormatter, :fork) output = normalize_durations(output.string) expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" |Running suite to find failures... (n.nnnn seconds) |Starting bisect with 1 failing example and 7 non-failing examples. |Checking that failure(s) are order-dependent... failure(s) do not require any non-failures to run first | |================================================================================ |NOTE: this bisect run used `config.bisect_runner = :fork`, which generally |provides significantly faster bisection runs than the old shell-based runner, |but may inaccurately report that no non-failures are required. If this result |is unexpected, consider setting `config.bisect_runner = :shell` and trying again. |================================================================================ | |Bisect complete! Reduced necessary non-failing examples from 7 to 0 in n.nnnn seconds. | |The minimal reproduction command is: | rspec 2.rb[1:1] EOS end it "can use the debug formatter for detailed output" do fake_bisect_runner.dependent_failures = {} output = StringIO.new find_minimal_repro(output, Formatters::BisectDebugFormatter) output = normalize_durations(output.string) expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" and bisect runner: "FakeBisectRunner" |Running suite to find failures... (n.nnnn seconds) | - Failing examples (1): | - 2.rb[1:1] | - Non-failing examples (7): | - 1.rb[1:1] | - 3.rb[1:1] | - 4.rb[1:1] | - 5.rb[1:1] | - 6.rb[1:1] | - 7.rb[1:1] | - 8.rb[1:1] |Checking that failure(s) are order-dependent.. | - Running: rspec 2.rb[1:1] (n.nnnn seconds) | - Failure is not order-dependent |Bisect complete! Reduced necessary non-failing examples from 7 to 0 in n.nnnn seconds. | |The minimal reproduction command is: | rspec 2.rb[1:1] EOS end end context "when the user aborst the bisect with ctrl-c" do let(:aborting_formatter) do Class.new(Formatters::BisectProgressFormatter) do Formatters.register self def bisect_round_started(notification) return super unless @round_count == 1 Process.kill("INT", Process.pid) # Process.kill is not a synchronous call, so to ensure the output # below aborts at a deterministic place, we need to block here. # The sleep will be interrupted by the signal once the OS sends it. # For the most part, this is only needed on JRuby, but we saw # the asynchronous behavior on an MRI 2.0 travis build as well. sleep 5 end end end it "prints the most minimal repro command it has found so far" do output = StringIO.new expect { find_minimal_repro(output, aborting_formatter) }.to raise_error(an_object_having_attributes( :class => SystemExit, :status => 1 )) output = normalize_durations(output.string) expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |Bisect started using options: "" |Running suite to find failures... (n.nnnn seconds) |Starting bisect with 2 failing examples and 6 non-failing examples. |Checking that failure(s) are order-dependent... failure appears to be order-dependent | |Round 1: bisecting over non-failing examples 1-6 .. ignoring examples 4-6 (n.nnnn seconds) | |Bisect aborted! | |The most minimal reproduction command discovered so far is: | rspec 1.rb[1:1] 2.rb[1:1] 3.rb[1:1] 4.rb[1:1] 5.rb[1:1] EOS end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/bisect/shell_command_spec.rb0000664000000000000000000002275514557677674027307 0ustar rootrootrequire 'rspec/core/bisect/shell_command' require 'rspec/core/formatters/bisect_drb_formatter' module RSpec::Core RSpec.describe Bisect::ShellCommand do let(:server) { instance_double("RSpec::Core::Bisect::Server", :drb_port => 1234) } let(:shell_command) { described_class.new(original_cli_args) } describe "#command_for" do def command_for(locations, options={}) load_path = options.fetch(:load_path) { [] } orig_load_path = $LOAD_PATH.dup $LOAD_PATH.replace(load_path) shell_command.command_for(locations, server) ensure $LOAD_PATH.replace(orig_load_path) end let(:original_cli_args) { %w[ spec/unit -rfoo -Ibar --warnings --backtrace ] } it "includes the original CLI arg options" do cmd = command_for(%w[ spec/1.rb spec/2.rb ]) expect(cmd).to include("-rfoo -Ibar --warnings --backtrace") end it 'replaces the locations from the original CLI args with the provided locations' do cmd = command_for(%w[ spec/1.rb spec/2.rb ]) expect(cmd).to match(%r{'?spec/1\.rb'? '?spec/2\.rb'?}).and exclude("spec/unit") end it 'escapes locations' do cmd = command_for(["path/with spaces/to/spec.rb"]) if uses_quoting_for_escaping? expect(cmd).to include("'path/with spaces/to/spec.rb'") else expect(cmd).to include('path/with\ spaces/to/spec.rb') end end it "includes an option for the server's DRB port" do cmd = command_for([]) expect(cmd).to include("--drb-port #{server.drb_port}") end it "ignores an existing --drb-port option (since we use the server's port instead)" do original_cli_args << "--drb-port" << "9999" cmd = command_for([]) expect(cmd).to include("--drb-port #{server.drb_port}").and exclude("9999") expect(cmd.scan("--drb-port").count).to eq(1) end %w[ --bisect --bisect=verbose --bisect=blah ].each do |value| it "ignores a `#{value}` option since that would infinitely recurse" do original_cli_args << value cmd = command_for([]) expect(cmd).to exclude(value) end end it 'uses the bisect formatter' do cmd = command_for([]) expect(cmd).to include("--format bisect") end def expect_formatters_to_be_excluded cmd = command_for([]) expect(cmd).to include("--format bisect").and exclude( "progress", "html", "--out", "specs.html", "-f ", "-o " ) expect(cmd.scan("--format").count).to eq(1) end it 'excludes any --format and matching --out options passed in the original args' do original_cli_args.concat %w[ --format progress --format html --out specs.html ] expect_formatters_to_be_excluded end it 'excludes any -f and matching -o options passed in the original args' do original_cli_args.concat %w[ -f progress -f html -o specs.html ] expect_formatters_to_be_excluded end it 'excludes any -f and matching -o options passed in the original args' do original_cli_args.concat %w[ -fprogress -fhtml -ospecs.html ] expect_formatters_to_be_excluded end it 'starts with the path to the current ruby executable' do cmd = command_for([]) expect(cmd).to start_with(File.join( RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] )) end it 'includes the path to the rspec executable after the ruby executable' do cmd = command_for([]) expect(cmd).to first_include("ruby").then_include(RSpec::Core.path_to_executable) end it 'escapes the rspec executable' do allow(RSpec::Core).to receive(:path_to_executable).and_return("path/with spaces/rspec") cmd = command_for([]) if uses_quoting_for_escaping? expect(cmd).to include("'path/with spaces/rspec'") else expect(cmd).to include('path/with\ spaces/rspec') end end it 'includes the current load path as an option to `ruby`, not as an option to `rspec`' do cmd = command_for([], :load_path => %W[ lp/foo lp/bar ]) if uses_quoting_for_escaping? expect(cmd).to first_include("-I'lp/foo':'lp/bar'").then_include(RSpec::Core.path_to_executable) else expect(cmd).to first_include("-Ilp/foo:lp/bar").then_include(RSpec::Core.path_to_executable) end end it 'escapes the load path entries' do cmd = command_for([], :load_path => ['l p/foo', 'l p/bar' ]) if uses_quoting_for_escaping? expect(cmd).to first_include("-I'l p/foo':'l p/bar'").then_include(RSpec::Core.path_to_executable) else expect(cmd).to first_include('-Il\ p/foo:l\ p/bar').then_include(RSpec::Core.path_to_executable) end end it 'supports Pathnames in the load path' do cmd = command_for([], :load_path => [Pathname('l p/foo'), Pathname('l p/bar') ]) if uses_quoting_for_escaping? expect(cmd).to first_include("-I'l p/foo':'l p/bar'").then_include(RSpec::Core.path_to_executable) else expect(cmd).to first_include('-Il\ p/foo:l\ p/bar').then_include(RSpec::Core.path_to_executable) end end end describe "#repro_command_from", :simulate_shell_allowing_unquoted_ids do let(:original_cli_args) { %w[ spec/unit --seed 1234 ] } def repro_command_from(ids) shell_command.repro_command_from(ids) end it 'starts with `rspec #{example_ids}`' do cmd = repro_command_from(%w[ ./spec/unit/1_spec.rb[1:1] ./spec/unit/2_spec.rb[1:1] ]) expect(cmd).to start_with("rspec ./spec/unit/1_spec.rb[1:1] ./spec/unit/2_spec.rb[1:1]") end it 'includes the original CLI args but excludes the original CLI locations' do cmd = repro_command_from(%w[ ./spec/unit/1_spec.rb[1:1] ./spec/unit/2_spec.rb[1:1] ]) expect(cmd).to include("--seed 1234").and exclude("spec/unit ") end it 'includes the original SPEC_OPTS but excludes the --bisect flag' do with_env_vars('SPEC_OPTS' => '--bisect --seed 1234') do cmd = repro_command_from(%w[ ./spec/unit/1_spec.rb[1:1] ]) expect(cmd).to include('SPEC_OPTS="--seed 1234"').and exclude("--bisect") end end it 'includes original options that `command_for` excludes' do original_cli_args << "--format" << "progress" expect(shell_command.command_for(%w[ ./foo.rb[1:1] ], server)).to exclude("--format progress") expect(repro_command_from(%w[ ./foo.rb[1:1] ])).to include("--format progress") end it 'groups multiple ids for the same file together' do cmd = repro_command_from(%w[ ./spec/unit/1_spec.rb[1:1] ./spec/unit/1_spec.rb[1:2] ]) expect(cmd).to include("./spec/unit/1_spec.rb[1:1,1:2]") end it 'prints the files in alphabetical order' do cmd = repro_command_from(%w[ ./spec/unit/2_spec.rb[1:1] ./spec/unit/1_spec.rb[1:1] ]) expect(cmd).to include("./spec/unit/1_spec.rb[1:1] ./spec/unit/2_spec.rb[1:1]") end it 'prints ids from the same file in sequential order' do cmd = repro_command_from(%w[ ./spec/unit/1_spec.rb[2:1] ./spec/unit/1_spec.rb[1:2] ./spec/unit/1_spec.rb[1:1] ./spec/unit/1_spec.rb[1:10] ./spec/unit/1_spec.rb[1:9] ]) expect(cmd).to include("./spec/unit/1_spec.rb[1:1,1:2,1:9,1:10,2:1]") end it 'does not include `--bisect` even though the original args do' do original_cli_args << "--bisect" expect(repro_command_from(%w[ ./foo.rb[1:1] ])).to exclude("bisect") end it 'quotes the ids on a shell like ZSH that requires it' do with_env_vars 'SHELL' => '/usr/local/bin/zsh' do expect(repro_command_from(%w[ ./foo.rb[1:1] ])).to include("'./foo.rb[1:1]'") end end end describe "#original_locations" do let(:original_cli_args) { %w[ spec/unit spec/integration/foo_spec.rb --order defined ] } it "returns the original files or directories to run" do expect(shell_command.original_locations).to eq %w[spec/unit spec/integration/foo_spec.rb] end end describe "#bisect_environment_hash" do let(:original_cli_args) { %w[] } context 'when `SPEC_OPTS` has been set' do it 'returns a hash with `SPEC_OPTS` set to the opts without --bisect' do with_env_vars 'SPEC_OPTS' => '--order defined --bisect' do expect(shell_command.bisect_environment_hash).to eq('SPEC_OPTS' => '--order defined') end end end context 'when `SPEC_OPTS` has not been set' do it 'returns a blank hash' do expect(shell_command.bisect_environment_hash).to eq({}) end end end describe "#spec_opts_without_bisect" do let(:original_cli_args) { %w[ ] } context 'when `SPEC_OPTS` has been set' do it 'returns the spec opts without --bisect' do with_env_vars 'SPEC_OPTS' => '--order defined --bisect' do expect(shell_command.spec_opts_without_bisect).to eq('--order defined') end end end context 'when `SPEC_OPTS` has not been set' do it 'returns a blank string' do expect(shell_command.spec_opts_without_bisect).to eq('') end end end def uses_quoting_for_escaping? RSpec::Support::OS.windows? || RSpec::Support::Ruby.jruby? end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/option_parser_spec.rb0000664000000000000000000003324014557677674026104 0ustar rootrootrequire 'rspec/core/drb' require 'rspec/core/bisect/coordinator' module RSpec::Core RSpec.describe OptionParser do before do allow(RSpec.configuration).to receive(:reporter) do fail "OptionParser is not allowed to access `config.reporter` since we want " + "ConfigurationOptions to have the chance to set `deprecation_stream` " + "(based on `--deprecation-out`) before the deprecation formatter is " + "initialized by the reporter instantiation. If you need to issue a deprecation, " + "populate an `options[:deprecations]` key and have ConfigurationOptions " + "issue the deprecation after configuring `deprecation_stream`" end end context "when given empty args" do it "does not parse them" do expect(OptionParser).not_to receive(:new) Parser.parse([]) end it "still returns a `:files_or_directories_to_run` entry since callers expect that" do expect( Parser.parse([]) ).to eq(:files_or_directories_to_run => []) end end it 'does not mutate the provided args array' do args = %w[ --require foo ] expect { Parser.parse(args) }.not_to change { args } end it "proposes you to use --help and returns an error on incorrect argument" do parser = Parser.new(["--my_wrong_arg"]) expect(parser).to receive(:abort).with(a_string_including('use --help')) parser.parse end it 'treats additional arguments as `:files_or_directories_to_run`' do options = Parser.parse(%w[ path/to/spec.rb --fail-fast spec/unit -Ibar 1_spec.rb:23 ]) expect(options).to include( :files_or_directories_to_run => %w[ path/to/spec.rb spec/unit 1_spec.rb:23 ] ) end { '--init' => ['-i','--I'], '--default-path' => ['-d'], '--dry-run' => ['-d'], '--drb-port' => ['-d'], }.each do |long, shorts| shorts.each do |option| it "won't parse #{option} as a shorthand for #{long}" do parser = Parser.new([option]) expect(parser).to receive(:abort).with(a_string_including('use --help')) parser.parse end end end %w[ -h --help ].each do |option| it 'sets the `:runner` option with the `PrintHelp` invocation' do parser = Parser.new([option]) options = parser.parse expect(options[:runner]).to be_instance_of(RSpec::Core::Invocations::PrintHelp) end end %w[ -v --version ].each do |option| describe option do it 'sets the `:runner` option with the `PrintVersion` invocation' do parser = Parser.new([option]) options = parser.parse expect(options[:runner]).to be_instance_of(RSpec::Core::Invocations::PrintVersion) end end end %w[ -X --drb ].each do |option| describe option do let(:parser) { Parser.new([option]) } it 'sets the `:drb` option to true' do options = parser.parse expect(options[:drb]).to be(true) end it 'sets the `:runner` option with the `DrbWithFallback` invocation' do options = parser.parse expect(options[:runner]).to be_instance_of(RSpec::Core::Invocations::DRbWithFallback) end end end describe '--init' do let(:initialize_project) { double(:initialize_project) } it 'sets the `:runner` option with the `InitializeProject` invocation' do parser = Parser.new(["--init"]) options = parser.parse expect(options[:runner]).to be_instance_of(RSpec::Core::Invocations::InitializeProject) end end describe "-I" do it "sets the path" do options = Parser.parse(%w[-I path/to/foo]) expect(options[:libs]).to eq %w[path/to/foo] end context "with a string containing `#{File::PATH_SEPARATOR}`" do it "splits into multiple paths, just like Ruby's `-I` option" do options = Parser.parse(%W[-I path/to/foo -I path/to/bar#{File::PATH_SEPARATOR}path/to/baz]) expect(options[:libs]).to eq %w[path/to/foo path/to/bar path/to/baz] end end end describe "--default-path" do it "sets the default path where RSpec looks for examples" do options = Parser.parse(%w[--default-path foo]) expect(options[:default_path]).to eq "foo" end end %w[--format -f].each do |option| describe option do it "defines the formatter" do options = Parser.parse([option, 'doc']) expect(options[:formatters].first).to eq(["doc"]) end end end %w[--out -o].each do |option| describe option do it "sets the output stream for the formatter" do options = Parser.parse([option, 'out.txt']) expect(options[:formatters].last).to eq(['progress', 'out.txt']) end context "with multiple formatters" do context "after last formatter" do it "sets the output stream for the last formatter" do options = Parser.parse(['-f', 'progress', '-f', 'doc', option, 'out.txt']) expect(options[:formatters][0]).to eq(['progress']) expect(options[:formatters][1]).to eq(['doc', 'out.txt']) end end context "after first formatter" do it "sets the output stream for the first formatter" do options = Parser.parse(['-f', 'progress', option, 'out.txt', '-f', 'doc']) expect(options[:formatters][0]).to eq(['progress', 'out.txt']) expect(options[:formatters][1]).to eq(['doc']) end end end end end describe "--deprecation-out" do it 'sets the deprecation stream' do options = Parser.parse(["--deprecation-out", "path/to/log"]) expect(options).to include(:deprecation_stream => "path/to/log") end end describe "--only-failures" do it 'is equivalent to `--tag last_run_status:failed`' do tag = Parser.parse(%w[ --tag last_run_status:failed ]) only_failures = Parser.parse(%w[ --only-failures ]) expect(only_failures).to include(tag) end end %w[--next-failure -n].each do |option| describe option do it 'is equivalent to `--tag last_run_status:failed --fail-fast --order defined`' do long_form = Parser.parse(%w[ --tag last_run_status:failed --fail-fast --order defined ]) next_failure = Parser.parse([option]) expect(next_failure).to include(long_form) end it 'does not force `--order defined` over a specified `--seed 1234` option that comes before it' do options = Parser.parse(['--seed', '1234', option]) expect(options).to include(:order => "rand:1234") end it 'does not force `--order defined` over a specified `--seed 1234` option that comes after it' do options = Parser.parse([option, '--seed', '1234']) expect(options).to include(:order => "rand:1234") end end end %w[--example -e].each do |option| describe option do it "escapes the arg" do options = Parser.parse([option, "this (and that)"]) expect(options[:full_description].length).to eq(1) expect("this (and that)").to match(options[:full_description].first) end end end %w[--example-matches -E].each do |option| describe option do it "does not escape the arg" do options = Parser.parse([option, 'this (and that)\b']) expect(options[:full_description].length).to eq(1) expect(/this (and that)\b/).to eq(options[:full_description].first) end end end %w[--pattern -P].each do |option| describe option do it "sets the filename pattern" do options = Parser.parse([option, 'spec/**/*.spec']) expect(options[:pattern]).to eq('spec/**/*.spec') end it 'combines multiple patterns' do options = Parser.parse([option, 'spec/**/*.spec', option, 'tests/**/*.spec']) expect(options[:pattern]).to eq('spec/**/*.spec,tests/**/*.spec') end end end %w[--tag -t].each do |option| describe option do context "without ~" do it "treats no value as true" do options = Parser.parse([option, 'foo']) expect(options[:inclusion_filter]).to eq(:foo => true) end it "treats 'true' as true" do options = Parser.parse([option, 'foo:true']) expect(options[:inclusion_filter]).to eq(:foo => true) end it "treats 'nil' as nil" do options = Parser.parse([option, 'foo:nil']) expect(options[:inclusion_filter]).to eq(:foo => nil) end it "treats 'false' as false" do options = Parser.parse([option, 'foo:false']) expect(options[:inclusion_filter]).to eq(:foo => false) end it "merges muliple invocations" do options = Parser.parse([option, 'foo:false', option, 'bar:true', option, 'foo:true']) expect(options[:inclusion_filter]).to eq(:foo => true, :bar => true) end it "treats 'any_string' as 'any_string'" do options = Parser.parse([option, 'foo:any_string']) expect(options[:inclusion_filter]).to eq(:foo => 'any_string') end it "treats ':any_sym' as :any_sym" do options = Parser.parse([option, 'foo::any_sym']) expect(options[:inclusion_filter]).to eq(:foo => :any_sym) end it "treats '42' as 42" do options = Parser.parse([option, 'foo:42']) expect(options[:inclusion_filter]).to eq(:foo => 42) end it "treats '3.146' as 3.146" do options = Parser.parse([option, 'foo:3.146']) expect(options[:inclusion_filter]).to eq(:foo => 3.146) end end context "with ~" do it "treats no value as true" do options = Parser.parse([option, '~foo']) expect(options[:exclusion_filter]).to eq(:foo => true) end it "treats 'true' as true" do options = Parser.parse([option, '~foo:true']) expect(options[:exclusion_filter]).to eq(:foo => true) end it "treats 'nil' as nil" do options = Parser.parse([option, '~foo:nil']) expect(options[:exclusion_filter]).to eq(:foo => nil) end it "treats 'false' as false" do options = Parser.parse([option, '~foo:false']) expect(options[:exclusion_filter]).to eq(:foo => false) end end end end describe "--order" do it "is nil by default" do expect(Parser.parse([])[:order]).to be_nil end %w[rand random].each do |option| context "with #{option}" do it "defines the order as random" do options = Parser.parse(['--order', option]) expect(options[:order]).to eq(option) end end end end describe "--seed" do it "sets the order to rand:SEED" do options = Parser.parse(%w[--seed 123]) expect(options[:order]).to eq("rand:123") end end describe "--bisect" do it "sets the `:bisect` option" do options = Parser.parse(%w[ --bisect ]) expect(options[:bisect]).to be(true) end it "sets the `:runner` option with the `Bisect` invocation" do parser = Parser.new(['--bisect']) options = parser.parse expect(options[:runner]).to be_instance_of(RSpec::Core::Invocations::Bisect) end end describe '--profile' do it 'sets profile_examples to true by default' do options = Parser.parse(%w[--profile]) expect(options[:profile_examples]).to eq true end it 'sets profile_examples to supplied int' do options = Parser.parse(%w[--profile 10]) expect(options[:profile_examples]).to eq 10 end it 'sets profile_examples to true when accidentally combined with path' do allow_warning options = Parser.parse(%w[--profile some/path]) expect(options[:profile_examples]).to eq true end it 'warns when accidentally combined with path' do expect_warning_without_call_site "Non integer specified as profile count" options = Parser.parse(%w[--profile some/path]) expect(options[:profile_examples]).to eq true end end describe '--fail-fast' do it 'warns when a non-integer is specified as fail count' do expect_warning_without_call_site a_string_including("--fail-fast", "three") Parser.parse(%w[--fail-fast=three]) end end describe '--warning' do around do |ex| verbose = $VERBOSE ex.run $VERBOSE = verbose end it 'immediately enables warnings so that warnings are issued for files loaded by `--require`' do $VERBOSE = false expect { Parser.parse(%w[--warnings]) }.to change { $VERBOSE }.from(false).to(true) end end describe '--force-color' do it 'aborts if --no-color was previously set' do parser = Parser.new(%w[--no-color --force-color]) expect(parser).to receive(:abort).with(a_string_including('only use one of `--force-color` and `--no-color`')) parser.parse end end describe '--no-color' do it 'aborts if --force-color was previously set' do parser = Parser.new(%w[--force-color --no-color]) expect(parser).to receive(:abort).with(a_string_including('only use one of --force-color and --no-color')) parser.parse end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/rake_task_spec.rb0000664000000000000000000004027214557677674025167 0ustar rootrootrequire "rspec/core/rake_task" require 'tempfile' module RSpec::Core RSpec.describe RakeTask do let(:task) { RakeTask.new } def ruby FileUtils::RUBY end def spec_command task.__send__(:spec_command) end context "with a name passed to the constructor" do let(:task) { RakeTask.new(:task_name) } it "correctly sets the name" do expect(task.name).to eq :task_name end end context "with args passed to the rake task" do it "correctly passes along task arguments" do the_task = RakeTask.new(:rake_task_args, :files) do |t, args| expect(args[:files]).to eq "first_spec.rb" end expect(the_task).to receive(:run_task) { true } Rake.application.invoke_task("rake_task_args[first_spec.rb]") end end default_load_path_opts = '-I\S+' context "default" do it "renders rspec" do expect(spec_command).to match(/^#{ruby} #{default_load_path_opts} '?#{task.rspec_path}'?/) end end context "with space", :unless => RSpec::Support::OS.windows? do it "renders rspec with space escaped" do task.rspec_path = '/path with space/exe/rspec' expect(spec_command).to match(/^#{ruby} #{default_load_path_opts} \/path\\ with\\ space\/exe\/rspec/) end end context "on windows, with a quote in the name", :if => RSpec::Support::OS.windows? do it "renders rspec quoted, with quote escaped" do task.rspec_path = "/foo'bar/exe/rspec" expect(spec_command).to include(%q|'/foo\'bar/exe/rspec'|) end end context "with ruby options" do it "renders them before the rspec path" do task.ruby_opts = "-w" expect(spec_command).to match(/^#{ruby} -w #{default_load_path_opts} '?#{task.rspec_path}'?/) end end context "with rspec_opts" do include RSpec::Core::ShellEscape it "adds the rspec_opts" do task.rspec_opts = "-Ifoo" expect(spec_command).to match(/#{task.rspec_path}.*-Ifoo/).and( include(escape(RSpec::Core::RakeTask::DEFAULT_PATTERN)) # sanity check for following specs ) end it 'correctly excludes the default pattern if rspec_opts includes --pattern' do task.rspec_opts = "--pattern some_specs" expect(spec_command).to include("--pattern some_specs").and( exclude(escape(RSpec::Core::RakeTask::DEFAULT_PATTERN)) ) end it 'behaves properly if rspec_opts is an array' do task.rspec_opts = %w[--pattern some_specs] expect(spec_command).to include("--pattern some_specs").and( exclude(escape(RSpec::Core::RakeTask::DEFAULT_PATTERN)) ) end end context "with pattern" do it "adds the pattern" do task.pattern = "complex_pattern" expect(spec_command).to match(/ --pattern '?complex_pattern'?/) end it "shellescapes the pattern as necessary", :unless => RSpec::Support::OS.windows? do task.pattern = "foo'bar" expect(spec_command).to include(" --pattern foo\\'bar") end end context "when `failure_message` is configured" do before do allow(task).to receive(:exit) task.failure_message = "Bad news" end it 'prints it if the RSpec run failed' do task.ruby_opts = '-e "exit(1);" ;#' expect { task.run_task false }.to output(/Bad news/).to_stdout end it 'does not print it if the RSpec run succeeded' do task.ruby_opts = '-e "exit(0);" ;#' expect { task.run_task false }.not_to output(/Bad/).to_stdout end end context 'with custom exit status' do def silence_output(&block) expect(&block).to output(anything).to_stdout.and output(anything).to_stderr end it 'returns the correct status on exit', :slow do expect(task).to receive(:exit).with(2) silence_output do task.ruby_opts = '-e "exit(2);" ;#' task.run_task true end end end context 'with verbose enabled' do it 'prints the command only to stdout for passing specs', :slow do expect { task.ruby_opts = '-e ""' task.run_task true }.to output(/-e ""/).to_stdout.and avoid_outputting.to_stderr end it 'prints an additional message to stderr for failures', :slow do allow(task).to receive(:exit) expect { task.ruby_opts = '-e "exit(1);" ;#' task.run_task true }.to output(/-e "exit\(1\);" ;#/).to_stdout.and output(/-e "exit\(1\);".* failed/).to_stderr end end context 'with verbose disabled' do it 'does not print to stdout or stderr', :slow do allow(task).to receive(:exit) expect { task.ruby_opts = '-e "exit(1);" ;#' task.run_task false }.to avoid_outputting.to_stdout.and avoid_outputting.to_stderr end end context "with_clean_environment is set" do it "removes the environment variables", :if => RUBY_VERSION >= '1.9.0', :unless => RSpec::Support::Ruby.jruby? do with_env_vars 'MY_ENV' => 'ABC' do if RSpec::Support::OS.windows? essential_shell_variables = /\["ANSICON", "ANSICON_DEF", "HOME", "TMPDIR", "USER"\]/ else essential_shell_variables = /\["PWD"(?:, "SHLVL")?(?:, "_")?(?:, "__CF_USER_TEXT_ENCODING")?\]/ end expect { task.with_clean_environment = true task.ruby_opts = '-e "puts \"Environment: #{ENV.keys.sort.inspect}\""' task.run_task false }.to avoid_outputting.to_stderr.and output(essential_shell_variables).to_stdout_from_any_process end end end def loaded_files args = Shellwords.split(spec_command) args -= [task.class::RUBY, "-S", task.rspec_path] config = Configuration.new config_options = ConfigurationOptions.new(args) config_options.configure(config) config.files_to_run end def specify_consistent_ordering_of_files_to_run(pattern, file_searcher) orderings = [ %w[ a/1.rb a/2.rb a/3.rb ], %w[ a/2.rb a/1.rb a/3.rb ], %w[ a/3.rb a/2.rb a/1.rb ] ].map do |files| allow(file_searcher).to receive(:[]).with(anything).and_call_original expect(file_searcher).to receive(:[]).with(a_string_including pattern) { files } loaded_files end expect(orderings.uniq.size).to eq(1) end context "with SPEC env var set" do it "sets files to run" do with_env_vars 'SPEC' => 'path/to/file' do expect(loaded_files).to contain_files("path/to/file") end end it "sets the files to run in a consistent order, regardless of the underlying FileList ordering" do with_env_vars 'SPEC' => 'a/*.rb' do specify_consistent_ordering_of_files_to_run('a/*.rb', FileList) end end end describe "load path manipulation" do def self.it_configures_rspec_load_path(description, path_template) context "when rspec is installed as #{description}" do # Matchers are lazily loaded via `autoload`, so we need to get the matcher before # the load path is manipulated, so we're using `let!` here to do that. let!(:include_expected_load_path_option) do match(/ -I'?#{path_template % "rspec-core"}'?#{File::PATH_SEPARATOR}'?#{path_template % "rspec-support"}'? /) end it "adds the current rspec-core and rspec-support dirs to the load path to ensure the current version is used" do $LOAD_PATH.replace([ path_template % "rspec-core", path_template % "rspec-support", path_template % "rspec-expectations", path_template % "rspec-mocks", path_template % "rake" ]) expect(spec_command).to include_expected_load_path_option end it "avoids adding the same load path entries twice" do $LOAD_PATH.replace([ path_template % "rspec-core", path_template % "rspec-support", path_template % "rspec-core", path_template % "rspec-support" ]) expect(spec_command).to include_expected_load_path_option end end end it_configures_rspec_load_path "bundler :git dependencies", "/Users/myron/code/some-gem/bundle/ruby/2.1.0/bundler/gems/%s-8d2e4e570994/lib" it_configures_rspec_load_path "bundler :path dependencies", "/Users/myron/code/rspec-dev/repos/%s/lib" it_configures_rspec_load_path "a rubygem", "/Users/myron/.gem/ruby/1.9.3/gems/%s-3.1.0.beta1/lib" it "does not include extra load path entries for other gems that have `rspec-core` in its path" do # matchers are lazily loaded with autoload, so we need to get the matcher before manipulating the load path. include_extra_load_path_entries = include("simplecov", "minitest", "rspec-core/spec") # these are items on my load path due to `bundle install --standalone`, # and my initial logic caused all these to be included in the `-I` option. $LOAD_PATH.replace([ "/Users/user/code/rspec-dev/repos/rspec-core/spec", "/Users/user/code/rspec-dev/repos/rspec-core/bundle/ruby/1.9.1/gems/simplecov-0.8.2/lib", "/Users/user/code/rspec-dev/repos/rspec-core/bundle/ruby/1.9.1/gems/simplecov-html-0.8.0/lib", "/Users/user/code/rspec-dev/repos/rspec-core/bundle/ruby/1.9.1/gems/minitest-5.3.3/lib", "/Users/user/code/rspec-dev/repos/rspec/lib", "/Users/user/code/rspec-dev/repos/rspec-mocks/lib", "/Users/user/code/rspec-dev/repos/rspec-core/lib", "/Users/user/code/rspec-dev/repos/rspec-expectations/lib", "/Users/user/code/rspec-dev/repos/rspec-support/lib", "/Users/user/code/rspec-dev/repos/rspec-core/bundle", ]) expect(spec_command).not_to include_extra_load_path_entries end end it "sets the files to run in a consistent order, regardless of the underlying FileList ordering" do task.pattern = 'a/*.rb' specify_consistent_ordering_of_files_to_run('a/*.rb', Dir) end context "with a pattern value" do context "that matches no files" do it "runs nothing" do task.pattern = 'a/*.no_match' expect(loaded_files).to eq([]) end end context "that is an existing directory, not a file glob" do it "loads the spec files in that directory" do task.pattern = "./spec/rspec/core/resources/acceptance" expect(loaded_files).to contain_files("./spec/rspec/core/resources/acceptance/foo_spec.rb") end end context "that is an existing file, not a file glob" do it "loads the spec file" do task.pattern = "./spec/rspec/core/resources/acceptance/foo_spec.rb" expect(loaded_files).to contain_files("./spec/rspec/core/resources/acceptance/foo_spec.rb") end end context "that is an absolute path file glob" do it "loads the matching spec files", :emits_warning_on_windows_on_old_ruby, :pending_on_windows_old_ruby do dir = File.expand_path("../resources", __FILE__) task.pattern = File.join(dir, "**/*_spec.rb") expect(loaded_files).to contain_files( "./spec/rspec/core/resources/acceptance/foo_spec.rb", "./spec/rspec/core/resources/a_spec.rb" ) end end context "that is a relative file glob, for a path not under the default spec dir (`spec`)" do it "loads the matching spec files" do Dir.chdir("./spec/rspec/core") do task.pattern = "resources/**/*_spec.rb" expect(loaded_files).to contain_files( "resources/acceptance/foo_spec.rb", "resources/a_spec.rb" ) end end end context "that is an array of existing files or directories, not a file glob" do it "loads the specified spec files, and spec files from the specified directories" do task.pattern = ["./spec/rspec/core/resources/acceptance", "./spec/rspec/core/resources/a_bar.rb"] expect(loaded_files).to contain_files( "./spec/rspec/core/resources/acceptance/foo_spec.rb", "./spec/rspec/core/resources/a_bar.rb" ) end end # https://github.com/rspec/rspec-core/issues/1695 context "that is a single glob that starts with ./" do it "loads the spec files that match the glob" do task.pattern = "./spec/rspec/core/resources/acceptance/**/*_spec.rb" expect(loaded_files).to contain_files("./spec/rspec/core/resources/acceptance/foo_spec.rb") end end context "that is an array of globs relative to the current working dir" do it "loads spec files that match any of the globs" do task.pattern = ["./spec/rspec/core/resources/acceptance/*_spec.rb", "./spec/rspec/core/resources/*_bar.rb"] expect(loaded_files).to contain_files( "./spec/rspec/core/resources/acceptance/foo_spec.rb", "./spec/rspec/core/resources/a_bar.rb" ) end end context "that is a mixture of file globs and individual files or dirs" do it "loads all specified or matching files" do task.pattern = ["./spec/rspec/core/resources/acceptance/*_spec.rb", "./spec/rspec/core/resources/a_bar.rb"] expect(loaded_files).to contain_files( "./spec/rspec/core/resources/acceptance/foo_spec.rb", "./spec/rspec/core/resources/a_bar.rb" ) end end context "that is a FileList" do it "loads the files from the FileList" do task.pattern = FileList["spec/rspec/core/resources/**/*_spec.rb"] expect(loaded_files).to contain_files( "spec/rspec/core/resources/a_spec.rb", "spec/rspec/core/resources/acceptance/foo_spec.rb" ) end end end context "without an exclude_pattern" do it 'does not pass the --exclude-pattern option' do expect(spec_command).not_to include("exclude") end end context "with an exclude_pattern" do include_context "isolated directory" def make_file(dir, name) File.join("spec", dir, name).tap { |f| FileUtils.touch(f) } end def make_files_in_dir(dir) %w[ foo_spec.rb bar_spec.rb ].map do |file_name| make_file(dir, file_name) end end before do spec_dir = File.join(Dir.getwd, "spec") task.exclude_pattern = "spec/acceptance/*_spec.rb" FileUtils.mkdir_p(File.join(spec_dir, "acceptance")) FileUtils.mkdir_p(File.join(spec_dir, "unit")) make_files_in_dir "acceptance" end it "shellescapes the pattern as necessary", :unless => RSpec::Support::OS.windows? do task.exclude_pattern = "foo'bar" expect(spec_command).to include(" --exclude-pattern foo\\'bar") end it "it does not load matching files" do task.pattern = "spec/**/*_spec.rb" unit_files = make_files_in_dir "unit" expect(loaded_files).to contain_files(*unit_files) end it "excludes files when pattern and exclusion_pattern don't consistently start with ./" do task.exclude_pattern = "./spec/acceptance/*_spec.rb" task.pattern = "spec/**/*_spec.rb" unit_files = make_files_in_dir "unit" expect(loaded_files).to contain_files(*unit_files) end end context "with paths with quotes or spaces" do include_context "isolated directory" it "matches files with quotes and spaces", :failing_on_windows_ci do spec_dir = File.join(Dir.getwd, "spec") task.pattern = "spec/*spec.rb" FileUtils.mkdir_p(spec_dir) files = ["first_spec.rb", "second_\"spec.rb", "third_\'spec.rb", "fourth spec.rb"].map do |file_name| File.join("spec", file_name).tap { |f| FileUtils.touch(f) } end expect(loaded_files).to contain_files(*files) end end it_behaves_like "handling symlinked directories when loading spec files" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/filterable_item_repository_spec.rb0000664000000000000000000002432114557677674030646 0ustar rootrootmodule RSpec module Core RSpec.describe FilterableItemRepository, "#items_for" do FilterableItem = Struct.new(:name) # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/MethodLength def self.it_behaves_like_a_filterable_item_repo(&when_the_repo_has_items_with_metadata) let(:repo) { described_class.new(:any?) } let(:item_1) { FilterableItem.new("Item 1") } let(:item_2) { FilterableItem.new("Item 2") } let(:item_3) { FilterableItem.new("Item 3") } let(:item_4) { FilterableItem.new("Item 4") } context "when the repository is empty" do it 'returns an empty list' do expect(repo.items_for(:foo => "bar")).to eq([]) end end shared_examples_for "adding items to the repository" do |add_method| describe "adding items using `#{add_method}`" do define_method :add_item do |*args| repo.__send__ add_method, *args end context "when the repository has items that have no metadata" do before do add_item item_1, {} add_item item_2, {} end it "returns those items, regardless of the provided argument" do expect(repo.items_for({})).to contain_exactly(item_1, item_2) expect(repo.items_for(:foo => "bar")).to contain_exactly(item_1, item_2) end end context "when the repository has items that have metadata" do before do add_item item_1, :foo => "bar" add_item item_2, :slow => true add_item item_3, :foo => "bar" end it 'return an empty list when given empty metadata' do expect(repo.items_for({})).to eq([]) end it 'return an empty list when given metadata that matches no items' do expect(repo.items_for(:slow => false, :foo => "bazz")).to eq([]) end it 'returns matching items for the provided metadata' do expect(repo.items_for(:slow => true)).to contain_exactly(item_2) expect(repo.items_for(:foo => "bar")).to contain_exactly(item_1, item_3) expect(repo.items_for(:slow => true, :foo => "bar")).to contain_exactly(item_1, item_2, item_3) end it 'returns the matching items in the correct order' do expect(repo.items_for(:slow => true, :foo => "bar")).to eq items_in_expected_order end it 'ignores other metadata keys that are not related to the appended items' do expect(repo.items_for(:slow => true, :other => "foo")).to contain_exactly(item_2) end it 'differentiates between an applicable key being missing and having an explicit `nil` value' do add_item item_4, :bar => nil expect(repo.items_for({})).to eq([]) expect(repo.items_for(:bar => nil)).to contain_exactly(item_4) end it 'returns the correct items when they are appended after a memoized lookup' do expect { add_item item_4, :slow => true }.to change { repo.items_for(:slow => true) }. from(a_collection_containing_exactly(item_2)). to(a_collection_containing_exactly(item_2, item_4)) end let(:flip_proc) do return_val = true Proc.new { return_val.tap { |v| return_val = !v } } end context "with proc values" do before do add_item item_4, { :include_it => flip_proc } end it 'evaluates the proc each time since the logic can return a different value each time' do expect(repo.items_for(:include_it => nil)).to contain_exactly(item_4) expect(repo.items_for(:include_it => nil)).to eq([]) expect(repo.items_for(:include_it => nil)).to contain_exactly(item_4) expect(repo.items_for(:include_it => nil)).to eq([]) end end context "when initialized with the `:any?` predicate" do let(:repo) { FilterableItemRepository::QueryOptimized.new(:any?) } it 'matches against multi-entry items when any of the metadata entries match' do add_item item_4, :key_1 => "val_1", :key_2 => "val_2" expect(repo.items_for(:key_1 => "val_1")).to contain_exactly(item_4) expect(repo.items_for(:key_2 => "val_2")).to contain_exactly(item_4) expect(repo.items_for(:key_1 => "val_1", :key_2 => "val_2")).to contain_exactly(item_4) end end context "when initialized with the `:all?` predicate" do let(:repo) { FilterableItemRepository::QueryOptimized.new(:all?) } it 'matches against multi-entry items when all of the metadata entries match' do add_item item_4, :key_1 => "val_1", :key_2 => "val_2" expect(repo.items_for(:key_1 => "val_1")).to eq([]) expect(repo.items_for(:key_2 => "val_2")).to eq([]) expect(repo.items_for(:key_1 => "val_1", :key_2 => "val_2")).to contain_exactly(item_4) end end module_eval(&when_the_repo_has_items_with_metadata) if when_the_repo_has_items_with_metadata end end end it_behaves_like "adding items to the repository", :append do let(:items_in_expected_order) { [item_1, item_2, item_3] } end it_behaves_like "adding items to the repository", :prepend do let(:items_in_expected_order) { [item_3, item_2, item_1] } end describe '#delete' do before do repo.append item_1, {} repo.append item_1, :foo => true repo.append item_1, :foo => true, :bar => true repo.append item_2, :foo => true end it 'deletes the specified item with the metadata' do expect { repo.delete(item_1, :foo => true) }. to change { repo.items_and_filters }. from([ [item_1, {}], [item_1, { :foo => true }], [item_1, { :foo => true, :bar => true }], [item_2, { :foo => true }] ]). to([ [item_1, {}], [item_1, { :foo => true, :bar => true }], [item_2, { :foo => true }] ]). and change { repo.items_for({ :foo => true }) }. from([item_1, item_1, item_1, item_2]). to([item_1, item_1, item_2]). and change { repo.items_for({ :foo => true, :bar => true }) }. from([item_1, item_1, item_1, item_2]). to([item_1, item_1, item_2]). and avoid_changing { repo.items_for({}) }. from([item_1]) end end end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/MethodLength describe FilterableItemRepository::UpdateOptimized do it_behaves_like_a_filterable_item_repo end describe FilterableItemRepository::QueryOptimized do it_behaves_like_a_filterable_item_repo do describe "performance optimization" do # NOTE: the specs in this context are potentially brittle because they are # coupled to the implementation's usage of `MetadataFilter.apply?`. However, # they demonstrate the perf optimization that was the reason we created # this class, and thus have value in demonstrating the memoization is working # properly and in documenting the reason the class exists in the first place. # Still, if these prove to be brittle in the future, feel free to delete them since # they are not concerned with externally visible behaviors. it 'is optimized to check metadata filter application for a given pair of metadata hashes only once' do # TODO: use mock expectations for this once https://github.com/rspec/rspec-mocks/pull/841 is fixed. call_counts = track_metadata_filter_apply_calls 3.times do expect(repo.items_for(:slow => true, :other => "foo")).to contain_exactly(item_2) end expect(call_counts[:slow => true]).to eq(1) end it 'ignores extraneous metadata keys when doing memoized lookups' do # TODO: use mock expectations for this once https://github.com/rspec/rspec-mocks/pull/841 is fixed. call_counts = track_metadata_filter_apply_calls expect(repo.items_for(:slow => true, :other => "foo")).to contain_exactly(item_2) expect(repo.items_for(:slow => true, :other => "bar")).to contain_exactly(item_2) expect(repo.items_for(:slow => true, :goo => "bazz")).to contain_exactly(item_2) expect(call_counts[:slow => true]).to eq(1) end context "when there are some proc keys" do before do add_item item_4, { :include_it => flip_proc } end it 'still performs memoization for metadata hashes that lack those keys' do call_counts = track_metadata_filter_apply_calls expect(repo.items_for(:slow => true, :other => "foo")).to contain_exactly(item_2) expect(repo.items_for(:slow => true, :other => "foo")).to contain_exactly(item_2) expect(call_counts[:slow => true]).to eq(1) end end def track_metadata_filter_apply_calls Hash.new(0).tap do |call_counts| allow(MetadataFilter).to receive(:apply?).and_wrap_original do |original, predicate, item_meta, request_meta| call_counts[item_meta] += 1 original.call(predicate, item_meta, request_meta) end end end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/runner_spec.rb0000664000000000000000000003737714557677674024550 0ustar rootrootrequire 'rspec/core/drb' require 'support/runner_support' module RSpec::Core RSpec.describe Runner do describe 'invocation' do before do # Simulate invoking the suite like exe/rspec does. allow(RSpec::Core::Runner).to receive(:run) RSpec::Core::Runner.invoke end it 'does not autorun after having been invoked' do expect(RSpec::Core::Runner).not_to receive(:at_exit) RSpec::Core::Runner.autorun end it 'prints a warning when autorun is attempted' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) RSpec::Core::Runner.autorun end end describe '.autorun' do before do @original_ivars = Hash[ Runner.instance_variables.map do |ivar| [ivar, Runner.instance_variable_get(ivar)] end ] end after do (@original_ivars.keys | Runner.instance_variables).each do |ivar| if @original_ivars.key?(ivar) Runner.instance_variable_set(ivar, @original_ivars[ivar]) else # send is necessary for 1.8.7 Runner.send(:remove_instance_variable, ivar) end end end it 'sets an at_exit hook if none is already set' do Runner.instance_eval do @autorun_disabled = false @installed_at_exit = false end allow(RSpec::Core::Runner).to receive(:running_in_drb?).and_return(false) allow(RSpec::Core::Runner).to receive(:invoke) expect(RSpec::Core::Runner).to receive(:at_exit) RSpec::Core::Runner.autorun end it 'does not set the at_exit hook if it is already set' do Runner.instance_eval do @autorun_disabled = false @installed_at_exit = true end allow(RSpec::Core::Runner).to receive(:running_in_drb?).and_return(false) expect(RSpec::Core::Runner).to receive(:at_exit).never RSpec::Core::Runner.autorun end end describe "at_exit hook" do before { allow(Runner).to receive(:invoke) } it 'normally runs the spec suite' do Runner.perform_at_exit expect(Runner).to have_received(:invoke) end it 'does not run the suite if an error triggered the exit' do begin raise "boom" rescue Runner.perform_at_exit end expect(Runner).not_to have_received(:invoke) end it 'stil runs the suite if a `SystemExit` occurs since that is caused by `Kernel#exit`' do begin exit rescue SystemExit Runner.perform_at_exit end expect(Runner).to have_received(:invoke) end end describe "interrupt handling" do before { allow(Runner).to receive(:exit!) } it 'prints a message the first time, then exits the second time' do expect { Runner.handle_interrupt }.to output(/shutting down/).to_stderr_from_any_process & change { RSpec.world.wants_to_quit }.from(a_falsey_value).to(true) expect(Runner).not_to have_received(:exit!) expect { Runner.handle_interrupt }.not_to output.to_stderr_from_any_process expect(Runner).to have_received(:exit!) end end describe "interrupt catching" do let(:interrupt_handlers) { [] } before do allow(Runner).to receive(:trap).with("INT", any_args) do |&block| interrupt_handlers << block end end def interrupt interrupt_handlers.each(&:call) end it "adds a handler for SIGINT" do expect(interrupt_handlers).to be_empty Runner.send(:trap_interrupt) expect(interrupt_handlers.size).to eq(1) end context "with SIGINT once" do it "aborts processing" do Runner.send(:trap_interrupt) expect(Runner).to receive(:handle_interrupt) interrupt end it "does not exit immediately, but notifies the user" do Runner.send(:trap_interrupt) expect(Runner).not_to receive(:exit) expect(Runner).not_to receive(:exit!) expect { interrupt }.to output(/RSpec is shutting down/).to_stderr end end context "with SIGINT twice" do it "exits immediately" do Runner.send(:trap_interrupt) expect(Runner).to receive(:exit!).with(1) expect { interrupt }.to output(//).to_stderr interrupt end end end # This is intermittently slow because this method calls out to the network # interface. describe ".running_in_drb?", :slow do subject { RSpec::Core::Runner.running_in_drb? } before do allow(::DRb).to receive(:current_server) { drb_server } # To deal with some network weirdness at my workplace, I had to # configure my network adapter in a non-standard way that causes # `IPSocket.getaddress(Socket.gethostname)` to raise # `SocketError: getaddrinfo: nodename nor servname provided, or not known` # I'm not sure why this happens, but to keep the specs here passing, # I have to stub this out :(. allow(IPSocket).to receive(:getaddress) { "127.0.0.1" } end context "when drb server is started with 127.0.0.1" do let(:drb_server) do instance_double(::DRb::DRbServer, :uri => "druby://127.0.0.1:0000/", :alive? => true) end it { should be_truthy } end context "when drb server is started with localhost" do let(:drb_server) do instance_double(::DRb::DRbServer, :uri => "druby://localhost:0000/", :alive? => true) end it { should be_truthy } end context "when drb server is started with another local ip address" do let(:drb_server) do instance_double(::DRb::DRbServer, :uri => "druby://192.168.0.1:0000/", :alive? => true) end before do allow(::IPSocket).to receive(:getaddress).and_return("192.168.0.1") end it { should be_truthy } end context "when drb server is started with 127.0.0.1 but not alive" do let(:drb_server) do instance_double(::DRb::DRbServer, :uri => "druby://127.0.0.1:0000/", :alive? => false) end it { should be_falsey } end context "when IPSocket cannot resolve the current hostname" do let(:drb_server) do instance_double(::DRb::DRbServer, :uri => "druby://localhost:0000/", :alive? => true) end before do allow(::IPSocket).to receive(:getaddress).and_raise( SocketError, "getaddrinfo: nodename nor servname provided, or not known" ) end it { should be_falsey } end context "when no drb server is running" do let(:drb_server) do raise ::DRb::DRbServerNotFound end it { should be_falsey } end end describe '#exit_code' do let(:world) { World.new } let(:config) { Configuration.new } let(:runner) { Runner.new({}, config, world) } it 'defaults to 1' do expect(runner.exit_code).to eq 1 end it 'is failure_exit_code by default' do config.failure_exit_code = 2 expect(runner.exit_code).to eq 2 end it 'is failure_exit_code when world is errored by default' do world.non_example_failure = true config.failure_exit_code = 2 expect(runner.exit_code).to eq 2 end it 'is error_exit_code when world is errored by and both are defined' do world.non_example_failure = true config.failure_exit_code = 2 config.error_exit_code = 3 expect(runner.exit_code).to eq 3 end it 'is error_exit_code when world is errored by and failure exit code is not defined' do world.non_example_failure = true config.error_exit_code = 3 expect(runner.exit_code).to eq 3 end it 'can be given success' do config.error_exit_code = 3 expect(runner.exit_code(true)).to eq 0 end it 'can be given success, but non_example_failure=true will still cause an error code' do world.non_example_failure = true config.error_exit_code = 3 expect(runner.exit_code(true)).to eq 3 end end describe ".invoke" do let(:runner) { RSpec::Core::Runner } it "runs the specs via #run" do allow(runner).to receive(:exit) expect(runner).to receive(:run) runner.invoke end it "doesn't exit on success" do allow(runner).to receive(:run) { 0 } expect(runner).to_not receive(:exit) runner.invoke end it "exits with #run's status on failure" do allow(runner).to receive(:run) { 123 } expect(runner).to receive(:exit).with(123) runner.invoke end end describe ".run" do let(:args) { double(:args) } let(:err) { StringIO.new } let(:out) { StringIO.new } let(:options) { { } } let(:configuration_options) { double(:configuration_options, :options => options) } before(:each) do allow(RSpec::Core::ConfigurationOptions).to receive(:new).and_return(configuration_options) end context 'when the options contain a runner callable' do let(:runner) { double(:runner, :call => nil) } let(:options) { { :runner => runner } } it 'invokes the runner callable' do RSpec::Core::Runner.run([], err, out) expect(runner).to have_received(:call).with(configuration_options, err, out) end end context 'when no runner callable is set' do it 'instantiates a Runner instance and runs it' do process_proxy = double(RSpec::Core::Runner, :run => 0) allow(RSpec::Core::Runner).to receive(:new).and_return(process_proxy) RSpec::Core::Runner.run([], err, out) expect(RSpec::Core::Runner).to have_received(:new) expect(process_proxy).to have_received(:run).with(err, out) end end end context "when run" do include_context "Runner support" before do allow(config.hooks).to receive(:run) end it "configures streams before command line options" do allow(RSpec).to receive(:deprecate) # remove this and should_receive when ordered stdout = StringIO.new allow(config).to receive(:load_spec_files) allow(config).to receive(:reporter).and_return(double.as_null_object) config.output_stream = $stdout # this is necessary to ensure that color works correctly on windows expect(config).to receive(:error_stream=).ordered expect(config).to receive(:output_stream=).ordered expect(config).to receive(:force).at_least(:once).ordered runner = build_runner runner.setup err, stdout end it "assigns submitted ConfigurationOptions to @options" do config_options = ConfigurationOptions.new(%w[--color]) runner = Runner.new(config_options) expect(runner.instance_exec { @options }).to be(config_options) end describe "#run" do it 'supports a test-queue like subclass that can perform setup once and run different sets of example groups multiple times' do order = [] RSpec.describe("group 1") do before { order << :group_1 } example("passing") { expect(1).to eq(1) } end RSpec.describe("group 2") do before { order << :group_2 } example("failed") { expect(1).to eq(2) } end subclass = Class.new(Runner) do define_method :run_specs do |example_groups| set_1, set_2 = example_groups.partition { |g| g.description.include?('1') } order << :start_set_1 super(set_1) order << :start_set_2 super(set_2) end end expect(config).to receive(:load_spec_files).once subclass.new(ConfigurationOptions.new([]), config, world).run(err, out) expect(order).to eq([:start_set_1, :group_1, :start_set_2, :group_2]) end it 'reports the expected example count accurately, even when subclasses filter example groups' do RSpec.describe("group 1") do example("1") { } context "nested" do 4.times { example { } } end end RSpec.describe("group 2") do example("2") { } example("3") { } context "nested" do 4.times { example { } } end end subclass = Class.new(Runner) do define_method :run_specs do |example_groups| super(example_groups.select { |g| g.description == 'group 2' }) end end my_formatter = instance_double(Formatters::BaseFormatter).as_null_object config.output_stream = out config.deprecation_stream = err config.reporter.register_listener(my_formatter, :start) allow(config).to receive(:load_spec_files) subclass.new(ConfigurationOptions.new([]), config, world).run(err, out) expect(my_formatter).to have_received(:start) do |notification| expect(notification.count).to eq(6) end end describe "persistence of example statuses" do let(:all_examples) { [double("example")] } def run allow(world).to receive(:all_examples).and_return(all_examples) allow(config).to receive(:load_spec_files) class_spy(ExampleStatusPersister, :load_from => []).as_stubbed_const runner = build_runner runner.run(err, out) end context "when `example_status_persistence_file_path` is configured" do it 'persists the status of all loaded examples' do config.example_status_persistence_file_path = "examples.txt" run expect(ExampleStatusPersister).to have_received(:persist).with(all_examples, "examples.txt") end end context "with --dry-run" do it "doesn't persist example status" do config.example_status_persistence_file_path = "examples.txt" config.dry_run = true run expect(ExampleStatusPersister).not_to have_received(:persist) end end context "when `example_status_persistence_file_path` is not configured" do it "doesn't persist example status" do config.example_status_persistence_file_path = nil run expect(ExampleStatusPersister).not_to have_received(:persist) end end end context "running files" do include_context "spec files" it "returns 0 if spec passes" do runner = build_runner passing_spec_filename expect(runner.run(err, out)).to eq 0 end it "returns 1 if spec fails" do runner = build_runner failing_spec_filename expect(runner.run(err, out)).to eq 1 end it "returns 2 if spec fails and --failure-exit-code is 2" do runner = build_runner failing_spec_filename, "--failure-exit-code", "2" expect(runner.run(err, out)).to eq 2 end end end describe "#run with custom output" do before { allow(config).to receive_messages :files_to_run => [] } let(:output_file) { File.new("#{Dir.tmpdir}/runner_spec_output.txt", 'w') } it "doesn't override output_stream" do config.output_stream = output_file runner = build_runner runner.run err, nil expect(runner.instance_exec { @configuration.output_stream }).to eq output_file end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/project_initializer_spec.rb0000664000000000000000000000773314557677674027301 0ustar rootrootrequire 'rspec/core/project_initializer' module RSpec::Core RSpec.describe ProjectInitializer, :isolated_directory => true do describe "#run" do context "with no args" do subject(:command_line_config) { ProjectInitializer.new(:report_stream => output) } let(:output) { StringIO.new } context "with no .rspec file" do it "says it's creating .rspec " do expect{ command_line_config.run }.to change{ output.rewind output.read }.to(include 'create .rspec') end it "generates a .rspec" do command_line_config.run expect(File.read('.rspec')).to match(/--require spec_helper/m) end end context "with a .rspec file" do it "says .rspec exists" do FileUtils.touch('.rspec') expect{ command_line_config.run }.to change{ output.rewind output.read }.to(include 'exist .rspec') end it "doesn't create a new one" do File.open('.rspec', 'w') {|f| f << '--not-a-real-flag'} command_line_config.run expect(File.read('.rspec')).to eq('--not-a-real-flag') end end context "with no spec/spec_helper.rb file" do it "says it's creating spec/spec_helper.rb " do expect{ command_line_config.run }.to change{ output.rewind output.read }.to(include 'create spec/spec_helper.rb') end it "generates a spec/spec_helper.rb" do command_line_config.run expect(File.read('spec/spec_helper.rb')).to match(/RSpec\.configure do \|config\|/m) end end context "with a spec/spec_helper.rb file" do before { FileUtils.mkdir('spec') } it "says spec/spec_helper.rb exists" do FileUtils.touch('spec/spec_helper.rb') expect{ command_line_config.run }.to change{ output.rewind output.read }.to(include 'exist spec/spec_helper.rb') end it "doesn't create a new one" do random_content = "content #{rand}" File.open('spec/spec_helper.rb', 'w') {|f| f << random_content} command_line_config.run expect(File.read('spec/spec_helper.rb')).to eq(random_content) end end end end describe "#run", "with a target directory" do subject(:command_line_config) { ProjectInitializer.new(:destination => tmpdir, :report_stream => StringIO.new) } let(:tmpdir) { 'relative/destination/' } before { FileUtils.mkdir_p(tmpdir) } context "with no .rspec file" do it "generates a .rspec" do command_line_config.run expect(File.read(File.join(tmpdir, '.rspec'))).to match(/--require spec_helper/m) end end context "with a .rspec file" do it "doesn't create a new one" do dot_rspec_file = File.join(tmpdir, '.rspec') File.open(dot_rspec_file, 'w') {|f| f << '--not-a-real-flag'} command_line_config.run expect(File.read(dot_rspec_file)).to eq('--not-a-real-flag') end end context "with no spec/spec_helper.rb file" do it "generates a spec/spec_helper.rb" do command_line_config.run expect(File.read(File.join(tmpdir, 'spec/spec_helper.rb'))).to match(/RSpec\.configure do \|config\|/m) end end context "with a spec/spec_helper.rb file" do it "doesn't create a new one" do FileUtils.mkdir File.join(tmpdir, 'spec') spec_helper_file = File.join(tmpdir, 'spec', 'spec_helper.rb') random_content = "content #{rand}" File.open(spec_helper_file, 'w') {|f| f << random_content} command_line_config.run expect(File.read(spec_helper_file)).to eq(random_content) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/example_group_spec.rb0000664000000000000000000020347614557677674026101 0ustar rootroot# encoding: utf-8 module RSpec::Core RSpec.describe ExampleGroup do it_behaves_like "metadata hash builder" do def metadata_hash(*args) group = RSpec.describe('example description', *args) group.metadata end end %w[ expect double spy ].each do |method| context "when calling `#{method}`, an example API, on an example group" do it "tells the user they are in the wrong scope for that API" do expect { RSpec.describe { __send__(method, "foo") } }.to raise_error(ExampleGroup::WrongScopeError) end end end %w[ describe context let before it it_behaves_like ].each do |method| context "when calling `#{method}`, an example group API, from within an example" do it "tells the user they are in the wrong scope for that API" do ex = nil RSpec.describe do ex = example { __send__(method, "foo") } end.run expect(ex).to fail_with(ExampleGroup::WrongScopeError) end end end it "surfaces NameError from an example group for other missing APIs, like normal" do expect { RSpec.describe { foobar } }.to raise_error(NameError, /foobar/) end it "surfaces NameError from an example for other missing APIs, like normal" do ex = nil RSpec.describe do ex = example { foobar } end.run expect(ex).to fail_with(NameError) end context "when RSpec.configuration.format_docstrings is set to a block" do it "formats the description with that block" do RSpec.configuration.format_docstrings { |s| s.upcase } group = RSpec.describe(' an example ') expect(group.description).to eq(' AN EXAMPLE ') end end it 'does not treat the first argument as a metadata key even if it is a symbol' do group = RSpec.describe(:symbol) expect(group.metadata).not_to include(:symbol) end it 'treats the first argument as part of the description when it is a symbol' do group = RSpec.describe(:symbol) expect(group.description).to eq("symbol") end describe "constant naming" do around do |ex| before_constants = RSpec::ExampleGroups.constants ex.run after_constants = RSpec::ExampleGroups.constants (after_constants - before_constants).each do |name| RSpec::ExampleGroups.send(:remove_const, name) end end if RUBY_VERSION == "1.9.2" RSpec::Matchers.define :have_class_const do |class_name| match do |group| class_name.gsub!('::','_::') class_name << '_' group.name == "RSpec::ExampleGroups::#{class_name}" && group == class_name.split('::').inject(RSpec::ExampleGroups) do |mod, name| mod.const_get(name) end end end else RSpec::Matchers.define :have_class_const do |class_name, _| match do |group| group.name == "RSpec::ExampleGroups::#{class_name}" && group == class_name.split('::').inject(RSpec::ExampleGroups) do |mod, name| mod.const_get(name) end end end end it 'gives groups friendly human readable class names' do stub_const("MyGem::Klass", Class.new) parent = RSpec.describe(MyGem::Klass) expect(parent).to have_class_const("MyGemKlass") end it 'nests constants to match the group nesting' do grandparent = RSpec.describe("The grandparent") parent = grandparent.describe("the parent") child = parent.describe("the child") expect(parent).to have_class_const("TheGrandparent::TheParent") expect(child).to have_class_const("TheGrandparent::TheParent::TheChild") end it 'removes non-ascii characters from the const name since some rubies barf on that' do group = RSpec.describe("A chinese character: 们") expect(group).to have_class_const("AChineseCharacter") end it 'prefixes the const name with "Nested" if needed to make a valid const' do expect { ExampleGroup.const_set("1B", Object.new) }.to raise_error(NameError) group = RSpec.describe("1B") expect(group).to have_class_const("Nested1B") end it 'does not warn when defining a Config example group (since RbConfig triggers warnings when Config is referenced)' do expect { RSpec.describe("Config") }.not_to output.to_stderr end it 'ignores top level constants that have the same name' do parent = RSpec.describe("Some Parent Group") child = parent.describe("Hash") # This would be `SomeParentGroup::Hash_2` if we didn't ignore the top level `Hash` expect(child).to have_class_const("SomeParentGroup::Hash") end it 'disambiguates name collisions by appending a number', :unless => RUBY_VERSION == '1.9.2' do groups = 10.times.map { RSpec.describe("Collision") } expect(groups[0]).to have_class_const("Collision") expect(groups[1]).to have_class_const("Collision_2") expect(groups[8]).to have_class_const("Collision_9") if RUBY_VERSION.to_f > 1.8 && !(defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx') # on 1.8.7, rbx "Collision_9".next => "Collisioo_0" expect(groups[9]).to have_class_const("Collision_10") end end it 'identifies unnamed groups as "Anonymous"' do # Wrap the anonymous group is a uniquely named one, # so the presence of another anonymous group in our # test suite doesn't cause an unexpected number # to be appended. group = RSpec.describe("name of unnamed group") subgroup = group.describe expect(subgroup).to have_class_const("NameOfUnnamedGroup::Anonymous") end it 'assigns the const before evaling the group so error messages include the name' do expect { RSpec.describe("Calling an undefined method") { foo } }.to raise_error(/ExampleGroups::CallingAnUndefinedMethod/) end it "assigns the const before including shared contexts via metadata so error messages from eval'ing the context include the name" do RSpec.shared_context("foo", :foo) { bar } expect { RSpec.describe("Including shared context via metadata", :foo) }.to raise_error(NameError, a_string_including('ExampleGroups::IncludingSharedContextViaMetadata', 'bar') ) end it 'does not have problems with example groups named "Core"', :unless => RUBY_VERSION == '1.9.2' do RSpec.describe("Core") expect(defined?(::RSpec::ExampleGroups::Core)).to be # The original bug was triggered when a group was defined AFTER one named `Core`, # due to it not using the fully qualified `::RSpec::Core::ExampleGroup` constant. group = RSpec.describe("Another group") expect(group).to have_class_const("AnotherGroup") end it 'does not have problems with example groups named "RSpec"', :unless => RUBY_VERSION == '1.9.2' do RSpec.describe("RSpec") expect(defined?(::RSpec::ExampleGroups::RSpec)).to be # The original bug was triggered when a group was defined AFTER one named `RSpec`, # due to it not using the fully qualified `::RSpec::Core::ExampleGroup` constant. group = RSpec.describe("Yet Another group") expect(group).to have_class_const("YetAnotherGroup") end end describe "ordering" do context "when tagged with `:order => :defined`" do it 'orders the subgroups and examples in defined order regardless of global order' do RSpec.configuration.order = :random run_order = [] group = RSpec.describe "outer", :order => :defined do context "subgroup 1" do example { run_order << :g1_e1 } example { run_order << :g1_e2 } end context "subgroup 2" do example { run_order << :g2_e1 } example { run_order << :g2_e2 } end end group.run expect(run_order).to eq([:g1_e1, :g1_e2, :g2_e1, :g2_e2]) end end context "when tagged with an unrecognized ordering" do let(:run_order) { [] } let(:definition_line) { __LINE__ + 4 } let(:group) do order = self.run_order RSpec.describe "group", :order => :unrecognized do example { order << :ex_1 } example { order << :ex_2 } end end before do RSpec.configuration.register_ordering(:global, &:reverse) allow(self.group).to receive(:warn) end it 'falls back to the global ordering' do self.group.run expect(self.run_order).to eq([:ex_2, :ex_1]) end it 'prints a warning so users are notified of their mistake' do warning = nil allow(self.group).to receive(:warn) { |msg| warning = msg } self.group.run expect(warning).to match(/unrecognized/) expect(warning).to match(/#{File.basename __FILE__}:#{definition_line}/) end end context "when tagged with a custom ordering" do def ascending_numbers lambda { |g| Integer(g.description[/\d+/]) } end it 'uses the custom orderings' do RSpec.configure do |c| c.register_ordering :custom do |items| items.sort_by(&ascending_numbers) end end run_order = [] group = RSpec.describe "outer", :order => :custom do example("e2") { run_order << :e2 } example("e1") { run_order << :e1 } context "subgroup 2" do example("ex 3") { run_order << :g2_e3 } example("ex 1") { run_order << :g2_e1 } example("ex 2") { run_order << :g2_e2 } end context "subgroup 1" do example("ex 2") { run_order << :g1_e2 } example("ex 1") { run_order << :g1_e1 } example("ex 3") { run_order << :g1_e3 } end context "subgroup 3" do example("ex 2") { run_order << :g3_e2 } example("ex 3") { run_order << :g3_e3 } example("ex 1") { run_order << :g3_e1 } end end group.run expect(run_order).to eq([ :e1, :e2, :g1_e1, :g1_e2, :g1_e3, :g2_e1, :g2_e2, :g2_e3, :g3_e1, :g3_e2, :g3_e3 ]) end end end describe "top level group" do it "runs its children" do examples_run = [] group = RSpec.describe("parent") do describe("child") do it "does something" do |ex| examples_run << ex end end end group.run expect(examples_run.count).to eq(1) end context "with a failure in the top level group" do it "runs its children " do examples_run = [] group = RSpec.describe("parent") do it "fails" do |ex| examples_run << ex raise "fail" end describe("child") do it "does something" do |ex| examples_run << ex end end end group.run expect(examples_run.count).to eq(2) end end describe "descendants" do it "returns self + all descendants" do group = RSpec.describe("parent") do describe("child") do describe("grandchild 1") {} describe("grandchild 2") {} end end expect(group.descendants.size).to eq(4) end end end describe "child" do it "is known by parent" do parent = RSpec.describe child = parent.describe expect(parent.children).to eq([child]) end it "is not registered in world" do parent = RSpec.describe parent.describe expect(RSpec.world.example_groups).to eq([parent]) end end describe "filtering" do let(:world) { World.new } before { allow(RSpec).to receive_messages(:world => self.world) } shared_examples "matching filters" do context "inclusion" do before do filter_manager = FilterManager.new filter_manager.include filter_metadata allow(self.world).to receive_messages(:filter_manager => filter_manager) end it "includes examples in groups matching filter" do group = RSpec.describe("does something", spec_metadata) all_examples = [ group.example("first"), group.example("second") ] expect(group.filtered_examples).to eq(all_examples) end it "includes examples directly matching filter" do group = RSpec.describe("does something") filtered_examples = [ group.example("first", spec_metadata), group.example("second", spec_metadata) ] group.example("third (not-filtered)") expect(group.filtered_examples).to eq(filtered_examples) end end context "exclusion" do before do filter_manager = FilterManager.new filter_manager.exclude filter_metadata allow(self.world).to receive_messages(:filter_manager => filter_manager) end it "excludes examples in groups matching filter" do group = RSpec.describe("does something", spec_metadata) [ group.example("first"), group.example("second") ] expect(group.filtered_examples).to be_empty end it "excludes examples directly matching filter" do group = RSpec.describe("does something") [ group.example("first", spec_metadata), group.example("second", spec_metadata) ] unfiltered_example = group.example("third (not-filtered)") expect(group.filtered_examples).to eq([unfiltered_example]) end end end context "matching false" do let(:spec_metadata) { { :awesome => false }} context "against false" do let(:filter_metadata) { { :awesome => false }} include_examples "matching filters" end context "against 'false'" do let(:filter_metadata) { { :awesome => 'false' }} include_examples "matching filters" end context "against :false" do let(:filter_metadata) { { :awesome => :false }} include_examples "matching filters" end end context "matching true" do let(:spec_metadata) { { :awesome => true }} context "against true" do let(:filter_metadata) { { :awesome => true }} include_examples "matching filters" end context "against 'true'" do let(:filter_metadata) { { :awesome => 'true' }} include_examples "matching filters" end context "against :true" do let(:filter_metadata) { { :awesome => :true }} include_examples "matching filters" end end context "matching a string" do let(:spec_metadata) { { :type => 'special' }} context "against a string" do let(:filter_metadata) { { :type => 'special' }} include_examples "matching filters" end context "against a symbol" do let(:filter_metadata) { { :type => :special }} include_examples "matching filters" end end context "matching a symbol" do let(:spec_metadata) { { :type => :special }} context "against a string" do let(:filter_metadata) { { :type => 'special' }} include_examples "matching filters" end context "against a symbol" do let(:filter_metadata) { { :type => :special }} include_examples "matching filters" end end context "with no filters" do it "returns all" do group = RSpec.describe example = group.example("does something") expect(group.filtered_examples).to eq([example]) end end context "with no examples or groups that match filters" do it "returns none" do filter_manager = FilterManager.new filter_manager.include :awesome => false allow(self.world).to receive_messages(:filter_manager => filter_manager) group = RSpec.describe group.example("does something") expect(group.filtered_examples).to eq([]) end end end describe '#described_class' do context "with a constant as the first parameter" do it "is that constant" do expect(RSpec.describe(Object) { }.described_class).to eq(Object) end end context "with a string as the first parameter" do it "is nil" do expect(RSpec.describe("i'm a computer") { }.described_class).to be_nil end end context "with a constant in an outer group" do context "and a string in an inner group" do it "is the top level constant" do group = RSpec.describe(String) do describe "inner" do example "described_class is String" do expect(described_class).to eq(String) end end end expect(group.run).to be(true) end end context "and metadata redefinition after `described_class` call" do it "is the redefined level constant" do group = RSpec.describe(String) do described_class metadata[:described_class] = Object describe "inner" do example "described_class is Object" do expect(described_class).to eq(Object) end end end expect(group.run).to be(true) end end end context "in a nested group" do it "inherits the described class/module from the outer group" do group = RSpec.describe(String) do describe "nested" do example "describes is String" do expect(described_class).to eq(String) end end end expect(group.run).to be(true), "expected examples in group to pass" end context "when a class is passed" do def described_class_value value = nil RSpec.describe(String) do yield if block_given? describe Array do example { value = described_class } end end.run value end it "overrides the described class" do expect(described_class_value).to eq(Array) end it "overrides the described class even when described_class is referenced in the outer group" do expect(described_class_value { described_class }).to eq(Array) end end end context "for `describe(SomeClass)` within a `describe 'some string' group" do def define_and_run_group(define_outer_example = false) outer_described_class = inner_described_class = nil RSpec.describe("some string") do example { outer_described_class = described_class } if define_outer_example describe Array do example { inner_described_class = described_class } end end.run return outer_described_class, inner_described_class end it "has a `nil` described_class in the outer group" do outer_described_class, _ = define_and_run_group(:define_outer_example) expect(outer_described_class).to be(nil) end it "has the inner described class as the described_class of the inner group" do _, inner_described_class = define_and_run_group expect(inner_described_class).to be(Array) # This is weird, but in RSpec 2.12 (and before, presumably), # the `described_class` value would be incorrect if there was an # example in the outer group, and correct if there was not one. _, inner_described_class = define_and_run_group(:define_outer_example) expect(inner_described_class).to be(Array) end end end describe '#described_class' do it "is the same as described_class" do expect(self.class.described_class).to eq(self.class.described_class) end end describe '#description' do it "grabs the description from the metadata" do group = RSpec.describe(Object, "my desc") { } expect(group.description).to eq(group.metadata[:description]) end end describe '#metadata' do it "adds the third parameter to the metadata" do expect(RSpec.describe(Object, nil, 'foo' => 'bar') { }.metadata).to include({ "foo" => 'bar' }) end it "adds the the file_path to metadata" do expect(RSpec.describe(Object) { }.metadata[:file_path]).to eq(relative_path(__FILE__)) end it "has a reader for file_path" do expect(RSpec.describe(Object) { }.file_path).to eq(relative_path(__FILE__)) end it "adds the line_number to metadata" do expect(RSpec.describe(Object) { }.metadata[:line_number]).to eq(__LINE__) end end [:focus, :fexample, :fit, :fspecify].each do |example_alias| describe ".#{example_alias}" do let(:focused_example) { RSpec.describe.send example_alias, "a focused example" } it 'defines an example that can be filtered with :focus => true' do expect(focused_example.metadata[:focus]).to be(true) end end end describe "#before, after, and around hooks" do describe "scope aliasing" do it "aliases the `:context` hook scope to `:all` for before-hooks" do group = RSpec.describe order = [] group.before(:context) { order << :before_context } group.example("example") { order << :example } group.example("example") { order << :example } group.run expect(order).to eq([:before_context, :example, :example]) end it "aliases the `:example` hook scope to `:each` for before-hooks" do group = RSpec.describe order = [] group.before(:example) { order << :before_example } group.example("example") { order << :example } group.example("example") { order << :example } group.run expect(order).to eq([:before_example, :example, :before_example, :example]) end it "aliases the `:context` hook scope to `:all` for after-hooks" do group = RSpec.describe order = [] group.example("example") { order << :example } group.example("example") { order << :example } group.after(:context) { order << :after_context } group.run expect(order).to eq([:example, :example, :after_context]) end it "aliases the `:example` hook scope to `:each` for after-hooks" do group = RSpec.describe order = [] group.example("example") { order << :example } group.example("example") { order << :example } group.after(:example) { order << :after_example } group.run expect(order).to eq([:example, :after_example, :example, :after_example]) end describe "#currently_executing_a_context_hook?" do it "sets currently_executing_a_context_hook? to false initially" do group = RSpec.describe expect(group.currently_executing_a_context_hook?).to be false end it "sets currently_executing_a_context_hook? during before(:context) execution" do group = RSpec.describe hook_result = nil group.before(:context) { hook_result = group.currently_executing_a_context_hook? } group.example("") {} group.run expect(hook_result).to be true end it "does not set currently_executing_a_context_hook? outside of before(:context) execution" do group = RSpec.describe hook_result = nil group.before(:context) { hook_result = group.currently_executing_a_context_hook? } group.before(:each) { hook_result = group.currently_executing_a_context_hook? } group.example("") {} group.run expect(hook_result).to be false end it "sets currently_executing_a_context_hook? during after(:context) execution" do group = RSpec.describe hook_result = nil group.after(:context) { hook_result = group.currently_executing_a_context_hook? } group.example("") {} group.run expect(hook_result).to be true end it "unsets currently_executing_a_context_hook? after an after(:context) hook is done" do group = RSpec.describe group.after(:context) { } group.example("") {} group.run expect(group.currently_executing_a_context_hook?).to be false end end end it "runs the before alls in order" do group = RSpec.describe order = [] group.before(:all) { order << 1 } group.before(:all) { order << 2 } group.before(:all) { order << 3 } group.example("example") {} group.run expect(order).to eq([1,2,3]) end it "does not set RSpec.world.wants_to_quit in case of an error in before all (without fail_fast?)" do group = RSpec.describe group.before(:all) { raise "error in before all" } group.example("example") {} group.run expect(RSpec.world.wants_to_quit).to be(false) end it "runs the before eachs in order" do group = RSpec.describe order = [] group.before(:each) { order << 1 } group.before(:each) { order << 2 } group.before(:each) { order << 3 } group.example("example") {} group.run expect(order).to eq([1,2,3]) end it "runs the after eachs in reverse order" do group = RSpec.describe order = [] group.after(:each) { order << 1 } group.after(:each) { order << 2 } group.after(:each) { order << 3 } group.example("example") {} group.run expect(order).to eq([3,2,1]) end it "runs the after alls in reverse order" do group = RSpec.describe order = [] group.after(:all) { order << 1 } group.after(:all) { order << 2 } group.after(:all) { order << 3 } group.example("example") {} group.run expect(order).to eq([3,2,1]) end it "only runs before/after(:all) hooks from example groups that have specs that run" do hooks_run = [] RSpec.configure do |c| c.filter_run :focus => true end unfiltered_group = RSpec.describe "unfiltered" do before(:all) { hooks_run << :unfiltered_before_all } after(:all) { hooks_run << :unfiltered_after_all } context "a subcontext" do it("has an example") { } end end filtered_group = RSpec.describe "filtered", :focus => true do before(:all) { hooks_run << :filtered_before_all } after(:all) { hooks_run << :filtered_after_all } context "a subcontext" do it("has an example") { } end end unfiltered_group.run filtered_group.run expect(hooks_run).to eq([:filtered_before_all, :filtered_after_all]) end it "runs before_all_defined_in_config, before all, before each, example, after each, after all, after_all_defined_in_config in that order" do order = [] RSpec.configure do |c| c.before(:all) { order << :before_all_defined_in_config } c.after(:all) { order << :after_all_defined_in_config } end group = RSpec.describe group.before(:all) { order << :top_level_before_all } group.before(:each) { order << :before_each } group.after(:each) { order << :after_each } group.after(:all) { order << :top_level_after_all } group.example("top level example") { order << :top_level_example } context1 = group.describe("context 1") context1.before(:all) { order << :nested_before_all } context1.example("nested example 1") { order << :nested_example_1 } context2 = group.describe("context 2") context2.after(:all) { order << :nested_after_all } context2.example("nested example 2") { order << :nested_example_2 } group.run expect(order).to eq([ :before_all_defined_in_config, :top_level_before_all, :before_each, :top_level_example, :after_each, :nested_before_all, :before_each, :nested_example_1, :after_each, :before_each, :nested_example_2, :after_each, :nested_after_all, :top_level_after_all, :after_all_defined_in_config ]) end context "after(:all)" do let(:outer) { RSpec.describe } let(:inner) { outer.describe } it "has access to state defined before(:all)" do outer.before(:all) { @outer = "outer" } inner.before(:all) { @inner = "inner" } outer.after(:all) do expect(@outer).to eq("outer") expect(@inner).to eq("inner") end inner.after(:all) do expect(@inner).to eq("inner") expect(@outer).to eq("outer") end outer.run end it "cleans up ivars in after(:all)" do outer.before(:all) { @outer = "outer" } inner.before(:all) { @inner = "inner" } outer.run expect(inner.before_context_ivars[:@inner]).to be_nil expect(inner.before_context_ivars[:@outer]).to be_nil expect(outer.before_context_ivars[:@inner]).to be_nil expect(outer.before_context_ivars[:@outer]).to be_nil end end it "treats an error in before(:each) as a failure" do group = RSpec.describe group.before(:each) { raise "error in before each" } example = group.example("equality") { expect(1).to eq(2) } expect(group.run).to be(false) expect(example.execution_result.exception.message).to eq("error in before each") end it "treats an error in before(:all) as a failure" do group = RSpec.describe group.before(:all) { raise "error in before all" } example = group.example("equality") { expect(1).to eq(2) } expect(group.run).to be(false) expect(example.metadata).not_to be_nil expect(example.execution_result.exception).not_to be_nil expect(example.execution_result.exception.message).to eq("error in before all") end it "exposes instance variables set in before(:all) from after(:all) even if a before(:all) error occurs" do ivar_value_in_after_hook = nil group = RSpec.describe do before(:all) do @an_ivar = :set_in_before_all raise "fail" end after(:all) { ivar_value_in_after_hook = @an_ivar } it("has a spec") { } end group.run expect(ivar_value_in_after_hook).to eq(:set_in_before_all) end it "treats an error in before(:all) as a failure for a spec in a nested group" do example = nil group = RSpec.describe do before(:all) { raise "error in before all" } describe "nested" do example = it("equality") { expect(1).to eq(2) } end end group.run expect(example.metadata).not_to be_nil expect(example.execution_result.exception).not_to be_nil expect(example.execution_result.exception.message).to eq("error in before all") end context "when an error occurs in an after(:all) hook" do hooks_run = [] before(:each) do hooks_run = [] allow(RSpec.configuration.reporter).to receive(:message) end let(:group) do RSpec.describe do after(:all) { hooks_run << :one; raise "An error in an after(:all) hook" } after(:all) { hooks_run << :two; raise "A different hook raising an error" } it("equality") { expect(1).to eq(1) } end end it "allows the example to pass" do self.group.run example = self.group.examples.first expect(example.execution_result.status).to eq(:passed) end it "rescues any error(s) and prints them out" do expect(RSpec.configuration.reporter).to receive(:message).with(/An error in an after\(:all\) hook/) expect(RSpec.configuration.reporter).to receive(:message).with(/A different hook raising an error/) self.group.run end it "still runs both after blocks" do self.group.run expect(hooks_run).to eq [:two,:one] end it "sets `world.non_example_failure` so the exit status will be non-zero" do expect { self.group.run }.to change { RSpec.world.non_example_failure }.from(a_falsey_value).to(true) end end end describe ".pending" do let(:group) { RSpec.describe { pending { fail } } } it "generates a pending example" do self.group.run expect(self.group.examples.first).to be_pending end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq(RSpec::Core::Pending::NO_REASON_GIVEN) end it 'sets the backtrace to the example definition so it can be located by the user' do file = RSpec::Core::Metadata.relative_path(__FILE__) expected = [file, __LINE__ + 2].map(&:to_s) group = RSpec.describe do pending { } end group.run actual = group.examples.first.exception.backtrace.first.split(':')[0..1] expect(actual).to eq(expected) end it 'generates a pending example when no block is provided' do group = RSpec.describe "group" example = group.pending "just because" group.run expect(example).to be_pending end end describe "pending with metadata" do let(:group) { RSpec.describe { example("unimplemented", :pending => true) { fail } } } it "generates a pending example" do self.group.run expect(self.group.examples.first).to be_pending end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq(RSpec::Core::Pending::NO_REASON_GIVEN) end end describe "pending with message in metadata" do let(:group) { RSpec.describe { example("unimplemented", :pending => 'not done') { fail } } } it "generates a pending example" do self.group.run expect(self.group.examples.first).to be_pending end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq("not done") end end describe ".skip" do let(:group) { RSpec.describe { skip("skip this") { } } } it "generates a skipped example" do self.group.run expect(self.group.examples.first).to be_skipped end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq(RSpec::Core::Pending::NO_REASON_GIVEN) end end describe "skip with metadata" do let(:group) { RSpec.describe { example("skip this", :skip => true) { } } } it "generates a skipped example" do self.group.run expect(self.group.examples.first).to be_skipped end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq(RSpec::Core::Pending::NO_REASON_GIVEN) end end describe "skip with message in metadata" do let(:group) { RSpec.describe { example("skip this", :skip => 'not done') { } } } it "generates a skipped example" do self.group.run expect(self.group.examples.first).to be_skipped end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq('not done') end end %w[xit xspecify xexample].each do |method_name| describe ".#{method_name}" do let(:group) { RSpec.describe.tap {|x| x.send(method_name, "is pending") { } }} it "generates a skipped example" do self.group.run expect(self.group.examples.first).to be_skipped end it "sets the pending message" do self.group.run expect(self.group.examples.first.execution_result.pending_message).to eq("Temporarily skipped with #{method_name}") end end end %w[ xdescribe xcontext ].each do |method_name| describe ".#{method_name}" do def extract_execution_results(group) group.examples.map do |ex| ex.metadata.fetch(:execution_result) end end it 'generates a pending example group' do group = ExampleGroup.send(method_name, "group") do it("passes") { } it("fails") { expect(2).to eq(3) } end group.run expect(extract_execution_results(group).map(&:to_h)).to match([ a_hash_including( :status => :pending, :pending_message => "Temporarily skipped with #{method_name}" ) ] * 2) end end end %w[ fdescribe fcontext ].each do |method_name| describe ".#{method_name}" do def executed_examples_of(group) examples = group.examples.select { |ex| ex.execution_result.started_at } group.children.inject(examples) { |exs, child| exs + executed_examples_of(child) } end it "generates an example group that can be filtered with :focus" do RSpec.configuration.filter_run :focus parent_group = RSpec.describe do describe "not focused" do example("not focused example") { } end send(method_name, "focused") do example("focused example") { } end end parent_group.run executed_descriptions = executed_examples_of(parent_group).map(&:description) expect(executed_descriptions).to eq(["focused example"]) end end end describe "setting pending metadata in parent" do def extract_execution_results(group) group.examples.map do |ex| ex.metadata.fetch(:execution_result) end end it 'marks every example as pending' do group = RSpec.describe("group", :pending => true) do it("passes") { } it("fails", :pending => 'unimplemented') { fail } end group.run expect(extract_execution_results(group).map(&:to_h)).to match([ a_hash_including( :status => :failed, :pending_message => "No reason given" ), a_hash_including( :status => :pending, :pending_message => "unimplemented" ) ]) end end describe "adding examples" do it "allows adding an example using 'it'" do group = RSpec.describe group.it("should do something") { } expect(group.examples.size).to eq(1) end it "exposes all examples at examples" do group = RSpec.describe group.it("should do something 1") { } group.it("should do something 2") { } group.it("should do something 3") { } expect(group.examples.count).to eq(3) end it "maintains the example order" do group = RSpec.describe group.it("should 1") { } group.it("should 2") { } group.it("should 3") { } expect(group.examples[0].description).to eq('should 1') expect(group.examples[1].description).to eq('should 2') expect(group.examples[2].description).to eq('should 3') end end describe Object, "describing nested example_groups", :little_less_nested => 'yep' do describe "A sample nested group", :nested_describe => "yep" do it "sets the described class to the nearest described class" do |ex| expect(ex.example_group.described_class).to eq(Object) end it "sets the description to 'A sample nested describe'" do |ex| expect(ex.example_group.description).to eq('A sample nested group') end it "has top level metadata from the example_group and its parent groups" do |ex| expect(ex.example_group.metadata).to include(:little_less_nested => 'yep', :nested_describe => 'yep') end it "exposes the parent metadata to the contained examples" do |ex| expect(ex.metadata).to include(:little_less_nested => 'yep', :nested_describe => 'yep') end end end describe "#run_examples" do let(:reporter) { RSpec::Core::NullReporter } it "returns true if all examples pass" do group = RSpec.describe('group') do example('ex 1') { expect(1).to eq(1) } example('ex 2') { expect(1).to eq(1) } end allow(group).to receive(:filtered_examples) { group.examples } expect(group.run(reporter)).to be(true) end it "returns false if any of the examples fail" do group = RSpec.describe('group') do example('ex 1') { expect(1).to eq(1) } example('ex 2') { expect(1).to eq(2) } end allow(group).to receive(:filtered_examples) { group.examples } expect(group.run(reporter)).to be(false) end it "runs all examples, regardless of any of them failing" do group = RSpec.describe('group') do example('ex 1') { expect(1).to eq(2) } example('ex 2') { expect(1).to eq(1) } end allow(group).to receive(:filtered_examples) { group.examples } group.filtered_examples.each do |example| expect(example).to receive(:run) end expect(group.run(reporter)).to be(false) end end describe "how instance variables are inherited" do before(:all) do @before_all_top_level = 'before_all_top_level' end before(:each) do @before_each_top_level = 'before_each_top_level' end it "can access a before each ivar at the same level" do expect(@before_each_top_level).to eq('before_each_top_level') end it "can access a before all ivar at the same level" do expect(@before_all_top_level).to eq('before_all_top_level') end it "can access the before all ivars in the before_all_ivars hash", :ruby => 1.8 do |ex| expect(ex.example_group.before_context_ivars).to include('@before_all_top_level' => 'before_all_top_level') end it "can access the before all ivars in the before_all_ivars hash", :ruby => 1.9 do |ex| expect(ex.example_group.before_context_ivars).to include(:@before_all_top_level => 'before_all_top_level') end describe "but now I am nested" do it "can access a parent example groups before each ivar at a nested level" do expect(@before_each_top_level).to eq('before_each_top_level') end it "can access a parent example groups before all ivar at a nested level" do expect(@before_all_top_level).to eq("before_all_top_level") end it "changes to before all ivars from within an example do not persist outside the current describe" do @before_all_top_level = "ive been changed" end describe "accessing a before_all ivar that was changed in a parent example_group" do it "does not have access to the modified version" do expect(@before_all_top_level).to eq('before_all_top_level') end end end end describe "ivars are not shared across examples" do it "(first example)" do @a = 1 expect(defined?(@b)).to be(nil) end it "(second example)" do @b = 2 expect(defined?(@a)).to be(nil) end end describe "#top_level_description" do it "returns the description from the outermost example group" do group = nil RSpec.describe("top") do context "middle" do group = describe "bottom" do end end end expect(group.top_level_description).to eq("top") end end describe "#run" do context "with `fail_fast` set to `nil`" do before { RSpec.configuration.fail_fast = nil } let(:group) { RSpec.describe } let(:reporter) { Reporter.new(RSpec.configuration) } it "does not run abort due to failures" do examples_run = [] group().example('example 1') { examples_run << self; fail } group().example('example 2') { examples_run << self; fail } group().example('example 3') { examples_run << self; fail } group().run(reporter) expect(examples_run.length).to eq(3) end end context "with fail_fast enabled" do before { RSpec.configuration.fail_fast = true } let(:group) { RSpec.describe } let(:reporter) { Reporter.new(RSpec.configuration) } it "does not run examples after the failed example" do examples_run = [] group().example('example 1') { examples_run << self } group().example('example 2') { examples_run << self; fail; } group().example('example 3') { examples_run << self } group().run(reporter) expect(examples_run.length).to eq(2) end it "sets RSpec.world.wants_to_quit flag if encountering an exception in before(:all)" do group().before(:all) { raise "error in before all" } group().example("equality") { expect(1).to eq(2) } expect(group().run(reporter)).to be(false) expect(RSpec.world.wants_to_quit).to be(true) end end context "with fail_fast set to 3" do before { RSpec.configuration.fail_fast = 3 } let(:group) { RSpec.describe } let(:reporter) { Reporter.new(RSpec.configuration) } it "does not run examples after 3 failed examples" do examples_run = [] group().example('example 1') { examples_run << self } group().example('example 2') { examples_run << self; fail; } group().example('example 3') { examples_run << self; fail; } group().example('example 4') { examples_run << self; fail; } group().example('example 5') { examples_run << self } group().run(reporter) expect(examples_run.length).to eq(4) end it "does not set RSpec.world.wants_to_quit flag if encountering an exception in before(:all) causing less than 3 failures" do group().before(:all) { raise "error in before all" } group().example("equality") { expect(1).to eq(2) } group().example("equality") { expect(1).to eq(2) } expect(group().run(reporter)).to be false expect(RSpec.world.wants_to_quit).to be(false) end it "sets RSpec.world.wants_to_quit flag if encountering an exception in before(:all) causing at least 3 failures" do group().before(:all) { raise "error in before all" } group().example("equality") { expect(1).to eq(1) } group().example("equality") { expect(1).to eq(1) } group().example("equality") { expect(1).to eq(1) } expect(group().run(reporter)).to be false expect(RSpec.world.wants_to_quit).to be true end end let(:reporter) { double("reporter").as_null_object } context "with RSpec.world.wants_to_quit=true" do let(:group) { RSpec.describe } before do RSpec.world.wants_to_quit = true end it "returns without starting the group" do expect(reporter).not_to receive(:example_group_started) group().run(reporter) end end context "with all examples passing" do it "returns true" do group = RSpec.describe("something") do it "does something" do # pass end describe "nested" do it "does something else" do # pass end end end expect(group.run(reporter)).to be(true) end end context "with top level example failing" do it "returns false" do group = RSpec.describe("something") do it "does something (wrong - fail)" do raise "fail" end describe "nested" do it "does something else" do # pass end end end expect(group.run(reporter)).to be(false) end end context "with nested example failing" do it "returns true" do group = RSpec.describe("something") do it "does something" do # pass end describe "nested" do it "does something else (wrong -fail)" do raise "fail" end end end expect(group.run(reporter)).to be(false) end end end describe "#update_inherited_metadata" do it "updates the group metadata with the provided hash" do group = RSpec.describe expect(group.metadata).not_to include(:foo => 1, :bar => 2) group.update_inherited_metadata(:foo => 1, :bar => 2) expect(group.metadata).to include(:foo => 1, :bar => 2) end it "does not overwrite existing metadata originating from that level" do group = RSpec.describe("group", :foo => 1) expect { group.update_inherited_metadata(:foo => 2) }.not_to change { group.metadata[:foo] }.from(1) end it "overwrites metadata originating from a parent" do group = nil RSpec.describe("group", :foo => 1) do group = context do end end expect { group.update_inherited_metadata(:foo => 2) }.to change { group.metadata[:foo] }.from(1).to(2) end it "does not replace the existing metadata object with a new one or change its default proc" do group = RSpec.describe expect { group.update_inherited_metadata(:foo => 1) }.to avoid_changing { group.metadata.__id__ }.and avoid_changing { group.metadata.default_proc } end it "propogates metadata updates to previously declared child examples" do group = RSpec.describe example = group.example expect { group.update_inherited_metadata(:foo => 1) }.to change { example.metadata[:foo] }.from(nil).to(1) end it "propogates metadata updates to previously declared child group" do group = RSpec.describe child_group = group.describe expect { group.update_inherited_metadata(:foo => 1) }.to change { child_group.metadata[:foo] }.from(nil).to(1) end it "applies new metadata-based config items based on the update" do extension = Module.new do def extension_method; 17; end end sequence = [] extension_checks = [] RSpec.configure do |c| c.before(:example, :foo => true) { sequence << :global_before_hook } c.after(:example, :foo => true) { sequence << :global_after_hook } c.extend extension, :foo => true end describe_successfully do example { sequence << :example_1 } extension_checks << begin self.extension_method rescue NoMethodError :method_not_defined end context "nested group before update" do example { sequence << :nested_example } end update_inherited_metadata(:foo => true) extension_checks << begin self.extension_method rescue NoMethodError :method_not_defined end example { sequence << :example_2 } end expect(sequence).to eq [ :global_before_hook, :example_1, :global_after_hook, :global_before_hook, :example_2, :global_after_hook, :global_before_hook, :nested_example, :global_after_hook, ] expect(extension_checks).to eq [:method_not_defined, 17] end it "does not cause duplicate hooks to be added when re-configuring the group" do sequence = [] RSpec.configure do |c| c.before(:example, :foo => true) { sequence << :global_before_hook } c.after(:example, :foo => true) { sequence << :global_after_hook } end describe_successfully("Group", :foo => true) do example { sequence << :example_1 } update_inherited_metadata(:bar => true) example { sequence << :example_2 } end expect(sequence).to eq [ :global_before_hook, :example_1, :global_after_hook, :global_before_hook, :example_2, :global_after_hook, ] end end %w[include_examples include_context].each do |name| describe "##{name}" do let(:group) { RSpec.describe } before do self.group.shared_examples "named this" do example("does something") {} end end it "includes the named examples" do self.group.send(name, "named this") expect(self.group.examples.first.description).to eq("does something") end it "raises a helpful error message when shared content is not found" do expect do self.group.send(name, "shared stuff") end.to raise_error(ArgumentError, /Could not find .* "shared stuff"/) end it "raises a helpful error message when shared content is accessed recursively" do self.group.shared_examples "named otherwise" do example("does something") {} self.send(name, "named otherwise") end expect do self.group.send(name, "named otherwise") end.to raise_error(ArgumentError, /can't include shared examples recursively/) end it "leaves RSpec's thread metadata unchanged" do expect { self.group.send(name, "named this") }.to avoid_changing(RSpec::Support, :thread_local_data) end it "leaves RSpec's thread metadata unchanged, even when an error occurs during evaluation" do expect { self.group.send(name, "named this") do raise "boom" end }.to raise_error("boom").and avoid_changing(RSpec::Support, :thread_local_data) end it "passes parameters to the shared content" do passed_params = {} group = RSpec.describe group.shared_examples "named this with params" do |param1, param2| it("has access to the given parameters") do passed_params[:param1] = param1 passed_params[:param2] = param2 end end group.send(name, "named this with params", :value1, :value2) group.run expect(passed_params).to eq({ :param1 => :value1, :param2 => :value2 }) end it "adds shared instance methods to the group" do group = RSpec.describe('fake group') group.shared_examples "named this with params" do |param1| def foo; end end group.send(name, "named this with params", :a) expect(group.public_instance_methods.map{|m| m.to_s}).to include("foo") end it "evals the shared example group only once" do eval_count = 0 group = RSpec.describe('fake group') group.shared_examples("named this with params") { |p| eval_count += 1 } group.send(name, "named this with params", :a) expect(eval_count).to eq(1) end it "evals the block when given" do key = "#{__FILE__}:#{__LINE__}" group = RSpec.describe do shared_examples(key) do it("does something") do expect(foo).to eq("bar") end end send name, key do def foo; "bar"; end end end expect(group.run).to be(true) end end end describe "#it_should_behave_like" do it "creates a nested group" do group = RSpec.describe('fake group') group.shared_examples_for("thing") {} group.it_should_behave_like("thing") expect(group.children.count).to eq(1) end it "creates a nested group for a class" do klass = Class.new group = RSpec.describe('fake group') group.shared_examples_for(klass) {} group.it_should_behave_like(klass) expect(group.children.count).to eq(1) end it "adds shared examples to nested group" do group = RSpec.describe('fake group') group.shared_examples_for("thing") do it("does something") end shared_group = group.it_should_behave_like("thing") expect(shared_group.examples.count).to eq(1) end it "adds shared instance methods to nested group" do group = RSpec.describe('fake group') group.shared_examples_for("thing") do def foo; end end shared_group = group.it_should_behave_like("thing") expect(shared_group.public_instance_methods.map{|m| m.to_s}).to include("foo") end it "adds shared class methods to nested group" do group = RSpec.describe('fake group') group.shared_examples_for("thing") do def self.foo; end end shared_group = group.it_should_behave_like("thing") expect(shared_group.methods.map{|m| m.to_s}).to include("foo") end it "passes parameters to the shared example group" do passed_params = {} group = RSpec.describe("group") do shared_examples_for("thing") do |param1, param2| it("has access to the given parameters") do passed_params[:param1] = param1 passed_params[:param2] = param2 end end it_should_behave_like "thing", :value1, :value2 end group.run expect(passed_params).to eq({ :param1 => :value1, :param2 => :value2 }) end it "adds shared instance methods to nested group" do group = RSpec.describe('fake group') group.shared_examples_for("thing") do |param1| def foo; end end shared_group = group.it_should_behave_like("thing", :a) expect(shared_group.public_instance_methods.map{|m| m.to_s}).to include("foo") end it "evals the shared example group only once" do eval_count = 0 group = RSpec.describe('fake group') group.shared_examples_for("thing") { |p| eval_count += 1 } group.it_should_behave_like("thing", :a) expect(eval_count).to eq(1) end context "given a block" do it "evaluates the block in nested group" do scopes = [] group = RSpec.describe("group") do shared_examples_for("thing") do it("gets run in the nested group") do scopes << self.class end end it_should_behave_like "thing" do it("gets run in the same nested group") do scopes << self.class end end end group.run expect(scopes[0]).to be(scopes[1]) end end it "raises a helpful error message when shared context is not found" do expect do RSpec.describe do it_should_behave_like "shared stuff" end end.to raise_error(ArgumentError,%q|Could not find shared examples "shared stuff"|) end it "leaves RSpec's thread metadata unchanged" do expect { RSpec.describe do shared_examples_for("stuff") { } it_should_behave_like "stuff" end }.to avoid_changing(RSpec::Support, :thread_local_data) end it "leaves RSpec's thread metadata unchanged, even when an error occurs during evaluation" do expect { RSpec.describe do shared_examples_for("stuff") { } it_should_behave_like "stuff" do raise "boom" end end }.to raise_error("boom").and avoid_changing(RSpec::Support, :thread_local_data) end end it 'minimizes the number of methods that users could inadvertantly overwrite' do rspec_core_methods = ExampleGroup.instance_methods - RSpec::Matchers.instance_methods - RSpec::Mocks::ExampleMethods.instance_methods - Object.instance_methods - ["singleton_class"] # Feel free to expand this list if you intend to add another public API # for users. RSpec internals should not add methods here, though. expect(rspec_core_methods.map(&:to_sym)).to contain_exactly( :described_class, :subject, :is_expected, :should, :should_not, :pending, :skip, :setup_mocks_for_rspec, :teardown_mocks_for_rspec, :verify_mocks_for_rspec ) end it 'prevents defining nested isolated contexts' do expect { RSpec.describe do describe {} RSpec.describe {} end }.to raise_error(/not allowed/) end it 'prevents defining nested isolated shared contexts' do expect { RSpec.describe do ExampleGroup.shared_examples("common functionality") {} end }.to raise_error(/not allowed/) end describe 'inspect output', :unless => RUBY_VERSION == '1.9.2' do context 'when there is no inspect output provided' do it "uses '(no description provided)' instead" do expect(ExampleGroup.new.inspect).to eq('#') end end context 'when an example has a description' do it 'includes description and location' do an_example = nil line = __LINE__ + 2 group = RSpec.describe 'SomeClass1' do example 'an example' do an_example = self end end group.run path = RSpec::Core::Metadata.relative_path(__FILE__) expect(an_example.inspect).to eq("#") end end context 'when an example does not have a description' do it 'includes fallback description' do an_example = nil line = __LINE__ + 2 group = RSpec.describe 'SomeClass2' do example do an_example = self end end group.run path = RSpec::Core::Metadata.relative_path(__FILE__) expect(an_example.inspect).to eq("#") end end it 'handles before context hooks' do a_before_hook = nil group = RSpec.describe 'SomeClass3' do before(:context) do a_before_hook = self end example {} end group.run expect(a_before_hook.inspect).to eq("#") end it 'handles after context hooks' do an_after_hook = nil group = RSpec.describe 'SomeClass4' do after(:context) do an_after_hook = self end example {} end group.run expect(an_after_hook.inspect).to eq("#") end it "does not pollute an example's `inspect` output with the inspect ivar from `before(:context)`" do inspect_output = nil line = __LINE__ + 2 group = RSpec.describe do example do inspect_output = inspect end before(:context) {} end group.run path = RSpec::Core::Metadata.relative_path(__FILE__) expect(inspect_output).to end_with("\"example at #{path}:#{line}\">") end end def group_ids group ids = [] ['descendant_filtered_examples', 'descendants', 'parent_groups', 'declaration_locations', 'before_context_ivars'].each do |method| ids << group.send(method).object_id end ids end it 'allows adding examples' do group = RSpec.describe('group') do example('ex 1') { expect(1).to eq(1) } end # ids should remain the same until we add/remove an example original_ids = group_ids group expect(original_ids).to eq(group_ids(group)) group.add_example group.examples.first expect(group.examples.length).to eq(2) expect(original_ids).to_not eq(group_ids(group)) end it 'allows removing examples' do group = RSpec.describe('group') do example('ex 1') { expect(1).to eq(1) } end group.add_example group.examples.first # ids should remain the same until we add/remove an example original_ids = group_ids group expect(original_ids).to eq(group_ids(group)) group.remove_example group.examples.first expect(group.examples.length).to eq(0) expect(original_ids).to_not eq(group_ids(group)) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/example_execution_result_spec.rb0000664000000000000000000001230214557677674030330 0ustar rootrootmodule RSpec module Core class Example RSpec.describe ExecutionResult do it "supports ruby 2.1's `to_h` protocol" do er = ExecutionResult.new er.run_time = 17 er.pending_message = "just because" expect(er.to_h).to include( :run_time => 17, :pending_message => "just because" ) end it 'includes all defined attributes in the `to_h` hash even if not set' do expect(ExecutionResult.new.to_h).to include( :status => nil, :pending_message => nil ) end it 'provides a `pending_fixed?` predicate' do er = ExecutionResult.new expect { er.pending_fixed = true }.to change(er, :pending_fixed?).from(false).to(true) end describe "backwards compatibility" do it 'supports indexed access like a hash' do er = ExecutionResult.new er.started_at = (started_at = ::Time.utc(2014, 3, 1, 12, 30)) expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /execution_result/) expect(er[:started_at]).to eq(started_at) end it 'supports indexed updates like a hash' do er = ExecutionResult.new expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /execution_result/) er[:started_at] = (started_at = ::Time.utc(2014, 3, 1, 12, 30)) expect(er.started_at).to eq(started_at) end it 'can get and set user defined attributes like with a hash' do er = ExecutionResult.new allow_deprecation expect { er[:foo] = 3 }.to change { er[:foo] }.from(nil).to(3) expect(er.to_h).to include(:foo => 3) end it 'supports `update` like a hash' do er = ExecutionResult.new expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /execution_result/) er.update(:pending_message => "some message", :exception => ArgumentError.new) expect(er.pending_message).to eq("some message") expect(er.exception).to be_a(ArgumentError) end it 'can set undefined attribute keys through any hash mutation method' do allow_deprecation er = ExecutionResult.new er.update(:pending_message => "msg", :foo => 3) expect(er.to_h).to include(:pending_message => "msg", :foo => 3) end it 'supports `merge` like a hash' do er = ExecutionResult.new er.exception = ArgumentError.new er.pending_message = "just because" expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /execution_result/) merged = er.merge(:exception => NotImplementedError.new, :foo => 3) expect(merged).to include( :exception => an_instance_of(NotImplementedError), :pending_message => "just because", :foo => 3 ) expect(er.exception).to be_an(ArgumentError) end it 'supports blocks for hash methods that support one' do er = ExecutionResult.new expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /execution_result/) expect(er.fetch(:foo) { 3 }).to eq(3) end # It's IndexError on 1.8.7, KeyError on 1.9+ fetch_not_found_error_class = defined?(::KeyError) ? ::KeyError : ::IndexError specify '#fetch treats unset properties the same as a hash does' do allow_deprecation er = ExecutionResult.new expect { er.fetch(:pending_message) }.to raise_error(fetch_not_found_error_class) er.pending_message = "some msg" expect(er.fetch(:pending_message)).to eq("some msg") end describe "status" do it 'returns a string when accessed like a hash' do er = ExecutionResult.new expect(er[:status]).to eq(nil) er.status = :failed expect(er[:status]).to eq("failed") end it "sets the status to a symbol when assigned as a string via the hash interface" do er = ExecutionResult.new er[:status] = "failed" expect(er.status).to eq(:failed) er[:status] = nil expect(er.status).to eq(nil) end it "is presented as a string when included in returned hashes" do er = ExecutionResult.new er.status = :failed expect(er.merge(:foo => 3)).to include(:status => "failed", :foo => 3) er.status = nil expect(er.merge(:foo => 3)).to include(:status => nil, :foo => 3) end it "is updated to a symbol when updated as a string via `update`" do er = ExecutionResult.new er.update(:status => "passed") expect(er.status).to eq(:passed) end it 'is presented as a symbol in `to_h`' do er = ExecutionResult.new er.status = :failed expect(er.to_h).to include(:status => :failed) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/filter_manager_spec.rb0000664000000000000000000004314114557677674026200 0ustar rootrootmodule RSpec::Core RSpec.describe FilterManager do def opposite(name) name =~ /^in/ ? name.sub(/^(in)/,'ex') : name.sub(/^(ex)/,'in') end subject(:filter_manager) { FilterManager.new } let(:inclusions) { filter_manager.inclusions } let(:exclusions) { filter_manager.exclusions } def prune(examples) # We want to enforce that our FilterManager, like a good citizen, # leaves the input array unmodified. There are a lot of code paths # through the filter manager, so rather than write one # `it 'does not mutate the input'` example that would not cover # all code paths, we're freezing the input here in order to # enforce that for ALL examples in this file that call `prune`, # the input array is not mutated. filter_manager.prune(examples.freeze) end %w[include inclusions exclude exclusions].each_slice(2) do |name, type| describe "##{name}" do subject(:rules) { send(type).rules } let(:opposite_rules) { send(opposite(type)).rules } it "merges #{type}" do filter_manager.send name, :foo => :bar filter_manager.send name, :baz => :bam expect(rules).to eq(:foo => :bar, :baz => :bam) end it "overrides previous #{type} with (via merge)" do filter_manager.send name, :foo => 1 filter_manager.send name, :foo => 2 expect(rules).to eq(:foo => 2) end it "deletes matching opposites" do filter_manager.exclusions.clear # defaults filter_manager.send opposite(name), :foo => 1 filter_manager.send name, :foo => 2 expect(rules).to eq(:foo => 2) expect(opposite_rules).to be_empty end if name == "include" context "with :full_description" do it "clears previous inclusions" do filter_manager.include :foo => :bar filter_manager.include :full_description => "value" expect(rules).to eq(:full_description => "value") end it "clears previous exclusion" do filter_manager.include :foo => :bar filter_manager.include :full_description => "value" expect(opposite_rules).to be_empty end it "does nothing when :full_description previously set" do filter_manager.include :full_description => "a_value" filter_manager.include :foo => :bar expect(rules).to eq(:full_description => "a_value") end end end end describe "##{name}_only" do subject(:rules) { send(type).rules } let(:opposite_rules) { send(opposite(type)).rules } it "replaces existing #{type}" do filter_manager.send name, :foo => 1, :bar => 2 filter_manager.send "#{name}_only", :foo => 3 expect(rules).to eq(:foo => 3) end it "deletes matching opposites" do filter_manager.send opposite(name), :foo => 1 filter_manager.send "#{name}_only", :foo => 2 expect(rules).to eq(:foo => 2) expect(opposite_rules).to be_empty end end describe "##{name}_with_low_priority" do subject(:rules) { send(type).rules } let(:opposite_rules) { send(opposite(type)).rules } it "ignores new #{type} if same key exists" do filter_manager.send name, :foo => 1 filter_manager.send "#{name}_with_low_priority", :foo => 2 expect(rules).to eq(:foo => 1) end it "ignores new #{type} if same key exists in opposite" do filter_manager.send opposite(name), :foo => 1 filter_manager.send "#{name}_with_low_priority", :foo => 1 expect(rules).to be_empty expect(opposite_rules).to eq(:foo => 1) end it "keeps new #{type} if same key exists in opposite but values are different" do filter_manager.send opposite(name), :foo => 1 filter_manager.send "#{name}_with_low_priority", :foo => 2 expect(rules).to eq(:foo => 2) expect(opposite_rules).to eq(:foo => 1) end end end describe "#prune" do def example_with(*args) RSpec.describe("group", *args).example("example") end shared_examples_for "example identification filter preference" do |type| it "prefers #{type} filter to exclusion filter" do group = RSpec.describe("group") included = group.example("include", :slow => true) {}; line = __LINE__ excluded = group.example("exclude") {} add_filter(:line_number => line, :scoped_id => "1:1") filter_manager.exclude_with_low_priority :slow => true expect(prune([included, excluded])).to eq([included]) end it "prefers #{type} on entire group to exclusion filter on a nested example" do # We way want to change this behaviour in future, see: # https://github.com/rspec/rspec-core/issues/779 group = RSpec.describe("group"); line = __LINE__ included = group.example("include", :slow => true) excluded = RSpec.describe.example add_filter(:line_number => line, :scoped_id => "1") filter_manager.exclude_with_low_priority :slow => true expect(prune([included, excluded])).to eq([included]) end it "still applies inclusion filters to examples from files with no #{type} filters" do group = RSpec.describe("group") included_via_loc_or_id = group.example("inc via #{type}"); line = __LINE__ excluded_via_loc_or_id = group.example("exc via #{type}", :foo) included_via_tag, excluded_via_tag = instance_eval <<-EOS, "some/other_spec.rb", 1 group = RSpec.describe("group") [group.example("inc via tag", :foo), group.example("exc via tag")] EOS add_filter(:line_number => line, :scoped_id => "1:1") filter_manager.include_with_low_priority :foo => true expect(prune([ included_via_loc_or_id, excluded_via_loc_or_id, included_via_tag, excluded_via_tag ]).map(&:description)).to eq([included_via_loc_or_id, included_via_tag].map(&:description)) end it "skips examples in external files when included from a #{type} filtered file" do group = RSpec.describe("group") included_via_loc_or_id = group.example("inc via #{type}"); line = __LINE__ # instantiate shared example in external file instance_eval <<-EOS, "a_shared_example.rb", 1 RSpec.shared_examples_for("a shared example") do example("inside of a shared example") end EOS included_via_behaves_like = group.it_behaves_like("a shared example") test_inside_a_shared_example = included_via_behaves_like.examples.first add_filter(:line_number => line, :scoped_id => "1:1") expect(prune([ included_via_loc_or_id, test_inside_a_shared_example ]).map(&:description)).to eq([included_via_loc_or_id].map(&:description)) end end describe "location filtering" do include_examples "example identification filter preference", :location do def add_filter(options) filter_manager.add_location(__FILE__, [options.fetch(:line_number)]) end end end describe "id filtering" do include_examples "example identification filter preference", :id do def add_filter(options) filter_manager.add_ids(__FILE__, [options.fetch(:scoped_id)]) end end end context "with a location and an id filter" do it 'takes the set union of matched examples' do group = RSpec.describe("group") matches_id = group.example matches_line_number = group.example; line_1 = __LINE__ matches_both = group.example; line_2 = __LINE__ matches_neither = group.example filter_manager.add_ids(__FILE__, ["1:1", "1:3"]) filter_manager.add_location(__FILE__, [line_1, line_2]) expect(prune([ matches_id, matches_line_number, matches_both, matches_neither ])).to eq([matches_id, matches_line_number, matches_both]) end end context "with examples from multiple spec source files" do it "applies exclusions only to examples defined in files with no location filters" do group = RSpec.describe("group") line = __LINE__ + 1 this_file_example = group.example("ex 1", :slow) { } # Using eval in order to make ruby think this got defined in another file. other_file_example = instance_eval "ex = nil; RSpec.describe('group') { ex = it('ex 2', :slow) { } }; ex", "some/external/file.rb", 1 filter_manager.exclude_with_low_priority :slow => true expect { filter_manager.add_location(__FILE__, [line]) }.to change { prune([this_file_example, other_file_example]).map(&:description) }.from([]).to([this_file_example.description]) end end it "prefers description to exclusion filter" do group = RSpec.describe("group") included = group.example("include", :slow => true) {} excluded = group.example("exclude") {} filter_manager.include(:full_description => /include/) filter_manager.exclude_with_low_priority :slow => true expect(prune([included, excluded])).to eq([included]) end it "includes objects with tags matching inclusions" do included = example_with({:foo => :bar}) excluded = example_with filter_manager.include :foo => :bar expect(prune([included, excluded])).to eq([included]) end it "excludes objects with tags matching exclusions" do included = example_with excluded = example_with({:foo => :bar}) filter_manager.exclude :foo => :bar expect(prune([included, excluded])).to eq([included]) end it "prefers exclusion when matches previously set inclusion" do included = example_with excluded = example_with({:foo => :bar}) filter_manager.include :foo => :bar filter_manager.exclude :foo => :bar expect(prune([included, excluded])).to eq([included]) end it "prefers inclusion when matches previously set exclusion" do included = example_with({:foo => :bar}) excluded = example_with filter_manager.exclude :foo => :bar filter_manager.include :foo => :bar expect(prune([included, excluded])).to eq([included]) end it "prefers previously set inclusion when exclusion matches but has lower priority" do included = example_with({:foo => :bar}) excluded = example_with filter_manager.include :foo => :bar filter_manager.exclude_with_low_priority :foo => :bar expect(prune([included, excluded])).to eq([included]) end it "prefers previously set exclusion when inclusion matches but has lower priority" do included = example_with excluded = example_with({:foo => :bar}) filter_manager.exclude :foo => :bar filter_manager.include_with_low_priority :foo => :bar expect(prune([included, excluded])).to eq([included]) end context "with multiple inclusion filters" do it 'includes objects that match any of them' do examples = [ included_1 = example_with(:foo => true), included_2 = example_with(:bar => true), example_with(:bazz => true) ] filter_manager.include :foo => true, :bar => true expect(prune(examples)).to contain_exactly(included_1, included_2) end end context "with :id filters" do it 'selects only the matched example when a single example id is given' do ex_1 = ex_2 = nil RSpec.describe do ex_1 = example ex_2 = example end filter_manager.add_ids(Metadata.relative_path(__FILE__), %w[ 1:2 ]) expect(prune([ex_1, ex_2])).to eq([ex_2]) end it 'can work with absolute file paths' do ex_1 = ex_2 = nil RSpec.describe do ex_1 = example ex_2 = example end filter_manager.add_ids(File.expand_path(__FILE__), %w[ 1:2 ]) expect(prune([ex_1, ex_2])).to eq([ex_2]) end it "can work with relative paths that lack the leading `.`" do path = Metadata.relative_path(__FILE__).sub(/^\.\//, '') ex_1 = ex_2 = nil RSpec.describe do ex_1 = example ex_2 = example end filter_manager.add_ids(path, %w[ 1:2 ]) expect(prune([ex_1, ex_2])).to eq([ex_2]) end it 'can select groups' do ex_1 = ex_2 = ex_3 = nil RSpec.describe { ex_1 = example } RSpec.describe do ex_2 = example ex_3 = example end filter_manager.add_ids(Metadata.relative_path(__FILE__), %w[ 2 ]) expect(prune([ex_1, ex_2, ex_3])).to eq([ex_2, ex_3]) end it 'uses the rerun file path when applying the id filter' do ex_1, ex_2 = instance_eval <<-EOS, "./some/spec.rb", 1 ex_1 = ex_2 = nil RSpec.shared_examples "shared" do ex_1 = example("ex 1") ex_2 = example("ex 2") end [ex_1, ex_2] EOS RSpec.describe { include_examples "shared" } filter_manager.add_ids(__FILE__, %w[ 1:1 ]) expect(prune([ex_1, ex_2]).map(&:description)).to eq([ex_1].map(&:description)) end end end describe "#inclusions#description" do subject(:description) { inclusions.description } it 'cleans up the description' do project_dir = File.expand_path('.') expect(lambda { }.inspect).to include(project_dir) expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9' expect(lambda { }.inspect).to include('0x') filter_manager.include :foo => lambda { } expect(description).not_to include(project_dir) expect(description).not_to include(' (lambda)') expect(description).not_to include('0x') end end describe "#exclusions#description" do subject(:description) { exclusions.description } it 'cleans up the description' do project_dir = File.expand_path('.') expect(lambda { }.inspect).to include(project_dir) expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9' expect(lambda { }.inspect).to include('0x') filter_manager.exclude :foo => lambda { } expect(description).not_to include(project_dir) expect(description).not_to include(' (lambda)') expect(description).not_to include('0x') end it 'returns `{}` when it only contains the default filters' do expect(description).to eq({}.inspect) end it 'includes other filters' do filter_manager.exclude :foo => :bar expect(description).to eq({ :foo => :bar }.inspect) end it 'includes an overridden :if filter' do allow(RSpec).to receive(:deprecate) filter_manager.exclude :if => :custom_filter expect(description).to eq({ :if => :custom_filter }.inspect) end it 'includes an overridden :unless filter' do allow(RSpec).to receive(:deprecate) filter_manager.exclude :unless => :custom_filter expect(description).to eq({ :unless => :custom_filter }.inspect) end end describe ":if and :unless ExclusionFilters" do def example_with_metadata(metadata) value = nil RSpec.describe("group") do value = example('arbitrary example', metadata) end value end def exclude?(example) prune([example]).empty? end describe "the default :if filter" do it "does not exclude a spec with { :if => true } metadata" do example = example_with_metadata(:if => true) expect(exclude?(example)).to be(false) end it "excludes a spec with { :if => false } metadata" do example = example_with_metadata(:if => false) expect(exclude?(example)).to be(true) end it "excludes a spec with { :if => nil } metadata" do example = example_with_metadata(:if => nil) expect(exclude?(example)).to be(true) end it "continues to be an exclusion even if exclusions are cleared" do example = example_with_metadata(:if => false) filter_manager.exclusions.clear expect(exclude?(example)).to be(true) end end describe "the default :unless filter" do it "excludes a spec with { :unless => true } metadata" do example = example_with_metadata(:unless => true) expect(exclude?(example)).to be(true) end it "does not exclude a spec with { :unless => false } metadata" do example = example_with_metadata(:unless => false) expect(exclude?(example)).to be(false) end it "does not exclude a spec with { :unless => nil } metadata" do example = example_with_metadata(:unless => nil) expect(exclude?(example)).to be(false) end it "continues to be an exclusion even if exclusions are cleared" do example = example_with_metadata(:unless => true) filter_manager.exclusions.clear expect(exclude?(example)).to be(true) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/hooks_filtering_spec.rb0000664000000000000000000004446114557677674026415 0ustar rootrootmodule RSpec::Core RSpec.describe "config block hook filtering" do context "when hooks are defined after a group has been defined" do it "still applies" do sequence = [] group = RSpec.describe do example { sequence << :ex_1 } example { sequence << :ex_2 } end RSpec.configure do |c| c.before(:context) { sequence << :before_cont_2 } c.prepend_before(:context) { sequence << :before_cont_1 } c.before(:example) { sequence << :before_ex_2 } c.prepend_before(:example) { sequence << :before_ex_1 } c.after(:context) { sequence << :after_cont_1 } c.append_after(:context) { sequence << :after_cont_2 } c.after(:example) { sequence << :after_ex_1 } c.append_after(:example) { sequence << :after_ex_2 } c.around(:example) do |ex| sequence << :around_before_ex ex.run sequence << :around_after_ex end end group.run expect(sequence).to eq [ :before_cont_1, :before_cont_2, :around_before_ex, :before_ex_1, :before_ex_2, :ex_1, :after_ex_1, :after_ex_2, :around_after_ex, :around_before_ex, :before_ex_1, :before_ex_2, :ex_2, :after_ex_1, :after_ex_2, :around_after_ex, :after_cont_1, :after_cont_2 ] end it "applies only to groups with matching metadata" do sequence = [] unmatching_group = RSpec.describe do example { } example { } end matching_group = RSpec.describe "", :run_hooks do example { sequence << :ex_1 } example { sequence << :ex_2 } end RSpec.configure do |c| c.before(:context, :run_hooks) { sequence << :before_cont_2 } c.prepend_before(:context, :run_hooks) { sequence << :before_cont_1 } c.before(:example, :run_hooks) { sequence << :before_ex_2 } c.prepend_before(:example, :run_hooks) { sequence << :before_ex_1 } c.after(:context, :run_hooks) { sequence << :after_cont_1 } c.append_after(:context, :run_hooks) { sequence << :after_cont_2 } c.after(:example, :run_hooks) { sequence << :after_ex_1 } c.append_after(:example, :run_hooks) { sequence << :after_ex_2 } c.around(:example, :run_hooks) do |ex| sequence << :around_before_ex ex.run sequence << :around_after_ex end end expect { unmatching_group.run }.not_to change { sequence }.from([]) matching_group.run expect(sequence).to eq [ :before_cont_1, :before_cont_2, :around_before_ex, :before_ex_1, :before_ex_2, :ex_1, :after_ex_1, :after_ex_2, :around_after_ex, :around_before_ex, :before_ex_1, :before_ex_2, :ex_2, :after_ex_1, :after_ex_2, :around_after_ex, :after_cont_1, :after_cont_2 ] end { ":example" => [:example], ":each" => [:each] }.each do |label, args| args << :run_hooks it "applies only to examples with matching metadata (for hooks declared with #{label})" do sequence = [] group = RSpec.describe do example("") { sequence << :ex_1 } example("", :run_hooks) { sequence << :ex_2 } end RSpec.configure do |c| c.before(*args) { sequence << :before_ex_2 } c.prepend_before(*args) { sequence << :before_ex_1 } c.after(*args) { sequence << :after_ex_1 } c.append_after(*args) { sequence << :after_ex_2 } c.around(*args) do |ex| sequence << :around_before_ex ex.run sequence << :around_after_ex end end group.run expect(sequence).to eq [ :ex_1, :around_before_ex, :before_ex_1, :before_ex_2, :ex_2, :after_ex_1, :after_ex_2, :around_after_ex, ] end end it "does not apply `suite` hooks to groups (or print warnings about suite hooks applied to example groups)" do sequence = [] group = RSpec.describe do example { sequence << :example } end RSpec.configure do |c| c.before(:suite) { sequence << :before_suite } c.prepend_before(:suite) { sequence << :prepended_before_suite } c.after(:suite) { sequence << :after_suite } c.append_after(:suite) { sequence << :appended_after_suite } end group.run expect(sequence).to eq [:example] end it "only runs example hooks once when there are multiple nested example groups" do sequence = [] group = RSpec.describe do context do example { sequence << :ex_1 } example { sequence << :ex_2 } end end RSpec.configure do |c| c.before(:example) { sequence << :before_ex_2 } c.prepend_before(:example) { sequence << :before_ex_1 } c.after(:example) { sequence << :after_ex_1 } c.append_after(:example) { sequence << :after_ex_2 } c.around(:example) do |ex| sequence << :around_before_ex ex.run sequence << :around_after_ex end end group.run expect(sequence).to eq [ :around_before_ex, :before_ex_1, :before_ex_2, :ex_1, :after_ex_1, :after_ex_2, :around_after_ex, :around_before_ex, :before_ex_1, :before_ex_2, :ex_2, :after_ex_1, :after_ex_2, :around_after_ex ] end it "only runs context hooks around the highest level group with matching filters" do sequence = [] group = RSpec.describe do before(:context) { sequence << :before_context } after(:context) { sequence << :after_context } context "", :match do context "", :match do example { sequence << :example } end end end RSpec.configure do |config| config.before(:context, :match) { sequence << :before_hook } config.after(:context, :match) { sequence << :after_hook } end group.run expect(sequence).to eq [:before_context, :before_hook, :example, :after_hook, :after_context] end end describe "unfiltered hooks" do it "is run" do filters = [] RSpec.configure do |c| c.before(:all) { filters << "before all in config"} c.around(:each) {|example| filters << "around each in config"; example.run} c.before(:each) { filters << "before each in config"} c.after(:each) { filters << "after each in config"} c.after(:all) { filters << "after all in config"} end group = RSpec.describe group.example("example") {} group.run expect(filters).to eq([ "before all in config", "around each in config", "before each in config", "after each in config", "after all in config" ]) end end describe "hooks with single filters" do context "with no scope specified" do it "is run around|before|after :each if the filter matches the example group's filter" do filters = [] RSpec.configure do |c| c.around(:match => true) {|example| filters << "around each in config"; example.run} c.before(:match => true) { filters << "before each in config"} c.after(:match => true) { filters << "after each in config"} end group = RSpec.describe("group", :match => true) group.example("example") {} group.run expect(filters).to eq([ "around each in config", "before each in config", "after each in config" ]) end end it "is run if the filter matches the example group's filter" do filters = [] RSpec.configure do |c| c.before(:all, :match => true) { filters << "before all in config"} c.around(:each, :match => true) {|example| filters << "around each in config"; example.run} c.before(:each, :match => true) { filters << "before each in config"} c.after(:each, :match => true) { filters << "after each in config"} c.after(:all, :match => true) { filters << "after all in config"} end group = RSpec.describe("group", :match => true) group.example("example") {} group.run expect(filters).to eq([ "before all in config", "around each in config", "before each in config", "after each in config", "after all in config" ]) end it "runs before|after :all hooks on matching nested example groups" do filters = [] RSpec.configure do |c| c.before(:all, :match => true) { filters << :before_all } c.after(:all, :match => true) { filters << :after_all } end example_1_filters = example_2_filters = nil group = RSpec.describe "group" do it("example 1") { example_1_filters = filters.dup } describe "subgroup", :match => true do it("example 2") { example_2_filters = filters.dup } end end group.run expect(example_1_filters).to be_empty expect(example_2_filters).to eq([:before_all]) expect(filters).to eq([:before_all, :after_all]) end it "runs before|after :all hooks only on the highest level group that matches the filter" do filters = [] RSpec.configure do |c| c.before(:all, :match => true) { filters << :before_all } c.after(:all, :match => true) { filters << :after_all } end example_1_filters = example_2_filters = example_3_filters = nil group = RSpec.describe "group", :match => true do it("example 1") { example_1_filters = filters.dup } describe "subgroup", :match => true do it("example 2") { example_2_filters = filters.dup } describe "sub-subgroup", :match => true do it("example 3") { example_3_filters = filters.dup } end end end group.run expect(example_1_filters).to eq([:before_all]) expect(example_2_filters).to eq([:before_all]) expect(example_3_filters).to eq([:before_all]) expect(filters).to eq([:before_all, :after_all]) end it "does not run if the filter doesn't match the example group's filter" do filters = [] RSpec.configure do |c| c.before(:all, :match => false) { filters << "before all in config"} c.around(:each, :match => false) {|example| filters << "around each in config"; example.run} c.before(:each, :match => false) { filters << "before each in config"} c.after(:each, :match => false) { filters << "after each in config"} c.after(:all, :match => false) { filters << "after all in config"} end group = RSpec.describe(:match => true) group.example("example") {} group.run expect(filters).to eq([]) end it "runs :all|:context hooks even if there are no unskipped examples in that context" do filters = [] group = RSpec.describe("un-skipped describe") do before(:all) { filters << "before all in group"} after(:all) { filters << "after all in group"} xcontext("skipped context") do before(:context) { filters << "before context in group"} after(:context) { filters << "after context in group"} it("is skipped") {} end end group.run expect(filters).to eq(["before all in group", "after all in group"]) end it "does not run :all|:context hooks in global config if the entire context is skipped" do filters = [] RSpec.configure do |c| c.before(:all) { filters << "before all in config"} c.after(:all) { filters << "after all in config"} c.before(:context) { filters << "before context in config"} c.after(:context) { filters << "after context in config"} end group = RSpec.xdescribe("skipped describe") do context("skipped context") do it("is skipped") {} end end group.run expect(filters).to eq([]) end it "does not run local :all|:context hooks if the entire context is skipped" do filters = [] group = RSpec.xdescribe("skipped describe") do before(:all) { filters << "before all in group"} after(:all) { filters << "after all in group"} context("skipped context") do before(:context) { filters << "before context in group"} after(:context) { filters << "after context in group"} it("is skipped") {} end end group.run expect(filters).to eq([]) end context "when the hook filters apply to individual examples instead of example groups" do let(:each_filters) { [] } let(:all_filters) { [] } let(:example_group) do md = example_metadata RSpec.describe do it("example", md) { } end end def filters each_filters + all_filters end before(:each) do af, ef = all_filters, each_filters RSpec.configure do |c| c.before(:all, :foo => :bar) { af << "before all in config"} c.around(:each, :foo => :bar) {|example| ef << "around each in config"; example.run} c.before(:each, :foo => :bar) { ef << "before each in config"} c.after(:each, :foo => :bar) { ef << "after each in config"} c.after(:all, :foo => :bar) { af << "after all in config"} end example_group.run end describe 'an example with matching metadata' do let(:example_metadata) { { :foo => :bar } } it "runs the `:each` hooks" do expect(each_filters).to eq([ 'around each in config', 'before each in config', 'after each in config' ]) end end describe 'an example without matching metadata' do let(:example_metadata) { { :foo => :bazz } } it "does not run any of the hooks" do expect(self.filters).to be_empty end end end end describe "hooks with multiple filters" do it "is run if all hook filters match the group's filters" do filters = [] RSpec.configure do |c| c.before(:all, :one => 1) { filters << "before all in config"} c.around(:each, :two => 2, :one => 1) {|example| filters << "around each in config"; example.run} c.before(:each, :one => 1, :two => 2) { filters << "before each in config"} c.after(:each, :one => 1, :two => 2, :three => 3) { filters << "after each in config"} c.after(:all, :one => 1, :three => 3) { filters << "after all in config"} end group = RSpec.describe("group", :one => 1, :two => 2, :three => 3) group.example("example") {} group.run expect(filters).to eq([ "before all in config", "around each in config", "before each in config", "after each in config", "after all in config" ]) end it "does not run if some hook filters don't match the group's filters" do sequence = [] RSpec.configure do |c| c.before(:all, :one => 1, :four => 4) { sequence << "before all in config"} c.around(:each, :two => 2, :four => 4) {|example| sequence << "around each in config"; example.run} c.before(:each, :one => 1, :two => 2, :four => 4) { sequence << "before each in config"} c.after(:each, :one => 1, :two => 2, :three => 3, :four => 4) { sequence << "after each in config"} c.after(:all, :one => 1, :three => 3, :four => 4) { sequence << "after all in config"} end RSpec.describe "group", :one => 1, :two => 2, :three => 3 do example("ex1") { sequence << "ex1" } example("ex2", :four => 4) { sequence << "ex2" } end.run expect(sequence).to eq([ "ex1", "before all in config", "around each in config", "before each in config", "ex2", "after each in config", "after all in config" ]) end it "does not run for examples that do not match, even if their group matches" do filters = [] RSpec.configure do |c| c.before(:each, :apply_it) { filters << :before_each } end RSpec.describe "Group", :apply_it do example("ex1") { filters << :matching_example } example("ex2", :apply_it => false) { filters << :nonmatching_example } end.run expect(filters).to eq([:before_each, :matching_example, :nonmatching_example]) end end describe ":context hooks defined in configuration with metadata" do it 'applies to individual matching examples' do sequence = [] RSpec.configure do |config| config.before(:context, :apply_it) { sequence << :before_context } config.after(:context, :apply_it) { sequence << :after_context } end RSpec.describe do example("ex", :apply_it) { sequence << :example } end.run expect(sequence).to eq([:before_context, :example, :after_context]) end it 'does not apply to individual matching examples for which it also applies to a parent example group' do sequence = [] RSpec.configure do |config| config.before(:context, :apply_it) { sequence << :before_context } config.after(:context, :apply_it) { sequence << :after_context } end RSpec.describe "Group", :apply_it do example("ex") { sequence << :outer_example } context "nested", :apply_it => false do example("ex", :apply_it) { sequence << :inner_example } end end.run expect(sequence).to eq([:before_context, :outer_example, :inner_example, :after_context]) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/pending_example_spec.rb0000664000000000000000000001422414557677674026360 0ustar rootrootRSpec.describe "an example" do context "declared pending with metadata" do it "uses the value assigned to :pending as the message" do group = RSpec.describe('group') do example "example", :pending => 'just because' do fail end end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_pending_with('just because') end it "sets the message to 'No reason given' if :pending => true" do group = RSpec.describe('group') do example "example", :pending => true do fail end end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_pending_with('No reason given') end it "passes if a mock expectation is not satisfied" do group = RSpec.describe('group') do example "example", :pending => "because" do expect(RSpec).to receive(:a_message_in_a_bottle) end end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_pending_with('because') expect(example.execution_result.status).to eq(:pending) end it "does not mutate the :pending attribute of the user metadata when handling mock expectation errors" do group = RSpec.describe('group') do example "example", :pending => "because" do expect(RSpec).to receive(:a_message_in_a_bottle) end end group.run example = group.examples.first expect(example.metadata[:pending]).to be(true) end end context "made pending with `define_derived_metadata`" do before do RSpec.configure do |config| config.define_derived_metadata(:not_ready) do |meta| meta[:pending] ||= "Not ready" end end end it 'has a pending result if there is an error' do group = RSpec.describe "group" do example "something", :not_ready do boom end end group.run example = group.examples.first expect(example).to be_pending_with("Not ready") end it 'fails if there is no error' do group = RSpec.describe "group" do example "something", :not_ready do end end group.run example = group.examples.first expect(example.execution_result.status).to be(:failed) expect(example.execution_result.exception.message).to include("Expected example to fail") end end context "with no block" do it "is listed as pending with 'Not yet implemented'" do group = RSpec.describe('group') do it "has no block" end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_skipped_with('Not yet implemented') end end context "with no args" do it "is listed as pending with the default message" do group = RSpec.describe('group') do it "does something" do pending fail end end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_pending_with(RSpec::Core::Pending::NO_REASON_GIVEN) end it "fails when the rest of the example passes" do called = false group = RSpec.describe('group') do it "does something" do pending called = true end end example = group.examples.first example.run(group.new, double.as_null_object) expect(called).to eq(true) result = example.execution_result expect(result.pending_fixed).to eq(true) expect(result.status).to eq(:failed) end it "does not mutate the :pending attribute of the user metadata when the rest of the example passes" do group = RSpec.describe('group') do it "does something" do pending end end group.run example = group.examples.first expect(example.metadata).to include(:pending => true) end end context "with no docstring" do context "declared with the pending method" do it "has an auto-generated description if it has an expectation" do ex = nil RSpec.describe('group') do it "checks something" do expect((3+4)).to eq(7) end ex = pending do expect("string".reverse).to eq("gnirts") end end.run expect(ex.description).to eq('is expected to eq "gnirts"') end end context "after another example with some assertion" do it "does not show any message" do ex = nil RSpec.describe('group') do it "checks something" do expect((3+4)).to eq(7) end ex = specify do pending end end.run expect(ex.description).to match(/example at/) end end end context "with a message" do it "is listed as pending with the supplied message" do group = RSpec.describe('group') do it "does something" do pending("just because") fail end end example = group.examples.first example.run(group.new, double.as_null_object) expect(example).to be_pending_with('just because') end end context "with a block" do it "fails with an ArgumentError stating the syntax is deprecated" do group = RSpec.describe('group') do it "calls pending with a block" do pending("with invalid syntax") do :no_op end fail end end example = group.examples.first group.run expect(example).to fail_with ArgumentError expect(example.exception.message).to match( /Passing a block within an example is now deprecated./ ) end it "does not yield to the block" do example_to_have_yielded = :did_not_yield group = RSpec.describe('group') do it "calls pending with a block" do pending("just because") do example_to_have_yielded = :pending_block end fail end end group.run expect(example_to_have_yielded).to eq :did_not_yield end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/did_you_mean_spec.rb0000664000000000000000000000254714557677674025662 0ustar rootrootmodule RSpec module Core RSpec.describe DidYouMean do describe '#call' do context "when `DidYouMean::SpellChecker` is available", :skip => !defined?(::DidYouMean::SpellChecker) do context 'Success' do let(:name) { './spec/rspec/core/did_you_mean_spec.rb' } it 'returns a useful suggestion' do expect(DidYouMean.new(name[0..-2]).call).to include name end context 'numerous possibilities' do it 'returns a small number of suggestions' do name = './spec/rspec/core/drb_spec.r' suggestions = DidYouMean.new(name).call expect(suggestions.split("\n").size).to eq 4 end end end context 'No suitable suggestions' do it 'returns empty string' do name = './' + 'x' * 50 expect(DidYouMean.new(name).call).to eq '' end end end context "when `DidYouMean::SpellChecker` is not available", :unless => defined?(::DidYouMean::SpellChecker) do describe 'Success' do let(:name) { './spec/rspec/core/did_you_mean_spec.rb' } it 'returns a hint' do expect(DidYouMean.new(name[0..-2]).call).to include 'Hint:' end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/profiler_spec.rb0000664000000000000000000000515314557677674025044 0ustar rootrootrequire 'rspec/core/profiler' RSpec.describe 'RSpec::Core::Profiler' do let(:profiler) { RSpec::Core::Profiler.new } it 'starts with an empty hash of example_groups' do expect(profiler.example_groups).to be_empty.and be_a Hash end context 'when hooked into the reporter' do include FormatterSupport let(:description ) { "My Group" } let(:now) { ::Time.utc(2015, 6, 2) } before do allow(::RSpec::Core::Time).to receive(:now) { now } end let(:group) { RSpec.describe "My Group" } describe '#example_group_started' do it 'records example groups start time and description' do expect { profiler.example_group_started group_notification group }.to change { profiler.example_groups[group] }. from(a_hash_excluding(:start, :description)). to(a_hash_including(:start => now, :description => description)) end context "when the group is not a top-level group" do let(:group) { super().describe "nested" } it 'no-ops since we only consider top-level groups for profiling' do expect { profiler.example_group_started group_notification group }.not_to change(profiler, :example_groups) end end end describe '#example_group_finished' do before do profiler.example_group_started group_notification group allow(::RSpec::Core::Time).to receive(:now) { now + 1 } end it 'records example groups total time and description' do expect { profiler.example_group_finished group_notification group }.to change { profiler.example_groups[group] }. from(a_hash_excluding(:total_time)). to(a_hash_including(:total_time => 1.0)) end context "when the group is not a top-level group" do let(:group) { super().describe "nested" } it 'no-ops since we only consider top-level groups for profiling' do expect { profiler.example_group_finished group_notification group }.not_to change(profiler, :example_groups) end end end describe '#example_started' do let(:example) { new_example } before do allow(example).to receive(:example_group) { group } allow(group).to receive(:parent_groups) { [group] } profiler.example_group_started group_notification group end it 'increments the count of examples for its parent group' do expect { profiler.example_started example_notification example }.to change { profiler.example_groups[group][:count] }.by 1 end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/metadata_filter_spec.rb0000664000000000000000000002351714557677674026353 0ustar rootrootmodule RSpec module Core RSpec.describe MetadataFilter do describe ".filter_applies?" do attr_accessor :parent_group_metadata, :group_metadata, :example_metadata def create_metadatas container = self RSpec.describe "parent group", :caller => ["/foo_spec.rb:#{__LINE__}"] do; container.parent_group_metadata = metadata describe "group", :caller => ["/foo_spec.rb:#{__LINE__}"] do; container.group_metadata = metadata container.example_metadata = it("example", :caller => ["/foo_spec.rb:#{__LINE__}"], :if => true).metadata end end end let(:world) { World.new } before do allow(RSpec).to receive(:world) { world } create_metadatas end def filter_applies?(key, value, metadata) MetadataFilter.filter_applies?(key, value, metadata) end context "with locations" do let(:condition_key){ :locations } let(:parent_group_condition) do {File.expand_path(parent_group_metadata[:file_path]) => [parent_group_metadata[:line_number]]} end let(:group_condition) do {File.expand_path(group_metadata[:file_path]) => [group_metadata[:line_number]]} end let(:example_condition) do {File.expand_path(example_metadata[:file_path]) => [example_metadata[:line_number]]} end let(:between_examples_condition) do {File.expand_path(group_metadata[:file_path]) => [group_metadata[:line_number] + 1]} end let(:next_example_condition) do {File.expand_path(example_metadata[:file_path]) => [example_metadata[:line_number] + 2]} end let(:preceeding_declaration_lines) {{ parent_group_metadata[:line_number] => parent_group_metadata[:line_number], group_metadata[:line_number] => group_metadata[:line_number], example_metadata[:line_number] => example_metadata[:line_number], (example_metadata[:line_number] + 1) => example_metadata[:line_number], (example_metadata[:line_number] + 2) => example_metadata[:line_number] + 2, }} before do expect(world).to receive(:preceding_declaration_line).at_least(:once) do |_file_name, line_num| preceeding_declaration_lines[line_num] end end it "matches the group when the line_number is the example group line number" do # this call doesn't really make sense since filter_applies? is only called # for example metadata not group metadata expect(filter_applies?(condition_key, group_condition, group_metadata)).to be(true) end it "matches the example when the line_number is the grandparent example group line number" do expect(filter_applies?(condition_key, parent_group_condition, example_metadata)).to be(true) end it "matches the example when the line_number is the parent example group line number" do expect(filter_applies?(condition_key, group_condition, example_metadata)).to be(true) end it "matches the example when the line_number is the example line number" do expect(filter_applies?(condition_key, example_condition, example_metadata)).to be(true) end it "matches when the line number is between this example and the next" do expect(filter_applies?(condition_key, between_examples_condition, example_metadata)).to be(true) end it "does not match when the line number matches the next example" do expect(filter_applies?(condition_key, next_example_condition, example_metadata)).to be(false) end end it "matches a proc with no arguments that evaluates to true" do expect(filter_applies?(:if, lambda { true }, example_metadata)).to be(true) end it "matches a proc that evaluates to true" do expect(filter_applies?(:if, lambda { |v| v }, example_metadata)).to be(true) end it "does not match a proc that evaluates to false" do expect(filter_applies?(:if, lambda { |v| !v }, example_metadata)).to be(false) end it "matches a proc with an arity of 2" do example_metadata[:foo] = nil expect(filter_applies?(:foo, lambda { |v, m| m == example_metadata }, example_metadata)).to be(true) end it "raises an error when the proc has an incorrect arity" do expect { filter_applies?(:if, lambda { |a,b,c| true }, example_metadata) }.to raise_error(ArgumentError) end it "matches an arbitrary object that has implemented `===` for matching" do matcher = Object.new def matcher.===(str) str.include?("T") end expect(filter_applies?(:foo, matcher, {:foo => "a sing"})).to be false expect(filter_applies?(:foo, matcher, {:foo => "a sTring"})).to be true end context "with an :ids filter" do it 'matches examples with a matching id and rerun_file_path' do metadata = { :scoped_id => "1:2", :rerun_file_path => "some/file" } expect(filter_applies?(:ids, { "some/file" => ["1:2"] }, metadata)).to be true end it 'does not match examples without a matching id' do metadata = { :scoped_id => "1:2", :rerun_file_path => "some/file" } expect(filter_applies?(:ids, { "some/file" => ["1:3"] }, metadata)).to be false end it 'does not match examples without a matching rerun_file_path' do metadata = { :scoped_id => "1:2", :rerun_file_path => "some/file" } expect(filter_applies?(:ids, { "some/file_2" => ["1:2"] }, metadata)).to be false end it 'matches the scoped id from a parent example group' do metadata = { :scoped_id => "1:2", :rerun_file_path => "some/file", :example_group => { :scoped_id => "1" } } expect(filter_applies?(:ids, { "some/file" => ["1"] }, metadata)).to be true expect(filter_applies?(:ids, { "some/file" => ["2"] }, metadata)).to be false end it 'matches only on entire id segments so (1 is not treated as a parent group of 11)' do metadata = { :scoped_id => "1:2", :rerun_file_path => "some/file", :example_group => { :scoped_id => "1" } } expect(filter_applies?(:ids, { "some/file" => ["1"] }, metadata)).to be true metadata = { :scoped_id => "11", :rerun_file_path => "some/file" } expect(filter_applies?(:ids, { "some/file" => ["1"] }, metadata)).to be false end end context "with a nested hash" do it 'matches when the nested entry matches' do metadata = { :foo => { :bar => "words" } } expect(filter_applies?(:foo, { :bar => /wor/ }, metadata)).to be(true) end it 'does not match when the nested entry does not match' do metadata = { :foo => { :bar => "words" } } expect(filter_applies?(:foo, { :bar => /sword/ }, metadata)).to be(false) end it 'does not match when the metadata lacks the key' do expect(filter_applies?(:foo, { :bar => /sword/ }, {})).to be(false) end it 'does not match when the metadata does not have a hash entry for the key' do metadata = { :foo => "words" } expect(filter_applies?(:foo, { :bar => /word/ }, metadata)).to be(false) end it 'matches when a metadata key is specified without a value and exists in the metadata hash' do metadata = { :foo => "words" } expect(filter_applies?(:foo, true, metadata)).to be(true) end end context "with an Array" do let(:metadata_with_array) do meta = nil RSpec.describe("group") do meta = example('example_with_array', :tag => [:one, 2, 'three', /four/]).metadata end meta end it "matches a symbol" do expect(filter_applies?(:tag, 'one', metadata_with_array)).to be(true) expect(filter_applies?(:tag, :one, metadata_with_array)).to be(true) expect(filter_applies?(:tag, 'two', metadata_with_array)).to be(false) end it "matches a string" do expect(filter_applies?(:tag, 'three', metadata_with_array)).to be(true) expect(filter_applies?(:tag, :three, metadata_with_array)).to be(true) expect(filter_applies?(:tag, 'tree', metadata_with_array)).to be(false) end it "matches an integer" do expect(filter_applies?(:tag, '2', metadata_with_array)).to be(true) expect(filter_applies?(:tag, 2, metadata_with_array)).to be(true) expect(filter_applies?(:tag, 3, metadata_with_array)).to be(false) end it "matches a regexp" do expect(filter_applies?(:tag, 'four', metadata_with_array)).to be(true) expect(filter_applies?(:tag, 'fourtune', metadata_with_array)).to be(true) expect(filter_applies?(:tag, 'fortune', metadata_with_array)).to be(false) end it "matches a proc that evaluates to true" do expect(filter_applies?(:tag, lambda { |values| values.include? 'three' }, metadata_with_array)).to be(true) end it "does not match a proc that evaluates to false" do expect(filter_applies?(:tag, lambda { |values| values.include? 'nothing' }, metadata_with_array)).to be(false) end it 'matches when a metadata key is specified without a value and exists in the metadata hash' do expect(filter_applies?(:tag, true, metadata_with_array)).to be(true) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/backtrace_formatter_spec.rb0000664000000000000000000003314714557677674027230 0ustar rootrootmodule RSpec::Core RSpec.describe BacktraceFormatter do def make_backtrace_formatter(exclusion_patterns=nil, inclusion_patterns=nil) BacktraceFormatter.new.tap do |bc| bc.exclusion_patterns = exclusion_patterns if exclusion_patterns bc.inclusion_patterns = inclusion_patterns if inclusion_patterns end end describe "defaults" do it "excludes rspec files" do expect(make_backtrace_formatter.exclude?("/lib/rspec/core.rb")).to be true expect(make_backtrace_formatter.exclude?("/lib/rspec/core/foo.rb")).to be true expect(make_backtrace_formatter.exclude?("/lib/rspec/expectations/foo.rb")).to be true expect(make_backtrace_formatter.exclude?("/lib/rspec/matchers/foo.rb")).to be true expect(make_backtrace_formatter.exclude?("/lib/rspec/mocks/foo.rb")).to be true expect(make_backtrace_formatter.exclude?("/lib/rspec/support/foo.rb")).to be true end it "excludes the rspec binary, even when rspec-core has installed as a bundler :git dependency" do expect(make_backtrace_formatter.exclude?("exe/rspec")).to be true end it "excludes java files (for JRuby)", :if => (RUBY_PLATFORM == 'java') do expect(make_backtrace_formatter.exclude?("org/jruby/RubyArray.java:2336")).to be true end it "includes files in projects containing 'gems' in the name" do expect(make_backtrace_formatter.exclude?('code/my-gems-plugin/lib/plugin.rb')).to be false end it "includes something in the current working directory" do expect(make_backtrace_formatter.exclude?("#{Dir.getwd}/arbitrary")).to be false end it 'allows users to exclude their bundler vendor directory' do formatter = make_backtrace_formatter([%r{/vendor/bundle/}]) vendored_gem_line = File.join(Dir.getwd, "vendor/bundle/gems/mygem-4.1.6/lib/my_gem:241") expect(formatter.exclude? vendored_gem_line).to be true end context "when the exclusion list has been replaced" do it "includes a line that the default patterns exclude" do formatter = make_backtrace_formatter expect { formatter = make_backtrace_formatter([/spec_helper/]) }.to change { formatter.exclude? "/path/to/lib/rspec/expectations/foo.rb" }.from(true).to(false) end end context "when the current working directory includes `gems` in the name" do around(:example) do |ex| Dir.mktmpdir do |tmp_dir| dir = File.join(tmp_dir, "gems") Dir.mkdir(dir) Dir.chdir(dir, &ex) end end it "includes something in the current working directory" do expect(make_backtrace_formatter.exclude?("#{Dir.getwd}/arbitrary")).to be false end end end describe "#filter_gem" do shared_examples_for "filtering a gem" do |gem_name, path| it 'filters backtrace lines for the named gem' do formatter = BacktraceFormatter.new line = File.join(path, "lib", "foo.rb:13") expect { formatter.filter_gem gem_name }.to change { formatter.exclude?(line) }.from(false).to(true) end end context "for a gem installed globally as a system gem" do include_examples "filtering a gem", "foo", "/Users/myron/.gem/ruby/2.1.1/gems/foo-1.6.3.1" end context "for a gem installed in a vendored bundler path" do include_examples "filtering a gem", "foo", "/Users/myron/code/my_project/bundle/ruby/2.1.0/gems/foo-0.3.6" end context "for a gem installed by bundler as a :git dependency" do include_examples "filtering a gem", "foo", "/Users/myron/code/my_project/bundle/ruby/2.1.0/bundler/gems/foo-2b826653e1f5" end context "for a gem sourced from a local path" do include_examples "filtering a gem", "foo", "/Users/myron/code/foo" end context "when vendored under the working directory" do include_examples "filtering a gem", "foo", File.join(Dir.getwd, "bundle/ruby/2.1.0/bundler/gems/foo-0.3.6") end end describe "#format_backtrace" do it "excludes lines from rspec libs by default" do backtrace = [ "/path/to/rspec-expectations/lib/rspec/expectations/foo.rb:37", "/path/to/rspec-expectations/lib/rspec/matchers/foo.rb:37", "./my_spec.rb:5", "/path/to/rspec-mocks/lib/rspec/mocks/foo.rb:37", "/path/to/rspec-core/lib/rspec/core/foo.rb:37" ] expect(BacktraceFormatter.new.format_backtrace(backtrace)).to eq(["./my_spec.rb:5"]) end it "excludes lines from bundler by default, since Bundler 1.12 now includes its stackframes in all stacktraces when you `bundle exec`" do bundler_trace = [ "/some/other/file.rb:13", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/cli/exec.rb:63:in `load'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/cli/exec.rb:63:in `kernel_load'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/cli/exec.rb:24:in `run'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/cli.rb:304:in `exec'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/cli.rb:11:in `start'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/exe/bundle:27:in `block in '", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/lib/bundler/friendly_errors.rb:98:in `with_friendly_errors'", "/Users/myron/.gem/ruby/2.3.0/gems/bundler-1.12.3/exe/bundle:19:in `'", "/Users/myron/.gem/ruby/2.3.0/bin/bundle:23:in `load'", "/Users/myron/.gem/ruby/2.3.0/bin/bundle:23:in `
'" ] expect(BacktraceFormatter.new.format_backtrace(bundler_trace)).to eq ["/some/other/file.rb:13"] end context "when every line is filtered out" do let(:backtrace) do [ "/path/to/rspec-expectations/lib/rspec/expectations/foo.rb:37", "/path/to/rspec-expectations/lib/rspec/matchers/foo.rb:37", "/path/to/rspec-mocks/lib/rspec/mocks/foo.rb:37", "/path/to/rspec-core/lib/rspec/core/foo.rb:37" ] end it "includes full backtrace" do expect(BacktraceFormatter.new.format_backtrace(self.backtrace).take(4)).to eq self.backtrace end it "adds a message explaining everything was filtered" do expect(BacktraceFormatter.new.format_backtrace(self.backtrace).drop(4).join).to match(/Showing full backtrace/) end end describe "for an empty backtrace" do it "does not add the explanatory message about backtrace filtering" do formatter = BacktraceFormatter.new expect(formatter.format_backtrace([])).to eq([]) end end describe "for a `nil` backtrace (since exceptions can have no backtrace!)" do it 'returns a blank array, with no explanatory message' do exception = Exception.new expect(exception.backtrace).to be_nil formatter = BacktraceFormatter.new expect(formatter.format_backtrace(exception.backtrace)).to eq([]) end end context "when rspec is installed in the current working directory" do it "excludes lines from rspec libs by default", :unless => RSpec::Support::OS.windows? do backtrace = [ "#{Dir.getwd}/.bundle/path/to/rspec-expectations/lib/rspec/expectations/foo.rb:37", "#{Dir.getwd}/.bundle/path/to/rspec-expectations/lib/rspec/matchers/foo.rb:37", "#{Dir.getwd}/my_spec.rb:5", "#{Dir.getwd}/.bundle/path/to/rspec-mocks/lib/rspec/mocks/foo.rb:37", "#{Dir.getwd}/.bundle/path/to/rspec-core/lib/rspec/core/foo.rb:37" ] expect(BacktraceFormatter.new.format_backtrace(backtrace)).to eq(["./my_spec.rb:5"]) end end end describe "#full_backtrace=true" do it "sets full_backtrace true" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true expect(formatter.full_backtrace?).to be true end it "preserves exclusion and inclusion patterns" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true expect(formatter.exclusion_patterns).to eq [/discard/] expect(formatter.inclusion_patterns).to eq [/keep/] end it "keeps all lines, even those that match exclusions" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true expect(formatter.exclude? "discard").to be false end end describe "#full_backtrace=false (after it was true)" do it "sets full_backtrace false" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true formatter.full_backtrace = false expect(formatter.full_backtrace?).to be false end it "preserves exclusion and inclusion patterns" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true formatter.full_backtrace = false expect(formatter.exclusion_patterns).to eq [/discard/] expect(formatter.inclusion_patterns).to eq [/keep/] end it "excludes lines that match exclusions" do formatter = make_backtrace_formatter([/discard/],[/keep/]) formatter.full_backtrace = true formatter.full_backtrace = false expect(formatter.exclude? "discard").to be true end end describe "#backtrace_line" do let(:formatter) { BacktraceFormatter.new } it "trims current working directory" do expect(self.formatter.__send__(:backtrace_line, File.expand_path(__FILE__))).to eq("./spec/rspec/core/backtrace_formatter_spec.rb") end it "preserves the original line" do original_line = File.expand_path(__FILE__) self.formatter.__send__(:backtrace_line, original_line) expect(original_line).to eq(File.expand_path(__FILE__)) end it "deals gracefully with a security error" do Metadata.instance_eval { @relative_path_regex = nil } with_safe_set_to_level_that_triggers_security_errors do self.formatter.__send__(:backtrace_line, __FILE__) # on some rubies, this doesn't raise a SecurityError; this test just # assures that if it *does* raise an error, the error is caught inside end end end context "when the current directory matches one of the default exclusion patterns" do include_context "isolated directory" around do |ex| FileUtils.mkdir_p("bin") Dir.chdir("./bin", &ex) end let(:line) { File.join(Dir.getwd, "foo.rb:13") } it 'does not exclude lines from files in the current directory' do expect(make_backtrace_formatter.exclude? self.line).to be false end context "with inclusion_patterns cleared" do it 'excludes lines from files in the current directory' do formatter = make_backtrace_formatter formatter.inclusion_patterns.clear expect(formatter.exclude? self.line).to be true end end end context "with no patterns" do it "keeps all lines" do lines = ["/tmp/a_file", "some_random_text", "hello\330\271!"] formatter = make_backtrace_formatter([], []) expect(lines.all? {|line| formatter.exclude? line}).to be false end it "is considered a full backtrace" do expect(make_backtrace_formatter([], []).full_backtrace?).to be true end end context "with an exclusion pattern but no inclusion patterns" do it "excludes lines that match the exclusion pattern" do formatter = make_backtrace_formatter([/discard/],[]) expect(formatter.exclude? "discard me").to be true end it "keeps lines that do not match the exclusion pattern" do formatter = make_backtrace_formatter([/discard/],[]) expect(formatter.exclude? "apple").to be false end it "is considered a partial backtrace" do formatter = make_backtrace_formatter([/discard/],[]) expect(formatter.full_backtrace?).to be false end end context "with an exclusion pattern and an inclusion pattern" do it "excludes lines that match the exclusion pattern but not the inclusion pattern" do formatter = make_backtrace_formatter([/discard/],[/keep/]) expect(formatter.exclude? "discard").to be true end it "keeps lines that match both patterns" do formatter = make_backtrace_formatter([/discard/],[/keep/]) expect(formatter.exclude? "discard/keep").to be false end it "keeps lines that match neither pattern" do formatter = make_backtrace_formatter([/discard/],[/keep/]) expect(formatter.exclude? "fish").to be false end it "is considered a partial backtrace" do formatter = make_backtrace_formatter([/discard/],[/keep/]) expect(formatter.full_backtrace?).to be false end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/world_spec.rb0000664000000000000000000002532614557677674024355 0ustar rootrootclass Bar; end class Foo; end module RSpec::Core RSpec.describe RSpec::Core::World do let(:configuration) { RSpec.configuration } let(:world) { RSpec.world } describe '#reset' do it 'clears #example_groups' do world.example_groups << :example_group world.reset expect(world.example_groups).to be_empty end it 'clears #source_from_file cache', :isolated_directory do File.open('foo.rb', 'w') { |file| file.write('puts 1') } expect(world.source_from_file('foo.rb').lines).to eq(['puts 1']) File.open('foo.rb', 'w') { |file| file.write('puts 2') } expect(world.source_from_file('foo.rb').lines).to eq(['puts 1']) world.reset expect(world.source_from_file('foo.rb').lines).to eq(['puts 2']) end it 'clears #syntax_highlighter memoization' do expect { world.reset }.to change { world.syntax_highlighter.object_id } end it 'removes the previously assigned example group constants' do RSpec.describe "group" expect { RSpec.world.reset }.to change(RSpec::ExampleGroups, :constants).to([]) end it 'clears #example_group_counts_by_spec_file' do RSpec.describe "group" expect { RSpec.world.reset }.to change { world.example_group_counts_by_spec_file }.to be_empty end end describe "#example_groups" do it "contains all registered example groups" do example_group = RSpec.describe("group") {} expect(world.example_groups).to include(example_group) end end describe "#all_example_groups" do it "contains all example groups from all levels of nesting" do RSpec.describe "eg1" do context "eg2" do context "eg3" context "eg4" end context "eg5" end RSpec.describe "eg6" do example end expect(RSpec.world.all_example_groups.map(&:description)).to match_array(%w[ eg1 eg2 eg3 eg4 eg5 eg6 ]) end end describe "#all_examples" do it "contains all examples from all levels of nesting" do RSpec.describe do example("ex1") context "nested" do example("ex2") context "nested" do example("ex3") example("ex4") end end example("ex5") end RSpec.describe do example("ex6") end expect(RSpec.world.all_examples.map(&:description)).to match_array(%w[ ex1 ex2 ex3 ex4 ex5 ex6 ]) end end describe "#preceding_declaration_line (again)" do let(:group) do RSpec.describe("group") do example("example") {} end end let(:second_group) do RSpec.describe("second_group") do example("second_example") {} end end let(:group_declaration_line) { group.metadata[:line_number] } let(:example_declaration_line) { group_declaration_line + 2 } def preceding_declaration_line(line_num) world.preceding_declaration_line(__FILE__, line_num) end context "with one example" do it "returns nil if no example or group precedes the line" do expect(preceding_declaration_line(group_declaration_line - 1)).to be_nil end it "returns the argument line number if a group starts on that line" do expect(preceding_declaration_line(group_declaration_line)).to eq(group_declaration_line) end it "returns the argument line number if an example starts on that line" do expect(preceding_declaration_line(example_declaration_line)).to eq(example_declaration_line) end it "returns line number of a group that immediately precedes the argument line" do expect(preceding_declaration_line(group_declaration_line + 1)).to eq(group_declaration_line) end it "returns line number of an example that immediately precedes the argument line" do expect(preceding_declaration_line(example_declaration_line + 1)).to eq(example_declaration_line) end end context "with two groups and the second example is registered first" do let(:second_group_declaration_line) { second_group.metadata[:line_number] } before do world.record(second_group) world.record(group) end it 'return line number of group if a group start on that line' do expect(preceding_declaration_line(second_group_declaration_line)).to eq(second_group_declaration_line) end end context "with groups from multiple files registered" do another_file = File.join(__FILE__, "another_spec_file.rb") let(:group_from_another_file) do instance_eval <<-EOS, another_file, 1 RSpec.describe("third group") do example("inside of a gropu") end EOS end before do world.record(group) world.record(group_from_another_file) end it "returns nil if given a file name with no declarations" do expect(world.preceding_declaration_line("/some/other/file.rb", 100_000)).to eq(nil) end it "considers only declaration lines from the provided files", :aggregate_failures do expect(world.preceding_declaration_line(another_file, 1)).to eq(1) expect(world.preceding_declaration_line(another_file, 2)).to eq(1) expect(world.preceding_declaration_line(another_file, 3)).to eq(3) expect(world.preceding_declaration_line(another_file, 4)).to eq(3) expect(world.preceding_declaration_line(another_file, 5)).to eq(3) expect(world.preceding_declaration_line(another_file, 100_000)).to eq(3) expect(world.preceding_declaration_line(__FILE__, group_declaration_line + 1)).to eq(group_declaration_line) end end end describe '#source_from_file' do it 'caches Source instances by file path' do expect(world.source_from_file(__FILE__)).to be_a(RSpec::Support::Source). and have_attributes(:path => __FILE__). and equal(world.source_from_file(__FILE__)) end end describe '#syntax_highlighter' do it 'returns a memoized SyntaxHighlighter' do expect(world.syntax_highlighter).to be_a(RSpec::Core::Formatters::SyntaxHighlighter). and equal(world.syntax_highlighter) end end describe "#announce_filters" do let(:reporter) { instance_spy(Reporter) } before { allow(world).to receive(:reporter) { reporter } } context "when --only-failures is passed" do before { configuration.force(:only_failures => true) } context "and all examples are filtered out" do before do configuration.filter_run_including :foo => 'bar' end it 'will ignore run_all_when_everything_filtered' do configuration.run_all_when_everything_filtered = true expect(world.filtered_examples).to_not receive(:clear) expect(world.inclusion_filter).to_not receive(:clear) world.announce_filters end end context "and `example_status_persistence_file_path` is not configured" do it 'aborts with a message explaining the config option must be set first' do configuration.example_status_persistence_file_path = nil world.announce_filters expect(reporter).to have_received(:abort_with).with(/example_status_persistence_file_path/, 1) end end context "and `example_status_persistence_file_path` is configured" do it 'does not abort' do configuration.example_status_persistence_file_path = "foo.txt" world.announce_filters expect(reporter).not_to have_received(:abort_with) end end end context "when --only-failures is not passed" do before { expect(configuration.only_failures?).not_to eq true } context "and `example_status_persistence_file_path` is not configured" do it 'does not abort' do configuration.example_status_persistence_file_path = nil world.announce_filters expect(reporter).not_to have_received(:abort_with) end end context "and `example_status_persistence_file_path` is configured" do it 'does not abort' do configuration.example_status_persistence_file_path = "foo.txt" world.announce_filters expect(reporter).not_to have_received(:abort_with) end end end context "with no examples" do before { allow(world).to receive(:example_count) { 0 } } context "with no filters" do it "announces" do expect(reporter).to receive(:message). with("No examples found.") world.announce_filters end end context "with an inclusion filter" do it "announces" do configuration.filter_run_including :foo => 'bar' expect(reporter).to receive(:message). with(/All examples were filtered out/) world.announce_filters end end context "with an inclusion filter and run_all_when_everything_filtered" do it "announces" do allow(configuration).to receive(:run_all_when_everything_filtered?) { true } configuration.filter_run_including :foo => 'bar' expect(reporter).to receive(:message). with(/All examples were filtered out/) world.announce_filters end end context "with an exclusion filter" do it "announces" do configuration.filter_run_excluding :foo => 'bar' expect(reporter).to receive(:message). with(/All examples were filtered out/) world.announce_filters end end context "with a filter but with silence_filter_announcements" do it "does not announce" do configuration.silence_filter_announcements = true configuration.filter_run_including :foo => 'bar' expect(reporter).to_not receive(:message) world.announce_filters end end end context "with examples" do before { allow(world).to receive(:example_count) { 1 } } context "with no filters" do it "does not announce" do expect(reporter).not_to receive(:message) world.announce_filters end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/0000775000000000000000000000000014557677674024045 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/deprecation_formatter_spec.rb0000664000000000000000000002377414557677674032001 0ustar rootrootrequire 'rspec/core/reporter' require 'rspec/core/formatters/deprecation_formatter' require 'tempfile' module RSpec::Core::Formatters RSpec.describe DeprecationFormatter do include FormatterSupport let(:summary_stream) { StringIO.new } def notification(hash) ::RSpec::Core::Notifications::DeprecationNotification.from_hash(hash) end before do setup_reporter deprecation_stream, summary_stream end describe "#deprecation" do context "with a File deprecation_stream", :slow do let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w+") } it "prints a message if provided, ignoring other data" do send_notification :deprecation, notification(:message => "this message", :deprecated => "x", :replacement => "y", :call_site => "z") deprecation_stream.rewind expect(deprecation_stream.read).to eq "this message\n" end it "surrounds multiline messages in fenceposts" do multiline_message = <<-EOS.gsub(/^\s+\|/, '') |line one |line two EOS send_notification :deprecation, notification(:message => multiline_message) deprecation_stream.rewind expected = <<-EOS.gsub(/^\s+\|/, '') |-------------------------------------------------------------------------------- |line one |line two |-------------------------------------------------------------------------------- EOS expect(deprecation_stream.read).to eq expected end it "includes the method" do send_notification :deprecation, notification(:deprecated => "i_am_deprecated") deprecation_stream.rewind expect(deprecation_stream.read).to match(/i_am_deprecated is deprecated/) end it "includes the replacement" do send_notification :deprecation, notification(:replacement => "use_me") deprecation_stream.rewind expect(deprecation_stream.read).to match(/Use use_me instead/) end it "includes the call site if provided" do send_notification :deprecation, notification(:call_site => "somewhere") deprecation_stream.rewind expect(deprecation_stream.read).to match(/Called from somewhere/) end end context "with an IO deprecation stream" do let(:deprecation_stream) { StringIO.new } it "prints nothing" do 5.times { send_notification :deprecation, notification(:deprecated => 'i_am_deprecated') } expect(deprecation_stream.string).to eq "" end end end describe "#deprecation_summary" do let(:summary) { double } context "with a File deprecation_stream", :slow do let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w") } it "prints a count of the deprecations" do send_notification :deprecation, notification(:deprecated => 'i_am_deprecated') send_notification :deprecation_summary, null_notification expect(summary_stream.string).to match(/1 deprecation logged to .*deprecation_summary_example_output/) end it "pluralizes the reported deprecation count for more than one deprecation" do send_notification :deprecation, notification(:deprecated => 'i_am_deprecated') send_notification :deprecation, notification(:deprecated => 'i_am_deprecated_also') send_notification :deprecation_summary, null_notification expect(summary_stream.string).to match(/2 deprecations/) end it "is not printed when there are no deprecations" do send_notification :deprecation_summary, null_notification expect(summary_stream.string).to eq "" end it 'uses synchronized/non-buffered output to work around odd duplicate output behavior we have observed' do expect { send_notification :deprecation, notification(:deprecated => 'foo') }.to change { deprecation_stream.sync }.from(false).to(true) end it 'does not print duplicate messages' do 3.times { send_notification :deprecation, notification(:deprecated => 'foo') } send_notification :deprecation_summary, null_notification expect(summary_stream.string).to match(/1 deprecation/) expect(File.read(deprecation_stream.path)).to eq("foo is deprecated.\n#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}") end it "can handle when the stream is reopened to a system stream", :unless => RSpec::Support::OS.windows? do send_notification :deprecation, notification(:deprecated => 'foo') deprecation_stream.reopen(IO.for_fd(IO.sysopen('/dev/null', "w+"))) send_notification :deprecation_summary, null_notification end end context "with an Error deprecation_stream" do let(:deprecation_stream) { DeprecationFormatter::RaiseErrorStream.new } it 'prints a summary of the number of deprecations found' do expect { send_notification :deprecation, notification(:deprecated => 'foo') }.to raise_error(RSpec::Core::DeprecationError) send_notification :deprecation_summary, null_notification expect(summary_stream.string).to eq("\n1 deprecation found.\n") end it 'pluralizes the count when it is greater than 1' do expect { send_notification :deprecation, notification(:deprecated => 'foo') }.to raise_error(RSpec::Core::DeprecationError) expect { send_notification :deprecation, notification(:deprecated => 'bar') }.to raise_error(RSpec::Core::DeprecationError) send_notification :deprecation_summary, null_notification expect(summary_stream.string).to eq("\n2 deprecations found.\n") end end context "with an IO deprecation_stream" do let(:deprecation_stream) { StringIO.new } it "groups similar deprecations together" do send_notification :deprecation, notification(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:1") send_notification :deprecation, notification(:deprecated => 'i_am_a_different_deprecation') send_notification :deprecation, notification(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:2") send_notification :deprecation_summary, null_notification expected = <<-EOS.gsub(/^\s+\|/, '') | |Deprecation Warnings: | |i_am_a_different_deprecation is deprecated. | |i_am_deprecated is deprecated. Called from foo.rb:1. |i_am_deprecated is deprecated. Called from foo.rb:2. | |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE} EOS expect(deprecation_stream.string).to eq expected.chomp end it "limits the deprecation warnings after 3 calls" do 5.times { |i| send_notification :deprecation, notification(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") } send_notification :deprecation_summary, null_notification expected = <<-EOS.gsub(/^\s+\|/, '') | |Deprecation Warnings: | |i_am_deprecated is deprecated. Called from foo.rb:1. |i_am_deprecated is deprecated. Called from foo.rb:2. |i_am_deprecated is deprecated. Called from foo.rb:3. |Too many uses of deprecated 'i_am_deprecated'. #{DeprecationFormatter::DEPRECATION_STREAM_NOTICE} | |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE} EOS expect(deprecation_stream.string).to eq expected.chomp end it "limits :message deprecation warnings with different callsites after 3 calls" do 5.times do |n| message = "This is a long string with some callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff can come after." send_notification :deprecation, notification(:message => message) end send_notification :deprecation_summary, null_notification expected = <<-EOS.gsub(/^\s+\|/, '') | |Deprecation Warnings: | |This is a long string with some callsite info: /path/0/to/some/file.rb:203. And some more stuff can come after. |This is a long string with some callsite info: /path/1/to/some/file.rb:213. And some more stuff can come after. |This is a long string with some callsite info: /path/2/to/some/file.rb:223. And some more stuff can come after. |Too many similar deprecation messages reported, disregarding further reports. #{DeprecationFormatter::DEPRECATION_STREAM_NOTICE} | |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE} EOS expect(deprecation_stream.string).to eq expected.chomp end it "prints the true deprecation count to the summary_stream" do 5.times { |i| send_notification :deprecation, notification(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") } 5.times do |n| send_notification :deprecation, notification(:message => "callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff") end send_notification :deprecation_summary, null_notification expect(summary_stream.string).to match(/10 deprecation warnings total/) end it 'does not print duplicate messages' do 3.times { send_notification :deprecation, notification(:deprecated => 'foo') } send_notification :deprecation_summary, null_notification expect(summary_stream.string).to match(/1 deprecation/) expected = <<-EOS.gsub(/^\s+\|/, '') | |Deprecation Warnings: | |foo is deprecated. | |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE} EOS expect(deprecation_stream.string).to eq expected.chomp end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/helpers_spec.rb0000664000000000000000000001046114557677674027050 0ustar rootrootrequire 'rspec/core/formatters/helpers' RSpec.describe RSpec::Core::Formatters::Helpers do helper = described_class describe "format duration" do context '< 1' do it "returns '0.xxxxx seconds' formatted string" do expect(helper.format_duration(0.123456)).to eq("0.12346 seconds") end end context '> 1 and < 60' do it "returns 'xx.xx seconds' formatted string" do expect(helper.format_duration(45.51)).to eq("45.51 seconds") end end context '> 60 and < 120' do it "returns 'x minute xx.xx seconds' formatted string" do expect(helper.format_duration(70.14)).to eq("1 minute 10.14 seconds") end end context '> 120 and < 300' do it "returns 'x minutes xx.x seconds' formatted string" do expect(helper.format_duration(135.14)).to eq("2 minutes 15.1 seconds") end end context '> 300' do it "returns 'x minutes xx seconds' formatted string" do expect(helper.format_duration(315.14)).to eq("5 minutes 15 seconds") expect(helper.format_duration(335.14)).to eq("5 minutes 35 seconds") end it "returns 'x minutes xx seconds' correctly on edgecase roundings" do expect(helper.format_duration(359.111111111111)).to eq("5 minutes 59 seconds") expect(helper.format_duration(359.999999999999)).to eq("6 minutes 0 seconds") end end context '= 61' do it "returns 'x minute x second' formatted string" do expect(helper.format_duration(61)).to eq("1 minute 1 second") end end context '= 1' do it "returns 'x second' formatted string" do expect(helper.format_duration(1)).to eq("1 second") end end context '= 70' do it "returns 'x minute, x0 seconds' formatted string" do expect(helper.format_duration(70)).to eq("1 minute 10 seconds") end end context 'with mathn loaded' do include MathnIntegrationSupport it "returns 'x minutes xx.x seconds' formatted string", :slow do with_mathn_loaded do expect(helper.format_duration(133.7)).to eq("2 minutes 13.7 seconds") end end end end describe "format seconds" do it "uses passed in precision if specified unless result is 0" do expect(helper.format_seconds(0.01234, 2)).to eq("0.01") end context "sub second times" do it "returns 5 digits of precision" do expect(helper.format_seconds(0.000006)).to eq("0.00001") end it "strips off trailing zeroes beyond sub-second precision" do expect(helper.format_seconds(0.020000)).to eq("0.02") end context "0" do it "strips off trailing zeroes" do expect(helper.format_seconds(0.00000000001)).to eq("0") end end context "> 1" do it "strips off trailing zeroes" do expect(helper.format_seconds(1.00000000001)).to eq("1") end end context "70" do it "doesn't strip of meaningful trailing zeros" do expect(helper.format_seconds(70)).to eq("70") end end end context "second and greater times" do it "returns 2 digits of precision" do expect(helper.format_seconds(50.330340)).to eq("50.33") end it "returns human friendly elapsed time" do expect(helper.format_seconds(50.1)).to eq("50.1") expect(helper.format_seconds(5)).to eq("5") expect(helper.format_seconds(5.0)).to eq("5") end end end describe "pluralize" do context "when word does not end in s" do let(:word){ "second" } it "pluralizes with 0" do expect(helper.pluralize(0, "second")).to eq("0 seconds") end it "does not pluralizes with 1" do expect(helper.pluralize(1, "second")).to eq("1 second") end it "pluralizes with 2" do expect(helper.pluralize(2, "second")).to eq("2 seconds") end end context "when word ends in s" do let(:word){ "process" } it "pluralizes with 0" do expect(helper.pluralize(0, "process")).to eq("0 processes") end it "does not pluralizes with 1" do expect(helper.pluralize(1, "process")).to eq("1 process") end it "pluralizes with 2" do expect(helper.pluralize(2, "process")).to eq("2 processes") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/console_codes_spec.rb0000664000000000000000000000523514557677674030230 0ustar rootrootrequire 'rspec/core/formatters/console_codes' RSpec.describe "RSpec::Core::Formatters::ConsoleCodes" do let(:console_codes) { RSpec::Core::Formatters::ConsoleCodes } describe "#console_code_for(code_or_symbol)" do context "when given a VT100 integer code" do it "returns the code" do expect(console_codes.console_code_for(32)).to eq 32 end end context "when given a VT100 compound code" do it "returns the code" do expect(console_codes.console_code_for('1;32')).to eq '1;32' end end context "when given a symbolic name" do it "returns the code" do expect(console_codes.console_code_for(:green)).to eq 32 end end context "when given an rspec code" do it "returns the console code" do RSpec.configuration.success_color = :blue # blue is 34 expect(console_codes.console_code_for(:success)).to eq 34 end end context "when given a nonexistant code" do it "returns the code for white" do expect(console_codes.console_code_for(:octarine)).to eq 37 end end end describe "#wrap" do before do allow(RSpec.configuration).to receive(:color_enabled?) { true } end context "when given a VT100 integer code" do it "formats the text with it" do expect(console_codes.wrap('abc', 32)).to eq "\e[32mabc\e[0m" end end context "when given a VT100 compound code" do it "formats the text with it" do expect(console_codes.wrap('abc', '1;32')).to eq "\e[1;32mabc\e[0m" end end context "when given a symbolic color name" do it "translates it to the correct integer code and formats the text with it" do expect(console_codes.wrap('abc', :green)).to eq "\e[32mabc\e[0m" end end context "when given a symbolic bold color name" do it "translates it to the correct integer code and formats the text with it" do expect(console_codes.wrap('abc', :bold_green)).to eq "\e[1;32mabc\e[0m" end end context "when given an rspec code" do it "returns the console code" do RSpec.configuration.success_color = :blue # blue is 34 expect(console_codes.wrap('abc', :success)).to eq "\e[34mabc\e[0m" end end context "when given a compound rspec code" do it "returns the console code" do RSpec.configuration.success_color = :bold_blue # blue is 34 expect(console_codes.wrap('abc', :success)).to eq "\e[1;34mabc\e[0m" end end context "when given :bold" do it "formats the text as bold" do expect(console_codes.wrap('abc', :bold)).to eq "\e[1mabc\e[0m" end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/exception_presenter_spec.rb0000664000000000000000000011033214557677674031471 0ustar rootroot# encoding: utf-8 require 'pathname' module RSpec::Core RSpec.describe Formatters::ExceptionPresenter do include FormatterSupport let(:example) { new_example } let(:presenter) { Formatters::ExceptionPresenter.new(exception, example) } before do allow(example.execution_result).to receive(:exception) { exception } example.metadata[:absolute_file_path] = __FILE__ end # This is a slightly more realistic exception than our instance_double # created, as this will behave correctly with `Exception#===`, note we # monkey patch the backtrace / cause in because these are not public # api but we need specific values for our fakes. class FakeException < Exception def initialize(message, backtrace = [], cause = nil) super(message) @backtrace = backtrace @cause = cause end attr_reader :backtrace if RSpec::Support::RubyFeatures.supports_exception_cause? attr_accessor :cause end end describe "#fully_formatted" do if RSpec::Support::OS.windows? let(:encoding_check) { '' } line_num = __LINE__ + 1 # The failure happened here! it 'should check that output is not mangled' else let(:encoding_check) { ' Handles encoding too! ЙЦ' } line_num = __LINE__ + 1 # The failure happened here! Handles encoding too! ЙЦ end let(:exception) { FakeException.new("Boom\nBam", [ "#{__FILE__}:#{line_num}"]) } it "formats the exception with all the normal details" do expect(presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it "indents properly when given a multiple-digit failure index" do expect(presenter.fully_formatted(100)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 100) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it "prints no identifier when no number argument is given" do expect(presenter.fully_formatted(nil)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it "allows the caller to specify additional indentation" do the_presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 4) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it 'aligns lines' do detail_formatter = Proc.new { "Some Detail" } the_presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 4, :detail_formatter => detail_formatter) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Some Detail | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end if String.method_defined?(:encoding) && !RSpec::Support::OS.windows? it 'allows the caller to add encoded description' do the_presenter = Formatters::ExceptionPresenter.new(exception, example, :description => "ジ".encode("CP932")) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) ジ | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end end it 'allows the caller to omit the description' do the_presenter = Formatters::ExceptionPresenter.new(exception, example, :detail_formatter => Proc.new { "Detail!" }, :description => nil) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Detail! | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it 'allows the failure/error line to be used as the description' do the_presenter = Formatters::ExceptionPresenter.new(exception, example, :description => nil) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it 'allows a caller to specify extra details that are added to the bottom' do the_presenter = Formatters::ExceptionPresenter.new( exception, example, :extra_detail_formatter => lambda do |failure_number, colorizer| "extra detail for failure: #{failure_number}" end ) expect(the_presenter.fully_formatted(2)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 2) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | extra detail for failure: 2 EOS end let(:the_exception) { FakeException.new("Boom\nBam", [ "#{__FILE__}:#{line_num}"], second_exception) } let(:second_exception) do FakeException.new("Second\nexception", ["#{__FILE__}:#{__LINE__}"], first_exception) end caused_by_line_num = __LINE__ + 1 let(:first_exception) { FakeException.new("Real\nculprit", ["#{__FILE__}:#{__LINE__}", "#{__FILE__}:#{__LINE__}"]) } it 'includes the first exception that caused the failure', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do the_presenter = Formatters::ExceptionPresenter.new(the_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | # ------------------ | # --- Caused by: --- | # Real | # culprit | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{caused_by_line_num} EOS end context 'with RSpec.configuration.full_cause_backtrace enabled' do before do RSpec.configuration.full_cause_backtrace = true end it 'prints full cause backtrace', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do the_presenter = Formatters::ExceptionPresenter.new(the_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | # ------------------ | # --- Caused by: --- | # Real | # culprit | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{caused_by_line_num} | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{caused_by_line_num} EOS end end context "when the first exception doesn't have a backgrace" do let(:first_exception) { FakeException.new("Real\nculprit", backtrace) } shared_examples 'expected result for the case when there is no backtrace' do it 'wont fail for the exception with a nil backtrace', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do the_presenter = Formatters::ExceptionPresenter.new(the_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | # ------------------ | # --- Caused by: --- | # Real | # culprit EOS end end context 'when backtrace is []' do let(:backtrace) { [] } it_behaves_like 'expected result for the case when there is no backtrace' end context 'when backtrace is nil' do let(:backtrace) { nil } it_behaves_like 'expected result for the case when there is no backtrace' end end it 'wont produce a stack error when cause is the exception itself', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do allow(the_exception).to receive(:cause) { the_exception } the_presenter = Formatters::ExceptionPresenter.new(the_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | # ------------------ | # --- Caused by: --- | # Boom | # Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it 'wont produce a stack error when the cause is an older exception', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do allow(the_exception).to receive(:cause) do FakeException.new("A loop", the_exception.backtrace, the_exception) end the_presenter = Formatters::ExceptionPresenter.new(the_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} | # ------------------ | # --- Caused by: --- | # A loop | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it 'will work when cause is incorrectly overridden', :if => RSpec::Support::RubyFeatures.supports_exception_cause? do incorrect_cause_exception = FakeException.new("A badly implemented exception", [], "An incorrect cause") the_presenter = Formatters::ExceptionPresenter.new(incorrect_cause_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: Unable to find matching line from backtrace | A badly implemented exception | # ------------------ | # --- Caused by: --- | # A badly implemented exception EOS end it 'will work then the message to_s raises a looped exception' do raising_to_s_klass = Class.new do def to_s raise StandardError, self end end if RSpec::Support::Ruby.jruby? expected_error = Java::JavaLang::StackOverflowError else expected_error = StandardError end incorrect_message_exception = FakeException.new(raising_to_s_klass.new, []) the_presenter = Formatters::ExceptionPresenter.new(incorrect_message_exception, example) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: Unable to find matching line from backtrace | A #{FakeException} for which `exception.message.to_s` raises #{expected_error}. EOS end it "adds extra failure lines from the example metadata" do extra_example = example.clone failure_line = 'http://www.example.com/job_details/123' extra_example.metadata[:extra_failure_lines] = [failure_line] the_presenter = Formatters::ExceptionPresenter.new(exception, extra_example, :indentation => 4) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | | #{failure_line} | | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end it "wont add extra blank lines around extra failure lines when lines are already padded" do extra_example = example.clone failure_line = 'http://www.example.com/job_details/123' extra_example.metadata[:extra_failure_lines] = ['', failure_line, ''] the_presenter = Formatters::ExceptionPresenter.new(exception, extra_example, :indentation => 4) expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, '')) | | 1) Example | Failure/Error: # The failure happened here!#{ encoding_check } | | Boom | Bam | | #{failure_line} | | # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num} EOS end describe 'line format' do let(:exception) do begin expression rescue RSpec::Support::AllExceptionsExceptOnesWeMustNotRescue => exception exception end end describe "syntax highlighting" do let(:expression) do expect('RSpec').to be_a(Integer) end it 'uses our syntax highlighter on the code snippet to format it nicely' do syntax_highlighter = instance_double(Formatters::SyntaxHighlighter) allow(syntax_highlighter).to receive(:highlight) do |lines| lines.map { |l| "#{l.strip}" } end allow(RSpec.world).to receive_messages(:syntax_highlighter => syntax_highlighter) formatted = presenter.fully_formatted(1) expect(formatted).to include("expect('RSpec').to be_a(Integer)") end end context 'with single line expression and single line RSpec exception message' do let(:expression) do expect('RSpec').to be_a(Integer) end it 'crams them without blank line' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: expect('RSpec').to be_a(Integer) | expected "RSpec" to be a kind of Integer | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with multiline expression and single line RSpec exception message', :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:expression) do expect('RSpec'). to be_a(Integer) end it 'inserts a blank line between the expression and the message' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: | expect('RSpec'). | to be_a(Integer) | | expected "RSpec" to be a kind of Integer | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with single line expression and multiline RSpec exception message' do let(:expression) do expect('RSpec').to be_falsey end it 'inserts a blank line between the expression and the message' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: expect('RSpec').to be_falsey | | expected: falsey value | got: "RSpec" | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with multiline expression and multiline RSpec exception message', :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:expression) do expect('RSpec'). to be_falsey end it 'inserts a blank line between the expression and the message' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: | expect('RSpec'). | to be_falsey | | expected: falsey value | got: "RSpec" | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with single line expression and RSpec exception message starting with linefeed (like `eq` matcher)' do let(:expression) do expect('Rspec').to eq('RSpec') end it 'does not insert a superfluous blank line' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: expect('Rspec').to eq('RSpec') | | expected: "RSpec" | got: "Rspec" | | (compared using ==) | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with multiline expression and RSpec exception message starting with linefeed (like `eq` matcher)', :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:expression) do expect('Rspec'). to eq('RSpec') end it 'does not insert a superfluous blank line' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: | expect('Rspec'). | to eq('RSpec') | | expected: "RSpec" | got: "Rspec" | | (compared using ==) | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with single line expression and single line non-RSpec exception message' do let(:expression) do expect { fail 'Something is wrong!' }.to change { RSpec } end it 'inserts a blank line between the expression and the message' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: expect { fail 'Something is wrong!' }.to change { RSpec } | | RuntimeError: | Something is wrong! | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end context 'with multiline expression and single line non-RSpec exception message', :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:expression) do expect { fail 'Something is wrong!' }. to change { RSpec } end it 'inserts a blank line between the expression and the message' do expect(presenter.fully_formatted(1)).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | | 1) Example | Failure/Error: | expect { fail 'Something is wrong!' }. | to change { RSpec } | | RuntimeError: | Something is wrong! | # ./spec/rspec/core/formatters/exception_presenter_spec.rb: EOS end end end end describe "#read_failed_lines" do def read_failed_lines presenter.send(:read_failed_lines) end context 'when the failed expression spans multiple lines', :if => RSpec::Support::RubyFeatures.ripper_supported? do let(:exception) do begin expect('RSpec').to be_a(String). and start_with('R'). and end_with('z') rescue RSpec::Expectations::ExpectationNotMetError => exception exception end end context 'and the line count does not exceed RSpec.configuration.max_displayed_failure_line_count' do it 'returns all the lines' do if RSpec::Support::Ruby.jruby_9000? && RSpec::Support::Ruby.jruby_version < '9.2.0.0' pending 'https://github.com/jruby/jruby/issues/4737' end expect(read_failed_lines).to eq([ " expect('RSpec').to be_a(String).", " and start_with('R').", " and end_with('z')" ]) end end context 'and the line count exceeds RSpec.configuration.max_displayed_failure_line_count' do before do RSpec.configuration.max_displayed_failure_line_count = 2 end it 'returns the lines without exceeding the max count' do if RSpec::Support::Ruby.jruby_9000? && RSpec::Support::Ruby.jruby_version < '9.2.0.0' pending 'https://github.com/jruby/jruby/issues/4737' end expect(read_failed_lines).to eq([ " expect('RSpec').to be_a(String).", " and start_with('R')." ]) end end end context "when backtrace is a heterogeneous language stack trace" do let(:exception) do instance_double(Exception, :backtrace => [ "at Object.prototypeMethod (foo:331:18)", "at Array.forEach (native)", "at a_named_javascript_function (/some/javascript/file.js:39:5)", "/some/line/of/ruby.rb:14" ]) end it "is handled gracefully" do expect { read_failed_lines }.not_to raise_error end end context "when backtrace will generate a security error" do let(:exception) { instance_double(Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"]) } it "is handled gracefully" do expect { with_safe_set_to_level_that_triggers_security_errors { read_failed_lines } }.not_to raise_error end end context "when ruby reports a bogus line number in the stack trace" do let(:exception) { instance_double(Exception, :backtrace => [ "#{__FILE__}:10000000"]) } it "reports the filename and that it was unable to find the matching line" do expect(read_failed_lines.first).to include("Unable to find matching line") end end context "when the stack trace is from a java exception" do let(:exception) { instance_double(Exception, :backtrace => [ "org.jruby.SomeJavaException(Unknown Source)"]) } it "reports that it was unable to infer a code location from the backtrace" do expect(read_failed_lines.first).to include("Unable to infer file and line number from backtrace") end end context "when ruby reports a file that does not exist" do let(:file) { "#{__FILE__}/blah.rb" } let(:exception) { instance_double(Exception, :backtrace => [ "#{file}:1"]) } it "reports the filename and that it was unable to find the matching line" do example.metadata[:absolute_file_path] = file expect(read_failed_lines.first).to include("Unable to find #{file} to read failed line") end end context "when the stacktrace includes relative paths (which can happen when using `rspec/autorun` and running files through `ruby`)" do let(:relative_file) { Pathname(__FILE__).relative_path_from(Pathname(Dir.pwd)) } line = __LINE__ let(:exception) { instance_double(Exception, :backtrace => ["#{relative_file}:#{line}"]) } it 'still finds the backtrace line' do expect(read_failed_lines.first).to include("line = __LINE__") end end context "when String alias to_int to_i" do before do String.class_exec do alias :to_int :to_i end end after do String.class_exec do undef to_int end end let(:exception) { instance_double(Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"]) } it "doesn't hang when file exists" do expect(read_failed_lines.first.strip).to eql( %Q[let(:exception) { instance_double(Exception, :backtrace => [ "\#{__FILE__}:\#{__LINE__}"]) }]) end end end end RSpec.describe Formatters::ExceptionPresenter::Factory::CommonBacktraceTruncater do def truncate(parent, child) described_class.new(parent).with_truncated_backtrace(child) end def exception_with(backtrace) exception = Exception.new exception.set_backtrace(backtrace) exception end it 'returns an exception with the common part truncated' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 ] child = exception_with %w[ file_1.rb:3 file_1.rb:9 foo.rb:1 bar.rb:2 car.rb:7 ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ file_1.rb:3 file_1.rb:9 ] end it 'ignores excess lines in the top of the parent trace that the child does not have' do parent = exception_with %w[ foo.rb:1 foo.rb:2 foo.rb:3 bar.rb:2 car.rb:7 ] child = exception_with %w[ file_1.rb:3 file_1.rb:9 bar.rb:2 car.rb:7 ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ file_1.rb:3 file_1.rb:9 ] end it 'does not truncate anything if the parent has excess lines at the bottom of the trace' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 bazz.rb:9 ] child = exception_with %w[ file_1.rb:3 file_1.rb:9 foo.rb:1 bar.rb:2 car.rb:7 ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ file_1.rb:3 file_1.rb:9 foo.rb:1 bar.rb:2 car.rb:7 ] end it 'does not mutate the provided exception' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 ] child = exception_with %w[ file_1.rb:3 file_1.rb:9 foo.rb:1 bar.rb:2 car.rb:7 ] expect { truncate(parent, child) }.not_to change(child, :backtrace) end it 'returns an exception with all the same attributes (except backtrace) as the provided one' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 ] my_custom_exception_class = Class.new(StandardError) do attr_accessor :foo, :bar end child = my_custom_exception_class.new("Some Message") child.foo = 13 child.bar = 20 child.set_backtrace(%w[ foo.rb:1 ]) truncated = truncate(parent, child) expect(truncated).to have_attributes( :message => "Some Message", :foo => 13, :bar => 20 ) end it 'handles child exceptions that have a blank array for the backtrace' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 ] child = exception_with %w[ ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ ] end it 'handles child exceptions that have `nil` for the backtrace' do parent = exception_with %w[ foo.rb:1 bar.rb:2 car.rb:7 ] child = Exception.new truncated = truncate(parent, child) expect(truncated.backtrace).to be_nil end it 'handles parent exceptions that have a blank array for the backtrace' do parent = exception_with %w[ ] child = exception_with %w[ foo.rb:1 ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ foo.rb:1 ] end it 'handles parent exceptions that have `nil` for the backtrace' do parent = Exception.new child = exception_with %w[ foo.rb:1 ] truncated = truncate(parent, child) expect(truncated.backtrace).to eq %w[ foo.rb:1 ] end it 'returns the original exception object (not a dup) when there is no need to update the backtrace' do parent = exception_with %w[ bar.rb:1 ] child = exception_with %w[ foo.rb:1 ] truncated = truncate(parent, child) expect(truncated).to be child end it 'returns the original exception object when parent and child have the same files' do parent = exception_with %w[ bar.rb:1 ] child = exception_with %w[ bar.rb:1 ] truncated = truncate(parent, child) expect(truncated).to be child end end RSpec.shared_examples_for "a class satisfying the common multiple exception error interface" do def new_failure(*a) RSpec::Expectations::ExpectationNotMetError.new(*a) end def new_error(*a) StandardError.new(*a) end it 'allows you to keep track of failures and other errors in order' do mee = new_multiple_exception_error f1 = new_failure e1 = new_error f2 = new_failure expect { mee.add(f1) }.to change(mee, :failures).to [f1] expect { mee.add(e1) }.to change(mee, :other_errors).to [e1] expect { mee.add(f2) }.to change(mee, :failures).to [f1, f2] expect(mee.all_exceptions).to eq([f1, e1, f2]) end it 'allows you to add exceptions of an anonymous class' do mee = new_multiple_exception_error expect { mee.add(Class.new(StandardError).new) }.to change(mee.other_errors, :count).by 1 end it 'ignores `Pending::PendingExampleFixedError` since it does not represent a real failure but rather the lack of one' do mee = new_multiple_exception_error expect { mee.add Pending::PendingExampleFixedError.new }.to avoid_changing(mee.other_errors, :count). and avoid_changing(mee.all_exceptions, :count). and avoid_changing(mee.failures, :count) end it 'is tagged with a common module so it is clear it has the interface for multiple exceptions' do expect(MultipleExceptionError::InterfaceTag).to be === new_multiple_exception_error end end RSpec.describe RSpec::Expectations::ExpectationNotMetError do include_examples "a class satisfying the common multiple exception error interface" do def new_multiple_exception_error failure_aggregator = RSpec::Expectations::FailureAggregator.new(nil, {}) RSpec::Expectations::MultipleExpectationsNotMetError.new(failure_aggregator) end end end RSpec.describe MultipleExceptionError do include_examples "a class satisfying the common multiple exception error interface" do def new_multiple_exception_error MultipleExceptionError.new end end it "does not let you add itself to the list of all_exceptions" do m = MultipleExceptionError.new m.add(m) expect(m.all_exceptions).to_not include(m) end it 'supports the same interface as `RSpec::Expectations::MultipleExpectationsNotMetError`' do skip "Skipping to allow an rspec-expectations PR to add a new method and remain green" if ENV['NEW_MUTLI_EXCEPTION_METHOD'] aggregate_failures { } # force autoload interface = RSpec::Expectations::MultipleExpectationsNotMetError.instance_methods - Exception.instance_methods expect(MultipleExceptionError.new).to respond_to(*interface) end it 'allows you to instantiate it with an initial list of exceptions' do mee = MultipleExceptionError.new(f1 = new_failure, e1 = new_error) expect(mee).to have_attributes( :failures => [f1], :other_errors => [e1], :all_exceptions => [f1, e1] ) end specify 'the `message` implementation provides all failure messages, but is not well formatted because we do not actually use it' do mee = MultipleExceptionError.new( new_failure("failure 1"), new_error("error 1") ) expect(mee.message).to include("failure 1", "error 1") end it 'provides a description of the exception counts, correctly categorized as failures or exceptions' do mee = MultipleExceptionError.new expect { mee.add new_failure mee.add new_error }.to change(mee, :exception_count_description). from("0 failures"). to("1 failure and 1 other error") expect { mee.add new_failure mee.add new_error }.to change(mee, :exception_count_description). to("2 failures and 2 other errors") end it 'provides a summary of the exception counts' do mee = MultipleExceptionError.new expect { mee.add new_failure mee.add new_error }.to change(mee, :summary). from("Got 0 failures"). to("Got 1 failure and 1 other error") expect { mee.add new_failure mee.add new_error }.to change(mee, :summary). to("Got 2 failures and 2 other errors") end it 'presents the same aggregation metadata that an `:aggregate_failures`-tagged example produces' do ex = nil RSpec.describe do ex = it "", :aggregate_failures do expect(1).to eq(2) expect(1).to eq(2) end end.run expected_metadata = ex.exception.aggregation_metadata expect(MultipleExceptionError.new.aggregation_metadata).to eq(expected_metadata) end describe "::InterfaceTag.for" do def value_for(ex) described_class::InterfaceTag.for(ex) end context "when given an `#{described_class.name}`" do it 'returns the provided error' do ex = MultipleExceptionError.new expect(value_for ex).to be ex end end context "when given an `RSpec::Expectations::MultipleExpectationsNotMetError`" do it 'returns the provided error' do failure_aggregator = RSpec::Expectations::FailureAggregator.new(nil, {}) ex = RSpec::Expectations::MultipleExpectationsNotMetError.new(failure_aggregator) expect(value_for ex).to be ex end end context "when given any other exception" do it 'wraps it in a `RSpec::Expectations::MultipleExceptionError`' do ex = StandardError.new expect(value_for ex).to be_a(MultipleExceptionError).and have_attributes(:all_exceptions => [ex]) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/snippet_extractor_spec.rb0000664000000000000000000002544514557677674031173 0ustar rootrootrequire 'rspec/core/formatters/snippet_extractor' require 'support/helper_methods' module RSpec::Core::Formatters RSpec.describe SnippetExtractor do include RSpecHelpers subject(:expression_lines) do SnippetExtractor.extract_expression_lines_at(file_path, line_number, max_line_count) end let(:file_path) do location[0] end let(:line_number) do location[1] end let(:location) do error.backtrace.find do |line| !line.include?('do_something_fail') && line.match(%r{\A(.+?):(\d+)}) end location = Regexp.last_match.captures location[1] = location[1].to_i location end let(:max_line_count) do nil end let(:error) do begin source rescue => error error else raise 'No error has been raised' end end # We use this helper method to raise an error while allowing any arguments, # # Note that MRI 1.9 strangely reports backtrace line as the first argument line instead of the # beginning of the method invocation. It's not SnippetExtractor's fault and even affects to the # simple single line extraction. def do_something_fail(*) raise end def another_expression(*) end context 'when the given file does not exist' do let(:file_path) do '/non-existent.rb' end let(:line_number) do 1 end it 'raises NoSuchFileError' do expect { expression_lines }.to raise_error(SnippetExtractor::NoSuchFileError) end end context 'when the given line does not exist in the file' do let(:file_path) do __FILE__ end let(:line_number) do 99999 end it 'raises NoSuchLineError' do expect { expression_lines }.to raise_error(SnippetExtractor::NoSuchLineError) end end context 'when the expression fits into a single line' do let(:source) do do_something_fail :foo end it 'returns the line' do expect(expression_lines).to eq([ ' do_something_fail :foo' ]) end end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do context 'when the expression spans multiple lines' do let(:source) do do_something_fail :foo, :bar end it 'returns the lines' do expect(expression_lines).to eq([ ' do_something_fail :foo,', ' :bar' ]) end end context 'when the expression ends with ")"-only line' do let(:source) do do_something_fail(:foo ) end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail(:foo', ' )' ]) end end context 'when the expression ends with "}"-only line' do let(:source) do do_something_fail { } end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail {', ' }' ]) end end context 'when the expression ends with "]"-only line' do let(:source) do do_something_fail :foo, [ ] end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail :foo, [', ' ]' ]) end end context 'when the expression contains do-end block and ends with "end"-only line' do let(:source) do do_something_fail do end end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail do', ' end' ]) end end argument_error_points_invoker = RSpec::Support::Ruby.jruby? && !RUBY_VERSION.start_with?('1.8.') context 'when the expression is a method definition and ends with "end"-only line', :unless => argument_error_points_invoker do let(:source) do obj = Object.new def obj.foo(arg) p arg end obj.foo end it 'returns all the lines' do expect(expression_lines).to eq([ ' def obj.foo(arg)', ' p arg', ' end' ]) end end context 'when the expression line includes an "end"-less method definition', :if => RUBY_VERSION.to_f >= 3.0 do include RSpec::Support::InSubProcess around(:example) do |example| require 'tempfile' example.call end let(:source) do in_sub_process do load(file.path) end end let(:file) do file = Tempfile.new('source.rb') file.write(unindent(<<-END)) obj = Object.new def obj.foo = raise obj.foo END file.close file end after do file.unlink end it 'returns only the line' do expect(expression_lines).to eq([ 'def obj.foo = raise' ]) end end context 'when the expression is a setter method definition', :unless => argument_error_points_invoker do let(:source) do obj = Object.new def obj.foo=(arg1, arg2) @foo = arg1 end obj.foo = 1 end it 'returns all the lines without confusing it with "end"-less method' do expect(expression_lines).to eq([ ' def obj.foo=(arg1, arg2)', ' @foo = arg1', ' end' ]) end end context "when the expression ends with multiple paren-only lines of same type" do let(:source) do do_something_fail(:foo, (:bar ) ) end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail(:foo, (:bar', ' )', ' )' ]) end end context "when the expression includes paren and heredoc pairs as non-nested structure" do let(:source) do do_something_fail(<<-END) foo END end it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail(<<-END)', ' foo', ' END' ]) end end context 'when the expression spans lines after the closing paren line' do let(:source) do do_something_fail(:foo ). do_something_chain end # [:program, # [[:call, # [:method_add_arg, [:fcall, [:@ident, "do_something_fail", [1, 10]]], [:arg_paren, nil]], # :".", # [:@ident, "do_something_chain", [3, 10]]]]] it 'returns all the lines' do expect(expression_lines).to eq([ ' do_something_fail(:foo', ' ).', ' do_something_chain' ]) end end context "when the expression's final line includes the same type of opening paren of another multiline expression" do let(:source) do do_something_fail(:foo ); another_expression(:bar ) end it 'ignores another expression' do expect(expression_lines).to eq([ ' do_something_fail(:foo', ' ); another_expression(:bar' ]) end end context "when the expression's first line includes a closing paren of another multiline expression" do let(:source) do another_expression(:bar ); do_something_fail(:foo ) end it 'ignores another expression' do expect(expression_lines).to eq([ ' ); do_something_fail(:foo', ' )' ]) end end context 'when no expression exists at the line' do let(:file_path) do __FILE__ end let(:line_number) do __LINE__ + 1 # The failure happened here without expression end it 'returns the line by falling back to the simple single line extraction' do expect(expression_lines).to eq([ ' # The failure happened here without expression' ]) end end context 'when Ripper cannot parse the source (which can happen on JRuby -- see jruby/jruby#2427)', :isolated_directory do let(:file_path) { 'invalid_source.rb' } let(:line_number) { 1 } let(:source) { <<-EOS.gsub(/^ +\|/, '') } |expect("some string").to include( | "some", "string" |] EOS before do File.open(file_path, 'w') { |file| file.write(source) } end it 'returns the line by falling back to the simple single line extraction' do expect(expression_lines).to eq([ 'expect("some string").to include(' ]) end end context 'when max line count is given' do let(:max_line_count) do 2 end let(:source) do do_something_fail "line1", [ "line2", "line3" ] end it 'returns the lines without exceeding the given count' do expect(expression_lines).to eq([ ' do_something_fail "line1", [', ' "line2",' ]) end end context 'when max line count is 1' do let(:max_line_count) do 1 end let(:source) do do_something_fail "line1", [ "line2", "line3" ] end before do RSpec.reset # Clear source cache end it 'returns the line without parsing the source for efficiency' do require 'ripper' expect(Ripper).not_to receive(:sexp) expect(expression_lines).to eq([ ' do_something_fail "line1", [' ]) end end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do context 'when the expression spans multiple lines' do let(:source) do do_something_fail :foo, :bar end it 'returns only the first line' do expect(expression_lines).to eq([ ' do_something_fail :foo,' ]) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/json_formatter_spec.rb0000664000000000000000000002135014557677674030441 0ustar rootrootrequire 'rspec/core/formatters/json_formatter' require 'json' require 'rspec/core/reporter' # todo, someday: # it "lists the groups (describe and context) separately" # it "includes full 'execution_result'" # it "relativizes backtrace paths" # it "includes profile information (implements dump_profile)" # it "shows the pending message if one was given" # it "shows the seed if run was randomized" # it "lists pending specs that were fixed" RSpec.describe RSpec::Core::Formatters::JsonFormatter do include FormatterSupport it "can be loaded via `--format json`" do output = run_example_specs_with_formatter("json", :normalize_output => false, :seed => 42) parsed = JSON.parse(output) expect(parsed.keys).to include("examples", "summary", "summary_line", "seed") end it "outputs expected json (brittle high level functional test)" do its = [] group = RSpec.describe("one apiece") do its.push it("succeeds") { expect(1).to eq 1 } its.push it("fails") { fail "eek" } its.push it("pends") { pending "world peace"; fail "eek" } end succeeding_line = __LINE__ - 4 failing_line = __LINE__ - 4 pending_line = __LINE__ - 4 now = Time.now allow(Time).to receive(:now).and_return(now) reporter.report(2) do |r| group.run(r) end # grab the actual backtrace -- kind of a cheat examples = formatter.output_hash[:examples] failing_backtrace = examples[1][:exception][:backtrace] this_file = relative_path(__FILE__) expected = { :version => RSpec::Core::Version::STRING, :examples => [ { :id => its[0].id, :description => "succeeds", :full_description => "one apiece succeeds", :status => "passed", :file_path => this_file, :line_number => succeeding_line, :run_time => formatter.output_hash[:examples][0][:run_time], :pending_message => nil, }, { :id => its[1].id, :description => "fails", :full_description => "one apiece fails", :status => "failed", :file_path => this_file, :line_number => failing_line, :run_time => formatter.output_hash[:examples][1][:run_time], :pending_message => nil, :exception => { :class => "RuntimeError", :message => "eek", :backtrace => failing_backtrace }, }, { :id => its[2].id, :description => "pends", :full_description => "one apiece pends", :status => "pending", :file_path => this_file, :line_number => pending_line, :run_time => formatter.output_hash[:examples][2][:run_time], :pending_message => "world peace", }, ], :summary => { :duration => formatter.output_hash[:summary][:duration], :example_count => 3, :failure_count => 1, :pending_count => 1, :errors_outside_of_examples_count => 0, }, :summary_line => "3 examples, 1 failure, 1 pending" } expect(formatter.output_hash).to eq expected expect(formatter_output.string).to eq expected.to_json end context "when full backtrace is enabled" do around do |example| original_value = RSpec.configuration.full_backtrace? RSpec.configuration.full_backtrace = true example.run RSpec.configuration.full_backtrace = original_value end it "outputs the full backtrace" do group = RSpec.describe do it("fails") { fail "eek" } end reporter.report(1) { |r| group.run(r) } formatted_backtrace = formatter.output_hash[:examples][0][:exception][:backtrace] exception_backtrace = group.examples[0].exception.backtrace.map { |l| l.gsub(Dir.pwd, ".") } expect(formatted_backtrace).to eq(exception_backtrace) end end context "when full backtrace is disabled" do around do |example| original_value = RSpec.configuration.full_backtrace? RSpec.configuration.full_backtrace = false example.run RSpec.configuration.full_backtrace = original_value end it "outputs a strict subset of the full backtrace" do group = RSpec.describe do it("fails") { fail "eek" } end reporter.report(1) { |r| group.run(r) } formatted_backtrace = formatter.output_hash[:examples][0][:exception][:backtrace] exception_backtrace = group.examples[0].exception.backtrace.map { |l| l.gsub(Dir.pwd, ".") } expect(formatted_backtrace).not_to be_empty # Every line in the formatted backtrace is also in the original backtrace expect(formatted_backtrace - exception_backtrace).to be_empty # The original backtrace contains lines not in the formatted backtrace expect(exception_backtrace - formatted_backtrace).not_to be_empty end end describe "#stop" do it "adds all examples to the output hash" do send_notification :stop, stop_notification expect(formatter.output_hash[:examples]).not_to be_nil end end describe "#seed" do context "use random seed" do it "adds random seed" do send_notification :seed, seed_notification(42) expect(formatter.output_hash[:seed]).to eq(42) end end context "don't use random seed" do it "don't add random seed" do send_notification :seed, seed_notification(42, false) expect(formatter.output_hash[:seed]).to be_nil end end end describe "#close" do it "outputs the results as a JSON string" do expect(formatter_output.string).to eq "" send_notification :close, null_notification expect(formatter_output.string).to eq({ :version => RSpec::Core::Version::STRING }.to_json) end it "does not close the stream so that it can be reused within a process" do formatter.close(RSpec::Core::Notifications::NullNotification) expect(formatter_output.closed?).to be(false) end end describe "#message" do it "adds a message to the messages list" do send_notification :message, message_notification("good job") expect(formatter.output_hash[:messages]).to eq ["good job"] end end describe "#dump_summary" do it "adds summary info to the output hash" do send_notification :dump_summary, summary_notification(1.0, examples(10), examples(3), examples(4), 0, 1) expect(formatter.output_hash[:summary]).to include( :duration => 1.0, :example_count => 10, :failure_count => 3, :pending_count => 4, :errors_outside_of_examples_count => 1 ) summary_line = formatter.output_hash[:summary_line] expect(summary_line).to eq "10 examples, 3 failures, 4 pending, 1 error occurred outside of examples" end end describe "#dump_profile", :slow do def profile *groups groups.each { |group| group.run(reporter) } examples = groups.map(&:examples).flatten send_notification :dump_profile, profile_notification(0.5, examples, 10) end before do setup_profiler formatter end context "with one example group" do before do profile( RSpec.describe("group") do example("example") { } end) end it "names the example" do expect(formatter.output_hash[:profile][:examples].first[:full_description]).to eq("group example") end it "provides example execution time" do expect(formatter.output_hash[:profile][:examples].first[:run_time]).not_to be_nil end it "doesn't profile a single example group" do expect(formatter.output_hash[:profile][:groups]).to be_empty end it "has the summary of profile information" do expect(formatter.output_hash[:profile].keys).to match_array([:examples, :groups, :slowest, :total]) end end context "with multiple example groups", :slow do before do start = Time.utc(2015, 6, 10, 12, 30) now = start allow(RSpec::Core::Time).to receive(:now) { now } group1 = RSpec.describe("slow group") do example("example") { } after { now += 100 } end group2 = RSpec.describe("fast group") do example("example 1") { } example("example 2") { } after { now += 1 } end profile group1, group2 end it "provides the slowest example groups" do expect(formatter.output_hash).not_to be_empty end it "provides information" do expect(formatter.output_hash[:profile][:groups].first.keys).to match_array([:total_time, :count, :description, :average, :location, :start]) end it "ranks the example groups by average time" do |ex| expect(formatter.output_hash[:profile][:groups].first[:description]).to eq("slow group") end end end end ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/fallback_message_formatter_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/fallback_message_formatter_spec0000664000000000000000000000101614557677674032326 0ustar rootrootrequire 'rspec/core/reporter' require 'rspec/core/formatters/fallback_message_formatter' module RSpec::Core::Formatters RSpec.describe FallbackMessageFormatter do include FormatterSupport describe "#message" do it 'writes the message to the output' do expect { send_notification :message, message_notification('Custom Message') }.to change { formatter_output.string }. from(excluding 'Custom Message'). to(including 'Custom Message') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/profile_formatter_spec.rb0000664000000000000000000000576414557677674031143 0ustar rootrootrequire 'rspec/core/formatters/profile_formatter' RSpec.describe RSpec::Core::Formatters::ProfileFormatter do include FormatterSupport def profile *groups setup_profiler groups.each { |group| group.run(reporter) } examples = groups.map(&:examples).flatten total_time = examples.map { |e| e.execution_result.run_time }.inject(&:+) send_notification :dump_profile, profile_notification(total_time, examples, 10) end describe "#dump_profile", :slow do example_line_number = nil shared_examples_for "profiles examples" do it "names the example" do expect(formatter_output.string).to match(/group example/m) end it "prints the time" do expect(formatter_output.string).to match(/0(\.\d+)? seconds/) end it "prints the path" do filename = __FILE__.split(File::SEPARATOR).last expect(formatter_output.string).to match(/#{filename}\:#{example_line_number}/) end it "prints the percentage taken from the total runtime" do expect(formatter_output.string).to match(/, 100.0% of total time\):/) end end context "with one example group" do before do example_clock = class_double(RSpec::Core::Time, :now => RSpec::Core::Time.now + 0.5) profile(RSpec.describe("group") do example("example") do |example| # make it look slow without actually taking up precious time example.clock = example_clock end example_line_number = __LINE__ - 4 end) end it_should_behave_like "profiles examples" it "doesn't profile a single example group" do expect(formatter_output.string).not_to match(/slowest example groups/) end end context "with multiple example groups" do before do example_clock = class_double(RSpec::Core::Time, :now => RSpec::Core::Time.now + 0.5) @slow_group_line_number = __LINE__ + 1 group1 = RSpec.describe("slow group") do example("example") do |example| # make it look slow without actually taking up precious time example.clock = example_clock end example_line_number = __LINE__ - 4 end group2 = RSpec.describe("fast group") do example("example 1") { } example("example 2") { } end profile group1, group2 end it_should_behave_like "profiles examples" it "prints the slowest example groups" do expect(formatter_output.string).to match(/slowest example groups/) end it "prints the time" do expect(formatter_output.string).to match(/0(\.\d+)? seconds/) end it "ranks the example groups by average time" do expect(formatter_output.string).to match(/slow group(.*)fast group/m) end it "prints the location of the slow groups" do expect(formatter_output.string).to include("#{RSpec::Core::Metadata.relative_path __FILE__}:#{@slow_group_line_number}") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/html_formatter_spec.rb0000664000000000000000000000536414557677674030443 0ustar rootroot# encoding: utf-8 require 'rspec/core/formatters/html_formatter' module RSpec module Core module Formatters RSpec.describe HtmlFormatter do include FormatterSupport let(:root) { File.expand_path("#{File.dirname(__FILE__)}/../../../..") } let(:expected_file) do "#{File.dirname(__FILE__)}/html_formatted.html" end let(:actual_html) do run_example_specs_with_formatter('html') do |runner| allow(runner.configuration).to receive(:load_spec_files) do runner.configuration.files_to_run.map { |f| load File.expand_path(f) } end # This is to minimize churn on backtrace lines runner.configuration.backtrace_exclusion_patterns << /.*/ runner.configuration.backtrace_inclusion_patterns << /formatter_specs\.rb/ end end let(:expected_html) do File.read(expected_file) end # Uncomment this group temporarily in order to overwrite the expected # with actual. Use with care!!! describe "file generator", :if => ENV['GENERATE'] do it "generates a new comparison file" do Dir.chdir(root) do File.open(expected_file, 'w') {|io| io.write(actual_html)} end end end def extract_backtrace_from(doc) doc.search("div.backtrace"). collect {|e| e.at("pre").inner_html}. collect {|e| e.split("\n")}.flatten. select {|e| e =~ /formatter_specs\.rb/} end describe 'produced HTML', :if => RUBY_VERSION <= '2.0.0' do # Rubies before 2 are a wild west of different outputs, and it's not # worth the effort to maintain accurate fixtures for all of them. # Since we are verifying fixtures on other rubies, if this code at # least runs we can be reasonably confident the output is right since # behaviour variances that we care about across versions is neglible. it 'is present' do expect(actual_html).to be end end describe 'produced HTML', :slow, :if => RUBY_VERSION >= '2.0.0' do it "is identical to the one we designed manually", :pending => (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby') do expect(actual_html).to eq(expected_html) end context 'with mathn loaded' do include MathnIntegrationSupport it "is identical to the one we designed manually", :slow, :pending => (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby') do with_mathn_loaded do expect(actual_html).to eq(expected_html) end end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/syntax_highlighter_spec.rb0000664000000000000000000001110214557677674031303 0ustar rootrootrequire 'rspec/core/formatters/syntax_highlighter' module RSpec::Core::Formatters RSpec.describe SyntaxHighlighter do let(:config) { RSpec::Core::Configuration.new.tap { |config| config.color_mode = :on } } let(:highlighter) { SyntaxHighlighter.new(config) } context "when CodeRay is available", :unless => RSpec::Support::OS.windows? do before { expect { require 'coderay' }.not_to raise_error } it 'highlights the syntax of the provided lines' do highlighted = highlighter.highlight(['[:ok, "ok"]']) expect(highlighted.size).to eq(1) expect(highlighted.first).to be_highlighted.and include(":ok") end it 'prefixes the each line with a reset escape code so it can be interpolated in a colored string without affecting the syntax highlighting of the snippet' do highlighted = highlighter.highlight(['a = 1', 'b = 2']) expect(highlighted).to all start_with("\e[0m") end it 'leaves leading spaces alone so it can be re-indented as needed without the leading reset code interfering' do highlighted = highlighter.highlight([' a = 1', ' b = 2']) expect(highlighted).to all start_with(" \e[0m") end it 'returns the provided lines unmodified if color is disabled' do config.color_mode = :off expect(highlighter.highlight(['[:ok, "ok"]'])).to eq(['[:ok, "ok"]']) end it 'dynamically adjusts to changing color config' do config.color_mode = :off expect(highlighter.highlight(['[:ok, "ok"]']).first).not_to be_highlighted config.color_mode = :on expect(highlighter.highlight(['[:ok, "ok"]']).first).to be_highlighted config.color_mode = :off expect(highlighter.highlight(['[:ok, "ok"]']).first).not_to be_highlighted end it "rescues coderay failures since we do not want a coderay error to be displayed instead of the user's error" do allow(CodeRay).to receive(:encode).and_raise(Exception.new "boom") lines = [":ok"] expect(highlighter.highlight(lines)).to eq(lines) end it "highlights core RSpec keyword-like methods" do highlighted_terms = find_highlighted_terms_in <<-EOS describe stuff do before { } after { } around { } let(stuff) { } subject { } context do it stuff do expect(thing).to foo allow(thing).to foo end example { } specify { } end end EOS expect(highlighted_terms).to match_array %w[ describe context it specify before after around let subject expect allow do end ] end it "does not blow up if the coderay constant we update with our keywords is missing" do hide_const("CodeRay::Scanners::Ruby::Patterns::IDENT_KIND") expect(highlighter.highlight(['[:ok, "ok"]']).first).to be_highlighted end def find_highlighted_terms_in(code_snippet) lines = code_snippet.split("\n") highlighted = highlighter.highlight(lines) highlighted_terms = [] highlighted.join("\n").scan(/\e\[[1-9]\dm(\w+)\e\[0m/) do |first_capture, _| highlighted_terms << first_capture end highlighted_terms.uniq end end context "when CodeRay is unavailable" do before do allow(highlighter).to receive(:require).with("coderay").and_raise(LoadError) end it 'does not highlight the syntax' do unhighlighted = highlighter.highlight(['[:ok, "ok"]']) expect(unhighlighted.size).to eq(1) expect(unhighlighted.first).not_to be_highlighted end it 'does not mutate the input array' do lines = ["a = 1", "b = 2"] expect { highlighter.highlight(lines) }.not_to change { lines } end it 'does not add the comment about coderay if the snippet is only one line as we do not want to convert it to multiline just for the comment' do expect(highlighter.highlight(["a = 1"])).to eq(["a = 1"]) end it 'does not add the comment about coderay if given no lines' do expect(highlighter.highlight([])).to eq([]) end it 'does not add the comment about coderay if color is disabled even when given a multiline snippet' do config.color_mode = :off lines = ["a = 1", "b = 2"] expect(highlighter.highlight(lines)).to eq(lines) end end def be_highlighted include("\e[31m") end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/documentation_formatter_spec.rb0000664000000000000000000001176514557677674032352 0ustar rootrootrequire 'rspec/core/formatters/documentation_formatter' module RSpec::Core::Formatters RSpec.describe DocumentationFormatter do include FormatterSupport before do send_notification :start, start_notification(2) end def execution_result(values) RSpec::Core::Example::ExecutionResult.new.tap do |er| values.each { |name, value| er.__send__(:"#{name}=", value) } end end it "numbers the failures" do send_notification :example_failed, example_notification( double("example 1", :description => "first example", :full_description => "group first example", :execution_result => execution_result(:status => :failed, :exception => Exception.new), :metadata => {} )) send_notification :example_failed, example_notification( double("example 2", :description => "second example", :full_description => "group second example", :execution_result => execution_result(:status => :failed, :exception => Exception.new), :metadata => {} )) expect(formatter_output.string).to match(/first example \(FAILED - 1\)/m) expect(formatter_output.string).to match(/second example \(FAILED - 2\)/m) end it 'will not error if more finishes than starts are called' do group = double("example 1", :description => "first example", :full_description => "group first example", :metadata => {}, :top_level? => true, :top_level_description => "Top group" ) send_notification :example_group_finished, group_notification(group) send_notification :example_group_finished, group_notification(group) send_notification :example_group_finished, group_notification(group) expect { send_notification :example_group_started, group_notification(group) }.not_to raise_error end it "represents nested group using hierarchy tree" do group = RSpec.describe("root") context1 = group.describe("context 1") context1.example("nested example 1.1"){} context1.example("nested example 1.2"){} context11 = context1.describe("context 1.1") context11.example("nested example 1.1.1"){} context11.example("nested example 1.1.2"){} context2 = group.describe("context 2") context2.example("nested example 2.1"){} context2.example("nested example 2.2"){} group.run(reporter) expect(formatter_output.string).to eql(" root context 1 nested example 1.1 nested example 1.2 context 1.1 nested example 1.1.1 nested example 1.1.2 context 2 nested example 2.1 nested example 2.2 ") end it "can output indented messages from within example group" do root = RSpec.describe("root") root.example("example") {|example| example.reporter.message("message")} root.run(reporter) expect(formatter_output.string).to eql(" root example message ") end it "can output indented messages" do root = RSpec.describe("root") context = root.describe("nested") context.example("example") {} root.run(reporter) reporter.message("message") expect(formatter_output.string).to eql(" root nested example message ") end it "strips whitespace for each row" do group = RSpec.describe(" root ") context1 = group.describe(" nested ") context1.example(" example 1 ") {} context1.example(" example 2 ", :pending => true){ fail } context1.example(" example 3 ") { fail } group.run(reporter) expect(formatter_output.string).to eql(" root nested example 1 example 2 (PENDING: No reason given) example 3 (FAILED - 1) ") end # The backtrace is slightly different on JRuby/Rubinius so we skip there. it 'produces the expected full output', :if => RSpec::Support::Ruby.mri? do output = run_example_specs_with_formatter("doc") output.gsub!(/ +$/, '') # strip trailing whitespace expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) | |pending spec with no implementation | is pending (PENDING: Not yet implemented) | |pending command with block format | with content that would fail | is pending (PENDING: No reason given) | behaves like shared | is marked as pending but passes (FAILED - 1) | |passing spec | passes | passes with a multiple | line description | |failing spec | fails (FAILED - 2) | fails twice (FAILED - 3) | |a failing spec with odd backtraces | fails with a backtrace that has no file (FAILED - 4) | fails with a backtrace containing an erb file (FAILED - 5) | with a `nil` backtrace | raises (FAILED - 6) | |#{expected_summary_output_for_example_specs} EOS end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/html_snippet_extractor_spec.rb0000664000000000000000000000361514557677674032212 0ustar rootrootrequire 'rspec/core/formatters/html_snippet_extractor' module RSpec module Core module Formatters RSpec.describe HtmlSnippetExtractor do it "falls back on a default message when it doesn't understand a line" do expect(RSpec::Core::Formatters::HtmlSnippetExtractor.new.snippet_for("blech")).to eq(["# Couldn't get snippet for blech", 1]) end it "falls back on a default message when it doesn't find the file" do expect(RSpec::Core::Formatters::HtmlSnippetExtractor.new.lines_around("blech", 8)).to eq("# Couldn't get snippet for blech") end if RSpec::Support::RubyFeatures.supports_taint? it "falls back on a default message when it gets a security error" do message = with_safe_set_to_level_that_triggers_security_errors do RSpec::Core::Formatters::HtmlSnippetExtractor.new.lines_around("blech".dup.taint, 8) end expect(message).to eq("# Couldn't get snippet for blech") end end describe "snippet extraction" do let(:snippet) do HtmlSnippetExtractor.new.snippet(["#{__FILE__}:#{__LINE__}"]) end before do # `send` is required for 1.8.7... @orig_converter = HtmlSnippetExtractor.send(:class_variable_get, :@@converter) end after do HtmlSnippetExtractor.send(:class_variable_set, :@@converter, @orig_converter) end it 'suggests you install coderay when it cannot be loaded' do HtmlSnippetExtractor.send(:class_variable_set, :@@converter, HtmlSnippetExtractor::NullConverter) expect(snippet).to include("Install the coderay gem") end it 'does not suggest installing coderay normally' do expect(snippet).to exclude("Install the coderay gem") end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/progress_formatter_spec.rb0000664000000000000000000000326114557677674031335 0ustar rootrootrequire 'rspec/core/formatters/progress_formatter' RSpec.describe RSpec::Core::Formatters::ProgressFormatter do include FormatterSupport before do send_notification :start, start_notification(2) end it 'prints a . on example_passed' do send_notification :example_passed, example_notification expect(formatter_output.string).to eq(".") end it 'prints a * on example_pending' do send_notification :example_pending, example_notification expect(formatter_output.string).to eq("*") end it 'prints a F on example_failed' do send_notification :example_failed, example_notification expect(formatter_output.string).to eq("F") end it "produces standard summary without pending when pending has a 0 count" do send_notification :dump_summary, summary_notification(0.00001, examples(2), [], [], 0) expect(formatter_output.string).to match(/^\n/) expect(formatter_output.string).to match(/2 examples, 0 failures/i) expect(formatter_output.string).not_to match(/0 pending/i) end it "pushes nothing on start" do #start already sent expect(formatter_output.string).to eq("") end it "pushes nothing on start dump" do send_notification :start_dump, null_notification expect(formatter_output.string).to eq("\n") end # The backtrace is slightly different on JRuby/Rubinius so we skip there. it 'produces the expected full output', :if => RSpec::Support::Ruby.mri? do output = run_example_specs_with_formatter("progress") output.gsub!(/ +$/, '') # strip trailing whitespace expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |**F..FFFFF | |#{expected_summary_output_for_example_specs} EOS end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/html_formatted.html0000664000000000000000000004173214557677674027753 0ustar rootroot RSpec results

RSpec Code Examples

 

 

pending spec with no implementation
is pending (PENDING: Not yet implemented)
pending command with block format
with content that would fail
is pending (PENDING: No reason given)
behaves like shared
is marked as pending but passes n.nnnns
  Expected pending 'No reason given' to fail. No error was raised.
  Shared Example Group: "shared" called from ./spec/rspec/core/resources/formatter_specs.rb:22
  # ./spec/rspec/core/resources/formatter_specs.rb:4
./spec/rspec/core/resources/formatter_specs.rb:4
2
3RSpec.shared_examples_for "shared" do
4  it "is marked as pending but passes" do
5    pending
6    expect(1).to eq(1)
passing spec
passesn.nnnns
passes with a multiple line descriptionn.nnnns
failing spec
fails n.nnnns
  Failure/Error: expect(1).to eq(2)

    expected: 2
         got: 1

    (compared using ==)
  # ./spec/rspec/core/resources/formatter_specs.rb:37:in `block (2 levels) in <top (required)>'
./spec/rspec/core/resources/formatter_specs.rb:37:in `block (2 levels) in <top (required)>'
35RSpec.describe "failing spec" do
36  it "fails" do
37    expect(1).to eq(2)
38  end
fails twice n.nnnns
  Got 2 failures:

  1) Failure/Error: expect(1).to eq(2)

       expected: 2
            got: 1

       (compared using ==)
     # ./spec/rspec/core/resources/formatter_specs.rb:41:in `block (2 levels) in <top (required)>'

  2) Failure/Error: expect(3).to eq(4)

       expected: 4
            got: 3

       (compared using ==)
     # ./spec/rspec/core/resources/formatter_specs.rb:42:in `block (2 levels) in <top (required)>'
-1# Couldn't get snippet for 
a failing spec with odd backtraces
fails with a backtrace that has no file n.nnnns
  Failure/Error: ERB.new("<%= raise 'foo' %>").result

  RuntimeError:
    foo
  # ./spec/rspec/core/resources/formatter_specs.rb:50:in `block (2 levels) in <top (required)>'
./spec/rspec/core/resources/formatter_specs.rb:50:in `block (2 levels) in <top (required)>'
48    require 'erb'
49
50    ERB.new("<%= raise 'foo' %>").result
51  end
fails with a backtrace containing an erb file n.nnnns
  Failure/Error: Unable to find /foo.html.erb to read failed line

  Exception:
    Exception
  # /foo.html.erb:1:in `<main>': foo (RuntimeError)
  #    from /lib/ruby/1.9.1/erb.rb:753:in `eval'
  # 
  #   Showing full backtrace because every line was filtered out.
  #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
  #   RSpec::Configuration#backtrace_inclusion_patterns for more information.
/foo.html.erb:1:in `<main>': foo (RuntimeError)
   from /lib/ruby/1.9.1/erb.rb:753:in `eval'

  Showing full backtrace because every line was filtered out.
  See docs for RSpec::Configuration#backtrace_exclusion_patterns and
  RSpec::Configuration#backtrace_inclusion_patterns for more information.
-1# Couldn't get snippet for 
with a `nil` backtrace
raises n.nnnns
  Failure/Error: Unable to find matching line from backtrace

  RuntimeError:
    boom
-1# Couldn't get snippet for 
ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/failure_list_formatter_spec.rb0000664000000000000000000000151214557677674032150 0ustar rootrootrequire 'rspec/core/formatters/failure_list_formatter' module RSpec::Core::Formatters RSpec.describe FailureListFormatter do include FormatterSupport it 'produces the expected full output' do output = run_example_specs_with_formatter('failures') expect(output).to eq(<<-EOS.gsub(/^\s+\|/, '')) |./spec/rspec/core/resources/formatter_specs.rb:4:is marked as pending but passes |./spec/rspec/core/resources/formatter_specs.rb:36:fails |./spec/rspec/core/resources/formatter_specs.rb:40:fails twice |./spec/rspec/core/resources/formatter_specs.rb:47:fails with a backtrace that has no file |./spec/rspec/core/resources/formatter_specs.rb:53:fails with a backtrace containing an erb file |./spec/rspec/core/resources/formatter_specs.rb:71:raises EOS end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/formatters/base_text_formatter_spec.rb0000664000000000000000000002666014557677674031457 0ustar rootroot# encoding: utf-8 require 'rspec/core/formatters/base_text_formatter' RSpec.describe RSpec::Core::Formatters::BaseTextFormatter do include FormatterSupport context "when closing the formatter", :isolated_directory => true do let(:output_to_close) { File.new("./output_to_close", "w") } let(:formatter) { described_class.new(output_to_close) } after do # Windows appears to not let the `:isolated_directory` shared group # cleanup if the file isn't closed. output_to_close.close unless output_to_close.closed? end it 'does not error on an already closed output stream' do output_to_close.close expect { formatter.close(RSpec::Core::Notifications::NullNotification) }.not_to raise_error end it "flushes output before closing the stream so buffered bytes are not lost if we exit right away" do expect(output_to_close).to receive(:flush).ordered.and_call_original formatter.close(RSpec::Core::Notifications::NullNotification) end it "does not close the stream so that it can be reused within a process" do formatter.close(RSpec::Core::Notifications::NullNotification) expect(output_to_close.closed?).to be(false) end end describe "#dump_summary" do it "with 0s outputs pluralized (excluding pending)" do send_notification :dump_summary, summary_notification(0, [], [], [], 0) expect(formatter_output.string).to match("0 examples, 0 failures") end it "with 1s outputs singular (including pending)" do send_notification :dump_summary, summary_notification(0, examples(1), examples(1), examples(1), 0) expect(formatter_output.string).to match("1 example, 1 failure, 1 pending") end it "with 1s outputs singular (only pending)" do send_notification :dump_summary, summary_notification(1, examples(1), examples(0), examples(1), 0) expect(formatter_output.string).to match("1 example, 0 failures, 1 pending") end it "with 2s outputs pluralized (including pending)" do send_notification :dump_summary, summary_notification(2, examples(2), examples(2), examples(2), 0) expect(formatter_output.string).to match("2 examples, 2 failures, 2 pending") end it 'with errors includes that count' do send_notification :dump_summary, summary_notification(2, examples(2), examples(2), examples(2), 0, 3) expect(formatter_output.string).to match("2 examples, 2 failures, 2 pending, 3 errors occurred outside of examples") end describe "rerun command for failed examples" do it "uses the location to identify the example" do line = __LINE__ + 2 example_group = RSpec.describe("example group") do it("fails") { fail } end expect(output_from_running example_group).to include("rspec #{RSpec::Core::Metadata::relative_path("#{__FILE__}:#{line}")} # example group fails") end context "for an example defined in an file required by the user rather than loaded by rspec" do it "looks through ancestor metadata to find a workable re-run command" do line = __LINE__ + 1 example_group = RSpec.describe("example group") do # Using eval in order to make it think this got defined in an external file. instance_eval "it('fails') { fail }", "some/external/file.rb", 1 end expect(output_from_running example_group).to include("rspec #{RSpec::Core::Metadata::relative_path("#{__FILE__}:#{line}")} # example group fails") end end context "for an example that is not uniquely identified by the location" do let(:example_group_in_this_file) { example_group_defined_in(__FILE__) } def example_group_defined_in(file) instance_eval <<-EOS, file, 1 $group = RSpec.describe("example group") do 1.upto(2) do |i| it("compares \#{i} against 2") { expect(i).to eq(2) } end end EOS $group end let(:id) { "#{RSpec::Core::Metadata::relative_path("#{__FILE__}")}[1:1]" } it "uses the id instead" do with_env_vars 'SHELL' => '/usr/local/bin/bash' do expect(output_from_running example_group_in_this_file).to include("rspec #{id} # example group compares 1 against 2") end end context "on a shell that may not handle unquoted ids" do around { |ex| with_env_vars('SHELL' => '/usr/local/bin/cash', &ex) } it 'quotes the id to be safe so the rerun command can be copied and pasted' do expect(output_from_running example_group_in_this_file).to include("rspec '#{id}'") end it 'correctly escapes file names that have quotes in them' do group_in_other_file = example_group_defined_in("./path/with'quote_spec.rb") expect(output_from_running group_in_other_file).to include("rspec './path/with\\'quote_spec.rb[1:1]'") end end end def output_from_running(example_group) allow(RSpec.configuration).to receive(:loaded_spec_files) { RSpec::Core::Set.new([File.expand_path(__FILE__)]) } example_group.run(reporter) examples = example_group.examples failed = examples.select { |e| e.execution_result.status == :failed } send_notification :dump_summary, summary_notification(1, examples, failed, [], 0) formatter_output.string end end end describe "#dump_failures" do let(:group) { RSpec.describe("group name") } before { allow(RSpec.configuration).to receive(:color_enabled?) { false } } def run_all_and_dump_failures group.run(reporter) send_notification :dump_failures, failed_examples_notification end it "preserves formatting" do group.example("example name") { expect("this").to eq("that") } run_all_and_dump_failures expect(formatter_output.string).to match(/group name example name/m) expect(formatter_output.string).to match(/(\s+)expected: \"that\"\n\1 got: \"this\"/m) end context "with an exception without a message" do it "does not throw NoMethodError" do exception_without_message = Exception.new() allow(exception_without_message).to receive(:message) { nil } group.example("example name") { raise exception_without_message } expect { run_all_and_dump_failures }.not_to raise_error end it "preserves ancestry" do example = group.example("example name") { raise "something" } run_all_and_dump_failures expect(example.example_group.parent_groups.size).to eq 1 end end context "with an exception that has an exception instance as its message" do it "does not raise NoMethodError" do gonzo_exception = RuntimeError.new allow(gonzo_exception).to receive(:message) { gonzo_exception } group.example("example name") { raise gonzo_exception } expect { run_all_and_dump_failures }.not_to raise_error end end context "with an instance of an anonymous exception class" do it "substitutes '(anonymous error class)' for the missing class name" do exception = Class.new(StandardError).new group.example("example name") { raise exception } run_all_and_dump_failures expect(formatter_output.string).to include('(anonymous error class)') end end context "with an exception class other than RSpec" do it "does not show the error class" do group.example("example name") { raise NameError.new('foo') } run_all_and_dump_failures expect(formatter_output.string).to match(/NameError/m) end end if String.method_defined?(:encoding) context "with an exception that has a differently encoded message" do it "runs without encountering an encoding exception" do group.example("Mixing encodings, e.g. UTF-8: © and Binary") { raise "Error: \xC2\xA9".dup.force_encoding("ASCII-8BIT") } run_all_and_dump_failures expect(formatter_output.string).to match(/RuntimeError:\n\s+Error: \?\?/m) # ?? because the characters dont encode properly end end end context "with a failed expectation (rspec-expectations)" do it "does not show the error class" do group.example("example name") { expect("this").to eq("that") } run_all_and_dump_failures expect(formatter_output.string).not_to match(/RSpec::/m) end end context "with a failed message expectation (rspec-mocks)" do it "does not show the error class" do group.example("example name") { expect("this").to receive("that") } run_all_and_dump_failures expect(formatter_output.string).not_to match(/RSpec::/m) end end %w[ include_examples it_should_behave_like ].each do |inclusion_method| context "for #shared_examples included using #{inclusion_method}" do it 'outputs the name and location' do group.shared_examples 'foo bar' do it("example name") { expect("this").to eq("that") } end line = __LINE__.next group.__send__(inclusion_method, 'foo bar') run_all_and_dump_failures expect(formatter_output.string.lines).to include(a_string_ending_with( 'Shared Example Group: "foo bar" called from ' + "#{RSpec::Core::Metadata.relative_path(__FILE__)}:#{line}\n" )) end context 'that contains nested example groups' do it 'outputs the name and location' do group.shared_examples 'foo bar' do describe 'nested group' do it("example name") { expect("this").to eq("that") } end end line = __LINE__.next group.__send__(inclusion_method, 'foo bar') run_all_and_dump_failures expect(formatter_output.string.lines).to include(a_string_ending_with( 'Shared Example Group: "foo bar" called from ' + "./spec/rspec/core/formatters/base_text_formatter_spec.rb:#{line}\n" )) end end context "that contains shared group nesting" do it 'includes each inclusion location in the output' do group.shared_examples "inner" do example { expect(1).to eq(2) } end inner_line = __LINE__ + 2 group.shared_examples "outer" do __send__(inclusion_method, "inner") end outer_line = __LINE__ + 1 group.__send__(inclusion_method, 'outer') run_all_and_dump_failures expect(formatter_output.string.lines.grep(/Shared Example Group/)).to match [ a_string_ending_with( 'Shared Example Group: "inner" called from ' + "./spec/rspec/core/formatters/base_text_formatter_spec.rb:#{inner_line}\n" ), a_string_ending_with( 'Shared Example Group: "outer" called from ' + "./spec/rspec/core/formatters/base_text_formatter_spec.rb:#{outer_line}\n" ), ] end end end end end describe "custom_colors" do it "uses the custom success color" do RSpec.configure do |config| config.color_mode = :on config.success_color = :cyan end send_notification :dump_summary, summary_notification(0, examples(1), [], [], 0) expect(formatter_output.string).to include("\e[36m") end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/memoized_helpers_spec.rb0000664000000000000000000004724614557677674026566 0ustar rootrootrequire 'thread_order' module RSpec::Core RSpec.describe MemoizedHelpers do before(:each) { RSpec.configuration.configure_expectation_framework } def subject_value_for(describe_arg, &block) example_group = RSpec.describe(describe_arg, &block) subject_value = nil example_group.example { subject_value = subject } example_group.run subject_value end describe "implicit subject" do describe "with a class" do it "returns an instance of the class" do expect(subject_value_for(Array)).to eq([]) end end describe "with a Module" do it "returns the Module" do expect(subject_value_for(Enumerable)).to eq(Enumerable) end end describe "with a string" do it "returns the string" do expect(subject_value_for("Foo")).to eq("Foo") end end describe "with a number" do it "returns the number" do expect(subject_value_for(15)).to eq(15) end end describe "with a hash" do it "returns the hash" do expect(subject_value_for(:foo => 3)).to eq(:foo => 3) end end describe "with a symbol" do it "returns the symbol" do expect(subject_value_for(:foo)).to eq(:foo) end end describe "with true" do it "returns `true`" do expect(subject_value_for(true)).to eq(true) end end describe "with false" do it "returns `false`" do expect(subject_value_for(false)).to eq(false) end end describe "with nil" do it "returns `nil`" do expect(subject_value_for(nil)).to eq(nil) end end it "can be overridden and super'd to from a nested group" do outer_subject_value = inner_subject_value = nil RSpec.describe(Array) do subject { super() << :parent_group } example { outer_subject_value = subject } context "nested" do subject { super() << :child_group } example { inner_subject_value = subject } end end.run expect(outer_subject_value).to eq([:parent_group]) expect(inner_subject_value).to eq([:parent_group, :child_group]) end end describe "explicit subject" do it "yields the example in which it is eval'd" do example_yielded_to_subject = nil example_yielded_to_example = nil example_group = RSpec.describe example_group.subject { |e| example_yielded_to_subject = e } example_group.example { |e| subject; example_yielded_to_example = e } example_group.run expect(example_yielded_to_subject).to eq example_yielded_to_example end context "doesn't issue a deprecation when used with doubles" do subject do Struct.new(:value) do def working_with?(double) double.value >= value end end.new 1 end it { should be_working_with double(:value => 10) } end [false, nil].each do |falsy_value| context "with a value of #{falsy_value.inspect}" do it "is evaluated once per example" do subject_calls = 0 describe_successfully do subject { subject_calls += 1; falsy_value } example { subject; subject } end expect(subject_calls).to eq(1) end end end describe "defined in a top level group" do it "replaces the implicit subject in that group" do subject_value = subject_value_for(Array) do subject { [1, 2, 3] } end expect(subject_value).to eq([1, 2, 3]) end end describe "defined in a top level group" do let(:group) do RSpec.describe do subject{ [4, 5, 6] } end end it "is available in a nested group (subclass)" do subject_value = nil group.describe("I'm nested!") do example { subject_value = subject } end.run expect(subject_value).to eq([4, 5, 6]) end it "is available in a doubly nested group (subclass)" do subject_value = nil group.describe("Nesting level 1") do describe("Nesting level 2") do example { subject_value = subject } end end.run expect(subject_value).to eq([4, 5, 6]) end it "can be overridden and super'd to from a nested group" do subject_value = nil group.describe("Nested") do subject { super() + [:override] } example { subject_value = subject } end.run expect(subject_value).to eq([4, 5, 6, :override]) end [:before, :after].each do |hook| it "raises an error when referenced from `#{hook}(:all)`" do result = nil line = nil RSpec.describe do subject { nil } send(hook, :all) { result = (subject rescue $!) }; line = __LINE__ example { } end.run expect(result).to be_an(Exception) expect(result.message).to match(/subject accessed.*#{hook}\(:context\).*#{__FILE__}:#{line}/m) end end end describe "with a name" do it "yields the example in which it is eval'd" do example_yielded_to_subject = nil example_yielded_to_example = nil group = RSpec.describe group.subject(:foo) { |e| example_yielded_to_subject = e } group.example { |e| foo; example_yielded_to_example = e } group.run expect(example_yielded_to_subject).to eq example_yielded_to_example end it "defines a method that returns the memoized subject" do list_value_1 = list_value_2 = subject_value_1 = subject_value_2 = nil RSpec.describe do subject(:list) { [1, 2, 3] } example do list_value_1 = list list_value_2 = list subject_value_1 = subject subject_value_2 = subject end end.run expect(list_value_1).to eq([1, 2, 3]) expect(list_value_1).to equal(list_value_2) expect(subject_value_1).to equal(subject_value_2) expect(subject_value_1).to equal(list_value_1) end it "is referred from inside subject by the name" do inner_subject_value = nil RSpec.describe do subject(:list) { [1, 2, 3] } describe 'first' do subject(:first_element) { list.first } example { inner_subject_value = subject } end end.run expect(inner_subject_value).to eq(1) end it 'can continue to be referenced by the name even when an inner group redefines the subject' do named_value = nil RSpec.describe do subject(:named) { :outer } describe "inner" do subject { :inner } example do subject # so the inner subject method is run and memoized named_value = self.named end end end.run expect(named_value).to eq(:outer) end it 'can continue to reference an inner subject after the outer subject name is referenced' do subject_value = nil RSpec.describe do subject(:named) { :outer } describe "inner" do subject { :inner } example do named # so the outer subject method is run and memoized subject_value = self.subject end end end.run expect(subject_value).to eq(:inner) end it 'is not overridden when an inner group defines a new method with the same name' do subject_value = nil RSpec.describe do subject(:named) { :outer_subject } describe "inner" do let(:named) { :inner_named } example { subject_value = self.subject } end end.run expect(subject_value).to be(:outer_subject) end context 'when `super` is used' do def should_raise_not_supported_error(&block) ex = nil RSpec.describe do let(:list) { ["a", "b", "c"] } subject { [1, 2, 3] } describe 'first' do module_exec(&block) if block subject(:list) { super().first(2) } ex = example { subject } end end.run expect(ex.execution_result.status).to eq(:failed) expect(ex.execution_result.exception.message).to match(/super.*not supported/) end it 'raises a "not supported" error' do should_raise_not_supported_error end context 'with a `let` definition before the named subject' do it 'raises a "not supported" error' do should_raise_not_supported_error do # My first pass implementation worked unless there was a `let` # declared before the named subject -- this let is in place to # ensure that bug doesn't return. let(:foo) { 3 } end end end end end end context "using 'self' as an explicit subject" do it "delegates matcher to the ExampleGroup" do group = RSpec.describe("group") do subject { self } def ok?; true; end def not_ok?; false; end it { should eq(self) } it { should be_ok } it { should_not be_not_ok } end expect(group.run).to be true end it 'supports a new expect-based syntax' do group = RSpec.describe([1, 2, 3]) do it { is_expected.to be_an Array } it { is_expected.not_to include 4 } end expect(group.run).to be true end end describe '#subject!' do let(:prepared_array) { [1,2,3] } subject! { prepared_array.pop } it "evaluates subject before example" do expect(prepared_array).to eq([1,2]) end it "returns memoized value from first invocation" do expect(subject).to eq(3) end end describe 'threadsafety', :threadsafe => true do before(:all) { eq 1 } # explanation: https://github.com/rspec/rspec-core/pull/1858/files#r25411166 context 'when not threadsafe' do # would be nice to not set this on the global before { RSpec.configuration.threadsafe = false } it 'can wind up overwriting the previous memoized value (but if you don\'t need threadsafety, this is faster)' do describe_successfully do let!(:order) { ThreadOrder.new } after { order.apocalypse! :join } let :memoized_value do if order.current == :second :second_access else order.pass_to :second, :resume_on => :exit :first_access end end example do order.declare(:second) { expect(memoized_value).to eq :second_access } expect(memoized_value).to eq :first_access end end end end context 'when threadsafe' do before(:context) { RSpec.configuration.threadsafe = true } specify 'first thread to access determines the return value' do describe_successfully do let!(:order) { ThreadOrder.new } after { order.apocalypse! :join } let :memoized_value do if order.current == :second :second_access else order.pass_to :second, :resume_on => :sleep :first_access end end example do order.declare(:second) { expect(memoized_value).to eq :first_access } expect(memoized_value).to eq :first_access end end end specify 'memoized block will only be evaluated once' do describe_successfully do let!(:order) { ThreadOrder.new } after { order.apocalypse! } before { @previously_accessed = false } let :memoized_value do raise 'Called multiple times!' if @previously_accessed @previously_accessed = true order.pass_to :second, :resume_on => :sleep end example do order.declare(:second) { memoized_value } memoized_value order.join_all end end end specify 'memoized blocks prevent other threads from accessing, even when it is accessed in a superclass' do describe_successfully do let!(:order) { ThreadOrder.new } after { order.apocalypse! :join } let!(:calls) { {:parent => 0, :child => 0} } let(:memoized_value) do calls[:parent] += 1 order.pass_to :second, :resume_on => :sleep 'parent' end describe 'child' do let :memoized_value do calls[:child] += 1 "#{super()}/child" end example do order.declare(:second) { expect(memoized_value).to eq 'parent/child' } expect(memoized_value).to eq 'parent/child' expect(calls).to eq :parent => 1, :child => 1 end end end end end end end RSpec.describe "#let" do let(:counter) do Class.new do def initialize @count = 0 end def count @count += 1 end end.new end let(:nil_value) do @nil_value_count += 1 nil end it "generates an instance method" do expect(counter.count).to eq(1) end it "caches the value" do expect(counter.count).to eq(1) expect(counter.count).to eq(2) end it "caches a nil value" do @nil_value_count = 0 nil_value nil_value expect(@nil_value_count).to eq(1) end let(:yield_the_example) do |example_yielded_to_let| @example_yielded_to_let = example_yielded_to_let end it "yields the example" do |example_yielded_to_example| yield_the_example expect(@example_yielded_to_let).to equal example_yielded_to_example end let(:regex_with_capture) { %r[RegexWithCapture(\d)] } it 'does not pass the block up the ancestor chain' do # Test for Ruby bug http://bugs.ruby-lang.org/issues/8059 expect("RegexWithCapture1".match(regex_with_capture)[1]).to eq('1') end it 'raises a useful error when called without a block' do expect do RSpec.describe { let(:list) } end.to raise_error(/#let or #subject called without a block/) end it 'raises an error when attempting to define a reserved name #initialize' do expect do RSpec.describe { let(:initialize) { true } } end.to raise_error(/#let or #subject called with reserved name `initialize`/) end it 'raises an error when attempting to define a reserved name #initialize as a string' do expect do RSpec.describe { let('initialize') { true } } end.to raise_error(/#let or #subject called with reserved name `initialize`/) end it 'raises an error when attempting to define a reserved name #to_s' do expect do RSpec.describe { let(:to_s) { true } } end.to raise_error(/#let or #subject called with reserved name `to_s`/) end it 'raises an error when attempting to define a reserved name #to_s as a string' do expect do RSpec.describe { let('to_s') { true } } end.to raise_error(/#let or #subject called with reserved name `to_s`/) end let(:a_value) { "a string" } context 'when overriding let in a nested context' do let(:a_value) { super() + " (modified)" } it 'can use `super` to reference the parent context value' do expect(a_value).to eq("a string (modified)") end end context 'when the declaration uses `return`' do let(:value) do return :early_exit if @early_exit :late_exit end it 'can exit the let declaration early' do @early_exit = true expect(value).to eq(:early_exit) end it 'can get past a conditional `return` statement' do @early_exit = false expect(value).to eq(:late_exit) end end [:before, :after].each do |hook| it "raises an error when referenced from `#{hook}(:all)`" do result = nil line = nil RSpec.describe do let(:foo) { nil } send(hook, :all) { result = (foo rescue $!) }; line = __LINE__ example { } end.run expect(result).to be_an(Exception) expect(result.message).to match(/let declaration `foo` accessed.*#{hook}\(:context\).*#{__FILE__}:#{line}/m) end end context "when included modules have hooks that define memoized helpers" do it "allows memoized helpers to override methods in previously included modules" do group = RSpec.describe do include Module.new { def self.included(m); m.let(:unrelated) { :unrelated }; end } include Module.new { def hello_message; "Hello from module"; end } let(:hello_message) { "Hello from let" } end expect(group.new.hello_message).to eq("Hello from let") end end end RSpec.describe "#let!" do subject { [1,2,3] } let!(:popped) { subject.pop } it "evaluates the value non-lazily" do expect(subject).to eq([1,2]) end it "returns memoized value from first invocation" do expect(popped).to eq(3) end end RSpec.describe 'using subject in before and let blocks' do shared_examples_for 'a subject' do let(:subject_id_in_let) { subject.object_id } before { @subject_id_in_before = subject.object_id } it 'should be memoized' do expect(subject_id_in_let).to eq(@subject_id_in_before) end it { is_expected.to eq(subject) } end describe Object do context 'with implicit subject' do it_should_behave_like 'a subject' end context 'with explicit subject' do subject { Object.new } it_should_behave_like 'a subject' end context 'with a constant subject'do subject { 123 } it_should_behave_like 'a subject' end end end RSpec.describe 'implicit block expectation syntax' do matcher :block_matcher do match { |actual| true } supports_block_expectations def supports_value_expectations? false end end subject { 'value or a Proc' } it '`should` prints a deprecation warning when given a value' do expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { should block_matcher }.not_to raise_error end it '`should_not` prints a deprecation warning when given a value' do expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { should_not block_matcher }.to raise_error(Exception) end end RSpec.describe 'Module#define_method' do it 'retains its normal private visibility on Ruby versions where it is normally private', :if => RUBY_VERSION < '2.5' do a_module = Module.new expect { a_module.define_method(:name) { "implementation" } }.to raise_error NoMethodError end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/shared_context_spec.rb0000664000000000000000000000624714557677674026241 0ustar rootrootRSpec.describe RSpec::SharedContext do it "is accessible as RSpec::Core::SharedContext" do RSpec::Core::SharedContext end it "is accessible as RSpec::SharedContext" do RSpec::SharedContext end it "supports before and after hooks" do before_all_hook = false before_each_hook = false after_each_hook = false after_all_hook = false shared = Module.new do extend RSpec::SharedContext before(:all) { before_all_hook = true } before(:each) { before_each_hook = true } after(:each) { after_each_hook = true } after(:all) { after_all_hook = true } end group = RSpec.describe do include shared example { } end group.run expect(before_all_hook).to be(true) expect(before_each_hook).to be(true) expect(after_each_hook).to be(true) expect(after_all_hook).to be(true) end include RSpec::Core::SharedExampleGroup::TopLevelDSL it "runs the before each hooks in configuration before those of the shared context" do ordered_hooks = [] RSpec.configure do |c| c.before(:each) { ordered_hooks << "config" } end RSpec.shared_context("before each stuff", :example => :before_each_hook_order) do before(:each) { ordered_hooks << "shared_context"} end group = RSpec.describe "description", :example => :before_each_hook_order do before(:each) { ordered_hooks << "example_group" } example {} end group.run expect(ordered_hooks).to be == ["config", "shared_context", "example_group"] end it "supports let" do shared = Module.new do extend RSpec::SharedContext let(:foo) { 'foo' } end group = RSpec.describe do include shared end expect(group.new.foo).to eq('foo') end it 'supports overriding let without warnings' do shared = Module.new do extend RSpec::SharedContext let(:foo) { 'foo' } end group = RSpec.describe do include shared let(:foo) { 'bar' } end expect(group.new.foo).to eq('bar') end it "supports let when applied to an individual example via metadata" do shared = Module.new do extend RSpec::SharedContext let(:foo) { "bar" } end RSpec.configuration.include shared, :include_it ex = value = nil RSpec.describe "group" do ex = example("ex1", :include_it) { value = foo } end.run expect(ex.execution_result).to have_attributes(:status => :passed, :exception => nil) expect(value).to eq("bar") end it 'supports explicit subjects' do shared = Module.new do extend RSpec::SharedContext subject { 17 } end group = RSpec.describe do include shared end expect(group.new.subject).to eq(17) end %w[describe context].each do |method_name| it "supports nested example groups using #{method_name}" do shared = Module.new do extend RSpec::SharedContext send(method_name, "nested using describe") do example {} end end group = RSpec.describe do include shared end group.run expect(group.children.length).to eq(1) expect(group.children.first.examples.length).to eq(1) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/0000775000000000000000000000000014557677674023671 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/blocking_pipe_bisect_spec.rb_0000664000000000000000000000033214557677674031523 0ustar rootroot# Deliberately named *.rb_ to avoid being loaded except when specified RSpec.describe "1000 tests" do puts "Try to saturate the pipe in Bisect command" (0..1000).each do |t| it { expect(t).to eq t } end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/utf8_encoded.rb0000664000000000000000000000021014557677674026556 0ustar rootroot# encoding: utf-8 module Custom class ExampleUTF8ClassNameVarietà def self.è così = :però così end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/a_bar.rb0000664000000000000000000000000014557677674025250 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/a_foo.rb0000664000000000000000000000000014557677674025267 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/formatter_specs.rb0000664000000000000000000000300114557677674027410 0ustar rootroot# Deliberately named _specs.rb to avoid being loaded except when specified RSpec.shared_examples_for "shared" do it "is marked as pending but passes" do pending expect(1).to eq(1) end end RSpec.describe "pending spec with no implementation" do it "is pending" end RSpec.describe "pending command with block format" do context "with content that would fail" do it "is pending" do pending expect(1).to eq(2) end end it_behaves_like "shared" end RSpec.describe "passing spec" do it "passes" do expect(1).to eq(1) end it 'passes with a multiple line description' do end end RSpec.describe "failing spec" do it "fails" do expect(1).to eq(2) end it "fails twice", :aggregate_failures do expect(1).to eq(2) expect(3).to eq(4) end end RSpec.describe "a failing spec with odd backtraces" do it "fails with a backtrace that has no file" do require 'erb' ERB.new("<%= raise 'foo' %>").result end it "fails with a backtrace containing an erb file" do e = Exception.new def e.backtrace ["/foo.html.erb:1:in `
': foo (RuntimeError)", " from /lib/ruby/1.9.1/erb.rb:753:in `eval'"] end def e.message # Redefining message steps around this behaviour # on JRuby: http://jira.codehaus.org/browse/JRUBY-5637 self.class.name end raise e end context "with a `nil` backtrace" do it "raises" do raise "boom" end after { |ex| ex.exception.set_backtrace(nil) } end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/fail_on_load_spec.rb_0000664000000000000000000000031214557677674027771 0ustar rootroot# Deliberately named *.rb_ to avoid being loaded except when specified RSpec.describe "A group" do puts "About to call misspelled method" contex "misspelled" do it "fails" do end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/custom_example_group_runner.rb0000664000000000000000000000032714557677674032052 0ustar rootrootmodule Custom class ExampleGroupRunner attr_reader :options, :arg def initialize(options, arg) @options, @arg = options, arg end def load_files(files) end def run end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/inconsistently_ordered_specs.rb0000664000000000000000000000043514557677674032206 0ustar rootroot# Deliberately named _specs.rb to avoid being loaded except when specified RSpec.configure do |c| c.register_ordering(:shuffled, &:shuffle) end RSpec.describe "Group", :order => :shuffled do 10.times do |i| it("passes #{i}") { } it("fails #{i}") { fail } end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/acceptance/0000775000000000000000000000000014557677674025757 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/acceptance/foo_spec.rb0000664000000000000000000000000014557677674030067 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/acceptance/bar.rb0000664000000000000000000000000014557677674027036 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/resources/a_spec.rb0000664000000000000000000000004514557677674025447 0ustar rootroot# Empty - used by ../options_spec.rb ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/configuration_options_spec.rb0000664000000000000000000005612714557677674027653 0ustar rootrootrequire 'ostruct' require 'rspec/core/drb' RSpec.describe RSpec::Core::ConfigurationOptions, :isolated_directory => true, :isolated_home => true do include ConfigOptionsHelper # On Ruby 2.4, `File.expand("~")` works even if `ENV['HOME']` is not set. # But on earlier versions, it fails. it "warns when HOME env var is not set", :unless => (RUBY_PLATFORM == 'java' || RSpec::Support::OS.windows? || RUBY_VERSION >= '2.4') do without_env_vars 'HOME' do expect_warning_with_call_site(__FILE__, __LINE__ + 1) RSpec::Core::ConfigurationOptions.new([]).options end end it "does not mutate the provided args array" do args = ['-e', 'some spec'] RSpec::Core::ConfigurationOptions.new(args).options expect(args).to eq(['-e', 'some spec']) end describe "#configure" do let(:config) { RSpec::Core::Configuration.new } it "configures deprecation_stream before loading requires (since required files may issue deprecations)" do opts = config_options_object(*%w[--deprecation-out path/to/log --require foo]) configuration = instance_double(RSpec::Core::Configuration).as_null_object opts.configure(configuration) expect(configuration).to have_received(:force).with({:deprecation_stream => "path/to/log"}).ordered expect(configuration).to have_received(:requires=).ordered end it "configures deprecation_stream before configuring filter_manager" do opts = config_options_object(*%w[--deprecation-out path/to/log --tag foo]) filter_manager = instance_double(RSpec::Core::FilterManager).as_null_object configuration = instance_double(RSpec::Core::Configuration, :filter_manager => filter_manager).as_null_object opts.configure(configuration) expect(configuration).to have_received(:force).with({:deprecation_stream => "path/to/log"}).ordered expect(filter_manager).to have_received(:include).with({:foo => true}).ordered end it "configures deprecation_stream before configuring formatters" do opts = config_options_object(*%w[--deprecation-out path/to/log --format doc]) configuration = instance_double(RSpec::Core::Configuration).as_null_object opts.configure(configuration) expect(configuration).to have_received(:force).with({:deprecation_stream => "path/to/log"}).ordered expect(configuration).to have_received(:add_formatter).ordered end it "sets dry_run before libs and requires" do opts = config_options_object(*%w[--dry-run --require a/path -I a/lib]) configuration = double("config").as_null_object expect(configuration).to receive(:force).with({:dry_run => true}).ordered expect(configuration).to receive(:libs=).ordered expect(configuration).to receive(:requires=).ordered opts.configure(configuration) end it "sends libs before requires" do opts = config_options_object(*%w[--require a/path -I a/lib]) configuration = double("config").as_null_object expect(configuration).to receive(:libs=).ordered expect(configuration).to receive(:requires=).ordered opts.configure(configuration) end it "loads requires before loading specs" do opts = config_options_object(*%w[-rspec_helper]) expect(config).to receive(:requires=).ordered expect(config).to receive(:get_files_to_run).ordered opts.configure(config) config.files_to_run end it "sets up load path and requires before formatter" do opts = config_options_object(*%w[--require a/path -f a/formatter]) configuration = double("config").as_null_object expect(configuration).to receive(:requires=).ordered expect(configuration).to receive(:add_formatter).ordered opts.configure(configuration) end it "sets default_path before loading specs" do opts = config_options_object(*%w[--default-path spec]) expect(config).to receive(:force).with({:default_path => 'spec'}).ordered expect(config).to receive(:get_files_to_run).ordered opts.configure(config) config.files_to_run end it "sets `files_or_directories_to_run` before `requires` so users can check `files_to_run` in a spec_helper loaded by `--require`" do opts = config_options_object(*%w[--require spec_helper]) expect(config).to receive(:files_or_directories_to_run=).ordered expect(config).to receive(:requires=).ordered opts.configure(config) end it "sets default_path before `files_or_directories_to_run` since it relies on it" do opts = config_options_object(*%w[--default-path spec]) expect(config).to receive(:force).with({:default_path => 'spec'}).ordered expect(config).to receive(:files_or_directories_to_run=).ordered opts.configure(config) end it 'configures the seed (via `order`) before requires so that required files can use the configured seed' do opts = config_options_object(*%w[ --seed 1234 --require spec_helper ]) expect(config).to receive(:force).with({:order => "rand:1234"}).ordered expect(config).to receive(:requires=).ordered opts.configure(config) end it 'configures `only_failures` before `files_or_directories_to_run` since it affects loaded files' do opts = config_options_object(*%w[ --only-failures ]) expect(config).to receive(:force).with({:only_failures => true}).ordered expect(config).to receive(:files_or_directories_to_run=).ordered opts.configure(config) end { "pattern" => :pattern, "exclude-pattern" => :exclude_pattern }.each do |flag, attr| it "sets #{attr} before `requires` so users can check `files_to_run` in a `spec_helper` loaded by `--require`" do opts = config_options_object(*%W[--require spec_helper --#{flag} **/*.spec]) expect(config).to receive(:force).with({attr => '**/*.spec'}).ordered expect(config).to receive(:requires=).ordered opts.configure(config) end end it "assigns inclusion_filter" do opts = config_options_object(*%w[--tag awesome]) opts.configure(config) expect(config.inclusion_filter.rules).to have_key(:awesome) end it "merges the :exclusion_filter option with the default exclusion_filter" do opts = config_options_object(*%w[--tag ~slow]) opts.configure(config) expect(config.exclusion_filter.rules).to have_key(:slow) end it "forces color" do opts = config_options_object(*%w[--color]) expect(config).to receive(:force).with({:color => true}) expect(config).to receive(:force).with({:color_mode => :automatic}) opts.configure(config) end it "forces force_color" do opts = config_options_object(*%w[--force-color]) expect(config).to receive(:force).with({:color_mode => :on}) opts.configure(config) end it "forces no_color" do opts = config_options_object(*%w[--no-color]) expect(config).to receive(:force).with({:color_mode => :off}) opts.configure(config) end [ ["--failure-exit-code", "3", :failure_exit_code, 3 ], ["--pattern", "foo/bar", :pattern, "foo/bar"], ["--failure-exit-code", "37", :failure_exit_code, 37], ["--default-path", "behavior", :default_path, "behavior"], ["--order", "rand", :order, "rand"], ["--seed", "37", :order, "rand:37"], ["--drb-port", "37", :drb_port, 37] ].each do |cli_option, cli_value, config_key, config_value| it "forces #{config_key}" do opts = config_options_object(cli_option, cli_value) expect(config).to receive(:force) do |pair| expect(pair.keys.first).to eq(config_key) expect(pair.values.first).to eq(config_value) end opts.configure(config) end end it "merges --require specified by multiple configuration sources" do with_env_vars 'SPEC_OPTS' => "--require file_from_env" do opts = config_options_object(*%w[--require file_from_opts]) expect(config).to receive(:require).with("file_from_opts") expect(config).to receive(:require).with("file_from_env") opts.configure(config) end end it "merges --I specified by multiple configuration sources" do with_env_vars 'SPEC_OPTS' => "-I dir_from_env" do opts = config_options_object(*%w[-I dir_from_opts]) expect(config).to receive(:libs=).with(["dir_from_opts", "dir_from_env"]) opts.configure(config) end end %w[ --only-failures --next-failure -n].each do |option| describe option do it "changes `config.only_failures?` to true" do opts = config_options_object(option) expect { opts.configure(config) }.to change(config, :only_failures?).from(a_falsey_value).to(true) end end end end describe "-c, --color, and --colour" do it "sets :color_mode => :automatic" do expect(parse_options('-c')).to include(:color_mode => :automatic) expect(parse_options('--color')).to include(:color_mode => :automatic) expect(parse_options('--colour')).to include(:color_mode => :automatic) end it "overrides previous color flag" do expect(parse_options('--no-color', '--color')).to include(:color_mode => :automatic) end end describe "--no-color" do it "sets :color_mode => :off" do expect(parse_options('--no-color')).to include(:color_mode => :off) end it "overrides previous color flag" do expect(parse_options('--color', '--no-color')).to include(:color_mode => :off) end end describe "--force-color" do it "sets :color_mode => :on" do expect(parse_options('--force-color')).to include(:color_mode => :on) end it "overrides previous color flag" do expect(parse_options('--color', '--force-color')).to include(:color_mode => :on) end end describe "-I" do example "adds to :libs" do expect(parse_options('-I', 'a_dir')).to include(:libs => ['a_dir']) end example "can be used more than once" do expect(parse_options('-I', 'dir_1', '-I', 'dir_2')).to include(:libs => ['dir_1','dir_2']) end end describe '--require' do example "requires files" do expect(parse_options('--require', 'a/path')).to include(:requires => ['a/path']) end example "can be used more than once" do expect(parse_options('--require', 'path/1', '--require', 'path/2')).to include(:requires => ['path/1','path/2']) end end describe "--format, -f" do it "sets :formatter" do [['--format', 'd'], ['-f', 'd'], '-fd'].each do |args| expect(parse_options(*args)).to include(:formatters => [['d']]) end end example "can accept a class name" do expect(parse_options('-fSome::Formatter::Class')).to include(:formatters => [['Some::Formatter::Class']]) end end describe "--profile, -p" do it "sets :profile_examples" do expect(parse_options('-p')).to include(:profile_examples => true) expect(parse_options('--profile')).to include(:profile_examples => true) expect(parse_options('-p', '4')).to include(:profile_examples => 4) expect(parse_options('--profile', '3')).to include(:profile_examples => 3) end end describe "--no-profile" do it "sets :profile_examples to false" do expect(parse_options('--no-profile')).to include(:profile_examples => false) end end describe "--example" do it "sets :full_description" do expect(parse_options('--example','foo')).to include(:full_description => [/foo/]) expect(parse_options('-e','bar')).to include(:full_description => [/bar/]) end end describe "--backtrace, -b" do it "sets full_backtrace on config" do expect(parse_options("--backtrace")).to include(:full_backtrace => true) expect(parse_options("-b")).to include(:full_backtrace => true) end end describe "--fail-fast" do it "defaults to nil" do expect(parse_options[:fail_fast]).to be(nil) end it "sets fail_fast to 1 on config" do expect(parse_options("--fail-fast")[:fail_fast]).to be(1) end it "sets fail_fast to false on config" do expect(parse_options("--no-fail-fast")[:fail_fast]).to be(false) end end describe "--failure-exit-code" do it "sets :failure_exit_code" do expect(parse_options('--failure-exit-code', '0')).to include(:failure_exit_code => 0) expect(parse_options('--failure-exit-code', '1')).to include(:failure_exit_code => 1) expect(parse_options('--failure-exit-code', '2')).to include(:failure_exit_code => 2) end it "overrides previous :failure_exit_code" do expect(parse_options('--failure-exit-code', '2', '--failure-exit-code', '3')).to include(:failure_exit_code => 3) end end describe "--error-exit-code" do it "sets :error_exit_code" do expect(parse_options('--error-exit-code', '0')).to include(:error_exit_code => 0) expect(parse_options('--error-exit-code', '1')).to include(:error_exit_code => 1) expect(parse_options('--error-exit-code', '2')).to include(:error_exit_code => 2) end it "overrides previous :error_exit_code" do expect(parse_options('--error-exit-code', '2', '--error-exit-code', '3')).to include(:error_exit_code => 3) end end describe "--dry-run" do it "defaults to nil" do expect(parse_options[:dry_run]).to be(nil) end it "sets dry_run on config" do expect(parse_options("--dry-run")[:dry_run]).to be(true) end end describe "--options" do it "sets :custom_options_file" do expect(parse_options(*%w[-O my.opts])).to include(:custom_options_file => "my.opts") expect(parse_options(*%w[--options my.opts])).to include(:custom_options_file => "my.opts") end end describe "--no-drb" do it "disables drb" do expect(parse_options("--no-drb")).to include(:drb => false) end it "overrides a previous drb => true" do expect(parse_options("--drb", "--no-drb")).to include(:drb => false) end it "gets overridden by a subsequent drb => true" do expect(parse_options("--no-drb", "--drb")).to include(:drb => true) end end describe "files_or_directories_to_run" do it "parses files from '-c file.rb dir/file.rb'" do expect(parse_options("-c", "file.rb", "dir/file.rb")).to include( :files_or_directories_to_run => ["file.rb", "dir/file.rb"] ) end it "parses dir from 'dir'" do expect(parse_options("dir")).to include(:files_or_directories_to_run => ["dir"]) end it "parses dir and files from 'spec/file1_spec.rb, spec/file2_spec.rb'" do expect(parse_options("dir", "spec/file1_spec.rb", "spec/file2_spec.rb")).to include( :files_or_directories_to_run => ["dir", "spec/file1_spec.rb", "spec/file2_spec.rb"] ) end it "parses file names that look like `default-path` option" do expect(parse_options("spec/default_path_spec.rb")).to include( :files_or_directories_to_run => ["spec/default_path_spec.rb"] ) end it "provides no files or directories if spec directory does not exist" do allow(FileTest).to receive(:directory?).with("spec").and_return false expect(parse_options()).to include(:files_or_directories_to_run => []) end end describe "default_path" do it "gets set before files_or_directories_to_run" do config = RSpec::Core::Configuration.new expect(config).to receive(:force).with({:default_path => 'foo'}).ordered expect(config).to receive(:get_files_to_run).ordered opts = config_options_object("--default-path", "foo") opts.configure(config) config.files_to_run end end describe "invalid options" do def expect_parsing_to_fail_mentioning_source(source, options=[]) expect { parse_options(*options) }.to raise_error(SystemExit).and output(a_string_including( "invalid option: --foo_bar (defined in #{source})", "Please use --help for a listing of valid options" )).to_stderr end %w[ ~/.rspec ./.rspec ./.rspec-local ].each do |file_name| context "defined in #{file_name}" do it "mentions the file name in the error so users know where to look for it" do file_name = File.expand_path(file_name) if file_name.start_with?("~") File.open(File.expand_path(file_name), "w") { |f| f << "--foo_bar" } expect_parsing_to_fail_mentioning_source(file_name) end end end context "defined in $XDG_CONFIG_HOME/rspec/options" do it "mentions the file name in the error so users know where to look for it" do file_name = File.expand_path("~/.config/rspec/options") create_fixture_file(file_name, "--foo_bar") expect_parsing_to_fail_mentioning_source(file_name) end end context "defined in SPEC_OPTS" do it "mentions ENV['SPEC_OPTS'] as the source in the error so users know where to look for it" do with_env_vars 'SPEC_OPTS' => "--foo_bar" do expect_parsing_to_fail_mentioning_source("ENV['SPEC_OPTS']") end end end context "defined in a custom file" do it "mentions the custom file as the source of the error so users know where to look for it" do File.open("./custom.opts", "w") {|f| f << "--foo_bar"} expect_parsing_to_fail_mentioning_source("./custom.opts", %w[-O ./custom.opts]) end context "passed at the command line" do it "does not mention the source since it is obvious where it came from" do expect { parse_options("--foo_bar") }.to raise_error(SystemExit).and output(a_string_including( "invalid option: --foo_bar\n", "Please use --help for a listing of valid options" )).to_stderr end end end end describe "sources: $XDG_CONFIG_HOME/rspec/options, ~/.rspec, ./.rspec, ./.rspec-local, custom, CLI, and SPEC_OPTS" do it "merges both global, local, SPEC_OPTS, and CLI" do create_fixture_file("./.rspec", "--require some_file") create_fixture_file("./.rspec-local", "--format global") create_fixture_file("~/.rspec", "--force-color") create_fixture_file("~/.config/rspec/options", "--order defined") with_env_vars 'SPEC_OPTS' => "--example 'foo bar'" do options = parse_options("--drb") # $XDG_CONFIG_HOME/rspec/options file ("order") is read, but ~/.rspec # file ("color") is not read because ~/.rspec has lower priority over # the file in the XDG config directory. expect(options[:order]).to eq("defined") expect(options[:color_mode]).to be_nil expect(options[:requires]).to eq(["some_file"]) expect(options[:full_description]).to eq([/foo\ bar/]) expect(options[:drb]).to be(true) expect(options[:formatters]).to eq([['global']]) end end it "reads ~/.rspec if $XDG_CONFIG_HOME/rspec/options is not found" do create_fixture_file("~/.rspec", "--force-color") options = parse_options() expect(options[:color_mode]).to eq(:on) expect(options[:order]).to be_nil end it "does not read ~/.rspec if $XDG_CONFIG_HOME/rspec/options is present" do create_fixture_file("~/.rspec", "--force-color") create_fixture_file("~/.config/rspec/options", "--order defined") options = parse_options() expect(options[:color_mode]).to be_nil expect(options[:order]).to eq("defined") end it "uses $XDG_CONFIG_HOME environment variable when set to find XDG global options" do create_fixture_file("~/.config/rspec/options", "--format default_xdg") create_fixture_file("~/.custom-config/rspec/options", "--format overridden_xdg") with_env_vars 'XDG_CONFIG_HOME' => "~/.custom-config" do options = parse_options() expect(options[:formatters]).to eq([['overridden_xdg']]) end without_env_vars 'XDG_CONFIG_HOME' do options = parse_options() expect(options[:formatters]).to eq([['default_xdg']]) end end it 'ignores file or dir names put in one of the option files or in SPEC_OPTS, since those are for persistent options' do create_fixture_file("./.rspec", "path/to/spec_1.rb" ) create_fixture_file("./.rspec-local", "path/to/spec_2.rb" ) create_fixture_file("~/.rspec", "path/to/spec_3.rb") create_fixture_file("~/.config/rspec/options", "path/to/spec_4.rb") with_env_vars 'SPEC_OPTS' => "path/to/spec_4.rb" do options = parse_options() expect(options[:files_or_directories_to_run]).to eq([]) end end it "prefers SPEC_OPTS over CLI" do with_env_vars 'SPEC_OPTS' => "--format spec_opts" do expect(parse_options("--format", "cli")[:formatters]).to eq([['spec_opts']]) end end it "prefers CLI over file options" do create_fixture_file("./.rspec", "--format project") create_fixture_file("~/.rspec", "--format global") create_fixture_file("~/.config/rspec/options", "--format xdg") expect(parse_options("--format", "cli")[:formatters]).to eq([['cli']]) end it "prefers CLI over file options for filter inclusion" do create_fixture_file("./.rspec", "--tag ~slow") opts = config_options_object("--tag", "slow") config = RSpec::Core::Configuration.new opts.configure(config) expect(config.inclusion_filter.rules).to have_key(:slow) expect(config.exclusion_filter.rules).not_to have_key(:slow) end it "prefers project file options over global file options" do create_fixture_file("./.rspec", "--format project") create_fixture_file("~/.rspec", "--format global") create_fixture_file("~/.config/rspec/options", "--format xdg") expect(parse_options[:formatters]).to eq([['project']]) end it "prefers local file options over project file options" do create_fixture_file("./.rspec-local", "--format local") create_fixture_file("./.rspec", "--format global") expect(parse_options[:formatters]).to eq([['local']]) end it "parses options file correctly if erb code has trimming options" do File.open("./.rspec", "w") do |f| f << "<% if true -%>\n" f << "--format local\n" f << "<%- end %>\n" end expect(parse_options[:formatters]).to eq([['local']]) end it 'ignores comment lines in option files' do create_fixture_file("./.rspec", "# --force-color\n # --format local") options = parse_options() expect(options[:color_mode]).to be_nil expect(parse_options[:formatters]).to be_nil end context "with custom options file" do it "ignores project and global options files" do create_fixture_file("./.rspec", "--format project") create_fixture_file("~/.rspec", "--format global") create_fixture_file("~/.config/rspec/options", "--format xdg") create_fixture_file("./custom.opts", "--force-color") options = parse_options("-O", "./custom.opts") expect(options[:format]).to be_nil expect(options[:color_mode]).to eq(:on) end it "parses -e 'full spec description'" do create_fixture_file("./custom.opts", "-e 'The quick brown fox jumps over the lazy dog'") options = parse_options("-O", "./custom.opts") expect(options[:full_description]).to eq([/The\ quick\ brown\ fox\ jumps\ over\ the\ lazy\ dog/]) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/invocations_spec.rb0000664000000000000000000001510114557677674025550 0ustar rootrootrequire 'rspec/core/drb' require 'rspec/core/bisect/coordinator' require 'rspec/core/project_initializer' module RSpec::Core RSpec.describe Invocations do let(:configuration_options) { instance_double(ConfigurationOptions) } let(:err) { StringIO.new } let(:out) { StringIO.new } def run_invocation subject.call(configuration_options, err, out) end describe Invocations::InitializeProject do it "initializes a project and returns a 0 exit code" do project_init = instance_double(ProjectInitializer, :run => nil) allow(ProjectInitializer).to receive_messages(:new => project_init) exit_code = run_invocation expect(project_init).to have_received(:run) expect(exit_code).to eq(0) end end describe Invocations::DRbWithFallback do context 'when a DRb server is running' do it "builds a DRbRunner and runs the specs" do drb_proxy = instance_double(RSpec::Core::DRbRunner, :run => 0) allow(RSpec::Core::DRbRunner).to receive(:new).and_return(drb_proxy) exit_code = run_invocation expect(drb_proxy).to have_received(:run).with(err, out) expect(exit_code).to eq(0) end end context 'when a DRb server is not running' do let(:runner) { instance_double(RSpec::Core::Runner, :run => 0) } before(:each) do allow(RSpec::Core::Runner).to receive(:new).and_return(runner) allow(RSpec::Core::DRbRunner).to receive(:new).and_raise(DRb::DRbConnError) end it "outputs a message" do run_invocation expect(err.string).to include( "No DRb server is running. Running in local process instead ..." ) end it "builds a runner instance and runs the specs" do run_invocation expect(RSpec::Core::Runner).to have_received(:new).with(configuration_options) expect(runner).to have_received(:run).with(err, out) end if RSpec::Support::RubyFeatures.supports_exception_cause? it "prevents the DRb error from being listed as the cause of expectation failures" do allow(RSpec::Core::Runner).to receive(:new) do |configuration_options| raise RSpec::Expectations::ExpectationNotMetError end expect { run_invocation }.to raise_error(RSpec::Expectations::ExpectationNotMetError) do |e| expect(e.cause).to be_nil end end end end end describe Invocations::Bisect do let(:original_cli_args) { %w[--bisect --seed 1234] } let(:configuration_options) { ConfigurationOptions.new(original_cli_args) } let(:success) { true } before do allow(RSpec::Core::Bisect::Coordinator).to receive(:bisect_with).and_return(success) end it "starts the bisection coordinator" do run_invocation expect(RSpec::Core::Bisect::Coordinator).to have_received(:bisect_with).with( an_instance_of(Runner), configuration_options.args, an_instance_of(Formatters::BisectProgressFormatter) ) end context "when the bisection is successful" do it "returns 0" do exit_code = run_invocation expect(exit_code).to eq(0) end end context "when the bisection is unsuccessful" do let(:success) { false } it "returns 1" do exit_code = run_invocation expect(exit_code).to eq(1) end context "with a custom failure code set" do it "returns the custom failure code" do in_sub_process do RSpec.configuration.failure_exit_code = 42 exit_code = run_invocation expect(exit_code).to eq(42) end end end end context "and the verbose option is specified" do let(:original_cli_args) { %w[--bisect=verbose --seed 1234] } it "starts the bisection coordinator with the debug formatter" do run_invocation expect(RSpec::Core::Bisect::Coordinator).to have_received(:bisect_with).with( an_instance_of(Runner), configuration_options.args, an_instance_of(Formatters::BisectDebugFormatter) ) end end end describe Invocations::PrintVersion do before do allow(subject).to receive(:require).and_call_original allow(subject).to receive(:require).with("rspec/rails/version").and_raise(LoadError) end it "prints the major.minor version of RSpec as a whole" do stub_const("RSpec::Core::Version::STRING", "9.18.23") run_invocation expect(out.string).to include("RSpec 9.18\n") end it "prints off the whole version if it's a pre-release" do stub_const("RSpec::Core::Version::STRING", "9.18.0-beta1") run_invocation expect(out.string).to include("RSpec 9.18.0-beta1\n") end it "prints off the version of each part of RSpec" do [:Core, :Expectations, :Mocks, :Support].each_with_index do |const_name, index| # validate that this is an existing const expect(RSpec.const_get(const_name)::Version::STRING).to be_a String stub_const("RSpec::#{const_name}::Version::STRING", "9.2.#{index}") end run_invocation expect(out.string).to include( "- rspec-core 9.2.0", "- rspec-expectations 9.2.1", "- rspec-mocks 9.2.2", "- rspec-support 9.2.3" ) end it "indicates a part is not installed if it cannot be loaded" do run_invocation expect(out.string).not_to include("rspec-rails") end it "returns a zero exit code" do expect(run_invocation).to eq 0 end end describe Invocations::PrintHelp do let(:parser) { instance_double(OptionParser) } let(:invalid_options) { %w[ -d ] } subject { described_class.new(parser, invalid_options) } before do allow(parser).to receive(:to_s).and_return(<<-EOS) -d --bisect[=verbose] Repeatedly runs the suite in order... EOS end it "prints the CLI options and returns a zero exit code" do exit_code = run_invocation expect(exit_code).to eq(0) expect(out.string).to include("--bisect") end it "won't display invalid options in the help output" do useless_lines = /^\s*-d\s*$\n/ run_invocation expect(out.string).to_not match(useless_lines) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/configuration_spec.rb0000664000000000000000000031065214557677674026074 0ustar rootrootrequire 'tmpdir' require 'rspec/support/spec/in_sub_process' module RSpec::Core RSpec.describe Configuration do include RSpec::Support::InSubProcess let(:config) { Configuration.new } let(:exclusion_filter) { config.exclusion_filter.rules } let(:inclusion_filter) { config.inclusion_filter.rules } before { config.world = RSpec.world } shared_examples_for "warning of deprecated `:example_group` during filtering configuration" do |method, *args| it "issues a deprecation warning when filtering by `:example_group`" do args << { :example_group => { :file_location => /spec\/unit/ } } expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /:example_group/) config.__send__(method, *args) end end describe '#on_example_group_definition' do before do RSpec.configure do |c| c.on_example_group_definition do |example_group| example_group.examples.first.metadata[:new_key] = :new_value end end end it 'successfully invokes the block' do RSpec.describe("group") { it "example 1" do; end} example = RSpec.world.example_groups.first.examples.first expect(example.metadata[:new_key]).to eq(:new_value) end end describe "#fail_fast" do it "defaults to `nil`" do expect(RSpec::Core::Configuration.new.fail_fast).to be(nil) end end describe "#fail_fast=" do context 'when true' do it 'is set to true' do config.fail_fast = true expect(config.fail_fast).to eq true end end context "when 'true'" do it 'is set to true' do config.fail_fast = 'true' expect(config.fail_fast).to eq true end end context "when false" do it 'is set to false' do config.fail_fast = false expect(config.fail_fast).to eq false end end context "when 'false'" do it 'is set to false' do config.fail_fast = 'false' expect(config.fail_fast).to eq false end end context "when 0" do it 'is set to false' do config.fail_fast = 0 expect(config.fail_fast).to eq false end end context "when integer number" do it 'is set to number' do config.fail_fast = 5 expect(config.fail_fast).to eq 5 end end context "when floating point number" do it 'is set to integer number' do config.fail_fast = 5.9 expect(config.fail_fast).to eq 5 end end context "when string representing an integer number" do it 'is set to number' do config.fail_fast = '5' expect(config.fail_fast).to eq 5 end end context "when nil" do it 'is nil' do config.fail_fast = nil expect(config.fail_fast).to eq nil end end context "when unrecognized value" do before do allow(RSpec).to receive(:warning) end it 'prints warning' do config.fail_fast = 'yes' expect(RSpec).to have_received(:warning).with(/Cannot set `RSpec.configuration.fail_fast`/i) end it 'is set to true' do config.fail_fast = 'yes' expect(config.fail_fast).to eq true end end end describe 'fail_if_no_examples' do it 'defaults to false' do expect(RSpec::Core::Configuration.new.fail_if_no_examples).to be(false) end it 'can be set to true' do config.fail_if_no_examples = true expect(config.fail_if_no_examples).to eq(true) end it 'can be set to false' do config.fail_if_no_examples = false expect(config.fail_if_no_examples).to eq(false) end end describe '#deprecation_stream' do it 'defaults to standard error' do expect($rspec_core_without_stderr_monkey_patch.deprecation_stream).to eq STDERR end it 'is configurable' do io = StringIO.new config.deprecation_stream = io expect(config.deprecation_stream).to eq io end context 'when the reporter has already been initialized' do before do config.reporter allow(config).to receive(:warn) end it 'prints a notice indicating the reconfigured output_stream will be ignored' do config.deprecation_stream = double("IO") expect(config).to have_received(:warn).with(/deprecation_stream.*#{__FILE__}:#{__LINE__ - 1}/) end it 'does not change the value of `deprecation_stream`' do value = config.deprecation_stream config.deprecation_stream = double("IO") expect(config.deprecation_stream).to equal(value) end it 'does not print a warning if set to the value it already has' do config.deprecation_stream = config.deprecation_stream expect(config).not_to have_received(:warn) end end end describe "#output_stream" do it 'defaults to standard output' do expect(config.output_stream).to eq $stdout end end describe "#output_stream=" do it 'is configurable' do io = StringIO.new config.output_stream = io expect(config.output_stream).to eq io end context 'when the reporter has already been initialized' do before do config.reporter allow(config).to receive(:warn) end it 'prints a notice indicating the reconfigured output_stream will be ignored' do config.output_stream = StringIO.new expect(config).to have_received(:warn).with(/output_stream.*#{__FILE__}:#{__LINE__ - 1}/) end it 'does not change the value of `output_stream`' do config.output_stream = StringIO.new expect(config.output_stream).to eq($stdout) end it 'does not print a warning if set to the value it already has' do config.output_stream = config.output_stream expect(config).not_to have_received(:warn) end end end describe "#requires=" do def absolute_path_to(dir) File.expand_path("../../../../#{dir}", __FILE__) end it 'adds `lib` to the load path' do lib_dir = absolute_path_to("lib") $LOAD_PATH.delete(lib_dir) expect($LOAD_PATH).not_to include(lib_dir) config.requires = [] expect($LOAD_PATH).to include(lib_dir) end it 'adds the configured `default_path` to the load path' do config.default_path = 'features' foo_dir = absolute_path_to("features") expect($LOAD_PATH).not_to include(foo_dir) config.requires = [] expect($LOAD_PATH).to include(foo_dir) end it 'stores the required files' do expect(config).to receive(:require).with('a/path') config.requires = ['a/path'] expect(config.requires).to eq ['a/path'] end context "when `default_path` refers to a file rather than a directory" do it 'does not add it to the load path' do config.default_path = 'Rakefile' config.requires = [] expect($LOAD_PATH).not_to include(match(/Rakefile/)) end end end describe "#load_spec_files" do it "loads files using load" do config.files_to_run = ["foo.bar", "blah_spec.rb"] expect(config).to receive(:load).twice config.load_spec_files end it "loads each file once, even if duplicated in list" do config.files_to_run = ["a_spec.rb", "a_spec.rb"] expect(config).to receive(:load).once config.load_spec_files end end describe "#mock_framework" do it "defaults to :rspec" do expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/rspec') expect(config.mock_framework).to eq(MockingAdapters::RSpec) end context "when rspec-mocks is not installed" do it 'gracefully falls back to :nothing' do allow(RSpec::Support).to receive(:require_rspec_core).and_call_original allow(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/rspec').and_raise(LoadError) expect(config.mock_framework).to eq(MockingAdapters::Null) end end end describe "#mock_framework="do it "delegates to mock_with" do expect(config).to receive(:mock_with).with(:rspec) config.mock_framework = :rspec end end shared_examples "a configurable framework adapter" do |m| it "yields a config object if the framework_module supports it" do mod = Module.new def mod.configuration; @config ||= Struct.new(:custom_setting).new; end config.send m, mod do |mod_config| mod_config.custom_setting = true end expect(mod.configuration.custom_setting).to be(true) end it "raises if framework module doesn't support configuration" do mod = Module.new expect { config.send m, mod do |mod_config| end }.to raise_error(/must respond to `configuration`/) end end describe "#mock_with" do before { allow(config).to receive(:require) } it_behaves_like "a configurable framework adapter", :mock_with it "allows rspec-mocks to be configured with a provided block" do mod = Module.new expect(RSpec::Mocks.configuration).to receive(:add_stub_and_should_receive_to).with(mod) config.mock_with :rspec do |c| c.add_stub_and_should_receive_to mod end end context "with a module" do it "sets the mock_framework_adapter to that module" do mod = Module.new config.mock_with mod expect(config.mock_framework).to eq(mod) end end it 'uses the named adapter' do expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/mocha') stub_const("RSpec::Core::MockingAdapters::Mocha", Module.new) config.mock_with :mocha end it "uses the null adapter when given :nothing" do expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/null').and_call_original config.mock_with :nothing end it "raises an error when given an unknown key" do expect { config.mock_with :crazy_new_mocking_framework_ive_not_yet_heard_of }.to raise_error(ArgumentError, /unknown mocking framework/i) end it "raises an error when given another type of object" do expect { config.mock_with Object.new }.to raise_error(ArgumentError, /unknown mocking framework/i) end context 'when there are already some example groups defined' do before { allow(RSpec::Support).to receive(:require_rspec_core) } it 'raises an error since this setting must be applied before any groups are defined' do allow(RSpec.world).to receive(:example_groups).and_return([double.as_null_object]) class_double("RSpec::Core::MockingAdapters::Mocha", :framework_name => :mocha).as_stubbed_const expect { config.mock_with :mocha }.to raise_error(/must be configured before any example groups are defined/) end it 'does not raise an error if the default `mock_with :rspec` is re-configured' do config.mock_framework # called by RSpec when configuring the first example group allow(RSpec.world).to receive(:example_groups).and_return([double.as_null_object]) config.mock_with :rspec end it 'does not raise an error if re-setting the same config' do class_double("RSpec::Core::MockingAdapters::Mocha", :framework_name => :mocha).as_stubbed_const groups = [] allow(RSpec.world).to receive_messages(:example_groups => groups) config.mock_with :mocha groups << double.as_null_object config.mock_with :mocha end end end describe "#expectation_frameworks" do it "defaults to :rspec" do expect(config).to receive(:require).with('rspec/expectations') expect(config.expectation_frameworks).to eq([RSpec::Matchers]) end context "when rspec-expectations is not installed" do def an_anonymous_module name = RUBY_VERSION.to_f < 1.9 ? '' : nil an_object_having_attributes(:class => Module, :name => name) end it 'gracefully falls back to an anonymous module' do allow(config).to receive(:require).with('rspec/expectations').and_raise(LoadError) expect(config.expectation_frameworks).to match([an_anonymous_module]) end end end describe "#expectation_framework=" do it "delegates to expect_with" do expect(config).to receive(:expect_with).with(:rspec) config.expectation_framework = :rspec end end def stub_expectation_adapters stub_const("Test::Unit::Assertions", Module.new) stub_const("Minitest::Assertions", Module.new) stub_const("RSpec::Core::TestUnitAssertionsAdapter", Module.new) stub_const("RSpec::Core::MinitestAssertionsAdapter", Module.new) allow(config).to receive(:require) end describe "#expect_with" do before do stub_expectation_adapters end it_behaves_like "a configurable framework adapter", :expect_with context "with :rspec" do it "requires rspec/expectations" do expect(config).to receive(:require).with('rspec/expectations') config.expect_with :rspec end it "sets the expectation framework to ::RSpec::Matchers" do config.expect_with :rspec expect(config.expectation_frameworks).to eq [::RSpec::Matchers] end end context "with :test_unit" do it "requires rspec/core/test_unit_assertions_adapter" do expect(config).to receive(:require). with('rspec/core/test_unit_assertions_adapter') config.expect_with :test_unit end it "sets the expectation framework to ::Test::Unit::Assertions" do config.expect_with :test_unit expect(config.expectation_frameworks).to eq [ ::RSpec::Core::TestUnitAssertionsAdapter ] end end context "with :minitest" do it "requires rspec/core/minitest_assertions_adapter" do expect(config).to receive(:require). with('rspec/core/minitest_assertions_adapter') config.expect_with :minitest end it "sets the expectation framework to ::Minitest::Assertions" do config.expect_with :minitest expect(config.expectation_frameworks).to eq [ ::RSpec::Core::MinitestAssertionsAdapter ] end end it "supports multiple calls" do config.expect_with :rspec config.expect_with :minitest expect(config.expectation_frameworks).to eq [ RSpec::Matchers, RSpec::Core::MinitestAssertionsAdapter ] end it "raises if block given with multiple args" do expect { config.expect_with :rspec, :minitest do |mod_config| end }.to raise_error(/expect_with only accepts/) end it "raises ArgumentError if framework is not supported" do expect do config.expect_with :not_supported end.to raise_error(ArgumentError) end context 'when there are already some example groups defined' do it 'raises an error since this setting must be applied before any groups are defined' do allow(RSpec.world).to receive(:example_groups).and_return([double.as_null_object]) expect { config.expect_with :rspec }.to raise_error(/must be configured before any example groups are defined/) end it 'does not raise an error if the default `expect_with :rspec` is re-configured' do config.expectation_frameworks # called by RSpec when configuring the first example group allow(RSpec.world).to receive(:example_groups).and_return([double.as_null_object]) config.expect_with :rspec end it 'does not raise an error if re-setting the same config' do groups = [] allow(RSpec.world).to receive_messages(:example_groups => groups) config.expect_with :minitest groups << double.as_null_object config.expect_with :minitest end end end describe "#files_to_run" do it "loads files not following pattern if named explicitly" do assign_files_or_directories_to_run "spec/rspec/core/resources/a_bar.rb" expect(config.files_to_run).to contain_files("spec/rspec/core/resources/a_bar.rb") end it "prevents repetition of dir when start of the pattern" do config.pattern = "spec/**/a_spec.rb" assign_files_or_directories_to_run "spec" expect(config.files_to_run).to contain_files("spec/rspec/core/resources/a_spec.rb") end it "does not prevent repetition of dir when later of the pattern" do config.pattern = "rspec/**/a_spec.rb" assign_files_or_directories_to_run "spec" expect(config.files_to_run).to contain_files("spec/rspec/core/resources/a_spec.rb") end it "supports patterns starting with ./" do config.pattern = "./spec/**/a_spec.rb" assign_files_or_directories_to_run "spec" expect(config.files_to_run).to contain_files("./spec/rspec/core/resources/a_spec.rb") end it "supports absolute path patterns", :emits_warning_on_windows_on_old_ruby do dir = File.expand_path("../resources", __FILE__) config.pattern = File.join(dir, "**/*_spec.rb") assign_files_or_directories_to_run "spec" expect(config.files_to_run).to contain_files( "./spec/rspec/core/resources/acceptance/foo_spec.rb", "./spec/rspec/core/resources/a_spec.rb" ) end it "supports relative path patterns for an alternate directory from `spec`" do Dir.chdir("./spec/rspec/core") do config.pattern = "resources/**/*_spec.rb" assign_files_or_directories_to_run "spec" # default dir expect(config.files_to_run).to contain_files( "resources/acceptance/foo_spec.rb", "resources/a_spec.rb" ) end end it "does not attempt to treat the pattern relative to `.` if it uses `**` in the first path segment as that would cause it load specs from vendored gems" do Dir.chdir("./spec/rspec/core") do config.pattern = "**/*_spec.rb" assign_files_or_directories_to_run "spec" # default dir expect(config.files_to_run).to contain_files() end end it 'reloads when `files_or_directories_to_run` is reassigned' do config.pattern = "spec/**/a_spec.rb" config.files_or_directories_to_run = "empty_dir" expect { config.files_or_directories_to_run = "spec" }.to change { config.files_to_run }. to(a_file_collection("spec/rspec/core/resources/a_spec.rb")) end it 'attempts to load the provided file names' do assign_files_or_directories_to_run "path/to/some/file.rb" expect(config.files_to_run).to contain_files("path/to/some/file.rb") end it 'does not attempt to load a file at the `default_path`' do config.default_path = "path/to/dir" assign_files_or_directories_to_run "path/to/dir" expect(config.files_to_run).to eq([]) end context "with :" do it "overrides inclusion filters set before config" do config.force(:inclusion_filter => {:foo => :bar}) assign_files_or_directories_to_run "path/to/file.rb:37" expect(inclusion_filter.size).to eq(1) expect(inclusion_filter[:locations].keys.first).to match(/path\/to\/file\.rb$/) expect(inclusion_filter[:locations].values.first).to eq([37]) end it "clears exclusion filters set before config" do config.force(:exclusion_filter => { :foo => :bar }) assign_files_or_directories_to_run "path/to/file.rb:37" expect(config.exclusion_filter).to be_empty, "expected exclusion filter to be empty:\n#{config.exclusion_filter}" end end context "with default pattern" do it "loads files named _spec.rb" do assign_files_or_directories_to_run "spec/rspec/core/resources" expect(config.files_to_run).to contain_files("spec/rspec/core/resources/a_spec.rb", "spec/rspec/core/resources/acceptance/foo_spec.rb") end it "loads files in Windows", :if => RSpec::Support::OS.windows? do assign_files_or_directories_to_run "C:\\path\\to\\project\\spec\\sub\\foo_spec.rb" expect(config.files_to_run).to contain_files("C:/path/to/project/spec/sub/foo_spec.rb") end it "loads files in Windows when directory is specified", :failing_on_windows_ci, :if => RSpec::Support::OS.windows? do assign_files_or_directories_to_run "spec\\rspec\\core\\resources" expect(config.files_to_run).to contain_files("spec/rspec/core/resources/a_spec.rb") end it_behaves_like "handling symlinked directories when loading spec files" do def loaded_files assign_files_or_directories_to_run "spec" config.files_to_run end end end context "with default default_path" do it "loads files in the default path when run by rspec" do allow(config).to receive(:command) { 'rspec' } assign_files_or_directories_to_run [] expect(config.files_to_run).not_to be_empty end it "loads files in the default path when run with DRB (e.g., spork)" do allow(config).to receive(:command) { 'spork' } allow(RSpec::Core::Runner).to receive(:running_in_drb?) { true } assign_files_or_directories_to_run [] expect(config.files_to_run).not_to be_empty end it "does not load files in the default path when run by ruby" do allow(config).to receive(:command) { 'ruby' } assign_files_or_directories_to_run [] expect(config.files_to_run).to be_empty end end it 'loads files in passed directories in alphabetical order to avoid OS-specific file-globbing non-determinism' do define_dirs "spec/unit" => [ ["spec/unit/b_spec.rb", "spec/unit/a_spec.rb"], ["spec/unit/a_spec.rb", "spec/unit/b_spec.rb"] ] expect(assign_files_or_directories_to_run "spec/unit").to match [ file_at("spec/unit/a_spec.rb"), file_at("spec/unit/b_spec.rb") ] expect(assign_files_or_directories_to_run "spec/unit").to match [ file_at("spec/unit/a_spec.rb"), file_at("spec/unit/b_spec.rb") ] end it 'respects the user-specified order of files and directories passed at the command line' do define_dirs "spec/b" => [["spec/b/1_spec.rb", "spec/b/2_spec.rb"]], "spec/c" => [["spec/c/1_spec.rb", "spec/c/2_spec.rb"]] expect(assign_files_or_directories_to_run "spec/b", "spec/a1_spec.rb", "spec/c", "spec/a2_spec.rb").to match [ file_at("spec/b/1_spec.rb"), file_at("spec/b/2_spec.rb"), file_at("spec/a1_spec.rb"), file_at("spec/c/1_spec.rb"), file_at("spec/c/2_spec.rb"), file_at("spec/a2_spec.rb") ] end it 'deduplicates spec files that are listed individually and present in a passed dir' do define_dirs "spec/unit" => [[ "spec/unit/a_spec.rb", "spec/unit/b_spec.rb", "spec/unit/c_spec.rb" ]] expect(assign_files_or_directories_to_run "spec/unit/b_spec.rb", "spec/unit").to match [ file_at("spec/unit/b_spec.rb"), file_at("spec/unit/a_spec.rb"), file_at("spec/unit/c_spec.rb") ] expect(assign_files_or_directories_to_run "spec/unit", "spec/unit/b_spec.rb").to match [ file_at("spec/unit/a_spec.rb"), file_at("spec/unit/b_spec.rb"), file_at("spec/unit/c_spec.rb") ] end def define_dirs(dirs_hash) allow(File).to receive(:directory?) do |path| !path.end_with?(".rb") end allow(Dir).to receive(:[]).and_return([]) dirs_hash.each do |dir, sequential_glob_return_values| allow(Dir).to receive(:[]).with( a_string_including(dir, config.pattern) ).and_return(*sequential_glob_return_values) end end def file_at(relative_path) eq(relative_path).or eq(File.expand_path(relative_path)) end end describe "#pattern" do context "with single pattern" do before { config.pattern = "**/*_foo.rb" } it "loads all explicitly specified files, even those that do not match the pattern" do file_1 = File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb") file_2 = File.expand_path(File.dirname(__FILE__) + "/resources/a_bar.rb") assign_files_or_directories_to_run file_1, file_2 expect(config.files_to_run).to contain_exactly(file_1, file_2) end it "loads files in directories following pattern" do dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).to include("#{dir}/a_foo.rb") end it "does not load files in directories not following pattern" do dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).not_to include("#{dir}/a_bar.rb") end it "ignores pattern if files are specified" do files = [ File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb"), File.expand_path(File.dirname(__FILE__) + "/resources/a_spec.rb") ] assign_files_or_directories_to_run(files) expect(config.files_to_run).to match_array(files) end end context "with multiple patterns" do it "supports comma separated values" do config.pattern = "**/*_foo.rb,**/*_bar.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).to include("#{dir}/a_foo.rb") expect(config.files_to_run).to include("#{dir}/a_bar.rb") end it "supports comma separated values with spaces" do config.pattern = "**/*_foo.rb, **/*_bar.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).to include("#{dir}/a_foo.rb") expect(config.files_to_run).to include("#{dir}/a_bar.rb") end it "supports curly braces glob syntax" do config.pattern = "**/*_{foo,bar}.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).to include("#{dir}/a_foo.rb") expect(config.files_to_run).to include("#{dir}/a_bar.rb") end end context "after files have already been loaded" do it 'warns that it will have no effect' do expect_warning_with_call_site(__FILE__, __LINE__ + 2, /has no effect/) config.load_spec_files config.pattern = "rspec/**/*.spec" end it 'does not warn if reset is called after load_spec_files' do config.load_spec_files config.reset expect(RSpec).to_not receive(:warning) config.pattern = "rspec/**/*.spec" end end context "after `files_to_run` has been accessed but before files have been loaded" do it 'still takes affect' do file = File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb") assign_files_or_directories_to_run File.dirname(file) expect(config.files_to_run).not_to include(file) config.pattern = "**/*_foo.rb" expect(config.files_to_run).to include(file) end end end describe "#exclude_pattern" do context "with single pattern" do before { config.exclude_pattern = "**/*_foo.rb" } it "does not load files in directories following exclude pattern" do dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).not_to include("#{dir}/a_foo.rb") end it "loads files in directories not following exclude pattern" do dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).to include("#{dir}/a_spec.rb") end it "ignores exclude_pattern if files are specified" do files = [ File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb"), File.expand_path(File.dirname(__FILE__) + "/resources/a_spec.rb") ] assign_files_or_directories_to_run(files) expect(config.files_to_run).to match_array(files) end end context "with multiple patterns" do it "supports comma separated values" do config.exclude_pattern = "**/*_foo.rb,**/*_bar.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).not_to include("#{dir}/a_foo.rb") expect(config.files_to_run).not_to include("#{dir}/a_bar.rb") end it "supports comma separated values with spaces" do config.exclude_pattern = "**/*_foo.rb, **/*_bar.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).not_to include("#{dir}/a_foo.rb") expect(config.files_to_run).not_to include("#{dir}/a_bar.rb") end it "supports curly braces glob syntax" do config.exclude_pattern = "**/*_{foo,bar}.rb" dir = File.expand_path(File.dirname(__FILE__) + "/resources") assign_files_or_directories_to_run dir expect(config.files_to_run).not_to include("#{dir}/a_foo.rb") expect(config.files_to_run).not_to include("#{dir}/a_bar.rb") end end context "after files have already been loaded" do it 'warns that it will have no effect' do expect_warning_with_call_site(__FILE__, __LINE__ + 2, /has no effect/) config.load_spec_files config.exclude_pattern = "rspec/**/*.spec" end it 'does not warn if reset is called after load_spec_files' do config.load_spec_files config.reset expect(RSpec).to_not receive(:warning) config.exclude_pattern = "rspec/**/*.spec" end end context "after `files_to_run` has been accessed but before files have been loaded" do it 'still takes affect' do config.pattern = "**/*.rb" file = File.expand_path(File.dirname(__FILE__) + "/resources/a_foo.rb") assign_files_or_directories_to_run File.dirname(file) expect(config.files_to_run).to include(file) config.exclude_pattern = "**/*_foo.rb" expect(config.files_to_run).not_to include(file) end end end context "with full_description set" do it "overrides filters" do config.filter_run :focused => true config.full_description = "foo" expect(inclusion_filter).not_to have_key(:focused) end it 'is possible to access the full description regular expression' do config.full_description = "foo" expect(config.full_description).to eq(/foo/) end end context "without full_description having been set" do it 'returns nil from #full_description' do expect(config.full_description).to eq nil end end context "with line number" do it "assigns the file and line number as a location filter" do assign_files_or_directories_to_run "path/to/a_spec.rb:37" expect(inclusion_filter).to eq({:locations => {File.expand_path("path/to/a_spec.rb") => [37]}}) end it "assigns multiple files with line numbers as location filters" do assign_files_or_directories_to_run "path/to/a_spec.rb:37", "other_spec.rb:44" expect(inclusion_filter).to eq({:locations => {File.expand_path("path/to/a_spec.rb") => [37], File.expand_path("other_spec.rb") => [44]}}) end it "assigns files with multiple line numbers as location filters" do assign_files_or_directories_to_run "path/to/a_spec.rb:37", "path/to/a_spec.rb:44" expect(inclusion_filter).to eq({:locations => {File.expand_path("path/to/a_spec.rb") => [37, 44]}}) end end context "with multiple line numbers" do it "assigns the file and line numbers as a location filter" do assign_files_or_directories_to_run "path/to/a_spec.rb:1:3:5:7" expect(inclusion_filter).to eq({:locations => {File.expand_path("path/to/a_spec.rb") => [1,3,5,7]}}) end end it "allows file names with brackets" do assign_files_or_directories_to_run "./path/to/a_[1:2]spec.rb" expect(config.files_to_run).to contain_files("./path/to/a_[1:2]spec.rb") assign_files_or_directories_to_run "./path/to/a_spec.rb[foo]" expect(config.files_to_run).to contain_files("./path/to/a_spec.rb[foo]") end context "with an example id" do it "assigns the file and id as an ids filter" do assign_files_or_directories_to_run "./path/to/a_spec.rb[1:2]" expect(inclusion_filter).to eq(:ids => { "./path/to/a_spec.rb" => ["1:2"] }) end end context "with a single file with multiple example ids" do it "assigns the file and ids as an ids filter" do assign_files_or_directories_to_run "./path/to/a_spec.rb[1:2,1:3]" expect(inclusion_filter).to eq(:ids => { "./path/to/a_spec.rb" => ["1:2", "1:3"] }) end it "ignores whitespace between scoped ids" do assign_files_or_directories_to_run "./path/to/a_spec.rb[1:2 , 1:3]" expect(inclusion_filter).to eq(:ids => { "./path/to/a_spec.rb" => ["1:2", "1:3"] }) end end context "with multiple files with ids" do it "assigns all of them to the ids filter" do assign_files_or_directories_to_run "./path/to/a_spec.rb[1:2,1:3]", "./path/to/b_spec.rb[1:4]" expect(inclusion_filter).to eq(:ids => { "./path/to/a_spec.rb" => ["1:2", "1:3"], "./path/to/b_spec.rb" => ["1:4"] }) end end context "with the same file specified multiple times with different scoped ids" do it "unions all the ids" do assign_files_or_directories_to_run "./path/to/a_spec.rb[1:2]", "./path/to/a_spec.rb[1:3]" expect(inclusion_filter).to eq(:ids => { "./path/to/a_spec.rb" => ["1:2", "1:3"] }) end end it "assigns the example name as the filter on description" do config.full_description = "foo" expect(inclusion_filter).to eq({:full_description => /foo/}) end it "assigns the example names as the filter on description if description is an array" do config.full_description = [ "foo", "bar" ] expect(inclusion_filter).to eq({:full_description => Regexp.union(/foo/, /bar/)}) end it 'is possible to access the full description regular expression' do config.full_description = "foo","bar" expect(config.full_description).to eq Regexp.union(/foo/,/bar/) end describe "#default_path" do it 'defaults to "spec"' do expect(config.default_path).to eq('spec') end it 'adds to the `project_source_dirs`' do expect { config.default_path = 'test' }.to change { config.project_source_dirs.include?('test') }.from(false).to(true) end end config_methods = %w[ include extend ] config_methods << "prepend" if RSpec::Support::RubyFeatures.module_prepends_supported? config_methods.each do |config_method| it "raises an immediate `TypeError` when you attempt to `config.#{config_method}` with something besides a module" do expect { config.send(config_method, :not_a_module) }.to raise_error(TypeError, a_string_including( "configuration.#{config_method}", "expects a module but got", "not_a_module" )) end end describe "#include_context" do context "with no metadata filters" do it 'includes the named shared example group in all groups' do RSpec.shared_examples "shared group" do let(:foo) { 17 } end RSpec.configuration.include_context "shared group" expect(RSpec.describe.new.foo).to eq 17 end end context "with metadata filters" do it 'includes the named shared example group in matching groups' do RSpec.shared_examples "shared group" do let(:foo) { 18 } end RSpec.configuration.include_context "shared group", :include_it expect(RSpec.describe.new).not_to respond_to(:foo) expect(RSpec.describe("", :include_it).new.foo).to eq 18 end it 'includes the named shared example group in the singleton class of matching examples' do RSpec.shared_examples "shared group" do let(:foo) { 19 } end RSpec.configuration.include_context "shared group", :include_it foo_value = nil describe_successfully do it { expect { self.foo }.to raise_error(NoMethodError) } it("", :include_it) { foo_value = foo } end expect(foo_value).to eq 19 end end end describe "#include" do include_examples "warning of deprecated `:example_group` during filtering configuration", :include, Enumerable module InstanceLevelMethods def you_call_this_a_blt? "egad man, where's the mayo?!?!?" end end it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.include(InstanceLevelMethods, *args) config.instance_variable_get(:@include_modules).items_and_filters.last.last end end context "with no filter" do it "includes the given module into each example group" do RSpec.configure do |c| c.include(InstanceLevelMethods) end group = RSpec.describe('does like, stuff and junk', :magic_key => :include) { } expect(group).not_to respond_to(:you_call_this_a_blt?) expect(group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") end it "includes the given module into each existing example group" do group = RSpec.describe('does like, stuff and junk', :magic_key => :include) { } RSpec.configure do |c| c.include(InstanceLevelMethods) end expect(group).not_to respond_to(:you_call_this_a_blt?) expect(group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") end end context "with a filter" do it "includes the given module into each matching example group" do RSpec.configure do |c| c.include(InstanceLevelMethods, :magic_key => :include) end group = RSpec.describe('does like, stuff and junk', :magic_key => :include) { } expect(group).not_to respond_to(:you_call_this_a_blt?) expect(group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") end it "includes in example groups that match a deprecated `:example_group` filter" do RSpec.configure do |c| c.include(InstanceLevelMethods, :example_group => { :file_path => /./ }) end group = RSpec.describe('does like, stuff and junk') expect(group).not_to respond_to(:you_call_this_a_blt?) expect(group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") end it "includes the given module into each existing matching example group" do matching_group = RSpec.describe('does like, stuff and junk', :magic_key => :include) { } non_matching_group = RSpec.describe nested_matching_group = non_matching_group.describe("", :magic_key => :include) RSpec.configure do |c| c.include(InstanceLevelMethods, :magic_key => :include) end expect(matching_group).not_to respond_to(:you_call_this_a_blt?) expect(matching_group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") expect(non_matching_group).not_to respond_to(:you_call_this_a_blt?) expect(non_matching_group.new).not_to respond_to(:you_call_this_a_blt?) expect(nested_matching_group).not_to respond_to(:you_call_this_a_blt?) expect(nested_matching_group.new.you_call_this_a_blt?).to eq("egad man, where's the mayo?!?!?") end it "includes the given module into the singleton class of matching examples" do RSpec.configure do |c| c.include(InstanceLevelMethods, :magic_key => :include) end value = ex1 = ex2 = nil RSpec.describe("Group") do ex1 = example("ex", :magic_key => :include) do value = you_call_this_a_blt? end ex2 = example("ex") { you_call_this_a_blt? } end.run expect(ex1.execution_result.exception).to be_nil expect(value).to match(/egad/) expect(ex2.execution_result.exception).to be_a(NameError) end it "ensures that `before` hooks have access to the module methods, even when only included in the singleton class of one example" do RSpec.configure do |c| c.include(Module.new { def which_mod; :mod_1; end }, :mod_1) c.include(Module.new { def which_mod; :mod_2; end }, :mod_2) end ex1_value = ex2_value = ex3 = nil RSpec.describe("group") do before { @value = which_mod } example("ex", :mod_1) { ex1_value = @value } example("ex", :mod_2) { ex2_value = @value } ex3 = example("ex") { } end.run expect(ex1_value).to eq(:mod_1) expect(ex2_value).to eq(:mod_2) expect(ex3.execution_result.exception).to be_a(NameError) end it "does not include the module in an example's singleton class when it has already been included in the group" do mod = Module.new do def self.inclusions @inclusions ||= [] end def self.included(klass) inclusions << klass end end RSpec.configure do |c| c.include mod, :magic_key end group = RSpec.describe("Group", :magic_key) do example("ex", :magic_key) { } end group.run expect(mod.inclusions).to eq([group]) end end end describe "#extend" do include_examples "warning of deprecated `:example_group` during filtering configuration", :extend, Enumerable module ThatThingISentYou def that_thing end end it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.extend(ThatThingISentYou, *args) config.instance_variable_get(:@extend_modules).items_and_filters.last.last end end it "extends the given module into each matching example group" do RSpec.configure do |c| c.extend(ThatThingISentYou, :magic_key => :extend) end group = RSpec.describe(ThatThingISentYou, :magic_key => :extend) { } expect(group).to respond_to(:that_thing) end it "extends the given module into each existing matching example group" do matching_group = RSpec.describe(ThatThingISentYou, :magic_key => :extend) { } non_matching_group = RSpec.describe nested_matching_group = non_matching_group.describe("Other", :magic_key => :extend) RSpec.configure do |c| c.extend(ThatThingISentYou, :magic_key => :extend) end expect(matching_group).to respond_to(:that_thing) expect(non_matching_group).not_to respond_to(:that_thing) expect(nested_matching_group).to respond_to(:that_thing) end end describe "#prepend", :if => RSpec::Support::RubyFeatures.module_prepends_supported? do include_examples "warning of deprecated `:example_group` during filtering configuration", :prepend, Enumerable module SomeRandomMod def foo "foobar" end end it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.prepend(SomeRandomMod, *args) config.instance_variable_get(:@prepend_modules).items_and_filters.last.last end end context "with no filter" do it "prepends the given module into each example group" do RSpec.configure do |c| c.prepend(SomeRandomMod) end group = RSpec.describe('yo') { } expect(group.new.foo).to eq("foobar") end it "prepends the given module into each existing example group" do group = RSpec.describe('yo') { } RSpec.configure do |c| c.prepend(SomeRandomMod) end expect(group.new.foo).to eq("foobar") end end context "with a filter" do it "prepends the given module into each matching example group" do RSpec.configure do |c| c.prepend(SomeRandomMod, :magic_key => :include) end group = RSpec.describe('yo', :magic_key => :include) { } expect(group.new.foo).to eq("foobar") end it "prepends the given module into each existing matching example group" do matching_group = RSpec.describe('yo', :magic_key => :include) { } non_matching_group = RSpec.describe nested_matching_group = non_matching_group.describe('', :magic_key => :include) RSpec.configure do |c| c.prepend(SomeRandomMod, :magic_key => :include) end expect(matching_group.new.foo).to eq("foobar") expect(non_matching_group.new).not_to respond_to(:foo) expect(nested_matching_group.new.foo).to eq("foobar") end end end describe "#run_all_when_everything_filtered?" do it "defaults to false" do expect(config.run_all_when_everything_filtered?).to be(false) end it "can be queried by predicate method" do config.run_all_when_everything_filtered = true expect(config.run_all_when_everything_filtered?).to be(true) end end describe "#color_mode" do context ":automatic" do before do config.color_mode = :automatic end context "with output.tty?" do it "sets color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true end end context "with !output.tty?" do it "sets !color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be false end end end context ":on" do before do config.color_mode = :on end context "with output.tty?" do it "sets color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true end end context "with !output.tty?" do it "sets color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be true end end end context ":off" do before do config.color_mode = :off end context "with output.tty?" do it "sets !color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be false end end context "with !output.tty?" do it "sets !color_enabled?" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be false end end it "prefers incoming cli_args" do config.output_stream = StringIO.new config.force :color_mode => :on config.color_mode = :off expect(config.color_mode).to be :on end end end describe "#color_enabled?" do it "allows overriding instance output stream with an argument" do config.output_stream = StringIO.new output_override = StringIO.new config.color_mode = :automatic allow(config.output_stream).to receive_messages(:tty? => false) allow(output_override).to receive_messages(:tty? => true) expect(config.color_enabled?).to be false expect(config.color_enabled?(output_override)).to be true end end describe "#color=" do before { config.color_mode = :automatic } context "given false" do before { config.color = false } context "with config.tty? and output.tty?" do it "sets color_enabled?" do output = StringIO.new config.output_stream = output config.tty = true allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true expect(config.color_enabled?(output)).to be true end end context "with config.tty? and !output.tty?" do it "does not set color_enabled?" do output = StringIO.new config.output_stream = output config.tty = true allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be false expect(config.color_enabled?(output)).to be false end end context "with !config.tty? and output.tty?" do it "sets color_enabled?" do output = StringIO.new config.output_stream = output config.tty = false allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true expect(config.color_enabled?(output)).to be true end end context "with !config.tty? and !output.tty?" do it "does not set color_enabled?" do output = StringIO.new config.output_stream = output config.tty = false allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be false expect(config.color_enabled?(output)).to be false end end end context "given true" do before { config.color = true } context "with config.tty? and output.tty?" do it "sets color_enabled?" do output = StringIO.new config.output_stream = output config.tty = true allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true expect(config.color_enabled?(output)).to be true end end context "with config.tty? and !output.tty?" do it "sets color_enabled?" do output = StringIO.new config.output_stream = output config.tty = true allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be true expect(config.color_enabled?(output)).to be true end end context "with !config.tty? and output.tty?" do it "sets color_enabled?" do output = StringIO.new config.output_stream = output config.tty = false allow(config.output_stream).to receive_messages(:tty? => true) expect(config.color_enabled?).to be true expect(config.color_enabled?(output)).to be true end end context "with !config.tty? and !output.tty?" do it "does not set color_enabled?" do output = StringIO.new config.output_stream = output config.tty = false allow(config.output_stream).to receive_messages(:tty? => false) expect(config.color_enabled?).to be false expect(config.color_enabled?(output)).to be false end end end it "prefers incoming cli_args" do config.output_stream = StringIO.new allow(config.output_stream).to receive_messages(:tty? => true) config.force :color => true config.color = false expect(config.color).to be true end end describe "#bisect_runner_class" do if RSpec::Support::RubyFeatures.fork_supported? it 'defaults to the faster `Bisect::ForkRunner` since fork is supported on this platform' do expect(config.bisect_runner_class).to be Bisect::ForkRunner end else it 'defaults to the slower `Bisect::ShellRunner` since fork is not supported on this platform' do expect(config.bisect_runner_class).to be Bisect::ShellRunner end end it "returns `Bisect::ForkRunner` when `bisect_runner == :fork" do config.bisect_runner = :fork expect(config.bisect_runner_class).to be Bisect::ForkRunner end it "returns `Bisect::ShellRunner` when `bisect_runner == :shell" do config.bisect_runner = :shell expect(config.bisect_runner_class).to be Bisect::ShellRunner end it "raises a clear error when `bisect_runner` is configured to an unrecognized value" do config.bisect_runner = :unknown expect { config.bisect_runner_class }.to raise_error(/Unsupported value for `bisect_runner`/) end it 'cannot be changed after the runner is in use' do config.bisect_runner = :fork config.bisect_runner_class expect { config.bisect_runner = :shell }.to raise_error(/config.bisect_runner = :shell/) end it 'can be set to the same value after the runner is in use' do config.bisect_runner = :shell config.bisect_runner_class expect { config.bisect_runner = :shell }.not_to raise_error end end %w[formatter= add_formatter].each do |config_method| describe "##{config_method}" do it "delegates to formatters#add" do expect(config.formatter_loader).to receive(:add).with('these','options') config.send(config_method,'these','options') end end end describe "#formatters" do it "returns a dup of the formatter_loader formatters" do config.add_formatter 'doc' config.formatters.clear expect(config.formatters).to_not eq [] end end describe '#reporter' do before do config.output_stream = StringIO.new config.deprecation_stream = StringIO.new end it 'does not immediately trigger formatter setup' do config.reporter expect(config.formatters).to be_empty end it 'buffers deprecations until the reporter is ready' do allow(config.formatter_loader).to receive(:prepare_default).and_wrap_original do |original, *args| config.reporter.deprecation :message => 'Test deprecation' original.call(*args) end expect { config.reporter.notify :deprecation_summary, Notifications::NullNotification }.to change { config.deprecation_stream.string }.to include 'Test deprecation' end it 'allows registering listeners without doubling up formatters' do config.reporter.register_listener double(:message => nil), :message expect { config.formatter = :documentation }.to change { config.formatters.size }.from(0).to(1) # notify triggers the formatter setup, there are two due to the already configured # documentation formatter and deprecation formatter expect { config.reporter.notify :message, double(:message => 'Triggers formatter setup') }.to change { config.formatters.size }.from(1).to(2) end it 'still configures a default formatter when none specified' do config.reporter.register_listener double(:message => nil), :message # notify triggers the formatter setup, there are two due to the default # (progress) and deprecation formatter expect { config.reporter.notify :message, double(:message => 'Triggers formatter setup') }.to change { config.formatters.size }.from(0).to(2) end end describe "#default_formatter" do it 'defaults to `progress`' do expect(config.default_formatter).to eq('progress') end it 'remembers changes' do config.default_formatter = 'doc' expect(config.default_formatter).to eq('doc') end context 'when another formatter has been set' do it 'does not get used' do config.default_formatter = 'doc' config.add_formatter 'progress' expect(used_formatters).to include(an_instance_of Formatters::ProgressFormatter) expect(used_formatters).not_to include(an_instance_of Formatters::DocumentationFormatter) end end context 'when no other formatter has been set' do before do config.output_stream = StringIO.new end it 'gets used' do config.default_formatter = 'doc' config.reporter.notify :message, double(:message => 'Triggers formatter setup') expect(used_formatters).not_to include(an_instance_of Formatters::ProgressFormatter) expect(used_formatters).to include(an_instance_of Formatters::DocumentationFormatter) end end context 'using a legacy formatter as default' do # Generating warnings during formatter initialisation triggers the # ProxyReporter code path. it 'remembers changes' do legacy_formatter = Class.new configuration = RSpec.configuration configuration.default_formatter = legacy_formatter configuration.reporter expect(configuration.default_formatter).to eq(legacy_formatter) end end def used_formatters config.reporter # to force freezing of formatters config.formatters end end describe "#filter_run_including" do it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.filter_run_including(*args) config.inclusion_filter.rules end end include_examples "warning of deprecated `:example_group` during filtering configuration", :filter_run_including it "sets the filter with a hash" do config.filter_run_including :foo => true expect(inclusion_filter).to eq( {:foo => true} ) end it "sets the filter with a symbol" do config.filter_run_including :foo expect(inclusion_filter).to eq( {:foo => true} ) end it "merges with existing filters" do config.filter_run_including :foo => true config.filter_run_including :bar => false expect(inclusion_filter).to eq( {:foo => true, :bar => false} ) end end describe "#filter_run_excluding" do it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.filter_run_excluding(*args) config.exclusion_filter.rules end end include_examples "warning of deprecated `:example_group` during filtering configuration", :filter_run_excluding it "sets the filter" do config.filter_run_excluding :foo => true expect(exclusion_filter).to eq( {:foo => true} ) end it "sets the filter using a symbol" do config.filter_run_excluding :foo expect(exclusion_filter).to eq( {:foo => true} ) end it "merges with existing filters" do config.filter_run_excluding :foo => true config.filter_run_excluding :bar => false expect(exclusion_filter).to eq( {:foo => true, :bar => false} ) end end shared_examples_for "a spec filter" do |type| describe "##{type}" do it "returns {} even if set to nil" do config.send("#{type}=", nil) expect(send(type)).to eq({}) end end describe "##{type}=" do it "treats symbols as hash keys with true values when told to" do config.send("#{type}=", :foo) expect(send(type)).to eq( {:foo => true} ) end it "overrides any #{type} set on the command line or in configuration files" do config.force(type => { :foo => :bar }) config.send("#{type}=", {:want => :this}) expect(send(type)).to eq( {:want => :this} ) end include_examples "warning of deprecated `:example_group` during filtering configuration", :"#{type}=" end end it_behaves_like "a spec filter", :inclusion_filter it_behaves_like "a spec filter", :exclusion_filter describe "#treat_symbols_as_metadata_keys_with_true_values=" do it 'is deprecated' do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) config.treat_symbols_as_metadata_keys_with_true_values = true end end describe "#full_backtrace=" do it "doesn't impact other instances of config" do config_1 = Configuration.new config_2 = Configuration.new config_1.full_backtrace = true expect(config_2.full_backtrace?).to be(false) end end describe "#backtrace_exclusion_patterns=" do it "actually receives the new filter values" do config.backtrace_exclusion_patterns = [/.*/] expect(config.backtrace_formatter.exclude? "this").to be(true) end end describe 'full_backtrace' do it 'returns true when backtrace patterns is empty' do config.backtrace_exclusion_patterns = [] expect(config.full_backtrace?).to eq true end it "returns false when backtrace patterns are not empty" do config.backtrace_exclusion_patterns = [:lib] expect(config.full_backtrace?).to eq false end end describe "#backtrace_exclusion_patterns" do it "can be appended to" do config.backtrace_exclusion_patterns << /.*/ expect(config.backtrace_formatter.exclude? "this").to be(true) end end describe "#backtrace_inclusion_patterns" do before { config.backtrace_exclusion_patterns << /.*/ } it 'can be assigned to' do config.backtrace_inclusion_patterns = [/foo/] expect(config.backtrace_formatter.exclude?("food")).to be false end it 'can be appended to' do config.backtrace_inclusion_patterns << /foo/ expect(config.backtrace_formatter.exclude?("food")).to be false end end describe "#filter_gems_from_backtrace" do def exclude?(line) config.backtrace_formatter.exclude?(line) end it 'filters the named gems from the backtrace' do line_1 = "/Users/myron/.gem/ruby/2.1.1/gems/foo-1.6.3.1/foo.rb:13" line_2 = "/Users/myron/.gem/ruby/2.1.1/gems/bar-1.6.3.1/bar.rb:13" expect { config.filter_gems_from_backtrace "foo", "bar" }.to change { exclude?(line_1) }.from(false).to(true). and change { exclude?(line_2) }.from(false).to(true) end end describe "#profile_examples" do it "defaults to false" do expect(config.profile_examples).to be false end it "can be set to an integer value" do config.profile_examples = 17 expect(config.profile_examples).to eq(17) end it "returns 10 when set simply enabled" do config.profile_examples = true expect(config.profile_examples).to eq(10) end end describe "#libs=" do it "adds directories to the LOAD_PATH" do expect($LOAD_PATH).to receive(:unshift).with("a/dir") config.libs = ["a/dir"] end end describe "libs" do it 'records paths added to the load path' do config.libs = ["a/dir"] expect(config.libs).to eq ["a/dir"] end end describe "#define_derived_metadata" do include_examples "warning of deprecated `:example_group` during filtering configuration", :define_derived_metadata it 'allows the provided block to mutate example group metadata' do RSpec.configuration.define_derived_metadata do |metadata| metadata[:reverse_description] = metadata[:description].reverse end group = RSpec.describe("My group") expect(group.metadata).to include(:description => "My group", :reverse_description => "puorg yM") end it 'allows the provided block to mutate example metadata' do RSpec.configuration.define_derived_metadata do |metadata| metadata[:reverse_description] = metadata[:description].reverse end ex = RSpec.describe("My group").example("foo") expect(ex.metadata).to include(:description => "foo", :reverse_description => "oof") end it 'allows multiple configured blocks to be applied, in order of definition' do RSpec.configure do |c| c.define_derived_metadata { |m| m[:b1_desc] = m[:description] + " (block 1)" } c.define_derived_metadata { |m| m[:b2_desc] = m[:b1_desc] + " (block 2)" } end group = RSpec.describe("bar") expect(group.metadata).to include(:b1_desc => "bar (block 1)", :b2_desc => "bar (block 1) (block 2)") end it 'supports cascades of derived metadata, but avoids re-running derived metadata blocks that have already been applied' do RSpec.configure do |c| c.define_derived_metadata(:foo1) { |m| m[:foo2] = (m[:foo2] || 0) + 1 } c.define_derived_metadata(:foo2) { |m| m[:foo3] = (m[:foo3] || 0) + 1 } c.define_derived_metadata(:foo3) { |m| m[:foo1] += 1 } end group = RSpec.describe("bar", :foo1 => 0) expect(group.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1) ex = RSpec.describe("My group").example("foo", :foo1 => 0) expect(ex.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1) end it 'does not allow a derived metadata cascade to recurse infinitely' do RSpec.configure do |c| counter = 1 derive_next_metadata = lambda do |outer_meta| tag = :"foo#{counter += 1}" outer_meta[tag] = true c.define_derived_metadata(tag) do |inner_meta| derive_next_metadata.call(inner_meta) end end c.define_derived_metadata(:foo1) do |meta| derive_next_metadata.call(meta) end end expect { RSpec.describe("group", :foo1) }.to raise_error(SystemStackError) end it "derives metadata before the group or example blocks are eval'd so their logic can depend on the derived metadata" do RSpec.configure do |c| c.define_derived_metadata(:foo) do |metadata| metadata[:bar] = "bar" end end group_bar_value = example_bar_value = nil RSpec.describe "Group", :foo do group_bar_value = self.metadata[:bar] example_bar_value = example("ex", :foo).metadata[:bar] end expect(group_bar_value).to eq("bar") expect(example_bar_value).to eq("bar") end it 'registers top-level groups before invoking the callback so the logic can configure already registered groups' do registered_groups = nil RSpec.configuration.define_derived_metadata do |_meta| registered_groups = RSpec.world.example_groups end group = RSpec.describe("My group") do end expect(registered_groups).to eq [group] end it 'registers nested groups before invoking the callback so the logic can configure already registered groups' do registered_groups = nil RSpec.configuration.define_derived_metadata(:inner) do |_meta| registered_groups = RSpec.world.all_example_groups end inner = nil outer = RSpec.describe("Outer") do inner = context "Inner", :inner do end end expect(registered_groups).to contain_exactly(outer, inner) end it 'registers examples before invoking the callback so the logic can configure already registered groups' do registered_examples = nil RSpec.configuration.define_derived_metadata(:ex) do |_meta| registered_examples = FlatMap.flat_map(RSpec.world.all_example_groups, &:examples) end example = nil RSpec.describe("Outer") do example = example("ex", :ex) end expect(registered_examples).to contain_exactly(example) end context "when passed a metadata filter" do it 'only applies to the groups and examples that match that filter' do RSpec.configure do |c| c.define_derived_metadata(:apply => true) do |metadata| metadata[:reverse_description] = metadata[:description].reverse end end g1 = RSpec.describe("G1", :apply) g2 = RSpec.describe("G2") e1 = g1.example("E1") e2 = g2.example("E2", :apply) e3 = g2.example("E3") expect(g1.metadata).to include(:reverse_description => "1G") expect(g2.metadata).not_to include(:reverse_description) expect(e1.metadata).to include(:reverse_description => "1E") expect(e2.metadata).to include(:reverse_description => "2E") expect(e3.metadata).not_to include(:reverse_description) end it 'applies if any of multiple filters apply (to align with module inclusion semantics)' do RSpec.configure do |c| c.define_derived_metadata(:a => 1, :b => 2) do |metadata| metadata[:reverse_description] = metadata[:description].reverse end end g1 = RSpec.describe("G1", :a => 1) g2 = RSpec.describe("G2", :b => 2) g3 = RSpec.describe("G3", :c => 3) expect(g1.metadata).to include(:reverse_description => "1G") expect(g2.metadata).to include(:reverse_description => "2G") expect(g3.metadata).not_to include(:reverse_description) end it 'allows a metadata filter to be passed as a raw symbol' do RSpec.configure do |c| c.define_derived_metadata(:apply) do |metadata| metadata[:reverse_description] = metadata[:description].reverse end end g1 = RSpec.describe("G1", :apply) g2 = RSpec.describe("G2") expect(g1.metadata).to include(:reverse_description => "1G") expect(g2.metadata).not_to include(:reverse_description) end end end describe "#when_first_matching_example_defined" do include_examples "warning of deprecated `:example_group` during filtering configuration", :when_first_matching_example_defined it "runs the block when the first matching example is defined" do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end RSpec.describe do example("ex 1") sequence << :before_first_matching_example_defined example("ex 2", :foo) sequence << :after_first_matching_example_defined end expect(sequence).to eq [:before_first_matching_example_defined, :callback, :after_first_matching_example_defined] end it "does not fire when later matching examples are defined" do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end RSpec.describe do example("ex 1", :foo) sequence.clear sequence << :before_second_matching_example_defined example("ex 2", :foo) sequence << :after_second_matching_example_defined end expect(sequence).to eq [:before_second_matching_example_defined, :after_second_matching_example_defined] end it "does not run the block if no matching examples are defined" do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end RSpec.describe do example("ex 1") example("ex 2", :bar) end expect(sequence).to eq [] end it 'does not run the block if groups match the metadata but no examples do' do called = false RSpec.configuration.when_first_matching_example_defined(:foo => true) do called = true end RSpec.describe "group 1", :foo => true do end RSpec.describe "group 2", :foo => true do example("ex", :foo => false) end expect(called).to be false end it "still runs after the first matching example even if there is a group that matches earlier" do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end RSpec.describe "group", :foo do end RSpec.describe do example("ex 1") sequence << :before_first_matching_example_defined example("ex 2", :foo) sequence << :after_first_matching_example_defined end expect(sequence).to eq [:before_first_matching_example_defined, :callback, :after_first_matching_example_defined] end context "when a group is defined with matching metadata" do it "runs the callback after the first example in the group is defined" do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end sequence << :before_group RSpec.describe "group", :foo do sequence << :before_example example("ex") sequence << :after_example end expect(sequence).to eq [:before_group, :before_example, :callback, :after_example] end end context 'when the value of the registered metadata is a Proc' do it 'does not fire when later matching examples are defined' do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo => proc { true }) do sequence << :callback end RSpec.describe do example("ex 1", :foo) sequence.clear sequence << :before_second_matching_example_defined example("ex 2", :foo) sequence << :after_second_matching_example_defined end expect(sequence).to eq [:before_second_matching_example_defined, :after_second_matching_example_defined] end end context 'when a matching example group with other registered metadata has been defined' do it 'does not fire when later matching examples with the other metadata are defined' do sequence = [] RSpec.configuration.when_first_matching_example_defined(:foo) do sequence << :callback end RSpec.configuration.when_first_matching_example_defined(:bar) do end RSpec.describe 'group', :foo, :bar do example("ex 1", :foo) sequence.clear sequence << :before_second_matching_example_defined example("ex 2", :foo, :bar) sequence << :after_second_matching_example_defined end expect(sequence).to eq [:before_second_matching_example_defined, :after_second_matching_example_defined] end end end describe "#add_setting" do describe "with no modifiers" do context "with no additional options" do before do config.add_setting :custom_option end it "defaults to nil" do expect(config.custom_option).to be_nil end it "adds a predicate" do expect(config.custom_option?).to be(false) end it "can be overridden" do config.custom_option = "a value" expect(config.custom_option).to eq("a value") end end context "with :default => 'a value'" do before do config.add_setting :custom_option, :default => 'a value' end it "defaults to 'a value'" do expect(config.custom_option).to eq("a value") end it "returns true for the predicate" do expect(config.custom_option?).to be(true) end it "can be overridden with a truthy value" do config.custom_option = "a new value" expect(config.custom_option).to eq("a new value") end it "can be overridden with nil" do config.custom_option = nil expect(config.custom_option).to eq(nil) end it "can be overridden with false" do config.custom_option = false expect(config.custom_option).to eq(false) end end end context "with :alias_with => " do before do config.add_setting :custom_option, :alias_with => :another_custom_option end it "delegates the getter to the other option" do config.another_custom_option = "this value" expect(config.custom_option).to eq("this value") end it "delegates the setter to the other option" do config.custom_option = "this value" expect(config.another_custom_option).to eq("this value") end it "delegates the predicate to the other option" do config.custom_option = true expect(config.another_custom_option?).to be(true) end end end describe "#configure_group" do it "extends with 'extend'" do mod = Module.new group = RSpec.describe("group", :foo => :bar) config.extend(mod, :foo => :bar) config.configure_group(group) expect(group).to be_a(mod) end it "includes with 'include'" do mod = Module.new group = RSpec.describe("group", :foo => :bar) config.include(mod, :foo => :bar) config.configure_group(group) expect(group.included_modules).to include(mod) end it "requires only one matching filter" do mod = Module.new group = RSpec.describe("group", :foo => :bar) config.include(mod, :foo => :bar, :baz => :bam) config.configure_group(group) expect(group.included_modules).to include(mod) end module IncludeExtendOrPrependMeOnce def self.included(host) raise "included again" if host.instance_methods.include?(:foobar) host.class_exec { def foobar; end } end def self.extended(host) raise "extended again" if host.respond_to?(:foobar) def host.foobar; end end def self.prepended(host) raise "prepended again" if host.instance_methods.include?(:barbaz) host.class_exec { def barbaz; end } end end it "doesn't include a module when already included in ancestor" do config.include(IncludeExtendOrPrependMeOnce, :foo => :bar) group = RSpec.describe("group", :foo => :bar) child = group.describe("child") config.configure_group(group) config.configure_group(child) end it "doesn't extend when ancestor is already extended with same module" do config.extend(IncludeExtendOrPrependMeOnce, :foo => :bar) group = RSpec.describe("group", :foo => :bar) child = group.describe("child") config.configure_group(group) config.configure_group(child) end it "doesn't prepend a module when already present in ancestor chain", :if => RSpec::Support::RubyFeatures.module_prepends_supported? do config.prepend(IncludeExtendOrPrependMeOnce, :foo => :bar) group = RSpec.describe("group", :foo => :bar) child = group.describe("child") config.configure_group(group) config.configure_group(child) end end describe "#alias_example_group_to" do after do RSpec::Core::DSL.example_group_aliases.delete(:my_group_method) RSpec.module_exec do class << self undef :my_group_method if method_defined? :my_group_method end end RSpec::Core::ExampleGroup.module_exec do class << self undef :my_group_method if method_defined? :my_group_method end end Module.class_exec do undef :my_group_method if method_defined? :my_group_method end end it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.alias_example_group_to :my_group_method, *args group = ExampleGroup.my_group_method("a group") group.metadata end end it 'overrides existing definitions of the aliased method name without issuing warnings' do config.expose_dsl_globally = true class << ExampleGroup def my_group_method; :original; end end Module.class_exec do def my_group_method; :original; end end config.alias_example_group_to :my_group_method expect(ExampleGroup.my_group_method).to be < ExampleGroup expect(Module.new.my_group_method).to be < ExampleGroup end it "allows adding additional metadata" do config.alias_example_group_to :my_group_method, { :some => "thing" } group = ExampleGroup.my_group_method("a group", :another => "thing") expect(group.metadata).to include(:some => "thing", :another => "thing") end it "passes `nil` as the description arg when no args are given" do config.alias_example_group_to :my_group_method, { :some => "thing" } group = ExampleGroup.my_group_method expect(group.metadata).to include( :description_args => [nil], :description => "", :some => "thing" ) end context 'when the aliased method is used' do it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.alias_example_group_to :my_group_method group = ExampleGroup.my_group_method("a group", *args) group.metadata end end end end describe "#alias_example_to" do it_behaves_like "metadata hash builder" do after do RSpec::Core::ExampleGroup.module_exec do class << self undef :my_example_method if method_defined? :my_example_method end end end def metadata_hash(*args) config.alias_example_to :my_example_method, *args group = RSpec.describe("group") example = group.my_example_method("description") example.metadata end end end describe "#reset" do it "clears the reporter" do expect(config.reporter).not_to be_nil config.reset expect(config.instance_variable_get("@reporter")).to be_nil end it "clears the formatters" do config.add_formatter "doc" config.reset expect(config.formatters).to be_empty end it "clears the output wrapper" do config.output_stream = StringIO.new config.reset expect(config.instance_variable_get("@output_wrapper")).to be_nil end end describe "#reset_reporter" do it "clears the reporter" do expect(config.reporter).not_to be_nil config.reset expect(config.instance_variable_get("@reporter")).to be_nil end it "clears the formatters" do config.add_formatter "doc" config.reset expect(config.formatters).to be_empty end it "clears the output wrapper" do config.output_stream = StringIO.new config.reset expect(config.instance_variable_get("@output_wrapper")).to be_nil end end def example_numbered(num) instance_double(Example, :id => "./foo_spec.rb[1:#{num}]") end describe "#force" do context "for ordering options" do let(:list) { 1.upto(4).map { |i| example_numbered(i) } } let(:ordering_strategy) { config.ordering_registry.fetch(:global) } let(:shuffled) { Ordering::Random.new(config).order list } specify "CLI `--order defined` takes precedence over `config.order = rand`" do config.force :order => "defined" config.order = "rand" expect(ordering_strategy.order(list)).to eq(list) end specify "CLI `--order rand:37` takes precedence over `config.order = defined`" do config.force :order => "rand:37" config.order = "defined" expect(ordering_strategy.order(list)).to eq(shuffled) end specify "CLI `--seed 37` forces order and seed" do config.force :seed => 37 config.order = "defined" config.seed = 145 expect(ordering_strategy.order(list)).to eq(shuffled) expect(config.seed).to eq(37) end specify "CLI `--order defined` takes precedence over `config.register_ordering(:global)`" do config.force :order => "defined" config.register_ordering(:global, &:reverse) expect(ordering_strategy.order(list)).to eq(list) end end it "forces 'false' value" do config.add_setting :custom_option config.custom_option = true expect(config.custom_option?).to be(true) config.force :custom_option => false expect(config.custom_option?).to be(false) config.custom_option = true expect(config.custom_option?).to be(false) end end describe '#seed' do it 'returns the seed as an int' do config.seed = '123' expect(config.seed).to eq(123) end end describe "#seed_used?" do def use_seed_on(registry) registry.fetch(:random).order([example_numbered(1), example_numbered(2)]) end it 'returns false if neither ordering registry used the seed' do expect(config.seed_used?).to be false end it 'returns true if the ordering registry used the seed' do use_seed_on(config.ordering_registry) expect(config.seed_used?).to be true end end describe '#order=' do context 'given "random"' do before do config.seed = 7654 config.order = 'random' end it 'does not change the seed' do expect(config.seed).to eq(7654) end it 'sets up random ordering' do allow(RSpec).to receive_messages(:configuration => config) global_ordering = config.ordering_registry.fetch(:global) expect(global_ordering).to be_an_instance_of(Ordering::Random) end end context 'given "random:123"' do before { config.order = 'random:123' } it 'sets seed to 123' do expect(config.seed).to eq(123) end it 'sets up random ordering' do allow(RSpec).to receive_messages(:configuration => config) global_ordering = config.ordering_registry.fetch(:global) expect(global_ordering).to be_an_instance_of(Ordering::Random) end end context 'given "defined"' do before do config.order = 'rand:123' config.order = 'defined' end it "does not change the seed" do expect(config.seed).to eq(123) end it 'clears the random ordering' do allow(RSpec).to receive_messages(:configuration => config) list = [1, 2, 3, 4] ordering_strategy = config.ordering_registry.fetch(:global) expect(ordering_strategy.order(list)).to eq([1, 2, 3, 4]) end end context 'given a custom ordering strategy' do before do allow(RSpec).to receive_messages(:configuration => config) end it 'will lookup a previously registed ordering strategy' do config.register_ordering(:custom_scheme) { |list| list.reverse } config.order = :custom_scheme strategy = config.ordering_registry.fetch(:global) expect(strategy.order([1, 2, 3, 4])).to eq [4, 3, 2, 1] end it 'will defer lookup until running' do config.order = :custom_scheme strategy = config.ordering_registry.fetch(:global) expect(strategy).to be_an_instance_of(Ordering::Delayed) config.register_ordering(:custom_scheme) { |list| list.reverse } expect(strategy.order([1, 2, 3, 4])).to eq [4, 3, 2, 1] end it 'will raise an error if ordering is not present when needed' do config.order = :custom_scheme strategy = config.ordering_registry.fetch(:global) expect(strategy).to be_an_instance_of(Ordering::Delayed) expect { strategy.order([1, 2, 3, 4]) }.to raise_error("Undefined ordering strategy :custom_scheme") end it 'will lookup schemes as symbols even if given as strings' do config.order = 'custom_scheme' config.register_ordering(:custom_scheme) { |list| list.reverse } strategy = config.ordering_registry.fetch(:global) expect(strategy.order([1, 2, 3, 4])).to eq [4, 3, 2, 1] end end end describe "#register_ordering" do def register_reverse_ordering config.register_ordering(:reverse, &:reverse) end it 'stores the ordering for later use' do register_reverse_ordering list = [1, 2, 3] strategy = config.ordering_registry.fetch(:reverse) expect(strategy).to be_a(Ordering::Custom) expect(strategy.order(list)).to eq([3, 2, 1]) end it 'can register an ordering object' do strategy = Object.new def strategy.order(list) list.reverse end config.register_ordering(:reverse, strategy) list = [1, 2, 3] fetched = config.ordering_registry.fetch(:reverse) expect(fetched).to be(strategy) expect(fetched.order(list)).to eq([3, 2, 1]) end end describe '#warnings' do around do |example| original_setting = $VERBOSE example.run $VERBOSE = original_setting end it "sets verbose to true when true" do config.warnings = true expect($VERBOSE).to eq true end it "sets verbose to false when true" do config.warnings = false expect($VERBOSE).to eq false end it 'returns the verbosity setting' do config.warnings = true expect(config.warnings?).to eq true config.warnings = false expect(config.warnings?).to eq false end it 'is loaded from config by #force' do config.force :warnings => true expect($VERBOSE).to eq true end end describe '#raise_on_warning=(value)' do around do |example| original_setting = RSpec::Support.warning_notifier example.run RSpec::Support.warning_notifier = original_setting end it 'causes warnings to raise errors when true' do config.raise_on_warning = true expect { RSpec.warning 'All hell breaks loose' }.to raise_error a_string_including('WARNING: All hell breaks loose') end it 'causes warnings to default to warning when false' do config.raise_on_warning = false expect_warning_with_call_site(__FILE__, __LINE__ + 1) RSpec.warning 'doesnt raise' end end describe "#raise_errors_for_deprecations!" do it 'causes deprecations to raise errors rather than printing to the deprecation stream' do config.deprecation_stream = stream = StringIO.new config.raise_errors_for_deprecations! expect { config.reporter.deprecation(:deprecated => "foo", :call_site => "foo.rb:1") }.to raise_error(RSpec::Core::DeprecationError, /foo is deprecated/) expect(stream.string).to eq("") end end describe "#expose_current_running_example_as" do before { stub_const(Configuration::ExposeCurrentExample.name, Module.new) } it 'exposes the current example via the named method' do RSpec.configuration.expose_current_running_example_as :the_example RSpec.configuration.expose_current_running_example_as :another_example_helper value_1 = value_2 = nil RSpec.describe "Group" do it "works" do value_1 = the_example value_2 = another_example_helper end end.run expect(value_1).to be_an(RSpec::Core::Example) expect(value_1.description).to eq("works") expect(value_2).to be(value_1) end end describe '#disable_monkey_patching!' do let!(:config) { RSpec.configuration } let!(:expectations) { RSpec::Expectations } let!(:mocks) { RSpec::Mocks } def in_fully_monkey_patched_rspec_environment in_sub_process do config.expose_dsl_globally = true mocks.configuration.syntax = [:expect, :should] mocks.configuration.patch_marshal_to_support_partial_doubles = true expectations.configuration.syntax = [:expect, :should] yield end end it 'stops exposing the DSL methods globally' do in_fully_monkey_patched_rspec_environment do mod = Module.new expect { config.disable_monkey_patching! }.to change { mod.respond_to?(:describe) }.from(true).to(false) end end it 'stops using should syntax for expectations' do in_fully_monkey_patched_rspec_environment do obj = Object.new config.expect_with :rspec expect { config.disable_monkey_patching! }.to change { obj.respond_to?(:should) }.from(true).to(false) end end it 'stops using should syntax for mocks' do in_fully_monkey_patched_rspec_environment do obj = Object.new config.mock_with :rspec expect { config.disable_monkey_patching! }.to change { obj.respond_to?(:should_receive) }.from(true).to(false) end end it 'stops patching of Marshal' do in_fully_monkey_patched_rspec_environment do expect { config.disable_monkey_patching! }.to change { Marshal.respond_to?(:dump_with_rspec_mocks) }.from(true).to(false) end end context 'when user did not configure mock framework' do def emulate_not_configured_mock_framework in_fully_monkey_patched_rspec_environment do allow(config).to receive(:rspec_mocks_loaded?).and_return(false, true) config.instance_variable_set :@mock_framework, nil ExampleGroup.send :remove_class_variable, :@@example_groups_configured yield end end it 'disables monkey patching after example groups being configured' do emulate_not_configured_mock_framework do obj = Object.new config.disable_monkey_patching! expect { ExampleGroup.ensure_example_groups_are_configured }.to change { obj.respond_to?(:should_receive) }.from(true).to(false) end end end context 'when user did not configure expectation framework' do def emulate_not_configured_expectation_framework in_fully_monkey_patched_rspec_environment do allow(config).to receive(:rspec_expectations_loaded?).and_return(false, true) config.instance_variable_set :@expectation_frameworks, [] ExampleGroup.send :remove_class_variable, :@@example_groups_configured yield end end it 'disables monkey patching after example groups being configured' do emulate_not_configured_expectation_framework do obj = Object.new config.disable_monkey_patching! expect { ExampleGroup.ensure_example_groups_are_configured }.to change { obj.respond_to?(:should) }.from(true).to(false) end end end end describe 'recording spec start time (for measuring load)' do it 'returns a time' do expect(config.start_time).to be_an_instance_of ::Time end it 'is configurable' do config.start_time = 42 expect(config.start_time).to eq 42 end end describe "hooks" do include_examples "warning of deprecated `:example_group` during filtering configuration", :before, :each end describe '#threadsafe', :threadsafe => true do it 'defaults to false' do expect(config.threadsafe).to eq true end it 'can be configured to true or false' do config.threadsafe = true expect(config.threadsafe).to eq true config.threadsafe = false expect(config.threadsafe).to eq false end end describe '#max_displayed_failure_line_count' do it 'defaults to 10' do expect(config.max_displayed_failure_line_count).to eq 10 end it 'is configurable' do config.max_displayed_failure_line_count = 5 expect(config.max_displayed_failure_line_count).to eq 5 end end describe '#failure_exit_code' do it 'defaults to 1' do expect(config.failure_exit_code).to eq 1 end it 'is configurable' do config.failure_exit_code = 2 expect(config.failure_exit_code).to eq 2 end end describe '#error_exit_code' do it 'defaults to nil' do expect(config.error_exit_code).to eq nil end it 'is configurable' do config.error_exit_code = 2 expect(config.error_exit_code).to eq 2 end end describe "#shared_context_metadata_behavior" do it "defaults to :trigger_inclusion for backwards compatibility" do expect(config.shared_context_metadata_behavior).to eq :trigger_inclusion end it "can be set to :apply_to_host_groups" do config.shared_context_metadata_behavior = :apply_to_host_groups expect(config.shared_context_metadata_behavior).to eq :apply_to_host_groups end it "can be set to :trigger_inclusion explicitly" do config.shared_context_metadata_behavior = :trigger_inclusion expect(config.shared_context_metadata_behavior).to eq :trigger_inclusion end it "cannot be set to any other values" do expect { config.shared_context_metadata_behavior = :another_value }.to raise_error(ArgumentError, a_string_including( "shared_context_metadata_behavior", ":another_value", ":trigger_inclusion", ":apply_to_host_groups" )) end end describe '#pending_failure_output' do it 'defaults to :full' do expect(config.pending_failure_output).to eq :full end it 'can be set to :full' do config.pending_failure_output = :full expect(config.pending_failure_output).to eq :full end it 'can be set to :no_backtrace' do config.pending_failure_output = :no_backtrace expect(config.pending_failure_output).to eq :no_backtrace end it 'can be set to :skip' do config.pending_failure_output = :skip expect(config.pending_failure_output).to eq :skip end it 'cannot be set to any other values' do expect { config.pending_failure_output = :another_value }.to raise_error( ArgumentError, '`pending_failure_output` can be set to :full, :no_backtrace, or :skip' ) end end # assigns files_or_directories_to_run and triggers post-processing # via `files_to_run`. def assign_files_or_directories_to_run(*value) config.files_or_directories_to_run = value config.files_to_run end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/output_wrapper_spec.rb0000664000000000000000000000147714557677674026327 0ustar rootrootmodule RSpec::Core RSpec.describe OutputWrapper do let(:output) { StringIO.new } let(:wrapper) { OutputWrapper.new(output) } it 'redirects calls to the wrapped object' do wrapper.puts('message') wrapper.print('another message') expect(output.string).to eq("message\nanother message").and eq(wrapper.string) end it 'redirects calls when send is overridden' do class << output undef :send end wrapper.puts('message') expect(output.string).to eq("message\n").and eq(wrapper.string) end describe '#output=' do let(:another_output) { StringIO.new } it 'changes the output stream' do wrapper.output = another_output wrapper.puts('message') expect(another_output.string).to eq("message\n") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/reporter_spec.rb0000664000000000000000000002624114557677674025065 0ustar rootrootmodule RSpec::Core RSpec.describe Reporter do include FormatterSupport let(:config) { Configuration.new } let(:world) { World.new(config) } let(:reporter) { Reporter.new config } let(:start_time) { Time.now } let(:example) { super() } describe "finish" do let(:formatter) { double("formatter") } %w[start_dump dump_pending dump_failures dump_summary close].map(&:to_sym).each do |message| it "sends #{message} to the formatter(s) that respond to message" do reporter.register_listener formatter, message expect(formatter.as_null_object).to receive(message) reporter.finish end it "doesnt notify formatters about messages they dont implement" do expect { reporter.finish }.to_not raise_error end end it "dumps the failure summary after the profile and deprecation summary so failures don't scroll off the screen and get missed" do config.profile_examples = 10 formatter = instance_double("RSpec::Core::Formatter::ProgressFormatter") reporter.register_listener(formatter, :dump_summary, :dump_profile, :deprecation_summary) expect(formatter).to receive(:deprecation_summary).ordered expect(formatter).to receive(:dump_profile).ordered expect(formatter).to receive(:dump_summary).ordered reporter.finish end it "allows the profiler to be used without being manually setup" do config.profile_examples = true expect { reporter.finish }.to_not raise_error end end describe 'start' do before { config.start_time = start_time } it 'notifies the formatter of start with example count' do formatter = double("formatter") reporter.register_listener formatter, :start expect(formatter).to receive(:start) do |notification| expect(notification.count).to eq 3 expect(notification.load_time).to eq 5 end reporter.start 3, (start_time + 5) end it 'notifies the formatter of the seed used before notifying of start' do formatter = double("formatter") reporter.register_listener formatter, :seed reporter.register_listener formatter, :start expect(formatter).to receive(:seed).ordered.with( an_object_having_attributes(:seed => config.seed, :seed_used? => config.seed_used?) ) expect(formatter).to receive(:start).ordered reporter.start 1 end end context "given one formatter" do it "passes messages to that formatter" do formatter = double("formatter", :example_started => nil) reporter.register_listener formatter, :example_started example = new_example expect(formatter).to receive(:example_started) do |notification| expect(notification.example).to eq example end reporter.example_started(example) end it "passes messages to the formatter in the correct order" do order = [] formatter = double("formatter") allow(formatter).to receive(:example_group_started) { |n| order << "Started: #{n.group.description}" } allow(formatter).to receive(:example_started) { |n| order << "Started Example" } allow(formatter).to receive(:example_finished) { |n| order << "Finished Example" } allow(formatter).to receive(:example_passed) { |n| order << "Passed" } allow(formatter).to receive(:example_pending) { |n| order << "Pending" } allow(formatter).to receive(:example_failed) { |n| order << "Failed" } allow(formatter).to receive(:example_group_finished) { |n| order << "Finished: #{n.group.description}" } reporter.register_listener formatter, :example_group_started, :example_group_finished, :example_started, :example_finished, :example_passed, :example_failed, :example_pending group = RSpec.describe("root") group.describe("context 1") do example("passing example") {} example("pending example", :skip => true) { } end group.describe("context 2") do example("failed example") { fail } end group.run(reporter) expect(order).to eq([ "Started: root", "Started: context 1", "Started Example", "Finished Example", "Passed", "Started Example", "Finished Example", "Pending", "Finished: context 1", "Started: context 2", "Started Example", "Finished Example", "Failed", "Finished: context 2", "Finished: root" ]) end end context "given an example group with no examples" do it "does not pass example_group_started or example_group_finished to formatter" do formatter = double("formatter") expect(formatter).not_to receive(:example_group_started) expect(formatter).not_to receive(:example_group_finished) reporter.register_listener formatter, :example_group_started, :example_group_finished group = RSpec.describe("root") group.run(reporter) end end context "given multiple formatters" do it "passes messages to all formatters" do formatters = (1..2).map { double("formatter", :example_started => nil) } example = new_example formatters.each do |formatter| expect(formatter).to receive(:example_started) do |notification| expect(notification.example).to eq example end reporter.register_listener formatter, :example_started end reporter.example_started(example) end end describe "#exit_early" do it "returns the passed exit code" do expect(reporter.exit_early(42)).to eq(42) end it "sends a complete cycle of notifications" do formatter = double("formatter") %w[seed start start_dump dump_pending dump_failures dump_summary seed close].map(&:to_sym).each do |message| reporter.register_listener formatter, message expect(formatter).to receive(message).ordered end reporter.exit_early(42) end end describe "#report" do it "supports one arg (count)" do reporter.report(1) {} end it "yields itself" do yielded = nil reporter.report(3) { |r| yielded = r } expect(yielded).to eq(reporter) end end describe "#register_listener" do let(:listener) { double("listener", :start => nil) } before { reporter.register_listener listener, :start } it 'will register the listener to specified notifications' do expect(reporter.registered_listeners :start).to eq [listener] end it 'will match string notification names' do reporter.register_listener listener, "stop" expect(reporter.registered_listeners :stop).to eq [listener] end it 'will send notifications when a subscribed event is triggered' do expect(listener).to receive(:start) do |notification| expect(notification.count).to eq 42 end reporter.start 42 end it 'will ignore duplicated listeners' do reporter.register_listener listener, :start expect(listener).to receive(:start).once reporter.start 42 end end describe "#publish" do let(:listener) { double("listener", :custom => nil) } before do reporter.register_listener listener, :custom, :start end it 'will send custom events to registered listeners' do expect(listener).to receive(:custom).with(RSpec::Core::Notifications::NullNotification) reporter.publish :custom end it 'will raise when encountering RSpec standard events' do expect { reporter.publish :start }.to raise_error( StandardError, a_string_including("not internal RSpec ones") ) end it 'will ignore event names sent as strings' do expect(listener).not_to receive(:custom) reporter.publish "custom" end it 'will provide a custom notification object based on the options hash' do expect(listener).to receive(:custom).with( an_object_having_attributes(:my_data => :value) ) reporter.publish :custom, :my_data => :value end end describe "#abort_with" do before { allow(reporter).to receive(:exit!) } it "publishes the message and notifies :close" do listener = double("Listener") reporter.register_listener(listener, :message, :close) stream = StringIO.new allow(listener).to receive(:message) { |n| stream << n.message } allow(listener).to receive(:close) { stream.close } reporter.register_listener(listener) reporter.abort_with("Booom!", 1) expect(stream).to have_attributes(:string => "Booom!").and be_closed end it "exits with the provided exit code" do reporter.abort_with("msg", 13) expect(reporter).to have_received(:exit!).with(13) end end describe "timing" do before do config.start_time = start_time end it "uses RSpec::Core::Time as to not be affected by changes to time in examples" do formatter = double(:formatter) reporter.register_listener formatter, :dump_summary reporter.start 1 allow(Time).to receive_messages(:now => ::Time.utc(2012, 10, 1)) duration = nil allow(formatter).to receive(:dump_summary) do |notification| duration = notification.duration end reporter.finish expect(duration).to be < 0.2 end it "captures the load time so it can report it later" do formatter = instance_double("ProgressFormatter") reporter.register_listener formatter, :dump_summary reporter.start 3, (start_time + 5) expect(formatter).to receive(:dump_summary) do |notification| expect(notification.load_time).to eq(5) end reporter.finish end end describe "#notify_non_example_exception" do it "sends a `message` notification that contains the formatted exception details" do formatter_out = StringIO.new formatter = Formatters::ProgressFormatter.new(formatter_out) reporter.register_listener formatter, :message line = __LINE__ + 1 exception = 1 / 0 rescue $! reporter.notify_non_example_exception(exception, "NonExample Context") expect(formatter_out.string).to start_with(<<-EOS.gsub(/^ +\|/, '').chomp) | |NonExample Context |Failure/Error: exception = 1 / 0 rescue $! | |ZeroDivisionError: | divided by 0 |# #{Metadata.relative_path(__FILE__)}:#{line} EOS end it "records the fact that a non example failure has occurred" do expect { reporter.notify_non_example_exception(Exception.new, "NonExample Context") }.to change(world, :non_example_failure).from(a_falsey_value).to(true) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/configuration/0000775000000000000000000000000014557677674024526 5ustar rootroot././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/configuration/only_failures_support_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/configuration/only_failures_support_spec.r0000664000000000000000000002070314557677674032374 0ustar rootrootmodule RSpec::Core RSpec.describe Configuration, "--only-failures support" do let(:config) { Configuration.new } def simulate_persisted_examples(*examples) config.example_status_persistence_file_path = "examples.txt" persister = class_double(ExampleStatusPersister).as_stubbed_const allow(persister).to receive(:load_from).with("examples.txt").and_return(examples.flatten) end describe "#last_run_statuses" do def last_run_statuses config.last_run_statuses end context "when `example_status_persistence_file_path` is configured" do before do simulate_persisted_examples( { :example_id => "id_1", :status => "passed" }, { :example_id => "id_2", :status => "failed" } ) end it 'gets the last run statuses from the ExampleStatusPersister' do expect(last_run_statuses).to eq( 'id_1' => 'passed', 'id_2' => 'failed' ) end it 'returns a memoized value' do expect(last_run_statuses).to be(last_run_statuses) end specify 'the hash returns `unknown` for unknown example ids for consistency' do expect(last_run_statuses["foo"]).to eq(Configuration::UNKNOWN_STATUS) expect(last_run_statuses["bar"]).to eq(Configuration::UNKNOWN_STATUS) end end context "when `example_status_persistence_file_path` is not configured" do before do config.example_status_persistence_file_path = nil end it 'returns a memoized value' do expect(last_run_statuses).to be(last_run_statuses) end it 'returns a blank hash without attempting to load the persisted statuses' do persister = class_double(ExampleStatusPersister).as_stubbed_const expect(persister).not_to receive(:load_from) expect(last_run_statuses).to eq({}) end specify 'the hash returns `unknown` for all ids for consistency' do expect(last_run_statuses["foo"]).to eq(Configuration::UNKNOWN_STATUS) expect(last_run_statuses["bar"]).to eq(Configuration::UNKNOWN_STATUS) end end def allows_value_to_change_when_updated simulate_persisted_examples( { :example_id => "id_1", :status => "passed" }, { :example_id => "id_2", :status => "failed" } ) config.example_status_persistence_file_path = nil expect { yield }.to change { last_run_statuses }.to('id_1' => 'passed', 'id_2' => 'failed') end it 'allows the value to be updated when `example_status_persistence_file_path` is set after first access' do allows_value_to_change_when_updated do config.example_status_persistence_file_path = "examples.txt" end end it 'allows the value to be updated when `example_status_persistence_file_path` is forced after first access' do allows_value_to_change_when_updated do config.force(:example_status_persistence_file_path => "examples.txt") end end end describe "#spec_files_with_failures" do def spec_files_with_failures config.spec_files_with_failures end context "when `example_status_persistence_file_path` is configured" do it 'returns a memoized array of unique spec files that contain failed examples' do simulate_persisted_examples( { :example_id => "./spec_1.rb[1:1]", :status => "failed" }, { :example_id => "./spec_1.rb[1:2]", :status => "failed" }, { :example_id => "./spec_2.rb[1:2]", :status => "passed" }, { :example_id => "./spec_3.rb[1:2]", :status => "pending" }, { :example_id => "./spec_4.rb[1:2]", :status => "unknown" }, { :example_id => "./spec_5.rb[1:2]", :status => "failed" } ) expect(spec_files_with_failures).to( be_an(Array) & be(spec_files_with_failures) & contain_exactly("./spec_1.rb", "./spec_5.rb") ) end end context 'when the file at `example_status_persistence_file_path` has corrupted `status` values' do before do simulate_persisted_examples( { :example_id => "./spec_1.rb[1:1]" }, { :example_id => "./spec_1.rb[1:2]", :status => "" }, { :example_id => "./spec_2.rb[1:2]", :status => nil }, { :example_id => "./spec_3.rb[1:2]", :status => "wrong" }, { :example_id => "./spec_4.rb[1:2]", :status => "unknown" }, { :example_id => "./spec_5.rb[1:2]", :status => "failed" }, { :example_id => "./spec_6.rb[1:2]", :status => "pending" }, :example_id => "./spec_7.rb[1:2]", :status => "passed" ) end it 'defaults invalid statuses to unknown' do expect(spec_files_with_failures).to( be_an(Array) & contain_exactly("./spec_5.rb") ) # Check that each example has the correct status expect(config.last_run_statuses).to eq( './spec_1.rb[1:1]' => 'unknown', './spec_1.rb[1:2]' => 'unknown', './spec_2.rb[1:2]' => 'unknown', './spec_3.rb[1:2]' => 'unknown', './spec_4.rb[1:2]' => 'unknown', './spec_5.rb[1:2]' => 'failed', './spec_6.rb[1:2]' => 'pending', './spec_7.rb[1:2]' => 'passed' ) end end context "when `example_status_persistence_file_path` is not configured" do it "returns a memoized blank array" do config.example_status_persistence_file_path = nil expect(spec_files_with_failures).to( eq([]) & be(spec_files_with_failures) ) end end def allows_value_to_change_when_updated simulate_persisted_examples({ :example_id => "./spec_1.rb[1:1]", :status => "failed" }) config.example_status_persistence_file_path = nil expect { yield }.to change { spec_files_with_failures }.to(["./spec_1.rb"]) end it 'allows the value to be updated when `example_status_persistence_file_path` is set after first access' do allows_value_to_change_when_updated do config.example_status_persistence_file_path = "examples.txt" end end it 'allows the value to be updated when `example_status_persistence_file_path` is forced after first access' do allows_value_to_change_when_updated do config.force(:example_status_persistence_file_path => "examples.txt") end end end describe "#files_to_run, when `only_failures` is set" do around do |ex| handle_current_dir_change do Dir.chdir("spec/rspec/core", &ex) end end let(:default_path) { "resources" } let(:files_with_failures) { ["./resources/a_spec.rb"] } let(:files_loaded_via_default_path) do configuration = Configuration.new configuration.default_path = default_path configuration.files_or_directories_to_run = [] configuration.files_to_run end before do expect(files_loaded_via_default_path).not_to eq(files_with_failures) config.default_path = default_path simulate_persisted_examples(files_with_failures.map do |file| { :example_id => "#{file}[1:1]", :status => "failed" } end) config.force(:only_failures => true) end context "and no explicit paths have been set" do it 'loads only the files that have failures' do config.files_or_directories_to_run = [] expect(config.files_to_run).to eq(files_with_failures) end it 'loads the default path if there are no files with failures' do simulate_persisted_examples([]) config.files_or_directories_to_run = [] expect(config.files_to_run).to eq(files_loaded_via_default_path) end end context "and a path has been set" do it "loads the intersection of files matching the path and files with failures" do config.files_or_directories_to_run = ["resources"] expect(config.files_to_run).to eq(files_with_failures) end it "loads all files matching the path when there are no intersecting files" do config.files_or_directories_to_run = ["resources/acceptance"] expect(config.files_to_run).to contain_files("resources/acceptance/foo_spec.rb") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/suite_hooks_spec.rb0000664000000000000000000001303414557677674025553 0ustar rootrootrequire "support/runner_support" module RSpec::Core RSpec.describe "Configuration :suite hooks" do [:before, :after, :prepend_before, :append_before, :prepend_after, :append_after].each do |registration_method| type = registration_method.to_s.split('_').last describe "a `:suite` hook registered with `#{registration_method}`" do it 'is skipped when in dry run mode' do RSpec.configuration.dry_run = true expect { |b| RSpec.configuration.__send__(registration_method, :suite, &b) RSpec.configuration.with_suite_hooks { } }.not_to yield_control end it 'notifies about errors in the hook' do RSpec.configuration.__send__(registration_method, :suite) { 1 / 0 } expect(RSpec.configuration.reporter).to receive(:notify_non_example_exception).with( ZeroDivisionError, /suite\)` hook/ ) RSpec.configuration.with_suite_hooks { } end it 'sets `wants_to_quit` when an error occurs so that the suite does not get run' do RSpec.configuration.__send__(registration_method, :suite) { 1 / 0 } allow(RSpec.configuration.reporter).to receive(:notify_non_example_exception) expect { RSpec.configuration.with_suite_hooks { } }.to change(RSpec.world, :wants_to_quit).from(a_falsey_value).to(true) end it 'runs in the context of an example group' do run_context = nil RSpec.configuration.__send__(registration_method, :suite) { run_context = self } RSpec.configuration.with_suite_hooks { } expect(run_context).to be_a ExampleGroup end it 'allows access to rspec-mocks methods within the hook' do run = false RSpec.configuration.__send__(registration_method, :suite) do RSpec::Mocks.with_temporary_scope { double('something') } run = true end RSpec.configuration.with_suite_hooks { } expect(run).to be true end it 'allows access to rspec-expectation methods within the hook' do notified_failure = nil RSpec::Support.with_failure_notifier(lambda { |e, _opts| notified_failure = e }) do RSpec.configuration.__send__(registration_method, :suite) do expect(true).to be false end RSpec.configuration.with_suite_hooks { } end expect(notified_failure).to be_a(RSpec::Expectations::ExpectationNotMetError) end context "registered on an example group" do it "is ignored with a clear warning" do sequence = [] expect { RSpec.describe "Group" do __send__(registration_method, :suite) { sequence << :suite_hook } example { sequence << :example } end.run }.to change { sequence }.to([:example]). and output(a_string_including("#{type}(:suite)")).to_stderr end end context "registered with metadata" do it "explicitly warns that the metadata is ignored" do expect { RSpec.configure do |c| c.__send__(registration_method, :suite, :some => :metadata) end }.to output(a_string_including(":suite", "metadata")).to_stderr end end end end it 'always runs `after(:suite)` hooks even in the face of errors' do expect { |b| RSpec.configuration.after(:suite, &b) RSpec.configuration.with_suite_hooks { raise "boom" } }.to raise_error("boom").and yield_control end describe "the runner" do include_context "Runner support" def define_and_run_example_group(&block) example_group = class_double(ExampleGroup, :descendants => []) allow(example_group).to receive(:run, &block) allow(world).to receive_messages(:ordered_example_groups => [example_group]) allow(config).to receive :load_spec_files runner = build_runner runner.run err, out end it "still runs :suite hooks with metadata even though the metadata is ignored" do sequence = [] allow(RSpec).to receive(:warn_with) config.before(:suite, :foo) { sequence << :before_suite } config.after(:suite, :foo) { sequence << :after_suite } define_and_run_example_group { sequence << :example_groups } expect(sequence).to eq([ :before_suite, :example_groups, :after_suite ]) end it "runs :suite hooks before and after example groups in the correct order" do sequence = [] config.before(:suite) { sequence << :before_suite_2 } config.before(:suite) { sequence << :before_suite_3 } config.append_before(:suite) { sequence << :before_suite_4 } config.prepend_before(:suite) { sequence << :before_suite_1 } config.after(:suite) { sequence << :after_suite_3 } config.after(:suite) { sequence << :after_suite_2 } config.prepend_after(:suite) { sequence << :after_suite_1 } config.append_after(:suite) { sequence << :after_suite_4 } define_and_run_example_group { sequence << :example_groups } expect(sequence).to eq([ :before_suite_1, :before_suite_2, :before_suite_3, :before_suite_4, :example_groups, :after_suite_1, :after_suite_2, :after_suite_3, :after_suite_4 ]) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core/rspec_matchers_spec.rb0000664000000000000000000000273614557677674026230 0ustar rootrootmodule RSpec::Matchers def __method_with_super super end module ModThatIncludesMatchers include RSpec::Matchers end RSpec.configure do |c| c.include RSpec::Matchers, :include_rspec_matchers => true c.include ModThatIncludesMatchers, :include_mod_that_includes_rspec_matchers => true end RSpec.describe self do shared_examples_for "a normal module with a method that supers" do it "raises the expected error (and not SystemStackError)" do expect { __method_with_super }.to raise_error(NoMethodError) # there is no __method_with_super in an ancestor end end it_behaves_like "a normal module with a method that supers" context "when RSpec::Matchers has been included in an example group" do include RSpec::Matchers it_behaves_like "a normal module with a method that supers" end context "when a module that includes RSpec::Matchers has been included in an example group" do include RSpec::Matchers::ModThatIncludesMatchers it_behaves_like "a normal module with a method that supers" end context "when RSpec::Matchers is included via configuration", :include_rspec_matchers => true do it_behaves_like "a normal module with a method that supers" end context "when RSpec::Matchers is included in a module that is included via configuration", :include_mod_that_includes_rspec_matchers => true do it_behaves_like "a normal module with a method that supers" end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/rspec/core_spec.rb0000664000000000000000000002674114557677674023230 0ustar rootrootrequire 'rspec/support/spec/library_wide_checks' RSpec.describe RSpec do fake_libs = File.expand_path('../../support/fake_libs', __FILE__) allowed_loaded_features = [ /optparse\.rb/, # Used by OptionParser. /rbconfig\.rb/, # loaded by rspec-support for OS detection. /shellwords\.rb/, # used by ConfigurationOptions and RakeTask. /stringio/, # Used by BaseFormatter. %r{/fake_libs/}, # ignore these, obviously ] # JRuby appears to not respect `--disable=gem` so rubygems also gets loaded. allowed_loaded_features << /rubygems/ if RSpec::Support::Ruby.jruby? # Truffleruby cext files allowed_loaded_features << /\/truffle\/cext/ if RSpec::Support::Ruby.truffleruby? disable_autorun_code = if RSpec::Support::OS.windows? # On Windows, the "redefine autorun" approach results in a different # exit status for a reason I don't understand, so we just disable # autorun outright. 'RSpec::Core::Runner.disable_autorun!' else # On JRuby, the `disable_autorun!` approach leads to a stderr warning # related to a deprecation emited when `rspec/core/autorun` gets loaded, # because of `caller_filter` issues, so we redefine the autorun method # instead. That works fine on all Rubies when we're not on Windows as # well. 'RSpec::Core::Runner.instance_exec { undef :autorun; def autorun; end }' end it_behaves_like 'library wide checks', 'rspec-core', :preamble_for_lib => [ # rspec-core loads a number of external libraries. We don't want them loaded # as part of loading all of rspec-core for these specs, for a few reasons: # # * Some external libraries issue warnings, which we can't do anything about. # Since we are trying to prevent _any_ warnings from loading RSpec, it's # easiest to avoid loading those libraries entirely. # * Some external libraries load many stdlibs. Here we allow a known set of # directly loaded stdlibs, and we're not directly concerned with transitive # dependencies. # * We're really only concerned with these issues w.r.t. rspec-mocks and # rspec-expectations from within their spec suites. Here we care only about # rspec-core, so avoiding loading them helps keep the spec suites independent. # * These are some of the slowest specs we have, and cutting out the loading # of external libraries cuts down on how long these specs take. # # To facilitate the avoidance of loading certain libraries, we have a bunch # of files in `support/fake_libs` that substitute for the real things when # we put that directory on the load path. Here's the list: # # * coderay -- loaded by the HTML formatter if available for syntax highlighting. # * drb -- loaded when `--drb` is used. Loads other stdlibs (socket, thread, fcntl). # * erb -- loaded by `ConfigurationOptions` so `.rspec` can use ERB. Loads other stdlibs (strscan, cgi/util). # * flexmock -- loaded by our Flexmock mocking adapter. # * json -- loaded by the JSON formatter, loads other stdlibs (ostruct, enc/utf_16le.bundle, etc). # * minitest -- loaded by our Minitest assertions adapter. # * mocha -- loaded by our Mocha mocking adapter. # * rake -- loaded by our Rake task. Loads other stdlibs (fileutils, ostruct, thread, monitor, etc). # * rr -- loaded by our RR mocking adapter. # * rspec-mocks -- loaded by our RSpec mocking adapter. # * rspec-expectations -- loaded by the generated `spec_helper` (defined in project_init). # * test-unit -- loaded by our T::U assertions adapter. # "$LOAD_PATH.unshift '#{fake_libs}'", # Many files assume this has already been loaded and will have errors if it has not. 'require "rspec/core"', # Prevent rspec/autorun from trying to run RSpec. disable_autorun_code ], :skip_spec_files => %r{/fake_libs/}, :allowed_loaded_feature_regexps => allowed_loaded_features do if RUBY_VERSION == '1.8.7' before(:example, :description => /(issues no warnings when the spec files are loaded|stdlibs)/) do pending "Not working on #{RUBY_DESCRIPTION}" end elsif RUBY_VERSION == '2.0.0' && RSpec::Support::Ruby.jruby? before(:example) do skip "Not reliably working on #{RUBY_DESCRIPTION}" end elsif RSpec::Support::Ruby.jruby? && JRUBY_VERSION =~ /9\.1\.17\.0/ before(:example, :description => /spec files/) do pending "JRuby 9.1.17.0 generates unrelated warnings" end end end describe ".configuration" do it "returns the same object every time" do expect(RSpec.configuration).to equal(RSpec.configuration) end end describe ".configuration=" do it "sets the configuration object" do configuration = RSpec::Core::Configuration.new RSpec.configuration = configuration expect(RSpec.configuration).to equal(configuration) end end describe ".configure" do it "yields the current configuration" do RSpec.configure do |config| expect(config).to equal(RSpec::configuration) end end end describe ".world" do it "returns the same object every time" do expect(RSpec.world).to equal(RSpec.world) end end describe ".world=" do it "sets the world object" do world = RSpec::Core::World.new RSpec.world = world expect(RSpec.world).to equal(world) end end describe ".current_example" do it "sets the example being executed" do group = RSpec.describe("an example group") example = group.example("an example") RSpec.current_example = example expect(RSpec.current_example).to be(example) end end describe ".current_scope" do before :context do expect(RSpec.current_scope).to eq(:before_context_hook) end before do expect(RSpec.current_scope).to eq(:before_example_hook) end it "returns :example inside an example" do expect(RSpec.current_scope).to eq(:example) end end describe ".reset" do it "resets the configuration and world objects" do config_before_reset = RSpec.configuration world_before_reset = RSpec.world RSpec.reset expect(RSpec.configuration).not_to equal(config_before_reset) expect(RSpec.world).not_to equal(world_before_reset) end it 'removes the previously assigned example group constants' do RSpec.describe "group" expect { RSpec.world.reset }.to change(RSpec::ExampleGroups, :constants).to([]) end end describe ".clear_examples" do let(:listener) { double("listener") } def reporter RSpec.configuration.reporter end before do RSpec.configuration.output_stream = StringIO.new RSpec.configuration.error_stream = StringIO.new end it "clears example groups" do RSpec.world.example_groups << :example_group RSpec.clear_examples expect(RSpec.world.example_groups).to be_empty end it "resets start_time" do start_time_before_clear = RSpec.configuration.start_time RSpec.clear_examples expect(RSpec.configuration.start_time).not_to eq(start_time_before_clear) end it "clears examples, failed_examples and pending_examples" do reporter.start(3) pending_ex = failing_ex = nil RSpec.describe do pending_ex = pending { fail } failing_ex = example { fail } end.run reporter.example_started(failing_ex) reporter.example_failed(failing_ex) reporter.example_started(pending_ex) reporter.example_pending(pending_ex) reporter.finish RSpec.clear_examples reporter.register_listener(listener, :dump_summary) expect(listener).to receive(:dump_summary) do |notification| expect(notification.examples).to be_empty expect(notification.failed_examples).to be_empty expect(notification.pending_examples).to be_empty end reporter.start(0) reporter.finish end it "restores inclusion rules set by configuration" do file_path = File.expand_path("foo_spec.rb") RSpec.configure do |config| config.filter_run_including(:locations => { file_path => [12] }) end allow(RSpec.configuration).to receive(:load).with(file_path) allow(reporter).to receive(:report) RSpec::Core::Runner.run(["foo_spec.rb:14"]) expect( RSpec.configuration.filter_manager.inclusions[:locations] ).to eq(file_path => [12, 14]) RSpec.clear_examples expect( RSpec.configuration.filter_manager.inclusions[:locations] ).to eq(file_path => [12]) end it "restores exclusion rules set by configuration" do RSpec.configure { |config| config.filter_run_excluding(:slow => true) } allow(RSpec.configuration).to receive(:load) allow(reporter).to receive(:report) RSpec::Core::Runner.run(["--tag", "~fast"]) expect( RSpec.configuration.filter_manager.exclusions.rules ).to eq(:slow => true, :fast => true) RSpec.clear_examples expect( RSpec.configuration.filter_manager.exclusions.rules ).to eq(:slow => true) end it 'clears the deprecation buffer' do RSpec.configuration.deprecation_stream = StringIO.new RSpec.describe do example { RSpec.deprecate("first deprecation") } end.run reporter.start(1) reporter.finish RSpec.clear_examples RSpec.configuration.deprecation_stream = StringIO.new(deprecations = "".dup) RSpec.describe do example { RSpec.deprecate("second deprecation") } end.run reporter.start(1) reporter.finish expect(deprecations).to include("second deprecation") expect(deprecations).to_not include("first deprecation") end it 'does not clear shared examples' do RSpec.shared_examples_for("shared") { } RSpec.clear_examples registry = RSpec.world.shared_example_group_registry expect(registry.find([:main], "shared")).to_not be_nil end end describe "::Core.path_to_executable" do it 'returns the absolute location of the exe/rspec file' do expect(File.exist? RSpec::Core.path_to_executable).to be(true) expect(File.read(RSpec::Core.path_to_executable)).to include("RSpec::Core::Runner.invoke") expect(File.executable? RSpec::Core.path_to_executable).to be(true) unless RSpec::Support::OS.windows? end end include RSpec::Support::ShellOut # This is hard to test :(. Best way I could come up with was starting # fresh ruby process w/o this stuff already loaded. it "loads mocks and expectations when the constants are referenced", :slow do code = 'require "rspec"; puts RSpec::Mocks.name; puts RSpec::Expectations.name' out, err, status = run_ruby_with_current_load_path(code) expect(err).to eq("") expect(out.split("\n")).to eq(%w[ RSpec::Mocks RSpec::Expectations ]) expect(status.exitstatus).to eq(0) expect(RSpec.const_missing(:Expectations)).to be(RSpec::Expectations) end it 'correctly raises an error when an invalid const is referenced' do expect { RSpec::NotAConst }.to raise_error(NameError, /RSpec::NotAConst/) end it "does not blow up if some gem defines `Kernel#it`", :slow do code = 'Kernel.module_eval { def it(*); end }; require "rspec/core"' out, err, status = run_ruby_with_current_load_path(code) expect(err).to eq("") expect(out).to eq("") expect(status.exitstatus).to eq(0) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/0000775000000000000000000000000014557677674021327 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/helper_methods.rb0000664000000000000000000000302514557677674024656 0ustar rootrootmodule RSpecHelpers SAFE_LEVEL_THAT_TRIGGERS_SECURITY_ERRORS = RUBY_VERSION >= '2.3' ? 1 : 3 SAFE_IS_GLOBAL_VARIABLE = RUBY_VERSION >= '2.6' def relative_path(path) RSpec::Core::Metadata.relative_path(path) end def ignoring_warnings original = $VERBOSE $VERBOSE = nil result = yield $VERBOSE = original result end # Intended for use with indented heredocs. # taken from Ruby Tapas: # https://rubytapas.dpdcart.com/subscriber/post?id=616#files def unindent(s) s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, "") end # In Ruby 2.7 taint was removed and has no effect, whilst SAFE warns that it # has no effect and will become a normal variable in 3.0. Other engines do not # implement SAFE. if RUBY_VERSION >= '2.7' || (defined?(RUBY_ENGINE) && RUBY_ENGINE != "ruby") def with_safe_set_to_level_that_triggers_security_errors yield end else def with_safe_set_to_level_that_triggers_security_errors result = nil orig_safe = $SAFE Thread.new do ignoring_warnings { $SAFE = SAFE_LEVEL_THAT_TRIGGERS_SECURITY_ERRORS } result = yield end.join # $SAFE is not supported on Rubinius # In Ruby 2.6, $SAFE became a global variable; previously it was local to a thread. unless defined?(Rubinius) || SAFE_IS_GLOBAL_VARIABLE # $SAFE should not have changed in this thread. expect($SAFE).to eql orig_safe end result ensure $SAFE = orig_safe if orig_safe && SAFE_IS_GLOBAL_VARIABLE end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/isolated_home_directory.rb0000664000000000000000000000206514557677674026557 0ustar rootrootrequire 'tmpdir' require 'fileutils' require 'pathname' RSpec.shared_context "isolated home directory" do around do |ex| Dir.mktmpdir do |tmp_dir| # If user running this test suite has a custom $XDG_CONFIG_HOME, also # clear that out when changing $HOME so tests don't touch the user's real # configuration files. without_env_vars "XDG_CONFIG_HOME" do with_env_vars "HOME" => tmp_dir do ex.call end end end end end module HomeFixtureHelpers def create_fixture_file(file_name, contents) path = Pathname.new(file_name).expand_path if !path.exist? path.dirname.mkpath # Pathname#write does not exist in all supported Ruby versions File.open(path.to_s, 'w') { |file| file << contents } else # Abort just in case we're about to destroy something important. raise "File at #{path} already exists!" end end end RSpec.configure do |c| c.include_context "isolated home directory", :isolated_home => true c.include HomeFixtureHelpers, :isolated_home => true end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/shared_example_groups.rb0000664000000000000000000000273314557677674026241 0ustar rootrootRSpec.shared_examples_for "metadata hash builder" do let(:hash) { metadata_hash(:foo, :bar, :bazz => 23) } it 'treats symbols as metadata keys with a true value' do expect(hash[:foo]).to be(true) expect(hash[:bar]).to be(true) end it 'still processes hash values normally' do expect(hash[:bazz]).to be(23) end end RSpec.shared_examples_for "handling symlinked directories when loading spec files" do include_context "isolated directory" let(:project_dir) { Dir.getwd } before(:example) do pending "Windows does not support symlinking on RUBY_VERSION < 2.3" end if RSpec::Support::OS.windows? && RUBY_VERSION < '2.3' it "finds the files" do foos_dir = File.join(project_dir, "spec/foos") FileUtils.mkdir_p foos_dir FileUtils.touch(File.join(foos_dir, "foo_spec.rb")) bars_dir = File.join(Dir.tmpdir, "shared/spec/bars") FileUtils.mkdir_p bars_dir FileUtils.touch(File.join(bars_dir, "bar_spec.rb")) FileUtils.ln_s bars_dir, File.join(project_dir, "spec/bars") expect(loaded_files).to contain_files( "spec/bars/bar_spec.rb", "spec/foos/foo_spec.rb" ) end it "works on a more complicated example (issue 1113)" do FileUtils.mkdir_p("subtrees/DD/spec") FileUtils.mkdir_p("spec/lib") FileUtils.touch("subtrees/DD/spec/dd_foo_spec.rb") FileUtils.ln_s(File.join(project_dir, "subtrees/DD/spec"), "spec/lib/DD") expect(loaded_files).to contain_files("spec/lib/DD/dd_foo_spec.rb") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/runner_support.rb0000664000000000000000000000062514557677674024764 0ustar rootrootmodule RSpec::Core RSpec.shared_context "Runner support" do let(:out) { StringIO.new } let(:err) { StringIO.new } let(:config) { RSpec.configuration } let(:world) { RSpec.world } def build_runner(*args) Runner.new(build_config_options(*args)) end def build_config_options(*args) ConfigurationOptions.new(args) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/matchers.rb0000664000000000000000000000755614557677674023477 0ustar rootrootRSpec::Matchers.define :map_specs do |specs| match do |autotest| @specs = specs @autotest = prepare(autotest) autotest.test_files_for(@file) == specs end chain :to do |file| @file = file end failure_message do "expected #{@autotest.class} to map #{@specs.inspect} to #{@file.inspect}\ngot #{@actual.inspect}" end def prepare(autotest) find_order = @specs.dup << @file autotest.instance_exec { @find_order = find_order } autotest end end RSpec::Matchers.define :fail_with do |exception_klass| match do |example| !example.execution_result.example_skipped? && failure_reason(example, exception_klass).nil? end failure_message do |example| "expected example to fail with a #{exception_klass} exception, but #{failure_reason(example, exception_klass)}" end def failure_reason(example, exception_klass) result = example.execution_result case when example.metadata[:pending] then "was pending" when result.status != :failed then result.status when !result.exception.is_a?(exception_klass) then "failed with a #{result.exception.class}" else nil end end end RSpec::Matchers.define :pass do match do |example| !example.execution_result.example_skipped? && failure_reason(example).nil? end failure_message do |example| "expected example to pass, but #{failure_reason(example)}" end def failure_reason(example) result = example.metadata[:execution_result] case when example.metadata[:pending] then "was pending" when result.status != :passed then result.status else nil end end end RSpec::Matchers.module_exec do alias_method :have_failed_with, :fail_with alias_method :have_passed, :pass end RSpec::Matchers.define :be_pending_with do |message| match do |example| example.pending? && !example.execution_result.example_skipped? && example.execution_result.pending_exception && example.execution_result.status == :pending && example.execution_result.pending_message == message end failure_message do |example| "expected: example pending with #{message.inspect}\n got: #{example.execution_result.pending_message.inspect}".tap do |msg| msg << " (but had no pending exception)" unless example.execution_result.pending_exception end end end RSpec::Matchers.define :be_skipped_with do |message| match do |example| example.skipped? && example.pending? && example.execution_result.example_skipped? && example.execution_result.pending_message == message end failure_message do |example| "expected: example skipped with #{message.inspect}\n got: #{example.execution_result.pending_message.inspect}" end end RSpec::Matchers.define :contain_files do |*expected_files| contain_exactly_matcher = RSpec::Matchers::BuiltIn::ContainExactly.new(expected_files.map { |f| File.expand_path(f) }) match do |actual_files| files = actual_files.map { |f| File.expand_path(f) } contain_exactly_matcher.matches?(files) end failure_message { contain_exactly_matcher.failure_message } failure_message_when_negated { contain_exactly_matcher.failure_message_when_negated } end RSpec::Matchers.define :first_include do |first_snippet| chain :then_include, :second_snippet match do |string| string.include?(first_snippet) && string.include?(second_snippet) && string.index(first_snippet) < string.index(second_snippet) end end RSpec::Matchers.alias_matcher :a_file_collection, :contain_files RSpec::Matchers.define_negated_matcher :avoid_outputting, :output RSpec::Matchers.define_negated_matcher :exclude, :include RSpec::Matchers.define_negated_matcher :excluding, :include RSpec::Matchers.define_negated_matcher :a_string_excluding, :a_string_including RSpec::Matchers.define_negated_matcher :avoid_changing, :change RSpec::Matchers.define_negated_matcher :a_hash_excluding, :include ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/sandboxing.rb0000664000000000000000000000116514557677674024013 0ustar rootrootrequire 'rspec/core/sandbox' # Because testing RSpec with RSpec tries to modify the same global # objects, we sandbox every test. RSpec.configure do |c| c.around do |ex| RSpec::Core::Sandbox.sandboxed do |config| # If there is an example-within-an-example, we want to make sure the inner example # does not get a reference to the outer example (the real spec) if it calls # something like `pending` config.before(:context) { RSpec.current_example = nil } config.color_mode = :off orig_load_path = $LOAD_PATH.dup ex.run $LOAD_PATH.replace(orig_load_path) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/config_options_helper.rb0000664000000000000000000000043514557677674026235 0ustar rootrootmodule ConfigOptionsHelper extend RSpec::SharedContext around(:each) { |e| without_env_vars('SPEC_OPTS', &e) } def config_options_object(*args) RSpec::Core::ConfigurationOptions.new(args) end def parse_options(*args) config_options_object(*args).options end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/spec_files.rb0000664000000000000000000000171314557677674023772 0ustar rootrootRSpec.shared_context "spec files" do def failing_spec_filename @failing_spec_filename ||= File.expand_path(File.dirname(__FILE__)) + "/_failing_spec.rb" end def passing_spec_filename @passing_spec_filename ||= File.expand_path(File.dirname(__FILE__)) + "/_passing_spec.rb" end def create_passing_spec_file File.open(passing_spec_filename, 'w') do |f| f.write %q{ RSpec.describe "passing spec" do it "passes" do expect(1).to eq(1) end end } end end def create_failing_spec_file File.open(failing_spec_filename, 'w') do |f| f.write %q{ RSpec.describe "failing spec" do it "fails" do expect(1).to eq(2) end end } end end before(:all) do create_passing_spec_file create_failing_spec_file end after(:all) do File.delete(passing_spec_filename) File.delete(failing_spec_filename) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/formatter_support.rb0000664000000000000000000003522414557677674025461 0ustar rootrootmodule FormatterSupport def run_example_specs_with_formatter(formatter_option, options={}, &block) output = run_rspec_with_formatter(formatter_option, options.merge(:extra_options => ["spec/rspec/core/resources/formatter_specs.rb"]), &block) return output unless options.fetch(:normalize_output, true) output = normalize_durations(output) caller_line = RSpec::Core::Metadata.relative_path(caller.first) output.lines.reject do |line| # remove the direct caller as that line is different for the summary output backtraces line.include?(caller_line) || # ignore scirpt/rspec_with_simplecov because we don't usually have it locally but # do have it on travis line.include?("script/rspec_with_simplecov") || # this line varies a bit depending on how you run the specs (via `rake` vs `rspec`) line.include?('/exe/rspec:') end.join end def run_rspec_with_formatter(formatter, options={}) extra_options = options.fetch(:extra_options) { [] } spec_order = options[:seed] ? ["--seed", options[:seed].to_s] : ["--order", "defined"] options = RSpec::Core::ConfigurationOptions.new([ "--no-profile", "--format", formatter, *(spec_order + extra_options) ]) err, out = StringIO.new, StringIO.new err.set_encoding("utf-8") if err.respond_to?(:set_encoding) runner = RSpec::Core::Runner.new(options) configuration = runner.configuration configuration.filter_gems_from_backtrace "gems/bundler" configuration.backtrace_formatter.exclusion_patterns << /rspec_with_simplecov/ configuration.backtrace_formatter.inclusion_patterns = [] yield runner if block_given? runner.run(err, out) out.string end RUN_LINE = __LINE__ - 3 def normalize_durations(output) output.gsub(/(?:\d+ minutes? )?\d+(?:\.\d+)?(s| seconds?)/) do |dur| suffix = $1 == "s" ? "s" : " seconds" "n.nnnn#{suffix}" end end if RUBY_VERSION.to_f < 1.9 def expected_summary_output_for_example_specs <<-EOS.gsub(/^\s+\|/, '').chomp |Pending: (Failures listed here are expected and do not affect your suite's status) | | 1) pending spec with no implementation is pending | # Not yet implemented | # ./spec/rspec/core/resources/formatter_specs.rb:11 | | 2) pending command with block format with content that would fail is pending | # No reason given | Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:18 | # ./spec/support/formatter_support.rb:#{RUN_LINE}:in `run_rspec_with_formatter' | # ./spec/support/formatter_support.rb:3:in `run_example_specs_with_formatter' | # ./spec/support/sandboxing.rb:16 | # ./spec/support/sandboxing.rb:7 | |Failures: | | 1) pending command with block format behaves like shared is marked as pending but passes FIXED | Expected pending 'No reason given' to fail. No error was raised. | Shared Example Group: "shared" called from ./spec/rspec/core/resources/formatter_specs.rb:22 | # ./spec/rspec/core/resources/formatter_specs.rb:4 | | 2) failing spec fails | Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:37 | # ./spec/support/formatter_support.rb:#{RUN_LINE}:in `run_rspec_with_formatter' | # ./spec/support/formatter_support.rb:3:in `run_example_specs_with_formatter' | # ./spec/support/sandboxing.rb:16 | # ./spec/support/sandboxing.rb:7 | | 3) failing spec fails twice | Got 2 failures: | | 3.1) Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:41 | | 3.2) Failure/Error: expect(3).to eq(4) | | expected: 4 | got: 3 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:42 | | 4) a failing spec with odd backtraces fails with a backtrace that has no file | Failure/Error: Unable to find (erb) to read failed line | | RuntimeError: | foo | # (erb):1 | | 5) a failing spec with odd backtraces fails with a backtrace containing an erb file | Failure/Error: Unable to find /foo.html.erb to read failed line | | Exception: | Exception | # /foo.html.erb:1:in `
': foo (RuntimeError) | | 6) a failing spec with odd backtraces with a `nil` backtrace raises | Failure/Error: Unable to find matching line from backtrace | | RuntimeError: | boom | |Finished in n.nnnn seconds (files took n.nnnn seconds to load) |10 examples, 6 failures, 2 pending | |Failed examples: | |rspec ./spec/rspec/core/resources/formatter_specs.rb:4 # pending command with block format behaves like shared is marked as pending but passes |rspec ./spec/rspec/core/resources/formatter_specs.rb:36 # failing spec fails |rspec ./spec/rspec/core/resources/formatter_specs.rb:40 # failing spec fails twice |rspec ./spec/rspec/core/resources/formatter_specs.rb:47 # a failing spec with odd backtraces fails with a backtrace that has no file |rspec ./spec/rspec/core/resources/formatter_specs.rb:53 # a failing spec with odd backtraces fails with a backtrace containing an erb file |rspec ./spec/rspec/core/resources/formatter_specs.rb:71 # a failing spec with odd backtraces with a `nil` backtrace raises EOS end else def expected_summary_output_for_example_specs <<-EOS.gsub(/^\s+\|/, '').chomp |Pending: (Failures listed here are expected and do not affect your suite's status) | | 1) pending spec with no implementation is pending | # Not yet implemented | # ./spec/rspec/core/resources/formatter_specs.rb:11 | | 2) pending command with block format with content that would fail is pending | # No reason given | Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:18:in `block (3 levels) in ' | # ./spec/support/formatter_support.rb:#{RUN_LINE}:in `run_rspec_with_formatter' | # ./spec/support/formatter_support.rb:3:in `run_example_specs_with_formatter' | # ./spec/support/sandboxing.rb:16:in `block (3 levels) in ' | # ./spec/support/sandboxing.rb:7:in `block (2 levels) in ' | |Failures: | | 1) pending command with block format behaves like shared is marked as pending but passes FIXED | Expected pending 'No reason given' to fail. No error was raised. | Shared Example Group: "shared" called from ./spec/rspec/core/resources/formatter_specs.rb:22 | # ./spec/rspec/core/resources/formatter_specs.rb:4 | | 2) failing spec fails | Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:37:in `block (2 levels) in ' | # ./spec/support/formatter_support.rb:#{RUN_LINE}:in `run_rspec_with_formatter' | # ./spec/support/formatter_support.rb:3:in `run_example_specs_with_formatter' | # ./spec/support/sandboxing.rb:16:in `block (3 levels) in ' | # ./spec/support/sandboxing.rb:7:in `block (2 levels) in ' | | 3) failing spec fails twice | Got 2 failures: | | 3.1) Failure/Error: expect(1).to eq(2) | | expected: 2 | got: 1 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:41:in `block (2 levels) in ' | | 3.2) Failure/Error: expect(3).to eq(4) | | expected: 4 | got: 3 | | (compared using ==) | # ./spec/rspec/core/resources/formatter_specs.rb:42:in `block (2 levels) in ' | | 4) a failing spec with odd backtraces fails with a backtrace that has no file | Failure/Error: ERB.new("<%= raise 'foo' %>").result | | RuntimeError: | foo | # (erb):1:in `
' | # ./spec/rspec/core/resources/formatter_specs.rb:50:in `block (2 levels) in ' | # ./spec/support/formatter_support.rb:#{RUN_LINE}:in `run_rspec_with_formatter' | # ./spec/support/formatter_support.rb:3:in `run_example_specs_with_formatter' | # ./spec/support/sandboxing.rb:16:in `block (3 levels) in ' | # ./spec/support/sandboxing.rb:7:in `block (2 levels) in ' | | 5) a failing spec with odd backtraces fails with a backtrace containing an erb file | Failure/Error: Unable to find /foo.html.erb to read failed line | | Exception: | Exception | # /foo.html.erb:1:in `
': foo (RuntimeError) | | 6) a failing spec with odd backtraces with a `nil` backtrace raises | Failure/Error: Unable to find matching line from backtrace | | RuntimeError: | boom | |Finished in n.nnnn seconds (files took n.nnnn seconds to load) |10 examples, 6 failures, 2 pending | |Failed examples: | |rspec ./spec/rspec/core/resources/formatter_specs.rb:4 # pending command with block format behaves like shared is marked as pending but passes |rspec ./spec/rspec/core/resources/formatter_specs.rb:36 # failing spec fails |rspec ./spec/rspec/core/resources/formatter_specs.rb:40 # failing spec fails twice |rspec ./spec/rspec/core/resources/formatter_specs.rb:47 # a failing spec with odd backtraces fails with a backtrace that has no file |rspec ./spec/rspec/core/resources/formatter_specs.rb:53 # a failing spec with odd backtraces fails with a backtrace containing an erb file |rspec ./spec/rspec/core/resources/formatter_specs.rb:71 # a failing spec with odd backtraces with a `nil` backtrace raises EOS end end def send_notification type, notification reporter.notify type, notification end def reporter @reporter ||= setup_reporter end def setup_reporter(*streams) streams << config.output_stream if streams.empty? config.formatter_loader.add described_class, *streams @formatter = config.formatters.first @reporter = config.reporter end def setup_profiler config.profile_examples = true end def formatter_output @formatter_output ||= StringIO.new end def config @configuration ||= begin config = RSpec::Core::Configuration.new config.output_stream = formatter_output config end end def configure yield config end def formatter @formatter ||= begin setup_reporter @formatter end end def new_example(metadata = {}) metadata = metadata.dup result = RSpec::Core::Example::ExecutionResult.new result.started_at = ::Time.now result.record_finished(metadata.delete(:status) { :passed }, ::Time.now) result.exception = Exception.new if result.status == :failed instance_double(RSpec::Core::Example, :description => "Example", :full_description => "Example", :example_group => group, :execution_result => result, :location => "", :location_rerun_argument => "", :metadata => { :shared_group_inclusion_backtrace => [] }.merge(metadata) ) end def examples(n) Array.new(n) { new_example } end def group group = class_double "RSpec::Core::ExampleGroup", :description => "Group" allow(group).to receive(:parent_groups) { [group] } group end def start_notification(count) ::RSpec::Core::Notifications::StartNotification.new count end def stop_notification ::RSpec::Core::Notifications::ExamplesNotification.new reporter end def example_notification(specific_example = new_example) ::RSpec::Core::Notifications::ExampleNotification.for specific_example end def group_notification group_to_notify = group ::RSpec::Core::Notifications::GroupNotification.new group_to_notify end def message_notification(message) ::RSpec::Core::Notifications::MessageNotification.new message end def null_notification ::RSpec::Core::Notifications::NullNotification end def seed_notification(seed, used = true) ::RSpec::Core::Notifications::SeedNotification.new seed, used end def failed_examples_notification ::RSpec::Core::Notifications::ExamplesNotification.new reporter end def summary_notification(duration, examples, failed, pending, time, errors = 0) ::RSpec::Core::Notifications::SummaryNotification.new duration, examples, failed, pending, time, errors end def profile_notification(duration, examples, number) ::RSpec::Core::Notifications::ProfileNotification.new duration, examples, number, reporter.instance_variable_get('@profiler').example_groups end end if RSpec::Support::RubyFeatures.module_prepends_supported? module RSpec::Core class Reporter module EnforceRSpecNotificationsListComplete def notify(event, *args) return super if caller_locations(1, 1).first.label =~ /publish/ return super if RSPEC_NOTIFICATIONS.include?(event) raise "#{event.inspect} must be added to `RSPEC_NOTIFICATIONS`" end end prepend EnforceRSpecNotificationsListComplete end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_bisect_runner.rb0000664000000000000000000000134614557677674025510 0ustar rootrootrequire 'rspec/core/bisect/utilities' FakeBisectRunner = Struct.new(:all_ids, :always_failures, :dependent_failures) do def start(_shell_command, _spec_runner) yield self end def original_results failures = always_failures | dependent_failures.keys RSpec::Core::Bisect::ExampleSetDescriptor.new(all_ids, failures.sort) end def run(ids) failures = ids & always_failures dependent_failures.each do |failing_example, depends_upon| failures << failing_example if dependency_satisfied?(depends_upon, ids) end RSpec::Core::Bisect::ExampleSetDescriptor.new(ids.sort, failures.sort) end private def dependency_satisfied?(depends_upon, ids) depends_upon.all? { |d| ids.include?(d) } end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/0000775000000000000000000000000014557677674023246 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rake/0000775000000000000000000000000014557677674024170 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rake/tasklib.rb0000664000000000000000000000004614557677674026146 0ustar rootrootmodule Rake class TaskLib end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rake.rb0000664000000000000000000000000014557677674024503 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/erb.rb0000664000000000000000000000004314557677674024340 0ustar rootrootmodule ERB module Util end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/flexmock/0000775000000000000000000000000014557677674025056 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/flexmock/rspec.rb0000664000000000000000000000006114557677674026514 0ustar rootrootmodule FlexMock module MockContainer end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/test/0000775000000000000000000000000014557677674024225 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/test/unit/0000775000000000000000000000000014557677674025204 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/test/unit/assertions.rb0000664000000000000000000000010214557677674027714 0ustar rootrootmodule Test module Unit module Assertions end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/mocha/0000775000000000000000000000000014557677674024335 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/mocha/api.rb0000664000000000000000000000004414557677674025431 0ustar rootrootmodule Mocha module API end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/json.rb0000664000000000000000000000000014557677674024532 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rspec/0000775000000000000000000000000014557677674024362 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rspec/expectations.rb0000664000000000000000000000027414557677674027420 0ustar rootrootmodule RSpec module Expectations MultipleExpectationsNotMetError = Class.new(Exception) end module Matchers def self.configuration; RSpec::Core::NullReporter; end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rspec/mocks.rb0000664000000000000000000000020414557677674026017 0ustar rootrootmodule RSpec module Mocks module ExampleMethods end def self.configuration; RSpec::Core::NullReporter; end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/open3.rb0000664000000000000000000000055514557677674024624 0ustar rootrootunless caller.any? { |line| line.include?("rspec/core/bisect/shell_runner.rb") } raise "open3 loaded from unexpected file. " \ "It is allowed to be loaded by the Bisect::ShellRunner " \ "because that is not loaded in the same process as end-user code, " \ "and we generally don't want open3 loaded for other things." end module Open3 end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/minitest.rb0000664000000000000000000000000014557677674025415 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/minitest/0000775000000000000000000000000014557677674025102 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/minitest/assertions.rb0000664000000000000000000000005614557677674027622 0ustar rootrootmodule Minitest module Assertions end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/drb/0000775000000000000000000000000014557677674024015 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/drb/acl.rb0000664000000000000000000000000014557677674025067 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/drb/drb.rb0000664000000000000000000000000014557677674025077 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/rr.rb0000664000000000000000000000021614557677674024215 0ustar rootrootmodule RR module Errors BACKTRACE_IDENTIFIER = /doesn't matter/ end module Extensions module InstanceMethods end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/fake_libs/coderay.rb0000664000000000000000000000000014557677674025207 0ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/error_highlight.rb0000664000000000000000000000065614557677674025043 0ustar rootrootif defined?(ErrorHighlight) class DummyErrorHighlightFormatter def self.message_for(spot) "" end end RSpec.configure do |c| c.around(:disable_error_highlight => true) do |ex| begin old_formatter = ErrorHighlight.formatter ErrorHighlight.formatter = DummyErrorHighlightFormatter ex.run ensure ErrorHighlight.formatter = old_formatter end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/mathn_integration_support.rb0000664000000000000000000000101414557677674027156 0ustar rootrootrequire 'rspec/support/spec/in_sub_process' module MathnIntegrationSupport include RSpec::Support::InSubProcess if RUBY_VERSION.to_f >= 2.2 def with_mathn_loaded skip "lib/mathn.rb is deprecated in Ruby 2.2" end elsif RUBY_VERSION.to_f < 1.9 def with_mathn_loaded in_sub_process do expect { require 'mathn' }.to output.to_stderr yield end end else def with_mathn_loaded in_sub_process do require 'mathn' yield end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/support/aruba_support.rb0000664000000000000000000000501014557677674024536 0ustar rootrootrequire 'support/helper_methods' if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version == "9.1.17.0" # A regression appeared in require_relative in JRuby 9.1.17.0 where require some # how ends up private, this monkey patch uses `send` module Kernel module_function def require_relative(relative_arg) relative_arg = relative_arg.to_path if relative_arg.respond_to? :to_path relative_arg = JRuby::Type.convert_to_str(relative_arg) caller.first.rindex(/:\d+:in /) file = $` # just the filename raise LoadError, "cannot infer basepath" if /\A\((.*)\)/ =~ file # eval etc. absolute_feature = File.expand_path(relative_arg, File.dirname(File.realpath(file))) # This was the original: # ::Kernel.require absolute_feature ::Kernel.send(:require, absolute_feature) end end end module ArubaLoader extend RSpec::Support::WithIsolatedStdErr with_isolated_stderr do require 'aruba/api' end end RSpec.shared_context "aruba support" do include Aruba::Api include RSpecHelpers let(:stderr) { StringIO.new } let(:stdout) { StringIO.new } attr_reader :last_cmd_stdout, :last_cmd_stderr, :last_cmd_exit_status def run_command(cmd) RSpec.configuration.color = true temp_stdout = StringIO.new temp_stderr = StringIO.new # So that `RSpec.warning` will go to temp_stderr. allow(::Kernel).to receive(:warn) { |msg| temp_stderr.puts(msg) } cmd_parts = ["--no-profile"] + Shellwords.split(cmd) handle_current_dir_change do cd '.' do with_isolated_stderr do @last_cmd_exit_status = RSpec::Core::Runner.run(cmd_parts, temp_stderr, temp_stdout) end end end ensure RSpec.reset RSpec.configuration.color = true # Ensure it gets cached with a proper value -- if we leave it set to nil, # and the next spec operates in a different dir, it could get set to an # invalid value. RSpec::Core::Metadata.relative_path_regex @last_cmd_stdout = temp_stdout.string @last_cmd_stderr = temp_stderr.string stdout.write(@last_cmd_stdout) stderr.write(@last_cmd_stderr) end def write_file_formatted(file_name, contents) # remove blank line at the start of the string and # strip extra indentation. formatted_contents = unindent(contents.sub(/\A\n/, "")) write_file file_name, formatted_contents end end RSpec.configure do |c| c.define_derived_metadata(:file_path => %r{spec/integration}) do |meta| meta[:slow] = true end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/0000775000000000000000000000000014557677674022136 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/persistence_failures_spec.rb0000664000000000000000000000443714557677674027723 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'Persistence failures' do include_context "aruba support" before { setup_aruba } context "when `config.example_status_persistence_file_path` is configured" do context "to an invalid file path (e.g. spec/spec_helper.rb/examples.txt)" do before do write_file_formatted "spec/1_spec.rb", " RSpec.configure do |c| c.example_status_persistence_file_path = 'spec/1_spec.rb/examples.txt' end RSpec.describe { example { } } " end it 'emits a helpful warning to the user, indicating we cannot write to it, and still runs the spec suite' do run_command "spec/1_spec.rb" expect(last_cmd_stderr).to include( "WARNING: Could not write", "spec/1_spec.rb/examples.txt", "config.example_status_persistence_file_path", "Errno:" ) expect(last_cmd_stdout).to include("1 example") end end context "to a file path for which we lack permissions" do before do write_file_formatted "spec/1_spec.rb", " RSpec.configure do |c| c.example_status_persistence_file_path = 'spec/examples.txt' end RSpec.describe { example { } } " write_file_formatted "spec/examples.txt", "" cd '.' do FileUtils.chmod 0000, "spec/examples.txt" end end it 'emits a helpful warning to the user, indicating we cannot read from it, and still runs the spec suite' do skip "Legacy builds run as root and this will never pass" if ENV['LEGACY_CI'] run_command "spec/1_spec.rb" expected_snippets = [ "WARNING: Could not read", "spec/examples.txt", "config.example_status_persistence_file_path", "Errno:" ] if RSpec::Support::OS.windows? # Not sure why, but on windows it doesn't trigger the read error, it # triggers a write error instead. The important thing is that whatever # system error occurs is reported accurately. expected_snippets[0] = "WARNING: Could not write" end expect(last_cmd_stderr).to include(*expected_snippets) expect(last_cmd_stdout).to include("1 example") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/suite_hooks_errors_spec.rb0000664000000000000000000001010314557677674027420 0ustar rootrootrequire 'support/aruba_support' require 'support/formatter_support' RSpec.describe 'Suite hook errors' do include_context "aruba support" include FormatterSupport let(:failure_exit_code) { rand(97) + 2 } # 2..99 let(:error_exit_code) { failure_exit_code + 2 } # 4..101 if RSpec::Support::Ruby.jruby_9000? && RSpec::Support::Ruby.jruby_version > '9.2.0.0' let(:spec_line_suffix) { ":in `block in
'" } elsif RSpec::Support::Ruby.jruby_9000? let(:spec_line_suffix) { ":in `block in (root)'" } elsif RSpec::Support::Ruby.jruby? let(:spec_line_suffix) { ":in `(root)'" } elsif RUBY_VERSION == "1.8.7" let(:spec_line_suffix) { "" } else let(:spec_line_suffix) { ":in `block (2 levels) in '" } end before do setup_aruba RSpec.configure do |c| c.filter_gems_from_backtrace "gems/aruba" c.filter_gems_from_backtrace "gems/bundler" c.backtrace_exclusion_patterns << %r{/rspec-core/spec/} << %r{rspec_with_simplecov} c.failure_exit_code = failure_exit_code c.error_exit_code = error_exit_code end end def run_spec_expecting_non_zero(before_or_after) write_file "the_spec.rb", " RSpec.configure do |c| c.#{before_or_after}(:suite) do raise 'boom' end end RSpec.describe do it { } end " run_command "the_spec.rb" expect(last_cmd_exit_status).to eq(error_exit_code) normalize_durations(last_cmd_stdout) end it 'nicely formats errors in `before(:suite)` hooks and exits with non-zero' do output = run_spec_expecting_non_zero(:before) expect(output).to eq unindent(<<-EOS) An error occurred in a `before(:suite)` hook. Failure/Error: raise 'boom' RuntimeError: boom # ./the_spec.rb:4#{spec_line_suffix} Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples EOS end it 'nicely formats errors in `after(:suite)` hooks and exits with non-zero' do output = run_spec_expecting_non_zero(:after) expect(output).to eq unindent(<<-EOS) . An error occurred in an `after(:suite)` hook. Failure/Error: raise 'boom' RuntimeError: boom # ./the_spec.rb:4#{spec_line_suffix} Finished in n.nnnn seconds (files took n.nnnn seconds to load) 1 example, 0 failures, 1 error occurred outside of examples EOS end it 'nicely formats errors from multiple :suite hooks of both types and exits with non-zero' do write_file "the_spec.rb", " RSpec.configure do |c| c.before(:suite) { raise 'before 1' } c.before(:suite) { raise 'before 2' } c.after(:suite) { raise 'after 1' } c.after(:suite) { raise 'after 2' } end RSpec.describe do it { } end " cause = if RSpec::Support::Ruby.jruby_9000? && RSpec::Support::Ruby.jruby_version > '9.2.0.0' unindent(<<-EOS) # ------------------ # --- Caused by: --- # RuntimeError: # before 1 # ./the_spec.rb:3:in `block in
' EOS else "" end run_command "the_spec.rb" expect(last_cmd_exit_status).to eq(error_exit_code) output = normalize_durations(last_cmd_stdout) expect(output).to eq unindent(<<-EOS) An error occurred in a `before(:suite)` hook. Failure/Error: c.before(:suite) { raise 'before 1' } RuntimeError: before 1 # ./the_spec.rb:3#{spec_line_suffix} An error occurred in an `after(:suite)` hook. Failure/Error: c.after(:suite) { raise 'after 2' } RuntimeError: after 2 # ./the_spec.rb:6#{spec_line_suffix} #{ cause } An error occurred in an `after(:suite)` hook. Failure/Error: c.after(:suite) { raise 'after 1' } RuntimeError: after 1 # ./the_spec.rb:5#{spec_line_suffix} #{ cause } Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 3 errors occurred outside of examples EOS end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/spec_file_load_errors_spec.rb0000664000000000000000000001751214557677674030027 0ustar rootrootrequire 'support/aruba_support' require 'support/formatter_support' RSpec.describe 'Spec file load errors' do include_context "aruba support" include FormatterSupport let(:failure_exit_code) { rand(97) + 2 } # 2..99 let(:error_exit_code) { failure_exit_code + 1 } # 3..100 if RSpec::Support::Ruby.jruby_9000? let(:spec_line_suffix) { ":in `
'" } elsif RSpec::Support::Ruby.jruby? let(:spec_line_suffix) { ":in `(root)'" } elsif RUBY_VERSION == "1.8.7" let(:spec_line_suffix) { "" } else let(:spec_line_suffix) { ":in `'" } end before do setup_aruba RSpec.configure do |c| c.filter_gems_from_backtrace "gems/aruba" c.filter_gems_from_backtrace "gems/bundler" c.backtrace_exclusion_patterns << %r{/rspec-core/spec/} << %r{rspec_with_simplecov} c.failure_exit_code = failure_exit_code c.error_exit_code = error_exit_code end end it 'nicely handles load-time errors from --require files' do write_file_formatted "helper_with_error.rb", "raise 'boom'" run_command "--require ./helper_with_error" expect(last_cmd_exit_status).to eq(error_exit_code) output = normalize_durations(last_cmd_stdout) expect(output).to eq unindent(<<-EOS) An error occurred while loading ./helper_with_error. Failure/Error: raise 'boom' RuntimeError: boom # ./helper_with_error.rb:1#{spec_line_suffix} No examples found. Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples EOS end it 'prints a single error when it happens on --require files' do write_file_formatted "helper_with_error.rb", "raise 'boom'" write_file_formatted "1_spec.rb", " RSpec.describe 'A broken spec file that will raise when loaded' do raise 'kaboom' end " run_command "--require ./helper_with_error 1_spec.rb" expect(last_cmd_exit_status).to eq(error_exit_code) output = normalize_durations(last_cmd_stdout) expect(output).to eq unindent(<<-EOS) An error occurred while loading ./helper_with_error. Failure/Error: raise 'boom' RuntimeError: boom # ./helper_with_error.rb:1#{spec_line_suffix} No examples found. Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples EOS end it 'prints a warning when a helper file exits early' do write_file_formatted "helper_with_exit.rb", "exit 999" expect { run_command "--require ./helper_with_exit.rb" }.to raise_error(SystemExit) output = normalize_durations(last_cmd_stdout) # Remove extra line which is only shown on CRuby output = output.sub("# ./helper_with_exit.rb:1:in `exit'\n", "") if defined?(JRUBY_VERSION) && !JRUBY_VERSION.empty? expect(output).to eq unindent(<<-EOS) While loading ./helper_with_exit.rb an `exit` / `raise SystemExit` occurred, RSpec will now quit. Failure/Error: Unable to find org/jruby/RubyKernel.java to read failed line SystemExit: exit # ./helper_with_exit.rb:1#{spec_line_suffix} EOS else expect(output).to eq unindent(<<-EOS) While loading ./helper_with_exit.rb an `exit` / `raise SystemExit` occurred, RSpec will now quit. Failure/Error: exit 999 SystemExit: exit # ./helper_with_exit.rb:1#{spec_line_suffix} EOS end end it 'nicely handles load-time errors in user spec files', :disable_error_highlight => true do write_file_formatted "1_spec.rb", " boom RSpec.describe 'Calling boom' do it 'will not run this example' do expect(1).to eq 1 end end " write_file_formatted "2_spec.rb", " RSpec.describe 'No Error' do it 'will not run this example, either' do expect(1).to eq 1 end end " write_file_formatted "3_spec.rb", " boom RSpec.describe 'Calling boom again' do it 'will not run this example, either' do expect(1).to eq 1 end end " run_command "1_spec.rb 2_spec.rb 3_spec.rb" expect(last_cmd_exit_status).to eq(error_exit_code) output = normalize_durations(last_cmd_stdout) object_suffix = if RUBY_VERSION.to_f > 3.2 "" else ":Object" end expect(output).to eq unindent(<<-EOS) An error occurred while loading ./1_spec.rb. Failure/Error: boom NameError: undefined local variable or method `boom' for main#{object_suffix} # ./1_spec.rb:1#{spec_line_suffix} An error occurred while loading ./3_spec.rb. Failure/Error: boom NameError: undefined local variable or method `boom' for main#{object_suffix} # ./3_spec.rb:1#{spec_line_suffix} Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 2 errors occurred outside of examples EOS end describe 'handling syntax errors' do let(:formatted_output) { normalize_durations(last_cmd_stdout).gsub(Dir.pwd, '.').gsub(/\e\[[0-9;]+m/, '') } before(:example) do write_file_formatted "broken_file.rb", " class WorkInProgress def initialize(arg) def foo end end " end if RSpec::Support::RubyFeatures.supports_syntax_suggest? it 'uses syntax_suggest formatting when available' do in_sub_process do require "syntax_suggest" run_command "--require ./broken_file" expect(last_cmd_exit_status).to eq(error_exit_code) expect(formatted_output).to include unindent(<<-EOS) While loading ./broken_file a `raise SyntaxError` occurred, RSpec will now quit. Failure/Error: __send__(method, file) EOS # A fix was backported to 3.2.3 if RUBY_VERSION > '3.2.2' expect(formatted_output).to include unindent(<<-EOS) SyntaxError: --> ./tmp/aruba/broken_file.rb Unmatched keyword, missing `end' ? 1 class WorkInProgress > 2 def initialize(arg) 3 def foo 4 end 5 end EOS else expect(formatted_output).to include unindent(<<-EOS) SyntaxError: --> ./tmp/aruba/broken_file.rb Unmatched keyword, missing `end' ? 1 class WorkInProgress > 2 def initialize(arg) 4 end 5 end EOS end expect(formatted_output).to include "./tmp/aruba/broken_file.rb:5: syntax error" expect(formatted_output).to include unindent(<<-EOS) Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples EOS end end else it 'prints a basic error when no syntax_suggest is available/loaded', :skip => RUBY_VERSION.to_f < 1.9 || RSpec::Support::Ruby.jruby? do run_command "--require ./broken_file" expect(last_cmd_exit_status).to eq(error_exit_code) expect(formatted_output).to include unindent(<<-EOS) While loading ./broken_file a `raise SyntaxError` occurred, RSpec will now quit. Failure/Error: __send__(method, file) EOS # This is subset of the formatted_output, it continues slightly but differs on different Rubies expect(formatted_output).to include "SyntaxError:\n ./tmp/aruba/broken_file.rb:5: syntax error" expect(formatted_output).to include unindent(<<-EOS) Finished in n.nnnn seconds (files took n.nnnn seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples EOS end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/failed_line_detection_spec.rb0000664000000000000000000001036614557677674027774 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'Failed line detection' do include_context "aruba support" before { setup_aruba } it "finds the source of a failure in a spec file that is defined at the current directory instead of in the normal `spec` subdir" do write_file "the_spec.rb", " RSpec.describe do it 'fails via expect' do expect(1).to eq(2) end end " run_command "the_spec.rb" expect(last_cmd_stdout).to include("expect(1).to eq(2)") end it "finds the source of a failure in a spec file loaded by running `ruby file` rather than loaded directly by RSpec" do write_file "passing_spec.rb", " RSpec.describe do example { } end " write_file "failing_spec.rb", " RSpec.describe do it 'fails via expect' do expect(1).to eq(2) end end " file = cd('.') { "#{Dir.pwd}/failing_spec.rb" } load file run_command "passing_spec.rb" expect(last_cmd_stdout).to include("expect(1).to eq(2)") end it "finds the direct source of failure in any lib, app or spec file, and allows the user to configure what is considered a project source dir" do write_file "lib/lib_mod.rb", " module LibMod def self.trigger_failure raise 'LibMod failure' end end " write_file "app/app_mod.rb", " module AppMod def self.trigger_failure raise 'AppMod failure' end end " write_file "spec/support/spec_support.rb", " module SpecSupport def self.trigger_failure raise 'SpecSupport failure' end end " write_file "spec/default_config_spec.rb", " require './lib/lib_mod' require './spec/support/spec_support' require './app/app_mod' RSpec.describe do example('1') { LibMod.trigger_failure } example('2') { AppMod.trigger_failure } example('3') { SpecSupport.trigger_failure } end " run_command "./spec/default_config_spec.rb" expect(last_cmd_stdout).to include("raise 'LibMod failure'"). and include("raise 'AppMod failure'"). and include("raise 'SpecSupport failure'"). and exclude("AppMod.trigger_failure") write_file "spec/change_config_spec.rb", " require './app/app_mod' RSpec.configure do |c| c.project_source_dirs = %w[ lib spec ] end RSpec.describe do example('1') { AppMod.trigger_failure } end " run_command "./spec/change_config_spec.rb" expect(last_cmd_stdout).to include("AppMod.trigger_failure"). and exclude("raise 'AppMod failure'") end it "finds the callsite of a method provided by a gem that fails (rather than the line in the gem)" do write_file "vendor/gems/assertions/lib/assertions.rb", " module Assertions AssertionFailed = Class.new(StandardError) def assert(value, msg) raise(AssertionFailed, msg) unless value end end " write_file "spec/unit/the_spec.rb", " require './vendor/gems/assertions/lib/assertions' RSpec.describe do include Assertions it 'fails via assert' do assert false, 'failed assertion' end it 'fails via expect' do expect(1).to eq(2) end end " run_command "" expect(last_cmd_stdout).to include("assert false, 'failed assertion'"). and include("expect(1).to eq(2)"). and exclude("raise(AssertionFailed, msg)") end it "falls back to finding a line in a gem when there are no backtrace lines in the app, lib or spec directories" do write_file "vendor/gems/before_failure/lib/before_failure.rb", " RSpec.configure do |c| c.before { raise 'before failure!' } end " write_file "spec/unit/the_spec.rb", " require './vendor/gems/before_failure/lib/before_failure' RSpec.describe do example('1') { } end " run_command "" expect(last_cmd_stdout).to include("c.before { raise 'before failure!' }"). and exclude("Unable to find matching line from backtrace") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/order_spec.rb0000664000000000000000000001737314557677674024623 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'command line', :ui do include_context "aruba support" before :all do write_file 'spec/simple_spec.rb', " RSpec.describe 'group 1' do specify('group 1 example 1') {} specify('group 1 example 2') {} specify('group 1 example 3') {} describe 'group 1-1' do specify('group 1-1 example 1') {} specify('group 1-1 example 2') {} specify('group 1-1 example 3') {} end end " write_file 'spec/simple_spec2.rb', " RSpec.describe 'group 2' do specify('group 2 example 1') {} specify('group 2 example 2') {} specify('group 2 example 3') {} describe 'group 2-1' do specify('group 2-1 example 1') {} specify('group 2-1 example 2') {} specify('group 2-1 example 3') {} end end " write_file 'spec/order_spec.rb', " RSpec.describe 'group 1' do specify('group 1 example 1') {} specify('group 1 example 2') {} specify('group 1 example 3') {} specify('group 1 example 4') {} specify('group 1 example 5') {} specify('group 1 example 6') {} specify('group 1 example 7') {} specify('group 1 example 8') {} specify('group 1 example 9') {} specify('group 1 example 10') {} describe 'group 1-1' do specify('group 1-1 example 1') {} specify('group 1-1 example 2') {} specify('group 1-1 example 3') {} specify('group 1-1 example 4') {} specify('group 1-1 example 5') {} specify('group 1-1 example 6') {} specify('group 1-1 example 7') {} specify('group 1-1 example 8') {} specify('group 1-1 example 9') {} specify('group 1-1 example 10') {} end describe('group 1-2') { specify('example') {} } describe('group 1-3') { specify('example') {} } describe('group 1-4') { specify('example') {} } describe('group 1-5') { specify('example') {} } describe('group 1-6') { specify('example') {} } describe('group 1-7') { specify('example') {} } describe('group 1-8') { specify('example') {} } describe('group 1-9') { specify('example') {} } describe('group 1-10') { specify('example') {} } end RSpec.describe('group 2') { specify('example') {} } RSpec.describe('group 3') { specify('example') {} } RSpec.describe('group 4') { specify('example') {} } RSpec.describe('group 5') { specify('example') {} } RSpec.describe('group 6') { specify('example') {} } RSpec.describe('group 7') { specify('example') {} } RSpec.describe('group 8') { specify('example') {} } RSpec.describe('group 9') { specify('example') {} } RSpec.describe('group 10') { specify('example') {} } " end describe '--order rand' do it 'runs the examples and groups in a different order each time' do run_command 'spec/order_spec.rb --order rand -f doc' original_seed = srand RSpec.configuration.seed = srand # reset seed in same process run_command 'spec/order_spec.rb --order rand -f doc' srand original_seed expect(stdout.string).to match(/Randomized with seed \d+/) top_level_groups {|first_run, second_run| expect(first_run).to_not eq(second_run)} nested_groups {|first_run, second_run| expect(first_run).to_not eq(second_run)} examples('group 1') {|first_run, second_run| expect(first_run).to_not eq(second_run)} examples('group 1-1') {|first_run, second_run| expect(first_run).to_not eq(second_run)} end end describe '--order rand:SEED' do it 'runs the examples and groups in the same order each time' do 2.times { run_command 'spec/order_spec.rb --order rand:123 -f doc' } expect(stdout.string).to match(/Randomized with seed 123/) top_level_groups {|first_run, second_run| expect(first_run).to eq(second_run)} nested_groups {|first_run, second_run| expect(first_run).to eq(second_run)} examples('group 1') {|first_run, second_run| expect(first_run).to eq(second_run)} examples('group 1-1') {|first_run, second_run| expect(first_run).to eq(second_run)} end end describe '--seed SEED' do it "forces '--order rand' and runs the examples and groups in the same order each time" do 2.times { run_command 'spec/order_spec.rb --seed 123 -f doc' } expect(stdout.string).to match(/Randomized with seed 123/) top_level_groups {|first_run, second_run| expect(first_run).to eq(second_run)} nested_groups {|first_run, second_run| expect(first_run).to eq(second_run)} examples('group 1') {|first_run, second_run| expect(first_run).to eq(second_run)} examples('group 1-1') {|first_run, second_run| expect(first_run).to eq(second_run)} end it "runs examples in the same order, regardless of the order in which files are given" do run_command 'spec/simple_spec.rb spec/simple_spec2.rb --seed 1337 -f doc' run_command 'spec/simple_spec2.rb spec/simple_spec.rb --seed 1337 -f doc' top_level_groups {|first_run, second_run| expect(first_run).to eq(second_run)} nested_groups {|first_run, second_run| expect(first_run).to eq(second_run)} end end describe '--order rand --order recently-modified' do it 'overrides random ordering with recently-modified option' do 2.times { run_command 'spec/order_spec.rb --order rand --order recently-modified -f doc' } expect(stdout.string).not_to match(/Randomized with seed/) top_level_groups { |first_run, second_run| expect(first_run).to eq(second_run) } nested_groups { |first_run, second_run| expect(first_run).to eq(second_run) } end end describe '--order defined on CLI with --order rand in .rspec' do after { remove '.rspec' } it "overrides --order rand with --order defined" do write_file '.rspec', '--order rand' run_command 'spec/order_spec.rb --order defined -f doc' expect(stdout.string).not_to match(/Randomized/) expect(stdout.string).to match( /group 1.*group 1 example 1.*group 1 example 2.*group 1-1.*group 1-2.*group 2.*/m ) end end context 'when a custom order is configured' do after { remove 'spec/custom_order_spec.rb' } before do write_file 'spec/custom_order_spec.rb', " RSpec.configure do |config| config.register_ordering :global do |list| list.sort_by { |item| item.description } end end RSpec.describe 'group B' do specify('group B example D') {} specify('group B example B') {} specify('group B example A') {} specify('group B example C') {} end RSpec.describe 'group A' do specify('group A example 1') {} end " end it 'orders the groups and examples by the provided strategy' do run_command 'spec/custom_order_spec.rb -f doc' top_level_groups { |groups| expect(groups.flatten).to eq(['group A', 'group B']) } examples('group B') do |examples| letters = examples.flatten.map { |e| e[/(.)\z/, 1] } expect(letters).to eq(['A', 'B', 'C', 'D']) end end end def examples(group) yield split_in_half(stdout.string.scan(/^\s+#{group} example.*$/)) end def top_level_groups yield example_groups_at_level(0) end def nested_groups yield example_groups_at_level(2) end def example_groups_at_level(level) split_in_half(stdout.string.scan(/^\s{#{level*2}}group.*$/)) end def split_in_half(array) length, midpoint = array.length, array.length / 2 return array.slice(0, midpoint), array.slice(midpoint, length) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/filtering_spec.rb0000664000000000000000000002340714557677674025466 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'Filtering' do include_context "aruba support" before { setup_aruba } it 'prints a rerun command for shared examples in external files that works to rerun' do write_file "spec/support/shared_examples.rb", " RSpec.shared_examples 'with a failing example' do example { expect(1).to eq(2) } # failing example { expect(2).to eq(2) } # passing end " write_file "spec/host_group_spec.rb", " load File.expand_path('../support/shared_examples.rb', __FILE__) RSpec.describe 'A group with shared examples' do include_examples 'with a failing example' end RSpec.describe 'A group with a passing example' do example { expect(1).to eq(1) } end " run_command "" expect(last_cmd_stdout).to include("3 examples, 1 failure") run_rerun_command_for_failing_spec expect(last_cmd_stdout).to include("1 example, 1 failure") # There was originally a bug when doing it again... run_rerun_command_for_failing_spec expect(last_cmd_stdout).to include("1 example, 1 failure") end def run_rerun_command_for_failing_spec command = last_cmd_stdout[/Failed examples:\s+rspec (\S+) #/, 1] run_command command end context "with a shared example containing a context in a separate file" do it "runs the example nested inside the shared" do write_file_formatted 'spec/shared_example.rb', " RSpec.shared_examples_for 'a shared example' do it 'succeeds' do end context 'with a nested context' do it 'succeeds (nested)' do end end end " write_file_formatted 'spec/simple_spec.rb', " require File.join(File.dirname(__FILE__), 'shared_example.rb') RSpec.describe 'top level' do it_behaves_like 'a shared example' end " run_command 'spec/simple_spec.rb:3 -fd' expect(last_cmd_stdout).to match(/2 examples, 0 failures/) end end context "passing a line-number filter" do it "works with different custom runners used in the same process" do result_counter = Class.new do RSpec::Core::Formatters.register(self, :example_passed) attr_accessor :passed_examples def initialize(*) @passed_examples = 0 end def example_passed(notification) @passed_examples += 1 end end spec_file = "spec/filtering_custom_runner_spec.rb" write_file_formatted spec_file, " RSpec.describe 'A group' do example('ex 1') { } example('ex 2') { } end " spec_file_path = expand_path(spec_file) formatter = result_counter.new RSpec.configuration.add_formatter(formatter) opts = RSpec::Core::ConfigurationOptions.new(["#{spec_file_path}[1:1]"]) RSpec::Core::Runner.new(opts).run(StringIO.new, StringIO.new) expect(formatter.passed_examples).to eq 1 RSpec.clear_examples formatter = result_counter.new RSpec.configuration.add_formatter(formatter) opts = RSpec::Core::ConfigurationOptions.new(["#{spec_file_path}[1:2]"]) RSpec::Core::Runner.new(opts).run(StringIO.new, StringIO.new) expect(formatter.passed_examples).to eq 1 end it "trumps exclusions, except for :if/:unless (which are absolute exclusions)" do write_file_formatted 'spec/a_spec.rb', " RSpec.configure do |c| c.filter_run_excluding :slow end RSpec.describe 'A slow group', :slow do example('ex 1') { } example('ex 2') { } end RSpec.describe 'A group with a slow example' do example('ex 3' ) { } example('ex 4', :slow ) { } example('ex 5', :if => false) { } end " run_command "spec/a_spec.rb -fd" expect(last_cmd_stdout).to include("1 example, 0 failures", "ex 3").and exclude("ex 1", "ex 2", "ex 4", "ex 5") run_command "spec/a_spec.rb:5 -fd" # selecting 'A slow group' expect(last_cmd_stdout).to include("2 examples, 0 failures", "ex 1", "ex 2").and exclude("ex 3", "ex 4", "ex 5") run_command "spec/a_spec.rb:12 -fd" # selecting slow example expect(last_cmd_stdout).to include("1 example, 0 failures", "ex 4").and exclude("ex 1", "ex 2", "ex 3", "ex 5") run_command "spec/a_spec.rb:13 -fd" # selecting :if => false example expect(last_cmd_stdout).to include("0 examples, 0 failures").and exclude("ex 1", "ex 2", "ex 3", "ex 4", "ex 5") end it 'works correctly when line numbers align with a shared example group line number from another file' do write_file_formatted 'spec/support/shared_examples_with_matching_line.rb', " # line 1 # line 2 # line 3 RSpec.shared_examples_for 'shared examples' do # line 4 it 'fails' do # line 5 fail 'shared example' end end " write_file_formatted 'spec/some_spec.rb', " require File.expand_path('../support/shared_examples_with_matching_line', __FILE__) # line 1 RSpec.describe 'A group' do # line 2 it_behaves_like 'shared examples' # line 3 # line 4 it 'passes' do # line 5 expect(1).to eq(1) end end " run_command "spec/some_spec.rb:5" expect(last_cmd_stdout).to include("1 example, 0 failures") end end context "passing a line-number-filtered file and a non-filtered file" do it "applies the line number filtering only to the filtered file, running all specs in the non-filtered file except excluded ones" do write_file_formatted "spec/file_1_spec.rb", " RSpec.describe 'File 1' do it('passes') { } it('fails') { fail } end " write_file_formatted "spec/file_2_spec.rb", " RSpec.configure do |c| c.filter_run_excluding :exclude_me end RSpec.describe 'File 2' do it('passes') { } it('passes') { } it('fails', :exclude_me) { fail } end " run_command "spec/file_1_spec.rb:2 spec/file_2_spec.rb -fd" expect(last_cmd_stdout).to match(/3 examples, 0 failures/) expect(last_cmd_stdout).not_to match(/fails/) end it 'applies command line tag filters only to files that lack a line number filter' do write_file_formatted "spec/file_1_spec.rb", " RSpec.describe 'File 1' do it('is selected by line') { } it('is not selected', :tag) { } end " write_file_formatted "spec/file_2_spec.rb", " RSpec.describe 'File 2' do it('is not selected') { } it('is selected by tag', :tag) { } end " run_command "spec/file_1_spec.rb:2 spec/file_2_spec.rb --tag tag -fd" expect(last_cmd_stdout).to include( "2 examples, 0 failures", "is selected by line", "is selected by tag" ).and exclude("not selected") end end context "passing example ids at the command line" do it "selects matching examples" do write_file_formatted "spec/file_1_spec.rb", " RSpec.describe 'File 1' do 1.upto(3) do |i| example('ex ' + i.to_s) { expect(i).to be_odd } end end " write_file_formatted "spec/file_2_spec.rb", " RSpec.describe 'File 2' do 1.upto(3) do |i| example('ex ' + i.to_s) { expect(i).to be_even } end end " # Using the form that Metadata.relative_path returns... run_command "./spec/file_1_spec.rb[1:1,1:3] ./spec/file_2_spec.rb[1:2]" expect(last_cmd_stdout).to match(/3 examples, 0 failures/) # Using spaces between scoped ids, and quoting the whole thing... run_command "'./spec/file_1_spec.rb[1:1, 1:3]' ./spec/file_2_spec.rb[1:2]" expect(last_cmd_stdout).to match(/3 examples, 0 failures/) # Without the leading `.`... run_command "spec/file_1_spec.rb[1:1,1:3] spec/file_2_spec.rb[1:2]" expect(last_cmd_stdout).to match(/3 examples, 0 failures/) # Using absolute paths... spec_root = cd('.') { File.expand_path("spec") } run_command "#{spec_root}/file_1_spec.rb[1:1,1:3] #{spec_root}/file_2_spec.rb[1:2]" expect(last_cmd_stdout).to match(/3 examples, 0 failures/) end it "selects matching example groups" do write_file_formatted "spec/file_1_spec.rb", " RSpec.describe 'Group 1' do example { fail } context 'nested 1' do it { } it { } end context 'nested 2' do example { fail } end end " run_command "./spec/file_1_spec.rb[1:2]" expect(last_cmd_stdout).to match(/2 examples, 0 failures/) end end context "with `filter_run_when_matching`" do it "filters to matching examples" do write_file_formatted "spec/example_spec.rb", " RSpec.configure do |c| c.filter_run_when_matching :some_tag end RSpec.describe 'A matching group', :some_tag do it 'passes' do end end RSpec.describe 'An unmatching group' do it 'passes', :some_tag do end it 'fails' do raise 'boom' end end " run_command "" expect(last_cmd_stdout).to include("2 examples, 0 failures") end it "is ignored when no examples match the provided filter" do write_file_formatted "spec/example_spec.rb", " RSpec.configure do |c| c.filter_run_when_matching :some_tag end RSpec.describe 'A group' do it 'is still run' do end end " run_command "" expect(last_cmd_stdout).to include("1 example, 0 failures") end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/bisect_spec.rb0000664000000000000000000000645414557677674024757 0ustar rootrootRSpec::Support.require_rspec_core "formatters/bisect_progress_formatter" module RSpec::Core RSpec.describe "Bisect", :slow, :simulate_shell_allowing_unquoted_ids do include FormatterSupport def bisect(cli_args, expected_status=nil) options = ConfigurationOptions.new(cli_args) expect { status = Invocations::Bisect.new.call(options, formatter_output, formatter_output) expect(status).to eq(expected_status) if expected_status }.to avoid_outputting.to_stdout_from_any_process.and avoid_outputting.to_stderr_from_any_process normalize_durations(formatter_output.string) end before do if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version == '9.1.17.0' skip "These specs are currently broken on JRuby 9.1.17.0" end end context "when a load-time problem occurs while running the suite" do it 'surfaces the stdout and stderr output to the user' do output = bisect(%w[spec/rspec/core/resources/fail_on_load_spec.rb_], 1) expect(output).to include("Bisect failed!", "undefined method `contex'", "About to call misspelled method") end end context "when the spec ordering is inconsistent" do it 'stops bisecting and surfaces the problem to the user' do output = bisect(%W[spec/rspec/core/resources/inconsistently_ordered_specs.rb], 1) expect(output).to include("Bisect failed!", "The example ordering is inconsistent") end end context "when the bisect command saturates the pipe" do # On OSX and Linux a file descriptor limit meant that the bisect process got stuck at a certain limit. # This test demonstrates that we can run large bisects above this limit (found to be at time of commit). # See: https://github.com/rspec/rspec-core/pull/2669 it 'does not hit pipe size limit and does not get stuck' do output = bisect(%W[spec/rspec/core/resources/blocking_pipe_bisect_spec.rb_], 1) expect(output).to include("No failures found.") end it 'does not leave zombie processes', :unless => RSpec::Support::OS.windows? do bisect(['--format', 'json', 'spec/rspec/core/resources/blocking_pipe_bisect_spec.rb_'], 1) zombie_process = RSpecChildProcess.new(Process.pid).zombie_process expect(zombie_process).to eq([]), <<-MSG Expected no zombie processes got #{zombie_process.count}: #{zombie_process} MSG end end class RSpecChildProcess Ps = Struct.new(:pid, :ppid, :state, :command) def initialize(pid) @list = child_process_list(pid) end def zombie_process @list.select { |child_process| child_process.state =~ /Z/ } end private def child_process_list(pid) childs_process_list = [] ps_pipe = `ps -o pid=,ppid=,state=,args= | grep #{pid}` ps_pipe.split(/\n/).map do |line| ps_part = line.lstrip.split(/\s+/) next unless ps_part[1].to_i == pid child_process = Ps.new child_process.pid = ps_part[0] child_process.ppid = ps_part[1] child_process.state = ps_part[2] child_process.command = ps_part[3..-1].join(' ') childs_process_list << child_process end childs_process_list end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/fail_if_no_examples_spec.rb0000664000000000000000000000613014557677674027460 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'Fail if no examples' do include_context "aruba support" before { setup_aruba } context 'when 1 passing example' do def passing_example(fail_if_no_examples) " RSpec.configure { |c| c.fail_if_no_examples = #{fail_if_no_examples} } RSpec.describe 'something' do it 'succeeds' do true end end " end it 'succeeds if fail_if_no_examples set to true' do write_file 'spec/example_spec.rb', passing_example(true) run_command "" expect(last_cmd_stdout).to include("1 example, 0 failures") expect(last_cmd_exit_status).to eq(0) end it 'succeeds if fail_if_no_examples set to false' do write_file 'spec/example_spec.rb', passing_example(false) run_command "" expect(last_cmd_stdout).to include("1 example, 0 failures") expect(last_cmd_exit_status).to eq(0) end end context 'when 1 failing example' do def failing_example(fail_if_no_examples) " RSpec.configure { |c| c.fail_if_no_examples = #{fail_if_no_examples} } RSpec.describe 'something' do it 'fails' do fail end end " end it 'fails if fail_if_no_examples set to true' do write_file 'spec/example_spec.rb', failing_example(true) run_command "" expect(last_cmd_stdout).to include("1 example, 1 failure") expect(last_cmd_exit_status).to eq(1) end it 'fails if fail_if_no_examples set to false' do write_file 'spec/example_spec.rb', failing_example(false) run_command "" expect(last_cmd_stdout).to include("1 example, 1 failure") expect(last_cmd_exit_status).to eq(1) end end context 'when 0 examples' do def no_examples(fail_if_no_examples) " RSpec.configure { |c| c.fail_if_no_examples = #{fail_if_no_examples} } RSpec.describe 'something' do end " end it 'fails if fail_if_no_examples set to true' do write_file 'spec/example_spec.rb', no_examples(true) run_command "" expect(last_cmd_stdout).to include("0 examples, 0 failures") expect(last_cmd_exit_status).to eq(1) end it 'succeeds if fail_if_no_examples set to false' do write_file 'spec/example_spec.rb', no_examples(false) run_command "" expect(last_cmd_stdout).to include("0 examples, 0 failures") expect(last_cmd_exit_status).to eq(0) end context 'when custom failure_exit_code set' do def no_examples_custom_failure_exit_code(fail_if_no_examples) " RSpec.configure do |c| c.fail_if_no_examples = #{fail_if_no_examples} c.failure_exit_code = 15 end RSpec.describe 'something' do end " end it 'fails if fail_if_no_examples set to true' do write_file 'spec/example_spec.rb', no_examples_custom_failure_exit_code(true) run_command "" expect(last_cmd_stdout).to include("0 examples, 0 failures") expect(last_cmd_exit_status).to eq(15) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/output_stream_spec.rb0000664000000000000000000000353114557677674026412 0ustar rootrootrequire 'support/aruba_support' RSpec.describe 'Output stream' do include_context 'aruba support' before { setup_aruba } context 'when a formatter set in a configure block' do it 'writes to the right output stream' do write_file_formatted 'spec/example_spec.rb', <<-SPEC RSpec.configure do |c| c.formatter = :documentation c.output_stream = File.open('saved_output', 'w') end RSpec.describe 'something' do it 'succeeds' do true end end SPEC run_command '' expect(last_cmd_stdout).to be_empty cd '.' do expect(File.read('saved_output')).to include('1 example, 0 failures') end end it 'writes to the right output stream even when its a filename' do write_file_formatted 'spec/example_spec.rb', <<-SPEC RSpec.configure do |c| c.formatter = :documentation c.output_stream = 'saved_output' end RSpec.describe 'something' do it 'succeeds' do true end end SPEC run_command '' expect(last_cmd_stdout).to be_empty cd '.' do expect(File.read('saved_output')).to include('1 example, 0 failures') end end it 'writes to the right output stream even when its a filename' do write_file_formatted 'spec/example_spec.rb', <<-SPEC require 'pathname' RSpec.configure do |c| c.formatter = :documentation c.output_stream = Pathname.new('saved_output') end RSpec.describe 'something' do it 'succeeds' do true end end SPEC run_command '' expect(last_cmd_stdout).to be_empty cd '.' do expect(File.read('saved_output')).to include('1 example, 0 failures') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/integration/bisect_runners_spec.rb0000664000000000000000000001022714557677674026524 0ustar rootrootrequire 'support/aruba_support' require 'rspec/core/bisect/shell_command' require 'rspec/core/bisect/shell_runner' require 'rspec/core/bisect/fork_runner' module RSpec::Core RSpec.shared_examples_for "a bisect runner" do include_context "aruba support" before { setup_aruba } let(:shell_command) { Bisect::ShellCommand.new([]) } def with_runner(&block) handle_current_dir_change do cd '.' do options = ConfigurationOptions.new(shell_command.original_cli_args) runner = Runner.new(options) output = StringIO.new runner.configure(output, output) described_class.start(shell_command, runner, &block) end end end it 'runs the specs in an isolated environment and reports the results' do RSpec.configuration.formatter = 'progress' write_file 'spec/a_spec.rb', " formatters = RSpec.configuration.formatter_loader.formatters if formatters.any? { |f| f.is_a?(RSpec::Core::Formatters::ProgressFormatter) } raise 'Leaked progress formatter from host environment' end RSpec.describe 'A group' do it('passes') { expect(1).to eq 1 } it('fails') { expect(1).to eq 2 } end " with_runner do |runner| expect(runner.original_results).to have_attributes( :all_example_ids => %w[ ./spec/a_spec.rb[1:1] ./spec/a_spec.rb[1:2] ], :failed_example_ids => %w[ ./spec/a_spec.rb[1:2] ] ) expect(runner.run(%w[ ./spec/a_spec.rb[1:1] ])).to have_attributes( :all_example_ids => %w[ ./spec/a_spec.rb[1:1] ], :failed_example_ids => %w[] ) end end it 'honors `run_all_when_everything_filtered`' do write_file 'spec/a_spec.rb', " RSpec.configure do |c| c.filter_run :focus c.run_all_when_everything_filtered = true end RSpec.describe 'A group' do it('passes') { expect(1).to eq 1 } it('fails') { expect(1).to eq 2 } end " with_runner do |runner| expect(runner.original_results).to have_attributes( :all_example_ids => %w[ ./spec/a_spec.rb[1:1] ./spec/a_spec.rb[1:2] ], :failed_example_ids => %w[ ./spec/a_spec.rb[1:2] ] ) end end it 'raises BisectFailedError with all run output when it encounters an error loading spec files' do write_file 'spec/a_spec.rb', " puts 'stdout in a_spec' warn 'stderr in a_spec' RSpec.escribe 'A group' do it('passes') { expect(1).to eq 1 } it('fails') { expect(1).to eq 2 } end " rspec_description = if RUBY_VERSION.to_f > 3.2 "module RSpec" else "RSpec:Module" end with_runner do |runner| expect { runner.original_results }.to raise_error(Bisect::BisectFailedError, a_string_including( "undefined method `escribe' for #{rspec_description}", 'stdout in a_spec', 'stderr in a_spec' )) end end end RSpec.describe Bisect::ShellRunner, :slow do include_examples 'a bisect runner' end RSpec.describe Bisect::ForkRunner, :if => RSpec::Support::RubyFeatures.fork_supported? do include_examples 'a bisect runner' context 'when a `--require` option has been provided' do let(:shell_command) { Bisect::ShellCommand.new(['--require', './spec/a_spec_helper']) } it 'loads the specified file only once (rather than once per subset run)' do write_file 'spec_helper_loads', '' write_file 'spec/a_spec_helper.rb', " File.open('spec_helper_loads', 'a') do |f| f.print('.') end " write_file 'spec/a_spec.rb', " RSpec.describe 'A group' do it('passes') { expect(1).to eq 1 } it('fails') { expect(1).to eq 2 } end " with_runner do |runner| runner.run(%w[ ./spec/a_spec.rb[1:1] ]) runner.run(%w[ ./spec/a_spec.rb[1:1] ]) end cd '.' do expect(File.read('spec_helper_loads')).to eq(".") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/spec/spec_helper.rb0000664000000000000000000000617414557677674022441 0ustar rootrootrequire 'rubygems' if RUBY_VERSION.to_f < 1.9 require 'rspec/support/spec' $rspec_core_without_stderr_monkey_patch = RSpec::Core::Configuration.new class RSpec::Core::Configuration def self.new(*args, &block) super.tap do |config| # We detect ruby warnings via $stderr, # so direct our deprecations to $stdout instead. config.deprecation_stream = $stdout end end end Dir['./spec/support/**/*.rb'].map do |file| # fake libs aren't intended to be loaded except by some specific specs # that shell out and run a new process. next if file =~ /fake_libs/ # Ensure requires are relative to `spec`, which is on the # load path. This helps prevent double requires on 1.8.7. require file.gsub("./spec/support", "support") end class RaiseOnFailuresReporter < RSpec::Core::NullReporter def self.example_failed(example) raise example.exception end end module CommonHelpers def describe_successfully(*args, &describe_body) example_group = RSpec.describe(*args, &describe_body) ran_successfully = example_group.run RaiseOnFailuresReporter expect(ran_successfully).to eq true example_group end def with_env_vars(vars) original = ENV.to_hash vars.each { |k, v| ENV[k] = v } begin yield ensure ENV.replace(original) end end def without_env_vars(*vars) original = ENV.to_hash vars.each { |k| ENV.delete(k) } begin yield ensure ENV.replace(original) end end def handle_current_dir_change RSpec::Core::Metadata.instance_variable_set(:@relative_path_regex, nil) yield ensure RSpec::Core::Metadata.instance_variable_set(:@relative_path_regex, nil) end end RSpec.configure do |c| c.pending_failure_output = :no_backtrace c.example_status_persistence_file_path = "./spec/examples.txt" c.around(:example, :isolated_directory) do |ex| handle_current_dir_change(&ex) end # structural c.alias_it_behaves_like_to 'it_has_behavior' c.include(RSpecHelpers) c.disable_monkey_patching! # runtime options c.raise_errors_for_deprecations! c.color = true c.include CommonHelpers c.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true expectations.max_formatted_output_length = 1000 end c.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end c.around(:example, :simulate_shell_allowing_unquoted_ids) do |ex| with_env_vars('SHELL' => '/usr/local/bin/bash', &ex) end if ENV['CI'] && RSpec::Support::OS.windows? && RUBY_VERSION.to_f < 2.3 c.around(:example, :emits_warning_on_windows_on_old_ruby) do |ex| ignoring_warnings(&ex) end c.define_derived_metadata(:pending_on_windows_old_ruby => true) do |metadata| metadata[:pending] = "This example is expected to fail on windows, on ruby older than 2.3" end end c.filter_run_excluding :ruby => lambda {|version| case version.to_s when "!jruby" RUBY_ENGINE == "jruby" when /^> (.*)/ !(RUBY_VERSION.to_s > $1) else !(RUBY_VERSION.to_s =~ /^#{version.to_s}/) end } $original_rspec_configuration = c end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/cucumber.yml0000664000000000000000000000072514557677674021215 0ustar rootroot<% USE_TILDE_TAGS = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') NOT_WIP_TAG = USE_TILDE_TAGS ? '~@wip' : '"not @wip"' NOT_JRUBY_TAG = USE_TILDE_TAGS ? '~@no-jruby' : '"not @no-jruby"' exclusions = [] exclusions << " --tags #{NOT_JRUBY_TAG}" if RUBY_PLATFORM == 'java' %> default: --require features --strict --format progress --tags <%= NOT_WIP_TAG %><%= exclusions.join %> features wip: --require features --tags @wip:30 --wip features ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.github/0000775000000000000000000000000014557677674020221 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.github/workflows/0000775000000000000000000000000014557677674022256 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.github/workflows/ci.yml0000664000000000000000000001143014557677674023373 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. name: RSpec CI on: push: branches: - 'main' - '*-maintenance' - '*-dev' pull_request: branches: - '*' permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: RSPEC_CI: true # This tells rspec-rails what branch to run in ci RSPEC_VERSION: '~> 3.13.0' jobs: rubocop: name: Rubocop runs-on: 'ubuntu-20.04' steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.0' - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_rubocop test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} runs-on: ${{ matrix.os || 'ubuntu-20.04' }} strategy: matrix: ruby: - '3.3' - '3.2' - '3.1' - '3.0' - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 env: - DIFF_LCS_VERSION: "> 1.4.3" include: - ruby: ruby-head env: RUBY_HEAD: true - ruby: jruby-9.2.13.0 env: JRUBY_OPTS: "--dev" - ruby: 2.7 name_extra: "with diff-lcs 1.3" env: DIFF_LCS_VERSION: "~> 1.3.0" - ruby: 2.7 name_extra: "with diff-lcs 1.4.3" env: DIFF_LCS_VERSION: "1.4.3" fail-fast: false continue-on-error: ${{ matrix.allow_failure || endsWith(matrix.ruby, 'head') }} env: ${{ matrix.env }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: ${{ matrix.bundler || '2.2.22' }} ruby-version: ${{ matrix.ruby }} - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_build legacy: name: Legacy Ruby Builds (${{ matrix.container.version }}) runs-on: ubuntu-20.04 container: image: ${{ matrix.container.tag }} options: ${{ matrix.container.options || '--add-host github-complains-if-this-is-empty.com:127.0.0.1' }} strategy: fail-fast: false matrix: container: - version: "2.1.9" tag: ghcr.io/rspec/docker-ci:2.1.9 post: git config --global --add safe.directory `pwd` - version: "2.0" tag: ghcr.io/rspec/docker-ci:2.0.0 - version: "1.9.3" tag: ghcr.io/rspec/docker-ci:1.9.3 - version: "1.9.2" tag: ghcr.io/rspec/docker-ci:1.9.2 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "1.8.7" tag: ghcr.io/rspec/docker-ci:1.8.7 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "REE" tag: ghcr.io/rspec/docker-ci:ree options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 1.7" tag: ghcr.io/rspec/docker-ci:jruby-1.7 - version: "JRuby 1.7 1.8 mode" tag: ghcr.io/rspec/docker-ci:jruby-1.7 jruby_opts: '--dev --1.8' pre: gem uninstall jruby-openssl options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 9.1.17.0" tag: ghcr.io/rspec/docker-ci:jruby-9.1.17.0 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" env: LEGACY_CI: true JRUBY_OPTS: ${{ matrix.container.jruby_opts || '--dev' }} steps: - uses: actions/checkout@v3 - run: ${{ matrix.container.pre }} - run: script/legacy_setup.sh - run: ${{ matrix.container.post }} - run: bundle exec bin/rspec - run: bundle exec script/cucumber.sh windows: name: Ruby ${{ matrix.ruby }} (Windows) runs-on: windows-latest strategy: matrix: ruby: - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 fail-fast: false steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: '2.2.22' ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: choco install ansicon - run: bundle exec rspec --backtrace ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.github/dependabot.yml0000664000000000000000000000043714557677674023055 0ustar rootroot# This file was generated on 2023-12-25T16:05:21+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. version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.github/FUNDING.yml0000664000000000000000000000033514557677674022037 0ustar rootroot# This file was generated on 2023-04-16T20:53:21+01: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, benoittgt] open_collective: rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/DEV-README.md0000664000000000000000000000125414557677674020556 0ustar rootroot## Set up the dev environment git clone https://github.com/rspec/rspec-core.git cd rspec-core gem install bundler bundle install Now you should be able to run any of: rake rake spec rake cucumber Or, if you prefer to use the rspec and cucumber commands directly, you can either: bundle exec rspec Or ... bundle install --binstubs bin/rspec ## Customize the dev environment The Gemfile includes the gems you'll need to be able to run specs. If you want to customize your dev environment with additional tools like guard or ruby-debug, add any additional gem declarations to Gemfile-custom (see Gemfile-custom.sample for some examples). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/CONTRIBUTING.md0000664000000000000000000001031714557677674021114 0ustar rootroot # Contributing RSpec is a community-driven project that has benefited from improvements from over *500* contributors. We welcome contributions from *everyone*. While contributing, please follow the project [code of conduct](CODE_OF_CONDUCT.md), so that everyone can be included. If you'd like to help make RSpec better, here are some ways you can contribute: - by running RSpec HEAD to help us catch bugs before new releases - by [reporting bugs you encounter](https://github.com/rspec/rspec-core/issues/new) with [report template](#report-template) - by [suggesting new features](https://github.com/rspec/rspec-core/issues/new) - by improving RSpec's Feature or API [documentation](https://rspec.info/documentation/) - by improving [RSpec's website](https://rspec.info/) ([source](https://github.com/rspec/rspec.github.io)) - by taking part in [feature and issue discussions](https://github.com/rspec/rspec-core/issues) - by adding a failing test for reproducible [reported bugs](https://github.com/rspec/rspec-core/issues) - by reviewing [pull requests](https://github.com/rspec/rspec-core/pulls) and suggesting improvements - by [writing code](DEVELOPMENT.md) (no patch is too small! fix typos or bad whitespace) If you need help getting started, check out the [DEVELOPMENT](DEVELOPMENT.md) file for steps that will get you up and running. Thanks for helping us make RSpec better! ## `Small` issues These issue are ones that we be believe are best suited for new contributors to get started with. They represent a meaningful contribution to the project that should not be too hard to pull off. ## Report template Having a way to reproduce your issue will be very helpful for others to help confirm, investigate and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared one basic [bug report templates](REPORT_TEMPLATE.md) for you to use as a starting point. ## Maintenance branches Maintenance branches are how we manage the different supported point releases of RSpec. As such, while they might look like good candidates to merge into main, please do not open pull requests to merge them. ## Working on multiple RSpec gems at the same time RSpec is composed of multiple gems (`rspec-core`, `rspec-mocks`, etc). Sometimes you have to work on a combination of them at the same time. When submitting your code for review, we ask that you get a passing build (green CI). If you are working across the repositories, please add a commit that temporarily pins your PR to the right branch of the other repository you depend on. For example, if we wanted a change in `rspec-expectations` that relied on a change for on `rspec-mocks`. We add a commit with the title: >[WIP] Use rspec-mocks with "custom-failure-message" branch And content: ```diff diff --git a/Gemfile b/Gemfile -%w[rspec rspec-core rspec-mocks rspec-support].each do |lib| +%w[rspec rspec-core rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path @@ -11,6 +11,7 @@ branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end +gem 'rspec-mocks', :git => "https://github.com/rspec/rspec-mocks.git", :branch => "custom-failure-message" ``` In general the process is: 1. Create PRs explaining what you are trying to achieve. 2. Pin the repositories to each other. 3. Check they pass (go green). 4. Await review if appropriate. 5. Remove the commit from step 2. We will merge ignoring the failure. 6. Remove the commit from the other, check it passes with the other commit now on `main`. 7. Merge the other. 8. We will trigger builds for the `main` branch of affected repositories to check if everything is in order. Steps 5-8 should happen continuously (e.g. one after another but within a short timespan) so that we don't leave a broken main around. It is important to triage that build process and revert if necessary. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/BUILD_DETAIL.md0000664000000000000000000001244014557677674021065 0ustar rootroot # The CI build, in detail The [Travis CI build](https://travis-ci.org/rspec/rspec-core) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` It can be useful to run the build steps individually to repro a failing part of a Travis build. Let's break the build down into the individual steps. ## Specs RSpec dogfoods itself. Its primary defense against regressions is its spec suite. Run with: ``` $ bundle exec rspec # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rspec ``` The spec suite performs a couple extra checks that are worth noting: * *That all the code is warning-free.* Any individual example that produces output to `stderr` will fail. We also have a spec that loads all the `lib` and `spec` files in a newly spawned process to detect load-time warnings and fail if there are any. RSpec must be warning-free so that users who enable Ruby warnings will not get warnings from our code. * *That only a minimal set of stdlibs are loaded.* Since Ruby makes loaded libraries available for use in any context, we want to minimize how many bits of the standard library we load and use. Otherwise, RSpec's use of part of the standard library could mask a problem where a gem author forgets to load a part of the standard library they rely on. The spec suite contains a spec that defines a list of allowed loaded stdlibs. In addition, we use [SimpleCov](https://github.com/colszowka/simplecov) to measure and enforce test coverage. If the coverage falls below a project-specific threshold, the build will fail. ## Cukes RSpec uses [cucumber](https://cucumber.io/) for both acceptance testing and [documentation](https://rspec.info/documentation). Since we publish our cukes as documentation, please limit new cucumber scenarios to user-facing examples that help demonstrate usage. Any tests that exist purely to prevent regressions should be written as specs, even if they are written in an acceptance style. Duplication between our YARD API docs and the cucumber documentation is fine. Run with: ``` $ bundle exec cucumber # or, if you installed your bundle with `--standalone --binstubs`: $ bin/cucumber ``` ## YARD documentation RSpec uses [YARD](https://yardoc.org/) for API documentation on the [rspec.info site](https://rspec.info/). Our commitment to [SemVer](https://semver.org) requires that we explicitly declare our public API, and our build uses YARD to ensure that every class, module and method has either been labeled `@private` or has at least some level of documentation. For new APIs, this forces us to make an intentional decision about whether or not it should be part of RSpec's public API or not. To run the YARD documentation coverage check, run: ``` $ bundle exec yard stats --list-undoc # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard stats --list-undoc ``` We also want to prevent YARD errors or warnings when actually generating the docs. To check for those, run: ``` $ bundle exec yard doc --no-cache # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard doc --no-cache ``` ## RuboCop We use [RuboCop](https://github.com/rubocop-hq/rubocop) to enforce style conventions on the project so that the code has stylistic consistency throughout. Run with: ``` $ bundle exec rubocop lib # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rubocop lib ``` Our RuboCop configuration is a work-in-progress, so if you get a failure due to a RuboCop default, feel free to ask about changing the configuration. Otherwise, you'll need to address the RuboCop failure, or, as a measure of last resort, by wrapping the offending code in comments like `# rubocop:disable SomeCheck` and `# rubocop:enable SomeCheck`. ## Run spec files one-by-one A fast TDD cycle depends upon being able to run a single spec file, without the rest of the test suite. While rare, it's fairly easy to create a situation where a spec passes when the entire suite runs but fails when its individual file is run. To guard against this, our CI build runs each spec file individually, using a bit of bash like: ``` for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done ``` Since this step boots RSpec so many times, it runs much, much faster when we can avoid the overhead of bundler. This is a main reason our CI build installs the bundle with `--standalone --binstubs` and runs RSpec via `bin/rspec` rather than `bundle exec rspec`. ## Running the spec suite for each of the other repos While each of the RSpec repos is an independent gem (generally designed to be usable on its own), there are interdependencies between the gems, and the specs for each tend to use features from the other gems. We don't want to merge a pull request for one repo that might break the build for another repo, so our CI build includes a spec that runs the spec suite of each of the _other_ project repos. Note that we only run the spec suite, not the full build, of the other projects, as the spec suite runs very quickly compared to the full build. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Filtering.md0000664000000000000000000001344114557677674021131 0ustar rootroot# Filtering RSpec supports filtering examples and example groups in multiple ways, allowing you to run a targeted subset of your suite that you are currently interested in. ## Filtering by Tag Examples and groups can be filtered by matching tags declared on the command line or options files, or filters declared via `RSpec.configure`, with hash key/values submitted within example group and/or example declarations. For example, given this declaration: ``` ruby RSpec.describe Thing, :awesome => true do it "does something" do # ... end end ``` That group (or any other with `:awesome => true`) would be filtered in with any of the following commands: rspec --tag awesome:true rspec --tag awesome rspec -t awesome:true rspec -t awesome Prefixing the tag names with `~` negates the tags, thus excluding this group with any of: rspec --tag ~awesome:true rspec --tag ~awesome rspec -t ~awesome:true rspec -t ~awesome ## Filtering by Example description RSpec provides the `--example` (short form: `-e`) option to allow you to select examples or groups by their description. All loaded examples whose full description (computed based on the description of the example plus that of all ancestor groups) contains the provided argument will be executed. rspec --example "Homepage when logged in" rspec -e "Homepage when logged in" You can specify this option multiple times to select multiple sets of examples: rspec -e "Homepage when logged in" -e "User" Note that RSpec will load all spec files in these situations, which can incur considerable start-up costs (particularly for Rails apps). If you know that the examples you are targeting are in particular files, you can also pass the file or directory name so that RSpec loads only those spec files, speeding things up: rspec spec/homepage_spec.rb -e "Homepage when logged in" rspec -e "Homepage when logged in" spec/homepage_spec.rb Note also that description-less examples that have generated descriptions (typical when using the one-liner syntax) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group's description to select all examples defined in the group (including those that have no description). ## Filtering by Example Location Examples and groups can be selected from the command line by passing the file and line number where they are defined, separated by a colon: rspec spec/homepage_spec.rb:14 spec/widgets_spec.rb:40 spec/users_spec.rb This command would run the example or group defined on line 14 of `spec/homepage_spec.rb`, the example or group defined on line 40 of `spec/widgets_spec.rb`, and all examples and groups defined in `spec/users_spec.rb`. If there is no example or group defined at the specified line, RSpec will run the last example or group defined before the line. ## Focusing RSpec supports configuration options that make it easy to select examples by temporarily tweaking them. In your `spec_helper.rb` (or a similar file), put this configuration: ``` ruby RSpec.configure do |config| config.filter_run_when_matching :focus end ``` This configuration is generated for you by `rspec --init` in the commented-out section of recommendations. With that in place, you can tag any example group or example with `:focus` metadata to select it: ``` ruby it "does something" do # becomes... it "does something", :focus do ``` RSpec also ships with aliases of the common example group definition methods (`describe`, `context`) and example methods (`it`, `specify`, `example`) with an `f` prefix that automatically includes `:focus => true` metadata, allowing you to easily change `it` to `fit` (think "focused it"), `describe` to `fdescribe`, etc in order to temporarily focus them. ## Options files and command line overrides Command line option declarations can be stored in `.rspec`, `~/.rspec`, `$XDG_CONFIG_HOME/rspec/options` or a custom options file. This is useful for storing defaults. For example, let's say you've got some slow specs that you want to suppress most of the time. You can tag them like this: ``` ruby RSpec.describe Something, :slow => true do ``` And then store this in `.rspec`: --tag ~slow:true Now when you run `rspec`, that group will be excluded. ## Overriding Of course, you probably want to run them sometimes, so you can override this tag on the command line like this: rspec --tag slow:true ## Precedence Location and description filters have priority over tag filters since they express a desire by the user to run specific examples. Thus, you could specify a location or description at the command line to run an example or example group that would normally be excluded due to a `:slow` tag if you were using the above configuration. ## RSpec.configure You can also store default tags with `RSpec.configure`. We use `tag` on the command line (and in options files like `.rspec`), but for historical reasons we use the term `filter` in `RSpec.configure`: ``` ruby RSpec.configure do |c| c.filter_run_including :foo => :bar c.filter_run_excluding :foo => :bar end ``` These declarations can also be overridden from the command line. ## Silencing filter announcements By default, RSpec will print a message before your specs run indicating what filters are configured, for instance, it might print "Run options: include {:focus=>true}" if you set `config.filter_run_including :focus => true`. If you wish to prevent those messages from appearing in your spec output, you can set the `silence_filter_announcements` config setting to `true` like this: ``` ruby RSpec.configure do |c| c.filter_run_including :foo => :bar c.silence_filter_announcements = true end ``` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/Guardfile0000664000000000000000000000026114557677674020505 0ustar rootrootguard 'rspec', :version => 2 do watch(/^spec\/(.*)_spec.rb/) watch(/^lib\/(.*)\.rb/) { |m| "spec/#{m[1]}_spec.rb" } watch(/^spec\/spec_helper.rb/) { "spec" } end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/0000775000000000000000000000000014557677674020477 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/clear_examples.feature0000664000000000000000000000532714557677674025047 0ustar rootrootFeature: Running specs multiple times with different runner options in the same process Use `clear_examples` command to clear all example groups between different runs in the same process. It: - clears all example groups - restores inclusion and exclusion filters set by configuration - clears inclusion and exclusion filters set by previous spec run (via runner) - resets all time counters (start time, load time, duration, etc.) - resets different counts of examples (all examples, pending and failed) ```ruby require "spec_helper" RSpec::Core::Runner.run([... some parameters ...]) RSpec.clear_examples RSpec::Core::Runner.run([... different parameters ...]) ``` Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.filter_run_when_matching :focus => true config.filter_run_excluding :slow => true end """ Given a file named "spec/truth_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "truth" do describe true do it "is truthy" do expect(true).to be_truthy end it "is not falsy" do expect(true).not_to be_falsy end end describe false do it "is falsy" do expect(false).to be_falsy end it "is truthy" do expect(false).not_to be_truthy end end end """ Scenario: Running specs multiple times in the same process Given a file named "scripts/multiple_runs.rb" with: """ruby require 'rspec/core' RSpec::Core::Runner.run(['spec']) RSpec.clear_examples RSpec::Core::Runner.run(['spec']) """ When I run `ruby scripts/multiple_runs.rb` Then the output should match: """ 4 examples, 0 failures .* 4 examples, 0 failures """ Scenario: Running specs multiple times in the same process with different parameters Given a file named "spec/bar_spec.rb" with: """ruby require 'spec_helper' RSpec.describe 'bar' do subject(:bar) { :focused } it 'is focused', :focus do expect(bar).to be(:focused) end end """ Given a file named "scripts/different_parameters.rb" with: """ruby require 'rspec/core' RSpec::Core::Runner.run(['spec']) RSpec.clear_examples RSpec::Core::Runner.run(['spec/truth_spec.rb:4']) RSpec.clear_examples RSpec::Core::Runner.run(['spec', '-e', 'fals']) """ When I run `ruby scripts/different_parameters.rb` Then the output should match: """ 1 example, 0 failures .* 2 examples, 0 failures .* 3 examples, 0 failures """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/filtering/0000775000000000000000000000000014557677674022462 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/filtering/filter_run_when_matching.feature0000664000000000000000000000444314557677674031110 0ustar rootrootFeature: Using `filter_run_when_matching` You can configure a _conditional_ filter that only applies if there are any matching examples using `config.filter_run_when_matching`. This is commonly used for focus filtering: ```ruby RSpec.configure do |c| c.filter_run_when_matching :focus end ``` This configuration allows you to filter to specific examples or groups by tagging them with `:focus` metadata. When no example or groups are focused (which should be the norm since it's intended to be a temporary change), the filter will be ignored. RSpec also provides aliases--`fit`, `fdescribe` and `fcontext`--as a shorthand for `it`, `describe` and `context` with `:focus` metadata, making it easy to temporarily focus an example or group by prefixing an `f`. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |c| c.filter_run_when_matching :focus end """ And a file named ".rspec" with: """ --require spec_helper """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "A group" do it "has a passing example" do end context "a nested group" do it "also has a passing example" do end end end """ Scenario: The filter is ignored when nothing is focused When I run `rspec --format doc` Then it should pass with "2 examples, 0 failures" And the output should contain: """ A group has a passing example a nested group also has a passing example """ Scenario: Examples can be focused with `fit` Given I have changed `it "has a passing example"` to `fit "has a passing example"` in "spec/example_spec.rb" When I run `rspec --format doc` Then it should pass with "1 example, 0 failures" And the output should contain: """ A group has a passing example """ Scenario: Groups can be focused with `fdescribe` or `fcontext` Given I have changed `context` to `fcontext` in "spec/example_spec.rb" When I run `rspec --format doc` Then it should pass with "1 example, 0 failures" And the output should contain: """ A group a nested group also has a passing example """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/filtering/inclusion_filters.feature0000664000000000000000000000603214557677674027573 0ustar rootrootFeature: Inclusion filters You can constrain which examples are run by declaring an inclusion filter. The most common use case is to focus on a subset of examples as you're focused on a particular problem. You can also specify metadata using only symbols. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |c| c.filter_run_including :focus => true end """ Scenario: Focus on an example Given a file named "spec/sample_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "does one thing" do end it "does another thing", :focus => true do end end """ When I run `rspec spec/sample_spec.rb --format doc` Then the output should contain "does another thing" And the output should not contain "does one thing" Scenario: Focus on a group Given a file named "spec/sample_spec.rb" with: """ruby require "spec_helper" RSpec.describe "group 1", :focus => true do it "group 1 example 1" do end it "group 1 example 2" do end end RSpec.describe "group 2" do it "group 2 example 1" do end end """ When I run `rspec spec/sample_spec.rb --format doc` Then the output should contain "group 1 example 1" And the output should contain "group 1 example 2" And the output should not contain "group 2 example 1" Scenario: `before`/`after(:context)` hooks in unmatched example group are not run Given a file named "spec/before_after_all_inclusion_filter_spec.rb" with: """ruby require "spec_helper" RSpec.describe "group 1", :focus => true do before(:context) { puts "before all in focused group" } after(:context) { puts "after all in focused group" } it "group 1 example" do end end RSpec.describe "group 2" do before(:context) { puts "before all in unfocused group" } after(:context) { puts "after all in unfocused group" } context "context 1" do it "group 2 context 1 example 1" do end end end """ When I run `rspec ./spec/before_after_all_inclusion_filter_spec.rb` Then the output should contain "before all in focused group" And the output should contain "after all in focused group" And the output should not contain "before all in unfocused group" And the output should not contain "after all in unfocused group" Scenario: Use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run :current_example end RSpec.describe "something" do it "does one thing" do end it "does another thing", :current_example do end end """ When I run `rspec symbols_as_metadata_spec.rb --format doc` Then the output should contain "does another thing" And the output should not contain "does one thing" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/filtering/if_and_unless.feature0000664000000000000000000001553514557677674026661 0ustar rootrootFeature: Conditional Filters The `:if` and `:unless` metadata keys can be used to filter examples without needing to configure an exclusion filter. Scenario: Implicit `:if` filter Given a file named "implicit_if_filter_spec.rb" with: """ruby RSpec.describe ":if => true group", :if => true do it(":if => true group :if => true example", :if => true) { } it(":if => true group :if => false example", :if => false) { } it(":if => true group no :if example") { } end RSpec.describe ":if => false group", :if => false do it(":if => false group :if => true example", :if => true) { } it(":if => false group :if => false example", :if => false) { } it(":if => false group no :if example") { } end RSpec.describe "no :if group" do it("no :if group :if => true example", :if => true) { } it("no :if group :if => false example", :if => false) { } it("no :if group no :if example") { } end """ When I run `rspec implicit_if_filter_spec.rb --format doc` Then the output should contain all of these: | :if => true group :if => true example | | :if => true group no :if example | | :if => false group :if => true example | | no :if group :if => true example | | no :if group no :if example | And the output should not contain any of these: | :if => true group :if => false example | | :if => false group :if => false example | | :if => false group no :if example | | no :if group :if => false example | Scenario: Implicit `:unless` filter Given a file named "implicit_unless_filter_spec.rb" with: """ruby RSpec.describe ":unless => true group", :unless => true do it(":unless => true group :unless => true example", :unless => true) { } it(":unless => true group :unless => false example", :unless => false) { } it(":unless => true group no :unless example") { } end RSpec.describe ":unless => false group", :unless => false do it(":unless => false group :unless => true example", :unless => true) { } it(":unless => false group :unless => false example", :unless => false) { } it(":unless => false group no :unless example") { } end RSpec.describe "no :unless group" do it("no :unless group :unless => true example", :unless => true) { } it("no :unless group :unless => false example", :unless => false) { } it("no :unless group no :unless example") { } end """ When I run `rspec implicit_unless_filter_spec.rb --format doc` Then the output should contain all of these: | :unless => true group :unless => false example | | :unless => false group :unless => false example | | :unless => false group no :unless example | | no :unless group :unless => false example | | no :unless group no :unless example | And the output should not contain any of these: | :unless => true group :unless => true example | | :unless => true group no :unless example | | :unless => false group :unless => true example | | no :unless group :unless => true example | Scenario: Combining implicit filter with explicit inclusion filter Given a file named "explicit_inclusion_filter_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run :focus => true end RSpec.describe "group with :focus", :focus => true do it("focused example") { } it("focused :if => true example", :if => true) { } it("focused :if => false example", :if => false) { } it("focused :unless => true example", :unless => true) { } it("focused :unless => false example", :unless => false) { } end RSpec.describe "group without :focus" do it("unfocused example") { } it("unfocused :if => true example", :if => true) { } it("unfocused :if => false example", :if => false) { } it("unfocused :unless => true example", :unless => true) { } it("unfocused :unless => false example", :unless => false) { } end """ When I run `rspec explicit_inclusion_filter_spec.rb --format doc` Then the output should contain all of these: | focused example | | focused :if => true example | | focused :unless => false example | And the output should not contain any of these: | focused :if => false example | | focused :unless => true example | | unfocused | Scenario: Combining implicit filter with explicit exclusion filter Given a file named "explicit_exclusion_filter_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end RSpec.describe "unbroken group" do it("included example") { } it("included :if => true example", :if => true) { } it("included :if => false example", :if => false) { } it("included :unless => true example", :unless => true) { } it("included :unless => false example", :unless => false) { } end RSpec.describe "broken group", :broken => true do it("excluded example") { } it("excluded :if => true example", :if => true) { } it("excluded :if => false example", :if => false) { } it("excluded :unless => true example", :unless => true) { } it("excluded :unless => false example", :unless => false) { } end """ When I run `rspec explicit_exclusion_filter_spec.rb --format doc` Then the output should contain all of these: | included example | | included :if => true example | | included :unless => false example | And the output should not contain any of these: | included :if => false example | | included :unless => true example | | excluded | Scenario: The :if and :unless exclusions stay in effect when there are explicit inclusions Given a file named "if_and_unless_spec.rb" with: """ruby RSpec.describe "Using inclusions" do context "inclusion target" do it "is filtered out by :if", :if => false do end it 'is filtered out by :unless', :unless => true do end it 'is still run according to :if', :if => true do end it 'is still run according to :unless', :unless => false do end end end """ When I run `rspec if_and_unless_spec.rb --format doc -e 'inclusion target'` Then the output should contain all of these: | is still run according to :if | | is still run according to :unless | And the output should not contain any of these: | is filtered out by :if | | is filtered out by :unless | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/filtering/exclusion_filters.feature0000664000000000000000000000776614557677674027620 0ustar rootrootFeature: Exclusion filters You can exclude examples from a run by declaring an exclusion filter and then tagging examples, or entire groups, with that filter. You can also specify metadata using only symbols. Scenario: Exclude an example Given a file named "spec/sample_spec.rb" with: """ruby RSpec.configure do |c| # declare an exclusion filter c.filter_run_excluding :broken => true end RSpec.describe "something" do it "does one thing" do end # tag example for exclusion by adding metadata it "does another thing", :broken => true do end end """ When I run `rspec ./spec/sample_spec.rb --format doc` Then the output should contain "does one thing" And the output should not contain "does another thing" Scenario: Exclude a group Given a file named "spec/sample_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end RSpec.describe "group 1", :broken => true do it "group 1 example 1" do end it "group 1 example 2" do end end RSpec.describe "group 2" do it "group 2 example 1" do end end """ When I run `rspec ./spec/sample_spec.rb --format doc` Then the output should contain "group 2 example 1" And the output should not contain "group 1 example 1" And the output should not contain "group 1 example 2" Scenario: Exclude multiple groups Given a file named "spec/sample_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end RSpec.describe "group 1", :broken => true do before(:context) do raise "you should not see me" end it "group 1 example 1" do end it "group 1 example 2" do end end RSpec.describe "group 2", :broken => true do before(:example) do raise "you should not see me" end it "group 2 example 1" do end end """ When I run `rspec ./spec/sample_spec.rb --format doc` Then the process should succeed even though no examples were run And the output should not contain "group 1" And the output should not contain "group 2" Scenario: `before`/`after(:context)` hooks in excluded example group are not run Given a file named "spec/before_after_context_exclusion_filter_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end RSpec.describe "group 1" do before(:context) { puts "before context in included group" } after(:context) { puts "after context in included group" } it "group 1 example" do end end RSpec.describe "group 2", :broken => true do before(:context) { puts "before context in excluded group" } after(:context) { puts "after context in excluded group" } context "context 1" do it "group 2 context 1 example 1" do end end end """ When I run `rspec ./spec/before_after_context_exclusion_filter_spec.rb` Then the output should contain "before context in included group" And the output should contain "after context in included group" And the output should not contain "before context in excluded group" And the output should not contain "after context in excluded group" Scenario: Use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: """ruby RSpec.configure do |c| c.filter_run_excluding :broken end RSpec.describe "something" do it "does one thing" do end # tag example for exclusion by adding metadata it "does another thing", :broken do end end """ When I run `rspec symbols_as_metadata_spec.rb --format doc` Then the output should contain "does one thing" And the output should not contain "does another thing" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/0000775000000000000000000000000014557677674026362 5ustar rootroot././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/pending_examples.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/pending_examples.fea0000664000000000000000000000564114557677674032367 0ustar rootrootFeature: Using `pending` with examples RSpec offers a number of different ways to indicate that an example is disabled pending some action. Scenario: `pending` any arbitrary reason with a failing example Given a file named "pending_without_block_spec.rb" with: """ruby RSpec.describe "an example" do it "is implemented but waiting" do pending("something else getting finished") fail end end """ When I run `rspec pending_without_block_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is implemented but waiting # something else getting finished """ Scenario: `pending` any arbitrary reason with a passing example Given a file named "pending_with_passing_example_spec.rb" with: """ruby RSpec.describe "an example" do it "is implemented but waiting" do pending("something else getting finished") expect(1).to be(1) end end """ When I run `rspec pending_with_passing_example_spec.rb` Then the exit status should not be 0 And the output should contain "1 example, 1 failure" And the output should contain "FIXED" And the output should contain "Expected pending 'something else getting finished' to fail. No error was raised." And the output should contain "pending_with_passing_example_spec.rb:2" Scenario: `pending` for an example that is currently passing Given a file named "pending_with_passing_block_spec.rb" with: """ruby RSpec.describe "an example" do pending("something else getting finished") do expect(1).to eq(1) end end """ When I run `rspec pending_with_passing_block_spec.rb` Then the exit status should not be 0 And the output should contain "1 example, 1 failure" And the output should contain "FIXED" And the output should contain "Expected pending 'No reason given' to fail. No error was raised." And the output should contain "pending_with_passing_block_spec.rb:2" Scenario: `pending` for an example that is currently passing with a reason Given a file named "pending_with_passing_block_spec.rb" with: """ruby RSpec.describe "an example" do example("something else getting finished", :pending => 'unimplemented') do expect(1).to eq(1) end end """ When I run `rspec pending_with_passing_block_spec.rb` Then the exit status should not be 0 And the output should contain "1 example, 1 failure" And the output should contain "FIXED" And the output should contain "Expected pending 'unimplemented' to fail. No error was raised." And the output should contain "pending_with_passing_block_spec.rb:2" ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/skipped_examples.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/skipped_examples.fea0000664000000000000000000001023214557677674032372 0ustar rootrootFeature: Using `skip` with examples RSpec offers a number of ways to indicate that an example should be skipped and not executed. Scenario: No implementation provided Given a file named "example_without_block_spec.rb" with: """ruby RSpec.describe "an example" do it "is a skipped example" end """ When I run `rspec example_without_block_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain "Not yet implemented" And the output should contain "example_without_block_spec.rb:2" Scenario: Skipping using `skip` Given a file named "skipped_spec.rb" with: """ruby RSpec.describe "an example" do skip "is skipped" do end end """ When I run `rspec skipped_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is skipped # No reason given # ./skipped_spec.rb:2 """ Scenario: Skipping using `skip` inside an example Given a file named "skipped_spec.rb" with: """ruby RSpec.describe "an example" do it "is skipped" do skip end end """ When I run `rspec skipped_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is skipped # No reason given # ./skipped_spec.rb:2 """ Scenario: Temporarily skipping by prefixing `it`, `specify`, or `example` with an x Given a file named "temporarily_skipped_spec.rb" with: """ruby RSpec.describe "an example" do xit "is skipped using xit" do end xspecify "is skipped using xspecify" do end xexample "is skipped using xexample" do end end """ When I run `rspec temporarily_skipped_spec.rb` Then the exit status should be 0 And the output should contain "3 examples, 0 failures, 3 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is skipped using xit # Temporarily skipped with xit # ./temporarily_skipped_spec.rb:2 2) an example is skipped using xspecify # Temporarily skipped with xspecify # ./temporarily_skipped_spec.rb:5 3) an example is skipped using xexample # Temporarily skipped with xexample # ./temporarily_skipped_spec.rb:8 """ Scenario: Skipping using metadata Given a file named "skipped_spec.rb" with: """ruby RSpec.describe "an example" do example "is skipped", :skip => true do end end """ When I run `rspec skipped_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is skipped # No reason given # ./skipped_spec.rb:2 """ Scenario: Skipping using metadata with a reason Given a file named "skipped_with_reason_spec.rb" with: """ruby RSpec.describe "an example" do example "is skipped", :skip => "waiting for planets to align" do raise "this line is never executed" end end """ When I run `rspec skipped_with_reason_spec.rb` Then the exit status should be 0 And the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) an example is skipped # waiting for planets to align # ./skipped_with_reason_spec.rb:2 """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/pending_and_skipped_examples/README.md0000664000000000000000000000125514557677674027644 0ustar rootroot# Pending and Skipped examples Sometimes you will have a failing example that can not be fixed, but is useful to keep around. For instance, the fix could depend on an upstream patch being merged, or the example is not supported on JRuby. RSpec provides two features for dealing with this scenario. An example can either be marked as _skipped_, in which is it not executed, or _pending_ in which it is executed but failure will not cause a failure of the entire suite. When a pending example passes (i.e. the underlying reasons for it being marked pending is no longer present) it will be marked as failed in order to communicate to you that it should no longer be marked as pending. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/expectation_framework_integration/0000775000000000000000000000000014557677674027502 5ustar rootroot././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/expectation_framework_integration/aggregating_failures.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/expectation_framework_integration/aggregating_fai0000664000000000000000000005402214557677674032526 0ustar rootrootFeature: Aggregating Failures RSpec::Expectations provides [`aggregate_failures`](../../rspec-expectations/aggregating-failures), an API that allows you to group a set of expectations and see all the failures at once, rather than it aborting on the first failure. RSpec::Core improves on this feature in a couple of ways: * RSpec::Core provides much better failure output, adding code snippets and backtraces to the sub-failures, just like it does for any normal failure. * RSpec::Core provides [metadata](../metadata/user-defined-metadata) integration for this feature. Each example that is tagged with `:aggregate_failures` will be wrapped in an `aggregate_failures` block. You can also use `config.define_derived_metadata` to apply this to every example automatically. The metadata form is quite convenient, but may not work well for end-to-end tests that have multiple distinct steps. For example, consider a spec for an HTTP client workflow that (1) makes a request, (2) expects a redirect, (3) follows the redirect, and (4) expects a particular response. You probably want the `expect(response.status).to be_between(300, 399)` expectation to immediately abort if it fails, because you can't perform the next step (following the redirect) if that is not satisfied. For these situations, we encourage you to use the `aggregate_failures` block form to wrap each set of expectations that represents a distinct step in the test workflow. Background: Given a file named "lib/client.rb" with: """ruby Response = Struct.new(:status, :headers, :body) class Client def self.make_request(url='/') Response.new(404, { "Content-Type" => "text/plain" }, "Not Found") end end """ @skip-when-diff-lcs-1.3 Scenario: Use `aggregate_failures` block form Given a file named "spec/use_block_form_spec.rb" with: """ruby require 'client' RSpec.describe Client do after do # this should be appended to failure list expect(false).to be(true), "after hook failure" end around do |ex| ex.run # this should also be appended to failure list expect(false).to be(true), "around hook failure" end it "returns a successful response" do response = Client.make_request aggregate_failures "testing response" do expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end end """ When I run `rspec spec/use_block_form_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Got 3 failures from failure aggregation block "testing response". # ./spec/use_block_form_spec.rb:18 # ./spec/use_block_form_spec.rb:10 1.1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/use_block_form_spec.rb:19 1.1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1 +1 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/use_block_form_spec.rb:20 1.1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/use_block_form_spec.rb:21 1.2) Failure/Error: expect(false).to be(true), "after hook failure" after hook failure # ./spec/use_block_form_spec.rb:6 # ./spec/use_block_form_spec.rb:10 1.3) Failure/Error: expect(false).to be(true), "around hook failure" around hook failure # ./spec/use_block_form_spec.rb:12 """ @skip-when-diff-lcs-1.4 Scenario: Use `aggregate_failures` block form Given a file named "spec/use_block_form_spec.rb" with: """ruby require 'client' RSpec.describe Client do after do # this should be appended to failure list expect(false).to be(true), "after hook failure" end around do |ex| ex.run # this should also be appended to failure list expect(false).to be(true), "around hook failure" end it "returns a successful response" do response = Client.make_request aggregate_failures "testing response" do expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end end """ When I run `rspec spec/use_block_form_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Got 3 failures from failure aggregation block "testing response". # ./spec/use_block_form_spec.rb:18 # ./spec/use_block_form_spec.rb:10 1.1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/use_block_form_spec.rb:19 1.1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1,2 +1,2 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/use_block_form_spec.rb:20 1.1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/use_block_form_spec.rb:21 1.2) Failure/Error: expect(false).to be(true), "after hook failure" after hook failure # ./spec/use_block_form_spec.rb:6 # ./spec/use_block_form_spec.rb:10 1.3) Failure/Error: expect(false).to be(true), "around hook failure" around hook failure # ./spec/use_block_form_spec.rb:12 """ Scenario: Use `:aggregate_failures` metadata Given a file named "spec/use_metadata_spec.rb" with: """ruby require 'client' RSpec.describe Client do it "follows a redirect", :aggregate_failures do response = Client.make_request expect(response.status).to eq(302) expect(response.body).to eq('{"message":"Redirect"}') redirect_response = Client.make_request(response.headers.fetch('Location')) expect(redirect_response.status).to eq(200) expect(redirect_response.body).to eq('{"message":"OK"}') end end """ When I run `rspec spec/use_metadata_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client follows a redirect Got 2 failures and 1 other error: 1.1) Failure/Error: expect(response.status).to eq(302) expected: 302 got: 404 (compared using ==) # ./spec/use_metadata_spec.rb:7 1.2) Failure/Error: expect(response.body).to eq('{"message":"Redirect"}') expected: "{\"message\":\"Redirect\"}" got: "Not Found" (compared using ==) # ./spec/use_metadata_spec.rb:8 1.3) Failure/Error: redirect_response = Client.make_request(response.headers.fetch('Location')) KeyError: key not found: "Location" # ./spec/use_metadata_spec.rb:10 # ./spec/use_metadata_spec.rb:10 """ @skip-when-diff-lcs-1.3 Scenario: Enable failure aggregation globally using `define_derived_metadata` Given a file named "spec/enable_globally_spec.rb" with: """ruby require 'client' RSpec.configure do |c| c.define_derived_metadata do |meta| meta[:aggregate_failures] = true end end RSpec.describe Client do it "returns a successful response" do response = Client.make_request expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/enable_globally_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/enable_globally_spec.rb:13 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1 +1 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/enable_globally_spec.rb:14 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/enable_globally_spec.rb:15 """ @skip-when-diff-lcs-1.4 Scenario: Enable failure aggregation globally using `define_derived_metadata` Given a file named "spec/enable_globally_spec.rb" with: """ruby require 'client' RSpec.configure do |c| c.define_derived_metadata do |meta| meta[:aggregate_failures] = true end end RSpec.describe Client do it "returns a successful response" do response = Client.make_request expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/enable_globally_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/enable_globally_spec.rb:13 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1,2 +1,2 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/enable_globally_spec.rb:14 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/enable_globally_spec.rb:15 """ @skip-when-diff-lcs-1.3 Scenario: Nested failure aggregation works Given a file named "spec/nested_failure_aggregation_spec.rb" with: """ruby require 'client' RSpec.describe Client do it "returns a successful response", :aggregate_failures do response = Client.make_request expect(response.status).to eq(200) aggregate_failures "testing headers" do expect(response.headers).to include("Content-Type" => "application/json") expect(response.headers).to include("Content-Length" => "21") end expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/nested_failure_aggregation_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/nested_failure_aggregation_spec.rb:7 1.2) Got 2 failures from failure aggregation block "testing headers". # ./spec/nested_failure_aggregation_spec.rb:9 1.2.1) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1 +1 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/nested_failure_aggregation_spec.rb:10 1.2.2) Failure/Error: expect(response.headers).to include("Content-Length" => "21") expected {"Content-Type" => "text/plain"} to include {"Content-Length" => "21"} Diff: @@ -1 +1 @@ -"Content-Length" => "21", +"Content-Type" => "text/plain", # ./spec/nested_failure_aggregation_spec.rb:11 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/nested_failure_aggregation_spec.rb:14 """ @skip-when-diff-lcs-1.4 Scenario: Nested failure aggregation works Given a file named "spec/nested_failure_aggregation_spec.rb" with: """ruby require 'client' RSpec.describe Client do it "returns a successful response", :aggregate_failures do response = Client.make_request expect(response.status).to eq(200) aggregate_failures "testing headers" do expect(response.headers).to include("Content-Type" => "application/json") expect(response.headers).to include("Content-Length" => "21") end expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/nested_failure_aggregation_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Client returns a successful response Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/nested_failure_aggregation_spec.rb:7 1.2) Got 2 failures from failure aggregation block "testing headers". # ./spec/nested_failure_aggregation_spec.rb:9 1.2.1) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1,2 +1,2 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/nested_failure_aggregation_spec.rb:10 1.2.2) Failure/Error: expect(response.headers).to include("Content-Length" => "21") expected {"Content-Type" => "text/plain"} to include {"Content-Length" => "21"} Diff: @@ -1,2 +1,2 @@ -"Content-Length" => "21", +"Content-Type" => "text/plain", # ./spec/nested_failure_aggregation_spec.rb:11 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/nested_failure_aggregation_spec.rb:14 """ Scenario: Mock expectation failures are aggregated as well Given a file named "spec/mock_expectation_failure_spec.rb" with: """ruby require 'client' RSpec.describe "Aggregating Failures", :aggregate_failures do it "has a normal expectation failure and a message expectation failure" do client = double("Client") expect(client).to receive(:put).with("updated data") allow(client).to receive(:get).and_return(Response.new(404, {}, "Not Found")) response = client.get expect(response.status).to eq(200) end end """ When I run `rspec spec/mock_expectation_failure_spec.rb` Then it should fail and list all the failures: """ Failures: 1) Aggregating Failures has a normal expectation failure and a message expectation failure Got 2 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/mock_expectation_failure_spec.rb:10 1.2) Failure/Error: expect(client).to receive(:put).with("updated data") (Double "Client").put("updated data") expected: 1 time with arguments: ("updated data") received: 0 times # ./spec/mock_expectation_failure_spec.rb:6 """ @skip-when-diff-lcs-1.3 Scenario: Pending integrates properly with aggregated failures Given a file named "spec/pending_spec.rb" with: """ruby require 'client' RSpec.describe Client do it "returns a successful response", :aggregate_failures do pending "Not yet ready" response = Client.make_request expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/pending_spec.rb` Then it should pass and list all the pending examples: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) Client returns a successful response # Not yet ready Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/pending_spec.rb:8 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1 +1 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/pending_spec.rb:9 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/pending_spec.rb:10 """ @skip-when-diff-lcs-1.4 Scenario: Pending integrates properly with aggregated failures Given a file named "spec/pending_spec.rb" with: """ruby require 'client' RSpec.describe Client do it "returns a successful response", :aggregate_failures do pending "Not yet ready" response = Client.make_request expect(response.status).to eq(200) expect(response.headers).to include("Content-Type" => "application/json") expect(response.body).to eq('{"message":"Success"}') end end """ When I run `rspec spec/pending_spec.rb` Then it should pass and list all the pending examples: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) Client returns a successful response # Not yet ready Got 3 failures: 1.1) Failure/Error: expect(response.status).to eq(200) expected: 200 got: 404 (compared using ==) # ./spec/pending_spec.rb:8 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json") expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"} Diff: @@ -1,2 +1,2 @@ -"Content-Type" => "application/json", +"Content-Type" => "text/plain", # ./spec/pending_spec.rb:9 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}') expected: "{\"message\":\"Success\"}" got: "Not Found" (compared using ==) # ./spec/pending_spec.rb:10 """ ././@LongLink0000644000000000000000000000017500000000000011606 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/expectation_framework_integration/configure_expectation_framework.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/expectation_framework_integration/configure_expec0000664000000000000000000001166414557677674032602 0ustar rootrootFeature: Configuring an expectation framework By default, RSpec is configured to include rspec-expectations for expressing desired outcomes. You can also configure RSpec to use: * rspec/expectations (explicitly) * test/unit assertions * minitest assertions * any combination of the above libraries Note that when you do not use rspec-expectations, you must explicitly provide a description to every example. You cannot rely on the generated descriptions provided by rspec-expectations. Scenario: Default configuration uses rspec-expectations Given a file named "example_spec.rb" with: """ruby RSpec::Matchers.define :be_a_multiple_of do |factor| match do |actual| actual % factor == 0 end end RSpec.describe 6 do it { is_expected.to be_a_multiple_of 3 } end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Configure rspec-expectations (explicitly) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec end RSpec.describe 5 do it "is greater than 4" do expect(5).to be > 4 end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Configure test/unit assertions Given rspec-expectations is not installed And a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :test_unit end RSpec.describe [1] do it "is equal to [1]" do assert_equal [1], [1], "expected [1] to equal [1]" end specify { assert_not_equal [1], [] } it "is equal to [2] (intentional failure)" do assert [1] == [2], "errantly expected [2] to equal [1]" end end """ When I run `rspec example_spec.rb` Then the output should match: """ (Test::Unit::AssertionFailedError|Mini(T|t)est::Assertion): errantly expected \[2\] to equal \[1\] """ And the output should contain "3 examples, 1 failure" @broken-on-jruby-9000 Scenario: Configure minitest assertions Given rspec-expectations is not installed And a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :minitest end RSpec.describe "Object identity" do it "the an object is the same as itself" do x = [1] assert_same x, x, "expected x to be the same x" end specify { refute_same [1], [1] } it "is empty (intentional failure)" do assert_empty [1], "errantly expected [1] to be empty" end it "marks pending for skip method" do skip "intentionally" end end """ When I run `rspec -b example_spec.rb` Then the output should match: """ MiniT|test::Assertion: errantly expected \[1\] to be empty """ And the output should contain "4 examples, 1 failure, 1 pending" And the output should not contain "Warning: you should require 'minitest/autorun' instead." Scenario: Configure rspec/expectations AND test/unit assertions Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec, :test_unit end RSpec.describe [1] do it "is equal to [1]" do assert_equal [1], [1], "expected [1] to equal [1]" end it "matches array [1]" do is_expected.to match_array([1]) end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Configure rspec/expectations AND minitest assertions Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec, :minitest end RSpec.describe "Object identity" do it "two arrays are not the same object" do refute_same [1], [1] end it "an array is itself" do array = [1] expect(array).to be array end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Configure test/unit and minitest assertions Given rspec-expectations is not installed And a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :test_unit, :minitest end RSpec.describe [1] do it "is equal to [1]" do assert_equal [1], [1], "expected [1] to equal [1]" end specify { assert_not_equal [1], [] } it "the an object is the same as itself" do x = [1] assert_same x, x, "expected x to be the same x" end specify { refute_same [1], [1] } end """ When I run `rspec example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/.nav0000664000000000000000000000303514557677674021265 0ustar rootroot- example_groups: - basic_structure.feature - shared_examples.feature - shared_context.feature - command_line: - example_name_option.feature - format_option.feature - tag.feature - line_number_appended_to_path.feature - exit_status.feature - order.md (`--order` option) - rake_task.feature - pending_and_skipped_examples: - pending_examples.feature - hooks: - before_and_after_hooks.feature - around_hooks.feature - filtering.feature - when_first_matching_example_defined.feature - subject: - implicit_subject.feature - explicit_subject.feature - one_liner_syntax.feature - helper_methods: - let.feature - arbitrary_methods.feature - modules.feature - metadata: - current_example.feature - described_class.feature - user_defined.feature - filtering: - inclusion_filters.feature - exclusion_filters.feature - if_and_unless.feature - filter_run_when_matching.feature - configuration: - read_options_from_file.feature - color.feature - fail_fast.feature - fail_if_no_examples.feature - custom_settings.feature - alias_example_to.feature - default_path.feature - expectation_framework_integration: - configure_expectation_framework.feature - aggregating_failures.feature - mock_framework_integration: - use_rspec.feature - use_flexmock.feature - use_mocha.feature - use_rr.feature - use_any_framework.feature - formatters: - configurable_colors.feature - json_formatter.feature - custom_formatter.feature - spec_files: - arbitrary_file_suffix.feature - core_standalone.feature ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/metadata/0000775000000000000000000000000014557677674022257 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/metadata/current_example.feature0000664000000000000000000000331514557677674027033 0ustar rootrootFeature: Using the current example You can reference the example object, and access its metadata, using the block argument provided to: `it`, `subject`, `let`, and the `before`, `after`, and `around` hooks. Scenario: Access the `example` object from within an example Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "example as block arg to it, before, and after" do before do |example| expect(example.description).to eq("is the example object") end after do |example| expect(example.description).to eq("is the example object") end it "is the example object" do |example| expect(example.description).to eq("is the example object") end end RSpec.describe "example as block arg to let" do let(:the_description) do |example| example.description end it "is the example object" do |example| expect(the_description).to eq("is the example object") end end RSpec.describe "example as block arg to subject" do subject do |example| example.description end it "is the example object" do |example| expect(subject).to eq("is the example object") end end RSpec.describe "example as block arg to subject with a name" do subject(:the_subject) do |example| example.description end it "is the example object" do |example| expect(the_subject).to eq("is the example object") expect(subject).to eq("is the example object") end end """ When I run `rspec spec/example_spec.rb` Then the example should pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/metadata/current_scope.feature0000664000000000000000000000501214557677674026505 0ustar rootrootFeature: `RSpec` provides the current scope as `RSpec.current_scope` You can detect which rspec scope your helper methods or library code is executing in. This is useful if for example, your method only makes sense to call in a certain context. Scenario: Detecting the current scope Given a file named "current_scope_spec.rb" with: """ruby # Outside of the test lifecycle, the current scope is `:suite` exit(1) unless RSpec.current_scope == :suite at_exit do exit(1) unless RSpec.current_scope == :suite end RSpec.configure do |c| c.before :suite do expect(RSpec.current_scope).to eq(:before_suite_hook) end c.before :context do expect(RSpec.current_scope).to eq(:before_context_hook) end c.before :example do expect(RSpec.current_scope).to eq(:before_example_hook) end c.around :example do |ex| expect(RSpec.current_scope).to eq(:before_example_hook) ex.run expect(RSpec.current_scope).to eq(:after_example_hook) end c.after :example do expect(RSpec.current_scope).to eq(:after_example_hook) end c.after :context do expect(RSpec.current_scope).to eq(:after_context_hook) end c.after :suite do expect(RSpec.current_scope).to eq(:after_suite_hook) end end RSpec.describe "RSpec.current_scope" do before :context do expect(RSpec.current_scope).to eq(:before_context_hook) end before :example do expect(RSpec.current_scope).to eq(:before_example_hook) end around :example do |ex| expect(RSpec.current_scope).to eq(:before_example_hook) ex.run expect(RSpec.current_scope).to eq(:after_example_hook) end after :example do expect(RSpec.current_scope).to eq(:after_example_hook) end after :context do expect(RSpec.current_scope).to eq(:after_context_hook) end it "is :example in an example" do expect(RSpec.current_scope).to eq(:example) end it "works for multiple examples" do expect(RSpec.current_scope).to eq(:example) end describe "in nested describe blocks" do it "still works" do expect(RSpec.current_scope).to eq(:example) end end end """ When I run `rspec current_scope_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/metadata/user_defined.feature0000664000000000000000000000744014557677674026275 0ustar rootrootFeature: User-defined metadata You can attach user-defined metadata to any example group or example. Pass a hash as the last argument (before the block) to `describe`, `context` or `it`. RSpec supports many configuration options that apply only to certain examples or groups based on the metadata. Metadata defined on an example group is available (and can be overridden) by any sub-group or from any example in that group or a sub-group. In addition, you can specify metadata using just symbols. Each symbol passed as an argument to `describe`, `context` or `it` will be a key in the metadata hash, with a corresponding value of `true`. Scenario: Define group metadata using a hash Given a file named "define_group_metadata_with_hash_spec.rb" with: """ruby RSpec.describe "a group with user-defined metadata", :foo => 17 do it 'has access to the metadata in the example' do |example| expect(example.metadata[:foo]).to eq(17) end it 'does not have access to metadata defined on sub-groups' do |example| expect(example.metadata).not_to include(:bar) end describe 'a sub-group with user-defined metadata', :bar => 12 do it 'has access to the sub-group metadata' do |example| expect(example.metadata[:bar]).to eq(12) end it 'also has access to metadata defined on parent groups' do |example| expect(example.metadata[:foo]).to eq(17) end end end """ When I run `rspec define_group_metadata_with_hash_spec.rb` Then the examples should all pass Scenario: Define example metadata using a hash Given a file named "define_example_metadata_with_hash_spec.rb" with: """ruby RSpec.describe "a group with no user-defined metadata" do it 'has an example with metadata', :foo => 17 do |example| expect(example.metadata[:foo]).to eq(17) expect(example.metadata).not_to include(:bar) end it 'has another example with metadata', :bar => 12, :bazz => 33 do |example| expect(example.metadata[:bar]).to eq(12) expect(example.metadata[:bazz]).to eq(33) expect(example.metadata).not_to include(:foo) end end """ When I run `rspec define_example_metadata_with_hash_spec.rb` Then the examples should all pass Scenario: Override user-defined metadata Given a file named "override_metadata_spec.rb" with: """ruby RSpec.describe "a group with user-defined metadata", :foo => 'bar' do it 'can be overridden by an example', :foo => 'bazz' do |example| expect(example.metadata[:foo]).to eq('bazz') end describe "a sub-group with an override", :foo => 'goo' do it 'can be overridden by a sub-group' do |example| expect(example.metadata[:foo]).to eq('goo') end end end """ When I run `rspec override_metadata_spec.rb` Then the examples should all pass Scenario: Less verbose metadata Given a file named "less_verbose_metadata_spec.rb" with: """ruby RSpec.describe "a group with simple metadata", :fast, :simple, :bug => 73 do it 'has `:fast => true` metadata' do |example| expect(example.metadata[:fast]).to eq(true) end it 'has `:simple => true` metadata' do |example| expect(example.metadata[:simple]).to eq(true) end it 'can still use a hash for metadata' do |example| expect(example.metadata[:bug]).to eq(73) end it 'can define simple metadata on an example', :special do |example| expect(example.metadata[:special]).to eq(true) end end """ When I run `rspec less_verbose_metadata_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/metadata/described_class.feature0000664000000000000000000000135614557677674026752 0ustar rootrootFeature: Using `described_class` If the first argument to an example group is a class, the class is exposed to each example in that example group via the `described_class()` method. Scenario: Access the described class from the example Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe Symbol do it "is available as described_class" do expect(described_class).to eq(Symbol) end describe 'inner' do describe String do it "is available as described_class" do expect(described_class).to eq(String) end end end end """ When I run `rspec spec/example_spec.rb` Then the example should pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/step_definitions/0000775000000000000000000000000014557677674024045 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/step_definitions/additional_cli_steps.rb0000664000000000000000000002140614557677674030552 0ustar rootrootrequire 'rspec/core' # to fix annoying "undefined method `configuration' for RSpec:Module (NoMethodError)" require './spec/support/formatter_support' Then /^the output should contain all of these:$/ do |table| table.raw.flatten.each do |string| expect(all_output).to include(string) end end Then /^the output should not contain any of these:$/ do |table| table.raw.flatten.each do |string| expect(all_output).not_to include(string) end end Then /^the output should contain one of the following:$/ do |table| matching_output = table.raw.flatten.select do |string| all_output.include?(string) end expect(matching_output.count).to eq(1) end Then /^the example(?:s)? should(?: all)? pass$/ do step %q{the output should contain "0 failures"} step %q{the output should not contain "0 examples"} step %q{the exit status should be 0} end Then /^the example(?:s)? should(?: all)? fail$/ do step %q{the output should not contain "0 examples"} step %q{the output should not contain "0 failures"} step %q{the exit status should be 1} example_summary = /(\d+) examples?, (\d+) failures?/.match(all_output) example_count, failure_count = example_summary.captures expect(failure_count).to eq(example_count) end Then /^the process should succeed even though no examples were run$/ do step %q{the output should contain "0 examples, 0 failures"} step %q{the exit status should be 0} end addition_example_formatter_output = <<-EOS Addition works EOS Then /^the output from `([^`]+)` (should(?: not)?) be in documentation format$/ do |cmd, should_or_not| step %Q{I run `#{cmd}`} step %q{the examples should all pass} step %Q{the output from "#{cmd}" #{should_or_not} contain "#{addition_example_formatter_output}"} end Then(/^the output from `([^`]+)` should indicate it ran only the subtraction file$/) do |cmd| step %Q{I run `#{cmd}`} step %q{the examples should all pass} step %Q{the output from "#{cmd}" should contain "1 example, 0 failures"} step %Q{the output from "#{cmd}" should contain "Subtraction"} step %Q{the output from "#{cmd}" should not contain "Addition"} end Then /^the backtrace\-normalized output should contain:$/ do |partial_output| # ruby 1.9 includes additional stuff in the backtrace, # so we need to normalize it to compare it with our expected output. normalized_output = all_output.split("\n").map do |line| line =~ /(^\s+# [^:]+:\d+)/ ? $1 : line # http://rubular.com/r/zDD7DdWyzF end.join("\n") expect(normalized_output).to include(partial_output) end Then /^the output should not contain any error backtraces$/ do step %q{the output should not contain "lib/rspec/core"} end # This step can be generalized if it's ever used to test other colors Then /^the failing example is printed (?:wrapped )?in (.*)$/ do |color| code = case color when "magenta" then "\e[35m" when /"(.*)"/ then "\e[#{$1}m" end # \e[35m = enable magenta # \e[0m = reset colors expect(all_output).to include(code + "F" + "\e[0m") end Then /^the output from `([^`]+)` should contain "(.*?)"$/ do |cmd, expected_output| step %Q{I run `#{cmd}`} step %Q{the output from "#{cmd}" should contain "#{expected_output}"} end Then /^the output from `([^`]+)` should not contain "(.*?)"$/ do |cmd, expected_output| step %Q{I run `#{cmd}`} step %Q{the output from "#{cmd}" should not contain "#{expected_output}"} end Given /^I have a brand new project with no files$/ do cd('.') do expect(Dir["**/*"]).to eq([]) end end Given /^I have run `([^`]*)`$/ do |cmd| run_command_and_stop(sanitize_text(cmd), :fail_on_error => true) end Given(/^a vendored gem named "(.*?)" containing a file named "(.*?)" with:$/) do |gem_name, file_name, file_contents| gem_dir = "vendor/#{gem_name}-1.2.3" step %Q{a file named "#{gem_dir}/#{file_name}" with:}, file_contents set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + " -I#{gem_dir}/lib") end When('I accept the recommended settings by removing `=begin` and `=end` from `spec_helper.rb`') do cd('.') do spec_helper = File.read("spec/spec_helper.rb") expect(spec_helper).to include("=begin", "=end") to_keep = spec_helper.lines.reject do |line| line.start_with?("=begin") || line.start_with?("=end") end File.open("spec/spec_helper.rb", "w") { |f| f.write(to_keep.join) } expect(File.read("spec/spec_helper.rb")).not_to include("=begin", "=end") end end When /^I create "([^"]*)" with the following content:$/ do |file_name, content| write_file(file_name, content) end Given(/^I have run `([^`]*)` once, resulting in "([^"]*)"$/) do |command, output_snippet| step %Q{I run `#{command}`} step %Q{the output from "#{command}" should contain "#{output_snippet}"} end When(/^I fix "(.*?)" by replacing "(.*?)" with "(.*?)"$/) do |file_name, original, replacement| cd('.') do contents = File.read(file_name) expect(contents).to include(original) fixed = contents.sub(original, replacement) File.open(file_name, "w") { |f| f.write(fixed) } end end Given(/^I have not configured `example_status_persistence_file_path`$/) do cd('.') do return unless File.exist?("spec/spec_helper.rb") return unless File.read("spec/spec_helper.rb").include?("example_status_persistence_file_path") File.open("spec/spec_helper.rb", "w") { |f| f.write("") } end end Given(/^files "(.*?)" through "(.*?)" with an unrelated passing spec in each file$/) do |file1, file2| index_1 = Integer(file1[/\d+/]) index_2 = Integer(file2[/\d+/]) pattern = file1.sub(/\d+/, '%s') index_1.upto(index_2) do |index| write_file(pattern % index, <<-EOS) RSpec.describe "Spec file #{index}" do example { } end EOS end end Then(/^bisect should (succeed|fail) with output like:$/) do |succeed, expected_output| last_process = all_commands.last expected_status = succeed == "succeed" ? 0 : 1 expect(last_process.exit_status).to eq(expected_status), "Expected exit status of #{expected_status} but got #{last_process.exit_status} \n\n" \ "Output:\n\n#{last_process.stdout}" expected = normalize_durations(expected_output) actual = normalize_durations(last_process.stdout).sub(/\n+\Z/, '') if !RSpec::Support::RubyFeatures.fork_supported? expected.gsub!('runner: :fork', 'runner: :shell') end if expected.include?("# ...") expected_start, expected_end = expected.split("# ...") expect(actual).to start_with(expected_start).and end_with(expected_end) else expect(actual).to eq(expected) end end When(/^I run `([^`]+)` and abort in the middle with ctrl\-c$/) do |cmd| set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + " -r#{File.expand_path("../../support/send_sigint_during_bisect.rb", __FILE__)}") step "I run `#{cmd}`" end Then(/^it should fail and list all the failures:$/) do |string| step %q{the exit status should not be 0} expect(normalize_failure_output(all_output)).to include(normalize_failure_output(string)) end Then(/^it should pass and list all the pending examples:$/) do |string| step %q{the exit status should be 0} expect(normalize_failure_output(all_output)).to include(normalize_failure_output(string)) end Then(/^the output should report "slow before context hook" as the slowest example group$/) do # These expectations are trying to guard against a regression that introduced # this output: # Top 1 slowest example groups: # slow before context hook # Inf seconds average (0.00221 seconds / 0 examples) RSpec::ExampleGroups::SlowBeforeContextHook::Nested # # Problems: # - "Inf seconds" # - 0 examples # - "Nested" group listed (it should be the outer group) # - The example group class name is listed (it should be the location) output = all_output expect(output).not_to match(/nested/i) expect(output).not_to match(/inf/i) expect(output).not_to match(/\b0 examples/i) seconds = '\d+(?:\.\d+)? seconds' expect(output).to match( %r{Top 1 slowest example groups?:\n\s+slow before context hook\n\s+#{seconds} average \(#{seconds} / 1 example\) \./spec/example_spec\.rb:1} ) end Given(/^I have changed `([^`]+)` to `([^`]+)` in "(.*?)"$/) do |old_code, new_code, file_name| cd('.') do file_content = File.read(file_name) expect(file_content).to include(old_code) new_file_content = file_content.sub(old_code, new_code) File.open(file_name, "w") { |f| f.write(new_file_content) } end end module Normalization def normalize_failure_output(text) whitespace_normalized = text.lines.map { |line| line.sub(/\s+$/, '').sub(/:in .*$/, '') }.join # 1.8.7 and JRuby produce slightly different output for `Hash#fetch` errors, so we # convert it to the same output here to match our expectation. whitespace_normalized. sub("IndexError", "KeyError"). sub(/key not found.*$/, "key not found") end end World(Normalization) World(FormatterSupport) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/step_definitions/core_standalone_steps.rb0000664000000000000000000000123614557677674030752 0ustar rootrootGiven(/^only rspec-core is installed$/) do if RUBY_VERSION.to_f >= 1.9 # --disable-gems is invalid on 1.8.7 # Ensure the gem versions of rspec-mocks and rspec-expectations # won't be loaded if available on the developers machine. set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + ' --disable-gems') end # This will make `require_expect_syntax_in_aruba_specs.rb` (loaded # automatically when the specs run) remove rspec-mocks and # rspec-expectations from the load path. set_environment_variable('REMOVE_OTHER_RSPEC_LIBS_FROM_LOAD_PATH', 'true') end Given(/^rspec-expectations is not installed$/) do step "only rspec-core is installed" end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/example_groups/0000775000000000000000000000000014557677674023531 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/example_groups/shared_examples.feature0000664000000000000000000002532614557677674030262 0ustar rootrootFeature: Using shared examples Shared examples let you describe behaviour of classes or modules. When declared, a shared group's content is stored. It is only realized in the context of another example group, which provides any context the shared group needs to run. A shared group is included in another group using any of: ```ruby include_examples "name" # include the examples in the current context it_behaves_like "name" # include the examples in a nested context it_should_behave_like "name" # include the examples in a nested context matching metadata # include the examples in the current context ``` **WARNING:** Files containing shared groups must be loaded before the files that use them. While there are conventions to handle this, RSpec does _not_ do anything special (like autoload). Doing so would require a strict naming convention for files that would break existing suites. **WARNING:** When you include parameterized examples in the current context multiple times, you may override previous method definitions and last declaration wins. So if you have this kind of shared example (or shared context) ```ruby RSpec.shared_examples "some example" do |parameter| \# Same behavior is triggered also with either `def something; 'some value'; end` \# or `define_method(:something) { 'some value' }` let(:something) { parameter } it "uses the given parameter" do expect(something).to eq(parameter) end end RSpec.describe SomeClass do include_examples "some example", "parameter1" include_examples "some example", "parameter2" end ``` You're actually doing this (notice that first example will fail): ```ruby RSpec.describe SomeClass do \# Reordered code for better understanding of what is happening let(:something) { "parameter1" } let(:something) { "parameter2" } it "uses the given parameter" do \# This example will fail because last let "wins" expect(something).to eq("parameter1") end it "uses the given parameter" do expect(something).to eq("parameter2") end end ``` To prevent this kind of subtle error a warning is emitted if you declare multiple methods with the same name in the same context. Should you get this warning the simplest solution is to replace `include_examples` with `it_behaves_like`, in this way method overriding is avoided because of the nested context created by `it_behaves_like` Conventions: ------------ 1. The simplest approach is to require files with shared examples explicitly from the files that use them. Keep in mind that RSpec adds the `spec` directory to the `LOAD_PATH`, so you can say `require 'shared_examples_for_widgets'` to require a file at `#{PROJECT_ROOT}/spec/shared_examples_for_widgets.rb`. 2. One convention is to put files containing shared examples in `spec/support/` and require files in that directory from `spec/spec_helper.rb`: ```ruby Dir["./spec/support/**/*.rb"].sort.each { |f| require f } ``` Historically, this was included in the generated `spec/spec_helper.rb` file in `rspec-rails`. However, in order to keep your test suite boot time down, it's a good idea to not autorequire all files in a directory like this. When running only one spec file, loading unneeded dependencies or performing unneeded setup can have a significant, noticeable effect on how long it takes before the first example runs. 3. When all of the groups that include the shared group reside in the same file, just declare the shared group in that file. Scenario: Shared examples group included in two groups in one file Given a file named "collection_spec.rb" with: """ruby require "set" RSpec.shared_examples "a collection" do let(:collection) { described_class.new([7, 2, 4]) } context "initialized with 3 items" do it "says it has three items" do expect(collection.size).to eq(3) end end describe "#include?" do context "with an item that is in the collection" do it "returns true" do expect(collection.include?(7)).to be(true) end end context "with an item that is not in the collection" do it "returns false" do expect(collection.include?(9)).to be(false) end end end end RSpec.describe Array do it_behaves_like "a collection" end RSpec.describe Set do it_behaves_like "a collection" end """ When I run `rspec collection_spec.rb --format documentation` Then the examples should all pass And the output should contain: """ Array behaves like a collection initialized with 3 items says it has three items #include? with an item that is in the collection returns true with an item that is not in the collection returns false Set behaves like a collection initialized with 3 items says it has three items #include? with an item that is in the collection returns true with an item that is not in the collection returns false """ Scenario: Providing context to a shared group using a block Given a file named "shared_example_group_spec.rb" with: """ruby require "set" RSpec.shared_examples "a collection object" do describe "<<" do it "adds objects to the end of the collection" do collection << 1 collection << 2 expect(collection.to_a).to match_array([1, 2]) end end end RSpec.describe Array do it_behaves_like "a collection object" do let(:collection) { Array.new } end end RSpec.describe Set do it_behaves_like "a collection object" do let(:collection) { Set.new } end end """ When I run `rspec shared_example_group_spec.rb --format documentation` Then the examples should all pass And the output should contain: """ Array behaves like a collection object << adds objects to the end of the collection Set behaves like a collection object << adds objects to the end of the collection """ Scenario: Passing parameters to a shared example group Given a file named "shared_example_group_params_spec.rb" with: """ruby RSpec.shared_examples "a measurable object" do |measurement, measurement_methods| measurement_methods.each do |measurement_method| it "should return #{measurement} from ##{measurement_method}" do expect(subject.send(measurement_method)).to eq(measurement) end end end RSpec.describe Array, "with 3 items" do subject { [1, 2, 3] } it_should_behave_like "a measurable object", 3, [:size, :length] end RSpec.describe String, "of 6 characters" do subject { "FooBar" } it_should_behave_like "a measurable object", 6, [:size, :length] end """ When I run `rspec shared_example_group_params_spec.rb --format documentation` Then the examples should all pass And the output should contain: """ Array with 3 items it should behave like a measurable object should return 3 from #size should return 3 from #length String of 6 characters it should behave like a measurable object should return 6 from #size should return 6 from #length """ Scenario: Aliasing `it_should_behave_like` to `it_has_behavior` Given a file named "shared_example_group_spec.rb" with: """ruby RSpec.configure do |c| c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:' end RSpec.shared_examples 'sortability' do it 'responds to <=>' do expect(sortable).to respond_to(:<=>) end end RSpec.describe String do it_has_behavior 'sortability' do let(:sortable) { 'sample string' } end end """ When I run `rspec shared_example_group_spec.rb --format documentation` Then the examples should all pass And the output should contain: """ String has behavior: sortability responds to <=> """ Scenario: Sharing metadata automatically includes shared example groups Given a file named "shared_example_metadata_spec.rb" with: """ruby RSpec.shared_examples "shared stuff", :a => :b do it 'runs wherever the metadata is shared' do end end RSpec.describe String, :a => :b do end """ When I run `rspec shared_example_metadata_spec.rb` Then the output should contain: """ 1 example, 0 failures """ Scenario: Shared examples are nestable by context Given a file named "context_specific_examples_spec.rb" with: """ruby RSpec.describe "shared examples" do context "per context" do shared_examples "shared examples are nestable" do specify { expect(true).to eq true } end it_behaves_like "shared examples are nestable" end end """ When I run `rspec context_specific_examples_spec.rb` Then the output should contain: """ 1 example, 0 failures """ Scenario: Shared examples are accessible from offspring contexts Given a file named "context_specific_examples_spec.rb" with: """ruby RSpec.describe "shared examples" do shared_examples "shared examples are nestable" do specify { expect(true).to eq true } end context "per context" do it_behaves_like "shared examples are nestable" end end """ When I run `rspec context_specific_examples_spec.rb` Then the output should contain: """ 1 example, 0 failures """ And the output should not contain: """ Accessing shared_examples defined across contexts is deprecated """ Scenario: Shared examples are isolated per context Given a file named "isolated_shared_examples_spec.rb" with: """ruby RSpec.describe "shared examples" do context do shared_examples "shared examples are isolated" do specify { expect(true).to eq true } end end context do it_behaves_like "shared examples are isolated" end end """ When I run `rspec isolated_shared_examples_spec.rb` Then the output should contain: """ Could not find shared examples \"shared examples are isolated\" """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/example_groups/shared_context.feature0000664000000000000000000001245614557677674030130 0ustar rootrootFeature: Using `shared_context` Use `shared_context` to define a block that will be evaluated in the context of example groups either locally, using `include_context` in an example group, or globally using `config.include_context`. When implicitly including shared contexts via matching metadata, the normal way is to define matching metadata on an example group, in which case the context is included in the entire group. However, you also have the option to include it in an individual example instead. RSpec treats every example as having a singleton example group (analogous to Ruby's singleton classes) containing just the one example. Background: Given a file named "shared_stuff.rb" with: """ruby RSpec.configure do |rspec| # This config option will be enabled by default on RSpec 4, # but for reasons of backwards compatibility, you have to # set it on RSpec 3. # # It causes the host group and examples to inherit metadata # from the shared context. rspec.shared_context_metadata_behavior = :apply_to_host_groups end RSpec.shared_context "shared stuff", :shared_context => :metadata do before { @some_var = :some_value } def shared_method "it works" end let(:shared_let) { {'arbitrary' => 'object'} } subject do 'this is the subject' end end RSpec.configure do |rspec| rspec.include_context "shared stuff", :include_shared => true end """ Scenario: Declare a shared context and include it with `include_context` Given a file named "shared_context_example.rb" with: """ruby require "./shared_stuff.rb" RSpec.describe "group that includes a shared context using 'include_context'" do include_context "shared stuff" it "has access to methods defined in shared context" do expect(shared_method).to eq("it works") end it "has access to methods defined with let in shared context" do expect(shared_let['arbitrary']).to eq('object') end it "runs the before hooks defined in the shared context" do expect(@some_var).to be(:some_value) end it "accesses the subject defined in the shared context" do expect(subject).to eq('this is the subject') end group = self it "inherits metadata from the included context" do |ex| expect(group.metadata).to include(:shared_context => :metadata) expect(ex.metadata).to include(:shared_context => :metadata) end end """ When I run `rspec shared_context_example.rb` Then the examples should all pass Scenario: Declare a shared context, include it with `include_context` and extend it with an additional block Given a file named "shared_context_example.rb" with: """ruby require "./shared_stuff.rb" RSpec.describe "including shared context using 'include_context' and a block" do include_context "shared stuff" do let(:shared_let) { {'in_a' => 'block'} } end it "evaluates the block in the shared context" do expect(shared_let['in_a']).to eq('block') end end """ When I run `rspec shared_context_example.rb` Then the examples should all pass Scenario: Declare a shared context and include it with metadata Given a file named "shared_context_example.rb" with: """ruby require "./shared_stuff.rb" RSpec.describe "group that includes a shared context using metadata", :include_shared => true do it "has access to methods defined in shared context" do expect(shared_method).to eq("it works") end it "has access to methods defined with let in shared context" do expect(shared_let['arbitrary']).to eq('object') end it "runs the before hooks defined in the shared context" do expect(@some_var).to be(:some_value) end it "accesses the subject defined in the shared context" do expect(subject).to eq('this is the subject') end group = self it "inherits metadata from the included context" do |ex| expect(group.metadata).to include(:shared_context => :metadata) expect(ex.metadata).to include(:shared_context => :metadata) end end """ When I run `rspec shared_context_example.rb` Then the examples should all pass Scenario: Declare a shared context and include it with metadata of an individual example Given a file named "shared_context_example.rb" with: """ruby require "./shared_stuff.rb" RSpec.describe "group that does not include the shared context" do it "does not have access to shared methods normally" do expect(self).not_to respond_to(:shared_method) end it "has access to shared methods from examples with matching metadata", :include_shared => true do expect(shared_method).to eq("it works") end it "inherits metadata from the included context due to the matching metadata", :include_shared => true do |ex| expect(ex.metadata).to include(:shared_context => :metadata) end end """ When I run `rspec shared_context_example.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/example_groups/basic_structure.feature0000664000000000000000000000322514557677674030311 0ustar rootrootFeature: The basic structure (`describe`/`it`) RSpec is a DSL for creating executable examples of how code is expected to behave, organized in groups. It uses the words "describe" and "it" so we can express concepts like a conversation: "Describe an account when it is first opened." "It has a balance of zero." The `describe` method creates an example group. Within the block passed to `describe` you can declare nested groups using the `describe` or `context` methods, or you can declare examples using the `it` or `specify` methods. Under the hood, an example group is a class in which the block passed to `describe` or `context` is evaluated. The blocks passed to `it` are evaluated in the context of an _instance_ of that class. Scenario: One group, one example Given a file named "sample_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do end end """ When I run `rspec sample_spec.rb -fdoc` Then the output should contain: """ something does something """ Scenario: Nested example groups (using `context`) Given a file named "nested_example_groups_spec.rb" with: """ruby RSpec.describe "something" do context "in one context" do it "does one thing" do end end context "in another context" do it "does another thing" do end end end """ When I run `rspec nested_example_groups_spec.rb -fdoc` Then the output should contain: """ something in one context does one thing in another context does another thing """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/example_groups/aliasing.feature0000664000000000000000000000254614557677674026704 0ustar rootrootFeature: Aliasing `describe` and `context` are the default aliases for `example_group`. You can define your own aliases for `example_group` and give those custom aliases default metadata. RSpec provides a few built-in aliases: * `xdescribe` and `xcontext` add `:skip` metadata to the example group in order to temporarily disable the examples. * `fdescribe` and `fcontext` add `:focus` metadata to the example group in order to make it easy to temporarily focus the example group (when combined with `config.filter_run :focus`.) Scenario: Custom example group aliases with metadata Given a file named "nested_example_group_aliases_spec.rb" with: """ruby RSpec.configure do |c| c.alias_example_group_to :detail, :detailed => true end RSpec.detail "a detail" do it "can do some less important stuff" do end end RSpec.describe "a thing" do describe "in broad strokes" do it "can do things" do end end detail "something less important" do it "can do an unimportant thing" do end end end """ When I run `rspec nested_example_group_aliases_spec.rb --tag detailed -fdoc` Then the output should contain: """ a detail can do some less important stuff a thing something less important """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/spec_files/0000775000000000000000000000000014557677674022613 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/spec_files/arbitrary_file_suffix.feature0000664000000000000000000000046514557677674030557 0ustar rootrootFeature: Using an arbitrary file suffix Scenario: `.spec` Given a file named "a.spec" with: """ruby RSpec.describe "something" do it "does something" do expect(3).to eq(3) end end """ When I run `rspec a.spec` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/0000775000000000000000000000000014557677674026110 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_flexmock.feature0000664000000000000000000000550014557677674032151 0ustar rootrootFeature: Mocking with `flexmock` Configure RSpec to use flexmock as shown in the scenarios below. Scenario: Passing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :flexmock end RSpec.describe "mocking with Flexmock" do it "passes when it should" do receiver = flexmock('receiver') receiver.should_receive(:message).once receiver.message end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Failing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :flexmock end RSpec.describe "mocking with Flexmock" do it "fails when it should" do receiver = flexmock('receiver') receiver.should_receive(:message).once end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 1 failure" Scenario: Failing message expectation in pending example (remains pending) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :flexmock end RSpec.describe "failed message expectation in a pending example" do it "is listed as pending" do pending receiver = flexmock('receiver') receiver.should_receive(:message).once end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the exit status should be 0 Scenario: Passing message expectation in pending example (fails) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :flexmock end RSpec.describe "passing message expectation in a pending example" do it "fails with FIXED" do pending receiver = flexmock('receiver') receiver.should_receive(:message).once receiver.message end end """ When I run `rspec example_spec.rb` Then the output should contain "FIXED" Then the output should contain "1 example, 1 failure" And the exit status should be 1 Scenario: Accessing `RSpec.configuration.mock_framework.framework_name` Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :flexmock end RSpec.describe "RSpec.configuration.mock_framework.framework_name" do it "returns :flexmock" do expect(RSpec.configuration.mock_framework.framework_name).to eq(:flexmock) end end """ When I run `rspec example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_rspec.feature0000664000000000000000000000646014557677674031463 0ustar rootrootFeature: Mocking with `rspec` RSpec uses its own mocking framework by default. You can also configure it explicitly if you wish. Scenario: Passing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "mocking with RSpec" do it "passes when it should" do receiver = double('receiver') expect(receiver).to receive(:message) receiver.message end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Failing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "mocking with RSpec" do it "fails when it should" do receiver = double('receiver') expect(receiver).to receive(:message) end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 1 failure" Scenario: Failing message expectation in pending example (remains pending) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "failed message expectation in a pending example" do it "is listed as pending" do pending receiver = double('receiver') expect(receiver).to receive(:message) end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the exit status should be 0 Scenario: Passing message expectation in pending example (fails) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "passing message expectation in a pending example" do it "fails with FIXED" do pending receiver = double('receiver') expect(receiver).to receive(:message) receiver.message end end """ When I run `rspec example_spec.rb` Then the output should contain "FIXED" Then the output should contain "1 example, 1 failure" And the exit status should be 1 Scenario: Accessing `RSpec.configuration.mock_framework.framework_name` Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "RSpec.configuration.mock_framework.framework_name" do it "returns :rspec" do expect(RSpec.configuration.mock_framework.framework_name).to eq(:rspec) end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Doubles may be used in generated descriptions Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rspec end RSpec.describe "Testing" do # Examples with no descriptions will default to RSpec-generated descriptions it do foo = double("Test") expect(foo).to be foo end end """ When I run `rspec example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_mocha.feature0000664000000000000000000000536414557677674031440 0ustar rootrootFeature: Mocking with `mocha` Configure RSpec to use mocha as shown in the scenarios below. Scenario: Passing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :mocha end RSpec.describe "mocking with RSpec" do it "passes when it should" do receiver = mock('receiver') receiver.expects(:message).once receiver.message end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Failing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :mocha end RSpec.describe "mocking with RSpec" do it "fails when it should" do receiver = mock('receiver') receiver.expects(:message).once end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 1 failure" Scenario: Failing message expectation in pending example (remains pending) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :mocha end RSpec.describe "failed message expectation in a pending example" do it "is listed as pending" do pending receiver = mock('receiver') receiver.expects(:message).once end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the exit status should be 0 Scenario: Passing message expectation in pending example (fails) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :mocha end RSpec.describe "passing message expectation in a pending example" do it "fails with FIXED" do pending receiver = mock('receiver') receiver.expects(:message).once receiver.message end end """ When I run `rspec example_spec.rb` Then the output should contain "FIXED" Then the output should contain "1 example, 1 failure" And the exit status should be 1 Scenario: Accessing `RSpec.configuration.mock_framework.framework_name` Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :mocha end RSpec.describe "RSpec.configuration.mock_framework.framework_name" do it "returns :mocha" do expect(RSpec.configuration.mock_framework.framework_name).to eq(:mocha) end end """ When I run `rspec example_spec.rb` Then the examples should all pass ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_any_framework.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_any_framework.feat0000664000000000000000000000542014557677674032472 0ustar rootrootFeature: Mocking with an alternative framework In addition to rspec, mocha, flexmock, and RR, you can choose an alternate framework as the mocking framework. You (or the framework authors) just needs to provide an adapter that hooks RSpec's events into those of the framework. A mock framework adapter must expose three methods: * `setup_mocks_for_rspec` * called before each example is run * `verify_mocks_for_rspec` * called after each example is run * this is where message expectation failures should result in an error with the appropriate failure message * `teardown_mocks_for_rspec` * called after `verify_mocks_for_rspec` * use this to clean up resources, restore objects to earlier state, etc * guaranteed to run even if there are failures Scenario: Mock with alternate framework Given a file named "expector.rb" with: """ruby class Expector class << self def expectors @expectors ||= [] end def clear_expectors expectors.clear end def verify_expectors expectors.each {|d| d.verify} end end def initialize self.class.expectors << self end def expectations @expectations ||= [] end def expect(message) expectations << message.to_s end def verify unless expectations.empty? raise expectations.map {|e| "expected #{e}, but it was never received" }.join("\n") end end private def method_missing(name, *args, &block) expectations.delete(name.to_s) end public module RSpecAdapter def setup_mocks_for_rspec # no setup necessary end def verify_mocks_for_rspec Expector.verify_expectors end def teardown_mocks_for_rspec Expector.clear_expectors end end end """ Given a file named "example_spec.rb" with: """ruby require File.expand_path("../expector", __FILE__) RSpec.configure do |config| config.mock_with Expector::RSpecAdapter end RSpec.describe Expector do it "passes when message is received" do expector = Expector.new expector.expect(:foo) expector.foo end it "fails when message is received" do expector = Expector.new expector.expect(:foo) end end """ When I run `rspec example_spec.rb --format doc` Then the exit status should be 1 And the output should contain "2 examples, 1 failure" And the output should contain "fails when message is received (FAILED - 1)" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/mock_framework_integration/use_rr.feature0000664000000000000000000000523614557677674030772 0ustar rootrootFeature: Mocking with `rr` Configure RSpec to use rr as shown in the scenarios below. Scenario: Passing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rr end RSpec.describe "mocking with RSpec" do it "passes when it should" do receiver = Object.new mock(receiver).message receiver.message end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Failing message expectation Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rr end RSpec.describe "mocking with RSpec" do it "fails when it should" do receiver = Object.new mock(receiver).message end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 1 failure" Scenario: Failing message expectation in pending example (remains pending) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rr end RSpec.describe "failed message expectation in a pending example" do it "is listed as pending" do pending receiver = Object.new mock(receiver).message end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the exit status should be 0 Scenario: Passing message expectation in pending example (fails) Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rr end RSpec.describe "passing message expectation in a pending example" do it "fails with FIXED" do pending receiver = Object.new mock(receiver).message receiver.message end end """ When I run `rspec example_spec.rb` Then the output should contain "FIXED" Then the output should contain "1 example, 1 failure" And the exit status should be 1 Scenario: Accessing `RSpec.configuration.mock_framework.framework_name` Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.mock_with :rr end RSpec.describe "RSpec.configuration.mock_framework.framework_name" do it "returns :rr" do expect(RSpec.configuration.mock_framework.framework_name).to eq(:rr) end end """ When I run `rspec example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/core_standalone.feature0000664000000000000000000000170414557677674025216 0ustar rootrootFeature: Use `rspec-core` without `rspec-mocks` or `rspec-expectations` It is most common to use rspec-core with rspec-mocks and rspec-expectations, and rspec-core will take care of loading those libraries automatically if available, but rspec-core can be used just fine without either of those gems installed. # Rubinius stacktrace includes kernel/loader.rb etc. @unsupported-on-rbx Scenario: Use only rspec-core when only it is installed Given only rspec-core is installed And a file named "core_only_spec.rb" with: """ruby RSpec.describe "Only rspec-core is available" do it "it fails when an rspec-mocks API is used" do dbl = double("MyDouble") end it "it fails when an rspec-expectations API is used" do expect(1).to eq(1) end end """ When I run `rspec core_only_spec.rb` Then the output should contain "2 examples, 2 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/README.md0000664000000000000000000000113714557677674021760 0ustar rootroot# RSpec Core `rspec-core` provides the structure for RSpec code examples: ```ruby RSpec.describe Account do it "has a balance of zero when first opened" do # example code goes here - for more on the # code inside the examples, see rspec-expectations # and rspec-mocks end end ``` ## Issues This documentation is [open source](https://github.com/rspec/rspec-core/tree/main/features), and a work in progress. If you find it incomplete or confusing, please [submit an issue](http://github.com/rspec/rspec-core/issues), or, better yet, [a pull request](http://github.com/rspec/rspec-core). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/0000775000000000000000000000000014557677674022213 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/env.rb0000664000000000000000000000161214557677674023330 0ustar rootrootrequire 'aruba/cucumber' Before do # Force ids to be printed unquoted for consistency set_environment_variable('SHELL', '/usr/bin/bash') end Aruba.configure do |config| config.exit_timeout = if RUBY_PLATFORM =~ /java/ || defined?(Rubinius) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'truffleruby') 120 else 10 end end Aruba.configure do |config| config.before(:command) do |cmd| set_environment_variable('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived end end if RUBY_PLATFORM == 'java' Aruba.configure do |config| config.before(:command) do |cmd| set_environment_variable('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived end end if defined?(Rubinius) module ArubaHelpers def all_output all_commands.map { |c| c.output }.join("\n") end end World(ArubaHelpers) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/jruby.rb0000664000000000000000000000037214557677674023675 0ustar rootrootAround "@broken-on-jruby-9000" do |scenario, block| require 'rspec/support/ruby_features' if RSpec::Support::Ruby.jruby_9000? skip_this_scenario "Skipping scenario #{scenario.name} not supported on JRuby 9000" else block.call end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/require_expect_syntax_in_aruba_specs.rb0000664000000000000000000000207214557677674032230 0ustar rootrootif defined?(Cucumber) require 'shellwords' use_tilde_tags = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') exclude_allow_should_syntax = use_tilde_tags ? '~@allow-should-syntax' : 'not @allow-should-syntax' exclude_with_clean_spec_ops = use_tilde_tags ? '~@with-clean-spec-opts' : 'not @with-clean-spec-opts' Before(exclude_allow_should_syntax, exclude_with_clean_spec_ops) do set_environment_variable('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}") end Before('@oneliner-should') do set_environment_variable('ALLOW_ONELINER_SHOULD', 'true') end else if ENV['REMOVE_OTHER_RSPEC_LIBS_FROM_LOAD_PATH'] $LOAD_PATH.reject! { |x| /rspec-mocks/ === x || /rspec-expectations/ === x } end module DisallowOneLinerShould def should(*) raise "one-liner should is not allowed" end def should_not(*) raise "one-liner should_not is not allowed" end end RSpec.configure do |rspec| rspec.disable_monkey_patching! rspec.include DisallowOneLinerShould unless ENV['ALLOW_ONELINER_SHOULD'] end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/rubinius.rb0000664000000000000000000000050414557677674024377 0ustar rootroot# Required until https://github.com/rubinius/rubinius/issues/2430 is resolved ENV['RBXOPT'] = "#{ENV["RBXOPT"]} -Xcompiler.no_rbc" Around "@unsupported-on-rbx" do |scenario, block| if defined?(Rubinius) block.call else skip_this_scenario "Skipping scenario #{scenario.name} not supported on Rubinius" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/ruby_27_support.rb0000664000000000000000000000027314557677674025627 0ustar rootrootAround "@ruby-2-7" do |scenario, block| if RUBY_VERSION.to_f == 2.7 block.call else skip_this_scenario "Skipping scenario #{scenario.name} on Ruby v#{RUBY_VERSION}" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/send_sigint_during_bisect.rb0000664000000000000000000000137314557677674027753 0ustar rootrootrequire 'rspec/core' RSpec::Support.require_rspec_core "formatters/bisect_progress_formatter" module RSpec::Core::Formatters BisectProgressFormatter = Class.new(remove_const :BisectProgressFormatter) do RSpec::Core::Formatters.register self def bisect_round_started(notification) return super unless @round_count == 3 Process.kill("INT", Process.pid) # Process.kill is not a synchronous call, so to ensure the output # below aborts at a deterministic place, we need to block here. # The sleep will be interrupted by the signal once the OS sends it. # For the most part, this is only needed on JRuby, but we saw # the asynchronous behavior on an MRI 2.0 travis build as well. sleep 5 end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/support/diff_lcs_versions.rb0000664000000000000000000000070414557677674026242 0ustar rootrootrequire 'diff-lcs' Around "@skip-when-diff-lcs-1.4" do |scenario, block| if Diff::LCS::VERSION >= '1.4' skip_this_scenario "Skipping scenario #{scenario.name} on `diff-lcs` v#{Diff::LCS::VERSION}" else block.call end end Around "@skip-when-diff-lcs-1.3" do |scenario, block| if Diff::LCS::VERSION < '1.4' skip_this_scenario "Skipping scenario #{scenario.name} on `diff-lcs` v#{Diff::LCS::VERSION}" else block.call end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/formatters/0000775000000000000000000000000014557677674022665 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/formatters/configurable_colors.feature0000664000000000000000000000353014557677674030264 0ustar rootrootFeature: Configurable colors RSpec allows you to configure the terminal colors used in the text formatters. * `failure_color`: Color used when tests fail (default: `:red`) * `success_color`: Color used when tests pass (default: `:green`) * `pending_color`: Color used when tests are pending (default: `:yellow`) * `fixed_color`: Color used when a pending block inside an example passes, but was expected to fail (default: `:blue`) * `detail_color`: Color used for miscellaneous test details (default: `:cyan`) Colors are specified as symbols. Options are `:black`, `:red`, `:green`, `:yellow`, `:blue`, `:magenta`, `:cyan`, `:white`, `:bold_black`, `:bold_red`, `:bold_green`, `:bold_yellow`, `:bold_blue`, `:bold_magenta`, `:bold_cyan`, and `:bold_white`, @keep-ansi-escape-sequences Scenario: Customizing the failure color Given a file named "custom_failure_color_spec.rb" with: """ruby RSpec.configure do |config| config.failure_color = :magenta config.color_mode = :on end RSpec.describe "failure" do it "fails and uses the custom color" do expect(2).to eq(4) end end """ When I run `rspec custom_failure_color_spec.rb --format progress` Then the failing example is printed in magenta @keep-ansi-escape-sequences Scenario: Customizing the failure color with a custom console code Given a file named "custom_failure_color_spec.rb" with: """ruby RSpec.configure do |config| config.failure_color = "1;32" config.color_mode = :on end RSpec.describe "failure" do it "fails and uses the custom color" do expect(2).to eq(4) end end """ When I run `rspec custom_failure_color_spec.rb --format progress` Then the failing example is printed wrapped in "1;32" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/formatters/json_formatter.feature0000664000000000000000000000203414557677674027275 0ustar rootrootFeature: The JSON formatter Scenario: Formatting example names for retry Given a file named "various_spec.rb" with: """ruby RSpec.describe "Various" do it "fails" do expect("fail").to eq("succeed") end it "succeeds" do expect("succeed").to eq("succeed") end it "pends" end """ When I run `rspec various_spec.rb --format j` Then the output should contain all of these: |"summary_line":"3 examples, 1 failure, 1 pending"| |"examples":[ | |"description":"fails" | |"full_description":"Various fails" | |"status":"failed" | |"file_path":"./various_spec.rb" | |"line_number":2 | |"exception":{ | |"class":"RSpec::Expectations::ExpectationNotMetError"| And the exit status should be 1 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/formatters/custom_formatter.feature0000664000000000000000000000255714557677674027650 0ustar rootrootFeature: Custom formatters RSpec ships with general purpose output formatters. You can tell RSpec which one to use using the [`--format` command line option](../command-line/format-option). When RSpec's built-in output formatters don't, however, give you everything you need, you can write your own custom formatter and tell RSpec to use that one instead. The simplest way is to subclass RSpec's `BaseTextFormatter`, and then override just the methods that you want to modify. Scenario: Custom formatter Given a file named "custom_formatter.rb" with: """ruby class CustomFormatter # This registers the notifications this formatter supports, and tells # us that this was written against the RSpec 3.x formatter API. RSpec::Core::Formatters.register self, :example_started def initialize(output) @output = output end def example_started(notification) @output << "example: " << notification.example.description end end """ And a file named "example_spec.rb" with: """ruby RSpec.describe "my group" do specify "my example" do end end """ When I run `rspec example_spec.rb --require ./custom_formatter.rb --format CustomFormatter` Then the output should contain "example: my example" And the exit status should be 0 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/subject/0000775000000000000000000000000014557677674022136 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/subject/implicit_subject.feature0000664000000000000000000000342314557677674027046 0ustar rootrootFeature: Implicitly defined subject If the first argument to an example group is a class, an instance of that class is exposed to each example in that example group via the `subject` method. While the examples below demonstrate how `subject` can be used as a user-facing concept, we recommend that you reserve it for support of custom matchers and/or extension libraries that hide its use from examples. Scenario: `subject` exposed in top level group Given a file named "top_level_subject_spec.rb" with: """ruby RSpec.describe Array do it "should be empty when first created" do expect(subject).to be_empty end end """ When I run `rspec ./top_level_subject_spec.rb` Then the examples should all pass Scenario: `subject` in a nested group Given a file named "nested_subject_spec.rb" with: """ruby RSpec.describe Array do describe "when first created" do it "should be empty" do expect(subject).to be_empty end end end """ When I run `rspec nested_subject_spec.rb` Then the examples should all pass Scenario: `subject` in a nested group with a different class (innermost wins) Given a file named "nested_subject_spec.rb" with: """ruby class ArrayWithOneElement < Array def initialize(*) super unshift "first element" end end RSpec.describe Array do describe ArrayWithOneElement do context "referenced as subject" do it "contains one element" do expect(subject).to include("first element") end end end end """ When I run `rspec nested_subject_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/subject/one_liner_syntax.feature0000664000000000000000000000515414557677674027100 0ustar rootroot@oneliner-should Feature: One-liner syntax RSpec supports a one-liner syntax for setting an expectation on the `subject`. RSpec will give the examples a doc string that is auto- generated from the matcher used in the example. This is designed specifically to help avoid duplication in situations where the doc string and the matcher used in the example mirror each other exactly. When used excessively, it can produce documentation output that does not read well or contribute to understanding the object you are describing. This comes in two flavors: * `is_expected` is defined simply as `expect(subject)` and is designed for when you are using rspec-expectations with its newer expect-based syntax. * `should` was designed back when rspec-expectations only had a should-based syntax. However, it continues to be available and work even if the `:should` syntax is disabled (since that merely removes `Object#should` but this is `RSpec::Core::ExampleGroup#should`). Notes: * This feature is only available when using rspec-expectations. * Examples defined using this one-liner syntax cannot be directly selected from the command line using the [`--example` option](../command-line/example-option). * The one-liner syntax only works with non-block expectations (e.g. `expect(obj).to eq`, etc) and it cannot be used with block expectations (e.g. `expect { object }`). Scenario: Implicit subject Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do describe "when first created" do # Rather than: # it "should be empty" do # subject.should be_empty # end it { should be_empty } # or it { is_expected.to be_empty } end end """ When I run `rspec example_spec.rb --format doc` Then the examples should all pass And the output should contain: """ Array when first created is expected to be empty is expected to be empty """ Scenario: Explicit subject Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do describe "with 3 items" do subject { [1,2,3] } it { should_not be_empty } # or it { is_expected.not_to be_empty } end end """ When I run `rspec example_spec.rb --format doc` Then the examples should all pass And the output should contain: """ Array with 3 items is expected not to be empty is expected not to be empty """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/subject/explicit_subject.feature0000664000000000000000000001506314557677674027060 0ustar rootrootFeature: Explicit Subject Use `subject` in the group scope to explicitly define the value that is returned by the `subject` method in the example scope. Note that while the examples below demonstrate how the `subject` helper can be used as a user-facing concept, we recommend that you reserve it for support of custom matchers and/or extension libraries that hide its use from examples. A named `subject` improves on the explicit `subject` by assigning it a contextually semantic name. Since a named `subject` is an explicit `subject`, it still defines the value that is returned by the `subject` method in the example scope. However, it defines an additional helper method with the provided name. This helper method is memoized. The value is cached across multiple calls in the same example but not across examples. We recommend using the named helper method over `subject` in examples. For more information about declaring a `subject` see the [API docs](http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/MemoizedHelpers/ClassMethods#subject-instance_method). Scenario: A `subject` can be defined and used in the top level group scope Given a file named "top_level_subject_spec.rb" with: """ruby RSpec.describe Array, "with some elements" do subject { [1, 2, 3] } it "has the prescribed elements" do expect(subject).to eq([1, 2, 3]) end end """ When I run `rspec top_level_subject_spec.rb` Then the examples should all pass Scenario: The `subject` defined in an outer group is available to inner groups Given a file named "nested_subject_spec.rb" with: """ruby RSpec.describe Array do subject { [1, 2, 3] } describe "has some elements" do it "which are the prescribed elements" do expect(subject).to eq([1, 2, 3]) end end end """ When I run `rspec nested_subject_spec.rb` Then the examples should all pass Scenario: The `subject` is memoized within an example but not across examples **Note:** This scenario shows mutation being performed in a `subject` definition block. This behavior is generally discouraged as it makes it more difficult to understand the specs. This is technique is used simply as a tool to demonstrate how the memoization occurs. Given a file named "memoized_subject_spec.rb" with: """ruby RSpec.describe Array do # This uses a context local variable. As you can see from the # specs, it can mutate across examples. Use with caution. element_list = [1, 2, 3] subject { element_list.pop } it "is memoized across calls (i.e. the block is invoked once)" do expect { 3.times { subject } }.to change{ element_list }.from([1, 2, 3]).to([1, 2]) expect(subject).to eq(3) end it "is not memoized across examples" do expect{ subject }.to change{ element_list }.from([1, 2]).to([1]) expect(subject).to eq(2) end end """ When I run `rspec memoized_subject_spec.rb` Then the examples should all pass Scenario: The `subject` is available in `before` hooks Given a file named "before_hook_subject_spec.rb" with: """ruby RSpec.describe Array, "with some elements" do subject { [] } before { subject.push(1, 2, 3) } it "has the prescribed elements" do expect(subject).to eq([1, 2, 3]) end end """ When I run `rspec before_hook_subject_spec.rb` Then the examples should all pass Scenario: Helper methods can be invoked from a `subject` definition block Given a file named "helper_subject_spec.rb" with: """ruby RSpec.describe Array, "with some elements" do def prepared_array [1, 2, 3] end subject { prepared_array } it "has the prescribed elements" do expect(subject).to eq([1, 2, 3]) end end """ When I run `rspec helper_subject_spec.rb` Then the examples should all pass Scenario: Use the `subject!` bang method to call the definition block before the example Given a file named "subject_bang_spec.rb" with: """ruby RSpec.describe "eager loading with subject!" do subject! { element_list.push(99) } let(:element_list) { [1, 2, 3] } it "calls the definition block before the example" do element_list.push(5) expect(element_list).to eq([1, 2, 3, 99, 5]) end end """ When I run `rspec subject_bang_spec.rb` Then the examples should all pass Scenario: Use `subject(:name)` to define a memoized helper method **Note:** While a global variable is used in the examples below, this behavior is strongly discouraged in actual specs. It is used here simply to demonstrate the value will be cached across multiple calls in the same example but not across examples. Given a file named "named_subject_spec.rb" with: """ruby $count = 0 RSpec.describe "named subject" do subject(:global_count) { $count += 1 } it "is memoized across calls (i.e. the block is invoked once)" do expect { 2.times { global_count } }.not_to change{ global_count }.from(1) end it "is not cached across examples" do expect(global_count).to eq(2) end it "is still available using the subject method" do expect(subject).to eq(3) end it "works with the one-liner syntax" do is_expected.to eq(4) end it "the subject and named helpers return the same object" do expect(global_count).to be(subject) end it "is set to the block return value (i.e. the global $count)" do expect(global_count).to be($count) end end """ When I run `rspec named_subject_spec.rb` Then the examples should all pass Scenario: Use `subject!(:name)` to define a helper method called before the example Given a file named "named_subject_bang_spec.rb" with: """ruby RSpec.describe "eager loading using a named subject!" do subject!(:updated_list) { element_list.push(99) } let(:element_list) { [1, 2, 3] } it "calls the definition block before the example" do element_list.push(5) expect(element_list).to eq([1, 2, 3, 99, 5]) expect(updated_list).to be(element_list) end end """ When I run `rspec named_subject_bang_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/helper_methods/0000775000000000000000000000000014557677674023501 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/helper_methods/arbitrary_methods.feature0000664000000000000000000000225014557677674030577 0ustar rootrootFeature: Defining arbitrary helper methods You can define methods in any example group using Ruby's `def` keyword or `define_method` method. These _helper_ methods are exposed to examples in the group in which they are defined and groups nested within that group, but not parent or sibling groups. Scenario: Use a method defined in the same group Given a file named "example_spec.rb" with: """ruby RSpec.describe "an example" do def help :available end it "has access to methods defined in its group" do expect(help).to be(:available) end end """ When I run `rspec example_spec.rb` Then the examples should all pass Scenario: Use a method defined in a parent group Given a file named "example_spec.rb" with: """ruby RSpec.describe "an example" do def help :available end describe "in a nested group" do it "has access to methods defined in its parent group" do expect(help).to be(:available) end end end """ When I run `rspec example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/helper_methods/modules.feature0000664000000000000000000001236314557677674026533 0ustar rootrootFeature: Define helper methods in a module You can define helper methods in a module and include it in your example groups using the `config.include` configuration option. `config.extend` can be used to extend the module onto your example groups so that the methods in the module are available in the example groups themselves (but not in the actual examples). You can also `include` or `extend` the module onto only certain example groups by passing a metadata hash as the last argument. Only groups that match the given metadata will `include` or `extend` the module. You can also specify metadata using only symbols. Note that examples that match a `config.include` module's metadata will also have the module included. RSpec treats every example as having a singleton example group (analogous to Ruby's singleton classes) containing just the one example. Background: Given a file named "helpers.rb" with: """ruby module Helpers def help :available end end """ Scenario: Include a module in all example groups Given a file named "include_module_spec.rb" with: """ruby require './helpers' RSpec.configure do |c| c.include Helpers end RSpec.describe "an example group" do it "has access to the helper methods defined in the module" do expect(help).to be(:available) end end """ When I run `rspec include_module_spec.rb` Then the examples should all pass Scenario: Extend a module in all example groups Given a file named "extend_module_spec.rb" with: """ruby require './helpers' RSpec.configure do |c| c.extend Helpers end RSpec.describe "an example group" do puts "Help is #{help}" it "does not have access to the helper methods defined in the module" do expect { help }.to raise_error(NameError) end end """ When I run `rspec extend_module_spec.rb` Then the examples should all pass And the output should contain "Help is available" Scenario: Include a module in only some example groups Given a file named "include_module_in_some_groups_spec.rb" with: """ruby require './helpers' RSpec.configure do |c| c.include Helpers, :foo => :bar end RSpec.describe "an example group with matching metadata", :foo => :bar do it "has access to the helper methods defined in the module" do expect(help).to be(:available) end end RSpec.describe "an example group without matching metadata" do it "does not have access to the helper methods defined in the module" do expect { help }.to raise_error(NameError) end it "does have access when the example has matching metadata", :foo => :bar do expect(help).to be(:available) end end """ When I run `rspec include_module_in_some_groups_spec.rb` Then the examples should all pass Scenario: Extend a module in only some example groups Given a file named "extend_module_in_only_some_groups_spec.rb" with: """ruby require './helpers' RSpec.configure do |c| c.extend Helpers, :foo => :bar end RSpec.describe "an example group with matching metadata", :foo => :bar do puts "In a matching group, help is #{help}" it "does not have access to the helper methods defined in the module" do expect { help }.to raise_error(NameError) end end RSpec.describe "an example group without matching metadata" do puts "In a non-matching group, help is #{help rescue 'not available'}" it "does not have access to the helper methods defined in the module" do expect { help }.to raise_error(NameError) end end """ When I run `rspec extend_module_in_only_some_groups_spec.rb` Then the examples should all pass And the output should contain "In a matching group, help is available" And the output should contain "In a non-matching group, help is not available" Scenario: Use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: """ruby require './helpers' RSpec.configure do |c| c.include Helpers, :include_helpers c.extend Helpers, :extend_helpers end RSpec.describe "an example group with matching include metadata", :include_helpers do puts "In a group not matching the extend filter, help is #{help rescue 'not available'}" it "has access to the helper methods defined in the module" do expect(help).to be(:available) end end RSpec.describe "an example group with matching extend metadata", :extend_helpers do puts "In a group matching the extend filter, help is #{help}" it "does not have access to the helper methods defined in the module" do expect { help }.to raise_error(NameError) end end """ When I run `rspec symbols_as_metadata_spec.rb` Then the examples should all pass And the output should contain "In a group not matching the extend filter, help is not available" And the output should contain "In a group matching the extend filter, help is available" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/helper_methods/let.feature0000664000000000000000000000313514557677674025644 0ustar rootrootFeature: `let` and `let!` Use `let` to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples. Note that `let` is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can use `let!` to force the method's invocation before each example. By default, `let` is threadsafe, but you can configure it not to be by disabling `config.threadsafe`, which makes `let` perform a bit faster. Scenario: Use `let` to define memoized helper method Given a file named "let_spec.rb" with: """ruby $count = 0 RSpec.describe "let" do let(:count) { $count += 1 } it "memoizes the value" do expect(count).to eq(1) expect(count).to eq(1) end it "is not cached across examples" do expect(count).to eq(2) end end """ When I run `rspec let_spec.rb` Then the examples should all pass Scenario: Use `let!` to define a memoized helper method that is called in a `before` hook Given a file named "let_bang_spec.rb" with: """ruby $count = 0 RSpec.describe "let!" do invocation_order = [] let!(:count) do invocation_order << :let! $count += 1 end it "calls the helper method in a before hook" do invocation_order << :example expect(invocation_order).to eq([:let!, :example]) expect(count).to eq(1) end end """ When I run `rspec let_bang_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/hooks/0000775000000000000000000000000014557677674021622 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/hooks/when_first_matching_example_defined.feature0000664000000000000000000000413414557677674032414 0ustar rootrootFeature: Using `when_first_matching_example_defined` hook In large projects that use RSpec, it's common to have some expensive setup logic that is only needed when certain kinds of specs have been loaded. If that kind of spec has not been loaded, you'd prefer to avoid the cost of doing the setup. The `when_first_matching_example_defined` hook makes it easy to conditionally perform some logic when the first example is defined with matching metadata, allowing you to ensure the necessary setup is performed only when needed. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.when_first_matching_example_defined(:db) do require "support/db" end end """ And a file named "spec/support/db.rb" with: """ruby RSpec.configure do |config| config.before(:suite) do puts "Bootstrapped the DB." end config.around(:example, :db) do |example| puts "Starting a DB transaction." example.run puts "Rolling back a DB transaction." end end """ And a file named ".rspec" with: """ --require spec_helper """ And a file named "spec/unit_spec.rb" with: """ RSpec.describe "A unit spec" do it "does not require a database" do puts "in unit example" end end """ And a file named "spec/integration_spec.rb" with: """ RSpec.describe "An integration spec", :db do it "requires a database" do puts "in integration example" end end """ Scenario: Running the entire suite loads the DB setup When I run `rspec` Then it should pass with: """ Bootstrapped the DB. Starting a DB transaction. in integration example Rolling back a DB transaction. .in unit example . """ Scenario: Running just the unit spec does not load the DB setup When I run `rspec spec/unit_spec.rb` Then the examples should all pass And the output should not contain "DB" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/hooks/around_hooks.feature0000664000000000000000000002472614557677674025705 0ustar rootrootFeature: `around` hooks `around` hooks receive the example as a block argument, extended to behave as a proc. This lets you define code that should be executed before and after the example. Of course, you can do the same thing with `before` and `after` hooks; and it's often cleaner to do so. Where `around` hooks shine is when you want to run an example within a block. For instance, if your database library offers a transaction method that receives a block, you can use an `around` to cleanly open and close the transaction around the example. **WARNING:** `around` hooks do not share state with the example the way `before` and `after` hooks do. This means that you cannot share instance variables between `around` hooks and examples. **WARNING:** Mock frameworks are set up and torn down within the context of running the example. You cannot interact with them directly in `around` hooks. **WARNING:** `around` hooks will execute *before* any `before` hooks, and *after* any `after` hooks regardless of the context they were defined in. Scenario: Use the example as a proc within the block passed to `around()` Given a file named "example_spec.rb" with: """ruby class Database def self.transaction puts "open transaction" yield puts "close transaction" end end RSpec.describe "around filter" do around(:example) do |example| Database.transaction(&example) end it "gets run in order" do puts "run the example" end end """ When I run `rspec example_spec.rb` Then the output should contain: """ open transaction run the example close transaction """ Scenario: Invoke the example using `run()` Given a file named "example_spec.rb" with: """ruby RSpec.describe "around hook" do around(:example) do |example| puts "around example before" example.run puts "around example after" end it "gets run in order" do puts "in the example" end end """ When I run `rspec example_spec.rb` Then the output should contain: """ around example before in the example around example after """ Scenario: Access the example metadata Given a file named "example_spec.rb" with: """ruby RSpec.describe "something" do around(:example) do |example| puts example.metadata[:foo] example.run end it "does something", :foo => "this should show up in the output" do end end """ When I run `rspec example_spec.rb` Then the output should contain "this should show up in the output" Scenario: An around hook continues to run even if the example throws an exception Given a file named "example_spec.rb" with: """ruby RSpec.describe "something" do around(:example) do |example| puts "around example setup" example.run puts "around example cleanup" end it "still executes the entire around hook" do fail "the example blows up" end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain: """ around example setup around example cleanup """ Scenario: Define a global `around` hook Given a file named "example_spec.rb" with: """ruby RSpec.configure do |c| c.around(:example) do |example| puts "around example before" example.run puts "around example after" end end RSpec.describe "around filter" do it "gets run in order" do puts "in the example" end end """ When I run `rspec example_spec.rb` Then the output should contain: """ around example before in the example around example after """ Scenario: Per example hooks are wrapped by the `around` hook Given a file named "example_spec.rb" with: """ruby RSpec.describe "around filter" do around(:example) do |example| puts "around example before" example.run puts "around example after" end before(:example) do puts "before example" end after(:example) do puts "after example" end it "gets run in order" do puts "in the example" end end """ When I run `rspec example_spec.rb` Then the output should contain: """ around example before before example in the example after example around example after """ Scenario: Context hooks are NOT wrapped by the `around` hook Given a file named "example_spec.rb" with: """ruby RSpec.describe "around filter" do around(:example) do |example| puts "around example before" example.run puts "around example after" end before(:context) do puts "before context" end after(:context) do puts "after context" end it "gets run in order" do puts "in the example" end end """ When I run `rspec --format progress example_spec.rb` Then the output should contain: """ before context around example before in the example around example after .after context """ Scenario: Examples run by an `around` block are run in the configured context Given a file named "example_spec.rb" with: """ruby module IncludedInConfigureBlock def included_in_configure_block; true; end end RSpec.configure do |c| c.include IncludedInConfigureBlock end RSpec.describe "around filter" do around(:example) do |example| example.run end it "runs the example in the correct context" do expect(included_in_configure_block).to be(true) end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failure" Scenario: Implicitly pending examples are detected as Not yet implemented Given a file named "example_spec.rb" with: """ruby RSpec.describe "implicit pending example" do around(:example) do |example| example.run end it "should be detected as Not yet implemented" end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) implicit pending example should be detected as Not yet implemented # Not yet implemented # ./example_spec.rb:6 """ Scenario: Explicitly pending examples are detected as pending Given a file named "example_spec.rb" with: """ruby RSpec.describe "explicit pending example" do around(:example) do |example| example.run end it "should be detected as pending" do pending fail end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failures, 1 pending" And the output should contain: """ Pending: (Failures listed here are expected and do not affect your suite's status) 1) explicit pending example should be detected as pending # No reason given """ Scenario: Multiple `around` hooks in the same scope Given a file named "example_spec.rb" with: """ruby RSpec.describe "if there are multiple around hooks in the same scope" do around(:example) do |example| puts "first around hook before" example.run puts "first around hook after" end around(:example) do |example| puts "second around hook before" example.run puts "second around hook after" end it "they should all be run" do puts "in the example" expect(1).to eq(1) end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failure" And the output should contain: """ first around hook before second around hook before in the example second around hook after first around hook after """ Scenario: `around` hooks in multiple scopes Given a file named "example_spec.rb" with: """ruby RSpec.describe "if there are around hooks in an outer scope" do around(:example) do |example| puts "first outermost around hook before" example.run puts "first outermost around hook after" end around(:example) do |example| puts "second outermost around hook before" example.run puts "second outermost around hook after" end describe "outer scope" do around(:example) do |example| puts "first outer around hook before" example.run puts "first outer around hook after" end around(:example) do |example| puts "second outer around hook before" example.run puts "second outer around hook after" end describe "inner scope" do around(:example) do |example| puts "first inner around hook before" example.run puts "first inner around hook after" end around(:example) do |example| puts "second inner around hook before" example.run puts "second inner around hook after" end it "they should all be run" do puts "in the example" end end end end """ When I run `rspec example_spec.rb` Then the output should contain "1 example, 0 failure" And the output should contain: """ first outermost around hook before second outermost around hook before first outer around hook before second outer around hook before first inner around hook before second inner around hook before in the example second inner around hook after first inner around hook after second outer around hook after first outer around hook after second outermost around hook after first outermost around hook after """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/hooks/before_and_after_hooks.feature0000664000000000000000000003075514557677674027661 0ustar rootrootFeature: `before` and `after` hooks Use `before` and `after` hooks to execute arbitrary code before and/or after the body of an example is run: ```ruby before(:example) # run before each example before(:context) # run one time only, before all of the examples in a group after(:example) # run after each example after(:context) # run one time only, after all of the examples in a group ``` `before` and `after` blocks are called in the following order: ```ruby before :suite before :context before :example after :example after :context after :suite ``` A bare `before` or `after` hook defaults to the `:example` scope. `before` and `after` hooks can be defined directly in the example groups they should run in, or in a global `RSpec.configure` block. Note that the status of the example does not affect the hooks. **WARNING:** Setting instance variables are not supported in `before(:suite)`. **WARNING:** Mocks are only supported in `before(:example)`. **WARNING:** `around` hooks will execute *before* any `before` hooks, and *after* any `after` hooks regardless of the context they were defined in. Note: the `:example` and `:context` scopes are also available as `:each` and `:all`, respectively. Use whichever you prefer. Scenario: Define `before(:example)` block Given a file named "before_example_spec.rb" with: """ruby require "rspec/expectations" class Thing def widgets @widgets ||= [] end end RSpec.describe Thing do before(:example) do @thing = Thing.new end describe "initialized in before(:example)" do it "has 0 widgets" do expect(@thing.widgets.count).to eq(0) end it "can accept new widgets" do @thing.widgets << Object.new end it "does not share state across examples" do expect(@thing.widgets.count).to eq(0) end end end """ When I run `rspec before_example_spec.rb` Then the examples should all pass Scenario: Define `before(:context)` block in example group Given a file named "before_context_spec.rb" with: """ruby require "rspec/expectations" class Thing def widgets @widgets ||= [] end end RSpec.describe Thing do before(:context) do @thing = Thing.new end describe "initialized in before(:context)" do it "has 0 widgets" do expect(@thing.widgets.count).to eq(0) end it "can accept new widgets" do @thing.widgets << Object.new end it "shares state across examples" do expect(@thing.widgets.count).to eq(1) end end end """ When I run `rspec before_context_spec.rb` Then the examples should all pass When I run `rspec before_context_spec.rb:15` Then the examples should all pass Scenario: Failure in `before(:context)` block Given a file named "before_context_spec.rb" with: """ruby RSpec.describe "an error in before(:context)" do before(:context) do raise "oops" end it "fails this example" do end it "fails this example, too" do end after(:context) do puts "after context ran" end describe "nested group" do it "fails this third example" do end it "fails this fourth example" do end describe "yet another level deep" do it "fails this last example" do end end end end """ When I run `rspec before_context_spec.rb --format documentation` Then the output should contain "5 examples, 5 failures" And the output should contain: """ an error in before(:context) fails this example (FAILED - 1) fails this example, too (FAILED - 2) nested group fails this third example (FAILED - 3) fails this fourth example (FAILED - 4) yet another level deep fails this last example (FAILED - 5) after context ran """ When I run `rspec before_context_spec.rb:9 --format documentation` Then the output should contain "1 example, 1 failure" And the output should contain: """ an error in before(:context) fails this example, too (FAILED - 1) """ Scenario: Failure in `after(:context)` block Given a file named "after_context_spec.rb" with: """ruby RSpec.describe "an error in after(:context)" do after(:context) do raise StandardError.new("Boom!") end it "passes this example" do end it "passes this example, too" do end end """ When I run `rspec after_context_spec.rb` Then it should fail with: """ An error occurred in an `after(:context)` hook. Failure/Error: raise StandardError.new("Boom!") StandardError: Boom! # ./after_context_spec.rb:3 """ Scenario: A failure in an example does not affect hooks Given a file named "failure_in_example_spec.rb" with: """ruby RSpec.describe "a failing example does not affect hooks" do before(:context) { puts "before context runs" } before(:example) { puts "before example runs" } after(:example) { puts "after example runs" } after(:context) { puts "after context runs" } it "fails the example but runs the hooks" do raise "An Error" end end """ When I run `rspec failure_in_example_spec.rb` Then it should fail with: """ before context runs before example runs after example runs Fafter context runs """ Scenario: Define `before` and `after` blocks in configuration Given a file named "befores_in_configuration_spec.rb" with: """ruby require "rspec/expectations" RSpec.configure do |config| config.before(:example) do @before_example = "before example" end config.before(:context) do @before_context = "before context" end end RSpec.describe "stuff in before blocks" do describe "with :context" do it "should be available in the example" do expect(@before_context).to eq("before context") end end describe "with :example" do it "should be available in the example" do expect(@before_example).to eq("before example") end end end """ When I run `rspec befores_in_configuration_spec.rb` Then the examples should all pass Scenario: `before`/`after` blocks are run in order Given a file named "ensure_block_order_spec.rb" with: """ruby require "rspec/expectations" RSpec.describe "before and after callbacks" do before(:context) do puts "before context" end before(:example) do puts "before example" end before do puts "also before example but by default" end after(:example) do puts "after example" end after do puts "also after example but by default" end after(:context) do puts "after context" end it "gets run in order" do end end """ When I run `rspec --format progress ensure_block_order_spec.rb` Then the output should contain: """ before context before example also before example but by default also after example but by default after example .after context """ Scenario: `before`/`after` blocks defined in configuration are run in order Given a file named "configuration_spec.rb" with: """ruby require "rspec/expectations" RSpec.configure do |config| config.before(:suite) do puts "before suite" end config.before(:context) do puts "before context" end config.before(:example) do puts "before example" end config.after(:example) do puts "after example" end config.after(:context) do puts "after context" end config.after(:suite) do puts "after suite" end end RSpec.describe "ignore" do example "ignore" do end end """ When I run `rspec --format progress configuration_spec.rb` Then the output should contain: """ before suite before context before example after example .after context after suite """ Scenario: `before`/`after` context blocks are run once Given a file named "before_and_after_context_spec.rb" with: """ruby RSpec.describe "before and after callbacks" do before(:context) do puts "outer before context" end example "in outer group" do end after(:context) do puts "outer after context" end describe "nested group" do before(:context) do puts "inner before context" end example "in nested group" do end after(:context) do puts "inner after context" end end end """ When I run `rspec --format progress before_and_after_context_spec.rb` Then the examples should all pass And the output should contain: """ outer before context .inner before context .inner after context outer after context """ When I run `rspec --format progress before_and_after_context_spec.rb:14` Then the examples should all pass And the output should contain: """ outer before context inner before context .inner after context outer after context """ When I run `rspec --format progress before_and_after_context_spec.rb:6` Then the examples should all pass And the output should contain: """ outer before context .outer after context """ Scenario: Nested examples have access to state set in outer `before(:context)` Given a file named "before_context_spec.rb" with: """ruby RSpec.describe "something" do before :context do @value = 123 end describe "nested" do it "access state set in before(:context)" do expect(@value).to eq(123) end describe "nested more deeply" do it "access state set in before(:context)" do expect(@value).to eq(123) end end end describe "nested in parallel" do it "access state set in before(:context)" do expect(@value).to eq(123) end end end """ When I run `rspec before_context_spec.rb` Then the examples should all pass Scenario: `before`/`after` context blocks have access to state Given a file named "before_and_after_context_spec.rb" with: """ruby RSpec.describe "before and after callbacks" do before(:context) do @outer_state = "set in outer before context" end example "in outer group" do expect(@outer_state).to eq("set in outer before context") end describe "nested group" do before(:context) do @inner_state = "set in inner before context" end example "in nested group" do expect(@outer_state).to eq("set in outer before context") expect(@inner_state).to eq("set in inner before context") end after(:context) do expect(@inner_state).to eq("set in inner before context") end end after(:context) do expect(@outer_state).to eq("set in outer before context") end end """ When I run `rspec before_and_after_context_spec.rb` Then the examples should all pass Scenario: Exception in `before(:example)` is captured and reported as failure Given a file named "error_in_before_example_spec.rb" with: """ruby RSpec.describe "error in before(:example)" do before(:example) do raise "this error" end it "is reported as failure" do end end """ When I run `rspec error_in_before_example_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "this error" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/hooks/filtering.feature0000664000000000000000000003337714557677674025177 0ustar rootrootFeature: Filtering `before`, `after`, and `around` hooks defined in the block passed to `RSpec.configure` can be constrained to specific examples and/or groups using metadata as a filter. ```ruby RSpec.configure do |c| c.before(:example, :type => :model) do end end RSpec.describe "something", :type => :model do end ``` Note that filtered `:context` hooks will still be applied to individual examples with matching metadata -- in effect, every example has a singleton example group containing just the one example (analogous to Ruby's singleton classes). You can also specify metadata using only symbols. Scenario: Filter `before(:example)` hooks using arbitrary metadata Given a file named "filter_before_example_hooks_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo => :bar) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without matching metadata" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "runs the hook for an example with matching metadata", :foo => :bar do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata", :foo => :bar do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_before_example_hooks_spec.rb` Then the examples should all pass Scenario: Filter `after(:example)` hooks using arbitrary metadata Given a file named "filter_after_example_hooks_spec.rb" with: """ruby RSpec.configure do |config| config.after(:example, :foo => :bar) do raise "boom!" end end RSpec.describe "a filtered after :example hook" do describe "group without matching metadata" do it "does not run the hook" do # should pass end it "runs the hook for an example with matching metadata", :foo => :bar do # should fail end end describe "group with matching metadata", :foo => :bar do it "runs the hook" do # should fail end end end """ When I run `rspec filter_after_example_hooks_spec.rb` Then the output should contain "3 examples, 2 failures" Scenario: Filter `around(:example)` hooks using arbitrary metadata Given a file named "filter_around_example_hooks_spec.rb" with: """ruby RSpec.configure do |config| config.around(:example, :foo => :bar) do |example| order << :before_around_example_foo_bar example.run expect(order).to eq([:before_around_example_foo_bar, :example]) end end RSpec.describe "a filtered around(:example) hook" do let(:order) { [] } describe "a group without matching metadata" do it "does not run the hook" do expect(order).to be_empty end it "runs the hook for an example with matching metadata", :foo => :bar do expect(order).to eq([:before_around_example_foo_bar]) order << :example end end describe "a group with matching metadata", :foo => :bar do it "runs the hook for an example with matching metadata", :foo => :bar do expect(order).to eq([:before_around_example_foo_bar]) order << :example end end end """ When I run `rspec filter_around_example_hooks_spec.rb` Then the examples should all pass Scenario: Filter `before(:context)` hooks using arbitrary metadata Given a file named "filter_before_context_hooks_spec.rb" with: """ruby RSpec.configure do |config| config.before(:context, :foo => :bar) { @hook = :before_context_foo_bar } end RSpec.describe "a filtered before(:context) hook" do describe "a group without matching metadata" do it "does not run the hook" do expect(@hook).to be_nil end it "runs the hook for a single example with matching metadata", :foo => :bar do expect(@hook).to eq(:before_context_foo_bar) end describe "a nested subgroup with matching metadata", :foo => :bar do it "runs the hook" do expect(@hook).to eq(:before_context_foo_bar) end end end describe "a group with matching metadata", :foo => :bar do it "runs the hook" do expect(@hook).to eq(:before_context_foo_bar) end describe "a nested subgroup" do it "runs the hook" do expect(@hook).to eq(:before_context_foo_bar) end end end end """ When I run `rspec filter_before_context_hooks_spec.rb` Then the examples should all pass Scenario: Filter `after(:context)` hooks using arbitrary metadata Given a file named "filter_after_context_hooks_spec.rb" with: """ruby example_msgs = [] RSpec.configure do |config| config.after(:context, :foo => :bar) do puts "after :context" end end RSpec.describe "a filtered after(:context) hook" do describe "a group without matching metadata" do it "does not run the hook" do puts "unfiltered" end it "runs the hook for a single example with matching metadata", :foo => :bar do puts "filtered 1" end end describe "a group with matching metadata", :foo => :bar do it "runs the hook" do puts "filtered 2" end end describe "another group without matching metadata" do describe "a nested subgroup with matching metadata", :foo => :bar do it "runs the hook" do puts "filtered 3" end end end end """ When I run `rspec --format progress filter_after_context_hooks_spec.rb --order defined` Then the examples should all pass And the output should contain: """ unfiltered .filtered 1 after :context .filtered 2 .after :context filtered 3 .after :context """ Scenario: Use symbols as metadata Given a file named "less_verbose_metadata_filter.rb" with: """ruby RSpec.configure do |c| c.before(:example, :before_example) { puts "before example" } c.after(:example, :after_example) { puts "after example" } c.around(:example, :around_example) do |example| puts "around example (before)" example.run puts "around example (after)" end c.before(:context, :before_context) { puts "before context" } c.after(:context, :after_context) { puts "after context" } end RSpec.describe "group 1", :before_context, :after_context do it("") { puts "example 1" } it("", :before_example) { puts "example 2" } it("", :after_example) { puts "example 3" } it("", :around_example) { puts "example 4" } end """ When I run `rspec --format progress less_verbose_metadata_filter.rb` Then the examples should all pass And the output should contain: """ before context example 1 .before example example 2 .example 3 after example .around example (before) example 4 around example (after) .after context """ Scenario: Filtering hooks using symbols Given a file named "filter_example_hooks_with_symbol_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without a matching metadata key" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "does not run the hook for an example with metadata hash containing the key with a falsey value", :foo => nil do expect(invoked_hooks).to be_empty end it "runs the hook for an example with metadata hash containing the key with a truthy value", :foo => :bar do expect(invoked_hooks).to eq([:before_example_foo_bar]) end it "runs the hook for an example with only the key defined", :foo do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata key", :foo do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_example_hooks_with_symbol_spec.rb` Then the examples should all pass Scenario: Filtering hooks using a hash Given a file named "filter_example_hooks_with_hash_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo => { :bar => :baz, :slow => true }) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without matching metadata" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "does not run the hook for an example if only part of the filter matches", :foo => { :bar => :baz } do expect(invoked_hooks).to be_empty end it "runs the hook for an example if the metadata contains all key value pairs from the filter", :foo => { :bar => :baz, :slow => true, :extra => :pair } do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata", :foo => { :bar => :baz, :slow => true } do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_example_hooks_with_hash_spec.rb` Then the examples should all pass Scenario: Filtering hooks using a Proc Given a file named "filter_example_hooks_with_proc_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo => Proc.new { |value| value.is_a?(String) } ) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without matching metadata" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "does not run the hook if the proc returns false", :foo => :bar do expect(invoked_hooks).to be_empty end it "runs the hook if the proc returns true", :foo => 'bar' do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata", :foo => 'bar' do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_example_hooks_with_proc_spec.rb` Then the examples should all pass Scenario: Filtering hooks using a regular expression Given a file named "filter_example_hooks_with_regexp_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo => /bar/ ) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without matching metadata" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "does not run the hook if the value does not match", :foo => 'baz' do expect(invoked_hooks).to be_empty end it "runs the hook if the value matches", :foo => 'bar' do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata", :foo => 'bar' do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_example_hooks_with_regexp_spec.rb` Then the examples should all pass Scenario: Filtering hooks using string comparison Given a file named "filter_example_hooks_with_strcmp_spec.rb" with: """ruby RSpec.configure do |config| config.before(:example, :foo => :bar ) do invoked_hooks << :before_example_foo_bar end end RSpec.describe "a filtered before :example hook" do let(:invoked_hooks) { [] } describe "group without matching metadata" do it "does not run the hook" do expect(invoked_hooks).to be_empty end it "does not run the hook if the coerced values do not match", :foo => 'baz' do expect(invoked_hooks).to be_empty end it "runs the hook if the coerced values match", :foo => 'bar' do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end describe "group with matching metadata", :foo => 'bar' do it "runs the hook" do expect(invoked_hooks).to eq([:before_example_foo_bar]) end end end """ When I run `rspec filter_example_hooks_with_strcmp_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/0000775000000000000000000000000014557677674023346 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/overriding_global_ordering.feature0000664000000000000000000000522514557677674032310 0ustar rootrootFeature: Overriding global ordering You can customize how RSpec orders examples and example groups. For an individual group, you can control it by tagging it with `:order` metadata: * `:defined` runs the examples (and sub groups) in defined order * `:random` runs them in random order If you have more specialized needs, you can register your own ordering using the `register_ordering` configuration option. If you register an ordering as `:global`, it will be the global default, used by all groups that do not have `:order` metadata (and by RSpec to order the top-level groups). Scenario: Running a specific example group in order Given a file named "order_dependent_spec.rb" with: """ruby RSpec.describe "examples only pass when they are run in order", :order => :defined do before(:context) { @list = [] } it "passes when run first" do @list << 1 expect(@list).to eq([1]) end it "passes when run second" do @list << 2 expect(@list).to eq([1, 2]) end it "passes when run third" do @list << 3 expect(@list).to eq([1, 2, 3]) end end """ When I run `rspec order_dependent_spec.rb --order random:1` Then the examples should all pass Scenario: Registering a custom ordering Given a file named "register_custom_ordering_spec.rb" with: """ruby RSpec.configure do |rspec| rspec.register_ordering(:reverse) do |items| items.reverse end end RSpec.describe "A group that must run in reverse order", :order => :reverse do before(:context) { @list = [] } it "passes when run second" do @list << 2 expect(@list).to eq([1, 2]) end it "passes when run first" do @list << 1 expect(@list).to eq([1]) end end """ When I run `rspec register_custom_ordering_spec.rb` Then the examples should all pass Scenario: Using a custom global ordering Given a file named "register_global_ordering_spec.rb" with: """ruby RSpec.configure do |rspec| rspec.register_ordering(:global) do |items| items.reverse end end RSpec.describe "A group without :order metadata" do before(:context) { @list = [] } it "passes when run second" do @list << 2 expect(@list).to eq([1, 2]) end it "passes when run first" do @list << 1 expect(@list).to eq([1]) end end """ When I run `rspec register_global_ordering_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/fail_fast.feature0000664000000000000000000000522014557677674026652 0ustar rootrootFeature: Setting the `fail_fast` option Use the `fail_fast` option to tell RSpec to abort the run after N failures: Scenario: `fail_fast` with no failures (runs all examples) Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure {|c| c.fail_fast = 1} """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "something" do it "passes" do end it "passes too" do end end """ When I run `rspec spec/example_spec.rb` Then the examples should all pass Scenario: `fail_fast` with first example failing (only runs the one example) Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure {|c| c.fail_fast = 1} """ And a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "fails" do fail end it "passes" do end end """ When I run `rspec spec/example_spec.rb -fd` Then the output should contain "1 example, 1 failure" Scenario: `fail_fast` with multiple files, second example failing (only runs the first two examples) Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure {|c| c.fail_fast = 1} """ And a file named "spec/example_1_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "passes" do end it "fails" do fail end end RSpec.describe "something else" do it "fails" do fail end end """ And a file named "spec/example_2_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "passes" do end end RSpec.describe "something else" do it "fails" do fail end end """ When I run `rspec spec` Then the output should contain "2 examples, 1 failure" Scenario: `fail_fast 2` with 1st and 3rd examples failing (only runs the first 3 examples) Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure {|c| c.fail_fast = 2} """ And a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "fails once" do fail end it "passes once" do end it "fails twice" do fail end it "passes" do end end """ When I run `rspec spec/example_spec.rb -fd` Then the output should contain "3 examples, 2 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/output_stream.feature0000664000000000000000000000132514557677674027637 0ustar rootrootFeature: Custom output stream Define a custom output stream (default `$stdout`). Aliases: `:output`, `:out`. ```ruby RSpec.configure { |c| c.output_stream = File.open('saved_output', 'w') } ``` Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.output_stream = File.open('saved_output', 'w') } """ Scenario: Redirecting output Given a file named "spec/example_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "an example" do it "passes" do true end end """ When I run `rspec spec/example_spec.rb` Then the file "saved_output" should contain "1 example, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/exclude_pattern.feature0000664000000000000000000000306514557677674030115 0ustar rootrootFeature: Using the `--exclude_pattern` option Use the `--exclude-pattern` option to tell RSpec to skip looking for specs in files that match the pattern specified. Background: Given a file named "spec/models/model_spec.rb" with: """ruby RSpec.describe "two specs here" do it "passes" do end it "passes too" do end end """ And a file named "spec/features/feature_spec.rb" with: """ruby RSpec.describe "only one spec" do it "passes" do end end """ Scenario: By default, RSpec runs files that match `"**/*_spec.rb"` When I run `rspec` Then the output should contain "3 examples, 0 failures" Scenario: The `--exclude-pattern` flag makes RSpec skip matching files When I run `rspec --exclude-pattern "**/models/*_spec.rb"` Then the output should contain "1 example, 0 failures" Scenario: The `--exclude-pattern` flag can be used to pass in multiple patterns, separated by comma When I run `rspec --exclude-pattern "**/models/*_spec.rb, **/features/*_spec.rb"` Then the output should contain "0 examples, 0 failures" Scenario: The `--exclude-pattern` flag accepts shell style glob unions When I run `rspec --exclude-pattern "**/{models,features}/*_spec.rb"` Then the output should contain "0 examples, 0 failures" Scenario: The `--exclude-pattern` flag can be used with the `--pattern` flag When I run `rspec --pattern "spec/**/*_spec.rb" --exclude-pattern "spec/models/*_spec.rb"` Then the output should contain "1 example, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/read_options_from_file.feature0000664000000000000000000000646014557677674031441 0ustar rootrootFeature: Reading command line configuration options from files RSpec reads command line configuration options from several different files, all conforming to a specific level of specificity. Options from a higher specificity will override conflicting options from lower specificity files. The locations are: * **Global options:** First file from the following list (i.e. the user's personal global options) * `$XDG_CONFIG_HOME/rspec/options` ([XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/) config) * `~/.rspec` * **Project options:** `./.rspec` (i.e. in the project's root directory, usually checked into the project) * **Local:** `./.rspec-local` (i.e. in the project's root directory, can be gitignored) Options specified at the command-line has even higher specificity, as does the `SPEC_OPTS` environment variable. That means that a command-line option would overwrite a project-specific option, which overrides the global value of that option. The default options files can all be ignored using the `--options` command-line argument, which selects a custom file to load options from. Scenario: Color set in `.rspec` Given a file named ".rspec" with: """ --force-color """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "color_enabled?" do context "when set with RSpec.configure" do it "is true" do expect(RSpec.configuration).to be_color_enabled end end end """ When I run `rspec ./spec/example_spec.rb` Then the examples should all pass Scenario: Custom options file Given a file named "my.options" with: """ --format documentation """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "formatter set in custom options file" do it "sets formatter" do expect(RSpec.configuration.formatters.first). to be_a(RSpec::Core::Formatters::DocumentationFormatter) end end """ When I run `rspec spec/example_spec.rb --options my.options` Then the examples should all pass Scenario: RSpec ignores `./.rspec` when custom options file is used Given a file named "my.options" with: """ --format documentation """ And a file named ".rspec" with: """ --no-color """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "custom options file" do it "causes .rspec to be ignored" do expect(RSpec.configuration.color_mode).to eq(:automatic) end end """ When I run `rspec spec/example_spec.rb --options my.options` Then the examples should all pass Scenario: Using ERB in `.rspec` Given a file named ".rspec" with: """ --format <%= true ? 'documentation' : 'progress' %> """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "formatter" do it "is set to documentation" do expect(RSpec.configuration.formatters.first). to be_an(RSpec::Core::Formatters::DocumentationFormatter) end end """ When I run `rspec ./spec/example_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/error_exit_code.feature0000664000000000000000000000253114557677674030100 0ustar rootrootFeature: Setting an error exit code Use the `error_exit_code` option to set a custom exit code when RSpec fails outside an example. ```ruby RSpec.configure { |c| c.error_exit_code = 42 } ``` Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.error_exit_code = 42 } """ Scenario: A erroring spec with the default exit code Given a file named "spec/typo_spec.rb" with: """ruby RSpec.escribe "something" do # intentional typo it "works" do true end end """ When I run `rspec spec/typo_spec.rb` Then the exit status should be 1 Scenario: A erroring spec with a custom exit code Given a file named "spec/typo_spec.rb" with: """ruby require 'spec_helper' RSpec.escribe "something" do # intentional typo it "works" do true end end """ When I run `rspec spec/typo_spec.rb` And the exit status should be 42 Scenario: Success running specs spec with a custom error exit code defined Given a file named "spec/example_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "something" do it "works" do true end end """ When I run `rspec spec/example_spec.rb` Then the exit status should be 0 ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/run_all_when_everything_filtered.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/run_all_when_everything_filtered.fe0000664000000000000000000000536714557677674032474 0ustar rootrootFeature: Using `run_all_when_everything_filtered` Note: this feature has been superseded by [`filter_run_when_matching`](../filtering/filter-run-when-matching) and will be removed in a future version of RSpec. Use the `run_all_when_everything_filtered` option to tell RSpec to run all the specs in the case where you try to run a filtered list of specs but no specs match that filter. This works well when paired with an inclusion filter like `:focus => true`, as it will run all the examples when none match the inclusion filter. ```ruby RSpec.configure { |c| c.run_all_when_everything_filtered = true } ``` Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure {|c| c.run_all_when_everything_filtered = true} """ Scenario: By default, no specs are run if they are all filtered out by an inclusion tag Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "examples" do it "with no tag" do end it "with no tag as well" do end end """ When I run `rspec spec/example_spec.rb --tag some_tag` Then the output should contain "0 examples, 0 failures" Scenario: Specs are still run if they are filtered out by an exclusion tag Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "examples" do it "with no tag" do end it "with no tag as well" do end end """ When I run `rspec spec/example_spec.rb --tag ~some_tag` Then the output should contain "2 examples, 0 failures" Scenario: When the `run_all_when_everything_filtered` option is turned on, if there are any matches for the filtering tag, only those features are run Given a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "examples" do it "with no tag", :some_tag => true do end it "with no tag as well" do end end """ When I run `rspec spec/example_spec.rb --tag some_tag` Then the output should contain "1 example, 0 failures" And the output should contain "Run options: include {:some_tag=>true}" Scenario: When the `run_all_when_everything_filtered` option is turned on, all the specs are run when the tag has no matches Given a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "examples" do it "with no tag" do end it "with no tag as well" do end end """ When I run `rspec spec/example_spec.rb --tag some_tag` Then the output should contain "2 examples, 0 failures" And the output should contain "All examples were filtered out; ignoring {:some_tag=>true}" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/default_path.feature0000664000000000000000000000231414557677674027363 0ustar rootrootFeature: Setting the default spec path You can just type `rspec` to run all specs that live in the `spec` directory. This is supported by a `--default-path` option, which is set to `spec` by default. If you prefer to keep your specs in a different directory, or assign an individual file to `--default-path`, you can do so on the command line or in a configuration file (for example `.rspec`). **NOTE:** this option is not supported on `RSpec.configuration`, as it needs to be set before spec files are loaded. Scenario: Run `rspec` with default `default-path` (`spec` directory) Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "an example" do it "passes" do end end """ When I run `rspec` Then the output should contain "1 example, 0 failures" Scenario: Run `rspec` with customized `default-path` Given a file named ".rspec" with: """ --default-path behavior """ Given a file named "behavior/example_spec.rb" with: """ruby RSpec.describe "an example" do it "passes" do end end """ When I run `rspec` Then the output should contain "1 example, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/pattern.feature0000664000000000000000000000330114557677674026375 0ustar rootrootFeature: Using the `--pattern` option Use the `pattern` option to configure RSpec to look for specs in files that match a pattern instead of the default `"**/*_spec.rb"`. ```ruby RSpec.configure { |c| c.pattern = '**/*.spec' } ``` Rather than using `require 'spec_helper'` at the top of each spec file, ensure that you have `--require spec_helper` in `.rspec`. That will always load before the pattern is resolved. With the pattern thus configured, only those spec files that match the pattern will then be loaded. Background: Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "two specs" do it "passes" do end it "passes too" do end end """ Scenario: Override the default pattern in configuration Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.pattern = '**/*.spec' end """ And a file named "spec/one_example.spec" with: """ruby RSpec.describe "something" do it "passes" do end end """ When I run `rspec -rspec_helper` Then the output should contain "1 example, 0 failures" Scenario: Append to the default pattern in configuration Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.pattern += ',**/*.spec' end """ And a file named "spec/two_examples.spec" with: """ruby RSpec.describe "something" do it "passes" do end it "passes again" do end end """ When I run `rspec -rspec_helper` Then the output should contain "4 examples, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/color.feature0000664000000000000000000000233114557677674026040 0ustar rootrootFeature: Windows may require additional solutions to display color The output uses [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) to show text in color. Windows systems (shells) often don't interpret those codes at all. If you're on Windows and you see ANSI escape codes in the output (something like `[1m [31m` ) and your text isn't in different colors, you may need to install a utility so that your Windows shell will interpret those codes correctly and show the colors. Here are some popular solutions: * [ANSICON](https://github.com/adoxa/ansicon): ANSICON runs 'on top of' cmd or powershell. This is a very popular solution. You can set it up so that it's always used whenever you use cmd or powershell, or use it only at specific times. * Alternatives to cmd.exe or powershell: [ConEmu](http://conemu.github.io/), [Console2](http://sourceforge.net/projects/console/), [ConsoleZ](https://github.com/cbucher/console) * Unix-like shells and utilities: [cygwin](https://www.cygwin.com/), [babun](http://babun.github.io/index.html), [MinGW](http://www.mingw.org/) (Minimalist GNU for Windows) To find out more, search for information about those solutions. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/profile.feature0000664000000000000000000002041314557677674026363 0ustar rootrootFeature: Profiling examples (`--profile`) The `--profile` command line option (available from `RSpec.configure` as `#profile_examples`), when set, will cause RSpec to dump out a list of your slowest examples. By default, it prints the 10 slowest examples, but you can set it to a different value to have it print more or fewer slow examples. If `--fail-fast` option is used together with `--profile` and there is a failure, slow examples are not shown. Background: Given a file named "spec/spec_helper.rb" with: """ruby """ And a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "sleeps for 0.1 seconds (example 1)" do sleep 0.1 expect(1).to eq(1) end it "sleeps for 0 seconds (example 2)" do expect(2).to eq(2) end it "sleeps for 0.15 seconds (example 3)" do sleep 0.15 expect(3).to eq(3) end it "sleeps for 0.05 seconds (example 4)" do sleep 0.05 expect(4).to eq(4) end it "sleeps for 0.05 seconds (example 5)" do sleep 0.05 expect(5).to eq(5) end it "sleeps for 0.05 seconds (example 6)" do sleep 0.05 expect(6).to eq(6) end it "sleeps for 0.05 seconds (example 7)" do sleep 0.05 expect(7).to eq(7) end it "sleeps for 0.05 seconds (example 8)" do sleep 0.05 expect(8).to eq(8) end it "sleeps for 0.05 seconds (example 9)" do sleep 0.05 expect(9).to eq(9) end it "sleeps for 0.05 seconds (example 10)" do sleep 0.05 expect(10).to eq(10) end it "sleeps for 0.05 seconds (example 11)" do sleep 0.05 expect(11).to eq(11) end end """ Scenario: By default does not show profile When I run `rspec spec` Then the examples should all pass And the output should not contain "example 1" And the output should not contain "example 2" And the output should not contain "example 3" And the output should not contain "example 4" And the output should not contain "example 5" And the output should not contain "example 6" And the output should not contain "example 7" And the output should not contain "example 8" And the output should not contain "example 9" And the output should not contain "example 10" And the output should not contain "example 11" Scenario: Setting `profile_examples` to true shows 10 examples Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.profile_examples = true } """ When I run `rspec spec` Then the examples should all pass And the output should contain "Top 10 slowest examples" And the output should contain "example 1" And the output should not contain "example 2" And the output should contain "example 3" And the output should contain "example 4" And the output should contain "example 5" And the output should contain "example 6" And the output should contain "example 7" And the output should contain "example 8" And the output should contain "example 9" And the output should contain "example 10" And the output should contain "example 11" Scenario: Setting `profile_examples` to 2 shows 2 examples Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.profile_examples = 2 } """ When I run `rspec spec` Then the examples should all pass And the output should contain "Top 2 slowest examples" And the output should contain "example 1" And the output should not contain "example 2" And the output should contain "example 3" And the output should not contain "example 4" And the output should not contain "example 5" And the output should not contain "example 6" And the output should not contain "example 7" And the output should not contain "example 8" And the output should not contain "example 9" And the output should not contain "example 10" And the output should not contain "example 11" Scenario: Setting profile examples through CLI using `--profile` When I run `rspec spec --profile 2` Then the examples should all pass And the output should contain "Top 2 slowest examples" And the output should contain "example 1" And the output should not contain "example 2" And the output should contain "example 3" And the output should not contain "example 4" And the output should not contain "example 5" And the output should not contain "example 6" And the output should not contain "example 7" And the output should not contain "example 8" And the output should not contain "example 9" And the output should not contain "example 10" And the output should not contain "example 11" Scenario: Using `--no-profile` overrules config options Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.profile_examples = true } """ When I run `rspec spec --no-profile` Then the examples should all pass And the output should not contain "example 1" And the output should not contain "example 2" And the output should not contain "example 3" And the output should not contain "example 4" And the output should not contain "example 5" And the output should not contain "example 6" And the output should not contain "example 7" And the output should not contain "example 8" And the output should not contain "example 9" And the output should not contain "example 10" And the output should not contain "example 11" Scenario: Using `--profile` with `--fail-fast` shows slow examples if everything passes When I run `rspec spec --fail-fast --profile` Then the examples should all pass And the output should contain "Top 10 slowest examples" And the output should contain "example 1" And the output should not contain "example 2" And the output should contain "example 3" And the output should contain "example 4" And the output should contain "example 5" And the output should contain "example 6" And the output should contain "example 7" And the output should contain "example 8" And the output should contain "example 9" And the output should contain "example 10" And the output should contain "example 11" Scenario: Using `--profile` shows slow examples even in case of failures Given a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "sleeps for 0.1 seconds (example 1)" do sleep 0.1 expect(1).to eq(1) end it "fails" do fail end end """ When I run `rspec spec --profile` Then the output should contain "2 examples, 1 failure" And the output should contain "Top 2 slowest examples" And the output should contain "example 1" Scenario: Using `--profile` with `--fail-fast` doesn't show slow examples in case of failures Given a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do it "sleeps for 0.1 seconds (example 1)" do sleep 0.1 expect(1).to eq(1) end it "fails" do fail end end """ When I run `rspec spec --fail-fast --profile` Then the output should not contain "Top 2 slowest examples" And the output should not contain "example 1" Scenario: Using `--profile` with slow before hooks includes hook execution time Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "slow before context hook" do before(:context) do sleep 0.2 end context "nested" do it "example" do expect(10).to eq(10) end end end RSpec.describe "slow example" do it "slow example" do sleep 0.1 expect(10).to eq(10) end end """ When I run `rspec spec --profile 1` Then the output should report "slow before context hook" as the slowest example group ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/order_and_seed.feature0000664000000000000000000000041414557677674027657 0ustar rootrootFeature: Setting the `--order` and/or `--seed` You can set the order to run specs and specify a seed if you are running the specs using the 'random' ordering. See [the documentation on the `--order` command line option](../command-line/order) for more on this. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/failure_exit_code.feature0000664000000000000000000000410714557677674030377 0ustar rootrootFeature: Setting a failure exit code Use the `failure_exit_code` option to set a custom exit code when RSpec fails. ```ruby RSpec.configure { |c| c.failure_exit_code = 42 } ``` Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.failure_exit_code = 42 } """ Scenario: A failing spec with the default exit code Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "something" do it "fails" do fail end end """ When I run `rspec spec/example_spec.rb` Then the exit status should be 1 Scenario: A failing spec with a custom exit code Given a file named "spec/example_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "something" do it "fails" do fail end end """ When I run `rspec spec/example_spec.rb` Then the exit status should be 42 Scenario: An error running specs spec with a custom exit code Given a file named "spec/typo_spec.rb" with: """ruby require 'spec_helper' RSpec.escribe "something" do # intentional typo it "works" do true end end """ When I run `rspec spec/typo_spec.rb` Then the exit status should be 42 Scenario: Success running specs spec with a custom exit code defined Given a file named "spec/example_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "something" do it "works" do true end end """ When I run `rspec spec/example_spec.rb` Then the exit status should be 0 Scenario: Exit with the default exit code when an `at_exit` hook is added upstream Given a file named "exit_at_spec.rb" with: """ruby require 'rspec/autorun' at_exit { exit(0) } RSpec.describe "exit 0 at_exit ignored" do it "does not interfere with the default exit code" do fail end end """ When I run `ruby exit_at_spec.rb` Then the exit status should be 1 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/pending_failure_output.feature0000664000000000000000000000432314557677674031500 0ustar rootrootFeature: Configuring pending failure output Configure the format of pending examples output with an option (defaults to `:full`): ```ruby RSpec.configure do |c| c.pending_failure_output = :no_backtrace end ``` Allowed options are `:full`, `:no_backtrace` and `:skip`. Background: Given a file named "spec/example_spec.rb" with: """ruby require "spec_helper" RSpec.describe "something" do pending "will never happen again" do expect(Time.now.year).to eq(2021) end end """ Scenario: By default outputs backtrace and details Given a file named "spec/spec_helper.rb" with: """ruby """ When I run `rspec spec` Then the examples should all pass And the output should contain "Pending: (Failures listed here are expected and do not affect your suite's status)" And the output should contain "1) something will never happen again" And the output should contain "expected: 2021" And the output should contain "./spec/example_spec.rb:5" Scenario: Setting `pending_failure_output` to `:no_backtrace` hides the backtrace Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.pending_failure_output = :no_backtrace } """ When I run `rspec spec` Then the examples should all pass And the output should contain "Pending: (Failures listed here are expected and do not affect your suite's status)" And the output should contain "1) something will never happen again" And the output should contain "expected: 2021" And the output should not contain "./spec/example_spec.rb:5" Scenario: Setting `pending_failure_output` to `:skip` hides the backtrace Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.pending_failure_output = :skip } """ When I run `rspec spec` Then the examples should all pass And the output should not contain "Pending: (Failures listed here are expected and do not affect your suite's status)" And the output should not contain "1) something will never happen again" And the output should not contain "expected: 2021" And the output should not contain "./spec/example_spec.rb:5" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/alias_example_to.feature0000664000000000000000000000350514557677674030234 0ustar rootrootFeature: Create example aliases Use `config.alias_example_to` to create new example group methods that define examples with the configured metadata. You can also specify metadata using only symbols. Scenario: Use `alias_example_to` to define a custom example name Given a file named "alias_example_to_spec.rb" with: """ruby RSpec.configure do |c| c.alias_example_to :task end RSpec.describe "a task example group" do task "does something" do expect(5).to eq(5) end end """ When I run `rspec alias_example_to_spec.rb --format doc` Then the output should contain "does something" And the examples should all pass Scenario: Use `alias_example_to` to define a pending example Given a file named "alias_example_to_pending_spec.rb" with: """ruby RSpec.configure do |c| c.alias_example_to :pit, :pending => "Pit alias used" end RSpec.describe "an example group" do pit "does something later on" do fail "not implemented yet" end end """ When I run `rspec alias_example_to_pending_spec.rb --format doc` Then the output should contain "does something later on (PENDING: Pit alias used)" And the output should contain "0 failures" Scenario: Use symbols as metadata Given a file named "use_symbols_as_metadata_spec.rb" with: """ruby RSpec.configure do |c| c.alias_example_to :pit, :pending end RSpec.describe "an example group" do pit "does something later on" do fail "not implemented yet" end end """ When I run `rspec use_symbols_as_metadata_spec.rb --format doc` Then the output should contain "does something later on (PENDING: No reason given)" And the output should contain "0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/deprecation_stream.feature0000664000000000000000000000510214557677674030571 0ustar rootrootFeature: Custom deprecation stream Define a custom output stream for warning about deprecations (default `$stderr`). ```ruby RSpec.configure do |c| c.deprecation_stream = File.open('deprecations.txt', 'w') end ``` or ```ruby RSpec.configure { |c| c.deprecation_stream = 'deprecations.txt' } ``` or pass `--deprecation-out` Background: Given a file named "lib/foo.rb" with: """ruby class Foo def bar RSpec.deprecate "Foo#bar" end end """ Scenario: Default - print deprecations to `$stderr` Given a file named "spec/example_spec.rb" with: """ruby require "foo" RSpec.describe "calling a deprecated method" do example { Foo.new.bar } end """ When I run `rspec spec/example_spec.rb` Then the output should contain "Deprecation Warnings:\n\nFoo#bar is deprecated" Scenario: Configure using the path to a file Given a file named "spec/example_spec.rb" with: """ruby require "foo" RSpec.configure {|c| c.deprecation_stream = 'deprecations.txt' } RSpec.describe "calling a deprecated method" do example { Foo.new.bar } end """ When I run `rspec spec/example_spec.rb` Then the output should not contain "Deprecation Warnings:" But the output should contain "1 deprecation logged to deprecations.txt" And the file "deprecations.txt" should contain "Foo#bar is deprecated" Scenario: Configure using a `File` object Given a file named "spec/example_spec.rb" with: """ruby require "foo" RSpec.configure do |c| c.deprecation_stream = File.open('deprecations.txt', 'w') end RSpec.describe "calling a deprecated method" do example { Foo.new.bar } end """ When I run `rspec spec/example_spec.rb` Then the output should not contain "Deprecation Warnings:" But the output should contain "1 deprecation logged to deprecations.txt" And the file "deprecations.txt" should contain "Foo#bar is deprecated" Scenario: Configure using the CLI `--deprecation-out` option Given a file named "spec/example_spec.rb" with: """ruby require "foo" RSpec.describe "calling a deprecated method" do example { Foo.new.bar } end """ When I run `rspec spec/example_spec.rb --deprecation-out deprecations.txt` Then the output should not contain "Deprecation Warnings:" But the output should contain "1 deprecation logged to deprecations.txt" And the file "deprecations.txt" should contain "Foo#bar is deprecated" ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/backtrace_exclusion_patterns.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/backtrace_exclusion_patterns.featur0000664000000000000000000001121614557677674032507 0ustar rootrootFeature: Excluding lines from the backtrace To reduce the noise when diagnosing failures, RSpec can exclude lines belonging to certain gems or matching given patterns. If you want to filter out backtrace lines belonging to specific gems, you can use `config.filter_gems_from_backtrace` like so: ```ruby config.filter_gems_from_backtrace "ignored_gem", "another_ignored_gem", ``` For more control over which lines to ignore, you can use the the `backtrace_exclusion_patterns` option to either replace the default exclusion patterns, or append your own, e.g. ```ruby config.backtrace_exclusion_patterns = [/first pattern/, /second pattern/] config.backtrace_exclusion_patterns << /another pattern/ ``` The default exclusion patterns are: ```ruby /\/lib\d*\/ruby\//, /org\/jruby\//, /bin\//, /lib\/rspec\/(core|expectations|matchers|mocks)/ ``` Additionally, `rspec` can be run with the `--backtrace` option to skip backtrace cleaning entirely. Scenario: Using default `backtrace_exclusion_patterns` Given a file named "spec/failing_spec.rb" with: """ruby RSpec.describe "2 + 2" do it "is 5" do expect(2+2).to eq(5) end end """ When I run `rspec` Then the output should contain "1 example, 1 failure" And the output should not contain "lib/rspec/expectations" Scenario: Replacing `backtrace_exclusion_patterns` Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.backtrace_exclusion_patterns = [ /spec_helper/ ] end """ And a file named "spec/example_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "foo" do it "returns baz" do expect("foo").to eq("baz") end end """ When I run `rspec` Then the output should contain "1 example, 1 failure" And the output should contain "lib/rspec/expectations" Scenario: Appending to `backtrace_exclusion_patterns` Given a file named "spec/support/assert_baz.rb" with: """ruby require "support/really_assert_baz" def assert_baz(arg) really_assert_baz(arg) end """ And a file named "spec/support/really_assert_baz.rb" with: """ruby def really_assert_baz(arg) expect(arg).to eq("baz") end """ And a file named "spec/example_spec.rb" with: """ruby require "support/assert_baz" RSpec.configure do |config| config.backtrace_exclusion_patterns << /really/ end RSpec.describe "bar" do it "is baz" do assert_baz("bar") end end """ When I run `rspec` Then the output should contain "1 example, 1 failure" And the output should contain "assert_baz" But the output should not contain "really_assert_baz" And the output should not contain "lib/rspec/expectations" Scenario: Running `rspec` with `--backtrace` prints unfiltered backtraces Given a file named "spec/support/custom_helper.rb" with: """ruby def assert_baz(arg) expect(arg).to eq("baz") end """ And a file named "spec/example_spec.rb" with: """ruby require "support/custom_helper" RSpec.configure do |config| config.backtrace_exclusion_patterns << /custom_helper/ end RSpec.describe "bar" do it "is baz" do assert_baz("bar") end end """ When I run `rspec --backtrace` Then the output should contain "1 example, 1 failure" And the output should contain "spec/support/custom_helper.rb:2:in `assert_baz'" And the output should contain "lib/rspec/expectations" And the output should contain "lib/rspec/core" Scenario: Using `filter_gems_from_backtrace` to filter the named gem Given a vendored gem named "my_gem" containing a file named "lib/my_gem.rb" with: """ruby class MyGem def self.do_amazing_things! # intentional bug to trigger an exception impossible_math = 10 / 0 "10 div 0 is: #{impossible_math}" end end """ And a file named "spec/use_my_gem_spec.rb" with: """ruby require 'my_gem' RSpec.describe "Using my_gem" do it 'does amazing things' do expect(MyGem.do_amazing_things!).to include("10 div 0 is") end end """ And a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.filter_gems_from_backtrace "my_gem" end """ Then the output from `rspec` should contain "vendor/my_gem-1.2.3/lib/my_gem.rb:4:in `do_amazing_things!'" But the output from `rspec --require spec_helper` should not contain "vendor/my_gem-1.2.3/lib/my_gem.rb:4:in `do_amazing_things!'" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/fail_if_no_examples.feature0000664000000000000000000000263414557677674030713 0ustar rootrootFeature: Setting the `fail_if_no_examples` option Use the `fail_if_no_examples` option to make RSpec exit with a failure status (by default 1) if there are no examples. Using this option, it is recommended to add a `--require spec_helper` option to `.rspec` file to ensure the `fail_if_no_examples` option is set even if no spec files are loaded. This option may be particularly useful when you happen to not run RSpec tests locally, but rely on CI to do this. This prevents from false positive builds, when you expected some RSpec examples to be run, but none were run. Such a situation may be caused by your misconfiguration or regression/major changes in RSpec. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure { |c| c.fail_if_no_examples = true } """ Given a file named ".rspec" with: """ruby --require spec_helper """ Given a file named "spec/some.spec.rb" with: """ruby RSpec.describe 'something' do it 'succeeds' do true end end """ Scenario: Examples file name is not matched by RSpec pattern, thus there are no examples run When I run `rspec` Then it should fail with "0 examples, 0 failures" Scenario: Examples file name is matched by RSpec pattern, 1 example is run When I run `rspec --pattern spec/**/*.spec.rb` Then it should pass with "1 example, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/zero_monkey_patching_mode.feature0000664000000000000000000000616514557677674032155 0ustar rootroot@allow-should-syntax Feature: Zero monkey patching mode Use the `disable_monkey_patching!` configuration option to disable all monkey patching done by RSpec: - stops exposing DSL globally - disables `should` and `should_not` syntax for rspec-expectations - disables `stub`, `should_receive`, and `should_not_receive` syntax for rspec-mocks ```ruby RSpec.configure { |c| c.disable_monkey_patching! } ``` Background: Given a file named "spec/example_describe_spec.rb" with: """ruby require 'spec_helper' describe "specs here" do it "passes" do end end """ Given a file named "spec/example_should_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "another specs here" do it "passes with monkey patched expectations" do x = 25 x.should eq 25 x.should_not be > 30 end it "passes with monkey patched mocks" do x = double("thing") x.stub(:hello => [:world]) x.should_receive(:count).and_return(4) x.should_not_receive(:all) (x.hello * x.count).should eq([:world, :world, :world, :world]) end end """ Given a file named "spec/example_expect_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "specs here too" do it "passes in zero monkey patching mode" do x = double("thing") allow(x).to receive(:hello).and_return([:world]) expect(x).to receive(:count).and_return(4) expect(x).not_to receive(:all) expect(x.hello * x.count).to eq([:world, :world, :world, :world]) end it "passes in zero monkey patching mode" do x = 25 expect(x).to eq(25) expect(x).not_to be > 30 end end """ Scenario: By default RSpec allows monkey patching Given a file named "spec/spec_helper.rb" with: """ruby # Empty spec_helper """ When I run `rspec` Then the examples should all pass Scenario: Monkey patched methods are undefined with `disable_monkey_patching!` Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.disable_monkey_patching! end """ When I run `rspec spec/example_should_spec.rb` Then the output should contain all of these: | undefined method `should' | | unexpected message :stub | When I run `rspec spec/example_describe_spec.rb` Then the output should contain "undefined method `describe'" Scenario: `allow` and `expect` syntax works with monkey patching Given a file named "spec/spec_helper.rb" with: """ruby # Empty spec_helper """ When I run `rspec spec/example_expect_spec.rb` Then the examples should all pass Scenario: `allow` and `expect` syntax works without monkey patching Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.disable_monkey_patching! end """ When I run `rspec spec/example_expect_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/enable_global_dsl.feature0000664000000000000000000000446214557677674030341 0ustar rootrootFeature: Global namespace DSL RSpec has a few top-level constructs that allow you to begin describing behaviour: * `RSpec.describe`: Define a named context for a group of examples. * `RSpec.shared_examples`: Define a set of shared examples that can later be included in an example group. * `RSpec.shared_context`: define some common context (using `before`, `let`, helper methods, etc) that can later be included in an example group. Historically, these constructs have been available directly off of the main object, so that you could use these at the start of a file without the `RSpec.` prefix. They have also been available off of any class or module so that you can scope your examples within a particular constant namespace. RSpec 3 now provides an option to disable this global monkey patching: ```ruby config.expose_dsl_globally = false ``` For backwards compatibility it defaults to `true`. @allow-should-syntax Scenario: By default RSpec allows the DSL to be used globally Given a file named "spec/example_spec.rb" with: """ruby describe "specs here" do it "passes" do end end """ When I run `rspec` Then the output should contain "1 example, 0 failures" @allow-should-syntax Scenario: By default rspec/autorun allows the DSL to be used globally Given a file named "spec/example_spec.rb" with: """ruby require 'rspec/autorun' describe "specs here" do it "passes" do end end """ When I run `ruby spec/example_spec.rb` Then the output should contain "1 example, 0 failures" Scenario: When exposing globally is disabled the top level DSL no longer works Given a file named "spec/example_spec.rb" with: """ruby RSpec.configure { |c| c.expose_dsl_globally = false } describe "specs here" do it "passes" do end end """ When I run `rspec` Then the output should contain "undefined method `describe'" Scenario: Regardless of setting Given a file named "spec/example_spec.rb" with: """ruby RSpec.configure { |c| c.expose_dsl_globally = true } RSpec.describe "specs here" do it "passes" do end end """ When I run `rspec` Then the output should contain "1 example, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/configuration/custom_settings.feature0000664000000000000000000000460414557677674030161 0ustar rootrootFeature: Custom settings Extensions like rspec-rails can add their own configuration settings. Scenario: Simple setting (with defaults) Given a file named "additional_setting_spec.rb" with: """ruby RSpec.configure do |c| c.add_setting :custom_setting end RSpec.describe "custom setting" do it "is nil by default" do expect(RSpec.configuration.custom_setting).to be_nil end it "is exposed as a predicate" do expect(RSpec.configuration.custom_setting?).to be(false) end it "can be overridden" do RSpec.configuration.custom_setting = true expect(RSpec.configuration.custom_setting).to be(true) expect(RSpec.configuration.custom_setting?).to be(true) end end """ When I run `rspec ./additional_setting_spec.rb` Then the examples should all pass Scenario: Default to `true` Given a file named "additional_setting_spec.rb" with: """ruby RSpec.configure do |c| c.add_setting :custom_setting, :default => true end RSpec.describe "custom setting" do it "is true by default" do expect(RSpec.configuration.custom_setting).to be(true) end it "is exposed as a predicate" do expect(RSpec.configuration.custom_setting?).to be(true) end it "can be overridden" do RSpec.configuration.custom_setting = false expect(RSpec.configuration.custom_setting).to be(false) expect(RSpec.configuration.custom_setting?).to be(false) end end """ When I run `rspec ./additional_setting_spec.rb` Then the examples should all pass Scenario: Overridden in a subsequent `RSpec.configure` block Given a file named "additional_setting_spec.rb" with: """ruby RSpec.configure do |c| c.add_setting :custom_setting end RSpec.configure do |c| c.custom_setting = true end RSpec.describe "custom setting" do it "returns the value set in the last configure block to get eval'd" do expect(RSpec.configuration.custom_setting).to be(true) end it "is exposed as a predicate" do expect(RSpec.configuration.custom_setting?).to be(true) end end """ When I run `rspec ./additional_setting_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/0000775000000000000000000000000014557677674023124 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/dry_run.feature0000664000000000000000000000150114557677674026160 0ustar rootrootFeature: `--dry-run` option Use the `--dry-run` option to have RSpec print your suite's formatter output without running any examples or hooks. Scenario: Using `--dry-run` Given a file named "spec/dry_run_spec.rb" with: """ruby RSpec.configure do |c| c.before(:suite) { puts "before suite" } c.after(:suite) { puts "after suite" } end RSpec.describe "dry run" do before(:context) { fail } before(:example) { fail } it "fails in example" do fail end after(:example) { fail } after(:context) { fail } end """ When I run `rspec --dry-run` Then the output should contain "1 example, 0 failures" And the output should not contain "before suite" And the output should not contain "after suite" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/fail_fast.feature0000664000000000000000000000230314557677674026427 0ustar rootrootFeature: `--fail-fast` option Use the `--fail-fast` option to tell RSpec to stop running the test suite on the first failed test. You may add a parameter to tell RSpec to stop running the test suite after N failed tests, for example: `--fail-fast=3`. You can also specify `--no-fail-fast` to turn it off (default behaviour). Background: Given a file named "fail_fast_spec.rb" with: """ruby RSpec.describe "fail fast" do it "passing test" do; end it "1st failing test" do fail end it "2nd failing test" do fail end it "3rd failing test" do fail end it "4th failing test" do fail end it "passing test" do; end end """ Scenario: Using `--fail-fast` When I run `rspec . --fail-fast` Then the output should contain ".F" Then the output should not contain ".F." Scenario: Using `--fail-fast=3` When I run `rspec . --fail-fast=3` Then the output should contain ".FFF" Then the output should not contain ".FFFF." Scenario: Using `--no-fail-fast` When I run `rspec . --no-fail-fast` Then the output should contain ".FFFF." ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/example_name_option.feature0000664000000000000000000000756214557677674030536 0ustar rootrootFeature: `--example` option Use the `--example` (or `-e`) option to filter examples by name. The argument is matched against the full description of the example, which is the concatenation of descriptions of the group (including any nested groups) and the example. This allows you to run a single uniquely named example, all examples with similar names, all the examples in a uniquely named group, etc, etc. You can also use the option more than once to specify multiple example matches. Note: description-less examples that have generated descriptions (typical when using the [one-liner syntax](../subject/one-liner-syntax)) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group's description to select all examples defined in the group (including those that have no description). Background: Given a file named "first_spec.rb" with: """ruby RSpec.describe "first group" do it "first example in first group" do; end it "second example in first group" do; end end """ And a file named "second_spec.rb" with: """ruby RSpec.describe "second group" do it "first example in second group" do; end it "second example in second group" do; end end """ And a file named "third_spec.rb" with: """ruby RSpec.describe "third group" do it "first example in third group" do; end context "nested group" do it "first example in nested group" do; end it "second example in nested group" do; end end end """ And a file named "fourth_spec.rb" with: """ruby RSpec.describe Array do describe "#length" do it "is the number of items" do expect(Array.new([1,2,3]).length).to eq 3 end end end """ Scenario: No matches When I run `rspec . --example nothing_like_this` Then the process should succeed even though no examples were run Scenario: Match on one word When I run `rspec . --example example` Then the examples should all pass Scenario: One match in each context When I run `rspec . --example 'first example'` Then the examples should all pass Scenario: One match in one file using just the example name When I run `rspec . --example 'first example in first group'` Then the examples should all pass Scenario: One match in one file using the example name and the group name When I run `rspec . --example 'first group first example in first group'` Then the examples should all pass Scenario: All examples in one group When I run `rspec . --example 'first group'` Then the examples should all pass Scenario: One match in one file with group name When I run `rspec . --example 'second group first example'` Then the examples should all pass Scenario: All examples in one group including examples in nested groups When I run `rspec . --example 'third group'` Then the examples should all pass Scenario: Match using `ClassName#method_name` form When I run `rspec . --example 'Array#length'` Then the examples should all pass Scenario: Multiple applications of example name option When I run `rspec . --example 'first group' --example 'second group' --format d` Then the examples should all pass And the output should contain all of these: |first example in first group| |second example in first group| |first example in second group| |second example in second group| And the output should not contain any of these: |first example in third group| |nested group first example in nested group| |nested group second example in nested group| ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/tag.feature0000664000000000000000000000766214557677674025267 0ustar rootrootFeature: `--tag` option Use the `--tag` (or `-t`) option to run examples that match a specified tag. The tag can be a simple `name` or a `name:value` pair. If a simple `name` is supplied, only examples with `:name => true` will run. If a `name:value` pair is given, examples with `name => value` will run, where `value` is always a string. In both cases, `name` is converted to a symbol. Tags can also be used to exclude examples by adding a `~` before the tag. For example, `~tag` will exclude all examples marked with `:tag => true` and `~tag:value` will exclude all examples marked with `:tag => value`. Filtering by tag uses a hash internally, which means that you can't specify multiple filters for the same key. For instance, if you try to exclude `:name => 'foo'` and `:name => 'bar'`, you will only end up excluding `:name => 'bar'`. To be compatible with the Cucumber syntax, tags can optionally start with an `@` symbol, which will be ignored as part of the tag, e.g. `--tag @focus` is treated the same as `--tag focus` and is expanded to `:focus => true`. Background: Given a file named "tagged_spec.rb" with: """ruby RSpec.describe "group with tagged specs" do it "example I'm working now", :focus => true do; end it "special example with string", :type => 'special' do; end it "special example with symbol", :type => :special do; end it "slow example", :skip => true do; end it "ordinary example", :speed => 'slow' do; end it "untagged example" do; end end """ Scenario: Filter examples with non-existent tag When I run `rspec . --tag mytag` Then the process should succeed even though no examples were run Scenario: Filter examples with a simple tag When I run `rspec . --tag focus` Then the output should contain "include {:focus=>true}" And the examples should all pass Scenario: Filter examples with a simple tag and @ When I run `rspec . --tag @focus` Then the output should contain "include {:focus=>true}" Then the examples should all pass Scenario: Filter examples with a `name:value` tag When I run `rspec . --tag type:special` Then the output should contain: """ include {:type=>"special"} """ And the output should contain "2 examples" And the examples should all pass Scenario: Filter examples with a `name:value` tag and @ When I run `rspec . --tag @type:special` Then the output should contain: """ include {:type=>"special"} """ And the examples should all pass Scenario: Exclude examples with a simple tag When I run `rspec . --tag ~skip` Then the output should contain "exclude {:skip=>true}" Then the examples should all pass Scenario: Exclude examples with a simple tag and @ When I run `rspec . --tag ~@skip` Then the output should contain "exclude {:skip=>true}" Then the examples should all pass Scenario: Exclude examples with a `name:value` tag When I run `rspec . --tag ~speed:slow` Then the output should contain: """ exclude {:speed=>"slow"} """ Then the examples should all pass Scenario: Exclude examples with a `name:value` tag and @ When I run `rspec . --tag ~@speed:slow` Then the output should contain: """ exclude {:speed=>"slow"} """ Then the examples should all pass Scenario: Filter examples with a simple tag, exclude examples with another tag When I run `rspec . --tag focus --tag ~skip` Then the output should contain "include {:focus=>true}" And the output should contain "exclude {:skip=>true}" And the examples should all pass Scenario: Exclude examples with multiple tags When I run `rspec . --tag ~skip --tag ~speed:slow` Then the output should contain one of the following: | exclude {:skip=>true, :speed=>"slow"} | | exclude {:speed=>"slow", :skip=>true} | Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/line_number_appended_to_path.feature0000664000000000000000000001444414557677674032365 0ustar rootrootFeature: `:` (line number appended to file path) To run one or more examples or groups, you can append the line number to the path, e.g. ```bash $ rspec path/to/example_spec.rb:37 ``` Background: Given a file named "example_spec.rb" with: """ruby RSpec.describe "outer group" do it "first example in outer group" do end it "second example in outer group" do end describe "nested group" do it "example in nested group" do end end end """ And a file named "example2_spec.rb" with: """ruby RSpec.describe "yet another group" do it "first example in second file" do end it "second example in second file" do end end """ And a file named "one_liner_spec.rb" with: """ruby RSpec.describe 9 do it { is_expected.to be > 8 } it { is_expected.to be < 10 } end """ Scenario: Nested groups - outer group on declaration line When I run `rspec example_spec.rb:1 --format doc` Then the examples should all pass And the output should contain "second example in outer group" And the output should contain "first example in outer group" And the output should contain "example in nested group" Scenario: Nested groups - outer group inside block before example When I run `rspec example_spec.rb:2 --format doc` Then the examples should all pass And the output should contain "second example in outer group" And the output should contain "first example in outer group" And the output should contain "example in nested group" Scenario: Nested groups - inner group on declaration line When I run `rspec example_spec.rb:11 --format doc` Then the examples should all pass And the output should contain "example in nested group" And the output should not contain "second example in outer group" And the output should not contain "first example in outer group" Scenario: Nested groups - inner group inside block before example When I run `rspec example_spec.rb:12 --format doc` Then the examples should all pass And the output should contain "example in nested group" And the output should not contain "second example in outer group" And the output should not contain "first example in outer group" Scenario: Two examples - first example on declaration line When I run `rspec example_spec.rb:3 --format doc` Then the examples should all pass And the output should contain "first example in outer group" But the output should not contain "second example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - first example inside block When I run `rspec example_spec.rb:4 --format doc` Then the examples should all pass And the output should contain "first example in outer group" But the output should not contain "second example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - first example on end When I run `rspec example_spec.rb:5 --format doc` Then the examples should all pass And the output should contain "first example in outer group" But the output should not contain "second example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - first example after end but before next example When I run `rspec example_spec.rb:6 --format doc` Then the examples should all pass And the output should contain "first example in outer group" But the output should not contain "second example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - second example on declaration line When I run `rspec example_spec.rb:7 --format doc` Then the examples should all pass And the output should contain "second example in outer group" But the output should not contain "first example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - second example inside block When I run `rspec example_spec.rb:7 --format doc` Then the examples should all pass And the output should contain "second example in outer group" But the output should not contain "first example in outer group" And the output should not contain "example in nested group" Scenario: Two examples - second example on end When I run `rspec example_spec.rb:7 --format doc` Then the examples should all pass And the output should contain "second example in outer group" But the output should not contain "first example in outer group" And the output should not contain "example in nested group" Scenario: Specified multiple times for different files When I run `rspec example_spec.rb:7 example2_spec.rb:4 --format doc` Then the examples should all pass And the output should contain "second example in outer group" And the output should contain "second example in second file" But the output should not contain "first example in outer group" And the output should not contain "nested group" And the output should not contain "first example in second file" Scenario: Specified multiple times for the same file with multiple arguments When I run `rspec example_spec.rb:7 example_spec.rb:11 --format doc` Then the examples should all pass And the output should contain "second example in outer group" And the output should contain "nested group" But the output should not contain "first example in outer group" And the output should not contain "second file" Scenario: Specified multiple times for the same file with a single argument When I run `rspec example_spec.rb:7:11 --format doc` Then the examples should all pass And the output should contain "second example in outer group" And the output should contain "nested group" But the output should not contain "first example in outer group" And the output should not contain "second file" Scenario: Matching one-liners When I run `rspec one_liner_spec.rb:3 --format doc` Then the examples should all pass Then the output should contain "is expected to be > 8" But the output should not contain "is expected to be < 10" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/require_option.feature0000664000000000000000000000243714557677674027553 0ustar rootrootFeature: `--require` option Use the `--require` (or `-r`) option to specify a file to require before running specs. Scenario: Using the `--require` option Given a file named "logging_formatter.rb" with: """ruby require "rspec/core/formatters/base_text_formatter" require 'delegate' class LoggingFormatter < RSpec::Core::Formatters::BaseTextFormatter RSpec::Core::Formatters.register self, :dump_summary def initialize(output) super LoggingIO.new(output) end class LoggingIO < SimpleDelegator def initialize(output) @file = File.new('rspec.log', 'w') super end def puts(*args) [@file, __getobj__].each { |out| out.puts(*args) } end def close @file.close end end end """ And a file named "spec/example_spec.rb" with: """ruby RSpec.describe "an embarrassing situation" do it "happens to everyone" do end end """ When I run `rspec --require ./logging_formatter.rb --format LoggingFormatter` Then the output should contain "1 example, 0 failures" And the file "rspec.log" should contain "1 example, 0 failures" And the exit status should be 0 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/pattern_option.feature0000664000000000000000000000267414557677674027557 0ustar rootrootFeature: `--pattern` option When you run RSpec without giving it specific file names, it determines which files to load by applying a pattern to the provided directory arguments or `spec` (if no directories are provided). By default, RSpec uses the following pattern: "**{,/*/**}/*_spec.rb" Use the `--pattern` option to declare a different pattern. Background: Given a file named "spec/example_spec.rb" with: """ruby RSpec.describe "two specs" do it "passes" do end it "passes too" do end end """ And a file named "spec/example_test.rb" with: """ruby RSpec.describe "one spec" do it "passes" do end end """ Scenario: By default, RSpec runs matching spec files When I run `rspec` Then the output should contain "2 examples, 0 failures" Scenario: The `--pattern` flag makes RSpec run files matching the specified pattern and ignore the default pattern When I run `rspec -P "**/*_test.rb"` Then the output should contain "1 example, 0 failures" Scenario: The `--pattern` flag can be used to pass in multiple patterns, separated by commas When I run `rspec -P "**/*_test.rb,**/*_spec.rb"` Then the output should contain "3 examples, 0 failures" Scenario: The `--pattern` flag accepts shell style glob unions When I run `rspec -P "**/*_{test,spec}.rb"` Then the output should contain "3 examples, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/order.feature0000664000000000000000000000630714557677674025622 0ustar rootrootFeature: Using the `--order` option Use the `--order` option to tell RSpec how to order the files, groups, and examples. The available ordering schemes are `defined` and `rand`. `defined` is the default, which executes groups and examples in the order they are defined as the spec files are loaded, with the caveat that each group runs its examples before running its nested example groups, even if the nested groups are defined before the examples. Use `rand` to randomize the order of groups and examples within the groups. Nested groups are always run from top-level to bottom-level in order to avoid executing `before(:context)` and `after(:context)` hooks more than once, but the order of groups at each level is randomized. With `rand` you can also specify a seed. Use `recently-modified` to run the most recently modified files first. You can combine it with `--only-failures` to find the most recent failing specs. Note that `recently-modified` and `rand` are mutually exclusive. ** Example usage ** The `defined` option is only necessary when you have `--order rand` stored in a config file (e.g. `.rspec`) and you want to override it from the command line.
--order defined
--order rand
--order rand:123
--seed 123 # same as --order rand:123
--order recently-modified
Scenario: Default order is `defined` Given a file named "example_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do end it "in order" do end end """ When I run `rspec example_spec.rb --format documentation` Then the output should contain: """ something does something in order """ Scenario: Order can be psuedo randomised (seed used here to fix the ordering for tests) Given a file named "example_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do end it "in order" do end end """ When I run `rspec example_spec.rb --format documentation --order rand:123` Then the output should contain: """ something in order does something """ Scenario: Configure custom ordering Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.register_ordering(:reverse) do |examples| examples.reverse end config.order = :reverse end RSpec.describe "something" do it "does something" do end it "in order" do end end """ When I run `rspec example_spec.rb --format documentation --order reverse` Then the output should contain: """ something in order does something """ Scenario: Override order to `defined` when another order is set Given a file named "example_spec.rb" with: """ruby RSpec.configure do |config| config.order = :random config.seed = 123 end RSpec.describe "something" do it "does something" do end it "in order" do end end """ When I run `rspec example_spec.rb --format documentation --order defined` Then the output should contain: """ something does something in order """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/init.feature0000664000000000000000000000374114557677674025451 0ustar rootrootFeature: `--init` option Use the `--init` option on the command line to generate conventional files for an RSpec project. It generates a `.rspec` and `spec/spec_helper.rb` with some example settings to get you started. These settings treat the case where you run an individual spec file differently, using the documentation formatter if no formatter has been explicitly set. Scenario: Generate `.rspec` When I run `rspec --init` Then the following files should exist: | .rspec | And the output should contain "create .rspec" Scenario: `.rspec` file already exists Given a file named ".rspec" with: """ --force-color """ When I run `rspec --init` Then the output should contain "exist .rspec" Scenario: Accept and use the recommended settings in `spec_helper` (which are initially commented out) Given I have a brand new project with no files And I have run `rspec --init` When I accept the recommended settings by removing `=begin` and `=end` from `spec_helper.rb` And I create "spec/addition_spec.rb" with the following content: """ruby RSpec.describe "Addition" do it "works" do expect(1 + 1).to eq(2) end end """ And I create "spec/subtraction_spec.rb" with the following content: """ruby RSpec.describe "Subtraction" do it "works" do expect(1 - 1).to eq(0) end end """ Then the output from `rspec` should not be in documentation format But the output from `rspec spec/addition_spec.rb` should be in documentation format But the output from `rspec spec/addition_spec.rb --format progress` should not be in documentation format And the output from `rspec --pattern 'spec/*ction_spec.rb'` should indicate it ran only the subtraction file And the output from `rspec --exclude-pattern 'spec/*dition_spec.rb'` should indicate it ran only the subtraction file ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/README.md0000664000000000000000000000223314557677674024403 0ustar rootroot# Command line options The `rspec` command comes with several options you can use to customize RSpec's behavior, including output formats, filtering examples, etc. For a full list of options, run the `rspec` command with the `--help` flag: ```ruby $ rspec --help ``` ### Run with `ruby` Generally, life is simpler if you just use the `rspec` command. If you must use the `ruby` command, however, you'll need to require `rspec/autorun`. You can either pass a `-rrspec/autorun` CLI option when invoking `ruby`, or add a `require 'rspec/autorun'` to one or more of your spec files. It is conventional to put configuration in and require assorted support files from `spec/spec_helper.rb`. It is also conventional to require that file from the spec files using `require 'spec_helper'`. This works because RSpec implicitly adds the `spec` directory to the `LOAD_PATH`. It also adds `lib`, so your implementation files will be on the `LOAD_PATH` as well. If you're using the `ruby` command, you'll need to do this yourself (with the `-I` option). Putting these together, your command might be something like this: ```ruby $ ruby -Ilib -Ispec -rrspec/autorun path/to/spec.rb ``` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/rake_task.feature0000664000000000000000000000755014557677674026454 0ustar rootrootFeature: Creating a rake task RSpec ships with a rake task with a number of useful options. We recommend you wrap this in a `rescue` clause so that you can use your `Rakefile` in an environment where RSpec is unavailable (for example on a production server). e.g: ```ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) rescue LoadError end ``` Scenario: Default options with passing spec (prints command and exit status is 0) Given a file named "Rakefile" with: """ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task :default => :spec rescue LoadError # no rspec available end """ And a file named "spec/thing_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do # pass end end """ When I run `rake` Then the output should match: """ (ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec """ Then the exit status should be 0 Scenario: Default options with failing spec (exit status is 1) Given a file named "Rakefile" with: """ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task :default => :spec rescue LoadError # no rspec available end """ And a file named "spec/thing_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do fail end end """ When I run `rake` Then the exit status should be 1 Scenario: Setting `fail_on_error = false` with failing spec (exit status is 0) Given a file named "Rakefile" with: """ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |t| t.fail_on_error = false end task :default => :spec rescue LoadError # no rspec available end """ And a file named "spec/thing_spec.rb" with: """ruby RSpec.describe "something" do it "does something" do fail end end """ When I run `rake` Then the exit status should be 0 Scenario: Passing arguments to the `rspec` command using `rspec_opts` Given a file named "Rakefile" with: """ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = "--tag fast" end rescue LoadError # no rspec available end """ And a file named "spec/thing_spec.rb" with: """ruby RSpec.describe "something" do it "has a tag", :fast => true do # pass end it "does not have a tag" do fail end end """ When I run `rake spec` Then the exit status should be 0 Then the output should match: """ (ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec --pattern spec[\/\\*{,}]+_spec.rb --tag fast """ Scenario: Passing rake task arguments to the `rspec` command via `rspec_opts` Given a file named "Rakefile" with: """ruby begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec, :tag) do |t, task_args| t.rspec_opts = "--tag #{task_args[:tag]}" end rescue LoadError # no rspec available end """ And a file named "spec/thing_spec.rb" with: """ruby RSpec.describe "something" do it "has a tag", :fast => true do # pass end it "does not have a tag" do fail end end """ When I run `rake spec[fast]` Then the exit status should be 0 Then the output should match: """ (ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec --pattern spec[\/\\*{,}]+_spec.rb --tag fast """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/randomization.feature0000664000000000000000000000433614557677674027365 0ustar rootrootFeature: Randomization can be reproduced across test runs In Ruby, randomness is seeded by calling `srand` and passing it the seed that you want to use. By doing this, subsequent calls to `rand`, `shuffle`, `sample`, etc. will all be randomized the same way given the same seed is passed to `srand`. RSpec takes care not to seed randomization directly when taking action that involves randomness (such as random ordering of examples). Since RSpec does not ever invoke `srand`, this means that you are free to choose which, if any, mechanism is used to seed randomization. There is an example below of how to use RSpec's seed for this purpose if you wish to do so. If you would like to manage seeding randomization without any help from RSpec, please keep the following things in mind: * The seed should never be hard-coded. The first example below only does this to show that seeding randomization with a seed other than the one used by RSpec will correctly seed randomization. * Report the seed that was chosen. The randomization that was used for a given test run can not be reproduced if no one knows what seed was used to begin with. * Provide a mechanism to feed the seed into the tests. Without this, the call to `srand` will have to be hard-coded any time it is necessary to replicate a given test run's randomness. Background: Given a file named ".rspec" with: """ --require spec_helper """ Given a file named "spec/random_spec.rb" with: """ruby RSpec.describe 'randomized example' do it 'prints random numbers' do puts 5.times.map { rand(99) }.join("-") end end """ Scenario: Specifying a seed using `srand` provides predictable randomization Given a file named "spec/spec_helper.rb" with: """ruby srand 123 """ When I run `rspec` Then the output should contain "66-92-98-17-83" Scenario: Passing the RSpec seed to `srand` provides predictable randomization Given a file named "spec/spec_helper.rb" with: """ruby srand RSpec.configuration.seed """ When I run `rspec --seed 123` Then the output should contain "66-92-98-17-83" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/warnings_option.feature0000664000000000000000000000212614557677674027722 0ustar rootrootFeature: `--warnings` option (run with warnings enabled) Use the `--warnings` option to run specs with warnings enabled. @unsupported-on-rbx Scenario: Given a file named "example_spec.rb" with: """ruby RSpec.describe do it 'generates warning' do $undefined end end """ When I run `rspec --warnings example_spec.rb` Then the output should contain "warning" @ruby-2-7 Scenario: Given a file named "example_spec.rb" with: """ruby def foo(**kwargs) kwargs end RSpec.describe do it "should warn about keyword arguments with 'rspec -w'" do expect(foo({a: 1})).to eq({a: 1}) end end """ When I run `rspec -w example_spec.rb` Then the output should contain "warning" @unsupported-on-rbx Scenario: Given a file named "example_spec.rb" with: """ruby RSpec.describe do it 'generates warning' do $undefined end end """ When I run `rspec example_spec.rb` Then the output should not contain "warning" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/only_failures.feature0000664000000000000000000001121614557677674027355 0ustar rootrootFeature: Using the `--only-failures` option The `--only-failures` option filters what examples are run so that only those that failed the last time they ran are executed. To use this option, you first have to configure `config.example_status_persistence_file_path`, which RSpec will use to store the status of each example the last time it ran. There's also a `--next-failure` option, which is shorthand for `--only-failures --fail-fast --order defined`. It allows you to repeatedly focus on just one of the currently failing examples, then move on to the next failure, etc. Either of these options can be combined with another a directory or file name; RSpec will run just the failures from the set of loaded examples. Background: Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |c| c.example_status_persistence_file_path = "examples.txt" end """ And a file named ".rspec" with: """ --require spec_helper --order random --format documentation """ And a file named "spec/array_spec.rb" with: """ruby RSpec.describe 'Array' do it "checks for inclusion of 1" do expect([1, 2]).to include(1) end it "checks for inclusion of 2" do expect([1, 2]).to include(2) end it "checks for inclusion of 3" do expect([1, 2]).to include(3) # failure end end """ And a file named "spec/string_spec.rb" with: """ruby RSpec.describe 'String' do it "checks for inclusion of 'foo'" do expect("food").to include('foo') end it "checks for inclusion of 'bar'" do expect("food").to include('bar') # failure end it "checks for inclusion of 'baz'" do expect("bazzy").to include('baz') end it "checks for inclusion of 'foobar'" do expect("food").to include('foobar') # failure end end """ And a file named "spec/passing_spec.rb" with: """ruby puts "Loading passing_spec.rb" RSpec.describe "A passing spec" do it "passes" do expect(1).to eq(1) end end """ And I have run `rspec` once, resulting in "8 examples, 3 failures" Scenario: Running `rspec --only-failures` loads only spec files with failures and runs only the failures When I run `rspec --only-failures` Then the output from "rspec --only-failures" should contain "3 examples, 3 failures" And the output from "rspec --only-failures" should not contain "Loading passing_spec.rb" Scenario: Combine `--only-failures` with a file name When I run `rspec spec/array_spec.rb --only-failures` Then the output should contain "1 example, 1 failure" When I run `rspec spec/string_spec.rb --only-failures` Then the output should contain "2 examples, 2 failures" Scenario: Use `--next-failure` to repeatedly run a single failure When I run `rspec --next-failure` Then the output should contain "1 example, 1 failure" And the output should contain "checks for inclusion of 3" When I fix "spec/array_spec.rb" by replacing "to include(3)" with "not_to include(3)" And I run `rspec --next-failure` Then the output should contain "2 examples, 1 failure" And the output should contain "checks for inclusion of 3" And the output should contain "checks for inclusion of 'bar'" When I fix "spec/string_spec.rb" by replacing "to include('bar')" with "not_to include('bar')" And I run `rspec --next-failure` Then the output should contain "2 examples, 1 failure" And the output should contain "checks for inclusion of 'bar'" And the output should contain "checks for inclusion of 'foobar'" When I fix "spec/string_spec.rb" by replacing "to include('foobar')" with "not_to include('foobar')" And I run `rspec --next-failure` Then the output should contain "1 example, 0 failures" And the output should contain "checks for inclusion of 'foobar'" When I run `rspec --next-failure` Then the output should contain "All examples were filtered out" Scenario: Running `rspec --only-failures` with spec files that pass doesn't run anything When I run `rspec spec/passing_spec.rb --only-failures` Then it should pass with "0 examples, 0 failures" Scenario: Clear error given when using `--only-failures` without configuring `example_status_persistence_file_path` Given I have not configured `example_status_persistence_file_path` When I run `rspec --only-failures` Then it should fail with "To use `--only-failures`, you must first set `config.example_status_persistence_file_path`." ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/example_matches_name_option.feature0000664000000000000000000001253014557677674032231 0ustar rootrootFeature: `--example-matches` option Use the `--example-matches` (or `-E`) option to filter examples by name using REGEX. The argument is matched against the full description of the example, which is the concatenation of descriptions of the group (including any nested groups) and the example. This allows you to run a single uniquely named example, all examples with similar names, all the examples in a uniquely named group, etc, etc. You can also use the option more than once to specify multiple example matches. Note: description-less examples that have generated descriptions (typical when using the [one-liner syntax](../subject/one-liner-syntax)) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group's description to select all examples defined in the group (including those that have no description). Background: Given a file named "first_spec.rb" with: """ruby RSpec.describe "first group" do it "first" do; end it "first example in first group" do; end it "second example in first group" do; end end """ And a file named "second_spec.rb" with: """ruby RSpec.describe "second group" do it "first example in second group" do; end it "second example in second group" do; end end """ And a file named "third_spec.rb" with: """ruby RSpec.describe "third group" do it "first example in third group" do; end context "group of nest" do it "first example in nested group" do; end it "second example in nested group" do; end it "third example in nested_group with underscore" do; end end end """ And a file named "fourth_spec.rb" with: """ruby RSpec.describe Array do describe "#length" do it "is the number of items" do expect(Array.new([1,2,3]).length).to eq 3 end end end """ Scenario: No matches When I run `rspec . --example-matches nothing_like_this` Then the process should succeed even though no examples were run Scenario: Match on one word When I run `rspec . --example-matches example` Then the examples should all pass Scenario: One match in each context When I run `rspec . --example-matches 'first example'` Then the examples should all pass Scenario: One match in one file using just the example name When I run `rspec . --example-matches 'first example in first group'` Then the examples should all pass Scenario: One match in one file using the example name and the group name When I run `rspec . --example-matches 'first group first example in first group'` Then the examples should all pass Scenario: All examples in one group When I run `rspec . --example-matches 'first group'` Then the examples should all pass Scenario: One match in one file with group name When I run `rspec . --example-matches 'second group first example'` Then the examples should all pass Scenario: All examples in one group including examples in nested groups When I run `rspec . --example-matches 'third group'` Then the examples should all pass Scenario: Match using `ClassName#method_name` form When I run `rspec . --example-matches 'Array#length'` Then the examples should all pass Scenario: Match only matching regex When I run `rspec . --example-matches "first$" --format d` Then the examples should all pass And the output should contain all of these: | first | And the output should not contain any of these: | first example in first group | | second example in first group | | first example in second group | | second example in second group | | first example in third group | | nested group first example in nested group | | nested group second example in nested group | # https://regex101.com/r/RABd8Q/2 Scenario: Match only matching regex with word boundaries When I run `rspec . --example-matches "nested[^_]" --format d` Then the examples should all pass And the output should contain all of these: | first example in nested group | | second example in nested group | And the output should not contain any of these: | first example in first group | | second example in first group | | first example in second group | | second example in second group | | first example in third group | | third example in nested_group | Scenario: Multiple applications of example name option When I run `rspec . --example-matches 'first group' --example-matches 'second group' --format d` Then the examples should all pass And the output should contain all of these: | first example in first group | | second example in first group | | first example in second group | | second example in second group | And the output should not contain any of these: | first example in third group | | nested group first example in nested group | | nested group second example in nested group | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/ruby.feature0000664000000000000000000000147114557677674025465 0ustar rootrootFeature: Run with `ruby` command You can use the `ruby` command to run specs. You just need to require `rspec/autorun`. Generally speaking, you're better off using the `rspec` command, which avoids the complexity of `rspec/autorun` (e.g. no `at_exit` hook needed!), but some tools only work with the `ruby` command. Scenario: Require `rspec/autorun` from a spec file Given a file named "example_spec.rb" with: """ruby require 'rspec/autorun' RSpec.describe 1 do it "is < 2" do expect(1).to be < 2 end it "has an intentional failure" do expect(1).to be > 2 end end """ When I run `ruby example_spec.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "expect(1).to be > 2" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/format_option.feature0000664000000000000000000000522414557677674027364 0ustar rootrootFeature: `--format` option Use the `--format` option to tell RSpec how to format the output. RSpec ships with several formatters built in. By default, it uses the progress formatter, which generates output like this: ....F.....*..... A '.' represents a passing example, 'F' is failing, and '*' is pending. Use the documentation formatter to see the documentation strings passed to `describe`, `it`, and their aliases: ```bash $ rspec spec --format documentation ``` You can also specify an output target (`$stdout` by default) with an `--out` option immediately following the `--format` option: ```bash $ rspec spec --format documentation --out rspec.txt ``` Run `rspec --help` to see a listing of available formatters. Background: Given a file named "example_spec.rb" with: """ruby RSpec.describe "something" do it "does something that passes" do expect(5).to eq(5) end it "does something that fails" do expect(5).to eq(4) end it "does something that is pending", :pending => true do expect(5).to be < 3 end it "does something that is skipped", :skip => true do expect(5).to be < 3 end end """ Scenario: Progress bar format (default) When I run `rspec --format progress example_spec.rb` Then the output should contain ".F**" Scenario: Documentation format When I run `rspec example_spec.rb --format documentation` Then the output should contain: """ something does something that passes does something that fails (FAILED - 1) does something that is pending (PENDING: No reason given) does something that is skipped (PENDING: No reason given) """ Scenario: Documentation format saved to a file When I run `rspec example_spec.rb --format documentation --out rspec.txt` Then the file "rspec.txt" should contain: """ something does something that passes does something that fails (FAILED - 1) does something that is pending (PENDING: No reason given) does something that is skipped (PENDING: No reason given) """ Scenario: Multiple formats and output targets When I run `rspec example_spec.rb --format progress --format documentation --out rspec.txt` Then the output should contain ".F**" And the file "rspec.txt" should contain: """ something does something that passes does something that fails (FAILED - 1) does something that is pending (PENDING: No reason given) does something that is skipped (PENDING: No reason given) """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/bisect.feature0000664000000000000000000002156314557677674025761 0ustar rootroot@with-clean-spec-opts Feature: Bisect RSpec's `--order random` and `--seed` options help surface flickering examples that only fail when one or more other examples are executed first. It can be very difficult to isolate the exact combination of examples that triggers the failure. The `--bisect` flag helps solve that problem. Pass the `--bisect` option (in addition to `--seed` and any other options) and RSpec will repeatedly run subsets of your suite in order to isolate the minimal set of examples that reproduce the same failures. At any point during the bisect run, you can hit ctrl-c to abort and it will provide you with the most minimal reproduction command it has discovered so far. To get more detailed output (particularly useful if you want to report a bug with bisect), use `--bisect=verbose`. Background: Given a file named "lib/calculator.rb" with: """ruby class Calculator def self.add(x, y) x + y end end """ And a file named "spec/calculator_1_spec.rb" with: """ruby require 'calculator' RSpec.describe "Calculator" do it 'adds numbers' do expect(Calculator.add(1, 2)).to eq(3) end end """ And files "spec/calculator_2_spec.rb" through "spec/calculator_9_spec.rb" with an unrelated passing spec in each file And a file named "spec/calculator_10_spec.rb" with: """ruby require 'calculator' RSpec.describe "Monkey patched Calculator" do it 'does screwy math' do # monkey patching `Calculator` affects examples that are # executed after this one! def Calculator.add(x, y) x - y end expect(Calculator.add(5, 10)).to eq(-5) end end """ Scenario: Use `--bisect` flag to create a minimal repro case for the ordering dependency When I run `rspec --seed 1234` Then the output should contain "10 examples, 1 failure" When I run `rspec --seed 1234 --bisect` Then bisect should succeed with output like: """ Bisect started using options: "--seed 1234" Running suite to find failures... (0.16755 seconds) Starting bisect with 1 failing example and 9 non-failing examples. Checking that failure(s) are order-dependent... failure appears to be order-dependent Round 1: bisecting over non-failing examples 1-9 .. ignoring examples 6-9 (0.30166 seconds) Round 2: bisecting over non-failing examples 1-5 .. ignoring examples 4-5 (0.30306 seconds) Round 3: bisecting over non-failing examples 1-3 .. ignoring example 3 (0.33292 seconds) Round 4: bisecting over non-failing examples 1-2 . ignoring example 1 (0.16476 seconds) Bisect complete! Reduced necessary non-failing examples from 9 to 1 in 1.26 seconds. The minimal reproduction command is: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234 """ When I run `rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234` Then the output should contain "2 examples, 1 failure" Scenario: Ctrl-C can be used to abort the bisect early and get the most minimal command it has discovered so far When I run `rspec --seed 1234 --bisect` and abort in the middle with ctrl-c Then bisect should fail with output like: """ Bisect started using options: "--seed 1234" Running suite to find failures... (0.17102 seconds) Starting bisect with 1 failing example and 9 non-failing examples. Checking that failure(s) are order-dependent... failure appears to be order-dependent Round 1: bisecting over non-failing examples 1-9 .. ignoring examples 6-9 (0.32943 seconds) Round 2: bisecting over non-failing examples 1-5 .. ignoring examples 4-5 (0.3154 seconds) Round 3: bisecting over non-failing examples 1-3 .. ignoring example 3 (0.2175 seconds) Bisect aborted! The most minimal reproduction command discovered so far is: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234 """ When I run `rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234` Then the output should contain "3 examples, 1 failure" Scenario: Use `--bisect=verbose` to enable verbose debug mode for more detail When I run `rspec --seed 1234 --bisect=verbose` Then bisect should succeed with output like: """ Bisect started using options: "--seed 1234" and bisect runner: :fork Running suite to find failures... (0.16528 seconds) - Failing examples (1): - ./spec/calculator_1_spec.rb[1:1] - Non-failing examples (9): - ./spec/calculator_10_spec.rb[1:1] - ./spec/calculator_2_spec.rb[1:1] - ./spec/calculator_3_spec.rb[1:1] - ./spec/calculator_4_spec.rb[1:1] - ./spec/calculator_5_spec.rb[1:1] - ./spec/calculator_6_spec.rb[1:1] - ./spec/calculator_7_spec.rb[1:1] - ./spec/calculator_8_spec.rb[1:1] - ./spec/calculator_9_spec.rb[1:1] Checking that failure(s) are order-dependent.. - Running: rspec ./spec/calculator_1_spec.rb[1:1] --seed 1234 (n.nnnn seconds) - Failure appears to be order-dependent Round 1: bisecting over non-failing examples 1-9 - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_6_spec.rb[1:1] ./spec/calculator_7_spec.rb[1:1] ./spec/calculator_8_spec.rb[1:1] ./spec/calculator_9_spec.rb[1:1] --seed 1234 (0.15302 seconds) - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] ./spec/calculator_4_spec.rb[1:1] ./spec/calculator_5_spec.rb[1:1] --seed 1234 (0.19708 seconds) - Examples we can safely ignore (4): - ./spec/calculator_6_spec.rb[1:1] - ./spec/calculator_7_spec.rb[1:1] - ./spec/calculator_8_spec.rb[1:1] - ./spec/calculator_9_spec.rb[1:1] - Remaining non-failing examples (5): - ./spec/calculator_10_spec.rb[1:1] - ./spec/calculator_2_spec.rb[1:1] - ./spec/calculator_3_spec.rb[1:1] - ./spec/calculator_4_spec.rb[1:1] - ./spec/calculator_5_spec.rb[1:1] Round 2: bisecting over non-failing examples 1-5 - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_4_spec.rb[1:1] ./spec/calculator_5_spec.rb[1:1] --seed 1234 (0.15836 seconds) - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234 (0.19065 seconds) - Examples we can safely ignore (2): - ./spec/calculator_4_spec.rb[1:1] - ./spec/calculator_5_spec.rb[1:1] - Remaining non-failing examples (3): - ./spec/calculator_10_spec.rb[1:1] - ./spec/calculator_2_spec.rb[1:1] - ./spec/calculator_3_spec.rb[1:1] Round 3: bisecting over non-failing examples 1-3 - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] --seed 1234 (0.21028 seconds) - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234 (0.1975 seconds) - Examples we can safely ignore (1): - ./spec/calculator_2_spec.rb[1:1] - Remaining non-failing examples (2): - ./spec/calculator_10_spec.rb[1:1] - ./spec/calculator_3_spec.rb[1:1] Round 4: bisecting over non-failing examples 1-2 - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234 (0.17173 seconds) - Examples we can safely ignore (1): - ./spec/calculator_3_spec.rb[1:1] - Remaining non-failing examples (1): - ./spec/calculator_10_spec.rb[1:1] Bisect complete! Reduced necessary non-failing examples from 9 to 1 in 1.47 seconds. The minimal reproduction command is: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234 """ When I run `rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234` Then the output should contain "2 examples, 1 failure" Scenario: Pick a bisect runner via a config option Given a file named "spec/spec_helper.rb" with: """ RSpec.configure do |c| c.bisect_runner = :shell end """ And a file named ".rspec" with: """ --require spec_helper """ When I run `rspec --seed 1234 --bisect=verbose` Then bisect should succeed with output like: """ Bisect started using options: "--seed 1234" and bisect runner: :shell # ... The minimal reproduction command is: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234 """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/features/command_line/exit_status.feature0000664000000000000000000000360514557677674027061 0ustar rootrootFeature: `--failure-exit-code` option (exit status) The `rspec` command exits with an exit status of 0 if all examples pass, and 1 if any examples fail. The failure exit code can be overridden using the `--failure-exit-code` option. Scenario: A passing spec with the default exit code Given a file named "ok_spec.rb" with: """ruby RSpec.describe "ok" do it "passes" do end end """ When I run `rspec ok_spec.rb` Then the exit status should be 0 And the examples should all pass Scenario: A failing spec with the default exit code Given a file named "ko_spec.rb" with: """ruby RSpec.describe "KO" do it "fails" do raise "KO" end end """ When I run `rspec ko_spec.rb` Then the exit status should be 1 And the output should contain "1 example, 1 failure" Scenario: A nested failing spec with the default exit code Given a file named "nested_ko_spec.rb" with: """ruby RSpec.describe "KO" do describe "nested" do it "fails" do raise "KO" end end end """ When I run `rspec nested_ko_spec.rb` Then the exit status should be 1 And the output should contain "1 example, 1 failure" Scenario: Exit with 0 when no examples are run Given a file named "a_no_examples_spec.rb" with: """ruby """ When I run `rspec a_no_examples_spec.rb` Then the exit status should be 0 And the output should contain "0 examples" Scenario: A failing spec and `--failure-exit-code` is 42 Given a file named "ko_spec.rb" with: """ruby RSpec.describe "KO" do it "fails" do raise "KO" end end """ When I run `rspec --failure-exit-code 42 ko_spec.rb` Then the exit status should be 42 And the output should contain "1 example, 1 failure" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/.gitignore0000664000000000000000000000027114557677674020651 0ustar rootroot.rvmrc *.sw? .DS_Store coverage* doc rdoc pkg tmp tags rerun.txt Gemfile.lock .bundle *.rbc bin .rbx .yardoc vendor Gemfile-custom .idea bundle .rspec-local spec/examples.txt specs.out ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/0000775000000000000000000000000014557677674017427 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/0000775000000000000000000000000014557677674020543 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/0000775000000000000000000000000014557677674021473 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/shared_example_group.rb0000664000000000000000000002403714557677674026223 0ustar rootrootRSpec::Support.require_rspec_support "with_keywords_when_needed" module RSpec module Core # Represents some functionality that is shared with multiple example groups. # The functionality is defined by the provided block, which is lazily # eval'd when the `SharedExampleGroupModule` instance is included in an example # group. class SharedExampleGroupModule < Module # @private attr_reader :definition def initialize(description, definition, metadata) @description = description @definition = definition @metadata = metadata end # Provides a human-readable representation of this module. def inspect "#<#{self.class.name} #{@description.inspect}>" end alias to_s inspect # Ruby callback for when a module is included in another module is class. # Our definition evaluates the shared group block in the context of the # including example group. def included(klass) inclusion_line = klass.metadata[:location] include_in klass, inclusion_line, [], nil end # @private def include_in(klass, inclusion_line, args, customization_block) klass.update_inherited_metadata(@metadata) unless @metadata.empty? SharedExampleGroupInclusionStackFrame.with_frame(@description, inclusion_line) do RSpec::Support::WithKeywordsWhenNeeded.class_exec(klass, *args, &@definition) klass.class_exec(&customization_block) if customization_block end end end # Shared example groups let you define common context and/or common # examples that you wish to use in multiple example groups. # # When defined, the shared group block is stored for later evaluation. # It can later be included in an example group either explicitly # (using `include_examples`, `include_context` or `it_behaves_like`) # or implicitly (via matching metadata). # # Named shared example groups are scoped based on where they are # defined. Shared groups defined in an example group are available # for inclusion in that example group or any child example groups, # but not in any parent or sibling example groups. Shared example # groups defined at the top level can be included from any example group. module SharedExampleGroup # @overload shared_examples(name, &block) # @param name [String, Symbol, Module] identifer to use when looking up # this shared group # @param block The block to be eval'd # @overload shared_examples(name, metadata, &block) # @param name [String, Symbol, Module] identifer to use when looking up # this shared group # @param metadata [Array, Hash] metadata to attach to this # group; any example group or example with matching metadata will # automatically include this shared example group. # @param block The block to be eval'd # # Stores the block for later use. The block will be evaluated # in the context of an example group via `include_examples`, # `include_context`, or `it_behaves_like`. # # @example # shared_examples "auditable" do # it "stores an audit record on save!" do # expect { auditable.save! }.to change(Audit, :count).by(1) # end # end # # RSpec.describe Account do # it_behaves_like "auditable" do # let(:auditable) { Account.new } # end # end # # @see ExampleGroup.it_behaves_like # @see ExampleGroup.include_examples # @see ExampleGroup.include_context def shared_examples(name, *args, &block) top_level = self == ExampleGroup if top_level && RSpec::Support.thread_local_data[:in_example_group] raise "Creating isolated shared examples from within a context is " \ "not allowed. Remove `RSpec.` prefix or move this to a " \ "top-level scope." end RSpec.world.shared_example_group_registry.add(self, name, *args, &block) end alias shared_context shared_examples alias shared_examples_for shared_examples # @api private # # Shared examples top level DSL. module TopLevelDSL # @private def self.definitions proc do def shared_examples(name, *args, &block) RSpec.world.shared_example_group_registry.add(:main, name, *args, &block) end alias shared_context shared_examples alias shared_examples_for shared_examples end end # @private def self.exposed_globally? @exposed_globally ||= false end # @api private # # Adds the top level DSL methods to Module and the top level binding. def self.expose_globally! return if exposed_globally? Core::DSL.change_global_dsl(&definitions) @exposed_globally = true end # @api private # # Removes the top level DSL methods to Module and the top level binding. def self.remove_globally! return unless exposed_globally? Core::DSL.change_global_dsl do undef shared_examples undef shared_context undef shared_examples_for end @exposed_globally = false end end # @private class Registry def add(context, name, *metadata_args, &block) unless block RSpec.warning "Shared example group #{name} was defined without a "\ "block and will have no effect. Please define a "\ "block or remove the definition." end if RSpec.configuration.shared_context_metadata_behavior == :trigger_inclusion return legacy_add(context, name, *metadata_args, &block) end unless valid_name?(name) raise ArgumentError, "Shared example group names can only be a string, " \ "symbol or module but got: #{name.inspect}" end ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line } warn_if_key_taken context, name, block metadata = Metadata.build_hash_from(metadata_args) shared_module = SharedExampleGroupModule.new(name, block, metadata) shared_example_groups[context][name] = shared_module end def find(lookup_contexts, name) lookup_contexts.each do |context| found = shared_example_groups[context][name] return found if found end shared_example_groups[:main][name] end private # TODO: remove this in RSpec 4. This exists only to support # `config.shared_context_metadata_behavior == :trigger_inclusion`, # the legacy behavior of shared context metadata, which we do # not want to support in RSpec 4. def legacy_add(context, name, *metadata_args, &block) ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line } shared_module = SharedExampleGroupModule.new(name, block, {}) if valid_name?(name) warn_if_key_taken context, name, block shared_example_groups[context][name] = shared_module else metadata_args.unshift name end return if metadata_args.empty? RSpec.configuration.include shared_module, *metadata_args end def shared_example_groups @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} } end def valid_name?(candidate) case candidate when String, Symbol, Module then true else false end end def warn_if_key_taken(context, key, new_block) existing_module = shared_example_groups[context][key] return unless existing_module old_definition_location = formatted_location existing_module.definition new_definition_location = formatted_location new_block loaded_spec_files = RSpec.configuration.loaded_spec_files if loaded_spec_files.include?(new_definition_location) && old_definition_location == new_definition_location RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil |WARNING: Your shared example group, '#{key}', defined at: | #{old_definition_location} |was automatically loaded by RSpec because the file name |matches the configured autoloading pattern (#{RSpec.configuration.pattern}), |and is also being required from somewhere else. To fix this |warning, either rename the file to not match the pattern, or |do not explicitly require the file. WARNING else RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil |WARNING: Shared example group '#{key}' has been previously defined at: | #{old_definition_location} |...and you are now defining it at: | #{new_definition_location} |The new definition will overwrite the original one. WARNING end end if RUBY_VERSION.to_f >= 1.9 def formatted_location(block) block.source_location.join(":") end else # 1.8.7 # :nocov: def formatted_location(block) block.source_location.join(":").gsub(/:in.*$/, '') end # :nocov: end if Proc.method_defined?(:source_location) def ensure_block_has_source_location(_block); end else # for 1.8.7 # :nocov: def ensure_block_has_source_location(block) source_location = yield.split(':') block.extend(Module.new { define_method(:source_location) { source_location } }) end # :nocov: end end end end instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/test_unit_assertions_adapter.rb0000664000000000000000000000167114557677674030015 0ustar rootrootrequire 'test/unit/assertions' module RSpec module Core # @private module TestUnitAssertionsAdapter include ::Test::Unit::Assertions # If using test/unit from Ruby core with Ruby 1.9+, it includes # MiniTest::Assertions by default. Note the upcasing of 'Test'. # # If the test/unit gem is being loaded, it will not include any minitest # assertions. # # Only if Minitest 5.x is included / loaded do we need to worry about # adding a shim for the new updates. Thus instead of checking on the # RUBY_VERSION we need to check ancestors. begin # MiniTest is 4.x. # Minitest is 5.x. if ancestors.include?(::Minitest::Assertions) require 'rspec/core/minitest_assertions_adapter' include ::RSpec::Core::MinitestAssertionsAdapter end rescue NameError # No-op. Minitest 5.x was not loaded. end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/option_parser.rb0000664000000000000000000003044714557677674024714 0ustar rootroot# http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html require 'optparse' module RSpec::Core # @private class Parser def self.parse(args, source=nil) new(args).parse(source) end attr_reader :original_args def initialize(original_args) @original_args = original_args end def parse(source=nil) return { :files_or_directories_to_run => [] } if original_args.empty? args = original_args.dup options = args.delete('--tty') ? { :tty => true } : {} begin parser(options).parse!(args) rescue OptionParser::InvalidOption => e abort "#{e.message}#{" (defined in #{source})" if source}\n\n" \ "Please use --help for a listing of valid options" end options[:files_or_directories_to_run] = args options end private # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/PerceivedComplexity def parser(options) OptionParser.new do |parser| parser.summary_width = 34 parser.banner = "Usage: rspec [options] [files or directories]\n\n" parser.on('-I PATH', 'Specify PATH to add to $LOAD_PATH (may be used more than once).') do |dirs| options[:libs] ||= [] options[:libs].concat(dirs.split(File::PATH_SEPARATOR)) end parser.on('-r', '--require PATH', 'Require a file.') do |path| options[:requires] ||= [] options[:requires] << path end parser.on('-O', '--options PATH', 'Specify the path to a custom options file.') do |path| options[:custom_options_file] = path end parser.on('--order TYPE[:SEED]', 'Run examples by the specified order type.', ' [defined] examples and groups are run in the order they are defined', ' [rand] randomize the order of groups and examples', ' [random] alias for rand', ' [random:SEED] e.g. --order random:123', ' [recently-modified] run the most recently modified files first') do |o| options[:order] = o end parser.on('--seed SEED', Integer, 'Equivalent of --order rand:SEED.') do |seed| options[:order] = "rand:#{seed}" end parser.on('--bisect[=verbose]', 'Repeatedly runs the suite in order to isolate the failures to the ', ' smallest reproducible case.') do |argument| options[:bisect] = argument || true options[:runner] = RSpec::Core::Invocations::Bisect.new end parser.on('--[no-]fail-fast[=COUNT]', 'Abort the run after a certain number of failures (1 by default).') do |argument| if argument == true value = 1 elsif argument == false || argument == 0 value = false else begin value = Integer(argument) rescue ArgumentError RSpec.warning "Expected an integer value for `--fail-fast`, got: #{argument.inspect}", :call_site => nil end end set_fail_fast(options, value) end parser.on('--failure-exit-code CODE', Integer, 'Override the exit code used when there are failing specs.') do |code| options[:failure_exit_code] = code end parser.on('--error-exit-code CODE', Integer, 'Override the exit code used when there are errors loading or running specs outside of examples.') do |code| options[:error_exit_code] = code end parser.on('-X', '--[no-]drb', 'Run examples via DRb.') do |use_drb| options[:drb] = use_drb options[:runner] = RSpec::Core::Invocations::DRbWithFallback.new if use_drb end parser.on('--drb-port PORT', 'Port to connect to the DRb server.') do |o| options[:drb_port] = o.to_i end parser.separator("\n **** Output ****\n\n") parser.on('-f', '--format FORMATTER', 'Choose a formatter.', ' [p]rogress (default - dots)', ' [d]ocumentation (group and example names)', ' [h]tml', ' [j]son', ' [f]ailures ("file:line:reason", suitable for editors integration)', ' custom formatter class name') do |o| options[:formatters] ||= [] options[:formatters] << [o] end parser.on('-o', '--out FILE', 'Write output to a file instead of $stdout. This option applies', ' to the previously specified --format, or the default format', ' if no format is specified.' ) do |o| options[:formatters] ||= [['progress']] options[:formatters].last << o end parser.on('--deprecation-out FILE', 'Write deprecation warnings to a file instead of $stderr.') do |file| options[:deprecation_stream] = file end parser.on('-b', '--backtrace', 'Enable full backtrace.') do |_o| options[:full_backtrace] = true end parser.on('-c', '--color', '--colour', '') do |_o| # flag will be excluded from `--help` output because it is deprecated options[:color] = true options[:color_mode] = :automatic end parser.on('--force-color', '--force-colour', 'Force the output to be in color, even if the output is not a TTY') do |_o| if options[:color_mode] == :off abort "Please only use one of `--force-color` and `--no-color`" end options[:color_mode] = :on end parser.on('--no-color', '--no-colour', 'Force the output to not be in color, even if the output is a TTY') do |_o| if options[:color_mode] == :on abort "Please only use one of --force-color and --no-color" end options[:color_mode] = :off end parser.on('-p', '--[no-]profile [COUNT]', 'Enable profiling of examples and list the slowest examples (default: 10).') do |argument| options[:profile_examples] = if argument.nil? true elsif argument == false false else begin Integer(argument) rescue ArgumentError RSpec.warning "Non integer specified as profile count, separate " \ "your path from options with -- e.g. " \ "`rspec --profile -- #{argument}`", :call_site => nil true end end end parser.on('--dry-run', 'Print the formatter output of your suite without', ' running any examples or hooks') do |_o| options[:dry_run] = true end parser.on('-w', '--warnings', 'Enable ruby warnings') do if Object.const_defined?(:Warning) && Warning.respond_to?(:[]=) Warning[:deprecated] = true end $VERBOSE = true end parser.separator <<-FILTERING **** Filtering/tags **** In addition to the following options for selecting specific files, groups, or examples, you can select individual examples by appending the line number(s) to the filename: rspec path/to/a_spec.rb:37:87 You can also pass example ids enclosed in square brackets: rspec path/to/a_spec.rb[1:5,1:6] # run the 5th and 6th examples/groups defined in the 1st group FILTERING parser.on('--only-failures', "Filter to just the examples that failed the last time they ran.") do configure_only_failures(options) end parser.on("-n", "--next-failure", "Apply `--only-failures` and abort after one failure.", " (Equivalent to `--only-failures --fail-fast --order defined`)") do configure_only_failures(options) set_fail_fast(options, 1) options[:order] ||= 'defined' end parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec/**/*_spec.rb").') do |o| if options[:pattern] options[:pattern] += ',' + o else options[:pattern] = o end end parser.on('--exclude-pattern PATTERN', 'Load files except those matching pattern. Opposite effect of --pattern.') do |o| options[:exclude_pattern] = o end parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING (may be", " used more than once)") do |o| (options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o)) end parser.on('-E', '--example-matches REGEX', "Run examples whose full nested names match REGEX (may be", " used more than once)") do |o| (options[:full_description] ||= []) << Regexp.compile(o) end parser.on('-t', '--tag TAG[:VALUE]', 'Run examples with the specified tag, or exclude examples', 'by adding ~ before the tag.', ' - e.g. ~slow', ' - TAG is always converted to a symbol') do |tag| filter_type = tag =~ /^~/ ? :exclusion_filter : :inclusion_filter name, value = tag.gsub(/^(~@|~|@)/, '').split(':', 2) name = name.to_sym parsed_value = case value when nil then true # The default value for tags is true when 'true' then true when 'false' then false when 'nil' then nil when /^:/ then value[1..-1].to_sym when /^\d+$/ then Integer(value) when /^\d+.\d+$/ then Float(value) else value end add_tag_filter(options, filter_type, name, parsed_value) end parser.on('--default-path PATH', 'Set the default path where RSpec looks for examples (can', ' be a path to a file or a directory).') do |path| options[:default_path] = path end parser.separator("\n **** Utility ****\n\n") parser.on('--init', 'Initialize your project with RSpec.') do |_cmd| options[:runner] = RSpec::Core::Invocations::InitializeProject.new end parser.on('-v', '--version', 'Display the version.') do options[:runner] = RSpec::Core::Invocations::PrintVersion.new end # These options would otherwise be confusing to users, so we forcibly # prevent them from executing. # # * --I is too similar to -I. # * -d was a shorthand for --debugger, which is removed, but now would # trigger --default-path. invalid_options = %w[-d --I] hidden_options = invalid_options + %w[-c] parser.on_tail('-h', '--help', "You're looking at it.") do options[:runner] = RSpec::Core::Invocations::PrintHelp.new(parser, hidden_options) end # This prevents usage of the invalid_options. invalid_options.each do |option| parser.on(option) do raise OptionParser::InvalidOption.new end end end end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity def add_tag_filter(options, filter_type, tag_name, value=true) (options[filter_type] ||= {})[tag_name] = value end def set_fail_fast(options, value) options[:fail_fast] = value end def configure_only_failures(options) options[:only_failures] = true add_tag_filter(options, :inclusion_filter, :last_run_status, 'failed') end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/minitest_assertions_adapter.rb0000664000000000000000000000175214557677674027633 0ustar rootrootbegin # Only the minitest 5.x gem includes the minitest.rb and assertions.rb files. require 'minitest' require 'minitest/assertions' rescue LoadError # We must be using Ruby Core's MiniTest or the Minitest gem 4.x. require 'minitest/unit' Minitest = MiniTest end module RSpec module Core # @private module MinitestAssertionsAdapter include ::Minitest::Assertions # Need to forcefully include Pending after Minitest::Assertions # to make sure our own #skip method beats Minitest's. include ::RSpec::Core::Pending # Minitest 5.x requires this accessor to be available. See # https://github.com/seattlerb/minitest/blob/38f0a5fcbd9c37c3f80a3eaad4ba84d3fc9947a0/lib/minitest/assertions.rb#L8 # # It is not required for other extension libraries, and RSpec does not # report or make this information available to formatters. attr_writer :assertions def assertions @assertions ||= 0 end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/ruby_project.rb0000664000000000000000000000265114557677674024533 0ustar rootroot# This is borrowed (slightly modified) from Scott Taylor's # project_path project: # http://github.com/smtlaissezfaire/project_path module RSpec module Core # @private module RubyProject def add_to_load_path(*dirs) dirs.each { |dir| add_dir_to_load_path(File.join(root, dir)) } end def add_dir_to_load_path(dir) $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) end def root @project_root ||= determine_root end def determine_root find_first_parent_containing('spec') || '.' end def find_first_parent_containing(dir) ascend_until { |path| File.exist?(File.join(path, dir)) } end def ascend_until fs = File::SEPARATOR escaped_slash = "\\#{fs}" special = "_RSPEC_ESCAPED_SLASH_" project_path = File.expand_path(".") parts = project_path.gsub(escaped_slash, special).squeeze(fs).split(fs).map do |x| x.gsub(special, escaped_slash) end until parts.empty? path = parts.join(fs) path = fs if path == "" return path if yield(path) parts.pop end end module_function :add_to_load_path module_function :add_dir_to_load_path module_function :root module_function :determine_root module_function :find_first_parent_containing module_function :ascend_until end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters.rb0000664000000000000000000002316314557677674024213 0ustar rootrootRSpec::Support.require_rspec_support "directory_maker" # ## Built-in Formatters # # * progress (default) - Prints dots for passing examples, `F` for failures, `*` # for pending. # * documentation - Prints the docstrings passed to `describe` and `it` methods # (and their aliases). # * html # * json - Useful for archiving data for subsequent analysis. # # The progress formatter is the default, but you can choose any one or more of # the other formatters by passing with the `--format` (or `-f` for short) # command-line option, e.g. # # rspec --format documentation # # You can also send the output of multiple formatters to different streams, e.g. # # rspec --format documentation --format html --out results.html # # This example sends the output of the documentation formatter to `$stdout`, and # the output of the html formatter to results.html. # # ## Custom Formatters # # You can tell RSpec to use a custom formatter by passing its path and name to # the `rspec` command. For example, if you define MyCustomFormatter in # path/to/my_custom_formatter.rb, you would type this command: # # rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter # # The reporter calls every formatter with this protocol: # # * To start # * `start(StartNotification)` # * Once per example group # * `example_group_started(GroupNotification)` # * Once per example # * `example_started(ExampleNotification)` # * One of these per example, depending on outcome # * `example_passed(ExampleNotification)` # * `example_failed(FailedExampleNotification)` # * `example_pending(ExampleNotification)` # * Optionally at any time # * `message(MessageNotification)` # * At the end of the suite # * `stop(ExamplesNotification)` # * `start_dump(NullNotification)` # * `dump_pending(ExamplesNotification)` # * `dump_failures(ExamplesNotification)` # * `dump_summary(SummaryNotification)` # * `seed(SeedNotification)` # * `close(NullNotification)` # # Only the notifications to which you subscribe your formatter will be called # on your formatter. To subscribe your formatter use: # `RSpec::Core::Formatters#register` e.g. # # `RSpec::Core::Formatters.register FormatterClassName, :example_passed, :example_failed` # # We recommend you implement the methods yourself; for simplicity we provide the # default formatter output via our notification objects but if you prefer you # can subclass `RSpec::Core::Formatters::BaseTextFormatter` and override the # methods you wish to enhance. # # @see RSpec::Core::Formatters::BaseTextFormatter # @see RSpec::Core::Reporter module RSpec::Core::Formatters autoload :DocumentationFormatter, 'rspec/core/formatters/documentation_formatter' autoload :HtmlFormatter, 'rspec/core/formatters/html_formatter' autoload :FallbackMessageFormatter, 'rspec/core/formatters/fallback_message_formatter' autoload :ProgressFormatter, 'rspec/core/formatters/progress_formatter' autoload :ProfileFormatter, 'rspec/core/formatters/profile_formatter' autoload :JsonFormatter, 'rspec/core/formatters/json_formatter' autoload :BisectDRbFormatter, 'rspec/core/formatters/bisect_drb_formatter' autoload :ExceptionPresenter, 'rspec/core/formatters/exception_presenter' autoload :FailureListFormatter, 'rspec/core/formatters/failure_list_formatter' # Register the formatter class # @param formatter_class [Class] formatter class to register # @param notifications [Array] one or more notifications to be # registered to the specified formatter # # @see RSpec::Core::Formatters::BaseFormatter def self.register(formatter_class, *notifications) Loader.formatters[formatter_class] = notifications end # @api private # # `RSpec::Core::Formatters::Loader` is an internal class for # managing formatters used by a particular configuration. It is # not expected to be used directly, but only through the configuration # interface. class Loader # @api private # # Internal formatters are stored here when loaded. def self.formatters @formatters ||= {} end # @api private def initialize(reporter) @formatters = [] @reporter = reporter self.default_formatter = 'progress' end # @return [Array] the loaded formatters attr_reader :formatters # @return [Reporter] the reporter attr_reader :reporter # @return [String] the default formatter to setup, defaults to `progress` attr_accessor :default_formatter # @private def prepare_default(output_stream, deprecation_stream) reporter.prepare_default(self, output_stream, deprecation_stream) end # @private def setup_default(output_stream, deprecation_stream) add default_formatter, output_stream if @formatters.empty? unless @formatters.any? { |formatter| DeprecationFormatter === formatter } add DeprecationFormatter, deprecation_stream, output_stream end unless existing_formatter_implements?(:message) add FallbackMessageFormatter, output_stream end return unless RSpec.configuration.profile_examples? return if existing_formatter_implements?(:dump_profile) add RSpec::Core::Formatters::ProfileFormatter, output_stream end # @private def add(formatter_to_use, *paths) # If a formatter instance was passed, we can register it directly, # with no need for any of the further processing that happens below. if Loader.formatters.key?(formatter_to_use.class) register formatter_to_use, notifications_for(formatter_to_use.class) return end formatter_class = find_formatter(formatter_to_use) args = paths.map { |p| p.respond_to?(:puts) ? p : open_stream(p) } if !Loader.formatters[formatter_class].nil? formatter = formatter_class.new(*args) register formatter, notifications_for(formatter_class) elsif defined?(RSpec::LegacyFormatters) formatter = RSpec::LegacyFormatters.load_formatter formatter_class, *args register formatter, formatter.notifications else call_site = "Formatter added at: #{::RSpec::CallerFilter.first_non_rspec_line}" RSpec.warn_deprecation <<-WARNING.gsub(/\s*\|/, ' ') |The #{formatter_class} formatter uses the deprecated formatter |interface not supported directly by RSpec 3. | |To continue to use this formatter you must install the |`rspec-legacy_formatters` gem, which provides support |for legacy formatters or upgrade the formatter to a |compatible version. | |#{call_site} WARNING end end private def find_formatter(formatter_to_use) built_in_formatter(formatter_to_use) || custom_formatter(formatter_to_use) || (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - " \ "maybe you meant 'documentation' or 'progress'?.") end def register(formatter, notifications) return if duplicate_formatter_exists?(formatter) @reporter.register_listener formatter, *notifications @formatters << formatter formatter end def duplicate_formatter_exists?(new_formatter) @formatters.any? do |formatter| formatter.class == new_formatter.class && has_matching_output?(formatter, new_formatter) end end def has_matching_output?(formatter, new_formatter) return true unless formatter.respond_to?(:output) && new_formatter.respond_to?(:output) formatter.output == new_formatter.output end def existing_formatter_implements?(notification) @reporter.registered_listeners(notification).any? end def built_in_formatter(key) case key.to_s when 'd', 'doc', 'documentation' DocumentationFormatter when 'h', 'html' HtmlFormatter when 'p', 'progress' ProgressFormatter when 'j', 'json' JsonFormatter when 'bisect-drb' BisectDRbFormatter when 'f', 'failures' FailureListFormatter end end def notifications_for(formatter_class) formatter_class.ancestors.inject(::RSpec::Core::Set.new) do |notifications, klass| notifications.merge Loader.formatters.fetch(klass) { ::RSpec::Core::Set.new } end end def custom_formatter(formatter_ref) if Class === formatter_ref formatter_ref elsif string_const?(formatter_ref) begin formatter_ref.gsub(/^::/, '').split('::').inject(Object) { |a, e| a.const_get e } rescue NameError require(path_for(formatter_ref)) ? retry : raise end end end def string_const?(str) str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str end def path_for(const_ref) underscore_with_fix_for_non_standard_rspec_naming(const_ref) end def underscore_with_fix_for_non_standard_rspec_naming(string) underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2') end # activesupport/lib/active_support/inflector/methods.rb, line 48 def underscore(camel_cased_word) word = camel_cased_word.to_s.dup word.gsub!(/::/, '/') word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.tr!("-", "_") word.downcase! word end def open_stream(path_or_wrapper) if RSpec::Core::OutputWrapper === path_or_wrapper path_or_wrapper.output = open_stream(path_or_wrapper.output) path_or_wrapper else RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path_or_wrapper)) File.new(path_or_wrapper, 'w') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/memoized_helpers.rb0000664000000000000000000004700214557677674025356 0ustar rootrootRSpec::Support.require_rspec_support 'reentrant_mutex' module RSpec module Core # This module is included in {ExampleGroup}, making the methods # available to be called from within example blocks. # # @see ClassMethods module MemoizedHelpers # @note `subject` was contributed by Joe Ferris to support the one-liner # syntax embraced by shoulda matchers: # # RSpec.describe Widget do # it { is_expected.to validate_presence_of(:name) } # # or # it { should validate_presence_of(:name) } # end # # While the examples below demonstrate how to use `subject` # explicitly in examples, we recommend that you define a method with # an intention revealing name instead. # # @example # # # Explicit declaration of subject. # RSpec.describe Person do # subject { Person.new(:birthdate => 19.years.ago) } # it "should be eligible to vote" do # subject.should be_eligible_to_vote # # ^ ^ explicit reference to subject not recommended # end # end # # # Implicit subject => { Person.new }. # RSpec.describe Person do # it "should be eligible to vote" do # subject.should be_eligible_to_vote # # ^ ^ explicit reference to subject not recommended # end # end # # # One-liner syntax - expectation is set on the subject. # RSpec.describe Person do # it { is_expected.to be_eligible_to_vote } # # or # it { should be_eligible_to_vote } # end # # @note Because `subject` is designed to create state that is reset # between each example, and `before(:context)` is designed to setup # state that is shared across _all_ examples in an example group, # `subject` is _not_ intended to be used in a `before(:context)` hook. # # @see #should # @see #should_not # @see #is_expected def subject __memoized.fetch_or_store(:subject) do described = described_class || self.class.metadata.fetch(:description_args).first Class === described ? described.new : described end end # When `should` is called with no explicit receiver, the call is # delegated to the object returned by `subject`. Combined with an # implicit subject this supports very concise expressions. # # @example # # RSpec.describe Person do # it { should be_eligible_to_vote } # end # # @see #subject # @see #is_expected # # @note This only works if you are using rspec-expectations. # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to` instead of `should`. def should(matcher=nil, message=nil) enforce_value_expectation(matcher, 'should') RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message) end # Just like `should`, `should_not` delegates to the subject (implicit or # explicit) of the example group. # # @example # # RSpec.describe Person do # it { should_not be_eligible_to_vote } # end # # @see #subject # @see #is_expected # # @note This only works if you are using rspec-expectations. # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to_not` instead of `should_not`. def should_not(matcher=nil, message=nil) enforce_value_expectation(matcher, 'should_not') RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message) end # Wraps the `subject` in `expect` to make it the target of an expectation. # Designed to read nicely for one-liners. # # @example # # describe [1, 2, 3] do # it { is_expected.to be_an Array } # it { is_expected.not_to include 4 } # end # # @see #subject # @see #should # @see #should_not # # @note This only works if you are using rspec-expectations. def is_expected expect(subject) end # @private # should just be placed in private section, # but Ruby issues warnings on private attributes. # and expanding it to the equivalent method upsets Rubocop, # b/c it should obviously be a reader attr_reader :__memoized private :__memoized private # @private def initialize(*) __init_memoized super end # @private def __init_memoized @__memoized = if RSpec.configuration.threadsafe? ThreadsafeMemoized.new else NonThreadSafeMemoized.new end end # @private def enforce_value_expectation(matcher, method_name) return if matcher_supports_value_expectations?(matcher) RSpec.deprecate( "#{method_name} #{RSpec::Support::ObjectFormatter.format(matcher)}", :message => "The implicit block expectation syntax is deprecated, you should pass " \ "a block to `expect` to use the provided block expectation matcher " \ "(#{RSpec::Support::ObjectFormatter.format(matcher)}), " \ "or the matcher must implement `supports_value_expectations?`." ) end def matcher_supports_value_expectations?(matcher) matcher.supports_value_expectations? rescue true end # @private class ThreadsafeMemoized def initialize @memoized = {} @mutex = Support::ReentrantMutex.new end def fetch_or_store(key) @memoized.fetch(key) do # only first access pays for synchronization @mutex.synchronize do @memoized.fetch(key) { @memoized[key] = yield } end end end end # @private class NonThreadSafeMemoized def initialize @memoized = {} end def fetch_or_store(key) @memoized.fetch(key) { @memoized[key] = yield } end end # Used internally to customize the behavior of the # memoized hash when used in a `before(:context)` hook. # # @private class ContextHookMemoized def self.isolate_for_context_hook(example_group_instance) exploding_memoized = self example_group_instance.instance_exec do @__memoized = exploding_memoized begin yield ensure # This is doing a reset instead of just isolating for context hook. # Really, this should set the old @__memoized back into place. # # Caller is the before and after context hooks # which are both called from self.run # I didn't look at why it made tests fail, maybe an object was getting reused in RSpec tests, # if so, then that probably already works, and its the tests that are wrong. __init_memoized end end end def self.fetch_or_store(key, &_block) description = if key == :subject "subject" else "let declaration `#{key}`" end raise <<-EOS #{description} accessed in #{article} #{hook_expression} hook at: #{CallerFilter.first_non_rspec_line} `let` and `subject` declarations are not intended to be called in #{article} #{hook_expression} hook, as they exist to define state that is reset between each example, while #{hook_expression} exists to #{hook_intention}. EOS end # @private class Before < self def self.hook_expression "`before(:context)`" end def self.article "a" end def self.hook_intention "define state that is shared across examples in an example group" end end # @private class After < self def self.hook_expression "`after(:context)`" end def self.article "an" end def self.hook_intention "cleanup state that is shared across examples in an example group" end end end # This module is extended onto {ExampleGroup}, making the methods # available to be called from within example group blocks. # You can think of them as being analagous to class macros. module ClassMethods # Generates a method whose return value is memoized after the first # call. Useful for reducing duplication between examples that assign # values to the same local variable. # # @note `let` _can_ enhance readability when used sparingly (1,2, or # maybe 3 declarations) in any given example group, but that can # quickly degrade with overuse. YMMV. # # @note `let` can be configured to be threadsafe or not. # If it is threadsafe, it will take longer to access the value. # If it is not threadsafe, it may behave in surprising ways in examples # that spawn separate threads. Specify this on `RSpec.configure` # # @note Because `let` is designed to create state that is reset between # each example, and `before(:context)` is designed to setup state that # is shared across _all_ examples in an example group, `let` is _not_ # intended to be used in a `before(:context)` hook. # # @example # # RSpec.describe Thing do # let(:thing) { Thing.new } # # it "does something" do # # First invocation, executes block, memoizes and returns result. # thing.do_something # # # Second invocation, returns the memoized value. # thing.should be_something # end # end def let(name, &block) # We have to pass the block directly to `define_method` to # allow it to use method constructs like `super` and `return`. raise "#let or #subject called without a block" if block.nil? # A list of reserved words that can't be used as a name for a memoized helper # Matches for both symbols and passed strings if [:initialize, :to_s].include?(name.to_sym) raise ArgumentError, "#let or #subject called with reserved name `#{name}`" end our_module = MemoizedHelpers.module_for(self) # If we have a module clash in our helper module # then we need to remove it to prevent a warning. # # Note we do not check ancestor modules (see: `instance_methods(false)`) # as we can override them. if our_module.instance_methods(false).include?(name) our_module.__send__(:remove_method, name) end our_module.__send__(:define_method, name, &block) # If we have a module clash in the example module # then we need to remove it to prevent a warning. # # Note we do not check ancestor modules (see: `instance_methods(false)`) # as we can override them. if instance_methods(false).include?(name) remove_method(name) end # Apply the memoization. The method has been defined in an ancestor # module so we can use `super` here to get the value. if block.arity == 1 define_method(name) { __memoized.fetch_or_store(name) { super(RSpec.current_example, &nil) } } else define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } } end end # Just like `let`, except the block is invoked by an implicit `before` # hook. This serves a dual purpose of setting up state and providing a # memoized reference to that state. # # @example # # class Thing # def self.count # @count ||= 0 # end # # def self.count=(val) # @count += val # end # # def self.reset_count # @count = 0 # end # # def initialize # self.class.count += 1 # end # end # # RSpec.describe Thing do # after(:example) { Thing.reset_count } # # context "using let" do # let(:thing) { Thing.new } # # it "is not invoked implicitly" do # Thing.count.should eq(0) # end # # it "can be invoked explicitly" do # thing # Thing.count.should eq(1) # end # end # # context "using let!" do # let!(:thing) { Thing.new } # # it "is invoked implicitly" do # Thing.count.should eq(1) # end # # it "returns memoized version on first invocation" do # thing # Thing.count.should eq(1) # end # end # end def let!(name, &block) let(name, &block) before { __send__(name) } end # Declares a `subject` for an example group which can then be wrapped # with `expect` using `is_expected` to make it the target of an # expectation in a concise, one-line example. # # Given a `name`, defines a method with that name which returns the # `subject`. This lets you declare the subject once and access it # implicitly in one-liners and explicitly using an intention revealing # name. # # When given a `name`, calling `super` in the block is not supported. # # @note `subject` can be configured to be threadsafe or not. # If it is threadsafe, it will take longer to access the value. # If it is not threadsafe, it may behave in surprising ways in examples # that spawn separate threads. Specify this on `RSpec.configure` # # @param name [String,Symbol] used to define an accessor with an # intention revealing name # @param block defines the value to be returned by `subject` in examples # # @example # # RSpec.describe CheckingAccount, "with $50" do # subject { CheckingAccount.new(Money.new(50, :USD)) } # it { is_expected.to have_a_balance_of(Money.new(50, :USD)) } # it { is_expected.not_to be_overdrawn } # end # # RSpec.describe CheckingAccount, "with a non-zero starting balance" do # subject(:account) { CheckingAccount.new(Money.new(50, :USD)) } # it { is_expected.not_to be_overdrawn } # it "has a balance equal to the starting balance" do # account.balance.should eq(Money.new(50, :USD)) # end # end # # @see MemoizedHelpers#should # @see MemoizedHelpers#should_not # @see MemoizedHelpers#is_expected def subject(name=nil, &block) if name let(name, &block) alias_method :subject, name self::NamedSubjectPreventSuper.__send__(:define_method, name) do raise NotImplementedError, "`super` in named subjects is not supported" end else let(:subject, &block) end end # Just like `subject`, except the block is invoked by an implicit # `before` hook. This serves a dual purpose of setting up state and # providing a memoized reference to that state. # # @example # # class Thing # def self.count # @count ||= 0 # end # # def self.count=(val) # @count += val # end # # def self.reset_count # @count = 0 # end # # def initialize # self.class.count += 1 # end # end # # RSpec.describe Thing do # after(:example) { Thing.reset_count } # # context "using subject" do # subject { Thing.new } # # it "is not invoked implicitly" do # Thing.count.should eq(0) # end # # it "can be invoked explicitly" do # subject # Thing.count.should eq(1) # end # end # # context "using subject!" do # subject!(:thing) { Thing.new } # # it "is invoked implicitly" do # Thing.count.should eq(1) # end # # it "returns memoized version on first invocation" do # subject # Thing.count.should eq(1) # end # end # end def subject!(name=nil, &block) subject(name, &block) before { subject } end end # @private # # Gets the LetDefinitions module. The module is mixed into # the example group and is used to hold all let definitions. # This is done so that the block passed to `let` can be # forwarded directly on to `define_method`, so that all method # constructs (including `super` and `return`) can be used in # a `let` block. # # The memoization is provided by a method definition on the # example group that supers to the LetDefinitions definition # in order to get the value to memoize. def self.module_for(example_group) get_constant_or_yield(example_group, :LetDefinitions) do mod = Module.new do include(Module.new { example_group.const_set(:NamedSubjectPreventSuper, self) }) end example_group.const_set(:LetDefinitions, mod) mod end end # @private def self.define_helpers_on(example_group) example_group.__send__(:include, module_for(example_group)) end if Module.method(:const_defined?).arity == 1 # for 1.8 # @private # # Gets the named constant or yields. # On 1.8, const_defined? / const_get do not take into # account the inheritance hierarchy. # :nocov: def self.get_constant_or_yield(example_group, name) if example_group.const_defined?(name) example_group.const_get(name) else yield end end # :nocov: else # @private # # Gets the named constant or yields. # On 1.9, const_defined? / const_get take into account the # the inheritance by default, and accept an argument to # disable this behavior. It's important that we don't # consider inheritance here; each example group level that # uses a `let` should get its own `LetDefinitions` module. def self.get_constant_or_yield(example_group, name) if example_group.const_defined?(name, (check_ancestors = false)) example_group.const_get(name, check_ancestors) else yield end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/pending.rb0000664000000000000000000001275314557677674023454 0ustar rootrootmodule RSpec module Core # Provides methods to mark examples as pending. These methods are available # to be called from within any example or hook. module Pending # Raised in the middle of an example to indicate that it should be marked # as skipped. class SkipDeclaredInExample < StandardError attr_reader :argument def initialize(argument) @argument = argument end end # If Test::Unit is loaded, we'll use its error as baseclass, so that # Test::Unit will report unmet RSpec expectations as failures rather than # errors. begin class PendingExampleFixedError < Test::Unit::AssertionFailedError; end rescue class PendingExampleFixedError < StandardError; end end # @private NO_REASON_GIVEN = 'No reason given' # @private NOT_YET_IMPLEMENTED = 'Not yet implemented' # @overload pending() # @overload pending(message) # # Marks an example as pending. The rest of the example will still be # executed, and if it passes the example will fail to indicate that the # pending can be removed. # # @param message [String] optional message to add to the summary report. # # @example # describe "some behaviour" do # # reported as "Pending: no reason given" # it "is pending with no message" do # pending # raise "broken" # end # # # reported as "Pending: something else getting finished" # it "is pending with a custom message" do # pending("something else getting finished") # raise "broken" # end # end # # @note When using `pending` inside an example body using this method # hooks, such as `before(:example)`, have already be run. This means that # a failure from the code in the `before` hook will prevent the example # from being considered pending, as the example body would not be # executed. If you need to consider hooks as pending as well you can use # the pending metadata as an alternative, e.g. # `it "does something", pending: "message"`. def pending(message=nil) current_example = RSpec.current_example if block_given? raise ArgumentError, <<-EOS.gsub(/^\s+\|/, '') |The semantics of `RSpec::Core::Pending#pending` have changed in |RSpec 3. In RSpec 2.x, it caused the example to be skipped. In |RSpec 3, the rest of the example is still run but is expected to |fail, and will be marked as a failure (rather than as pending) if |the example passes. | |Passing a block within an example is now deprecated. Marking the |example as pending provides the same behavior in RSpec 3 which was |provided only by the block in RSpec 2.x. | |Move the code in the block provided to `pending` into the rest of |the example body. | |Called from #{CallerFilter.first_non_rspec_line}. | EOS elsif current_example Pending.mark_pending! current_example, message else raise "`pending` may not be used outside of examples, such as in " \ "before(:context). Maybe you want `skip`?" end end # @overload skip() # @overload skip(message) # # Marks an example as pending and skips execution. # # @param message [String] optional message to add to the summary report. # # @example # describe "an example" do # # reported as "Pending: no reason given" # it "is skipped with no message" do # skip # end # # # reported as "Pending: something else getting finished" # it "is skipped with a custom message" do # skip "something else getting finished" # end # end def skip(message=nil) current_example = RSpec.current_example Pending.mark_skipped!(current_example, message) if current_example raise SkipDeclaredInExample.new(message) end # @private # # Mark example as skipped. # # @param example [RSpec::Core::Example] the example to mark as skipped # @param message_or_bool [Boolean, String] the message to use, or true def self.mark_skipped!(example, message_or_bool) Pending.mark_pending! example, message_or_bool example.metadata[:skip] = true end # @private # # Mark example as pending. # # @param example [RSpec::Core::Example] the example to mark as pending # @param message_or_bool [Boolean, String] the message to use, or true def self.mark_pending!(example, message_or_bool) message = if !message_or_bool || !(String === message_or_bool) NO_REASON_GIVEN else message_or_bool end example.metadata[:pending] = true example.execution_result.pending_message = message example.execution_result.pending_fixed = false end # @private # # Mark example as fixed. # # @param example [RSpec::Core::Example] the example to mark as fixed def self.mark_fixed!(example) example.execution_result.pending_fixed = true end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/metadata_filter.rb0000664000000000000000000002317114557677674025151 0ustar rootrootmodule RSpec module Core # Contains metadata filtering logic. This has been extracted from # the metadata classes because it operates ON a metadata hash but # does not manage any of the state in the hash. We're moving towards # having metadata be a raw hash (not a custom subclass), so externalizing # this filtering logic helps us move in that direction. module MetadataFilter class << self # @private def apply?(predicate, filters, metadata) filters.__send__(predicate) { |k, v| filter_applies?(k, v, metadata) } end # @private def filter_applies?(key, filter_value, metadata) silence_metadata_example_group_deprecations do return location_filter_applies?(filter_value, metadata) if key == :locations return id_filter_applies?(filter_value, metadata) if key == :ids return filters_apply?(key, filter_value, metadata) if Hash === filter_value meta_value = metadata.fetch(key) { return false } return true if TrueClass === filter_value && meta_value return proc_filter_applies?(key, filter_value, metadata) if Proc === filter_value return filter_applies_to_any_value?(key, filter_value, metadata) if Array === meta_value filter_value === meta_value || filter_value.to_s == meta_value.to_s end end # @private def silence_metadata_example_group_deprecations RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations] = true yield ensure RSpec::Support.thread_local_data.delete(:silence_metadata_example_group_deprecations) end private def filter_applies_to_any_value?(key, value, metadata) metadata[key].any? { |v| filter_applies?(key, v, key => value) } end def id_filter_applies?(rerun_paths_to_scoped_ids, metadata) scoped_ids = rerun_paths_to_scoped_ids.fetch(metadata[:rerun_file_path]) { return false } Metadata.ascend(metadata).any? do |meta| scoped_ids.include?(meta[:scoped_id]) end end def location_filter_applies?(locations, metadata) Metadata.ascend(metadata).any? do |meta| file_path = meta[:absolute_file_path] line_num = meta[:line_number] locations[file_path].any? do |filter_line_num| line_num == RSpec.world.preceding_declaration_line(file_path, filter_line_num) end end end def proc_filter_applies?(key, proc, metadata) case proc.arity when 0 then proc.call when 2 then proc.call(metadata[key], metadata) else proc.call(metadata[key]) end end def filters_apply?(key, value, metadata) subhash = metadata[key] return false unless Hash === subhash || HashImitatable === subhash value.all? { |k, v| filter_applies?(k, v, subhash) } end end end # Tracks a collection of filterable items (e.g. modules, hooks, etc) # and provides an optimized API to get the applicable items for the # metadata of an example or example group. # # There are two implementations, optimized for different uses. # @private module FilterableItemRepository # This implementation is simple, and is optimized for frequent # updates but rare queries. `append` and `prepend` do no extra # processing, and no internal memoization is done, since this # is not optimized for queries. # # This is ideal for use by a example or example group, which may # be updated multiple times with globally configured hooks, etc, # but will not be queried frequently by other examples or example # groups. # @private class UpdateOptimized attr_reader :items_and_filters def initialize(applies_predicate) @applies_predicate = applies_predicate @items_and_filters = [] end def append(item, metadata) @items_and_filters << [item, metadata] end def prepend(item, metadata) @items_and_filters.unshift [item, metadata] end def delete(item, metadata) @items_and_filters.delete [item, metadata] end def items_for(request_meta) @items_and_filters.each_with_object([]) do |(item, item_meta), to_return| to_return << item if item_meta.empty? || MetadataFilter.apply?(@applies_predicate, item_meta, request_meta) end end unless [].respond_to?(:each_with_object) # For 1.8.7 # :nocov: undef items_for def items_for(request_meta) @items_and_filters.inject([]) do |to_return, (item, item_meta)| to_return << item if item_meta.empty? || MetadataFilter.apply?(@applies_predicate, item_meta, request_meta) to_return end end # :nocov: end end # This implementation is much more complex, and is optimized for # rare (or hopefully no) updates once the queries start. Updates # incur a cost as it has to clear the memoization and keep track # of applicable keys. Queries will be O(N) the first time an item # is provided with a given set of applicable metadata; subsequent # queries with items with the same set of applicable metadata will # be O(1) due to internal memoization. # # This is ideal for use by config, where filterable items (e.g. hooks) # are typically added at the start of the process (e.g. in `spec_helper`) # and then repeatedly queried as example groups and examples are defined. # @private class QueryOptimized < UpdateOptimized alias find_items_for items_for private :find_items_for def initialize(applies_predicate) super @applicable_keys = Set.new @proc_keys = Set.new @memoized_lookups = Hash.new do |hash, applicable_metadata| hash[applicable_metadata] = find_items_for(applicable_metadata) end end def append(item, metadata) super handle_mutation(metadata) end def prepend(item, metadata) super handle_mutation(metadata) end def delete(item, metadata) super reconstruct_caches end def items_for(metadata) # The filtering of `metadata` to `applicable_metadata` is the key thing # that makes the memoization actually useful in practice, since each # example and example group have different metadata (e.g. location and # description). By filtering to the metadata keys our items care about, # we can ignore extra metadata keys that differ for each example/group. # For example, given `config.include DBHelpers, :db`, example groups # can be split into these two sets: those that are tagged with `:db` and those # that are not. For each set, this method for the first group in the set is # still an `O(N)` calculation, but all subsequent groups in the set will be # constant time lookups when they call this method. applicable_metadata = applicable_metadata_from(metadata) if applicable_metadata.any? { |k, _| @proc_keys.include?(k) } # It's unsafe to memoize lookups involving procs (since they can # be non-deterministic), so we skip the memoization in this case. find_items_for(applicable_metadata) else @memoized_lookups[applicable_metadata] end end private def reconstruct_caches @applicable_keys.clear @proc_keys.clear @items_and_filters.each do |_item, metadata| handle_mutation(metadata) end end def handle_mutation(metadata) @applicable_keys.merge(metadata.keys) @proc_keys.merge(proc_keys_from metadata) @memoized_lookups.clear end def applicable_metadata_from(metadata) MetadataFilter.silence_metadata_example_group_deprecations do @applicable_keys.inject({}) do |hash, key| # :example_group is treated special here because... # - In RSpec 2, example groups had an `:example_group` key # - In RSpec 3, that key is deprecated (it was confusing!). # - The key is not technically present in an example group metadata hash # (and thus would fail the `metadata.key?(key)` check) but a value # is provided when accessed via the hash's `default_proc` # - Thus, for backwards compatibility, we have to explicitly check # for `:example_group` here if it is one of the keys being used to # filter. hash[key] = metadata[key] if metadata.key?(key) || key == :example_group hash end end end def proc_keys_from(metadata) metadata.each_with_object([]) do |(key, value), to_return| to_return << key if Proc === value end end unless [].respond_to?(:each_with_object) # For 1.8.7 # :nocov: undef proc_keys_from def proc_keys_from(metadata) metadata.inject([]) do |to_return, (key, value)| to_return << key if Proc === value to_return end end # :nocov: end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/world.rb0000664000000000000000000002076214557677674023156 0ustar rootrootmodule RSpec module Core # @api private # # Internal container for global non-configuration data. class World # @private attr_reader :example_groups, :filtered_examples, :example_group_counts_by_spec_file # Used internally to determine what to do when a SIGINT is received. attr_accessor :wants_to_quit # Used internally to signify that a SystemExit occurred in # `Configuration#load_file_handling_errors`, and thus examples cannot # be counted accurately. Specifically, we cannot accurately report # "No examples found". # @private attr_accessor :rspec_is_quitting # Used internally to signal that a failure outside of an example # has occurred, and that therefore the exit status should indicate # the run failed. # @private attr_accessor :non_example_failure def initialize(configuration=RSpec.configuration) @wants_to_quit = false @rspec_is_quitting = false @configuration = configuration configuration.world = self @example_groups = [] @example_group_counts_by_spec_file = Hash.new(0) prepare_example_filtering end # @api public # # Prepares filters so that they apply to example groups when they run. # # This is a separate method so that filters can be modified/replaced and # examples refiltered during a process's lifetime, which can be useful for # a custom runner. def prepare_example_filtering @filtered_examples = Hash.new do |hash, group| hash[group] = filter_manager.prune(group.examples) end end # @api private # # Apply ordering strategy from configuration to example groups. def ordered_example_groups ordering_strategy = @configuration.ordering_registry.fetch(:global) ordering_strategy.order(@example_groups) end # @api private # # Reset world to 'scratch' before running suite. def reset RSpec::ExampleGroups.remove_all_constants example_groups.clear @sources_by_path.clear if defined?(@sources_by_path) @syntax_highlighter = nil @example_group_counts_by_spec_file = Hash.new(0) end # @private def filter_manager @configuration.filter_manager end # @private def registered_example_group_files @example_group_counts_by_spec_file.keys end # @api private # # Records an example group. def record(example_group) @configuration.on_example_group_definition_callbacks.each { |block| block.call(example_group) } @example_group_counts_by_spec_file[example_group.metadata[:absolute_file_path]] += 1 end # @private def num_example_groups_defined_in(file) @example_group_counts_by_spec_file[file] end # @private def shared_example_group_registry @shared_example_group_registry ||= SharedExampleGroup::Registry.new end # @private def inclusion_filter @configuration.inclusion_filter end # @private def exclusion_filter @configuration.exclusion_filter end # @api private # # Get count of examples to be run. def example_count(groups=example_groups) FlatMap.flat_map(groups) { |g| g.descendants }. inject(0) { |a, e| a + e.filtered_examples.size } end # @private def all_example_groups FlatMap.flat_map(example_groups) { |g| g.descendants } end # @private def all_examples FlatMap.flat_map(all_example_groups) { |g| g.examples } end # @private # Traverses the tree of each top level group. # For each it yields the group, then the children, recursively. # Halts the traversal of a branch of the tree as soon as the passed block returns true. # Note that siblings groups and their sub-trees will continue to be explored. # This is intended to make it easy to find the top-most group that satisfies some # condition. def traverse_example_group_trees_until(&block) example_groups.each do |group| group.traverse_tree_until(&block) end end # @api private # # Find line number of previous declaration. def preceding_declaration_line(absolute_file_name, filter_line) line_numbers = descending_declaration_line_numbers_by_file.fetch(absolute_file_name) do return nil end line_numbers.find { |num| num <= filter_line } end # @private def reporter @configuration.reporter end # @private def source_from_file(path) unless defined?(@sources_by_path) RSpec::Support.require_rspec_support 'source' @sources_by_path = {} end @sources_by_path[path] ||= Support::Source.from_file(path) end # @private def syntax_highlighter @syntax_highlighter ||= Formatters::SyntaxHighlighter.new(@configuration) end # @api private # # Notify reporter of filters. def announce_filters fail_if_config_and_cli_options_invalid filter_announcements = [] announce_inclusion_filter filter_announcements announce_exclusion_filter filter_announcements unless filter_manager.empty? if filter_announcements.length == 1 report_filter_message("Run options: #{filter_announcements[0]}") else report_filter_message("Run options:\n #{filter_announcements.join("\n ")}") end end if @configuration.run_all_when_everything_filtered? && example_count.zero? && !@configuration.only_failures? report_filter_message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}") filtered_examples.clear inclusion_filter.clear end return unless example_count.zero? example_groups.clear unless rspec_is_quitting if filter_manager.empty? report_filter_message("No examples found.") elsif exclusion_filter.empty? || inclusion_filter.empty? report_filter_message(everything_filtered_message) end end end # @private def report_filter_message(message) reporter.message(message) unless @configuration.silence_filter_announcements? end # @private def everything_filtered_message "\nAll examples were filtered out" end # @api private # # Add inclusion filters to announcement message. def announce_inclusion_filter(announcements) return if inclusion_filter.empty? announcements << "include #{inclusion_filter.description}" end # @api private # # Add exclusion filters to announcement message. def announce_exclusion_filter(announcements) return if exclusion_filter.empty? announcements << "exclude #{exclusion_filter.description}" end private def descending_declaration_line_numbers_by_file @descending_declaration_line_numbers_by_file ||= begin declaration_locations = FlatMap.flat_map(example_groups, &:declaration_locations) hash_of_arrays = Hash.new { |h, k| h[k] = [] } # TODO: change `inject` to `each_with_object` when we drop 1.8.7 support. line_nums_by_file = declaration_locations.inject(hash_of_arrays) do |hash, (file_name, line_number)| hash[file_name] << line_number hash end line_nums_by_file.each_value do |list| list.sort! list.reverse! end end end def fail_if_config_and_cli_options_invalid return unless @configuration.only_failures_but_not_configured? reporter.abort_with( "\nTo use `--only-failures`, you must first set " \ "`config.example_status_persistence_file_path`.", 1 # exit code ) end # @private # Provides a null implementation for initial use by configuration. module Null def self.non_example_failure; end def self.non_example_failure=(_); end def self.registered_example_group_files [] end def self.traverse_example_group_trees_until end # :nocov: def self.example_groups [] end def self.all_example_groups [] end # :nocov: end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/set.rb0000664000000000000000000000172314557677674022616 0ustar rootrootmodule RSpec module Core # @private # # We use this to replace `::Set` so we can have the advantage of # constant time key lookups for unique arrays but without the # potential to pollute a developers environment with an extra # piece of the stdlib. This helps to prevent false positive # builds. # class Set include Enumerable def initialize(array=[]) @values = {} merge(array) end def empty? @values.empty? end def <<(key) @values[key] = true self end def delete(key) @values.delete(key) end def each(&block) @values.keys.each(&block) self end def include?(key) @values.key?(key) end def merge(values) values.each do |key| @values[key] = true end self end def clear @values.clear self end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/flat_map.rb0000664000000000000000000000060014557677674023577 0ustar rootrootmodule RSpec module Core # @private module FlatMap if [].respond_to?(:flat_map) def flat_map(array, &block) array.flat_map(&block) end else # for 1.8.7 # :nocov: def flat_map(array, &block) array.map(&block).flatten(1) end # :nocov: end module_function :flat_map end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/version.rb0000664000000000000000000000031014557677674023477 0ustar rootrootmodule RSpec module Core # Version information for RSpec Core. module Version # Current version of RSpec Core, in semantic versioning format. STRING = '3.13.0' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/example_group.rb0000664000000000000000000007714514557677674024705 0ustar rootrootRSpec::Support.require_rspec_support 'recursive_const_methods' module RSpec module Core # rubocop:disable Metrics/ClassLength # ExampleGroup and {Example} are the main structural elements of # rspec-core. Consider this example: # # RSpec.describe Thing do # it "does something" do # end # end # # The object returned by `describe Thing` is a subclass of ExampleGroup. # The object returned by `it "does something"` is an instance of Example, # which serves as a wrapper for an instance of the ExampleGroup in which it # is declared. # # Example group bodies (e.g. `describe` or `context` blocks) are evaluated # in the context of a new subclass of ExampleGroup. Individual examples are # evaluated in the context of an instance of the specific ExampleGroup # subclass to which they belong. # # Besides the class methods defined here, there are other interesting macros # defined in {Hooks}, {MemoizedHelpers::ClassMethods} and # {SharedExampleGroup}. There are additional instance methods available to # your examples defined in {MemoizedHelpers} and {Pending}. class ExampleGroup extend Hooks include MemoizedHelpers extend MemoizedHelpers::ClassMethods include Pending extend SharedExampleGroup # Define a singleton method for the singleton class (remove the method if # it's already been defined). # @private def self.idempotently_define_singleton_method(name, &definition) (class << self; self; end).module_exec do remove_method(name) if method_defined?(name) && instance_method(name).owner == self define_method(name, &definition) end end # @!group Metadata # The [Metadata](Metadata) object associated with this group. # @see Metadata def self.metadata @metadata ||= nil end # Temporarily replace the provided metadata. # Intended primarily to allow an example group's singleton class # to return the metadata of the example that it exists for. This # is necessary for shared example group inclusion to work properly # with singleton example groups. # @private def self.with_replaced_metadata(meta) orig_metadata = metadata @metadata = meta yield ensure @metadata = orig_metadata end # @private # @return [Metadata] belonging to the parent of a nested {ExampleGroup} def self.superclass_metadata @superclass_metadata ||= superclass.respond_to?(:metadata) ? superclass.metadata : nil end # @private def self.delegate_to_metadata(*names) names.each do |name| idempotently_define_singleton_method(name) { metadata.fetch(name) } end end delegate_to_metadata :described_class, :file_path, :location # @return [String] the current example group description def self.description description = metadata[:description] RSpec.configuration.format_docstrings_block.call(description) end # Returns the class or module passed to the `describe` method (or alias). # Returns nil if the subject is not a class or module. # @example # RSpec.describe Thing do # it "does something" do # described_class == Thing # end # end # def described_class self.class.described_class end # @!endgroup # @!group Defining Examples # @private # @macro [attach] define_example_method # @!scope class # @method $1 # @overload $1 # @overload $1(&example_implementation) # @param example_implementation [Block] The implementation of the example. # @overload $1(doc_string, *metadata) # @param doc_string [String] The example's doc string. # @param metadata [Array, Hash] Metadata for the example. # Symbols will be transformed into hash entries with `true` values. # @overload $1(doc_string, *metadata, &example_implementation) # @param doc_string [String] The example's doc string. # @param metadata [Array, Hash] Metadata for the example. # Symbols will be transformed into hash entries with `true` values. # @param example_implementation [Block] The implementation of the example. # @yield [Example] the example object # @example # $1 do # end # # $1 "does something" do # end # # $1 "does something", :slow, :uses_js do # end # # $1 "does something", :with => 'additional metadata' do # end # # $1 "does something" do |ex| # # ex is the Example object that contains metadata about the example # end # # @example # $1 "does something", :slow, :load_factor => 100 do # end # def self.define_example_method(name, extra_options={}) idempotently_define_singleton_method(name) do |*all_args, &block| desc, *args = *all_args options = Metadata.build_hash_from(args) options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block options.update(extra_options) RSpec::Core::Example.new(self, desc, options, block) end end # Defines an example within a group. define_example_method :example # Defines an example within a group. # This is the primary API to define a code example. define_example_method :it # Defines an example within a group. # Useful for when your docstring does not read well off of `it`. # @example # RSpec.describe MyClass do # specify "#do_something is deprecated" do # # ... # end # end define_example_method :specify # Shortcut to define an example with `:focus => true`. # @see example define_example_method :focus, :focus => true # Shortcut to define an example with `:focus => true`. # @see example define_example_method :fexample, :focus => true # Shortcut to define an example with `:focus => true`. # @see example define_example_method :fit, :focus => true # Shortcut to define an example with `:focus => true`. # @see example define_example_method :fspecify, :focus => true # Shortcut to define an example with `:skip => 'Temporarily skipped with xexample'`. # @see example define_example_method :xexample, :skip => 'Temporarily skipped with xexample' # Shortcut to define an example with `:skip => 'Temporarily skipped with xit'`. # @see example define_example_method :xit, :skip => 'Temporarily skipped with xit' # Shortcut to define an example with `:skip => 'Temporarily skipped with xspecify'`. # @see example define_example_method :xspecify, :skip => 'Temporarily skipped with xspecify' # Shortcut to define an example with `:skip => true` # @see example define_example_method :skip, :skip => true # Shortcut to define an example with `:pending => true` # @see example define_example_method :pending, :pending => true # @!endgroup # @!group Defining Example Groups # @private # @macro [attach] define_example_group_method # @!scope class # @overload $1 # @overload $1(&example_group_definition) # @param example_group_definition [Block] The definition of the example group. # @overload $1(doc_string, *metadata, &example_implementation) # @param doc_string [String] The group's doc string. # @param metadata [Array, Hash] Metadata for the group. # Symbols will be transformed into hash entries with `true` values. # @param example_group_definition [Block] The definition of the example group. # # Generates a subclass of this example group which inherits # everything except the examples themselves. # # @example # # RSpec.describe "something" do # << This describe method is defined in # # << RSpec::Core::DSL, included in the # # << global namespace (optional) # before do # do_something_before # end # # before(:example, :clean_env) do # env.clear! # end # # let(:thing) { Thing.new } # # $1 "attribute (of something)" do # # examples in the group get the before hook # # declared above, and can access `thing` # end # # $1 "needs additional setup", :clean_env, :implementation => JSON do # # specifies that hooks with matching metadata # # should be be run additionally # end # end # # @see DSL#describe def self.define_example_group_method(name, metadata={}) idempotently_define_singleton_method(name) do |*args, &example_group_block| thread_data = RSpec::Support.thread_local_data top_level = self == ExampleGroup registration_collection = if top_level if thread_data[:in_example_group] raise "Creating an isolated context from within a context is " \ "not allowed. Change `RSpec.#{name}` to `#{name}` or " \ "move this to a top-level scope." end thread_data[:in_example_group] = true RSpec.world.example_groups else children end begin description = args.shift combined_metadata = metadata.dup combined_metadata.merge!(args.pop) if args.last.is_a? Hash args << combined_metadata subclass(self, description, args, registration_collection, &example_group_block) ensure thread_data.delete(:in_example_group) if top_level end end RSpec::Core::DSL.expose_example_group_alias(name) end define_example_group_method :example_group # An alias of `example_group`. Generally used when grouping examples by a # thing you are describing (e.g. an object, class or method). # @see example_group define_example_group_method :describe # An alias of `example_group`. Generally used when grouping examples # contextually (e.g. "with xyz", "when xyz" or "if xyz"). # @see example_group define_example_group_method :context # Shortcut to temporarily make an example group skipped. # @see example_group define_example_group_method :xdescribe, :skip => "Temporarily skipped with xdescribe" # Shortcut to temporarily make an example group skipped. # @see example_group define_example_group_method :xcontext, :skip => "Temporarily skipped with xcontext" # Shortcut to define an example group with `:focus => true`. # @see example_group define_example_group_method :fdescribe, :focus => true # Shortcut to define an example group with `:focus => true`. # @see example_group define_example_group_method :fcontext, :focus => true # @!endgroup # @!group Including Shared Example Groups # @private # @macro [attach] define_nested_shared_group_method # @!scope class # # @see SharedExampleGroup def self.define_nested_shared_group_method(new_name, report_label="it should behave like") idempotently_define_singleton_method(new_name) do |name, *args, &customization_block| # Pass :caller so the :location metadata is set properly. # Otherwise, it'll be set to the next line because that's # the block's source_location. group = example_group("#{report_label} #{name}", :caller => (the_caller = caller)) do find_and_eval_shared("examples", name, the_caller.first, *args, &customization_block) end group.metadata[:shared_group_name] = name group end end # Generates a nested example group and includes the shared content # mapped to `name` in the nested group. define_nested_shared_group_method :it_behaves_like, "behaves like" # Generates a nested example group and includes the shared content # mapped to `name` in the nested group. define_nested_shared_group_method :it_should_behave_like # Includes shared content mapped to `name` directly in the group in which # it is declared, as opposed to `it_behaves_like`, which creates a nested # group. If given a block, that block is also eval'd in the current # context. # # @see SharedExampleGroup def self.include_context(name, *args, &block) find_and_eval_shared("context", name, caller.first, *args, &block) end # Includes shared content mapped to `name` directly in the group in which # it is declared, as opposed to `it_behaves_like`, which creates a nested # group. If given a block, that block is also eval'd in the current # context. # # @see SharedExampleGroup def self.include_examples(name, *args, &block) find_and_eval_shared("examples", name, caller.first, *args, &block) end # Clear memoized values when adding/removing examples # @private def self.reset_memoized @descendant_filtered_examples = nil @_descendants = nil @parent_groups = nil @declaration_locations = nil end # Adds an example to the example group def self.add_example(example) reset_memoized examples << example end # Removes an example from the example group def self.remove_example(example) reset_memoized examples.delete example end # @private def self.find_and_eval_shared(label, name, inclusion_location, *args, &customization_block) shared_module = RSpec.world.shared_example_group_registry.find(parent_groups, name) unless shared_module raise ArgumentError, "Could not find shared #{label} #{name.inspect}" end shared_module.include_in( self, Metadata.relative_path(inclusion_location), args, customization_block ) end # @!endgroup # @private def self.subclass(parent, description, args, registration_collection, &example_group_block) subclass = Class.new(parent) subclass.set_it_up(description, args, registration_collection, &example_group_block) subclass.module_exec(&example_group_block) if example_group_block # The LetDefinitions module must be included _after_ other modules # to ensure that it takes precedence when there are name collisions. # Thus, we delay including it until after the example group block # has been eval'd. MemoizedHelpers.define_helpers_on(subclass) subclass end # @private def self.set_it_up(description, args, registration_collection, &example_group_block) # Ruby 1.9 has a bug that can lead to infinite recursion and a # SystemStackError if you include a module in a superclass after # including it in a subclass: https://gist.github.com/845896 # To prevent this, we must include any modules in # RSpec::Core::ExampleGroup before users create example groups and have # a chance to include the same module in a subclass of # RSpec::Core::ExampleGroup. So we need to configure example groups # here. ensure_example_groups_are_configured # Register the example with the group before creating the metadata hash. # This is necessary since creating the metadata hash triggers # `when_first_matching_example_defined` callbacks, in which users can # load RSpec support code which defines hooks. For that to work, the # examples and example groups must be registered at the time the # support code is called or be defined afterwards. # Begin defined beforehand but registered afterwards causes hooks to # not be applied where they should. registration_collection << self @user_metadata = Metadata.build_hash_from(args) @metadata = Metadata::ExampleGroupHash.create( superclass_metadata, @user_metadata, superclass.method(:next_runnable_index_for), description, *args, &example_group_block ) config = RSpec.configuration config.apply_derived_metadata_to(@metadata) ExampleGroups.assign_const(self) @currently_executing_a_context_hook = false config.configure_group(self) end # @private def self.examples @examples ||= [] end # @private def self.filtered_examples RSpec.world.filtered_examples[self] end # @private def self.descendant_filtered_examples @descendant_filtered_examples ||= filtered_examples + FlatMap.flat_map(children, &:descendant_filtered_examples) end # @private def self.children @children ||= [] end # @private # Traverses the tree of groups, starting with `self`, then the children, recursively. # Halts the traversal of a branch of the tree as soon as the passed block returns true. # Note that siblings groups and their sub-trees will continue to be explored. # This is intended to make it easy to find the top-most group that satisfies some # condition. def self.traverse_tree_until(&block) return if yield self children.each do |child| child.traverse_tree_until(&block) end end # @private def self.next_runnable_index_for(file) if self == ExampleGroup # We add 1 so the ids start at 1 instead of 0. This is # necessary for this branch (but not for the other one) # because we register examples and groups with the # `children` and `examples` collection BEFORE this # method is called as part of metadata hash creation, # but the example group is recorded with # `RSpec.world.example_group_counts_by_spec_file` AFTER # the metadata hash is created and the group is returned # to the caller. RSpec.world.num_example_groups_defined_in(file) + 1 else children.count + examples.count end end # @private def self.descendants @_descendants ||= [self] + FlatMap.flat_map(children, &:descendants) end ## @private def self.parent_groups @parent_groups ||= ancestors.select { |a| a < RSpec::Core::ExampleGroup } end # @private def self.top_level? superclass == ExampleGroup end # @private def self.ensure_example_groups_are_configured unless defined?(@@example_groups_configured) RSpec.configuration.configure_mock_framework RSpec.configuration.configure_expectation_framework # rubocop:disable Style/ClassVars @@example_groups_configured = true # rubocop:enable Style/ClassVars end end # @private def self.before_context_ivars @before_context_ivars ||= {} end # @private def self.store_before_context_ivars(example_group_instance) each_instance_variable_for_example(example_group_instance) do |ivar| before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar) end end # Returns true if a `before(:context)` or `after(:context)` # hook is currently executing. def self.currently_executing_a_context_hook? @currently_executing_a_context_hook end # @private def self.run_before_context_hooks(example_group_instance) set_ivars(example_group_instance, superclass_before_context_ivars) @currently_executing_a_context_hook = true ContextHookMemoized::Before.isolate_for_context_hook(example_group_instance) do hooks.run(:before, :context, example_group_instance) end ensure store_before_context_ivars(example_group_instance) @currently_executing_a_context_hook = false end if RUBY_VERSION.to_f >= 1.9 # @private def self.superclass_before_context_ivars superclass.before_context_ivars end else # 1.8.7 # :nocov: # @private def self.superclass_before_context_ivars if superclass.respond_to?(:before_context_ivars) superclass.before_context_ivars else # `self` must be the singleton class of an ExampleGroup instance. # On 1.8.7, the superclass of a singleton class of an instance of A # is A's singleton class. On 1.9+, it's A. On 1.8.7, the first ancestor # is A, so we can mirror 1.8.7's behavior here. Note that we have to # search for the first that responds to `before_context_ivars` # in case a module has been included in the singleton class. ancestors.find { |a| a.respond_to?(:before_context_ivars) }.before_context_ivars end end # :nocov: end # @private def self.run_after_context_hooks(example_group_instance) set_ivars(example_group_instance, before_context_ivars) @currently_executing_a_context_hook = true ContextHookMemoized::After.isolate_for_context_hook(example_group_instance) do hooks.run(:after, :context, example_group_instance) end ensure before_context_ivars.clear @currently_executing_a_context_hook = false end # Runs all the examples in this group. def self.run(reporter=RSpec::Core::NullReporter) return if RSpec.world.wants_to_quit reporter.example_group_started(self) should_run_context_hooks = descendant_filtered_examples.any? begin RSpec.current_scope = :before_context_hook run_before_context_hooks(new('before(:context) hook')) if should_run_context_hooks result_for_this_group = run_examples(reporter) results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all? result_for_this_group && results_for_descendants rescue Pending::SkipDeclaredInExample => ex for_filtered_examples(reporter) { |example| example.skip_with_exception(reporter, ex) } true rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex for_filtered_examples(reporter) { |example| example.fail_with_exception(reporter, ex) } RSpec.world.wants_to_quit = true if reporter.fail_fast_limit_met? false ensure RSpec.current_scope = :after_context_hook run_after_context_hooks(new('after(:context) hook')) if should_run_context_hooks reporter.example_group_finished(self) end end # @private def self.ordering_strategy order = metadata.fetch(:order, :global) registry = RSpec.configuration.ordering_registry registry.fetch(order) do warn <<-WARNING.gsub(/^ +\|/, '') |WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata. | Falling back to configured global ordering. | Unrecognized ordering specified at: #{location} WARNING registry.fetch(:global) end end # @private def self.run_examples(reporter) ordering_strategy.order(filtered_examples).map do |example| next if RSpec.world.wants_to_quit instance = new(example.inspect_output) set_ivars(instance, before_context_ivars) succeeded = example.run(instance, reporter) if !succeeded && reporter.fail_fast_limit_met? RSpec.world.wants_to_quit = true end succeeded end.all? end # @private def self.for_filtered_examples(reporter, &block) filtered_examples.each(&block) children.each do |child| reporter.example_group_started(child) child.for_filtered_examples(reporter, &block) reporter.example_group_finished(child) end false end # @private def self.declaration_locations @declaration_locations ||= [Metadata.location_tuple_from(metadata)] + examples.map { |e| Metadata.location_tuple_from(e.metadata) } + FlatMap.flat_map(children, &:declaration_locations) end # @return [String] the unique id of this example group. Pass # this at the command line to re-run this exact example group. def self.id Metadata.id_from(metadata) end # @private def self.top_level_description parent_groups.last.description end # @private def self.set_ivars(instance, ivars) ivars.each { |name, value| instance.instance_variable_set(name, value) } end if RUBY_VERSION.to_f < 1.9 # :nocov: # @private INSTANCE_VARIABLE_TO_IGNORE = '@__inspect_output'.freeze # :nocov: else # @private INSTANCE_VARIABLE_TO_IGNORE = :@__inspect_output end # @private def self.each_instance_variable_for_example(group) group.instance_variables.each do |ivar| yield ivar unless ivar == INSTANCE_VARIABLE_TO_IGNORE end end # @private def initialize(inspect_output=nil) @__inspect_output = inspect_output || '(no description provided)' super() # no args get passed end # @private def inspect "#<#{self.class} #{@__inspect_output}>" end unless method_defined?(:singleton_class) # for 1.8.7 # :nocov: # @private def singleton_class class << self; self; end end # :nocov: end # @private def self.update_inherited_metadata(updates) metadata.update(updates) do |key, existing_group_value, new_inherited_value| @user_metadata.key?(key) ? existing_group_value : new_inherited_value end RSpec.configuration.configure_group(self) examples.each { |ex| ex.update_inherited_metadata(updates) } children.each { |group| group.update_inherited_metadata(updates) } end # Raised when an RSpec API is called in the wrong scope, such as `before` # being called from within an example rather than from within an example # group block. WrongScopeError = Class.new(NoMethodError) def self.method_missing(name, *args) if method_defined?(name) raise WrongScopeError, "`#{name}` is not available on an example group (e.g. a " \ "`describe` or `context` block). It is only available from " \ "within individual examples (e.g. `it` blocks) or from " \ "constructs that run in the scope of an example (e.g. " \ "`before`, `let`, etc)." end super end private_class_method :method_missing private def method_missing(name, *args) if self.class.respond_to?(name) raise WrongScopeError, "`#{name}` is not available from within an example (e.g. an " \ "`it` block) or from constructs that run in the scope of an " \ "example (e.g. `before`, `let`, etc). It is only available " \ "on an example group (e.g. a `describe` or `context` block)." end super(name, *args) end ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) end # rubocop:enable Metrics/ClassLength # @private # Unnamed example group used by `SuiteHookContext`. class AnonymousExampleGroup < ExampleGroup def self.metadata {} end end # Contains information about the inclusion site of a shared example group. class SharedExampleGroupInclusionStackFrame # @return [String] the name of the shared example group attr_reader :shared_group_name # @return [String] the location where the shared example was included attr_reader :inclusion_location # @private def initialize(shared_group_name, inclusion_location) @shared_group_name = shared_group_name @inclusion_location = inclusion_location end # @return [String] The {#inclusion_location}, formatted for display by a formatter. def formatted_inclusion_location @formatted_inclusion_location ||= begin RSpec.configuration.backtrace_formatter.backtrace_line( inclusion_location.sub(/(:\d+):in .+$/, '\1') ) end end # @return [String] Description of this stack frame, in the form used by # RSpec's built-in formatters. def description @description ||= "Shared Example Group: #{shared_group_name.inspect} " \ "called from #{formatted_inclusion_location}" end # @private def self.current_backtrace shared_example_group_inclusions.reverse end # @private def self.with_frame(name, location) current_stack = shared_example_group_inclusions if current_stack.any? { |frame| frame.shared_group_name == name } raise ArgumentError, "can't include shared examples recursively" else current_stack << new(name, location) yield end ensure current_stack.pop end # @private def self.shared_example_group_inclusions RSpec::Support.thread_local_data[:shared_example_group_inclusions] ||= [] end end end # @private # # Namespace for the example group subclasses generated by top-level # `describe`. module ExampleGroups extend Support::RecursiveConstMethods def self.assign_const(group) base_name = base_name_for(group) const_scope = constant_scope_for(group) name = disambiguate(base_name, const_scope) const_scope.const_set(name, group) end def self.constant_scope_for(group) const_scope = group.superclass const_scope = self if const_scope == ::RSpec::Core::ExampleGroup const_scope end def self.remove_all_constants constants.each do |constant| __send__(:remove_const, constant) end end def self.base_name_for(group) return "Anonymous".dup if group.description.empty? # Convert to CamelCase. name = ' ' + group.description name.gsub!(/[^0-9a-zA-Z]+([0-9a-zA-Z])/) do match = ::Regexp.last_match[1] match.upcase! match end name.lstrip! # Remove leading whitespace name.gsub!(/\W/, ''.freeze) # JRuby, RBX and others don't like non-ascii in const names # Ruby requires first const letter to be A-Z. Use `Nested` # as necessary to enforce that. name.gsub!(/\A([^A-Z]|\z)/, 'Nested\1'.freeze) name end if RUBY_VERSION == '1.9.2' # :nocov: class << self alias _base_name_for base_name_for def base_name_for(group) _base_name_for(group) + '_' end end private_class_method :_base_name_for # :nocov: end def self.disambiguate(name, const_scope) return name unless const_defined_on?(const_scope, name) # Add a trailing number if needed to disambiguate from an existing # constant. name << "_2" name.next! while const_defined_on?(const_scope, name) name end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/example_status_persister.rb0000664000000000000000000001627614557677674027172 0ustar rootrootRSpec::Support.require_rspec_support "directory_maker" module RSpec module Core # Persists example ids and their statuses so that we can filter # to just the ones that failed the last time they ran. # @private class ExampleStatusPersister def self.load_from(file_name) return [] unless File.exist?(file_name) ExampleStatusParser.parse(File.read(file_name)) end def self.persist(examples, file_name) new(examples, file_name).persist end def initialize(examples, file_name) @examples = examples @file_name = file_name end def persist RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(@file_name)) File.open(@file_name, File::RDWR | File::CREAT) do |f| # lock the file while reading / persisting to avoid a race # condition where parallel or unrelated spec runs race to # update the same file f.flock(File::LOCK_EX) unparsed_previous_runs = f.read f.rewind f.write(dump_statuses(unparsed_previous_runs)) f.flush f.truncate(f.pos) end end private def dump_statuses(unparsed_previous_runs) statuses_from_previous_runs = ExampleStatusParser.parse(unparsed_previous_runs) merged_statuses = ExampleStatusMerger.merge(statuses_from_this_run, statuses_from_previous_runs) ExampleStatusDumper.dump(merged_statuses) end def statuses_from_this_run @examples.map do |ex| result = ex.execution_result { :example_id => ex.id, :status => result.status ? result.status.to_s : Configuration::UNKNOWN_STATUS, :run_time => result.run_time ? Formatters::Helpers.format_duration(result.run_time) : "" } end end end # Merges together a list of example statuses from this run # and a list from previous runs (presumably loaded from disk). # Each example status object is expected to be a hash with # at least an `:example_id` and a `:status` key. Examples that # were loaded but not executed (due to filtering, `--fail-fast` # or whatever) should have a `:status` of `UNKNOWN_STATUS`. # # This will produce a new list that: # - Will be missing examples from previous runs that we know for sure # no longer exist. # - Will have the latest known status for any examples that either # definitively do exist or may still exist. # - Is sorted by file name and example definition order, so that # the saved file is easily scannable if users want to inspect it. # @private class ExampleStatusMerger def self.merge(this_run, from_previous_runs) new(this_run, from_previous_runs).merge end def initialize(this_run, from_previous_runs) @this_run = hash_from(this_run) @from_previous_runs = hash_from(from_previous_runs) @file_exists_cache = Hash.new { |hash, file| hash[file] = File.exist?(file) } end def merge delete_previous_examples_that_no_longer_exist @this_run.merge(@from_previous_runs) do |_ex_id, new, old| new.fetch(:status) == Configuration::UNKNOWN_STATUS ? old : new end.values.sort_by(&method(:sort_value_from)) end private def hash_from(example_list) example_list.inject({}) do |hash, example| hash[example.fetch(:example_id)] = example hash end end def delete_previous_examples_that_no_longer_exist @from_previous_runs.delete_if do |ex_id, _| example_must_no_longer_exist?(ex_id) end end def example_must_no_longer_exist?(ex_id) # Obviously, it exists if it was loaded for this spec run... return false if @this_run.key?(ex_id) spec_file = spec_file_from(ex_id) # `this_run` includes examples that were loaded but not executed. # Given that, if the spec file for this example was loaded, # but the id does not still exist, it's safe to assume that # the example must no longer exist. return true if loaded_spec_files.include?(spec_file) # The example may still exist as long as the file exists... !@file_exists_cache[spec_file] end def loaded_spec_files @loaded_spec_files ||= Set.new(@this_run.keys.map(&method(:spec_file_from))) end def spec_file_from(ex_id) ex_id.split("[").first end def sort_value_from(example) file, scoped_id = Example.parse_id(example.fetch(:example_id)) [file, *scoped_id.split(":").map(&method(:Integer))] end end # Dumps a list of hashes in a pretty, human readable format # for later parsing. The hashes are expected to have symbol # keys and string values, and each hash should have the same # set of keys. # @private class ExampleStatusDumper def self.dump(examples) new(examples).dump end def initialize(examples) @examples = examples end def dump return nil if @examples.empty? (formatted_header_rows + formatted_value_rows).join("\n") << "\n" end private def formatted_header_rows @formatted_header_rows ||= begin dividers = column_widths.map { |w| "-" * w } [formatted_row_from(headers.map(&:to_s)), formatted_row_from(dividers)] end end def formatted_value_rows @formatted_value_rows ||= rows.map do |row| formatted_row_from(row) end end def rows @rows ||= @examples.map { |ex| ex.values_at(*headers) } end def formatted_row_from(row_values) padded_values = row_values.each_with_index.map do |value, index| value.ljust(column_widths[index]) end padded_values.join(" | ") << " |" end def headers @headers ||= @examples.first.keys end def column_widths @column_widths ||= begin value_sets = rows.transpose headers.each_with_index.map do |header, index| values = value_sets[index] << header.to_s values.map(&:length).max end end end end # Parses a string that has been previously dumped by ExampleStatusDumper. # Note that this parser is a bit naive in that it does a simple split on # "\n" and " | ", with no concern for handling escaping. For now, that's # OK because the values we plan to persist (example id, status, and perhaps # example duration) are highly unlikely to contain "\n" or " | " -- after # all, who puts those in file names? # @private class ExampleStatusParser def self.parse(string) new(string).parse end def initialize(string) @header_line, _, *@row_lines = string.lines.to_a end def parse @row_lines.map { |line| parse_row(line) } end private def parse_row(line) Hash[headers.zip(split_line(line))] end def headers @headers ||= split_line(@header_line).grep(/\S/).map(&:to_sym) end def split_line(line) line.split(/\s+\|\s+?/, -1) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/ordering.rb0000664000000000000000000001253014557677674023632 0ustar rootrootmodule RSpec module Core # @private module Ordering # @private # The default global ordering (defined order). class Identity def order(items) items end end # @private # Orders items randomly. class Random def initialize(configuration) @configuration = configuration @used = false end def used? @used end def order(items) @used = true seed = @configuration.seed.to_s items.sort_by { |item| jenkins_hash_digest(seed + item.id) } end private # http://en.wikipedia.org/wiki/Jenkins_hash_function # Jenkins provides a good distribution and is simpler than MD5. # It's a bit slower than MD5 (primarily because `Digest::MD5` is # implemented in C) but has the advantage of not requiring us # to load another part of stdlib, which we try to minimize. def jenkins_hash_digest(string) hash = 0 string.each_byte do |byte| hash += byte hash &= MAX_32_BIT hash += ((hash << 10) & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 6 end hash += ((hash << 3) & MAX_32_BIT) hash &= MAX_32_BIT hash ^= hash >> 11 hash += ((hash << 15) & MAX_32_BIT) hash &= MAX_32_BIT hash end MAX_32_BIT = 4_294_967_295 end # @private # Orders items by modification time (most recent modified first). class RecentlyModified def order(list) list.sort_by { |item| -File.mtime(item.metadata[:absolute_file_path]).to_i } end end # @private # Orders items based on a custom block. class Custom def initialize(callable) @callable = callable end def order(list) @callable.call(list) end end # @private # A strategy which delays looking up the ordering until needed class Delayed def initialize(registry, name) @registry = registry @name = name end def order(list) strategy.order(list) end private def strategy @strategy ||= lookup_strategy end def lookup_strategy raise "Undefined ordering strategy #{@name.inspect}" unless @registry.has_strategy?(@name) @registry.fetch(@name) end end # @private # Stores the different ordering strategies. class Registry def initialize(configuration) @configuration = configuration @strategies = {} register(:random, Random.new(configuration)) register(:recently_modified, RecentlyModified.new) identity = Identity.new register(:defined, identity) # The default global ordering is --defined. register(:global, identity) end def fetch(name, &fallback) @strategies.fetch(name, &fallback) end def has_strategy?(name) @strategies.key?(name) end def register(sym, strategy) @strategies[sym] = strategy end def used_random_seed? @strategies[:random].used? end end # @private # Manages ordering configuration. # # @note This is not intended to be used externally. Use # the APIs provided by `RSpec::Core::Configuration` instead. class ConfigurationManager attr_reader :seed, :ordering_registry def initialize @ordering_registry = Registry.new(self) @seed = rand(0xFFFF) @seed_forced = false @order_forced = false end def seed_used? ordering_registry.used_random_seed? end def seed=(seed) return if @seed_forced register_ordering(:global, ordering_registry.fetch(:random)) @seed = seed.to_i end def order=(type) order, seed = type.to_s.split(':') @seed = seed.to_i if seed ordering_name = if order.include?('rand') :random elsif order == 'defined' :defined elsif order == 'recently-modified' :recently_modified else order.to_sym end if ordering_name strategy = if ordering_registry.has_strategy?(ordering_name) ordering_registry.fetch(ordering_name) else Delayed.new(ordering_registry, ordering_name) end register_ordering(:global, strategy) end end def force(hash) if hash.key?(:seed) self.seed = hash[:seed] @seed_forced = true @order_forced = true elsif hash.key?(:order) self.order = hash[:order] @order_forced = true end end def register_ordering(name, strategy=Custom.new(Proc.new { |l| yield l })) return if @order_forced && name == :global ordering_registry.register(name, strategy) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/runner.rb0000664000000000000000000001562414557677674023341 0ustar rootrootmodule RSpec module Core # Provides the main entry point to run a suite of RSpec examples. class Runner # @attr_reader # @private attr_reader :options, :configuration, :world # Register an `at_exit` hook that runs the suite when the process exits. # # @note This is not generally needed. The `rspec` command takes care # of running examples for you without involving an `at_exit` # hook. This is only needed if you are running specs using # the `ruby` command, and even then, the normal way to invoke # this is by requiring `rspec/autorun`. def self.autorun if autorun_disabled? RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command") return elsif installed_at_exit? || running_in_drb? return end at_exit { perform_at_exit } @installed_at_exit = true end # @private def self.perform_at_exit # Don't bother running any specs and just let the program terminate # if we got here due to an unrescued exception (anything other than # SystemExit, which is raised when somebody calls Kernel#exit). return unless $!.nil? || $!.is_a?(SystemExit) # We got here because either the end of the program was reached or # somebody called Kernel#exit. Run the specs and then override any # existing exit status with RSpec's exit status if any specs failed. invoke end # Runs the suite of specs and exits the process with an appropriate exit # code. def self.invoke disable_autorun! status = run(ARGV, $stderr, $stdout).to_i exit(status) if status != 0 end # Run a suite of RSpec examples. Does not exit. # # This is used internally by RSpec to run a suite, but is available # for use by any other automation tool. # # If you want to run this multiple times in the same process, and you # want files like `spec_helper.rb` to be reloaded, be sure to load `load` # instead of `require`. # # @param args [Array] command-line-supported arguments # @param err [IO] error stream # @param out [IO] output stream # @return [Fixnum] exit status code. 0 if all specs passed, # or the configured failure exit code (1 by default) if specs # failed. def self.run(args, err=$stderr, out=$stdout) trap_interrupt options = ConfigurationOptions.new(args) if options.options[:runner] options.options[:runner].call(options, err, out) else new(options).run(err, out) end end def initialize(options, configuration=RSpec.configuration, world=RSpec.world) @options = options @configuration = configuration @world = world end # Configures and runs a spec suite. # # @param err [IO] error stream # @param out [IO] output stream def run(err, out) setup(err, out) return @configuration.reporter.exit_early(exit_code) if RSpec.world.wants_to_quit run_specs(@world.ordered_example_groups).tap do persist_example_statuses end end # Wires together the various configuration objects and state holders. # # @param err [IO] error stream # @param out [IO] output stream def setup(err, out) configure(err, out) return if RSpec.world.wants_to_quit @configuration.load_spec_files ensure @world.announce_filters end # Runs the provided example groups. # # @param example_groups [Array] groups to run # @return [Fixnum] exit status code. 0 if all specs passed, # or the configured failure exit code (1 by default) if specs # failed. def run_specs(example_groups) examples_count = @world.example_count(example_groups) examples_passed = @configuration.reporter.report(examples_count) do |reporter| @configuration.with_suite_hooks do if examples_count == 0 && @configuration.fail_if_no_examples return @configuration.failure_exit_code end example_groups.map { |g| g.run(reporter) }.all? end end exit_code(examples_passed) end # @private def configure(err, out) @configuration.error_stream = err @configuration.output_stream = out if @configuration.output_stream == $stdout @options.configure(@configuration) end # @private def self.disable_autorun! @autorun_disabled = true end # @private def self.autorun_disabled? @autorun_disabled ||= false end # @private def self.installed_at_exit? @installed_at_exit ||= false end # @private def self.running_in_drb? return false unless defined?(DRb) server = begin DRb.current_server rescue DRb::DRbServerNotFound return false end return false unless server && server.alive? require 'socket' require 'uri' local_ipv4 = begin IPSocket.getaddress(Socket.gethostname) rescue SocketError return false end ["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host } end # @private def self.trap_interrupt trap('INT') { handle_interrupt } end # @private def self.handle_interrupt if RSpec.world.wants_to_quit exit!(1) else RSpec.world.wants_to_quit = true $stderr.puts( "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit " \ "(warning: at_exit hooks will be skipped if you force quit)." ) end end # @private def exit_code(examples_passed=false) return @configuration.error_exit_code || @configuration.failure_exit_code if @world.non_example_failure return @configuration.failure_exit_code unless examples_passed 0 end private def persist_example_statuses return if @configuration.dry_run return unless (path = @configuration.example_status_persistence_file_path) ExampleStatusPersister.persist(@world.all_examples, path) rescue SystemCallError => e RSpec.warning "Could not write example statuses to #{path} (configured as " \ "`config.example_status_persistence_file_path`) due to a " \ "system error: #{e.inspect}. Please check that the config " \ "option is set to an accessible, valid file path", :call_site => nil end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/0000775000000000000000000000000014557677674022744 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/example_minimizer.rb0000664000000000000000000001326714557677674027020 0ustar rootrootRSpec::Support.require_rspec_core "bisect/utilities" module RSpec module Core module Bisect # @private # Contains the core bisect logic. Searches for examples we can ignore by # repeatedly running different subsets of the suite. class ExampleMinimizer attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids attr_accessor :remaining_ids def initialize(shell_command, runner, notifier) @shell_command = shell_command @runner = runner @notifier = notifier end def find_minimal_repro prep _, duration = track_duration do bisect(non_failing_example_ids) end notify(:bisect_complete, :duration => duration, :original_non_failing_count => non_failing_example_ids.size, :remaining_count => remaining_ids.size) remaining_ids + failed_example_ids end def bisect(candidate_ids) notify(:bisect_dependency_check_started) if get_expected_failures_for?([]) notify(:bisect_dependency_check_failed) self.remaining_ids = [] return end notify(:bisect_dependency_check_passed) bisect_over(candidate_ids) end def bisect_over(candidate_ids) return if candidate_ids.one? notify( :bisect_round_started, :candidate_range => example_range(candidate_ids), :candidates_count => candidate_ids.size ) slice_size = (candidate_ids.length / 2.0).ceil lhs, rhs = candidate_ids.each_slice(slice_size).to_a ids_to_ignore, duration = track_duration do [lhs, rhs].find do |ids| get_expected_failures_for?(remaining_ids - ids) end end if ids_to_ignore self.remaining_ids -= ids_to_ignore notify( :bisect_round_ignoring_ids, :ids_to_ignore => ids_to_ignore, :ignore_range => example_range(ids_to_ignore), :remaining_ids => remaining_ids, :duration => duration ) bisect_over(candidate_ids - ids_to_ignore) else notify( :bisect_round_detected_multiple_culprits, :duration => duration ) bisect_over(lhs) bisect_over(rhs) end end def currently_needed_ids remaining_ids + failed_example_ids end def repro_command_for_currently_needed_ids return shell_command.repro_command_from(currently_needed_ids) if remaining_ids "(Not yet enough information to provide any repro command)" end # @private # Convenience class for describing a subset of the candidate examples ExampleRange = Struct.new(:start, :finish) do def description if start == finish "example #{start}" else "examples #{start}-#{finish}" end end end private def example_range(ids) ExampleRange.new( non_failing_example_ids.find_index(ids.first) + 1, non_failing_example_ids.find_index(ids.last) + 1 ) end def prep notify(:bisect_starting, :original_cli_args => shell_command.original_cli_args, :bisect_runner => runner.class.name) _, duration = track_duration do original_results = runner.original_results @all_example_ids = original_results.all_example_ids @failed_example_ids = original_results.failed_example_ids @remaining_ids = non_failing_example_ids end if @failed_example_ids.empty? raise BisectFailedError, "\n\nNo failures found. Bisect only works " \ "in the presence of one or more failing examples." else notify(:bisect_original_run_complete, :failed_example_ids => failed_example_ids, :non_failing_example_ids => non_failing_example_ids, :duration => duration) end end def non_failing_example_ids @non_failing_example_ids ||= all_example_ids - failed_example_ids end def get_expected_failures_for?(ids) ids_to_run = ids + failed_example_ids notify( :bisect_individual_run_start, :command => shell_command.repro_command_from(ids_to_run), :ids_to_run => ids_to_run ) results, duration = track_duration { runner.run(ids_to_run) } notify(:bisect_individual_run_complete, :duration => duration, :results => results) abort_if_ordering_inconsistent(results) (failed_example_ids & results.failed_example_ids) == failed_example_ids end def track_duration start = ::RSpec::Core::Time.now [yield, ::RSpec::Core::Time.now - start] end def abort_if_ordering_inconsistent(results) expected_order = all_example_ids & results.all_example_ids return if expected_order == results.all_example_ids raise BisectFailedError, "\n\nThe example ordering is inconsistent. " \ "`--bisect` relies upon consistent ordering (e.g. by passing " \ "`--seed` if you're using random ordering) to work properly." end def notify(*args) @notifier.publish(*args) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/server.rb0000664000000000000000000000334314557677674024602 0ustar rootrootrequire 'drb/drb' require 'drb/acl' RSpec::Support.require_rspec_core "bisect/utilities" module RSpec module Core # @private module Bisect # @private # A DRb server that receives run results from a separate RSpec process # started by the bisect process. class Server def self.run server = new server.start yield server ensure server.stop end def capture_run_results(files_or_directories_to_run=[], expected_failures=[]) self.expected_failures = expected_failures self.files_or_directories_to_run = files_or_directories_to_run self.latest_run_results = nil run_output = yield if latest_run_results.nil? || latest_run_results.all_example_ids.empty? raise BisectFailedError.for_failed_spec_run(run_output) end latest_run_results end def start # Only allow remote DRb requests from this machine. DRb.install_acl ACL.new(%w[ deny all allow localhost allow 127.0.0.1 allow ::1 ]) # We pass `nil` as the first arg to allow it to pick a DRb port. @drb = DRb.start_service(nil, self) end def stop @drb.stop_service end def drb_port @drb_port ||= Integer(@drb.uri[/\d+$/]) end # Fetched via DRb by the BisectDRbFormatter to determine when to abort. attr_accessor :expected_failures # Set via DRb by the BisectDRbFormatter with the results of the run. attr_accessor :latest_run_results # Fetched via DRb to tell clients which files to run attr_accessor :files_or_directories_to_run end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/shell_runner.rb0000664000000000000000000000377214557677674026002 0ustar rootrootrequire 'open3' RSpec::Support.require_rspec_core "bisect/server" module RSpec module Core module Bisect # Provides an API to run the suite for a set of locations, using # the given bisect server to capture the results. # # Sets of specs are run by shelling out. # @private class ShellRunner def self.start(shell_command, _spec_runner) Server.run do |server| yield new(server, shell_command) end end def self.name :shell end def initialize(server, shell_command) @server = server @shell_command = shell_command end def run(locations) run_locations(locations, original_results.failed_example_ids) end def original_results @original_results ||= run_locations(@shell_command.original_locations) end private def run_locations(*capture_args) @server.capture_run_results(*capture_args) do run_command @shell_command.command_for([], @server) end end # `Open3.capture2e` does not work on JRuby: # https://github.com/jruby/jruby/issues/2766 if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby? def run_command(cmd) Open3.capture2e(@shell_command.bisect_environment_hash, cmd).first end else # for 1.8.7 # :nocov: def run_command(cmd) out = err = nil original_spec_opts = ENV['SPEC_OPTS'] ENV['SPEC_OPTS'] = @shell_command.spec_opts_without_bisect Open3.popen3(cmd) do |_, stdout, stderr| # Reading the streams blocks until the process is complete out = stdout.read err = stderr.read end "Stdout:\n#{out}\n\nStderr:\n#{err}" ensure ENV['SPEC_OPTS'] = original_spec_opts end # :nocov: end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/shell_command.rb0000664000000000000000000000745014557677674026104 0ustar rootrootRSpec::Support.require_rspec_core "shell_escape" require 'shellwords' module RSpec module Core module Bisect # Provides an API to generate shell commands to run the suite for a # set of locations, using the given bisect server to capture the results. # @private class ShellCommand attr_reader :original_cli_args def initialize(original_cli_args) @original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") } end def command_for(locations, server) parts = [] parts << RUBY << load_path parts << open3_safe_escape(RSpec::Core.path_to_executable) parts << "--format" << "bisect-drb" parts << "--drb-port" << server.drb_port parts.concat(reusable_cli_options) parts.concat(locations.map { |l| open3_safe_escape(l) }) parts.join(" ") end def repro_command_from(locations) parts = [] parts.concat environment_repro_parts parts << "rspec" parts.concat Formatters::Helpers.organize_ids(locations) parts.concat original_cli_args_without_locations parts.join(" ") end def original_locations parsed_original_cli_options.fetch(:files_or_directories_to_run) end def bisect_environment_hash if ENV.key?('SPEC_OPTS') { 'SPEC_OPTS' => spec_opts_without_bisect } else {} end end def spec_opts_without_bisect Shellwords.join( Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg| arg =~ /^--bisect/ end ) end private include RSpec::Core::ShellEscape # On JRuby, Open3.popen3 does not handle shellescaped args properly: # https://github.com/jruby/jruby/issues/2767 if RSpec::Support::Ruby.jruby? # :nocov: alias open3_safe_escape quote # :nocov: else alias open3_safe_escape escape end def environment_repro_parts bisect_environment_hash.map do |k, v| %Q(#{k}="#{v}") end end def reusable_cli_options @reusable_cli_options ||= begin opts = original_cli_args_without_locations if (port = parsed_original_cli_options[:drb_port]) opts -= %W[ --drb-port #{port} ] end parsed_original_cli_options.fetch(:formatters) { [] }.each do |(name, out)| opts -= %W[ --format #{name} -f -f#{name} ] opts -= %W[ --out #{out} -o -o#{out} ] end opts end end def original_cli_args_without_locations @original_cli_args_without_locations ||= begin files_or_dirs = parsed_original_cli_options.fetch(:files_or_directories_to_run) @original_cli_args - files_or_dirs end end def parsed_original_cli_options @parsed_original_cli_options ||= Parser.parse(@original_cli_args) end def load_path @load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}" end # Path to the currently running Ruby executable, borrowed from Rake: # https://github.com/ruby/rake/blob/v10.4.2/lib/rake/file_utils.rb#L8-L12 # Note that we skip `ENV['RUBY']` because we don't have to deal with running # RSpec from within a MRI source repository: # https://github.com/ruby/rake/commit/968682759b3b65e42748cd2befb2ff3e982272d9 RUBY = File.join( RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']). sub(/.*\s.*/m, '"\&"') end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/coordinator.rb0000664000000000000000000000416114557677674025616 0ustar rootrootRSpec::Support.require_rspec_core "bisect/shell_command" RSpec::Support.require_rspec_core "bisect/example_minimizer" RSpec::Support.require_rspec_core "bisect/utilities" RSpec::Support.require_rspec_core "formatters/bisect_progress_formatter" module RSpec module Core module Bisect # The main entry point into the bisect logic. Coordinates among: # - Bisect::ShellCommand: Generates shell commands to run spec subsets # - Bisect::ExampleMinimizer: Contains the core bisect logic. # - A bisect runner: runs a set of examples and returns the results. # - A bisect formatter: provides progress updates to the user. # @private class Coordinator def self.bisect_with(spec_runner, original_cli_args, formatter) new(spec_runner, original_cli_args, formatter).bisect end def initialize(spec_runner, original_cli_args, formatter) @spec_runner = spec_runner @shell_command = ShellCommand.new(original_cli_args) @notifier = Bisect::Notifier.new(formatter) end def bisect repro = start_bisect_runner do |runner| minimizer = ExampleMinimizer.new(@shell_command, runner, @notifier) gracefully_abort_on_sigint(minimizer) minimizer.find_minimal_repro minimizer.repro_command_for_currently_needed_ids end @notifier.publish(:bisect_repro_command, :repro => repro) true rescue BisectFailedError => e @notifier.publish(:bisect_failed, :failure_explanation => e.message) false ensure @notifier.publish(:close) end private def start_bisect_runner(&block) klass = @spec_runner.configuration.bisect_runner_class klass.start(@shell_command, @spec_runner, &block) end def gracefully_abort_on_sigint(minimizer) trap('INT') do repro = minimizer.repro_command_for_currently_needed_ids @notifier.publish(:bisect_aborted, :repro => repro) exit(1) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/utilities.rb0000664000000000000000000000377614557677674025321 0ustar rootrootmodule RSpec module Core module Bisect # @private ExampleSetDescriptor = Struct.new(:all_example_ids, :failed_example_ids) # @private class BisectFailedError < StandardError def self.for_failed_spec_run(spec_output) new("Failed to get results from the spec run. Spec run output:\n\n" + spec_output) end end # Wraps a `formatter` providing a simple means to notify it in place # of an `RSpec::Core::Reporter`, without involving configuration in # any way. # @private class Notifier def initialize(formatter) @formatter = formatter end def publish(event, *args) return unless @formatter.respond_to?(event) notification = Notifications::CustomNotification.for(*args) @formatter.__send__(event, notification) end end # Wraps a pipe to support sending objects between a child and # parent process. Where supported, encoding is explicitly # set to ensure binary data is able to pass from child to # parent. # @private class Channel if String.method_defined?(:encoding) MARSHAL_DUMP_ENCODING = Marshal.dump("").encoding end def initialize @read_io, @write_io = IO.pipe if defined?(MARSHAL_DUMP_ENCODING) && IO.method_defined?(:set_encoding) # Ensure the pipe can send any content produced by Marshal.dump @write_io.set_encoding MARSHAL_DUMP_ENCODING end end def send(message) packet = Marshal.dump(message) @write_io.write("#{packet.bytesize}\n#{packet}") end # rubocop:disable Security/MarshalLoad def receive packet_size = Integer(@read_io.gets) Marshal.load(@read_io.read(packet_size)) end # rubocop:enable Security/MarshalLoad def close @read_io.close @write_io.close end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/bisect/fork_runner.rb0000664000000000000000000001225714557677674025632 0ustar rootrootrequire 'stringio' RSpec::Support.require_rspec_core "formatters/base_bisect_formatter" RSpec::Support.require_rspec_core "bisect/utilities" module RSpec module Core module Bisect # A Bisect runner that runs requested subsets of the suite by forking # sub-processes. The main process bootstraps RSpec and the application # environment (including preloading files specified via `--require`) so # that the individual spec runs do not have to re-pay that cost. Each # spec run happens in a forked process, ensuring that the spec files are # not loaded in the main process. # # For most projects, bisections that use `ForkRunner` instead of # `ShellRunner` will finish significantly faster, because the `ShellRunner` # pays the cost of booting RSpec and the app environment on _every_ run of # a subset. In contrast, `ForkRunner` pays that cost only once. # # However, not all projects can use `ForkRunner`. Obviously, on platforms # that do not support forking (e.g. Windows), it cannot be used. In addition, # it can cause problems for some projects that put side-effectful spec # bootstrapping logic that should run on every spec run directly at the top # level in a file loaded by `--require`, rather than in a `before(:suite)` # hook. For example, consider a project that relies on some top-level logic # in `spec_helper` to boot a Redis server for the test suite, intending the # Redis bootstrapping to happen on every spec run. With `ShellRunner`, the # bootstrapping logic will happen for each run of any subset of the suite, # but for `ForkRunner`, such logic will only get run once, when the # `RunDispatcher` boots the application environment. This might cause # problems. The solution is for users to move the bootstrapping logic into # a `before(:suite)` hook, or use the slower `ShellRunner`. # # @private class ForkRunner def self.start(shell_command, spec_runner) instance = new(shell_command, spec_runner) yield instance ensure instance.shutdown end def self.name :fork end def initialize(shell_command, spec_runner) @shell_command = shell_command @channel = Channel.new @run_dispatcher = RunDispatcher.new(spec_runner, @channel) end def run(locations) run_descriptor = ExampleSetDescriptor.new(locations, original_results.failed_example_ids) dispatch_run(run_descriptor) end def original_results @original_results ||= dispatch_run(ExampleSetDescriptor.new( @shell_command.original_locations, [])) end def shutdown @channel.close end private def dispatch_run(run_descriptor) @run_dispatcher.dispatch_specs(run_descriptor) @channel.receive.tap do |result| if result.is_a?(String) raise BisectFailedError.for_failed_spec_run(result) end end end # @private class RunDispatcher def initialize(runner, channel) @runner = runner @channel = channel @spec_output = StringIO.new runner.configuration.tap do |c| c.reset_reporter c.output_stream = @spec_output c.error_stream = @spec_output end end def dispatch_specs(run_descriptor) pid = fork { run_specs(run_descriptor) } # We don't use Process.waitpid here as it was causing bisects to # block due to the file descriptor limit on OSX / Linux. We need # to detach the process to avoid having zombie processes # consuming slots in the kernel process table during bisect runs. Process.detach(pid) end private def run_specs(run_descriptor) $stdout = $stderr = @spec_output formatter = CaptureFormatter.new(run_descriptor.failed_example_ids) @runner.configuration.tap do |c| c.files_or_directories_to_run = run_descriptor.all_example_ids c.formatter = formatter c.load_spec_files end # `announce_filters` has the side effect of implementing the logic # that honors `config.run_all_when_everything_filtered` so we need # to call it here. When we remove `run_all_when_everything_filtered` # (slated for RSpec 4), we can remove this call to `announce_filters`. @runner.world.announce_filters @runner.run_specs(@runner.world.ordered_example_groups) latest_run_results = formatter.results if latest_run_results.nil? || latest_run_results.all_example_ids.empty? @channel.send(@spec_output.string) else @channel.send(latest_run_results) end end end class CaptureFormatter < Formatters::BaseBisectFormatter attr_accessor :results alias_method :notify_results, :results= end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/drb.rb0000664000000000000000000000772614557677674022603 0ustar rootrootrequire 'drb/drb' module RSpec module Core # @private class DRbRunner def initialize(options, configuration=RSpec.configuration) @options = options @configuration = configuration end def drb_port @options.options[:drb_port] || ENV['RSPEC_DRB'] || 8989 end def run(err, out) begin DRb.start_service("druby://localhost:0") rescue SocketError, Errno::EADDRNOTAVAIL DRb.start_service("druby://:0") end spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}") spec_server.run(drb_argv, err, out) end def drb_argv @drb_argv ||= begin @options.configure_filter_manager(@configuration.filter_manager) DRbOptions.new(@options.options, @configuration.filter_manager).options end end end # @private class DRbOptions def initialize(submitted_options, filter_manager) @submitted_options = submitted_options @filter_manager = filter_manager end def options argv = [] argv << "--color" if @submitted_options[:color] argv << "--force-color" if @submitted_options[:color_mode] == :on argv << "--no-color" if @submitted_options[:color_mode] == :off argv << "--profile" if @submitted_options[:profile_examples] argv << "--backtrace" if @submitted_options[:full_backtrace] argv << "--tty" if @submitted_options[:tty] argv << "--fail-fast" if @submitted_options[:fail_fast] argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file] argv << "--order" << @submitted_options[:order] if @submitted_options[:order] add_failure_exit_code(argv) add_error_exit_code(argv) add_full_description(argv) add_filter(argv, :inclusion, @filter_manager.inclusions) add_filter(argv, :exclusion, @filter_manager.exclusions) add_formatters(argv) add_libs(argv) add_requires(argv) argv + @submitted_options[:files_or_directories_to_run] end def add_failure_exit_code(argv) return unless @submitted_options[:failure_exit_code] argv << "--failure-exit-code" << @submitted_options[:failure_exit_code].to_s end def add_error_exit_code(argv) return unless @submitted_options[:error_exit_code] argv << "--error-exit-code" << @submitted_options[:error_exit_code].to_s end def add_full_description(argv) return unless @submitted_options[:full_description] # The argument to --example is regexp-escaped before being stuffed # into a regexp when received for the first time (see OptionParser). # Hence, merely grabbing the source of this regexp will retain the # backslashes, so we must remove them. @submitted_options[:full_description].each do |description| argv << "--example" << description.source.delete('\\') end end CONDITIONAL_FILTERS = [:if, :unless] def add_filter(argv, name, hash) hash.each_pair do |k, v| next if CONDITIONAL_FILTERS.include?(k) tag = name == :inclusion ? k.to_s : "~#{k}".dup tag << ":#{v}" if v.is_a?(String) argv << "--tag" << tag end unless hash.empty? end def add_formatters(argv) @submitted_options[:formatters].each do |pair| argv << "--format" << pair[0] argv << "--out" << pair[1] if pair[1] end if @submitted_options[:formatters] end def add_libs(argv) @submitted_options[:libs].each do |path| argv << "-I" << path end if @submitted_options[:libs] end def add_requires(argv) @submitted_options[:requires].each do |path| argv << "--require" << path end if @submitted_options[:requires] end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/configuration_options.rb0000664000000000000000000001632714557677674026453 0ustar rootrootrequire 'erb' require 'shellwords' module RSpec module Core # Responsible for utilizing externally provided configuration options, # whether via the command line, `.rspec`, `~/.rspec`, # `$XDG_CONFIG_HOME/rspec/options`, `.rspec-local` or a custom options # file. class ConfigurationOptions # @param args [Array] command line arguments def initialize(args) @args = args.dup organize_options end # Updates the provided {Configuration} instance based on the provided # external configuration options. # # @param config [Configuration] the configuration instance to update def configure(config) process_options_into config configure_filter_manager config.filter_manager load_formatters_into config end # @api private # Updates the provided {FilterManager} based on the filter options. # @param filter_manager [FilterManager] instance to update def configure_filter_manager(filter_manager) @filter_manager_options.each do |command, value| filter_manager.__send__ command, value end end # @return [Hash] the final merged options, drawn from all external sources attr_reader :options # @return [Array] the original command-line arguments attr_reader :args private def organize_options @filter_manager_options = [] @options = (file_options << command_line_options << env_options).each do |opts| @filter_manager_options << [:include, opts.delete(:inclusion_filter)] if opts.key?(:inclusion_filter) @filter_manager_options << [:exclude, opts.delete(:exclusion_filter)] if opts.key?(:exclusion_filter) end @options = @options.inject(:libs => [], :requires => []) do |hash, opts| hash.merge(opts) do |key, oldval, newval| [:libs, :requires].include?(key) ? oldval + newval : newval end end end UNFORCED_OPTIONS = Set.new([ :requires, :profile, :drb, :libs, :files_or_directories_to_run, :full_description, :full_backtrace, :tty ]) UNPROCESSABLE_OPTIONS = Set.new([:formatters]) def force?(key) !UNFORCED_OPTIONS.include?(key) end def order(keys) OPTIONS_ORDER.reverse_each do |key| keys.unshift(key) if keys.delete(key) end keys end OPTIONS_ORDER = [ # It's important to set this before anything that might issue a # deprecation (or otherwise access the reporter). :deprecation_stream, # In order for `RSpec.configuration.dry_run?` to return `true` during # processing the `requires` option, it must be parsed before it. :dry_run, # load paths depend on nothing, but must be set before `requires` # to support load-path-relative requires. :libs, # `files_or_directories_to_run` uses `default_path` so it must be # set before it. :default_path, :only_failures, # These must be set before `requires` to support checking # `config.files_to_run` from within `spec_helper.rb` when a # `-rspec_helper` option is used. :files_or_directories_to_run, :pattern, :exclude_pattern, # Necessary so that the `--seed` option is applied before requires, # in case required files do something with the provided seed. # (such as seed global randomization with it). :order, # In general, we want to require the specified files as early as # possible. The `--require` option is specifically intended to allow # early requires. For later requires, they can just put the require in # their spec files, but `--require` provides a unique opportunity for # users to instruct RSpec to load an extension file early for maximum # flexibility. :requires ] def process_options_into(config) opts = options.reject { |k, _| UNPROCESSABLE_OPTIONS.include? k } order(opts.keys).each do |key| force?(key) ? config.force(key => opts[key]) : config.__send__("#{key}=", opts[key]) end end def load_formatters_into(config) options[:formatters].each { |pair| config.add_formatter(*pair) } if options[:formatters] end def file_options if custom_options_file [custom_options] else [global_options, project_options, local_options] end end def env_options return {} unless ENV['SPEC_OPTS'] parse_args_ignoring_files_or_dirs_to_run( Shellwords.split(ENV["SPEC_OPTS"]), "ENV['SPEC_OPTS']" ) end def command_line_options @command_line_options ||= Parser.parse(@args) end def custom_options options_from(custom_options_file) end def local_options @local_options ||= options_from(local_options_file) end def project_options @project_options ||= options_from(project_options_file) end def global_options @global_options ||= options_from(global_options_file) end def options_from(path) args = args_from_options_file(path) parse_args_ignoring_files_or_dirs_to_run(args, path) end def parse_args_ignoring_files_or_dirs_to_run(args, source) options = Parser.parse(args, source) options.delete(:files_or_directories_to_run) options end def args_from_options_file(path) return [] unless path && File.exist?(path) config_string = options_file_as_erb_string(path) config_lines = config_string.split(/\n+/).reject { |s| s =~ /\A\s*#/ } FlatMap.flat_map(config_lines, &:shellsplit) end def options_file_as_erb_string(path) if RUBY_VERSION >= '2.6' ERB.new(File.read(path), :trim_mode => '-').result(binding) else ERB.new(File.read(path), nil, '-').result(binding) end end def custom_options_file command_line_options[:custom_options_file] end def project_options_file "./.rspec" end def local_options_file "./.rspec-local" end def global_options_file xdg_options_file_if_exists || home_options_file_path end def xdg_options_file_if_exists path = xdg_options_file_path if path && File.exist?(path) path end end def home_options_file_path File.join(File.expand_path("~"), ".rspec") rescue ArgumentError # :nocov: RSpec.warning "Unable to find ~/.rspec because the HOME environment variable is not set" nil # :nocov: end def xdg_options_file_path xdg_config_home = resolve_xdg_config_home if xdg_config_home File.join(xdg_config_home, "rspec", "options") end end def resolve_xdg_config_home File.expand_path(ENV.fetch("XDG_CONFIG_HOME", "~/.config")) rescue ArgumentError # :nocov: # On Ruby 2.4, `File.expand("~")` works even if `ENV['HOME']` is not set. # But on earlier versions, it fails. nil # :nocov: end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/configuration.rb0000664000000000000000000025572414557677674024706 0ustar rootrootRSpec::Support.require_rspec_core "backtrace_formatter" RSpec::Support.require_rspec_core "ruby_project" RSpec::Support.require_rspec_core "formatters/deprecation_formatter" RSpec::Support.require_rspec_core "output_wrapper" module RSpec module Core # rubocop:disable Metrics/ClassLength # Stores runtime configuration information. # # Configuration options are loaded from multiple files and joined together # with command-line switches and the `SPEC_OPTS` environment variable. # # Precedence order (where later entries overwrite earlier entries on # conflicts): # # * Global (`$XDG_CONFIG_HOME/rspec/options`, or `~/.rspec` if it does # not exist) # * Project-specific (`./.rspec`) # * Local (`./.rspec-local`) # * Command-line options # * `SPEC_OPTS` # # For example, an option set in the local file will override an option set # in your global file. # # The global, project-specific and local files can all be overridden with a # separate custom file using the --options command-line parameter. # # @example Standard settings # RSpec.configure do |c| # c.drb = true # c.drb_port = 1234 # c.default_path = 'behavior' # end # # @example Hooks # RSpec.configure do |c| # c.before(:suite) { establish_connection } # c.before(:example) { log_in_as :authorized } # c.around(:example) { |ex| Database.transaction(&ex) } # end # # @see RSpec.configure # @see Hooks class Configuration include RSpec::Core::Hooks # Module that holds `attr_reader` declarations. It's in a separate # module to allow us to override those methods and use `super`. # @private Readers = Module.new include Readers # @private class MustBeConfiguredBeforeExampleGroupsError < StandardError; end # @private def self.define_reader(name) Readers.class_eval do remove_method name if method_defined?(name) attr_reader name end define_method(name) { value_for(name) { super() } } end # @private def self.define_alias(name, alias_name) alias_method alias_name, name alias_method "#{alias_name}=", "#{name}=" define_predicate alias_name end # @private def self.define_predicate(name) define_method "#{name}?" do !!send(name) end end # @private # # Invoked by the `add_setting` instance method. Use that method on a # `Configuration` instance rather than this class method. def self.add_setting(name, opts={}) raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default) attr_writer name add_read_only_setting name Array(opts[:alias_with]).each do |alias_name| define_alias(name, alias_name) end end # @private # # As `add_setting` but only add the reader. def self.add_read_only_setting(name, opts={}) raise "Use the instance add_setting method if you want to set a default" if opts.key?(:default) define_reader name define_predicate name end # @macro [attach] add_setting # @!attribute [rw] $1 # # @macro [attach] define_reader # @!attribute [r] $1 # @macro add_setting # Path to use if no path is provided to the `rspec` command (default: # `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to # run all the examples in the `spec` directory. # # @note Other scripts invoking `rspec` indirectly will ignore this # setting. # @return [String] add_read_only_setting :default_path def default_path=(path) project_source_dirs << path @default_path = path end # @macro add_setting # Run examples over DRb (default: `false`). RSpec doesn't supply the DRb # server, but you can use tools like spork. # @return [Boolean] add_setting :drb # @macro add_setting # The drb_port (default: nil). add_setting :drb_port # @macro add_setting # Default: `$stderr`. add_setting :error_stream # Indicates if the DSL has been exposed off of modules and `main`. # Default: true # @return [Boolean] def expose_dsl_globally? Core::DSL.exposed_globally? end # Use this to expose the core RSpec DSL via `Module` and the `main` # object. It will be set automatically but you can override it to # remove the DSL. # Default: true def expose_dsl_globally=(value) if value Core::DSL.expose_globally! Core::SharedExampleGroup::TopLevelDSL.expose_globally! else Core::DSL.remove_globally! Core::SharedExampleGroup::TopLevelDSL.remove_globally! end end # Determines where deprecation warnings are printed. # Defaults to `$stderr`. # @return [IO, String] IO or filename to write to define_reader :deprecation_stream # Determines where deprecation warnings are printed. # @param value [IO, String] IO to write to or filename to write to def deprecation_stream=(value) if @reporter && !value.equal?(@deprecation_stream) warn "RSpec's reporter has already been initialized with " \ "#{deprecation_stream.inspect} as the deprecation stream, so your change to "\ "`deprecation_stream` will be ignored. You should configure it earlier for " \ "it to take effect, or use the `--deprecation-out` CLI option. " \ "(Called from #{CallerFilter.first_non_rspec_line})" else @deprecation_stream = value end end # @macro define_reader # The file path to use for persisting example statuses. Necessary for the # `--only-failures` and `--next-failure` CLI options. # # @overload example_status_persistence_file_path # @return [String] the file path # @overload example_status_persistence_file_path=(value) # @param value [String] the file path define_reader :example_status_persistence_file_path # Sets the file path to use for persisting example statuses. Necessary for the # `--only-failures` and `--next-failure` CLI options. def example_status_persistence_file_path=(value) @example_status_persistence_file_path = value clear_values_derived_from_example_status_persistence_file_path end # @macro define_reader # Indicates if the `--only-failures` (or `--next-failure`) flag is being used. define_reader :only_failures alias_method :only_failures?, :only_failures # @private def only_failures_but_not_configured? only_failures? && !example_status_persistence_file_path end # @macro define_reader # If specified, indicates the number of failures required before cleaning # up and exit (default: `nil`). Can also be `true` to fail and exit on first # failure define_reader :fail_fast # @see fail_fast def fail_fast=(value) case value when true, 'true' @fail_fast = true when false, 'false', 0 @fail_fast = false when nil @fail_fast = nil else @fail_fast = value.to_i if value.to_i == 0 # TODO: in RSpec 4, consider raising an error here. RSpec.warning "Cannot set `RSpec.configuration.fail_fast`" \ " to `#{value.inspect}`. Only `true`, `false`, `nil` and integers" \ " are valid values." @fail_fast = true end end end # @macro add_setting # Prints the formatter output of your suite without running any # examples or hooks. add_setting :dry_run # @macro add_setting # The exit code to return if there are any failures (default: 1). # @return [Integer] add_setting :failure_exit_code # @macro add_setting # The exit code to return if there are any errors outside examples (default: failure_exit_code) # @return [Integer] add_setting :error_exit_code # @macro add_setting # Whether or not to fail when there are no RSpec examples (default: false). # @return [Boolean] add_setting :fail_if_no_examples # @macro define_reader # Indicates files configured to be required. # @return [Array] define_reader :requires # @macro define_reader # Returns dirs that have been prepended to the load path by the `-I` # command line option. # @return [Array] define_reader :libs # @macro add_setting # Determines where RSpec will send its output. # Default: `$stdout`. # @return [IO, String] define_reader :output_stream # Set the output stream for reporter. # @attr value [IO, String] IO to write to or filename to write to, defaults to $stdout def output_stream=(value) if @reporter && !value.equal?(@output_stream) warn "RSpec's reporter has already been initialized with " \ "#{output_stream.inspect} as the output stream, so your change to "\ "`output_stream` will be ignored. You should configure it earlier for " \ "it to take effect. (Called from #{CallerFilter.first_non_rspec_line})" else @output_stream = value output_wrapper.output = @output_stream end end # @macro define_reader # Load files matching this pattern (default: `'**{,/*/**}/*_spec.rb'`). # @return [String] define_reader :pattern # Set pattern to match files to load. # @attr value [String] the filename pattern to filter spec files by def pattern=(value) update_pattern_attr :pattern, value end # @macro define_reader # Exclude files matching this pattern. # @return [String] define_reader :exclude_pattern # Set pattern to match files to exclude. # @attr value [String] the filename pattern to exclude spec files by def exclude_pattern=(value) update_pattern_attr :exclude_pattern, value end # @macro add_setting # Specifies which directories contain the source code for your project. # When a failure occurs, RSpec looks through the backtrace to find a # a line of source to print. It first looks for a line coming from # one of the project source directories so that, for example, it prints # the expectation or assertion call rather than the source code from # the expectation or assertion framework. # @return [Array] add_setting :project_source_dirs # @macro add_setting # Report the times for the slowest examples (default: `false`). # Use this to specify the number of examples to include in the profile. # @return [Boolean] attr_writer :profile_examples define_predicate :profile_examples # @macro add_setting # Run all examples if none match the configured filters # (default: `false`). # @deprecated Use {#filter_run_when_matching} instead for the specific # filters that you want to be ignored if none match. add_setting :run_all_when_everything_filtered # @macro add_setting # Color to use to indicate success. Defaults to `:green` but can be set # to one of the following: `[:black, :white, :red, :green, :yellow, # :blue, :magenta, :cyan]` # @return [Symbol] add_setting :success_color # @macro add_setting # Color to use to print pending examples. Defaults to `:yellow` but can # be set to one of the following: `[:black, :white, :red, :green, # :yellow, :blue, :magenta, :cyan]` # @return [Symbol] add_setting :pending_color # @macro add_setting # Color to use to indicate failure. Defaults to `:red` but can be set to # one of the following: `[:black, :white, :red, :green, :yellow, :blue, # :magenta, :cyan]` # @return [Symbol] add_setting :failure_color # @macro add_setting # The default output color. Defaults to `:white` but can be set to one of # the following: `[:black, :white, :red, :green, :yellow, :blue, # :magenta, :cyan]` # @return [Symbol] add_setting :default_color # @macro add_setting # Color used when a pending example is fixed. Defaults to `:blue` but can # be set to one of the following: `[:black, :white, :red, :green, # :yellow, :blue, :magenta, :cyan]` # @return [Symbol] add_setting :fixed_color # @macro add_setting # Color used to print details. Defaults to `:cyan` but can be set to one # of the following: `[:black, :white, :red, :green, :yellow, :blue, # :magenta, :cyan]` # @return [Symbol] add_setting :detail_color # @macro add_setting # Don't print filter info i.e. "Run options: include {:focus=>true}" # (default `false`). # return [Boolean] add_setting :silence_filter_announcements # @deprecated This config option was added in RSpec 2 to pave the way # for this being the default behavior in RSpec 3. Now this option is # a no-op. def treat_symbols_as_metadata_keys_with_true_values=(_value) RSpec.deprecate( "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=", :message => "RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= " \ "is deprecated, it is now set to true as default and " \ "setting it to false has no effect." ) end # @macro define_reader # Configures how RSpec treats metadata passed as part of a shared example # group definition. For example, given this shared example group definition: # # RSpec.shared_context "uses DB", :db => true do # around(:example) do |ex| # MyORM.transaction(:rollback => true, &ex) # end # end # # ...there are two ways RSpec can treat the `:db => true` metadata, each # of which has a corresponding config option: # # 1. `:trigger_inclusion`: this shared context will be implicitly included # in any groups (or examples) that have `:db => true` metadata. # 2. `:apply_to_host_groups`: the metadata will be inherited by the metadata # hash of all host groups and examples. # # `:trigger_inclusion` is the legacy behavior from before RSpec 3.5 but should # be considered deprecated. Instead, you can explicitly include a group with # `include_context`: # # RSpec.describe "My model" do # include_context "uses DB" # end # # ...or you can configure RSpec to include the context based on matching metadata # using an API that mirrors configured module inclusion: # # RSpec.configure do |rspec| # rspec.include_context "uses DB", :db => true # end # # `:apply_to_host_groups` is a new feature of RSpec 3.5 and will be the only # supported behavior in RSpec 4. # # @overload shared_context_metadata_behavior # @return [:trigger_inclusion, :apply_to_host_groups] the configured behavior # @overload shared_context_metadata_behavior=(value) # @param value [:trigger_inclusion, :apply_to_host_groups] sets the configured behavior define_reader :shared_context_metadata_behavior # @see shared_context_metadata_behavior def shared_context_metadata_behavior=(value) case value when :trigger_inclusion, :apply_to_host_groups @shared_context_metadata_behavior = value else raise ArgumentError, "Cannot set `RSpec.configuration." \ "shared_context_metadata_behavior` to `#{value.inspect}`. Only " \ "`:trigger_inclusion` and `:apply_to_host_groups` are valid values." end end # Record the start time of the spec suite to measure load time. # return [Time] add_setting :start_time # @macro add_setting # Use threadsafe options where available. # Currently this will place a mutex around memoized values such as let blocks. # return [Boolean] add_setting :threadsafe # @macro add_setting # Maximum count of failed source lines to display in the failure reports # (defaults to `10`). # return [Integer] add_setting :max_displayed_failure_line_count # @macro full_cause_backtrace # Display the full backtrace of an exceptions cause (defaults to `false`). # return [Boolean] add_setting :full_cause_backtrace # @macro add_setting # Format the output for pending examples. Can be set to: # - :full (default) - pending examples appear similarly to failures # - :no_backtrace - same as above, but with no backtrace # - :skip - do not show the section at all # return [Symbol] add_read_only_setting :pending_failure_output def pending_failure_output=(mode) raise ArgumentError, "`pending_failure_output` can be set to :full, :no_backtrace, " \ "or :skip" unless [:full, :no_backtrace, :skip].include?(mode) @pending_failure_output = mode end # Determines which bisect runner implementation gets used to run subsets # of the suite during a bisection. Your choices are: # # - `:shell`: Performs a spec run by shelling out, booting RSpec and your # application environment each time. This runner is the most widely # compatible runner, but is not as fast. On platforms that do not # support forking, this is the default. # - `:fork`: Pre-boots RSpec and your application environment in a parent # process, and then forks a child process for each spec run. This runner # tends to be significantly faster than the `:shell` runner but cannot # be used in some situations. On platforms that support forking, this # is the default. If you use this runner, you should ensure that all # of your one-time setup logic goes in a `before(:suite)` hook instead # of getting run at the top-level of a file loaded by `--require`. # # @note This option will only be used by `--bisect` if you set it in a file # loaded via `--require`. # # @return [Symbol] attr_reader :bisect_runner def bisect_runner=(value) if @bisect_runner_class && value != @bisect_runner raise "`config.bisect_runner = #{value.inspect}` can no longer take " \ "effect as the #{@bisect_runner.inspect} bisect runnner is already " \ "in use. This config setting must be set in a file loaded by a " \ "`--require` option (passed at the CLI or in a `.rspec` file) for " \ "it to have any effect." end @bisect_runner = value end # @private # @deprecated Use {#color_mode} = :on, instead of {#color} with {#tty} add_setting :tty # @private attr_writer :files_to_run # @private attr_accessor :filter_manager, :world # @private attr_accessor :static_config_filter_manager # @private attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/MethodLength # Build an object to store runtime configuration options and set defaults def initialize # rubocop:disable Style/GlobalVars @start_time = $_rspec_core_load_started_at || ::RSpec::Core::Time.now # rubocop:enable Style/GlobalVars @expectation_frameworks = [] @include_modules = FilterableItemRepository::QueryOptimized.new(:any?) @extend_modules = FilterableItemRepository::QueryOptimized.new(:any?) @prepend_modules = FilterableItemRepository::QueryOptimized.new(:any?) @bisect_runner = RSpec::Support::RubyFeatures.fork_supported? ? :fork : :shell @bisect_runner_class = nil @before_suite_hooks = [] @after_suite_hooks = [] @mock_framework = nil @files_or_directories_to_run = [] @loaded_spec_files = Set.new @color = false @color_mode = :automatic @pattern = '**{,/*/**}/*_spec.rb' @exclude_pattern = '' @failure_exit_code = 1 @error_exit_code = nil # so it can be overridden by failure exit code @fail_if_no_examples = false @spec_files_loaded = false @backtrace_formatter = BacktraceFormatter.new @default_path = 'spec' @project_source_dirs = %w[ spec lib app ] @deprecation_stream = $stderr @output_stream = $stdout @reporter = nil @reporter_buffer = nil @filter_manager = FilterManager.new @static_config_filter_manager = FilterManager.new @ordering_manager = Ordering::ConfigurationManager.new @preferred_options = {} @failure_color = :red @success_color = :green @pending_color = :yellow @default_color = :white @fixed_color = :blue @detail_color = :cyan @profile_examples = false @requires = [] @libs = [] @derived_metadata_blocks = FilterableItemRepository::QueryOptimized.new(:any?) @threadsafe = true @max_displayed_failure_line_count = 10 @full_cause_backtrace = false @world = World::Null @shared_context_metadata_behavior = :trigger_inclusion @pending_failure_output = :full define_built_in_hooks end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/MethodLength # @private # # Used to set higher priority option values from the command line. def force(hash) ordering_manager.force(hash) @preferred_options.merge!(hash) return unless hash.key?(:example_status_persistence_file_path) clear_values_derived_from_example_status_persistence_file_path end # @private def reset @spec_files_loaded = false reset_reporter end # @private def reset_reporter @reporter = nil @formatter_loader = nil @output_wrapper = nil end # @private def reset_filters self.filter_manager = FilterManager.new filter_manager.include_only( Metadata.deep_hash_dup(static_config_filter_manager.inclusions.rules) ) filter_manager.exclude_only( Metadata.deep_hash_dup(static_config_filter_manager.exclusions.rules) ) end # @overload add_setting(name) # @overload add_setting(name, opts) # @option opts [Symbol] :default # # Set a default value for the generated getter and predicate methods: # # add_setting(:foo, :default => "default value") # # @option opts [Symbol] :alias_with # # Use `:alias_with` to alias the setter, getter, and predicate to # another name, or names: # # add_setting(:foo, :alias_with => :bar) # add_setting(:foo, :alias_with => [:bar, :baz]) # # Adds a custom setting to the RSpec.configuration object. # # RSpec.configuration.add_setting :foo # # Used internally and by extension frameworks like rspec-rails, so they # can add config settings that are domain specific. For example: # # RSpec.configure do |c| # c.add_setting :use_transactional_fixtures, # :default => true, # :alias_with => :use_transactional_examples # end # # `add_setting` creates three methods on the configuration object, a # setter, a getter, and a predicate: # # RSpec.configuration.foo=(value) # RSpec.configuration.foo # RSpec.configuration.foo? # Returns true if foo returns anything but nil or false. def add_setting(name, opts={}) default = opts.delete(:default) (class << self; self; end).class_exec do add_setting(name, opts) end __send__("#{name}=", default) if default end # Returns the configured mock framework adapter module. # @return [Symbol] def mock_framework if @mock_framework.nil? begin mock_with :rspec rescue LoadError mock_with :nothing end end @mock_framework end # Delegates to mock_framework=(framework). def mock_framework=(framework) mock_with framework end # Regexps used to exclude lines from backtraces. # # Excludes lines from ruby (and jruby) source, installed gems, anything # in any "bin" directory, and any of the RSpec libs (outside gem # installs) by default. # # You can modify the list via the getter, or replace it with the setter. # # To override this behaviour and display a full backtrace, use # `--backtrace` on the command line, in a `.rspec` file, or in the # `rspec_options` attribute of RSpec's rake task. # @return [Array] def backtrace_exclusion_patterns @backtrace_formatter.exclusion_patterns end # Set regular expressions used to exclude lines in backtrace. # @param patterns [Array] set backtrace_formatter exclusion_patterns def backtrace_exclusion_patterns=(patterns) @backtrace_formatter.exclusion_patterns = patterns end # Regexps used to include lines in backtraces. # # Defaults to [Regexp.new Dir.getwd]. # # Lines that match an exclusion _and_ an inclusion pattern # will be included. # # You can modify the list via the getter, or replace it with the setter. # @return [Array] def backtrace_inclusion_patterns @backtrace_formatter.inclusion_patterns end # Set regular expressions used to include lines in backtrace. # @attr patterns [Array] set backtrace_formatter inclusion_patterns def backtrace_inclusion_patterns=(patterns) @backtrace_formatter.inclusion_patterns = patterns end # Adds {#backtrace_exclusion_patterns} that will filter lines from # the named gems from backtraces. # # @param gem_names [Array] Names of the gems to filter # # @example # RSpec.configure do |config| # config.filter_gems_from_backtrace "rack", "rake" # end # # @note The patterns this adds will match the named gems in their common # locations (e.g. system gems, vendored with bundler, installed as a # :git dependency with bundler, etc) but is not guaranteed to work for # all possible gem locations. For example, if you have the gem source # in a directory with a completely unrelated name, and use bundler's # :path option, this will not filter it. def filter_gems_from_backtrace(*gem_names) gem_names.each do |name| @backtrace_formatter.filter_gem(name) end end # @private MOCKING_ADAPTERS = { :rspec => :RSpec, :flexmock => :Flexmock, :rr => :RR, :mocha => :Mocha, :nothing => :Null } # Sets the mock framework adapter module. # # `framework` can be a Symbol or a Module. # # Given any of `:rspec`, `:mocha`, `:flexmock`, or `:rr`, configures the # named framework. # # Given `:nothing`, configures no framework. Use this if you don't use # any mocking framework to save a little bit of overhead. # # Given a Module, includes that module in every example group. The module # should adhere to RSpec's mock framework adapter API: # # setup_mocks_for_rspec # - called before each example # # verify_mocks_for_rspec # - called after each example if the example hasn't yet failed. # Framework should raise an exception when expectations fail # # teardown_mocks_for_rspec # - called after verify_mocks_for_rspec (even if there are errors) # # If the module responds to `configuration` and `mock_with` receives a # block, it will yield the configuration object to the block e.g. # # config.mock_with OtherMockFrameworkAdapter do |mod_config| # mod_config.custom_setting = true # end def mock_with(framework) framework_module = if framework.is_a?(Module) framework else const_name = MOCKING_ADAPTERS.fetch(framework) do raise ArgumentError, "Unknown mocking framework: #{framework.inspect}. " \ "Pass a module or one of #{MOCKING_ADAPTERS.keys.inspect}" end RSpec::Support.require_rspec_core "mocking_adapters/#{const_name.to_s.downcase}" RSpec::Core::MockingAdapters.const_get(const_name) end new_name, old_name = [framework_module, @mock_framework].map do |mod| mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed end unless new_name == old_name assert_no_example_groups_defined(:mock_framework) end if block_given? raise "#{framework_module} must respond to `configuration` so that " \ "mock_with can yield it." unless framework_module.respond_to?(:configuration) yield framework_module.configuration end @mock_framework = framework_module end # Returns the configured expectation framework adapter module(s) def expectation_frameworks if @expectation_frameworks.empty? begin expect_with :rspec rescue LoadError expect_with Module.new end end @expectation_frameworks end # Delegates to expect_with(framework). def expectation_framework=(framework) expect_with(framework) end # Sets the expectation framework module(s) to be included in each example # group. # # `frameworks` can be `:rspec`, `:test_unit`, `:minitest`, a custom # module, or any combination thereof: # # config.expect_with :rspec # config.expect_with :test_unit # config.expect_with :minitest # config.expect_with :rspec, :minitest # config.expect_with OtherExpectationFramework # # RSpec will translate `:rspec`, `:minitest`, and `:test_unit` into the # appropriate modules. # # ## Configuration # # If the module responds to `configuration`, `expect_with` will # yield the `configuration` object if given a block: # # config.expect_with OtherExpectationFramework do |custom_config| # custom_config.custom_setting = true # end def expect_with(*frameworks) modules = frameworks.map do |framework| case framework when Module framework when :rspec require 'rspec/expectations' # Tag this exception class so our exception formatting logic knows # that it satisfies the `MultipleExceptionError` interface. ::RSpec::Expectations::MultipleExpectationsNotMetError.__send__( :include, MultipleExceptionError::InterfaceTag ) ::RSpec::Matchers when :test_unit require 'rspec/core/test_unit_assertions_adapter' ::RSpec::Core::TestUnitAssertionsAdapter when :minitest require 'rspec/core/minitest_assertions_adapter' ::RSpec::Core::MinitestAssertionsAdapter else raise ArgumentError, "#{framework.inspect} is not supported" end end if (modules - @expectation_frameworks).any? assert_no_example_groups_defined(:expect_with) end if block_given? raise "expect_with only accepts a block with a single argument. " \ "Call expect_with #{modules.length} times, " \ "once with each argument, instead." if modules.length > 1 raise "#{modules.first} must respond to `configuration` so that " \ "expect_with can yield it." unless modules.first.respond_to?(:configuration) yield modules.first.configuration end @expectation_frameworks.push(*modules) end # Check if full backtrace is enabled. # @return [Boolean] is full backtrace enabled def full_backtrace? @backtrace_formatter.full_backtrace? end # Toggle full backtrace. # @attr true_or_false [Boolean] toggle full backtrace display def full_backtrace=(true_or_false) @backtrace_formatter.full_backtrace = true_or_false end # Enables color output if the output is a TTY. As of RSpec 3.6, this is # the default behavior and this option is retained only for backwards # compatibility. # # @deprecated No longer recommended because of complex behavior. Instead, # rely on the fact that TTYs will display color by default, or set # {#color_mode} to :on to display color on a non-TTY output. # @see color_mode # @see color_enabled? # @return [Boolean] def color value_for(:color) { @color } end # The mode for determining whether to display output in color. One of: # # - :automatic - the output will be in color if the output is a TTY (the # default) # - :on - the output will be in color, whether or not the output is a TTY # - :off - the output will not be in color # # @see color_enabled? # @return [Boolean] def color_mode value_for(:color_mode) { @color_mode } end # Check if color is enabled for a particular output. # @param output [IO] an output stream to use, defaults to the current # `output_stream` # @return [Boolean] def color_enabled?(output=output_stream) case color_mode when :on then true when :off then false else # automatic output_to_tty?(output) || (color && tty?) end end # Set the color mode. attr_writer :color_mode # Toggle output color. # # @deprecated No longer recommended because of complex behavior. Instead, # rely on the fact that TTYs will display color by default, or set # {:color_mode} to :on to display color on a non-TTY output. attr_writer :color # @private def libs=(libs) libs.map do |lib| @libs.unshift lib $LOAD_PATH.unshift lib end end # Run examples matching on `description` in all files to run. # @param description [String, Regexp] the pattern to filter on def full_description=(description) filter_run :full_description => Regexp.union(*Array(description).map { |d| Regexp.new(d) }) end # @return [Array] full description filter def full_description filter.fetch :full_description, nil end # @overload add_formatter(formatter) # @overload add_formatter(formatter, output) # # @param formatter [Class, String, Object] formatter to use. Can be any of the # string values supported from the CLI (`p`/`progress`, # `d`/`doc`/`documentation`, `h`/`html`, or `j`/`json`), any # class that implements the formatter protocol and has registered # itself with RSpec as a formatter, or a formatter instance. # @param output [String, IO] where the formatter will write its output. # Can be an IO object or a string path to a file. If not provided, # the configured `output_stream` (`$stdout`, by default) will be used. # # Adds a formatter to the set RSpec will use for this run. # # @see RSpec::Core::Formatters::Protocol def add_formatter(formatter, output=output_wrapper) formatter_loader.add(formatter, output) end alias_method :formatter=, :add_formatter # The formatter that will be used if no formatter has been set. # Defaults to 'progress'. def default_formatter formatter_loader.default_formatter end # Sets a fallback formatter to use if none other has been set. # # @example # # RSpec.configure do |rspec| # rspec.default_formatter = 'doc' # end def default_formatter=(value) formatter_loader.default_formatter = value end # Returns a duplicate of the formatters currently loaded in # the `FormatterLoader` for introspection. # # Note as this is a duplicate, any mutations will be disregarded. # # @return [Array] the formatters currently loaded def formatters formatter_loader.formatters.dup end # @private def formatter_loader @formatter_loader ||= Formatters::Loader.new(Reporter.new(self)) end # @private # # This buffer is used to capture all messages sent to the reporter during # reporter initialization. It can then replay those messages after the # formatter is correctly initialized. Otherwise, deprecation warnings # during formatter initialization can cause an infinite loop. class DeprecationReporterBuffer def initialize @calls = [] end def deprecation(*args) @calls << args end def play_onto(reporter) @calls.each do |args| reporter.deprecation(*args) end end end # @return [RSpec::Core::Reporter] the currently configured reporter def reporter # @reporter_buffer should only ever be set in this method to cover # initialization of @reporter. @reporter_buffer || @reporter ||= begin @reporter_buffer = DeprecationReporterBuffer.new formatter_loader.prepare_default output_wrapper, deprecation_stream @reporter_buffer.play_onto(formatter_loader.reporter) @reporter_buffer = nil formatter_loader.reporter end end # @api private # # Defaults `profile_examples` to 10 examples when `@profile_examples` is # `true`. def profile_examples profile = value_for(:profile_examples) { @profile_examples } if profile && !profile.is_a?(Integer) 10 else profile end end # @private def files_or_directories_to_run=(*files) files = files.flatten if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty? files << default_path end @files_or_directories_to_run = files @files_to_run = nil end # The spec files RSpec will run. # @return [Array] specified files about to run def files_to_run @files_to_run ||= get_files_to_run(@files_or_directories_to_run) end # @private def last_run_statuses @last_run_statuses ||= Hash.new(UNKNOWN_STATUS).tap do |statuses| if (path = example_status_persistence_file_path) begin ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example| status = example[:status] status = UNKNOWN_STATUS unless VALID_STATUSES.include?(status) hash[example.fetch(:example_id)] = status hash end rescue SystemCallError => e RSpec.warning "Could not read from #{path.inspect} (configured as " \ "`config.example_status_persistence_file_path`) due " \ "to a system error: #{e.inspect}. Please check that " \ "the config option is set to an accessible, valid " \ "file path", :call_site => nil end end end end # @private UNKNOWN_STATUS = "unknown".freeze # @private FAILED_STATUS = "failed".freeze # @private PASSED_STATUS = "passed".freeze # @private PENDING_STATUS = "pending".freeze # @private VALID_STATUSES = [UNKNOWN_STATUS, FAILED_STATUS, PASSED_STATUS, PENDING_STATUS] # @private def spec_files_with_failures @spec_files_with_failures ||= last_run_statuses.inject(Set.new) do |files, (id, status)| files << Example.parse_id(id).first if status == FAILED_STATUS files end.to_a end # Creates a method that delegates to `example` including the submitted # `args`. Used internally to add variants of `example` like `pending`: # @param name [String] example name alias # @param args [Array, Hash] metadata for the generated example # # @note The specific example alias below (`pending`) is already # defined for you. # @note Use with caution. This extends the language used in your # specs, but does not add any additional documentation. We use this # in RSpec to define methods like `focus` and `xit`, but we also add # docs for those methods. # # @example # RSpec.configure do |config| # config.alias_example_to :pending, :pending => true # end # # # This lets you do this: # # RSpec.describe Thing do # pending "does something" do # thing = Thing.new # end # end # # # ... which is the equivalent of # # RSpec.describe Thing do # it "does something", :pending => true do # thing = Thing.new # end # end def alias_example_to(name, *args) extra_options = Metadata.build_hash_from(args) RSpec::Core::ExampleGroup.define_example_method(name, extra_options) end # Creates a method that defines an example group with the provided # metadata. Can be used to define example group/metadata shortcuts. # # @example # RSpec.configure do |config| # config.alias_example_group_to :describe_model, :type => :model # end # # shared_context_for "model tests", :type => :model do # # define common model test helper methods, `let` declarations, etc # end # # # This lets you do this: # # RSpec.describe_model User do # end # # # ... which is the equivalent of # # RSpec.describe User, :type => :model do # end # # @note The defined aliased will also be added to the top level # (e.g. `main` and from within modules) if # `expose_dsl_globally` is set to true. # @see #alias_example_to # @see #expose_dsl_globally= def alias_example_group_to(new_name, *args) extra_options = Metadata.build_hash_from(args) RSpec::Core::ExampleGroup.define_example_group_method(new_name, extra_options) end # Define an alias for it_should_behave_like that allows different # language (like "it_has_behavior" or "it_behaves_like") to be # employed when including shared examples. # # @example # RSpec.configure do |config| # config.alias_it_behaves_like_to(:it_has_behavior, 'has behavior:') # end # # # allows the user to include a shared example group like: # # RSpec.describe Entity do # it_has_behavior 'sortability' do # let(:sortable) { Entity.new } # end # end # # # which is reported in the output as: # # Entity # # has behavior: sortability # # ...sortability examples here # # @note Use with caution. This extends the language used in your # specs, but does not add any additional documentation. We use this # in RSpec to define `it_should_behave_like` (for backward # compatibility), but we also add docs for that method. def alias_it_behaves_like_to(new_name, report_label='') RSpec::Core::ExampleGroup.define_nested_shared_group_method(new_name, report_label) end alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to # Adds key/value pairs to the `inclusion_filter`. If `args` # includes any symbols that are not part of the hash, each symbol # is treated as a key in the hash with the value `true`. # # ### Note # # Filters set using this method can be overridden from the command line # or config files (e.g. `.rspec`). # # @example # # Given this declaration. # describe "something", :foo => 'bar' do # # ... # end # # # Any of the following will include that group. # config.filter_run_including :foo => 'bar' # config.filter_run_including :foo => /^ba/ # config.filter_run_including :foo => lambda {|v| v == 'bar'} # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'} # # # Given a proc with an arity of 1, the lambda is passed the value # # related to the key, e.g. # config.filter_run_including :foo => lambda {|v| v == 'bar'} # # # Given a proc with an arity of 2, the lambda is passed the value # # related to the key, and the metadata itself e.g. # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'} # # filter_run_including :foo # same as filter_run_including :foo => true def filter_run_including(*args) meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) filter_manager.include_with_low_priority meta static_config_filter_manager.include_with_low_priority Metadata.deep_hash_dup(meta) end alias_method :filter_run, :filter_run_including # Applies the provided filter only if any of examples match, in constrast # to {#filter_run}, which always applies even if no examples match, in # which case no examples will be run. This allows you to leave configured # filters in place that are intended only for temporary use. The most common # example is focus filtering: `config.filter_run_when_matching :focus`. # With that configured, you can temporarily focus an example or group # by tagging it with `:focus` metadata, or prefixing it with an `f` # (as in `fdescribe`, `fcontext` and `fit`) since those are aliases for # `describe`/`context`/`it` with `:focus` metadata. def filter_run_when_matching(*args) when_first_matching_example_defined(*args) do filter_run(*args) end end # Clears and reassigns the `inclusion_filter`. Set to `nil` if you don't # want any inclusion filter at all. # # ### Warning # # This overrides any inclusion filters/tags set on the command line or in # configuration files. def inclusion_filter=(filter) meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering) filter_manager.include_only meta end alias_method :filter=, :inclusion_filter= # Returns the `inclusion_filter`. If none has been set, returns an empty # hash. def inclusion_filter filter_manager.inclusions end alias_method :filter, :inclusion_filter # Adds key/value pairs to the `exclusion_filter`. If `args` # includes any symbols that are not part of the hash, each symbol # is treated as a key in the hash with the value `true`. # # ### Note # # Filters set using this method can be overridden from the command line # or config files (e.g. `.rspec`). # # @example # # Given this declaration. # describe "something", :foo => 'bar' do # # ... # end # # # Any of the following will exclude that group. # config.filter_run_excluding :foo => 'bar' # config.filter_run_excluding :foo => /^ba/ # config.filter_run_excluding :foo => lambda {|v| v == 'bar'} # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'} # # # Given a proc with an arity of 1, the lambda is passed the value # # related to the key, e.g. # config.filter_run_excluding :foo => lambda {|v| v == 'bar'} # # # Given a proc with an arity of 2, the lambda is passed the value # # related to the key, and the metadata itself e.g. # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'} # # filter_run_excluding :foo # same as filter_run_excluding :foo => true def filter_run_excluding(*args) meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) filter_manager.exclude_with_low_priority meta static_config_filter_manager.exclude_with_low_priority Metadata.deep_hash_dup(meta) end # Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't # want any exclusion filter at all. # # ### Warning # # This overrides any exclusion filters/tags set on the command line or in # configuration files. def exclusion_filter=(filter) meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering) filter_manager.exclude_only meta end # Returns the `exclusion_filter`. If none has been set, returns an empty # hash. def exclusion_filter filter_manager.exclusions end # Tells RSpec to include `mod` in example groups. Methods defined in # `mod` are exposed to examples (not example groups). Use `filters` to # constrain the groups or examples in which to include the module. # # @example # # module AuthenticationHelpers # def login_as(user) # # ... # end # end # # module PreferencesHelpers # def preferences(user, preferences = {}) # # ... # end # end # # module UserHelpers # def users(username) # # ... # end # end # # RSpec.configure do |config| # config.include(UserHelpers) # included in all groups # # # included in examples with `:preferences` metadata # config.include(PreferenceHelpers, :preferences) # # # included in examples with `:type => :request` metadata # config.include(AuthenticationHelpers, :type => :request) # end # # describe "edit profile", :preferences, :type => :request do # it "can be viewed by owning user" do # login_as preferences(users(:jdoe), :lang => 'es') # get "/profiles/jdoe" # assert_select ".username", :text => 'jdoe' # end # end # # @note Filtered module inclusions can also be applied to # individual examples that have matching metadata. Just like # Ruby's object model is that every object has a singleton class # which has only a single instance, RSpec's model is that every # example has a singleton example group containing just the one # example. # # @see #include_context # @see #extend # @see #prepend def include(mod, *filters) define_mixed_in_module(mod, filters, @include_modules, :include) do |group| safe_include(mod, group) end end # Tells RSpec to include the named shared example group in example groups. # Use `filters` to constrain the groups or examples in which to include # the example group. # # @example # # RSpec.shared_context "example admin user" do # let(:admin_user) { create_user(:admin) } # end # # RSpec.shared_context "example guest user" do # let(:guest_user) { create_user(:guest) } # end # # RSpec.configure do |config| # config.include_context "example guest user", :type => :request # config.include_context "example admin user", :admin, :type => :request # end # # RSpec.describe "The admin page", :type => :request do # it "can be viewed by admins", :admin do # login_with admin_user # get "/admin" # expect(response).to be_ok # end # # it "cannot be viewed by guests" do # login_with guest_user # get "/admin" # expect(response).to be_forbidden # end # end # # @note Filtered context inclusions can also be applied to # individual examples that have matching metadata. Just like # Ruby's object model is that every object has a singleton class # which has only a single instance, RSpec's model is that every # example has a singleton example group containing just the one # example. # # @see #include def include_context(shared_group_name, *filters) shared_module = world.shared_example_group_registry.find([:main], shared_group_name) include shared_module, *filters end # Tells RSpec to extend example groups with `mod`. Methods defined in # `mod` are exposed to example groups (not examples). Use `filters` to # constrain the groups to extend. # # Similar to `include`, but behavior is added to example groups, which # are classes, rather than the examples, which are instances of those # classes. # # @example # # module UiHelpers # def run_in_browser # # ... # end # end # # module PermissionHelpers # def define_permissions # # ... # end # end # # RSpec.configure do |config| # config.extend(UiHelpers, :type => :request) # config.extend(PermissionHelpers, :with_permissions, :type => :request) # end # # describe "edit profile", :with_permissions, :type => :request do # run_in_browser # define_permissions # # it "does stuff in the client" do # # ... # end # end # # @see #include # @see #prepend def extend(mod, *filters) define_mixed_in_module(mod, filters, @extend_modules, :extend) do |group| safe_extend(mod, group) end end if RSpec::Support::RubyFeatures.module_prepends_supported? # Tells RSpec to prepend example groups with `mod`. Methods defined in # `mod` are exposed to examples (not example groups). Use `filters` to # constrain the groups in which to prepend the module. # # Similar to `include`, but module is included before the example group's class # in the ancestor chain. # # @example # # module OverrideMod # def override_me # "overridden" # end # end # # RSpec.configure do |config| # config.prepend(OverrideMod, :method => :prepend) # end # # describe "overriding example's class", :method => :prepend do # it "finds the user" do # self.class.class_eval do # def override_me # end # end # override_me # => "overridden" # # ... # end # end # # @see #include # @see #extend def prepend(mod, *filters) define_mixed_in_module(mod, filters, @prepend_modules, :prepend) do |group| safe_prepend(mod, group) end end end # @private # # Used internally to extend a group with modules using `include`, `prepend` and/or # `extend`. def configure_group(group) group.hooks.register_globals(group, hooks) configure_group_with group, @include_modules, :safe_include configure_group_with group, @extend_modules, :safe_extend configure_group_with group, @prepend_modules, :safe_prepend end # @private # # Used internally to extend the singleton class of a single example's # example group instance with modules using `include` and/or `extend`. def configure_example(example, example_hooks) example_hooks.register_global_singleton_context_hooks(example, hooks) singleton_group = example.example_group_instance.singleton_class # We replace the metadata so that SharedExampleGroupModule#included # has access to the example's metadata[:location]. singleton_group.with_replaced_metadata(example.metadata) do modules = @include_modules.items_for(example.metadata) modules.each do |mod| safe_include(mod, example.example_group_instance.singleton_class) end MemoizedHelpers.define_helpers_on(singleton_group) unless modules.empty? end end # @private def requires=(paths) directories = ['lib', default_path].select { |p| File.directory? p } RSpec::Core::RubyProject.add_to_load_path(*directories) paths.each { |path| load_file_handling_errors(:require, path) } @requires += paths end # @private def in_project_source_dir_regex regexes = project_source_dirs.map do |dir| /\A#{Regexp.escape(File.expand_path(dir))}\// end Regexp.union(regexes) end # @private def configure_mock_framework RSpec::Core::ExampleGroup.__send__(:include, mock_framework) conditionally_disable_mocks_monkey_patching end # @private def configure_expectation_framework expectation_frameworks.each do |framework| RSpec::Core::ExampleGroup.__send__(:include, framework) end conditionally_disable_expectations_monkey_patching end # @private def load_spec_files # Note which spec files world is already aware of. # This is generally only needed for when the user runs # `ruby path/to/spec.rb` (and loads `rspec/autorun`) -- # in that case, the spec file was loaded by `ruby` and # isn't loaded by us here so we only know about it because # of an example group being registered in it. world.registered_example_group_files.each do |f| loaded_spec_files << f # the registered files are already expended absolute paths end files_to_run.uniq.each do |f| file = File.expand_path(f) load_file_handling_errors(:load, file) loaded_spec_files << file end @spec_files_loaded = true end # @private DEFAULT_FORMATTER = lambda { |string| string } # Formats the docstring output using the block provided. # # @example # # This will strip the descriptions of both examples and example # # groups. # RSpec.configure do |config| # config.format_docstrings { |s| s.strip } # end def format_docstrings(&block) @format_docstrings_block = block_given? ? block : DEFAULT_FORMATTER end # @private def format_docstrings_block @format_docstrings_block ||= DEFAULT_FORMATTER end # @private def self.delegate_to_ordering_manager(*methods) methods.each do |method| define_method method do |*args, &block| ordering_manager.__send__(method, *args, &block) end end end # @!method seed=(value) # # Sets the seed value and sets the default global ordering to random. delegate_to_ordering_manager :seed= # @!method seed # Seed for random ordering (default: generated randomly each run). # # When you run specs with `--order random`, RSpec generates a random seed # for the randomization and prints it to the `output_stream` (assuming # you're using RSpec's built-in formatters). If you discover an ordering # dependency (i.e. examples fail intermittently depending on order), set # this (on Configuration or on the command line with `--seed`) to run # using the same seed while you debug the issue. # # We recommend, actually, that you use the command line approach so you # don't accidentally leave the seed encoded. delegate_to_ordering_manager :seed # @!method order=(value) # # Sets the default global ordering strategy. By default this can be one # of `:defined`, `:random`, but is customizable through the # `register_ordering` API. If order is set to `'rand:'`, # the seed will also be set. # # @see #register_ordering delegate_to_ordering_manager :order= # @!method register_ordering(name) # # Registers a named ordering strategy that can later be # used to order an example group's subgroups by adding # `:order => ` metadata to the example group. # # @param name [Symbol] The name of the ordering. # @yield Block that will order the given examples or example groups # @yieldparam list [Array, # Array] The examples or groups to order # @yieldreturn [Array, # Array] The re-ordered examples or groups # # @example # RSpec.configure do |rspec| # rspec.register_ordering :reverse do |list| # list.reverse # end # end # # RSpec.describe 'MyClass', :order => :reverse do # # ... # end # # @note Pass the symbol `:global` to set the ordering strategy that # will be used to order the top-level example groups and any example # groups that do not have declared `:order` metadata. # # @example # RSpec.configure do |rspec| # rspec.register_ordering :global do |examples| # acceptance, other = examples.partition do |example| # example.metadata[:type] == :acceptance # end # other + acceptance # end # end # # RSpec.describe 'MyClass', :type => :acceptance do # # will run last # end # # RSpec.describe 'MyClass' do # # will run first # end # delegate_to_ordering_manager :register_ordering # @private delegate_to_ordering_manager :seed_used?, :ordering_registry # Set Ruby warnings on or off. def warnings=(value) $VERBOSE = !!value end # @return [Boolean] Whether or not ruby warnings are enabled. def warnings? $VERBOSE end # @private RAISE_ERROR_WARNING_NOTIFIER = lambda { |message| raise message } # Turns warnings into errors. This can be useful when # you want RSpec to run in a 'strict' no warning situation. # # @example # # RSpec.configure do |rspec| # rspec.raise_on_warning = true # end def raise_on_warning=(value) if value RSpec::Support.warning_notifier = RAISE_ERROR_WARNING_NOTIFIER else RSpec::Support.warning_notifier = RSpec::Support::DEFAULT_WARNING_NOTIFIER end end # Exposes the current running example via the named # helper method. RSpec 2.x exposed this via `example`, # but in RSpec 3.0, the example is instead exposed via # an arg yielded to `it`, `before`, `let`, etc. However, # some extension gems (such as Capybara) depend on the # RSpec 2.x's `example` method, so this config option # can be used to maintain compatibility. # # @param method_name [Symbol] the name of the helper method # # @example # # RSpec.configure do |rspec| # rspec.expose_current_running_example_as :example # end # # RSpec.describe MyClass do # before do # # `example` can be used here because of the above config. # do_something if example.metadata[:type] == "foo" # end # end def expose_current_running_example_as(method_name) ExposeCurrentExample.module_exec do extend RSpec::SharedContext let(method_name) { |ex| ex } end include ExposeCurrentExample end # @private module ExposeCurrentExample; end # Turns deprecation warnings into errors, in order to surface # the full backtrace of the call site. This can be useful when # you need more context to address a deprecation than the # single-line call site normally provided. # # @example # # RSpec.configure do |rspec| # rspec.raise_errors_for_deprecations! # end def raise_errors_for_deprecations! self.deprecation_stream = Formatters::DeprecationFormatter::RaiseErrorStream.new end # Enables zero monkey patching mode for RSpec. It removes monkey # patching of the top-level DSL methods (`describe`, # `shared_examples_for`, etc) onto `main` and `Module`, instead # requiring you to prefix these methods with `RSpec.`. It enables # expect-only syntax for rspec-mocks and rspec-expectations. It # simply disables monkey patching on whatever pieces of RSpec # the user is using. # # @note It configures rspec-mocks and rspec-expectations only # if the user is using those (either explicitly or implicitly # by not setting `mock_with` or `expect_with` to anything else). # # @note If the user uses this options with `mock_with :mocha` # (or similar) they will still have monkey patching active # in their test environment from mocha. # # @example # # # It disables all monkey patching. # RSpec.configure do |config| # config.disable_monkey_patching! # end # # # Is an equivalent to # RSpec.configure do |config| # config.expose_dsl_globally = false # # config.mock_with :rspec do |mocks| # mocks.syntax = :expect # mocks.patch_marshal_to_support_partial_doubles = false # end # # config.expect_with :rspec do |expectations| # expectations.syntax = :expect # end # end def disable_monkey_patching! self.expose_dsl_globally = false self.disable_monkey_patching = true conditionally_disable_mocks_monkey_patching conditionally_disable_expectations_monkey_patching end # @private attr_accessor :disable_monkey_patching # Defines a callback that can assign derived metadata values. # # @param filters [Array, Hash] metadata filters that determine # which example or group metadata hashes the callback will be triggered # for. If none are given, the callback will be run against the metadata # hashes of all groups and examples. # @yieldparam metadata [Hash] original metadata hash from an example or # group. Mutate this in your block as needed. # # @example # RSpec.configure do |config| # # Tag all groups and examples in the spec/unit directory with # # :type => :unit # config.define_derived_metadata(:file_path => %r{/spec/unit/}) do |metadata| # metadata[:type] = :unit # end # end def define_derived_metadata(*filters, &block) meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) @derived_metadata_blocks.append(block, meta) end # Defines a callback that runs after the first example with matching # metadata is defined. If no examples are defined with matching metadata, # it will not get called at all. # # This can be used to ensure some setup is performed (such as bootstrapping # a DB or loading a specific file that adds significantly to the boot time) # if needed (as indicated by the presence of an example with matching metadata) # but avoided otherwise. # # @example # RSpec.configure do |config| # config.when_first_matching_example_defined(:db) do # # Load a support file that does some heavyweight setup, # # including bootstrapping the DB, but only if we have loaded # # any examples tagged with `:db`. # require 'support/db' # end # end def when_first_matching_example_defined(*filters) specified_meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) callback = lambda do |example_or_group_meta| # Example groups do not have `:example_group` metadata # (instead they have `:parent_example_group` metadata). return unless example_or_group_meta.key?(:example_group) # Ensure the callback only fires once. @derived_metadata_blocks.delete(callback, specified_meta) yield end @derived_metadata_blocks.append(callback, specified_meta) end # @private def apply_derived_metadata_to(metadata) already_run_blocks = Set.new # We loop and attempt to re-apply metadata blocks to support cascades # (e.g. where a derived bit of metadata triggers the application of # another piece of derived metadata, etc) # # We limit our looping to 200 times as a way to detect infinitely recursing derived metadata blocks. # It's hard to imagine a valid use case for a derived metadata cascade greater than 200 iterations. 200.times do return if @derived_metadata_blocks.items_for(metadata).all? do |block| already_run_blocks.include?(block).tap do |skip_block| block.call(metadata) unless skip_block already_run_blocks << block end end end # If we got here, then `@derived_metadata_blocks.items_for(metadata).all?` never returned # `true` above and we treat this as an attempt to recurse infinitely. It's better to fail # with a clear # error than hang indefinitely, which is what would happen if we didn't limit # the looping above. raise SystemStackError, "Attempted to recursively derive metadata indefinitely." end # Defines a `before` hook. See {Hooks#before} for full docs. # # This method differs from {Hooks#before} in only one way: it supports # the `:suite` scope. Hooks with the `:suite` scope will be run once before # the first example of the entire suite is executed. Conditions passed along # with `:suite` are effectively ignored. # # @see #prepend_before # @see #after # @see #append_after def before(scope=nil, *meta, &block) handle_suite_hook(scope, meta) do @before_suite_hooks << Hooks::BeforeHook.new(block, {}) end || begin # defeat Ruby 2.5 lazy proc allocation to ensure # the methods below are passed the same proc instances # so `Hook` equality is preserved. For more info, see: # https://bugs.ruby-lang.org/issues/14045#note-5 block.__id__ add_hook_to_existing_matching_groups(meta, scope) { |g| g.before(scope, *meta, &block) } super(scope, *meta, &block) end end alias_method :append_before, :before # Adds `block` to the start of the list of `before` blocks in the same # scope (`:example`, `:context`, or `:suite`), in contrast to {#before}, # which adds the hook to the end of the list. # # See {Hooks#before} for full `before` hook docs. # # This method differs from {Hooks#prepend_before} in only one way: it supports # the `:suite` scope. Hooks with the `:suite` scope will be run once before # the first example of the entire suite is executed. Conditions passed along # with `:suite` are effectively ignored. # # @see #before # @see #after # @see #append_after def prepend_before(scope=nil, *meta, &block) handle_suite_hook(scope, meta) do @before_suite_hooks.unshift Hooks::BeforeHook.new(block, {}) end || begin # defeat Ruby 2.5 lazy proc allocation to ensure # the methods below are passed the same proc instances # so `Hook` equality is preserved. For more info, see: # https://bugs.ruby-lang.org/issues/14045#note-5 block.__id__ add_hook_to_existing_matching_groups(meta, scope) { |g| g.prepend_before(scope, *meta, &block) } super(scope, *meta, &block) end end # Defines a `after` hook. See {Hooks#after} for full docs. # # This method differs from {Hooks#after} in only one way: it supports # the `:suite` scope. Hooks with the `:suite` scope will be run once after # the last example of the entire suite is executed. Conditions passed along # with `:suite` are effectively ignored. # # @see #append_after # @see #before # @see #prepend_before def after(scope=nil, *meta, &block) handle_suite_hook(scope, meta) do @after_suite_hooks.unshift Hooks::AfterHook.new(block, {}) end || begin # defeat Ruby 2.5 lazy proc allocation to ensure # the methods below are passed the same proc instances # so `Hook` equality is preserved. For more info, see: # https://bugs.ruby-lang.org/issues/14045#note-5 block.__id__ add_hook_to_existing_matching_groups(meta, scope) { |g| g.after(scope, *meta, &block) } super(scope, *meta, &block) end end alias_method :prepend_after, :after # Adds `block` to the end of the list of `after` blocks in the same # scope (`:example`, `:context`, or `:suite`), in contrast to {#after}, # which adds the hook to the start of the list. # # See {Hooks#after} for full `after` hook docs. # # This method differs from {Hooks#append_after} in only one way: it supports # the `:suite` scope. Hooks with the `:suite` scope will be run once after # the last example of the entire suite is executed. Conditions passed along # with `:suite` are effectively ignored. # # @see #append_after # @see #before # @see #prepend_before def append_after(scope=nil, *meta, &block) handle_suite_hook(scope, meta) do @after_suite_hooks << Hooks::AfterHook.new(block, {}) end || begin # defeat Ruby 2.5 lazy proc allocation to ensure # the methods below are passed the same proc instances # so `Hook` equality is preserved. For more info, see: # https://bugs.ruby-lang.org/issues/14045#note-5 block.__id__ add_hook_to_existing_matching_groups(meta, scope) { |g| g.append_after(scope, *meta, &block) } super(scope, *meta, &block) end end # Registers `block` as an `around` hook. # # See {Hooks#around} for full `around` hook docs. def around(scope=nil, *meta, &block) # defeat Ruby 2.5 lazy proc allocation to ensure # the methods below are passed the same proc instances # so `Hook` equality is preserved. For more info, see: # https://bugs.ruby-lang.org/issues/14045#note-5 block.__id__ add_hook_to_existing_matching_groups(meta, scope) { |g| g.around(scope, *meta, &block) } super(scope, *meta, &block) end # @private def with_suite_hooks return yield if dry_run? begin RSpec.current_scope = :before_suite_hook run_suite_hooks("a `before(:suite)` hook", @before_suite_hooks) yield ensure RSpec.current_scope = :after_suite_hook run_suite_hooks("an `after(:suite)` hook", @after_suite_hooks) RSpec.current_scope = :suite end end # @private # Holds the various registered hooks. Here we use a FilterableItemRepository # implementation that is specifically optimized for the read/write patterns # of the config object. def hooks @hooks ||= HookCollections.new(self, FilterableItemRepository::QueryOptimized) end # Invokes block before defining an example group def on_example_group_definition(&block) on_example_group_definition_callbacks << block end # @api private # Returns an array of blocks to call before defining an example group def on_example_group_definition_callbacks @on_example_group_definition_callbacks ||= [] end # @private def bisect_runner_class @bisect_runner_class ||= begin case bisect_runner when :fork RSpec::Support.require_rspec_core 'bisect/fork_runner' Bisect::ForkRunner when :shell RSpec::Support.require_rspec_core 'bisect/shell_runner' Bisect::ShellRunner else raise "Unsupported value for `bisect_runner` (#{bisect_runner.inspect}). " \ "Only `:fork` and `:shell` are supported." end end end private def load_file_handling_errors(method, file) __send__(method, file) rescue LoadError => ex relative_file = Metadata.relative_path(file) suggestions = DidYouMean.new(relative_file).call reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.#{suggestions}") RSpec.world.wants_to_quit = true rescue SyntaxError => ex relative_file = Metadata.relative_path(file) reporter.notify_non_example_exception( ex, "While loading #{relative_file} a `raise SyntaxError` occurred, RSpec will now quit." ) RSpec.world.rspec_is_quitting = true rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex relative_file = Metadata.relative_path(file) reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.") RSpec.world.wants_to_quit = true rescue SystemExit => ex relative_file = Metadata.relative_path(file) reporter.notify_non_example_exception( ex, "While loading #{relative_file} an `exit` / `raise SystemExit` occurred, RSpec will now quit." ) RSpec.world.rspec_is_quitting = true raise ex end def handle_suite_hook(scope, meta) return nil unless scope == :suite unless meta.empty? # TODO: in RSpec 4, consider raising an error here. # We warn only for backwards compatibility. RSpec.warn_with "WARNING: `:suite` hooks do not support metadata since " \ "they apply to the suite as a whole rather than " \ "any individual example or example group that has metadata. " \ "The metadata you have provided (#{meta.inspect}) will be ignored." end yield end def run_suite_hooks(hook_description, hooks) context = SuiteHookContext.new(hook_description, reporter) hooks.each do |hook| begin hook.run(context) rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex context.set_exception(ex) # Do not run subsequent `before` hooks if one fails. # But for `after` hooks, we run them all so that all # cleanup bits get a chance to complete, minimizing the # chance that resources get left behind. break if hooks.equal?(@before_suite_hooks) end end end def get_files_to_run(paths) files = FlatMap.flat_map(paths_to_check(paths)) do |path| path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR File.directory?(path) ? gather_directories(path) : extract_location(path) end.uniq return files unless only_failures? relative_files = files.map { |f| Metadata.relative_path(File.expand_path f) } intersection = (relative_files & spec_files_with_failures.to_a) intersection.empty? ? files : intersection end def paths_to_check(paths) return paths if pattern_might_load_specs_from_vendored_dirs? paths + [Dir.getwd] end def pattern_might_load_specs_from_vendored_dirs? pattern.split(File::SEPARATOR).first.include?('**') end def gather_directories(path) include_files = get_matching_files(path, pattern) exclude_files = get_matching_files(path, exclude_pattern) (include_files - exclude_files).uniq end def get_matching_files(path, pattern) raw_files = Dir[file_glob_from(path, pattern)] raw_files.map { |file| File.expand_path(file) }.sort end def file_glob_from(path, pattern) stripped = "{#{pattern.gsub(/\s*,\s*/, ',')}}" return stripped if pattern =~ /^(\.\/)?#{Regexp.escape path}/ || absolute_pattern?(pattern) File.join(path, stripped) end if RSpec::Support::OS.windows? # :nocov: def absolute_pattern?(pattern) pattern =~ /\A[A-Z]:\\/ || windows_absolute_network_path?(pattern) end def windows_absolute_network_path?(pattern) return false unless ::File::ALT_SEPARATOR pattern.start_with?(::File::ALT_SEPARATOR + ::File::ALT_SEPARATOR) end # :nocov: else def absolute_pattern?(pattern) pattern.start_with?(File::Separator) end end def extract_location(path) match = /^(.*?)((?:\:\d+)+)$/.match(path) if match captures = match.captures path = captures[0] lines = captures[1][1..-1].split(":").map(&:to_i) filter_manager.add_location path, lines else path, scoped_ids = Example.parse_id(path) filter_manager.add_ids(path, scoped_ids.split(/\s*,\s*/)) if scoped_ids end return [] if path == default_path File.expand_path(path) end def command $0.split(File::SEPARATOR).last end def value_for(key) @preferred_options.fetch(key) { yield } end def define_built_in_hooks around(:example, :aggregate_failures => true) do |procsy| begin aggregate_failures(nil, :hide_backtrace => true, &procsy) rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception procsy.example.set_aggregate_failures_exception(exception) end end end def assert_no_example_groups_defined(config_option) return unless world.example_groups.any? raise MustBeConfiguredBeforeExampleGroupsError.new( "RSpec's #{config_option} configuration option must be configured before " \ "any example groups are defined, but you have already defined a group." ) end def output_wrapper @output_wrapper ||= OutputWrapper.new(output_stream) end def output_to_tty?(output=output_stream) output.respond_to?(:tty?) && output.tty? end def conditionally_disable_mocks_monkey_patching return unless disable_monkey_patching && rspec_mocks_loaded? RSpec::Mocks.configuration.tap do |config| config.syntax = :expect config.patch_marshal_to_support_partial_doubles = false end end def conditionally_disable_expectations_monkey_patching return unless disable_monkey_patching && rspec_expectations_loaded? RSpec::Expectations.configuration.syntax = :expect end def rspec_mocks_loaded? defined?(RSpec::Mocks.configuration) end def rspec_expectations_loaded? defined?(RSpec::Expectations.configuration) end def update_pattern_attr(name, value) if @spec_files_loaded RSpec.warning "Configuring `#{name}` to #{value} has no effect since " \ "RSpec has already loaded the spec files." end instance_variable_set(:"@#{name}", value) @files_to_run = nil end def clear_values_derived_from_example_status_persistence_file_path @last_run_statuses = nil @spec_files_with_failures = nil end def configure_group_with(group, module_list, application_method) module_list.items_for(group.metadata).each do |mod| __send__(application_method, mod, group) end end def add_hook_to_existing_matching_groups(meta, scope, &block) # For example hooks, we have to apply it to each of the top level # groups, even if the groups do not match. When we apply it, we # apply it with the metadata, so it will only apply to examples # in the group that match the metadata. # #2280 for background and discussion. if scope == :example || scope == :each || scope.nil? world.example_groups.each(&block) else meta = Metadata.build_hash_from(meta.dup) on_existing_matching_groups(meta, &block) end end def on_existing_matching_groups(meta) world.traverse_example_group_trees_until do |group| metadata_applies_to_group?(meta, group).tap do |applies| yield group if applies end end end def metadata_applies_to_group?(meta, group) meta.empty? || MetadataFilter.apply?(:any?, meta, group.metadata) end if RSpec::Support::RubyFeatures.module_prepends_supported? def safe_prepend(mod, host) host.__send__(:prepend, mod) unless host < mod end end if RUBY_VERSION.to_f >= 1.9 def safe_include(mod, host) host.__send__(:include, mod) unless host < mod end def safe_extend(mod, host) host.extend(mod) unless host.singleton_class < mod end else # for 1.8.7 # :nocov: def safe_include(mod, host) host.__send__(:include, mod) unless host.included_modules.include?(mod) end def safe_extend(mod, host) host.extend(mod) unless (class << host; self; end).included_modules.include?(mod) end # :nocov: end def define_mixed_in_module(mod, filters, mod_list, config_method, &block) unless Module === mod raise TypeError, "`RSpec.configuration.#{config_method}` expects a module but got: #{mod.inspect}" end meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering) mod_list.append(mod, meta) on_existing_matching_groups(meta, &block) end end # rubocop:enable Metrics/ClassLength end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/0000775000000000000000000000000014557677674025005 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/rspec.rb0000664000000000000000000000107714557677674026453 0ustar rootrootrequire 'rspec/mocks' module RSpec module Core module MockingAdapters # @private module RSpec include ::RSpec::Mocks::ExampleMethods def self.framework_name :rspec end def self.configuration ::RSpec::Mocks.configuration end def setup_mocks_for_rspec ::RSpec::Mocks.setup end def verify_mocks_for_rspec ::RSpec::Mocks.verify end def teardown_mocks_for_rspec ::RSpec::Mocks.teardown end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/flexmock.rb0000664000000000000000000000106714557677674027146 0ustar rootroot# Created by Jim Weirich on 2007-04-10. # Copyright (c) 2007. All rights reserved. require 'flexmock/rspec' module RSpec module Core module MockingAdapters # @private module Flexmock include ::FlexMock::MockContainer def self.framework_name :flexmock end def setup_mocks_for_rspec # No setup required. end def verify_mocks_for_rspec flexmock_verify end def teardown_mocks_for_rspec flexmock_close end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/mocha.rb0000664000000000000000000000246414557677674026427 0ustar rootroot# In order to support all versions of mocha, we have to jump through some # hoops here. # # mocha >= '0.13.0': # require 'mocha/api' is required. # require 'mocha/object' raises a LoadError b/c the file no longer exists. # mocha < '0.13.0', >= '0.9.7' # require 'mocha/api' is required. # require 'mocha/object' is required. # mocha < '0.9.7': # require 'mocha/api' raises a LoadError b/c the file does not yet exist. # require 'mocha/standalone' is required. # require 'mocha/object' is required. begin require 'mocha/api' begin require 'mocha/object' rescue LoadError # Mocha >= 0.13.0 no longer contains this file nor needs it to be loaded. end rescue LoadError require 'mocha/standalone' require 'mocha/object' end module RSpec module Core module MockingAdapters # @private module Mocha def self.framework_name :mocha end # Mocha::Standalone was deprecated as of Mocha 0.9.7. begin include ::Mocha::API rescue NameError include ::Mocha::Standalone end def setup_mocks_for_rspec mocha_setup end def verify_mocks_for_rspec mocha_verify end def teardown_mocks_for_rspec mocha_teardown end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/null.rb0000664000000000000000000000036014557677674026303 0ustar rootrootmodule RSpec module Core module MockingAdapters # @private module Null def setup_mocks_for_rspec; end def verify_mocks_for_rspec; end def teardown_mocks_for_rspec; end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/mocking_adapters/rr.rb0000664000000000000000000000113714557677674025757 0ustar rootrootrequire 'rr' RSpec.configuration.backtrace_exclusion_patterns.push(RR::Errors::BACKTRACE_IDENTIFIER) module RSpec module Core # @private module MockingAdapters # @private module RR def self.framework_name :rr end include ::RR::Extensions::InstanceMethods def setup_mocks_for_rspec ::RR::Space.instance.reset end def verify_mocks_for_rspec ::RR::Space.instance.verify_doubles end def teardown_mocks_for_rspec ::RR::Space.instance.reset end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/reporter.rb0000664000000000000000000002060714557677674023667 0ustar rootrootmodule RSpec::Core # A reporter will send notifications to listeners, usually formatters for the # spec suite run. class Reporter # @private RSPEC_NOTIFICATIONS = Set.new( [ :close, :deprecation, :deprecation_summary, :dump_failures, :dump_pending, :dump_profile, :dump_summary, :example_failed, :example_group_finished, :example_group_started, :example_passed, :example_pending, :example_started, :message, :seed, :start, :start_dump, :stop, :example_finished ]) def initialize(configuration) @configuration = configuration @listeners = Hash.new { |h, k| h[k] = Set.new } @examples = [] @failed_examples = [] @pending_examples = [] @duration = @start = @load_time = nil @non_example_exception_count = 0 @setup_default = lambda {} @setup = false @profiler = nil end # @private attr_reader :examples, :failed_examples, :pending_examples # Registers a listener to a list of notifications. The reporter will send # notification of events to all registered listeners. # # @param listener [Object] An object that wishes to be notified of reporter # events # @param notifications [Array] Array of symbols represents the events a # listener wishes to subscribe too def register_listener(listener, *notifications) notifications.each do |notification| @listeners[notification.to_sym] << listener end true end # @private def prepare_default(loader, output_stream, deprecation_stream) @setup_default = lambda do loader.setup_default output_stream, deprecation_stream end end # @private def registered_listeners(notification) @listeners[notification].to_a end # @overload report(count, &block) # @overload report(count, &block) # @param expected_example_count [Integer] the number of examples being run # @yield [Block] block yields itself for further reporting. # # Initializes the report run and yields itself for further reporting. The # block is required, so that the reporter can manage cleaning up after the # run. # # @example # # reporter.report(group.examples.size) do |r| # example_groups.map {|g| g.run(r) } # end # def report(expected_example_count) start(expected_example_count) begin yield self ensure finish end end # @param exit_code [Integer] the exit_code to be return by the reporter # # Reports a run that exited early without having run any examples. # def exit_early(exit_code) report(0) { exit_code } end # @private def start(expected_example_count, time=RSpec::Core::Time.now) @start = time @load_time = (@start - @configuration.start_time).to_f notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?) notify :start, Notifications::StartNotification.new(expected_example_count, @load_time) end # @param message [#to_s] A message object to send to formatters # # Send a custom message to supporting formatters. def message(message) notify :message, Notifications::MessageNotification.new(message) end # @param event [Symbol] Name of the custom event to trigger on formatters # @param options [Hash] Hash of arguments to provide via `CustomNotification` # # Publish a custom event to supporting registered formatters. # @see RSpec::Core::Notifications::CustomNotification def publish(event, options={}) if RSPEC_NOTIFICATIONS.include? event raise "RSpec::Core::Reporter#publish is intended for sending custom " \ "events not internal RSpec ones, please rename your custom event." end notify event, Notifications::CustomNotification.for(options) end # @private def example_group_started(group) notify :example_group_started, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty? end # @private def example_group_finished(group) notify :example_group_finished, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty? end # @private def example_started(example) @examples << example notify :example_started, Notifications::ExampleNotification.for(example) end # @private def example_finished(example) notify :example_finished, Notifications::ExampleNotification.for(example) end # @private def example_passed(example) notify :example_passed, Notifications::ExampleNotification.for(example) end # @private def example_failed(example) @failed_examples << example notify :example_failed, Notifications::ExampleNotification.for(example) end # @private def example_pending(example) @pending_examples << example notify :example_pending, Notifications::ExampleNotification.for(example) end # @private def deprecation(hash) notify :deprecation, Notifications::DeprecationNotification.from_hash(hash) end # @private # Provides a way to notify of an exception that is not tied to any # particular example (such as an exception encountered in a :suite hook). # Exceptions will be formatted the same way they normally are. def notify_non_example_exception(exception, context_description) @configuration.world.non_example_failure = true @non_example_exception_count += 1 example = Example.new(AnonymousExampleGroup, context_description, {}) presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 0) message presenter.fully_formatted(nil) end # @private def finish close_after do stop notify :start_dump, Notifications::NullNotification notify :dump_pending, Notifications::ExamplesNotification.new(self) notify :dump_failures, Notifications::ExamplesNotification.new(self) notify :deprecation_summary, Notifications::NullNotification unless mute_profile_output? notify :dump_profile, Notifications::ProfileNotification.new(@duration, @examples, @configuration.profile_examples, @profiler.example_groups) end notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples, @pending_examples, @load_time, @non_example_exception_count) notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?) end end # @private def close_after yield ensure close end # @private def stop @duration = (RSpec::Core::Time.now - @start).to_f if @start notify :stop, Notifications::ExamplesNotification.new(self) end # @private def notify(event, notification) ensure_listeners_ready registered_listeners(event).each do |formatter| formatter.__send__(event, notification) end end # @private def abort_with(msg, exit_status) message(msg) close exit!(exit_status) end # @private def fail_fast_limit_met? return false unless (fail_fast = @configuration.fail_fast) if fail_fast == true @failed_examples.any? else fail_fast <= @failed_examples.size end end private def ensure_listeners_ready return if @setup @setup_default.call @profiler = Profiler.new register_listener @profiler, *Profiler::NOTIFICATIONS @setup = true end def close notify :close, Notifications::NullNotification end def mute_profile_output? # Don't print out profiled info if there are failures and `--fail-fast` is # used, it just clutters the output. !@configuration.profile_examples? || fail_fast_limit_met? end def seed_used? @configuration.seed && @configuration.seed_used? end end # @private # # Used in place of a {Reporter} for situations where we don't want reporting output. class NullReporter def self.method_missing(*) # ignore end private_class_method :method_missing end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/output_wrapper.rb0000664000000000000000000000115614557677674025123 0ustar rootrootmodule RSpec module Core # @private class OutputWrapper # @private attr_accessor :output # @private def initialize(output) @output = output end def respond_to?(name, priv=false) output.respond_to?(name, priv) end def method_missing(name, *args, &block) output.__send__(name, *args, &block) end # Redirect calls for IO interface methods IO.instance_methods(false).each do |method| define_method(method) do |*args, &block| output.__send__(method, *args, &block) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/notifications.rb0000664000000000000000000004607414557677674024704 0ustar rootrootRSpec::Support.require_rspec_core "formatters/console_codes" RSpec::Support.require_rspec_core "formatters/exception_presenter" RSpec::Support.require_rspec_core "formatters/helpers" RSpec::Support.require_rspec_core "shell_escape" module RSpec::Core # Notifications are value objects passed to formatters to provide them # with information about a particular event of interest. module Notifications # @private module NullColorizer module_function def wrap(line, _code_or_symbol) line end end # The `StartNotification` represents a notification sent by the reporter # when the suite is started. It contains the expected amount of examples # to be executed, and the load time of RSpec. # # @attr count [Fixnum] the number counted # @attr load_time [Float] the number of seconds taken to boot RSpec # and load the spec files StartNotification = Struct.new(:count, :load_time) # The `ExampleNotification` represents notifications sent by the reporter # which contain information about the current (or soon to be) example. # It is used by formatters to access information about that example. # # @example # def example_started(notification) # puts "Hey I started #{notification.example.description}" # end # # @attr example [RSpec::Core::Example] the current example ExampleNotification = Struct.new(:example) class ExampleNotification # @private def self.for(example) execution_result = example.execution_result return SkippedExampleNotification.new(example) if execution_result.example_skipped? return new(example) unless execution_result.status == :pending || execution_result.status == :failed klass = if execution_result.pending_fixed? PendingExampleFixedNotification elsif execution_result.status == :pending PendingExampleFailedAsExpectedNotification else FailedExampleNotification end klass.new(example) end private_class_method :new end # The `ExamplesNotification` represents notifications sent by the reporter # which contain information about the suites examples. # # @example # def stop(notification) # puts "Hey I ran #{notification.examples.size}" # end # class ExamplesNotification def initialize(reporter) @reporter = reporter end # @return [Array] list of examples def examples @reporter.examples end # @return [Array] list of failed examples def failed_examples @reporter.failed_examples end # @return [Array] list of pending examples def pending_examples @reporter.pending_examples end # @return [Array] # returns examples as notifications def notifications @notifications ||= format_examples(examples) end # @return [Array] # returns failed examples as notifications def failure_notifications @failed_notifications ||= format_examples(failed_examples) end # @return [Array] # returns pending examples as notifications def pending_notifications @pending_notifications ||= format_examples(pending_examples) end # @return [String] The list of failed examples, fully formatted in the way # that RSpec's built-in formatters emit. def fully_formatted_failed_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes) formatted = "\nFailures:\n" failure_notifications.each_with_index do |failure, index| formatted += failure.fully_formatted(index.next, colorizer) end formatted end # @return [String] The list of pending examples, fully formatted in the # way that RSpec's built-in formatters emit. def fully_formatted_pending_examples(colorizer=::RSpec::Core::Formatters::ConsoleCodes) return if RSpec.configuration.pending_failure_output == :skip formatted = "\nPending: (Failures listed here are expected and do not affect your suite's status)\n".dup pending_notifications.each_with_index do |notification, index| formatted << notification.fully_formatted(index.next, colorizer) end formatted end private def format_examples(examples) examples.map do |example| ExampleNotification.for(example) end end end # The `FailedExampleNotification` extends `ExampleNotification` with # things useful for examples that have failure info -- typically a # failed or pending spec. # # @example # def example_failed(notification) # puts "Hey I failed :(" # puts "Here's my stack trace" # puts notification.exception.backtrace.join("\n") # end # # @attr [RSpec::Core::Example] example the current example # @see ExampleNotification class FailedExampleNotification < ExampleNotification public_class_method :new # @return [Exception] The example failure def exception @exception_presenter.exception end # @return [String] The example description def description @exception_presenter.description end # Returns the message generated for this failure line by line. # # @return [Array] The example failure message def message_lines @exception_presenter.message_lines end # Returns the message generated for this failure colorized line by line. # # @param colorizer [#wrap] An object to colorize the message_lines by # @return [Array] The example failure message colorized def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes) @exception_presenter.colorized_message_lines(colorizer) end # Returns the failures formatted backtrace. # # @return [Array] the examples backtrace lines def formatted_backtrace @exception_presenter.formatted_backtrace end # Returns the failures colorized formatted backtrace. # # @param colorizer [#wrap] An object to colorize the message_lines by # @return [Array] the examples colorized backtrace lines def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes) @exception_presenter.colorized_formatted_backtrace(colorizer) end # @return [String] The failure information fully formatted in the way that # RSpec's built-in formatters emit. def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) @exception_presenter.fully_formatted(failure_number, colorizer) end # @return [Array] The failure information fully formatted in the way that # RSpec's built-in formatters emit, split by line. def fully_formatted_lines(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) @exception_presenter.fully_formatted_lines(failure_number, colorizer) end private def initialize(example, exception_presenter=Formatters::ExceptionPresenter::Factory.new(example).build) @exception_presenter = exception_presenter super(example) end end # @deprecated Use {FailedExampleNotification} instead. class PendingExampleFixedNotification < FailedExampleNotification; end # @deprecated Use {FailedExampleNotification} instead. class PendingExampleFailedAsExpectedNotification < FailedExampleNotification; end # The `SkippedExampleNotification` extends `ExampleNotification` with # things useful for specs that are skipped. # # @attr [RSpec::Core::Example] example the current example # @see ExampleNotification class SkippedExampleNotification < ExampleNotification public_class_method :new # @return [String] The pending detail fully formatted in the way that # RSpec's built-in formatters emit. def fully_formatted(pending_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) formatted_caller = RSpec.configuration.backtrace_formatter.backtrace_line(example.location) [ colorizer.wrap("\n #{pending_number}) #{example.full_description}", :pending), "\n ", Formatters::ExceptionPresenter::PENDING_DETAIL_FORMATTER.call(example, colorizer), "\n", colorizer.wrap(" # #{formatted_caller}\n", :detail) ].join("") end end # The `GroupNotification` represents notifications sent by the reporter # which contain information about the currently running (or soon to be) # example group. It is used by formatters to access information about that # group. # # @example # def example_group_started(notification) # puts "Hey I started #{notification.group.description}" # end # @attr group [RSpec::Core::ExampleGroup] the current group GroupNotification = Struct.new(:group) # The `MessageNotification` encapsulates generic messages that the reporter # sends to formatters. # # @attr message [String] the message MessageNotification = Struct.new(:message) # The `SeedNotification` holds the seed used to randomize examples and # whether that seed has been used or not. # # @attr seed [Fixnum] the seed used to randomize ordering # @attr used [Boolean] whether the seed has been used or not SeedNotification = Struct.new(:seed, :used) class SeedNotification # @api # @return [Boolean] has the seed been used? def seed_used? !!used end private :used # @return [String] The seed information fully formatted in the way that # RSpec's built-in formatters emit. def fully_formatted "\nRandomized with seed #{seed}\n" end end # The `SummaryNotification` holds information about the results of running # a test suite. It is used by formatters to provide information at the end # of the test run. # # @attr duration [Float] the time taken (in seconds) to run the suite # @attr examples [Array] the examples run # @attr failed_examples [Array] the failed examples # @attr pending_examples [Array] the pending examples # @attr load_time [Float] the number of seconds taken to boot RSpec # and load the spec files # @attr errors_outside_of_examples_count [Integer] the number of errors that # have occurred processing # the spec suite SummaryNotification = Struct.new(:duration, :examples, :failed_examples, :pending_examples, :load_time, :errors_outside_of_examples_count) class SummaryNotification # @api # @return [Fixnum] the number of examples run def example_count @example_count ||= examples.size end # @api # @return [Fixnum] the number of failed examples def failure_count @failure_count ||= failed_examples.size end # @api # @return [Fixnum] the number of pending examples def pending_count @pending_count ||= pending_examples.size end # @api # @return [String] A line summarising the result totals of the spec run. def totals_line summary = Formatters::Helpers.pluralize(example_count, "example") + ", " + Formatters::Helpers.pluralize(failure_count, "failure") summary += ", #{pending_count} pending" if pending_count > 0 if errors_outside_of_examples_count > 0 summary += ( ", " + Formatters::Helpers.pluralize(errors_outside_of_examples_count, "error") + " occurred outside of examples" ) end summary end # @api public # # Wraps the results line with colors based on the configured # colors for failure, pending, and success. Defaults to red, # yellow, green accordingly. # # @param colorizer [#wrap] An object which supports wrapping text with # specific colors. # @return [String] A colorized results line. def colorized_totals_line(colorizer=::RSpec::Core::Formatters::ConsoleCodes) if failure_count > 0 || errors_outside_of_examples_count > 0 colorizer.wrap(totals_line, RSpec.configuration.failure_color) elsif pending_count > 0 colorizer.wrap(totals_line, RSpec.configuration.pending_color) else colorizer.wrap(totals_line, RSpec.configuration.success_color) end end # @api public # # Formats failures into a rerunable command format. # # @param colorizer [#wrap] An object which supports wrapping text with # specific colors. # @return [String] A colorized summary line. def colorized_rerun_commands(colorizer=::RSpec::Core::Formatters::ConsoleCodes) "\nFailed examples:\n\n" + failed_examples.map do |example| colorizer.wrap("rspec #{rerun_argument_for(example)}", RSpec.configuration.failure_color) + " " + colorizer.wrap("# #{example.full_description}", RSpec.configuration.detail_color) end.join("\n") end # @return [String] a formatted version of the time it took to run the # suite def formatted_duration Formatters::Helpers.format_duration(duration) end # @return [String] a formatted version of the time it took to boot RSpec # and load the spec files def formatted_load_time Formatters::Helpers.format_duration(load_time) end # @return [String] The summary information fully formatted in the way that # RSpec's built-in formatters emit. def fully_formatted(colorizer=::RSpec::Core::Formatters::ConsoleCodes) formatted = "\nFinished in #{formatted_duration} " \ "(files took #{formatted_load_time} to load)\n" \ "#{colorized_totals_line(colorizer)}\n" unless failed_examples.empty? formatted += (colorized_rerun_commands(colorizer) + "\n") end formatted end private include RSpec::Core::ShellEscape def rerun_argument_for(example) location = example.location_rerun_argument return location unless duplicate_rerun_locations.include?(location) conditionally_quote(example.id) end def duplicate_rerun_locations @duplicate_rerun_locations ||= begin locations = RSpec.world.all_examples.map(&:location_rerun_argument) Set.new.tap do |s| locations.group_by { |l| l }.each do |l, ls| s << l if ls.count > 1 end end end end end # The `ProfileNotification` holds information about the results of running a # test suite when profiling is enabled. It is used by formatters to provide # information at the end of the test run for profiling information. # # @attr duration [Float] the time taken (in seconds) to run the suite # @attr examples [Array] the examples run # @attr number_of_examples [Fixnum] the number of examples to profile # @attr example_groups [Array] example groups run class ProfileNotification def initialize(duration, examples, number_of_examples, example_groups) @duration = duration @examples = examples @number_of_examples = number_of_examples @example_groups = example_groups end attr_reader :duration, :examples, :number_of_examples # @return [Array] the slowest examples def slowest_examples @slowest_examples ||= examples.sort_by do |example| -example.execution_result.run_time end.first(number_of_examples) end # @return [Float] the time taken (in seconds) to run the slowest examples def slow_duration @slow_duration ||= slowest_examples.inject(0.0) do |i, e| i + e.execution_result.run_time end end # @return [String] the percentage of total time taken def percentage @percentage ||= begin time_taken = slow_duration / duration '%.1f' % ((time_taken.nan? ? 0.0 : time_taken) * 100) end end # @return [Array] the slowest example groups def slowest_groups @slowest_groups ||= calculate_slowest_groups end private def calculate_slowest_groups # stop if we've only one example group return {} if @example_groups.keys.length <= 1 @example_groups.each_value do |hash| hash[:average] = hash[:total_time].to_f / hash[:count] end groups = @example_groups.sort_by { |_, hash| -hash[:average] }.first(number_of_examples) groups.map { |group, data| [group.location, data] } end end # The `DeprecationNotification` is issued by the reporter when a deprecated # part of RSpec is encountered. It represents information about the # deprecated call site. # # @attr message [String] A custom message about the deprecation # @attr deprecated [String] A custom message about the deprecation (alias of # message) # @attr replacement [String] An optional replacement for the deprecation # @attr call_site [String] An optional call site from which the deprecation # was issued DeprecationNotification = Struct.new(:deprecated, :message, :replacement, :call_site) class DeprecationNotification private_class_method :new # @api # Convenience way to initialize the notification def self.from_hash(data) new data[:deprecated], data[:message], data[:replacement], data[:call_site] end end # `NullNotification` represents a placeholder value for notifications that # currently require no information, but we may wish to extend in future. class NullNotification end # `CustomNotification` is used when sending custom events to formatters / # other registered listeners, it creates attributes based on supplied hash # of options. class CustomNotification < Struct # @param options [Hash] A hash of method / value pairs to create on this notification # @return [CustomNotification] # # Build a custom notification based on the supplied option key / values. def self.for(options={}) return NullNotification if options.keys.empty? new(*options.keys).new(*options.values) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/project_initializer/0000775000000000000000000000000014557677674025544 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/project_initializer/.rspec0000664000000000000000000000002614557677674026657 0ustar rootroot--require spec_helper ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/project_initializer/spec/0000775000000000000000000000000014557677674026476 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/project_initializer/spec/spec_helper.rb0000664000000000000000000001117514557677674031321 0ustar rootroot# This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause # this file to always be loaded, without a need to explicitly require it in any # files. # # Given that it is always loaded, you are encouraged to keep this file as # light-weight as possible. Requiring heavyweight dependencies from this file # will add to the boot time of your test suite on EVERY test run, even for an # individual file that may not need all of that loaded. Instead, consider making # a separate helper file that requires the additional dependencies and performs # the additional setup, and require it from the spec files that actually need # it. # # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest # assertions if you prefer. config.expect_with :rspec do |expectations| # This option will default to `true` in RSpec 4. It makes the `description` # and `failure_message` of custom matchers include text for helper methods # defined using `chain`, e.g.: # be_bigger_than(2).and_smaller_than(4).description # # => "be bigger than 2 and smaller than 4" # ...rather than: # # => "be bigger than 2" expectations.include_chain_clauses_in_custom_matcher_descriptions = true end # rspec-mocks config goes here. You can use an alternate test double # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| # Prevents you from mocking or stubbing a method that does not exist on # a real object. This is generally recommended, and will default to # `true` in RSpec 4. mocks.verify_partial_doubles = true end # This option will default to `:apply_to_host_groups` in RSpec 4 (and will # have no way to turn it off -- the option exists only for backwards # compatibility in RSpec 3). It causes shared context metadata to be # inherited by the metadata hash of host groups and examples, rather than # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin # This allows you to limit a spec run to individual examples or groups # you care about by tagging them with `:focus` metadata. When nothing # is tagged with `:focus`, all examples get run. RSpec also provides # aliases for `it`, `describe`, and `context` that include `:focus` # metadata: `fit`, `fdescribe` and `fcontext`, respectively. config.filter_run_when_matching :focus # Allows RSpec to persist some state between runs in order to support # the `--only-failures` and `--next-failure` CLI options. We recommend # you configure your source control system to ignore this file. config.example_status_persistence_file_path = "spec/examples.txt" # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: # https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/ config.disable_monkey_patching! # This setting enables warnings. It's recommended, but in some cases may # be too noisy due to issues in dependencies. config.warnings = true # Many RSpec users commonly either run the entire suite or an individual # file, and it's useful to allow more verbose output when running an # individual spec file. if config.files_to_run.one? # Use the documentation formatter for detailed output, # unless a formatter has already been configured # (e.g. via a command-line flag). config.default_formatter = "doc" end # Print the 10 slowest examples and example groups at the # end of the spec run, to help surface which specs are running # particularly slow. config.profile_examples = 10 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 config.order = :random # Seed global randomization in this process using the `--seed` CLI option. # Setting this allows you to use `--seed` to deterministically reproduce # test failures related to randomization by passing the same `--seed` value # as the one that triggered the failure. Kernel.srand config.seed =end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/profiler.rb0000664000000000000000000000175214557677674023647 0ustar rootrootmodule RSpec module Core # @private class Profiler NOTIFICATIONS = [:example_group_started, :example_group_finished, :example_started] def initialize @example_groups = Hash.new { |h, k| h[k] = { :count => 0 } } end attr_reader :example_groups def example_group_started(notification) return unless notification.group.top_level? @example_groups[notification.group][:start] = Time.now @example_groups[notification.group][:description] = notification.group.top_level_description end def example_group_finished(notification) return unless notification.group.top_level? group = @example_groups[notification.group] return unless group.key?(:start) group[:total_time] = Time.now - group[:start] end def example_started(notification) group = notification.example.example_group.parent_groups.last @example_groups[group][:count] += 1 end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/rake_task.rb0000664000000000000000000001407114557677674023767 0ustar rootrootrequire 'rake' require 'rake/tasklib' require 'rspec/support' RSpec::Support.require_rspec_support "ruby_features" # :nocov: unless RSpec::Support.respond_to?(:require_rspec_core) RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative "../#{f}" } end # :nocov: RSpec::Support.require_rspec_core "shell_escape" module RSpec module Core # RSpec rake task # # @see Rakefile class RakeTask < ::Rake::TaskLib include ::Rake::DSL if defined?(::Rake::DSL) include RSpec::Core::ShellEscape # Default path to the RSpec executable. DEFAULT_RSPEC_PATH = File.expand_path('../../../../exe/rspec', __FILE__) # Default pattern for spec files. DEFAULT_PATTERN = 'spec/**{,/*/**}/*_spec.rb' # Name of task. Defaults to `:spec`. attr_accessor :name # Files matching this pattern will be loaded. # Defaults to `'spec/**{,/*/**}/*_spec.rb'`. attr_accessor :pattern # Files matching this pattern will be excluded. # Defaults to `nil`. attr_accessor :exclude_pattern # Whether or not to fail Rake when an error occurs (typically when # examples fail). Defaults to `true`. attr_accessor :fail_on_error # A message to print to stderr when there are failures. attr_accessor :failure_message if RUBY_VERSION < "1.9.0" || Support::Ruby.jruby? # Run RSpec with a clean (empty) environment is not supported def with_clean_environment=(_value) raise ArgumentError, "Running in a clean environment is not supported on Ruby versions before 1.9.0" end # Run RSpec with a clean (empty) environment is not supported def with_clean_environment false end else # Run RSpec with a clean (empty) environment. attr_accessor :with_clean_environment end # Use verbose output. If this is set to true, the task will print the # executed spec command to stdout. Defaults to `true`. attr_accessor :verbose # Command line options to pass to ruby. Defaults to `nil`. attr_accessor :ruby_opts # Path to RSpec. Defaults to the absolute path to the # rspec binary from the loaded rspec-core gem. attr_accessor :rspec_path # Command line options to pass to RSpec. Defaults to `nil`. attr_accessor :rspec_opts def initialize(*args, &task_block) @name = args.shift || :spec @ruby_opts = nil @rspec_opts = nil @verbose = true @fail_on_error = true @rspec_path = DEFAULT_RSPEC_PATH @pattern = DEFAULT_PATTERN define(args, &task_block) end # @private def run_task(verbose) command = spec_command puts command if verbose if with_clean_environment return if system({}, command, :unsetenv_others => true) else return if system(command) end puts failure_message if failure_message return unless fail_on_error $stderr.puts "#{command} failed" if verbose exit $?.exitstatus || 1 end private # @private def define(args, &task_block) desc "Run RSpec code examples" unless ::Rake.application.last_description task name, *args do |_, task_args| RakeFileUtils.__send__(:verbose, verbose) do task_block.call(*[self, task_args].slice(0, task_block.arity)) if task_block run_task verbose end end end def file_inclusion_specification if ENV['SPEC'] FileList[ENV['SPEC']].sort elsif String === pattern && !File.exist?(pattern) return if [*rspec_opts].any? { |opt| opt =~ /--pattern/ } "--pattern #{escape pattern}" else # Before RSpec 3.1, we used `FileList` to get the list of matched # files, and then pass that along to the `rspec` command. Starting # with 3.1, we prefer to pass along the pattern as-is to the `rspec` # command, for 3 reasons: # # * It's *much* less verbose to pass one `--pattern` option than a # long list of files. # * It ensures `task.pattern` and `--pattern` have the same # behavior. # * It fixes a bug, where # `task.pattern = pattern_that_matches_no_files` would run *all* # files because it would cause no pattern or file args to get # passed to `rspec`, which causes all files to get run. # # However, `FileList` is *far* more flexible than the `--pattern` # option. Specifically, it supports individual files and directories, # as well as arrays of files, directories and globs, as well as other # `FileList` objects. # # For backwards compatibility, we have to fall back to using FileList # if the user has passed a `pattern` option that will not work with # `--pattern`. # # TODO: consider deprecating support for this and removing it in # RSpec 4. FileList[pattern].sort.map { |file| escape file } end end def file_exclusion_specification " --exclude-pattern #{escape exclude_pattern}" if exclude_pattern end def spec_command cmd_parts = [] cmd_parts << RUBY cmd_parts << ruby_opts cmd_parts << rspec_load_path cmd_parts << escape(rspec_path) cmd_parts << file_inclusion_specification cmd_parts << file_exclusion_specification cmd_parts << rspec_opts cmd_parts.flatten.reject(&blank).join(" ") end def blank lambda { |s| s.nil? || s == "" } end def rspec_load_path @rspec_load_path ||= begin core_and_support = $LOAD_PATH.grep( /#{File::SEPARATOR}rspec-(core|support)[^#{File::SEPARATOR}]*#{File::SEPARATOR}lib/ ).uniq "-I#{core_and_support.map { |file| escape file }.join(File::PATH_SEPARATOR)}" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/invocations.rb0000664000000000000000000000474014557677674024361 0ustar rootrootmodule RSpec module Core # @private module Invocations # @private class InitializeProject def call(*_args) RSpec::Support.require_rspec_core "project_initializer" ProjectInitializer.new.run 0 end end # @private class DRbWithFallback def call(options, err, out) require 'rspec/core/drb' begin return DRbRunner.new(options).run(err, out) rescue DRb::DRbConnError err.puts "No DRb server is running. Running in local process instead ..." end RSpec::Core::Runner.new(options).run(err, out) end end # @private class Bisect def call(options, err, out) RSpec::Support.require_rspec_core "bisect/coordinator" runner = Runner.new(options).tap { |r| r.configure(err, out) } formatter = bisect_formatter_klass_for(options.options[:bisect]).new( out, runner.configuration.bisect_runner ) success = RSpec::Core::Bisect::Coordinator.bisect_with( runner, options.args, formatter ) runner.exit_code(success) end private def bisect_formatter_klass_for(argument) return Formatters::BisectDebugFormatter if argument == "verbose" Formatters::BisectProgressFormatter end end # @private class PrintVersion def call(_options, _err, out) overall_version = RSpec::Core::Version::STRING unless overall_version =~ /[a-zA-Z]+/ overall_version = overall_version.split('.').first(2).join('.') end out.puts "RSpec #{overall_version}" [:Core, :Expectations, :Mocks, :Rails, :Support].each do |const_name| lib_name = const_name.to_s.downcase begin require "rspec/#{lib_name}/version" rescue LoadError # Not worth mentioning libs that are not installed nil else out.puts " - rspec-#{lib_name} #{RSpec.const_get(const_name)::Version::STRING}" end end 0 end end # @private PrintHelp = Struct.new(:parser, :hidden_options) do def call(_options, _err, out) # Removing the hidden options from the output. out.puts parser.to_s.gsub(/^\s+(#{hidden_options.join('|')})\b.*$\n/, '') 0 end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/0000775000000000000000000000000014557677674023661 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/exception_presenter.rb0000664000000000000000000005047014557677674030301 0ustar rootroot# encoding: utf-8 RSpec::Support.require_rspec_core "formatters/console_codes" RSpec::Support.require_rspec_core "formatters/snippet_extractor" RSpec::Support.require_rspec_core 'formatters/syntax_highlighter' RSpec::Support.require_rspec_support "encoded_string" module RSpec module Core module Formatters # @private class ExceptionPresenter attr_reader :exception, :example, :description, :message_color, :detail_formatter, :extra_detail_formatter, :backtrace_formatter private :message_color, :detail_formatter, :extra_detail_formatter, :backtrace_formatter def initialize(exception, example, options={}) @exception = exception @example = example @message_color = options.fetch(:message_color) { RSpec.configuration.failure_color } @description = options.fetch(:description) { example.full_description } @detail_formatter = options.fetch(:detail_formatter) { Proc.new {} } @extra_detail_formatter = options.fetch(:extra_detail_formatter) { Proc.new {} } @backtrace_formatter = options.fetch(:backtrace_formatter) { RSpec.configuration.backtrace_formatter } @indentation = options.fetch(:indentation, 2) @skip_shared_group_trace = options.fetch(:skip_shared_group_trace, false) @failure_lines = options[:failure_lines] end def message_lines add_shared_group_lines(failure_lines, Notifications::NullColorizer) end def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes) add_shared_group_lines(failure_lines, colorizer).map do |line| colorizer.wrap line, message_color end end def formatted_backtrace(exception=@exception) backtrace_formatter.format_backtrace(exception.backtrace, example.metadata) + formatted_cause(exception) end if RSpec::Support::RubyFeatures.supports_exception_cause? def formatted_cause(exception) last_cause = final_exception(exception, [exception]) cause = [] if exception.cause cause << '------------------' cause << '--- Caused by: ---' cause << "#{exception_class_name(last_cause)}:" unless exception_class_name(last_cause) =~ /RSpec/ encoded_string(exception_message_string(last_cause)).split("\n").each do |line| cause << " #{line}" end unless last_cause.backtrace.nil? || last_cause.backtrace.empty? lines = backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata) lines = [lines[0]] unless RSpec.configuration.full_cause_backtrace # rubocop:disable Metrics/BlockNesting lines.each do |line| cause << (" #{line}") end end end cause end else # :nocov: def formatted_cause(_) [] end # :nocov: end def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes) formatted_backtrace.map do |backtrace_info| colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color end end def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes) lines = fully_formatted_lines(failure_number, colorizer) lines.join("\n") << "\n" end def fully_formatted_lines(failure_number, colorizer) lines = [ encoded_description(description), detail_formatter.call(example, colorizer), formatted_message_and_backtrace(colorizer), extra_detail_formatter.call(failure_number, colorizer), ].compact.flatten lines = indent_lines(lines, failure_number) lines.unshift("") lines end private def final_exception(exception, previous=[]) cause = exception.cause if cause && Exception === cause && !previous.include?(cause) previous << cause final_exception(cause, previous) else exception end end if String.method_defined?(:encoding) def encoding_of(string) string.encoding end def encoded_string(string) RSpec::Support::EncodedString.new(string, Encoding.default_external) end else # for 1.8.7 # :nocov: def encoding_of(_string) end def encoded_string(string) RSpec::Support::EncodedString.new(string) end # :nocov: end def indent_lines(lines, failure_number) alignment_basis = ' ' * @indentation alignment_basis << "#{failure_number}) " if failure_number indentation = ' ' * alignment_basis.length lines.each_with_index.map do |line, index| if index == 0 "#{alignment_basis}#{line}" elsif line.empty? line else "#{indentation}#{line}" end end end def exception_class_name(exception=@exception) name = exception.class.name.to_s name = "(anonymous error class)" if name == '' name end def failure_lines @failure_lines ||= [].tap do |lines| lines.concat(failure_slash_error_lines) sections = [failure_slash_error_lines, exception_lines] if sections.any? { |section| section.size > 1 } && !exception_lines.first.empty? lines << '' end lines.concat(exception_lines) lines.concat(extra_failure_lines) end end def failure_slash_error_lines lines = read_failed_lines if lines.count == 1 lines[0] = "Failure/Error: #{lines[0].strip}" else least_indentation = SnippetExtractor.least_indentation_from(lines) lines = lines.map { |line| line.sub(/^#{least_indentation}/, ' ') } lines.unshift('Failure/Error:') end lines end # rubocop:disable Lint/RescueException if SyntaxError.instance_methods.include?(:detailed_message) def exception_message_string(exception) case exception when SyntaxError then exception.detailed_message.to_s else exception.message.to_s end rescue Exception => other "A #{exception.class} for which `exception.message.to_s` raises #{other.class}." end else def exception_message_string(exception) exception.message.to_s rescue Exception => other "A #{exception.class} for which `exception.message.to_s` raises #{other.class}." end end # rubocop:enable Lint/RescueException def exception_lines @exception_lines ||= begin lines = [] lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/ encoded_string(exception_message_string(exception)).split("\n").each do |line| lines << (line.empty? ? line : " #{line}") end lines end end def extra_failure_lines @extra_failure_lines ||= begin lines = Array(example.metadata[:extra_failure_lines]) unless lines.empty? lines.unshift('') unless lines.first == '' lines.push('') unless lines.last == '' end lines end end def add_shared_group_lines(lines, colorizer) return lines if @skip_shared_group_trace example.metadata[:shared_group_inclusion_backtrace].each do |frame| lines << colorizer.wrap(frame.description, RSpec.configuration.default_color) end lines end def read_failed_lines matching_line = find_failed_line unless matching_line return ["Unable to find matching line from backtrace"] end file_and_line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/) unless file_and_line_number return ["Unable to infer file and line number from backtrace"] end file_path, line_number = file_and_line_number[1..2] max_line_count = RSpec.configuration.max_displayed_failure_line_count lines = SnippetExtractor.extract_expression_lines_at(file_path, line_number.to_i, max_line_count) RSpec.world.syntax_highlighter.highlight(lines) rescue SnippetExtractor::NoSuchFileError ["Unable to find #{file_path} to read failed line"] rescue SnippetExtractor::NoSuchLineError ["Unable to find matching line in #{file_path}"] rescue SecurityError ["Unable to read failed line"] end def find_failed_line line_regex = RSpec.configuration.in_project_source_dir_regex loaded_spec_files = RSpec.configuration.loaded_spec_files exception_backtrace.reject! do |line| line.start_with?(" "#{@example.full_description} FIXED", :message_color => RSpec.configuration.fixed_color, :failure_lines => [ "Expected pending '#{@execution_result.pending_message}' to fail. No error was raised." ] } elsif @execution_result.status == :pending options = { :message_color => RSpec.configuration.pending_color, :detail_formatter => PENDING_DETAIL_FORMATTER } if RSpec.configuration.pending_failure_output == :no_backtrace options[:backtrace_formatter] = EmptyBacktraceFormatter end options end end def with_multiple_error_options_as_needed(exception, options) return options unless multiple_exceptions_error?(exception) options = options.merge( :failure_lines => [], :extra_detail_formatter => sub_failure_list_formatter(exception, options[:message_color]), :detail_formatter => multiple_exception_summarizer(exception, options[:detail_formatter], options[:message_color]) ) return options unless exception.aggregation_metadata[:hide_backtrace] options[:backtrace_formatter] = EmptyBacktraceFormatter options end def multiple_exceptions_error?(exception) MultipleExceptionError::InterfaceTag === exception end def multiple_exception_summarizer(exception, prior_detail_formatter, color) lambda do |example, colorizer| summary = if exception.aggregation_metadata[:hide_backtrace] # Since the backtrace is hidden, the subfailures will come # immediately after this, and using `:` will read well. "Got #{exception.exception_count_description}:" else # The backtrace comes after this, so using a `:` doesn't make sense # since the failures may be many lines below. "#{exception.summary}." end summary = colorizer.wrap(summary, color || RSpec.configuration.failure_color) return summary unless prior_detail_formatter [ prior_detail_formatter.call(example, colorizer), summary ] end end def sub_failure_list_formatter(exception, message_color) common_backtrace_truncater = CommonBacktraceTruncater.new(exception) lambda do |failure_number, colorizer| FlatMap.flat_map(exception.all_exceptions.each_with_index) do |failure, index| options = with_multiple_error_options_as_needed( failure, :description => nil, :indentation => 0, :message_color => message_color || RSpec.configuration.failure_color, :skip_shared_group_trace => true ) failure = common_backtrace_truncater.with_truncated_backtrace(failure) presenter = ExceptionPresenter.new(failure, @example, options) presenter.fully_formatted_lines( "#{failure_number ? "#{failure_number}." : ''}#{index + 1}", colorizer ) end end end # @private # Used to prevent a confusing backtrace from showing up from the `aggregate_failures` # block declared for `:aggregate_failures` metadata. module EmptyBacktraceFormatter def self.format_backtrace(*) [] end end # @private class CommonBacktraceTruncater def initialize(parent) @parent = parent end def with_truncated_backtrace(child) child_bt = child.backtrace parent_bt = @parent.backtrace return child if child_bt.nil? || child_bt.empty? || parent_bt.nil? index_before_first_common_frame = -1.downto(-child_bt.size).find do |index| parent_bt[index] != child_bt[index] end return child if index_before_first_common_frame.nil? return child if index_before_first_common_frame == -1 child = child.dup child.set_backtrace(child_bt[0..index_before_first_common_frame]) child end end end # @private PENDING_DETAIL_FORMATTER = Proc.new do |example, colorizer| colorizer.wrap("# #{example.execution_result.pending_message}", :detail) end end end # Provides a single exception instance that provides access to # multiple sub-exceptions. This is used in situations where a single # individual spec has multiple exceptions, such as one in the `it` block # and one in an `after` block. class MultipleExceptionError < StandardError # @private # Used so there is a common module in the ancestor chain of this class # and `RSpec::Expectations::MultipleExpectationsNotMetError`, which allows # code to detect exceptions that are instances of either, without first # checking to see if rspec-expectations is loaded. module InterfaceTag # Appends the provided exception to the list. # @param exception [Exception] Exception to append to the list. # @private def add(exception) # `PendingExampleFixedError` can be assigned to an example that initially has no # failures, but when the `aggregate_failures` around hook completes, it notifies of # a failure. If we do not ignore `PendingExampleFixedError` it would be surfaced to # the user as part of a multiple exception error, which is undesirable. While it's # pretty weird we handle this here, it's the best solution I've been able to come # up with, and `PendingExampleFixedError` always represents the _lack_ of any exception # so clearly when we are transitioning to a `MultipleExceptionError`, it makes sense to # ignore it. return if Pending::PendingExampleFixedError === exception return if exception == self all_exceptions << exception if exception.class.name =~ /RSpec/ failures << exception else other_errors << exception end end # Provides a way to force `ex` to be something that satisfies the multiple # exception error interface. If it already satisfies it, it will be returned; # otherwise it will wrap it in a `MultipleExceptionError`. # @private def self.for(ex) return ex if self === ex MultipleExceptionError.new(ex) end end include InterfaceTag # @return [Array] The list of failures. attr_reader :failures # @return [Array] The list of other errors. attr_reader :other_errors # @return [Array] The list of failures and other exceptions, combined. attr_reader :all_exceptions # @return [Hash] Metadata used by RSpec for formatting purposes. attr_reader :aggregation_metadata # @return [nil] Provided only for interface compatibility with # `RSpec::Expectations::MultipleExpectationsNotMetError`. attr_reader :aggregation_block_label # @param exceptions [Array] The initial list of exceptions. def initialize(*exceptions) super() @failures = [] @other_errors = [] @all_exceptions = [] @aggregation_metadata = { :hide_backtrace => true } @aggregation_block_label = nil exceptions.each { |e| add e } end # @return [String] Combines all the exception messages into a single string. # @note RSpec does not actually use this -- instead it formats each exception # individually. def message all_exceptions.map(&:message).join("\n\n") end # @return [String] A summary of the failure, including the block label and a count of failures. def summary "Got #{exception_count_description}" end # return [String] A description of the failure/error counts. def exception_count_description failure_count = Formatters::Helpers.pluralize(failures.size, "failure") return failure_count if other_errors.empty? error_count = Formatters::Helpers.pluralize(other_errors.size, "other error") "#{failure_count} and #{error_count}" end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/console_codes.rb0000664000000000000000000000471714557677674027036 0ustar rootrootmodule RSpec module Core module Formatters # ConsoleCodes provides helpers for formatting console output # with ANSI codes, e.g. color's and bold. module ConsoleCodes # @private VT100_CODES = { :black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :magenta => 35, :cyan => 36, :white => 37, :bold_black => '1;30', :bold_red => '1;31', :bold_green => '1;32', :bold_yellow => '1;33', :bold_blue => '1;34', :bold_magenta => '1;35', :bold_cyan => '1;36', :bold_white => '1;37', :bold => 1, } # @private VT100_CODE_VALUES = VT100_CODES.invert module_function # @private def config_colors_to_methods @config_colors_to_methods ||= Configuration.instance_methods.grep(/_color\z/).inject({}) do |hash, method| hash[method.to_s.sub(/_color\z/, '').to_sym] = method hash end end # Fetches the correct code for the supplied symbol, or checks # that a code is valid. Defaults to white (37). # # @param code_or_symbol [Symbol, Fixnum] Symbol or code to check # @return [Fixnum] a console code def console_code_for(code_or_symbol) if (config_method = config_colors_to_methods[code_or_symbol]) console_code_for RSpec.configuration.__send__(config_method) elsif VT100_CODE_VALUES.key?(code_or_symbol) code_or_symbol else VT100_CODES.fetch(code_or_symbol) do console_code_for(:white) end end end # Wraps a piece of text in ANSI codes with the supplied code. Will # only apply the control code if `RSpec.configuration.color_enabled?` # returns true. # # @param text [String] the text to wrap # @param code_or_symbol [Symbol, Fixnum] the desired control code # @return [String] the wrapped text def wrap(text, code_or_symbol) if RSpec.configuration.color_enabled? "\e[#{console_code_for(code_or_symbol)}m#{text}\e[0m" else text end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/html_snippet_extractor.rb0000664000000000000000000000772714557677674031024 0ustar rootrootmodule RSpec module Core module Formatters # @api private # # Extracts code snippets by looking at the backtrace of the passed error # and applies synax highlighting and line numbers using html. class HtmlSnippetExtractor # @private module NullConverter def self.convert(code) %Q(#{code}\n# Install the coderay gem to get syntax highlighting) end end # @private module CoderayConverter def self.convert(code) CodeRay.scan(code, :ruby).html(:line_numbers => false) end end # rubocop:disable Style/ClassVars # @private @@converter = NullConverter begin require 'coderay' RSpec::Support.require_rspec_core 'formatters/syntax_highlighter' RSpec::Core::Formatters::SyntaxHighlighter.attempt_to_add_rspec_terms_to_coderay_keywords @@converter = CoderayConverter # rubocop:disable Lint/HandleExceptions rescue LoadError # it'll fall back to the NullConverter assigned above # rubocop:enable Lint/HandleExceptions end # rubocop:enable Style/ClassVars # @api private # # Extract lines of code corresponding to a backtrace. # # @param backtrace [String] the backtrace from a test failure # @return [String] highlighted code snippet indicating where the test # failure occurred # # @see #post_process def snippet(backtrace) raw_code, line = snippet_for(backtrace[0]) highlighted = @@converter.convert(raw_code) post_process(highlighted, line) end # rubocop:enable Style/ClassVars # @api private # # Create a snippet from a line of code. # # @param error_line [String] file name with line number (i.e. # 'foo_spec.rb:12') # @return [String] lines around the target line within the file # # @see #lines_around def snippet_for(error_line) if error_line =~ /(.*):(\d+)/ file = Regexp.last_match[1] line = Regexp.last_match[2].to_i [lines_around(file, line), line] else ["# Couldn't get snippet for #{error_line}", 1] end end # @api private # # Extract lines of code centered around a particular line within a # source file. # # @param file [String] filename # @param line [Fixnum] line number # @return [String] lines around the target line within the file (2 above # and 1 below). def lines_around(file, line) if File.file?(file) lines = File.read(file).split("\n") min = [0, line - 3].max max = [line + 1, lines.length - 1].min selected_lines = [] selected_lines.join("\n") lines[min..max].join("\n") else "# Couldn't get snippet for #{file}" end rescue SecurityError "# Couldn't get snippet for #{file}" end # @api private # # Adds line numbers to all lines and highlights the line where the # failure occurred using html `span` tags. # # @param highlighted [String] syntax-highlighted snippet surrounding the # offending line of code # @param offending_line [Fixnum] line where failure occurred # @return [String] completed snippet def post_process(highlighted, offending_line) new_lines = [] highlighted.split("\n").each_with_index do |line, i| new_line = "#{offending_line + i - 2}#{line}" new_line = "#{new_line}" if i == 2 new_lines << new_line end new_lines.join("\n") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/html_formatter.rb0000664000000000000000000001215214557677674027236 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_text_formatter" RSpec::Support.require_rspec_core "formatters/html_printer" module RSpec module Core module Formatters # @private class HtmlFormatter < BaseFormatter Formatters.register self, :start, :example_group_started, :start_dump, :example_started, :example_passed, :example_failed, :example_pending, :dump_summary def initialize(output) super(output) @failed_examples = [] @example_group_number = 0 @example_number = 0 @header_red = nil @printer = HtmlPrinter.new(output) end def start(notification) super @printer.print_html_start @printer.flush end def example_group_started(notification) super @example_group_red = false @example_group_number += 1 @printer.print_example_group_end unless example_group_number == 1 @printer.print_example_group_start(example_group_number, notification.group.description, notification.group.parent_groups.size) @printer.flush end def start_dump(_notification) @printer.print_example_group_end @printer.flush end def example_started(_notification) @example_number += 1 end def example_passed(passed) @printer.move_progress(percent_done) @printer.print_example_passed(passed.example.description, passed.example.execution_result.run_time) @printer.flush end def example_failed(failure) @failed_examples << failure.example unless @header_red @header_red = true @printer.make_header_red end unless @example_group_red @example_group_red = true @printer.make_example_group_header_red(example_group_number) end @printer.move_progress(percent_done) example = failure.example exception = failure.exception message_lines = failure.fully_formatted_lines(nil, RSpec::Core::Notifications::NullColorizer) exception_details = if exception { # drop 2 removes the description (regardless of newlines) and leading blank line :message => message_lines.drop(2).join("\n"), :backtrace => failure.formatted_backtrace.join("\n"), } end extra = extra_failure_content(failure) @printer.print_example_failed( example.execution_result.pending_fixed, example.description, example.execution_result.run_time, @failed_examples.size, exception_details, (extra == "") ? false : extra ) @printer.flush end def example_pending(pending) example = pending.example @printer.make_header_yellow unless @header_red @printer.make_example_group_header_yellow(example_group_number) unless @example_group_red @printer.move_progress(percent_done) @printer.print_example_pending(example.description, example.execution_result.pending_message) @printer.flush end def dump_summary(summary) @printer.print_summary( summary.duration, summary.example_count, summary.failure_count, summary.pending_count ) @printer.flush end private # If these methods are declared with attr_reader Ruby will issue a # warning because they are private. # rubocop:disable Style/TrivialAccessors # The number of the currently running example_group. def example_group_number @example_group_number end # The number of the currently running example (a global counter). def example_number @example_number end # rubocop:enable Style/TrivialAccessors def percent_done result = 100.0 if @example_count > 0 result = (((example_number).to_f / @example_count.to_f * 1000).to_i / 10.0).to_f end result end # Override this method if you wish to output extra HTML for a failed # spec. For example, you could output links to images or other files # produced during the specs. def extra_failure_content(failure) RSpec::Support.require_rspec_core "formatters/html_snippet_extractor" backtrace = (failure.exception.backtrace || []).map do |line| RSpec.configuration.backtrace_formatter.backtrace_line(line) end backtrace.compact! @snippet_extractor ||= HtmlSnippetExtractor.new "
#{@snippet_extractor.snippet(backtrace)}
" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/progress_formatter.rb0000664000000000000000000000141214557677674030133 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_text_formatter" RSpec::Support.require_rspec_core "formatters/console_codes" module RSpec module Core module Formatters # @private class ProgressFormatter < BaseTextFormatter Formatters.register self, :example_passed, :example_pending, :example_failed, :start_dump def example_passed(_notification) output.print ConsoleCodes.wrap('.', :success) end def example_pending(_notification) output.print ConsoleCodes.wrap('*', :pending) end def example_failed(_notification) output.print ConsoleCodes.wrap('F', :failure) end def start_dump(_notification) output.puts end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/html_printer.rb0000664000000000000000000002667514557677674026735 0ustar rootrootrequire 'erb' module RSpec module Core module Formatters # @private class HtmlPrinter include ERB::Util # For the #h method. def initialize(output) @output = output end def print_html_start @output.puts HTML_HEADER @output.puts REPORT_HEADER end def print_example_group_end @output.puts " " @output.puts "" end def print_example_group_start(group_id, description, number_of_parents) @output.puts "
" @output.puts "
" @output.puts "
#{h(description)}
" end def print_example_passed(description, run_time) formatted_run_time = "%.5f" % run_time @output.puts "
" \ "#{h(description)}" \ "#{formatted_run_time}s
" end def print_example_failed(pending_fixed, description, run_time, failure_id, exception, extra_content) formatted_run_time = "%.5f" % run_time @output.puts "
" @output.puts " #{h(description)}" @output.puts " #{formatted_run_time}s" @output.puts "
" if exception @output.puts "
#{h(exception[:message])}
" @output.puts "
#{h exception[:backtrace]}
" end @output.puts extra_content if extra_content @output.puts "
" @output.puts "
" end def print_example_pending(description, pending_message) @output.puts "
" \ "#{h(description)} " \ "(PENDING: #{h(pending_message)})
" end def print_summary(duration, example_count, failure_count, pending_count) totals = String.new( "#{example_count} example#{'s' unless example_count == 1}, " ) totals << "#{failure_count} failure#{'s' unless failure_count == 1}" totals << ", #{pending_count} pending" if pending_count > 0 formatted_duration = "%.5f" % duration @output.puts "" @output.puts "" @output.puts "
" @output.puts "" @output.puts "" @output.puts "" end def flush @output.flush end def move_progress(percent_done) @output.puts " " @output.flush end def make_header_red @output.puts " " end def make_header_yellow @output.puts " " end def make_example_group_header_red(group_id) @output.puts " " @output.puts " " end def make_example_group_header_yellow(group_id) @output.puts " " @output.puts " " end private def indentation_style(number_of_parents) "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\"" end REPORT_HEADER = <<-EOF

RSpec Code Examples

 

 

EOF GLOBAL_SCRIPTS = <<-EOF function addClass(element_id, classname) { document.getElementById(element_id).className += (" " + classname); } function removeClass(element_id, classname) { var elem = document.getElementById(element_id); var classlist = elem.className.replace(classname,''); elem.className = classlist; } function moveProgressBar(percentDone) { document.getElementById("rspec-header").style.width = percentDone +"%"; } function makeRed(element_id) { removeClass(element_id, 'passed'); removeClass(element_id, 'not_implemented'); addClass(element_id,'failed'); } function makeYellow(element_id) { var elem = document.getElementById(element_id); if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented removeClass(element_id, 'passed'); addClass(element_id,'not_implemented'); } } } function apply_filters() { var passed_filter = document.getElementById('passed_checkbox').checked; var failed_filter = document.getElementById('failed_checkbox').checked; var pending_filter = document.getElementById('pending_checkbox').checked; assign_display_style("example passed", passed_filter); assign_display_style("example failed", failed_filter); assign_display_style("example not_implemented", pending_filter); assign_display_style_for_group("example_group passed", passed_filter); assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter); assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter); } function get_display_style(display_flag) { var style_mode = 'none'; if (display_flag == true) { style_mode = 'block'; } return style_mode; } function assign_display_style(classname, display_flag) { var style_mode = get_display_style(display_flag); var elems = document.getElementsByClassName(classname) for (var i=0; i RSpec results EOF end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/base_bisect_formatter.rb0000664000000000000000000000271014557677674030534 0ustar rootrootRSpec::Support.require_rspec_core "bisect/utilities" module RSpec module Core module Formatters # Contains common logic for formatters used by `--bisect` to communicate results # back to the bisect runner. # # Subclasses must define a `notify_results(all_example_ids, failed_example_ids)` # method. # @private class BaseBisectFormatter def self.inherited(formatter) Formatters.register formatter, :start_dump, :example_failed, :example_finished end def initialize(expected_failures) @all_example_ids = [] @failed_example_ids = [] @remaining_failures = expected_failures end def example_failed(notification) @failed_example_ids << notification.example.id end def example_finished(notification) @all_example_ids << notification.example.id return unless @remaining_failures.include?(notification.example.id) @remaining_failures.delete(notification.example.id) status = notification.example.execution_result.status return if status == :failed && !@remaining_failures.empty? RSpec.world.wants_to_quit = true end def start_dump(_notification) # `notify_results` is defined in the subclass notify_results(Bisect::ExampleSetDescriptor.new( @all_example_ids, @failed_example_ids)) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/documentation_formatter.rb0000664000000000000000000000543214557677674031146 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_text_formatter" RSpec::Support.require_rspec_core "formatters/console_codes" module RSpec module Core module Formatters # @private class DocumentationFormatter < BaseTextFormatter Formatters.register self, :example_started, :example_group_started, :example_group_finished, :example_passed, :example_pending, :example_failed def initialize(output) super @group_level = 0 @example_running = false @messages = [] end def example_started(_notification) @example_running = true end def example_group_started(notification) output.puts if @group_level == 0 output.puts "#{current_indentation}#{notification.group.description.strip}" @group_level += 1 end def example_group_finished(_notification) @group_level -= 1 if @group_level > 0 end def example_passed(passed) output.puts passed_output(passed.example) flush_messages @example_running = false end def example_pending(pending) output.puts pending_output(pending.example, pending.example.execution_result.pending_message) flush_messages @example_running = false end def example_failed(failure) output.puts failure_output(failure.example) flush_messages @example_running = false end def message(notification) if @example_running @messages << notification.message else output.puts "#{current_indentation}#{notification.message}" end end private def flush_messages @messages.each do |message| output.puts "#{current_indentation(1)}#{message}" end @messages.clear end def passed_output(example) ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}", :success) end def pending_output(example, message) ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \ "(PENDING: #{message})", :pending) end def failure_output(example) ConsoleCodes.wrap("#{current_indentation}#{example.description.strip} " \ "(FAILED - #{next_failure_index})", :failure) end def next_failure_index @next_failure_index ||= 0 @next_failure_index += 1 end def current_indentation(offset=0) ' ' * (@group_level + offset) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/deprecation_formatter.rb0000664000000000000000000001714714557677674030600 0ustar rootrootRSpec::Support.require_rspec_core "formatters/helpers" module RSpec module Core module Formatters # @private class DeprecationFormatter Formatters.register self, :deprecation, :deprecation_summary attr_reader :count, :deprecation_stream, :summary_stream def initialize(deprecation_stream, summary_stream) @deprecation_stream = deprecation_stream @summary_stream = summary_stream @seen_deprecations = Set.new @count = 0 end alias :output :deprecation_stream def printer @printer ||= case deprecation_stream when File ImmediatePrinter.new(FileStream.new(deprecation_stream), summary_stream, self) when RaiseErrorStream ImmediatePrinter.new(deprecation_stream, summary_stream, self) else DelayedPrinter.new(deprecation_stream, summary_stream, self) end end def deprecation(notification) return if @seen_deprecations.include? notification @count += 1 printer.print_deprecation_message notification @seen_deprecations << notification end def deprecation_summary(_notification) printer.deprecation_summary end def deprecation_message_for(data) if data.message SpecifiedDeprecationMessage.new(data) else GeneratedDeprecationMessage.new(data) end end RAISE_ERROR_CONFIG_NOTICE = <<-EOS.gsub(/^\s+\|/, '') | |If you need more of the backtrace for any of these deprecations to |identify where to make the necessary changes, you can configure |`config.raise_errors_for_deprecations!`, and it will turn the |deprecation warnings into errors, giving you the full backtrace. EOS DEPRECATION_STREAM_NOTICE = "Pass `--deprecation-out` or set " \ "`config.deprecation_stream` to a file for full output." TOO_MANY_WARNINGS_NOTICE = "Too many similar deprecation messages " \ "reported, disregarding further reports. #{DEPRECATION_STREAM_NOTICE}" # @private SpecifiedDeprecationMessage = Struct.new(:type) do def initialize(data) @message = data.message super deprecation_type_for(data) end def to_s output_formatted @message end def too_many_warnings_message TOO_MANY_WARNINGS_NOTICE end private def output_formatted(str) return str unless str.lines.count > 1 separator = '-' * 80 "#{separator}\n#{str.chomp}\n#{separator}" end def deprecation_type_for(data) data.message.gsub(/(\w+\/)+\w+\.rb:\d+/, '') end end # @private GeneratedDeprecationMessage = Struct.new(:type) do def initialize(data) @data = data super data.deprecated end def to_s msg = String.new("#{@data.deprecated} is deprecated.") msg << " Use #{@data.replacement} instead." if @data.replacement msg << " Called from #{@data.call_site}." if @data.call_site msg end def too_many_warnings_message "Too many uses of deprecated '#{type}'. #{DEPRECATION_STREAM_NOTICE}" end end # @private class ImmediatePrinter attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter def initialize(deprecation_stream, summary_stream, deprecation_formatter) @deprecation_stream = deprecation_stream @summary_stream = summary_stream @deprecation_formatter = deprecation_formatter end def print_deprecation_message(data) deprecation_message = deprecation_formatter.deprecation_message_for(data) deprecation_stream.puts deprecation_message.to_s end def deprecation_summary return if deprecation_formatter.count.zero? deprecation_stream.summarize(summary_stream, deprecation_formatter.count) end end # @private class DelayedPrinter TOO_MANY_USES_LIMIT = 4 attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter def initialize(deprecation_stream, summary_stream, deprecation_formatter) @deprecation_stream = deprecation_stream @summary_stream = summary_stream @deprecation_formatter = deprecation_formatter @seen_deprecations = Hash.new { 0 } @deprecation_messages = Hash.new { |h, k| h[k] = [] } end def print_deprecation_message(data) deprecation_message = deprecation_formatter.deprecation_message_for(data) @seen_deprecations[deprecation_message] += 1 stash_deprecation_message(deprecation_message) end def stash_deprecation_message(deprecation_message) if @seen_deprecations[deprecation_message] < TOO_MANY_USES_LIMIT @deprecation_messages[deprecation_message] << deprecation_message.to_s elsif @seen_deprecations[deprecation_message] == TOO_MANY_USES_LIMIT @deprecation_messages[deprecation_message] << deprecation_message.too_many_warnings_message end end def deprecation_summary return unless @deprecation_messages.any? print_deferred_deprecation_warnings deprecation_stream.puts RAISE_ERROR_CONFIG_NOTICE summary_stream.puts "\n#{Helpers.pluralize(deprecation_formatter.count, 'deprecation warning')} total" end def print_deferred_deprecation_warnings deprecation_stream.puts "\nDeprecation Warnings:\n\n" @deprecation_messages.keys.sort_by(&:type).each do |deprecation| messages = @deprecation_messages[deprecation] messages.each { |msg| deprecation_stream.puts msg } deprecation_stream.puts end end end # @private # Not really a stream, but is usable in place of one. class RaiseErrorStream def puts(message) raise DeprecationError, message end def summarize(summary_stream, deprecation_count) summary_stream.puts "\n#{Helpers.pluralize(deprecation_count, 'deprecation')} found." end end # @private # Wraps a File object and provides file-specific operations. class FileStream def initialize(file) @file = file # In one of my test suites, I got lots of duplicate output in the # deprecation file (e.g. 200 of the same deprecation, even though # the `puts` below was only called 6 times). Setting `sync = true` # fixes this (but we really have no idea why!). @file.sync = true end def puts(*args) @file.puts(*args) end def summarize(summary_stream, deprecation_count) path = @file.respond_to?(:path) ? @file.path : @file.inspect summary_stream.puts "\n#{Helpers.pluralize(deprecation_count, 'deprecation')} logged to #{path}" puts RAISE_ERROR_CONFIG_NOTICE end end end end # Deprecation Error. DeprecationError = Class.new(StandardError) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/snippet_extractor.rb0000664000000000000000000001105614557677674027766 0ustar rootrootmodule RSpec module Core module Formatters # @private class SnippetExtractor NoSuchFileError = Class.new(StandardError) NoSuchLineError = Class.new(StandardError) def self.extract_line_at(file_path, line_number) source = source_from_file(file_path) line = source.lines[line_number - 1] raise NoSuchLineError unless line line end def self.source_from_file(path) raise NoSuchFileError unless File.exist?(path) RSpec.world.source_from_file(path) end if RSpec::Support::RubyFeatures.ripper_supported? NoExpressionAtLineError = Class.new(StandardError) attr_reader :source, :beginning_line_number, :max_line_count def self.extract_expression_lines_at(file_path, beginning_line_number, max_line_count=nil) if max_line_count == 1 [extract_line_at(file_path, beginning_line_number)] else source = source_from_file(file_path) new(source, beginning_line_number, max_line_count).expression_lines end end def initialize(source, beginning_line_number, max_line_count=nil) @source = source @beginning_line_number = beginning_line_number @max_line_count = max_line_count end def expression_lines line_range = line_range_of_expression if max_line_count && line_range.count > max_line_count line_range = (line_range.begin)..(line_range.begin + max_line_count - 1) end source.lines[(line_range.begin - 1)..(line_range.end - 1)] rescue SyntaxError, NoExpressionAtLineError [self.class.extract_line_at(source.path, beginning_line_number)] end private def line_range_of_expression @line_range_of_expression ||= begin line_range = line_range_of_location_nodes_in_expression initial_unclosed_tokens = unclosed_tokens_in_line_range(line_range) unclosed_tokens = initial_unclosed_tokens until (initial_unclosed_tokens & unclosed_tokens).empty? line_range = (line_range.begin)..(line_range.end + 1) unclosed_tokens = unclosed_tokens_in_line_range(line_range) end line_range end end def unclosed_tokens_in_line_range(line_range) tokens = FlatMap.flat_map(line_range) do |line_number| source.tokens_by_line_number[line_number] end tokens.each_with_object([]) do |token, unclosed_tokens| if token.opening? unclosed_tokens << token else index = unclosed_tokens.rindex do |unclosed_token| unclosed_token.closed_by?(token) end unclosed_tokens.delete_at(index) if index end end end def line_range_of_location_nodes_in_expression line_numbers = expression_node.each_with_object(Set.new) do |node, set| set << node.location.line if node.location end line_numbers.min..line_numbers.max end def expression_node raise NoExpressionAtLineError if location_nodes_at_beginning_line.empty? @expression_node ||= begin common_ancestor_nodes = location_nodes_at_beginning_line.map do |node| node.each_ancestor.to_a end.reduce(:&) common_ancestor_nodes.find { |node| expression_outmost_node?(node) } end end def expression_outmost_node?(node) return true unless node.parent return false if node.type.to_s.start_with?('@') ![node, node.parent].all? do |n| # See `Ripper::PARSER_EVENTS` for the complete list of sexp types. type = n.type.to_s type.end_with?('call') || type.start_with?('method_add_') end end def location_nodes_at_beginning_line source.nodes_by_line_number[beginning_line_number] end else # :nocov: def self.extract_expression_lines_at(file_path, beginning_line_number, *) [extract_line_at(file_path, beginning_line_number)] end # :nocov: end def self.least_indentation_from(lines) lines.map { |line| line[/^[ \t]*/] }.min end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/syntax_highlighter.rb0000664000000000000000000000526114557677674030116 0ustar rootrootmodule RSpec module Core module Formatters # @private # Provides terminal syntax highlighting of code snippets # when coderay is available. class SyntaxHighlighter def initialize(configuration) @configuration = configuration end def highlight(lines) implementation.highlight_syntax(lines) end # rubocop:disable Lint/RescueException # rubocop:disable Lint/HandleExceptions def self.attempt_to_add_rspec_terms_to_coderay_keywords CodeRay::Scanners::Ruby::Patterns::IDENT_KIND.add(%w[ describe context it specify before after around let subject expect allow ], :keyword) rescue Exception # Mutating CodeRay's contants like this is not a public API # and might not always work. If we cannot add our keywords # to CodeRay it is not a big deal and not worth raising an # error over, so we ignore it. end # rubocop:enable Lint/HandleExceptions # rubocop:enable Lint/RescueException private if RSpec::Support::OS.windows? # :nocov: def implementation WindowsImplementation end # :nocov: else def implementation return color_enabled_implementation if @configuration.color_enabled? NoSyntaxHighlightingImplementation end end def color_enabled_implementation @color_enabled_implementation ||= begin require 'coderay' self.class.attempt_to_add_rspec_terms_to_coderay_keywords CodeRayImplementation rescue LoadError NoSyntaxHighlightingImplementation end end # @private module CodeRayImplementation RESET_CODE = "\e[0m" def self.highlight_syntax(lines) highlighted = begin CodeRay.encode(lines.join("\n"), :ruby, :terminal) rescue Support::AllExceptionsExceptOnesWeMustNotRescue return lines end highlighted.split("\n").map do |line| line.sub(/\S/) { |char| char.insert(0, RESET_CODE) } end end end # @private module NoSyntaxHighlightingImplementation def self.highlight_syntax(lines) lines end end # @private # Not sure why, but our code above (and/or coderay itself) does not work # on Windows, so we disable the feature on Windows. WindowsImplementation = NoSyntaxHighlightingImplementation end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/bisect_progress_formatter.rb0000664000000000000000000001370514557677674031474 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_text_formatter" module RSpec module Core module Formatters # @private # Produces progress output while bisecting. class BisectProgressFormatter < BaseTextFormatter def initialize(output, bisect_runner) super(output) @bisect_runner = bisect_runner end def bisect_starting(notification) @round_count = 0 output.puts bisect_started_message(notification) output.print "Running suite to find failures..." end def bisect_original_run_complete(notification) failures = Helpers.pluralize(notification.failed_example_ids.size, "failing example") non_failures = Helpers.pluralize(notification.non_failing_example_ids.size, "non-failing example") output.puts " (#{Helpers.format_duration(notification.duration)})" output.puts "Starting bisect with #{failures} and #{non_failures}." end def bisect_dependency_check_started(_notification) output.print "Checking that failure(s) are order-dependent.." end def bisect_dependency_check_passed(_notification) output.puts " failure appears to be order-dependent" end def bisect_dependency_check_failed(_notification) output.puts " failure(s) do not require any non-failures to run first" if @bisect_runner == :fork output.puts output.puts "=" * 80 output.puts "NOTE: this bisect run used `config.bisect_runner = :fork`, which generally" output.puts "provides significantly faster bisection runs than the old shell-based runner," output.puts "but may inaccurately report that no non-failures are required. If this result" output.puts "is unexpected, consider setting `config.bisect_runner = :shell` and trying again." output.puts "=" * 80 end end def bisect_round_started(notification, include_trailing_space=true) @round_count += 1 range_desc = notification.candidate_range.description output.print "\nRound #{@round_count}: bisecting over non-failing #{range_desc}" output.print " " if include_trailing_space end def bisect_round_ignoring_ids(notification) range_desc = notification.ignore_range.description output.print " ignoring #{range_desc}" output.print " (#{Helpers.format_duration(notification.duration)})" end def bisect_round_detected_multiple_culprits(notification) output.print " multiple culprits detected - splitting candidates" output.print " (#{Helpers.format_duration(notification.duration)})" end def bisect_individual_run_complete(_) output.print '.' end def bisect_complete(notification) output.puts "\nBisect complete! Reduced necessary non-failing examples " \ "from #{notification.original_non_failing_count} to " \ "#{notification.remaining_count} in " \ "#{Helpers.format_duration(notification.duration)}." end def bisect_repro_command(notification) output.puts "\nThe minimal reproduction command is:\n #{notification.repro}" end def bisect_failed(notification) output.puts "\nBisect failed! #{notification.failure_explanation}" end def bisect_aborted(notification) output.puts "\n\nBisect aborted!" output.puts "\nThe most minimal reproduction command discovered so far is:\n #{notification.repro}" end private def bisect_started_message(notification) options = notification.original_cli_args.join(' ') "Bisect started using options: #{options.inspect}" end end # @private # Produces detailed debug output while bisecting. Used when bisect is # performed with `--bisect=verbose`. Designed to provide details for # us when we need to troubleshoot bisect bugs. class BisectDebugFormatter < BisectProgressFormatter def bisect_original_run_complete(notification) output.puts " (#{Helpers.format_duration(notification.duration)})" output.puts " - #{describe_ids 'Failing examples', notification.failed_example_ids}" output.puts " - #{describe_ids 'Non-failing examples', notification.non_failing_example_ids}" end def bisect_individual_run_start(notification) output.print "\n - Running: #{notification.command}" end def bisect_individual_run_complete(notification) output.print " (#{Helpers.format_duration(notification.duration)})" end def bisect_dependency_check_passed(_notification) output.print "\n - Failure appears to be order-dependent" end def bisect_dependency_check_failed(_notification) output.print "\n - Failure is not order-dependent" end def bisect_round_started(notification) super(notification, false) end def bisect_round_ignoring_ids(notification) output.print "\n - #{describe_ids 'Examples we can safely ignore', notification.ids_to_ignore}" output.print "\n - #{describe_ids 'Remaining non-failing examples', notification.remaining_ids}" end def bisect_round_detected_multiple_culprits(_notification) output.print "\n - Multiple culprits detected - splitting candidates" end private def describe_ids(description, ids) organized_ids = Formatters::Helpers.organize_ids(ids) formatted_ids = organized_ids.map { |id| " - #{id}" }.join("\n") "#{description} (#{ids.size}):\n#{formatted_ids}" end def bisect_started_message(notification) "#{super} and bisect runner: #{notification.bisect_runner.inspect}" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/helpers.rb0000664000000000000000000000772014557677674025656 0ustar rootrootRSpec::Support.require_rspec_core "shell_escape" module RSpec module Core module Formatters # Formatters helpers. module Helpers # @private SUB_SECOND_PRECISION = 5 # @private DEFAULT_PRECISION = 2 # @api private # # Formats seconds into a human-readable string. # # @param duration [Float, Fixnum] in seconds # @return [String] human-readable time # # @example # format_duration(1) #=> "1 minute 1 second" # format_duration(135.14) #=> "2 minutes 15.14 seconds" def self.format_duration(duration) precision = case when duration < 1 then SUB_SECOND_PRECISION when duration < 120 then DEFAULT_PRECISION when duration < 300 then 1 else 0 end if duration > 60 minutes = (duration.round / 60).to_i seconds = (duration - minutes * 60) "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds, precision), 'second')}" else pluralize(format_seconds(duration, precision), 'second') end end # @api private # # Formats seconds to have 5 digits of precision with trailing zeros # removed if the number is less than 1 or with 2 digits of precision if # the number is greater than zero. # # @param float [Float] # @return [String] formatted float # # @example # format_seconds(0.000006) #=> "0.00001" # format_seconds(0.020000) #=> "0.02" # format_seconds(1.00000000001) #=> "1" # # The precision used is set in {Helpers::SUB_SECOND_PRECISION} and # {Helpers::DEFAULT_PRECISION}. # # @see #strip_trailing_zeroes def self.format_seconds(float, precision=nil) return '0' if float < 0 precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION formatted = "%.#{precision}f" % float strip_trailing_zeroes(formatted) end # @api private # # Remove trailing zeros from a string. # # Only remove trailing zeros after a decimal place. # see: http://rubular.com/r/ojtTydOgpn # # @param string [String] string with trailing zeros # @return [String] string with trailing zeros removed def self.strip_trailing_zeroes(string) string.sub(/(?:(\..*[^0])0+|\.0+)$/, '\1') end private_class_method :strip_trailing_zeroes # @api private # # Pluralize a word based on a count. # # @param count [Fixnum] number of objects # @param string [String] word to be pluralized # @return [String] pluralized word def self.pluralize(count, string) pluralized_string = if count.to_f == 1 string elsif string.end_with?('s') # e.g. "process" "#{string}es" # e.g. "processes" else "#{string}s" end "#{count} #{pluralized_string}" end # @api private # Given a list of example ids, organizes them into a compact, ordered list. def self.organize_ids(ids) grouped = ids.inject(Hash.new { |h, k| h[k] = [] }) do |hash, id| file, id = Example.parse_id(id) hash[file] << id hash end grouped.sort_by(&:first).map do |file, grouped_ids| grouped_ids = grouped_ids.sort_by { |id| id.split(':').map(&:to_i) } id = Metadata.id_from(:rerun_file_path => file, :scoped_id => grouped_ids.join(',')) ShellEscape.conditionally_quote(id) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/json_formatter.rb0000664000000000000000000000634714557677674027254 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_formatter" require 'json' module RSpec module Core module Formatters # @private class JsonFormatter < BaseFormatter Formatters.register self, :message, :dump_summary, :dump_profile, :stop, :seed, :close attr_reader :output_hash def initialize(output) super @output_hash = { :version => RSpec::Core::Version::STRING } end def message(notification) (@output_hash[:messages] ||= []) << notification.message end def dump_summary(summary) @output_hash[:summary] = { :duration => summary.duration, :example_count => summary.example_count, :failure_count => summary.failure_count, :pending_count => summary.pending_count, :errors_outside_of_examples_count => summary.errors_outside_of_examples_count } @output_hash[:summary_line] = summary.totals_line end def stop(group_notification) @output_hash[:examples] = group_notification.notifications.map do |notification| format_example(notification.example).tap do |hash| e = notification.example.exception if e hash[:exception] = { :class => e.class.name, :message => e.message, :backtrace => notification.formatted_backtrace, } end end end end def seed(notification) return unless notification.seed_used? @output_hash[:seed] = notification.seed end def close(_notification) output.write @output_hash.to_json end def dump_profile(profile) @output_hash[:profile] = {} dump_profile_slowest_examples(profile) dump_profile_slowest_example_groups(profile) end # @api private def dump_profile_slowest_examples(profile) @output_hash[:profile] = {} @output_hash[:profile][:examples] = profile.slowest_examples.map do |example| format_example(example).tap do |hash| hash[:run_time] = example.execution_result.run_time end end @output_hash[:profile][:slowest] = profile.slow_duration @output_hash[:profile][:total] = profile.duration end # @api private def dump_profile_slowest_example_groups(profile) @output_hash[:profile] ||= {} @output_hash[:profile][:groups] = profile.slowest_groups.map do |loc, hash| hash.update(:location => loc) end end private def format_example(example) { :id => example.id, :description => example.description, :full_description => example.full_description, :status => example.execution_result.status.to_s, :file_path => example.metadata[:file_path], :line_number => example.metadata[:line_number], :run_time => example.execution_result.run_time, :pending_message => example.execution_result.pending_message, } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/failure_list_formatter.rb0000664000000000000000000000120314557677674030747 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_formatter" module RSpec module Core module Formatters # @private class FailureListFormatter < BaseFormatter Formatters.register self, :example_failed, :dump_profile, :message def example_failed(failure) output.puts "#{failure.example.location}:#{failure.example.description}" end # Discard profile and messages # # These outputs are not really relevant in the context of this failure # list formatter. def dump_profile(_profile); end def message(_message); end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/profile_formatter.rb0000664000000000000000000000440414557677674027733 0ustar rootrootRSpec::Support.require_rspec_core "formatters/console_codes" module RSpec module Core module Formatters # @api private # Formatter for providing profile output. class ProfileFormatter Formatters.register self, :dump_profile def initialize(output) @output = output end # @private attr_reader :output # @api public # # This method is invoked after the dumping the summary if profiling is # enabled. # # @param profile [ProfileNotification] containing duration, # slowest_examples and slowest_example_groups def dump_profile(profile) dump_profile_slowest_examples(profile) dump_profile_slowest_example_groups(profile) end private def dump_profile_slowest_examples(profile) @output.puts "\nTop #{profile.slowest_examples.size} slowest " \ "examples (#{Helpers.format_seconds(profile.slow_duration)} " \ "seconds, #{profile.percentage}% of total time):\n" profile.slowest_examples.each do |example| @output.puts " #{example.full_description}" @output.puts " #{bold(Helpers.format_seconds(example.execution_result.run_time))} " \ "#{bold("seconds")} #{format_caller(example.location)}" end end def dump_profile_slowest_example_groups(profile) return if profile.slowest_groups.empty? @output.puts "\nTop #{profile.slowest_groups.size} slowest example groups:" profile.slowest_groups.each do |loc, hash| average = "#{bold(Helpers.format_seconds(hash[:average]))} #{bold("seconds")} average" total = "#{Helpers.format_seconds(hash[:total_time])} seconds" count = Helpers.pluralize(hash[:count], "example") @output.puts " #{hash[:description]}" @output.puts " #{average} (#{total} / #{count}) #{loc}" end end def format_caller(caller_info) RSpec.configuration.backtrace_formatter.backtrace_line( caller_info.to_s.split(':in `block').first) end def bold(text) ConsoleCodes.wrap(text, :bold) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/bisect_drb_formatter.rb0000664000000000000000000000215214557677674030371 0ustar rootrootrequire 'drb/drb' RSpec::Support.require_rspec_core "formatters/base_bisect_formatter" module RSpec module Core module Formatters # Used by `--bisect`. When it shells out and runs a portion of the suite, it uses # this formatter as a means to have the status reported back to it, via DRb. # # Note that since DRb calls carry considerable overhead compared to normal # method calls, we try to minimize the number of DRb calls for perf reasons, # opting to communicate only at the start and the end of the run, rather than # after each example. # @private class BisectDRbFormatter < BaseBisectFormatter def initialize(_output) drb_uri = "druby://localhost:#{RSpec.configuration.drb_port}" @bisect_server = DRbObject.new_with_uri(drb_uri) RSpec.configuration.files_or_directories_to_run = @bisect_server.files_or_directories_to_run super(Set.new(@bisect_server.expected_failures)) end def notify_results(results) @bisect_server.latest_run_results = results end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/fallback_message_formatter.rb0000664000000000000000000000125214557677674031534 0ustar rootrootmodule RSpec module Core module Formatters # @api private # Formatter for providing message output as a fallback when no other # profiler implements #message class FallbackMessageFormatter Formatters.register self, :message def initialize(output) @output = output end # @private attr_reader :output # @api public # # Used by the reporter to send messages to the output stream. # # @param notification [MessageNotification] containing message def message(notification) output.puts notification.message end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/protocol.rb0000664000000000000000000001453414557677674026056 0ustar rootrootmodule RSpec module Core module Formatters # This class isn't loaded at runtime but serves to document all of the # notifications implemented as part of the standard interface. The # reporter will issue these during a normal test suite run, but a # formatter will only receive those notifications it has registered # itself to receive. To register a formatter call: # # `::RSpec::Core::Formatters.register class, :list, :of, :notifications` # # e.g. # # `::RSpec::Core::Formatters.register self, :start, :example_started` # # @see RSpec::Core::Formatters::BaseFormatter # @see RSpec::Core::Formatters::BaseTextFormatter # @see RSpec::Core::Reporter class Protocol # @method initialize(output) # @api public # # @param output [IO] the formatter output # @method start(notification) # @api public # @group Suite Notifications # # This method is invoked before any examples are run, right after # they have all been collected. This can be useful for special # formatters that need to provide progress on feedback (graphical ones). # # This will only be invoked once, and the next one to be invoked # is {#example_group_started}. # # @param notification [Notifications::StartNotification] # @method example_group_started(notification) # @api public # @group Group Notifications # # This method is invoked at the beginning of the execution of each # example group. # # The next method to be invoked after this is {#example_passed}, # {#example_pending}, or {#example_group_finished}. # # @param notification [Notifications::GroupNotification] containing example_group # subclass of {ExampleGroup} # @method example_group_finished(notification) # @api public # @group Group Notifications # # Invoked at the end of the execution of each example group. # # @param notification [Notifications::GroupNotification] containing example_group # subclass of {ExampleGroup} # @method example_started(notification) # @api public # @group Example Notifications # # Invoked at the beginning of the execution of each example. # # @param notification [Notifications::ExampleNotification] containing example subclass # of {Example} # @method example_finished(notification) # @api public # @group Example Notifications # # Invoked at the end of the execution of each example. # # @param notification [Notifications::ExampleNotification] containing example subclass # of {Example} # @method example_passed(notification) # @api public # @group Example Notifications # # Invoked when an example passes. # # @param notification [Notifications::ExampleNotification] containing example subclass # of {Example} # @method example_pending(notification) # @api public # @group Example Notifications # # Invoked when an example is pending. # # @param notification [Notifications::ExampleNotification] containing example subclass # of {Example} # @method example_failed(notification) # @api public # @group Example Notifications # # Invoked when an example fails. # # @param notification [Notifications::ExampleNotification] containing example subclass # of {Example} # @method message(notification) # @api public # @group Suite Notifications # # Used by the reporter to send messages to the output stream. # # @param notification [Notifications::MessageNotification] containing message # @method stop(notification) # @api public # @group Suite Notifications # # Invoked after all examples have executed, before dumping post-run # reports. # # @param notification [Notifications::NullNotification] # @method start_dump(notification) # @api public # @group Suite Notifications # # This method is invoked after all of the examples have executed. The # next method to be invoked after this one is {#dump_failures} # (BaseTextFormatter then calls {#dump_failures} once for each failed # example). # # @param notification [Notifications::NullNotification] # @method dump_failures(notification) # @api public # @group Suite Notifications # # Dumps detailed information about each example failure. # # @param notification [Notifications::NullNotification] # @method dump_summary(summary) # @api public # @group Suite Notifications # # This method is invoked after the dumping of examples and failures. # Each parameter is assigned to a corresponding attribute. # # @param summary [Notifications::SummaryNotification] containing duration, # example_count, failure_count and pending_count # @method dump_profile(profile) # @api public # @group Suite Notifications # # This method is invoked after the dumping the summary if profiling is # enabled. # # @param profile [Notifications::ProfileNotification] containing duration, # slowest_examples and slowest_example_groups # @method dump_pending(notification) # @api public # @group Suite Notifications # # Outputs a report of pending examples. This gets invoked # after the summary if option is set to do so. # # @param notification [Notifications::NullNotification] # @method close(notification) # @api public # @group Suite Notifications # # Invoked at the end of a suite run. Allows the formatter to do any # tidying up, but be aware that formatter output streams may be used # elsewhere so don't actually close them. # # @param notification [Notifications::NullNotification] end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/base_text_formatter.rb0000664000000000000000000000452414557677674030254 0ustar rootrootRSpec::Support.require_rspec_core "formatters/base_formatter" module RSpec module Core module Formatters # Base for all of RSpec's built-in formatters. See # RSpec::Core::Formatters::BaseFormatter to learn more about all of the # methods called by the reporter. # # @see RSpec::Core::Formatters::BaseFormatter # @see RSpec::Core::Reporter class BaseTextFormatter < BaseFormatter Formatters.register self, :message, :dump_summary, :dump_failures, :dump_pending, :seed # @api public # # Used by the reporter to send messages to the output stream. # # @param notification [MessageNotification] containing message def message(notification) output.puts notification.message end # @api public # # Dumps detailed information about each example failure. # # @param notification [NullNotification] def dump_failures(notification) return if notification.failure_notifications.empty? output.puts notification.fully_formatted_failed_examples end # @api public # # This method is invoked after the dumping of examples and failures. # Each parameter is assigned to a corresponding attribute. # # @param summary [SummaryNotification] containing duration, # example_count, failure_count and pending_count def dump_summary(summary) output.puts summary.fully_formatted end # @private def dump_pending(notification) return if notification.pending_examples.empty? output.puts notification.fully_formatted_pending_examples end # @private def seed(notification) return unless notification.seed_used? output.puts notification.fully_formatted end # @api public # # Invoked at the end of a suite run. Allows the formatter to do any # tidying up, but be aware that formatter output streams may be used # elsewhere so don't actually close them. # # @param _notification [NullNotification] (Ignored) def close(_notification) return if output.closed? output.puts output.flush end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/formatters/base_formatter.rb0000664000000000000000000000403214557677674027202 0ustar rootrootRSpec::Support.require_rspec_core "formatters/helpers" require 'stringio' module RSpec module Core module Formatters # RSpec's built-in formatters are all subclasses of # RSpec::Core::Formatters::BaseFormatter. # # @see RSpec::Core::Formatters::BaseTextFormatter # @see RSpec::Core::Reporter # @see RSpec::Core::Formatters::Protocol class BaseFormatter # All formatters inheriting from this formatter will receive these # notifications. Formatters.register self, :start, :example_group_started, :close attr_accessor :example_group attr_reader :output # @api public # @param output [IO] the formatter output # @see RSpec::Core::Formatters::Protocol#initialize def initialize(output) @output = output || StringIO.new @example_group = nil end # @api public # # @param notification [StartNotification] # @see RSpec::Core::Formatters::Protocol#start def start(notification) start_sync_output @example_count = notification.count end # @api public # # @param notification [GroupNotification] containing example_group # subclass of `RSpec::Core::ExampleGroup` # @see RSpec::Core::Formatters::Protocol#example_group_started def example_group_started(notification) @example_group = notification.group end # @api public # # @param _notification [NullNotification] (Ignored) # @see RSpec::Core::Formatters::Protocol#close def close(_notification) restore_sync_output end private def start_sync_output @old_sync, output.sync = output.sync, true if output_supports_sync end def restore_sync_output output.sync = @old_sync if output_supports_sync && !output.closed? end def output_supports_sync output.respond_to?(:sync=) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/sandbox.rb0000664000000000000000000000235614557677674023464 0ustar rootrootmodule RSpec module Core # A sandbox isolates the enclosed code into an environment that looks 'new' # meaning globally accessed objects are reset for the duration of the # sandbox. # # @note This module is not normally available. You must require # `rspec/core/sandbox` to load it. module Sandbox # Execute a provided block with RSpec global objects (configuration, # world) reset. This is used to test RSpec with RSpec. # # When calling this the configuration is passed into the provided block. # Use this to set custom configs for your sandboxed examples. # # ``` # Sandbox.sandboxed do |config| # config.before(:context) { RSpec.current_example = nil } # end # ``` def self.sandboxed orig_config = RSpec.configuration orig_world = RSpec.world orig_example = RSpec.current_example RSpec.configuration = RSpec::Core::Configuration.new RSpec.world = RSpec::Core::World.new(RSpec.configuration) yield RSpec.configuration ensure RSpec.configuration = orig_config RSpec.world = orig_world RSpec.current_example = orig_example end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/shared_context.rb0000664000000000000000000000256414557677674025041 0ustar rootrootmodule RSpec module Core # Exposes {ExampleGroup}-level methods to a module, so you can include that # module in an {ExampleGroup}. # # @example # # module LoggedInAsAdmin # extend RSpec::Core::SharedContext # before(:example) do # log_in_as :admin # end # end # # describe "admin section" do # include LoggedInAsAdmin # # ... # end module SharedContext # @private def included(group) __shared_context_recordings.each do |recording| recording.playback_onto(group) end end # @private def __shared_context_recordings @__shared_context_recordings ||= [] end # @private Recording = Struct.new(:method_name, :args, :block) do def playback_onto(group) group.__send__(method_name, *args, &block) end end # @private def self.record(methods) methods.each do |meth| define_method(meth) do |*args, &block| __shared_context_recordings << Recording.new(meth, args, block) end end end # @private record [:describe, :context] + Hooks.instance_methods(false) + MemoizedHelpers::ClassMethods.instance_methods(false) end end # @private SharedContext = Core::SharedContext end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/hooks.rb0000664000000000000000000006346714557677674023163 0ustar rootrootmodule RSpec module Core # Provides `before`, `after` and `around` hooks as a means of # supporting common setup and teardown. This module is extended # onto {ExampleGroup}, making the methods available from any `describe` # or `context` block and included in {Configuration}, making them # available off of the configuration object to define global setup # or teardown logic. module Hooks # @api public # # @overload before(&block) # @overload before(scope, &block) # @param scope [Symbol] `:example`, `:context`, or `:suite` # (defaults to `:example`) # @overload before(scope, *conditions, &block) # @param scope [Symbol] `:example`, `:context`, or `:suite` # (defaults to `:example`) # @param conditions [Array, Hash] constrains this hook to # examples matching these conditions e.g. # `before(:example, :ui => true) { ... }` will only run with examples # or groups declared with `:ui => true`. Symbols will be transformed # into hash entries with `true` values. # @overload before(conditions, &block) # @param conditions [Hash] # constrains this hook to examples matching these conditions e.g. # `before(:example, :ui => true) { ... }` will only run with examples # or groups declared with `:ui => true`. # # @see #after # @see #around # @see ExampleGroup # @see SharedContext # @see SharedExampleGroup # @see Configuration # # Declare a block of code to be run before each example (using `:example`) # or once before any example (using `:context`). These are usually # declared directly in the {ExampleGroup} to which they apply, but they # can also be shared across multiple groups. # # You can also use `before(:suite)` to run a block of code before any # example groups are run. This should be declared in {RSpec.configure}. # # Instance variables declared in `before(:example)` or `before(:context)` # are accessible within each example. # # ### Order # # `before` hooks are stored in three scopes, which are run in order: # `:suite`, `:context`, and `:example`. They can also be declared in # several different places: `RSpec.configure`, a parent group, the current # group. They are run in the following order: # # before(:suite) # Declared in RSpec.configure. # before(:context) # Declared in RSpec.configure. # before(:context) # Declared in a parent group. # before(:context) # Declared in the current group. # before(:example) # Declared in RSpec.configure. # before(:example) # Declared in a parent group. # before(:example) # Declared in the current group. # # If more than one `before` is declared within any one example group, they # are run in the order in which they are declared. Any `around` hooks will # execute after `before` context hooks but before any `before` example # hook regardless of where they are declared. # # ### Conditions # # When you add a conditions hash to `before(:example)` or # `before(:context)`, RSpec will only apply that hook to groups or # examples that match the conditions. e.g. # # RSpec.configure do |config| # config.before(:example, :authorized => true) do # log_in_as :authorized_user # end # end # # RSpec.describe Something, :authorized => true do # # The before hook will run in before each example in this group. # end # # RSpec.describe SomethingElse do # it "does something", :authorized => true do # # The before hook will run before this example. # end # # it "does something else" do # # The hook will not run before this example. # end # end # # Note that filtered config `:context` hooks can still be applied # to individual examples that have matching metadata. Just like # Ruby's object model is that every object has a singleton class # which has only a single instance, RSpec's model is that every # example has a singleton example group containing just the one # example. # # ### Warning: `before(:suite, :with => :conditions)` # # The conditions hash is used to match against specific examples. Since # `before(:suite)` is not run in relation to any specific example or # group, conditions passed along with `:suite` are effectively ignored. # # ### Exceptions # # When an exception is raised in a `before` block, RSpec skips any # subsequent `before` blocks and the example, but runs all of the # `after(:example)` and `after(:context)` hooks. # # ### Warning: implicit before blocks # # `before` hooks can also be declared in shared contexts which get # included implicitly either by you or by extension libraries. Since # RSpec runs these in the order in which they are declared within each # scope, load order matters, and can lead to confusing results when one # before block depends on state that is prepared in another before block # that gets run later. # # ### Warning: `before(:context)` # # It is very tempting to use `before(:context)` to speed things up, but we # recommend that you avoid this as there are a number of gotchas, as well # as things that simply don't work. # # #### Context # # `before(:context)` is run in an example that is generated to provide # group context for the block. # # #### Instance variables # # Instance variables declared in `before(:context)` are shared across all # the examples in the group. This means that each example can change the # state of a shared object, resulting in an ordering dependency that can # make it difficult to reason about failures. # # #### Unsupported RSpec constructs # # RSpec has several constructs that reset state between each example # automatically. These are not intended for use from within # `before(:context)`: # # * `let` declarations # * `subject` declarations # * Any mocking, stubbing or test double declaration # # ### other frameworks # # Mock object frameworks and database transaction managers (like # ActiveRecord) are typically designed around the idea of setting up # before an example, running that one example, and then tearing down. This # means that mocks and stubs can (sometimes) be declared in # `before(:context)`, but get torn down before the first real example is # ever run. # # You _can_ create database-backed model objects in a `before(:context)` # in rspec-rails, but it will not be wrapped in a transaction for you, so # you are on your own to clean up in an `after(:context)` block. # # @example before(:example) declared in an {ExampleGroup} # # RSpec.describe Thing do # before(:example) do # @thing = Thing.new # end # # it "does something" do # # Here you can access @thing. # end # end # # @example before(:context) declared in an {ExampleGroup} # # RSpec.describe Parser do # before(:context) do # File.open(file_to_parse, 'w') do |f| # f.write <<-CONTENT # stuff in the file # CONTENT # end # end # # it "parses the file" do # Parser.parse(file_to_parse) # end # # after(:context) do # File.delete(file_to_parse) # end # end # # @note The `:example` and `:context` scopes are also available as # `:each` and `:all`, respectively. Use whichever you prefer. # @note The `:suite` scope is only supported for hooks registered on # `RSpec.configuration` since they exist independently of any # example or example group. def before(*args, &block) hooks.register :append, :before, *args, &block end alias_method :append_before, :before # Adds `block` to the front of the list of `before` blocks in the same # scope (`:example`, `:context`, or `:suite`). # # See {#before} for scoping semantics. def prepend_before(*args, &block) hooks.register :prepend, :before, *args, &block end # @api public # @overload after(&block) # @overload after(scope, &block) # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to # `:example`) # @overload after(scope, *conditions, &block) # @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to # `:example`) # @param conditions [Array, Hash] constrains this hook to # examples matching these conditions e.g. # `after(:example, :ui => true) { ... }` will only run with examples # or groups declared with `:ui => true`. Symbols will be transformed # into hash entries with `true` values. # @overload after(conditions, &block) # @param conditions [Hash] # constrains this hook to examples matching these conditions e.g. # `after(:example, :ui => true) { ... }` will only run with examples # or groups declared with `:ui => true`. # # @see #before # @see #around # @see ExampleGroup # @see SharedContext # @see SharedExampleGroup # @see Configuration # # Declare a block of code to be run after each example (using `:example`) # or once after all examples n the context (using `:context`). See # {#before} for more information about ordering. # # ### Exceptions # # `after` hooks are guaranteed to run even when there are exceptions in # `before` hooks or examples. When an exception is raised in an after # block, the exception is captured for later reporting, and subsequent # `after` blocks are run. # # ### Order # # `after` hooks are stored in three scopes, which are run in order: # `:example`, `:context`, and `:suite`. They can also be declared in # several different places: `RSpec.configure`, a parent group, the current # group. They are run in the following order: # # after(:example) # Declared in the current group. # after(:example) # Declared in a parent group. # after(:example) # Declared in RSpec.configure. # after(:context) # Declared in the current group. # after(:context) # Declared in a parent group. # after(:context) # Declared in RSpec.configure. # after(:suite) # Declared in RSpec.configure. # # This is the reverse of the order in which `before` hooks are run. # Similarly, if more than one `after` is declared within any example # group, they are run in reverse order of that in which they are declared. # Also `around` hooks will run after any `after` example hooks are # invoked but before any `after` context hooks. # # @note The `:example` and `:context` scopes are also available as # `:each` and `:all`, respectively. Use whichever you prefer. # @note The `:suite` scope is only supported for hooks registered on # `RSpec.configuration` since they exist independently of any # example or example group. def after(*args, &block) hooks.register :prepend, :after, *args, &block end alias_method :prepend_after, :after # Adds `block` to the back of the list of `after` blocks in the same # scope (`:example`, `:context`, or `:suite`). # # See {#after} for scoping semantics. def append_after(*args, &block) hooks.register :append, :after, *args, &block end # @api public # @overload around(&block) # @overload around(scope, &block) # @param scope [Symbol] `:example` (defaults to `:example`) # present for syntax parity with `before` and `after`, but # `:example`/`:each` is the only supported value. # @overload around(scope, *conditions, &block) # @param scope [Symbol] `:example` (defaults to `:example`) # present for syntax parity with `before` and `after`, but # `:example`/`:each` is the only supported value. # @param conditions [Array, Hash] constrains this hook to # examples matching these conditions e.g. # `around(:example, :ui => true) { ... }` will only run with examples # or groups declared with `:ui => true`. Symbols will be transformed # into hash entries with `true` values. # @overload around(conditions, &block) # @param conditions [Hash] constrains this hook to examples matching # these conditions e.g. `around(:example, :ui => true) { ... }` will # only run with examples or groups declared with `:ui => true`. # # @yield [Example] the example to run # # @note the syntax of `around` is similar to that of `before` and `after` # but the semantics are quite different. `before` and `after` hooks are # run in the context of the examples with which they are associated, # whereas `around` hooks are actually responsible for running the # examples. Consequently, `around` hooks do not have direct access to # resources that are made available within the examples and their # associated `before` and `after` hooks. # # @note `:example`/`:each` is the only supported scope. # # Declare a block of code, parts of which will be run before and parts # after the example. It is your responsibility to run the example: # # around(:example) do |ex| # # Do some stuff before. # ex.run # # Do some stuff after. # end # # The yielded example aliases `run` with `call`, which lets you treat it # like a `Proc`. This is especially handy when working with libraries # that manage their own setup and teardown using a block or proc syntax, # e.g. # # around(:example) {|ex| Database.transaction(&ex)} # around(:example) {|ex| FakeFS(&ex)} # # ### Order # # The `around` hooks execute surrounding an example and its hooks. # # This means after any `before` context hooks, but before any `before` # example hooks, and similarly after any `after` example hooks but before # any `after` context hooks. # # They are not a synonym for `before`/`after`. def around(*args, &block) hooks.register :prepend, :around, *args, &block end # @private # Holds the various registered hooks. def hooks @hooks ||= HookCollections.new(self, FilterableItemRepository::UpdateOptimized) end # @private Hook = Struct.new(:block, :options) # @private class BeforeHook < Hook def run(example) example.instance_exec(example, &block) end end # @private class AfterHook < Hook def run(example) example.instance_exec(example, &block) rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex example.set_exception(ex) end end # @private class AfterContextHook < Hook def run(example) example.instance_exec(example, &block) rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e RSpec.configuration.reporter.notify_non_example_exception(e, "An error occurred in an `after(:context)` hook.") end end # @private class AroundHook < Hook def execute_with(example, procsy) example.instance_exec(procsy, &block) return if procsy.executed? Pending.mark_skipped!(example, "#{hook_description} did not execute the example") end if Proc.method_defined?(:source_location) def hook_description "around hook at #{Metadata.relative_path(block.source_location.join(':'))}" end else # for 1.8.7 # :nocov: def hook_description "around hook" end # :nocov: end end # @private # # This provides the primary API used by other parts of rspec-core. By hiding all # implementation details behind this facade, it's allowed us to heavily optimize # this, so that, for example, hook collection objects are only instantiated when # a hook is added. This allows us to avoid many object allocations for the common # case of a group having no hooks. # # This is only possible because this interface provides a "tell, don't ask"-style # API, so that callers _tell_ this class what to do with the hooks, rather than # asking this class for a list of hooks, and then doing something with them. class HookCollections def initialize(owner, filterable_item_repo_class) @owner = owner @filterable_item_repo_class = filterable_item_repo_class @before_example_hooks = nil @after_example_hooks = nil @before_context_hooks = nil @after_context_hooks = nil @around_example_hooks = nil end def register_globals(host, globals) parent_groups = host.parent_groups process(host, parent_groups, globals, :before, :example, &:options) process(host, parent_groups, globals, :after, :example, &:options) process(host, parent_groups, globals, :around, :example, &:options) process(host, parent_groups, globals, :before, :context, &:options) process(host, parent_groups, globals, :after, :context, &:options) end def register_global_singleton_context_hooks(example, globals) parent_groups = example.example_group.parent_groups process(example, parent_groups, globals, :before, :context) { {} } process(example, parent_groups, globals, :after, :context) { {} } end def register(prepend_or_append, position, *args, &block) scope, options = scope_and_options_from(*args) if scope == :suite # TODO: consider making this an error in RSpec 4. For SemVer reasons, # we are only warning in RSpec 3. RSpec.warn_with "WARNING: `#{position}(:suite)` hooks are only supported on " \ "the RSpec configuration object. This " \ "`#{position}(:suite)` hook, registered on an example " \ "group, will be ignored." return elsif scope == :context && position == :around # TODO: consider making this an error in RSpec 4. For SemVer reasons, # we are only warning in RSpec 3. RSpec.warn_with "WARNING: `around(:context)` hooks are not supported and " \ "behave like `around(:example)." end hook = HOOK_TYPES[position][scope].new(block, options) ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options) end # @private # # Runs all of the blocks stored with the hook in the context of the # example. If no example is provided, just calls the hook directly. def run(position, scope, example_or_group) return if RSpec.configuration.dry_run? if scope == :context unless example_or_group.class.metadata[:skip] run_owned_hooks_for(position, :context, example_or_group) end else case position when :before then run_example_hooks_for(example_or_group, :before, :reverse_each) when :after then run_example_hooks_for(example_or_group, :after, :each) when :around then run_around_example_hooks_for(example_or_group) { yield } end end end SCOPES = [:example, :context] SCOPE_ALIASES = { :each => :example, :all => :context } HOOK_TYPES = { :before => Hash.new { BeforeHook }, :after => Hash.new { AfterHook }, :around => Hash.new { AroundHook } } HOOK_TYPES[:after][:context] = AfterContextHook protected EMPTY_HOOK_ARRAY = [].freeze def matching_hooks_for(position, scope, example_or_group) repository = hooks_for(position, scope) { return EMPTY_HOOK_ARRAY } # It would be nice to not have to switch on type here, but # we don't want to define `ExampleGroup#metadata` because then # `metadata` from within an individual example would return the # group's metadata but the user would probably expect it to be # the example's metadata. metadata = case example_or_group when ExampleGroup then example_or_group.class.metadata else example_or_group.metadata end repository.items_for(metadata) end def all_hooks_for(position, scope) hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }.items_and_filters.map(&:first) end def run_owned_hooks_for(position, scope, example_or_group) matching_hooks_for(position, scope, example_or_group).each do |hook| hook.run(example_or_group) end end def processable_hooks_for(position, scope, host) if scope == :example all_hooks_for(position, scope) else matching_hooks_for(position, scope, host) end end private def hooks_for(position, scope) if position == :before scope == :example ? @before_example_hooks : @before_context_hooks elsif position == :after scope == :example ? @after_example_hooks : @after_context_hooks else # around @around_example_hooks end || yield end def ensure_hooks_initialized_for(position, scope) if position == :before if scope == :example @before_example_hooks ||= @filterable_item_repo_class.new(:all?) else @before_context_hooks ||= @filterable_item_repo_class.new(:all?) end elsif position == :after if scope == :example @after_example_hooks ||= @filterable_item_repo_class.new(:all?) else @after_context_hooks ||= @filterable_item_repo_class.new(:all?) end else # around @around_example_hooks ||= @filterable_item_repo_class.new(:all?) end end def process(host, parent_groups, globals, position, scope) hooks_to_process = globals.processable_hooks_for(position, scope, host) return if hooks_to_process.empty? hooks_to_process -= FlatMap.flat_map(parent_groups) do |group| group.hooks.all_hooks_for(position, scope) end return if hooks_to_process.empty? repository = ensure_hooks_initialized_for(position, scope) hooks_to_process.each { |hook| repository.append hook, (yield hook) } end def scope_and_options_from(*args) return :suite if args.first == :suite scope = extract_scope_from(args) meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) return scope, meta end def extract_scope_from(args) if known_scope?(args.first) normalized_scope_for(args.shift) elsif args.any? { |a| a.is_a?(Symbol) } error_message = "You must explicitly give a scope " \ "(#{SCOPES.join(", ")}) or scope alias " \ "(#{SCOPE_ALIASES.keys.join(", ")}) when using symbols as " \ "metadata for a hook." raise ArgumentError.new error_message else :example end end def known_scope?(scope) SCOPES.include?(scope) || SCOPE_ALIASES.keys.include?(scope) end def normalized_scope_for(scope) SCOPE_ALIASES[scope] || scope end def run_example_hooks_for(example, position, each_method) owner_parent_groups.__send__(each_method) do |group| group.hooks.run_owned_hooks_for(position, :example, example) end end def run_around_example_hooks_for(example) hooks = FlatMap.flat_map(owner_parent_groups) do |group| group.hooks.matching_hooks_for(:around, :example, example) end return yield if hooks.empty? # exit early to avoid the extra allocation cost of `Example::Procsy` initial_procsy = Example::Procsy.new(example) { yield } hooks.inject(initial_procsy) do |procsy, around_hook| procsy.wrap { around_hook.execute_with(example, procsy) } end.call end if respond_to?(:singleton_class) && singleton_class.ancestors.include?(singleton_class) def owner_parent_groups @owner.parent_groups end else # Ruby < 2.1 (see https://bugs.ruby-lang.org/issues/8035) # :nocov: def owner_parent_groups @owner_parent_groups ||= [@owner] + @owner.parent_groups end # :nocov: end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/example.rb0000664000000000000000000005545714557677674023473 0ustar rootrootmodule RSpec module Core # Wrapper for an instance of a subclass of {ExampleGroup}. An instance of # `RSpec::Core::Example` is returned by example definition methods # such as {ExampleGroup.it it} and is yielded to the {ExampleGroup.it it}, # {Hooks#before before}, {Hooks#after after}, {Hooks#around around}, # {MemoizedHelpers::ClassMethods#let let} and # {MemoizedHelpers::ClassMethods#subject subject} blocks. # # This allows us to provide rich metadata about each individual # example without adding tons of methods directly to the ExampleGroup # that users may inadvertently redefine. # # Useful for configuring logging and/or taking some action based # on the state of an example's metadata. # # @example # # RSpec.configure do |config| # config.before do |example| # log example.description # end # # config.after do |example| # log example.description # end # # config.around do |example| # log example.description # example.run # end # end # # shared_examples "auditable" do # it "does something" do # log "#{example.full_description}: #{auditable.inspect}" # auditable.should do_something # end # end # # @see ExampleGroup # @note Example blocks are evaluated in the context of an instance # of an `ExampleGroup`, not in the context of an instance of `Example`. class Example # @private # # Used to define methods that delegate to this example's metadata. def self.delegate_to_metadata(key) define_method(key) { @metadata[key] } end # @return [ExecutionResult] represents the result of running this example. delegate_to_metadata :execution_result # @return [String] the relative path to the file where this example was # defined. delegate_to_metadata :file_path # @return [String] the full description (including the docstrings of # all parent example groups). delegate_to_metadata :full_description # @return [String] the exact source location of this example in a form # like `./path/to/spec.rb:17` delegate_to_metadata :location # @return [Boolean] flag that indicates that the example is not expected # to pass. It will be run and will either have a pending result (if a # failure occurs) or a failed result (if no failure occurs). delegate_to_metadata :pending # @return [Boolean] flag that will cause the example to not run. # The {ExecutionResult} status will be `:pending`. delegate_to_metadata :skip # Returns the string submitted to `example` or its aliases (e.g. # `specify`, `it`, etc). If no string is submitted (e.g. # `it { is_expected.to do_something }`) it returns the message generated # by the matcher if there is one, otherwise returns a message including # the location of the example. def description description = if metadata[:description].to_s.empty? location_description else metadata[:description] end RSpec.configuration.format_docstrings_block.call(description) end # Returns a description of the example that always includes the location. def inspect_output inspect_output = "\"#{description}\"" unless metadata[:description].to_s.empty? inspect_output += " (#{location})" end inspect_output end # Returns the location-based argument that can be passed to the `rspec` command to rerun this example. def location_rerun_argument @location_rerun_argument ||= begin loaded_spec_files = RSpec.configuration.loaded_spec_files Metadata.ascending(metadata) do |meta| return meta[:location] if loaded_spec_files.include?(meta[:absolute_file_path]) end end end # Returns the location-based argument that can be passed to the `rspec` command to rerun this example. # # @deprecated Use {#location_rerun_argument} instead. # @note If there are multiple examples identified by this location, they will use {#id} # to rerun instead, but this method will still return the location (that's why it is deprecated!). def rerun_argument location_rerun_argument end # @return [String] the unique id of this example. Pass # this at the command line to re-run this exact example. def id @id ||= Metadata.id_from(metadata) end # @private def self.parse_id(id) # http://rubular.com/r/OMZSAPcAfn id.match(/\A(.*?)(?:\[([\d\s:,]+)\])?\z/).captures end # Duplicates the example and overrides metadata with the provided # hash. # # @param metadata_overrides [Hash] the hash to override the example metadata # @return [Example] a duplicate of the example with modified metadata def duplicate_with(metadata_overrides={}) new_metadata = metadata.clone.merge(metadata_overrides) RSpec::Core::Metadata::RESERVED_KEYS.each do |reserved_key| new_metadata.delete reserved_key end # don't clone the example group because the new example # must belong to the same example group (not a clone). # # block is nil in new_metadata so we have to get it from metadata. Example.new(example_group, description.clone, new_metadata, metadata[:block]) end # @private def update_inherited_metadata(updates) metadata.update(updates) do |_key, existing_example_value, _new_inherited_value| existing_example_value end end # @attr_reader # # Returns the first exception raised in the context of running this # example (nil if no exception is raised). attr_reader :exception # @attr_reader # # Returns the metadata object associated with this example. attr_reader :metadata # @attr_reader # @private # # Returns the example_group_instance that provides the context for # running this example. attr_reader :example_group_instance # @attr # @private attr_accessor :clock # Creates a new instance of Example. # @param example_group_class [Class] the subclass of ExampleGroup in which # this Example is declared # @param description [String] the String passed to the `it` method (or # alias) # @param user_metadata [Hash] additional args passed to `it` to be used as # metadata # @param example_block [Proc] the block of code that represents the # example # @api private def initialize(example_group_class, description, user_metadata, example_block=nil) @example_group_class = example_group_class @example_block = example_block # Register the example with the group before creating the metadata hash. # This is necessary since creating the metadata hash triggers # `when_first_matching_example_defined` callbacks, in which users can # load RSpec support code which defines hooks. For that to work, the # examples and example groups must be registered at the time the # support code is called or be defined afterwards. # Begin defined beforehand but registered afterwards causes hooks to # not be applied where they should. example_group_class.examples << self @metadata = Metadata::ExampleHash.create( @example_group_class.metadata, user_metadata, example_group_class.method(:next_runnable_index_for), description, example_block ) config = RSpec.configuration config.apply_derived_metadata_to(@metadata) # This should perhaps be done in `Metadata::ExampleHash.create`, # but the logic there has no knowledge of `RSpec.world` and we # want to keep it that way. It's easier to just assign it here. @metadata[:last_run_status] = config.last_run_statuses[id] @example_group_instance = @exception = nil @clock = RSpec::Core::Time @reporter = RSpec::Core::NullReporter end # Provide a human-readable representation of this class def inspect "#<#{self.class.name} #{description.inspect}>" end alias to_s inspect # @return [RSpec::Core::Reporter] the current reporter for the example attr_reader :reporter # Returns the example group class that provides the context for running # this example. def example_group @example_group_class end def pending? !!pending end def skipped? !!skip end # @api private # instance_execs the block passed to the constructor in the context of # the instance of {ExampleGroup}. # @param example_group_instance the instance of an ExampleGroup subclass def run(example_group_instance, reporter) @example_group_instance = example_group_instance @reporter = reporter RSpec.configuration.configure_example(self, hooks) RSpec.current_example = self start(reporter) Pending.mark_pending!(self, pending) if pending? begin if skipped? Pending.mark_pending! self, skip elsif !RSpec.configuration.dry_run? with_around_and_singleton_context_hooks do begin run_before_example RSpec.current_scope = :example @example_group_instance.instance_exec(self, &@example_block) if pending? Pending.mark_fixed! self raise Pending::PendingExampleFixedError, 'Expected example to fail since it is pending, but it passed.', [location] end rescue Pending::SkipDeclaredInExample => _ # The "=> _" is normally useless but on JRuby it is a workaround # for a bug that prevents us from getting backtraces: # https://github.com/jruby/jruby/issues/4467 # # no-op, required metadata has already been set by the `skip` # method. rescue AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt => e set_exception(e) ensure RSpec.current_scope = :after_example_hook run_after_example end end end rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e set_exception(e) ensure @example_group_instance = nil # if you love something... let it go end finish(reporter) ensure execution_result.ensure_timing_set(clock) RSpec.current_example = nil end if RSpec::Support::Ruby.jruby? || RUBY_VERSION.to_f < 1.9 # :nocov: # For some reason, rescuing `Support::AllExceptionsExceptOnesWeMustNotRescue` # in place of `Exception` above can cause the exit status to be the wrong # thing. I have no idea why. See: # https://github.com/rspec/rspec-core/pull/2063#discussion_r38284978 # @private AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt = Exception # :nocov: else # @private AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt = Support::AllExceptionsExceptOnesWeMustNotRescue end # Wraps both a `Proc` and an {Example} for use in {Hooks#around # around} hooks. In around hooks we need to yield this special # kind of object (rather than the raw {Example}) because when # there are multiple `around` hooks we have to wrap them recursively. # # @example # # RSpec.configure do |c| # c.around do |ex| # Procsy which wraps the example # if ex.metadata[:key] == :some_value && some_global_condition # raise "some message" # end # ex.run # run delegates to ex.call. # end # end # # @note This class also exposes the instance methods of {Example}, # proxying them through to the wrapped {Example} instance. class Procsy # The {Example} instance. attr_reader :example Example.public_instance_methods(false).each do |name| name_sym = name.to_sym next if name_sym == :run || name_sym == :inspect || name_sym == :to_s define_method(name) { |*a, &b| @example.__send__(name, *a, &b) } end Proc.public_instance_methods(false).each do |name| name_sym = name.to_sym next if name_sym == :call || name_sym == :inspect || name_sym == :to_s || name_sym == :to_proc define_method(name) { |*a, &b| @proc.__send__(name, *a, &b) } end # Calls the proc and notes that the example has been executed. def call(*args, &block) @executed = true @proc.call(*args, &block) end alias run call # Provides a wrapped proc that will update our `executed?` state when # executed. def to_proc method(:call).to_proc end def initialize(example, &block) @example = example @proc = block @executed = false end # @private def wrap(&block) self.class.new(example, &block) end # Indicates whether or not the around hook has executed the example. def executed? @executed end # @private def inspect @example.inspect.gsub('Example', 'Example::Procsy') end end # @private # # The exception that will be displayed to the user -- either the failure of # the example or the `pending_exception` if the example is pending. def display_exception @exception || execution_result.pending_exception end # @private # # Assigns the exception that will be displayed to the user -- either the failure of # the example or the `pending_exception` if the example is pending. def display_exception=(ex) if pending? && !(Pending::PendingExampleFixedError === ex) @exception = nil execution_result.pending_fixed = false execution_result.pending_exception = ex else @exception = ex end end # rubocop:disable Naming/AccessorMethodName # @private # # Used internally to set an exception in an after hook, which # captures the exception but doesn't raise it. def set_exception(exception) return self.display_exception = exception unless display_exception unless RSpec::Core::MultipleExceptionError === display_exception self.display_exception = RSpec::Core::MultipleExceptionError.new(display_exception) end display_exception.add exception end # @private # # Used to set the exception when `aggregate_failures` fails. def set_aggregate_failures_exception(exception) return set_exception(exception) unless display_exception exception = RSpec::Core::MultipleExceptionError::InterfaceTag.for(exception) exception.add display_exception self.display_exception = exception end # rubocop:enable Naming/AccessorMethodName # @private # # Used internally to set an exception and fail without actually executing # the example when an exception is raised in before(:context). def fail_with_exception(reporter, exception) start(reporter) set_exception(exception) finish(reporter) end # @private # # Used internally to skip without actually executing the example when # skip is used in before(:context). def skip_with_exception(reporter, exception) start(reporter) Pending.mark_skipped! self, exception.argument finish(reporter) end # @private def instance_exec(*args, &block) @example_group_instance.instance_exec(*args, &block) end private def hooks example_group_instance.singleton_class.hooks end def with_around_example_hooks RSpec.current_scope = :before_example_hook hooks.run(:around, :example, self) { yield } rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e set_exception(e) end def start(reporter) reporter.example_started(self) execution_result.started_at = clock.now end def finish(reporter) pending_message = execution_result.pending_message if @exception execution_result.exception = @exception record_finished :failed, reporter reporter.example_failed self false elsif pending_message execution_result.pending_message = pending_message record_finished :pending, reporter reporter.example_pending self true else record_finished :passed, reporter reporter.example_passed self true end end def record_finished(status, reporter) execution_result.record_finished(status, clock.now) reporter.example_finished(self) end def run_before_example @example_group_instance.setup_mocks_for_rspec hooks.run(:before, :example, self) end def with_around_and_singleton_context_hooks singleton_context_hooks_host = example_group_instance.singleton_class singleton_context_hooks_host.run_before_context_hooks(example_group_instance) with_around_example_hooks { yield } ensure singleton_context_hooks_host.run_after_context_hooks(example_group_instance) end def run_after_example assign_generated_description if defined?(::RSpec::Matchers) hooks.run(:after, :example, self) verify_mocks ensure @example_group_instance.teardown_mocks_for_rspec end def verify_mocks @example_group_instance.verify_mocks_for_rspec if mocks_need_verification? rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e set_exception(e) end def mocks_need_verification? exception.nil? || execution_result.pending_fixed? end def assign_generated_description if metadata[:description].empty? && (description = generate_description) metadata[:description] = description metadata[:full_description] += description end ensure RSpec::Matchers.clear_generated_description end def generate_description RSpec::Matchers.generated_description rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e location_description + " (Got an error when generating description " \ "from matcher: #{e.class}: #{e.message} -- #{e.backtrace.first})" end def location_description "example at #{location}" end # Represents the result of executing an example. # Behaves like a hash for backwards compatibility. class ExecutionResult include HashImitatable # @return [Symbol] `:passed`, `:failed` or `:pending`. attr_accessor :status # @return [Exception, nil] The failure, if there was one. attr_accessor :exception # @return [Time] When the example started. attr_accessor :started_at # @return [Time] When the example finished. attr_accessor :finished_at # @return [Float] How long the example took in seconds. attr_accessor :run_time # @return [String, nil] The reason the example was pending, # or nil if the example was not pending. attr_accessor :pending_message # @return [Exception, nil] The exception triggered while # executing the pending example. If no exception was triggered # it would no longer get a status of `:pending` unless it was # tagged with `:skip`. attr_accessor :pending_exception # @return [Boolean] For examples tagged with `:pending`, # this indicates whether or not it now passes. attr_accessor :pending_fixed def pending_fixed? !!pending_fixed end # @return [Boolean] Indicates if the example was completely skipped # (typically done via `:skip` metadata or the `skip` method). Skipped examples # will have a `:pending` result. A `:pending` result can also come from examples # that were marked as `:pending`, which causes them to be run, and produces a # `:failed` result if the example passes. def example_skipped? status == :pending && !pending_exception end # @api private # Records the finished status of the example. def record_finished(status, finished_at) self.status = status calculate_run_time(finished_at) end # @api private # Populates finished_at and run_time if it has not yet been set def ensure_timing_set(clock) calculate_run_time(clock.now) unless finished_at end private def calculate_run_time(finished_at) self.finished_at = finished_at self.run_time = (finished_at - started_at).to_f end # For backwards compatibility we present `status` as a string # when presenting the legacy hash interface. def hash_for_delegation super.tap do |hash| hash[:status] &&= status.to_s end end def set_value(name, value) value &&= value.to_sym if name == :status super(name, value) end def get_value(name) if name == :status status.to_s if status else super end end def issue_deprecation(_method_name, *_args) RSpec.deprecate("Treating `metadata[:execution_result]` as a hash", :replacement => "the attributes methods to access the data") end end end # @private # Provides an execution context for before/after :suite hooks. class SuiteHookContext < Example def initialize(hook_description, reporter) super(AnonymousExampleGroup, hook_description, {}) @example_group_instance = AnonymousExampleGroup.new @reporter = reporter end # rubocop:disable Naming/AccessorMethodName def set_exception(exception) reporter.notify_non_example_exception(exception, "An error occurred in #{description}.") RSpec.world.wants_to_quit = true end # rubocop:enable Naming/AccessorMethodName end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/warnings.rb0000664000000000000000000000177614557677674023663 0ustar rootrootrequire "rspec/support/warnings" module RSpec module Core # @private module Warnings # @private # # Used internally to print deprecation warnings. def deprecate(deprecated, data={}) RSpec.configuration.reporter.deprecation( { :deprecated => deprecated, :call_site => CallerFilter.first_non_rspec_line }.merge(data) ) end # @private # # Used internally to print deprecation warnings. def warn_deprecation(message, opts={}) RSpec.configuration.reporter.deprecation opts.merge(:message => message) end # @private def warn_with(message, options={}) if options[:use_spec_location_as_call_site] message += "." unless message.end_with?(".") if RSpec.current_example message += " Warning generated from spec at `#{RSpec.current_example.location}`." end end super(message, options) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/filter_manager.rb0000664000000000000000000001430614557677674025003 0ustar rootrootmodule RSpec module Core # @private class FilterManager attr_reader :exclusions, :inclusions def initialize @exclusions, @inclusions = FilterRules.build end # @api private # # @param file_path [String] # @param line_numbers [Array] def add_location(file_path, line_numbers) # locations is a hash of expanded paths to arrays of line # numbers to match against. e.g. # { "path/to/file.rb" => [37, 42] } add_path_to_arrays_filter(:locations, File.expand_path(file_path), line_numbers) end def add_ids(rerun_path, scoped_ids) # ids is a hash of relative paths to arrays of ids # to match against. e.g. # { "./path/to/file.rb" => ["1:1", "2:4"] } rerun_path = Metadata.relative_path(File.expand_path rerun_path) add_path_to_arrays_filter(:ids, rerun_path, scoped_ids) end def empty? inclusions.empty? && exclusions.empty? end def prune(examples) # Semantically, this is unnecessary (the filtering below will return the empty # array unmodified), but for perf reasons it's worth exiting early here. Users # commonly have top-level examples groups that do not have any direct examples # and instead have nested groups with examples. In that kind of situation, # `examples` will be empty. return examples if examples.empty? examples = prune_conditionally_filtered_examples(examples) if inclusions.standalone? examples.select { |e| inclusions.include_example?(e) } else locations, ids, non_scoped_inclusions = inclusions.split_file_scoped_rules examples.select do |ex| file_scoped_include?(ex.metadata, ids, locations) do !exclusions.include_example?(ex) && non_scoped_inclusions.include_example?(ex) end end end end def exclude(*args) exclusions.add(args.last) end def exclude_only(*args) exclusions.use_only(args.last) end def exclude_with_low_priority(*args) exclusions.add_with_low_priority(args.last) end def include(*args) inclusions.add(args.last) end def include_only(*args) inclusions.use_only(args.last) end def include_with_low_priority(*args) inclusions.add_with_low_priority(args.last) end private def add_path_to_arrays_filter(filter_key, path, values) filter = inclusions.delete(filter_key) || Hash.new { |h, k| h[k] = [] } filter[path].concat(values) inclusions.add(filter_key => filter) end def prune_conditionally_filtered_examples(examples) examples.reject do |ex| meta = ex.metadata !meta.fetch(:if, true) || meta[:unless] end end # When a user specifies a particular spec location, that takes priority # over any exclusion filters (such as if the spec is tagged with `:slow` # and there is a `:slow => true` exclusion filter), but only for specs # defined in the same file as the location filters. Excluded specs in # other files should still be excluded. def file_scoped_include?(ex_metadata, ids, locations) no_id_filters = ids[ex_metadata[:rerun_file_path]].empty? no_location_filters = locations[ File.expand_path(ex_metadata[:rerun_file_path]) ].empty? return yield if no_location_filters && no_id_filters MetadataFilter.filter_applies?(:ids, ids, ex_metadata) || MetadataFilter.filter_applies?(:locations, locations, ex_metadata) end end # @private class FilterRules PROC_HEX_NUMBER = /0x[0-9a-f]+@?/ PROJECT_DIR = File.expand_path('.') attr_accessor :opposite attr_reader :rules def self.build exclusions = ExclusionRules.new inclusions = InclusionRules.new exclusions.opposite = inclusions inclusions.opposite = exclusions [exclusions, inclusions] end def initialize(rules={}) @rules = rules end def add(updated) @rules.merge!(updated).each_key { |k| opposite.delete(k) } end def add_with_low_priority(updated) updated = updated.merge(@rules) opposite.each_pair { |k, v| updated.delete(k) if updated[k] == v } @rules.replace(updated) end def use_only(updated) updated.each_key { |k| opposite.delete(k) } @rules.replace(updated) end def clear @rules.clear end def delete(key) @rules.delete(key) end def fetch(*args, &block) @rules.fetch(*args, &block) end def [](key) @rules[key] end def empty? rules.empty? end def each_pair(&block) @rules.each_pair(&block) end def description rules.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)', '') end def include_example?(example) MetadataFilter.apply?(:any?, @rules, example.metadata) end end # @private ExclusionRules = FilterRules # @private class InclusionRules < FilterRules def add(*args) apply_standalone_filter(*args) || super end def add_with_low_priority(*args) apply_standalone_filter(*args) || super end def include_example?(example) @rules.empty? || super end def standalone? is_standalone_filter?(@rules) end def split_file_scoped_rules rules_dup = @rules.dup locations = rules_dup.delete(:locations) { Hash.new([]) } ids = rules_dup.delete(:ids) { Hash.new([]) } return locations, ids, self.class.new(rules_dup) end private def apply_standalone_filter(updated) return true if standalone? return nil unless is_standalone_filter?(updated) replace_filters(updated) true end def replace_filters(new_rules) @rules.replace(new_rules) opposite.clear end def is_standalone_filter?(rules) rules.key?(:full_description) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/metadata.rb0000664000000000000000000004202214557677674023600 0ustar rootrootmodule RSpec module Core # Each ExampleGroup class and Example instance owns an instance of # Metadata, which is Hash extended to support lazy evaluation of values # associated with keys that may or may not be used by any example or group. # # In addition to metadata that is used internally, this also stores # user-supplied metadata, e.g. # # RSpec.describe Something, :type => :ui do # it "does something", :slow => true do # # ... # end # end # # `:type => :ui` is stored in the Metadata owned by the example group, and # `:slow => true` is stored in the Metadata owned by the example. These can # then be used to select which examples are run using the `--tag` option on # the command line, or several methods on `Configuration` used to filter a # run (e.g. `filter_run_including`, `filter_run_excluding`, etc). # # @see Example#metadata # @see ExampleGroup.metadata # @see FilterManager # @see Configuration#filter_run_including # @see Configuration#filter_run_excluding module Metadata # Matches strings either at the beginning of the input or prefixed with a # whitespace, containing the current path, either postfixed with the # separator, or at the end of the string. Match groups are the character # before and the character after the string if any. # # http://rubular.com/r/fT0gmX6VJX # http://rubular.com/r/duOrD4i3wb # http://rubular.com/r/sbAMHFrOx1 def self.relative_path_regex @relative_path_regex ||= /(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/ end # @api private # # @param line [String] current code line # @return [String] relative path to line def self.relative_path(line) line = line.sub(relative_path_regex, "\\1.\\2".freeze) line = line.sub(/\A([^:]+:\d+)$/, '\\1'.freeze) return nil if line == '-e:1'.freeze line rescue SecurityError # :nocov: nil # :nocov: end # @private # Iteratively walks up from the given metadata through all # example group ancestors, yielding each metadata hash along the way. def self.ascending(metadata) yield metadata return unless (group_metadata = metadata.fetch(:example_group) { metadata[:parent_example_group] }) loop do yield group_metadata break unless (group_metadata = group_metadata[:parent_example_group]) end end # @private # Returns an enumerator that iteratively walks up the given metadata through all # example group ancestors, yielding each metadata hash along the way. def self.ascend(metadata) enum_for(:ascending, metadata) end # @private # Used internally to build a hash from an args array. # Symbols are converted into hash keys with a value of `true`. # This is done to support simple tagging using a symbol, rather # than needing to do `:symbol => true`. def self.build_hash_from(args, warn_about_example_group_filtering=false) hash = args.last.is_a?(Hash) ? args.pop : {} hash[args.pop] = true while args.last.is_a?(Symbol) if warn_about_example_group_filtering && hash.key?(:example_group) RSpec.deprecate("Filtering by an `:example_group` subhash", :replacement => "the subhash to filter directly") end hash end # @private def self.deep_hash_dup(object) return object.dup if Array === object return object unless Hash === object object.inject(object.dup) do |duplicate, (key, value)| duplicate[key] = deep_hash_dup(value) duplicate end end # @private def self.id_from(metadata) "#{metadata[:rerun_file_path]}[#{metadata[:scoped_id]}]" end # @private def self.location_tuple_from(metadata) [metadata[:absolute_file_path], metadata[:line_number]] end # @private # Used internally to populate metadata hashes with computed keys # managed by RSpec. class HashPopulator attr_reader :metadata, :user_metadata, :description_args, :block def initialize(metadata, user_metadata, index_provider, description_args, block) @metadata = metadata @user_metadata = user_metadata @index_provider = index_provider @description_args = description_args @block = block end def populate ensure_valid_user_keys metadata[:block] = block metadata[:description_args] = description_args metadata[:description] = build_description_from(*metadata[:description_args]) metadata[:full_description] = full_description metadata[:described_class] = described_class populate_location_attributes metadata.update(user_metadata) end private def populate_location_attributes backtrace = user_metadata.delete(:caller) file_path, line_number = if backtrace file_path_and_line_number_from(backtrace) elsif block.respond_to?(:source_location) block.source_location else file_path_and_line_number_from(caller) end relative_file_path = Metadata.relative_path(file_path) absolute_file_path = File.expand_path(relative_file_path) metadata[:file_path] = relative_file_path metadata[:line_number] = line_number.to_i metadata[:location] = "#{relative_file_path}:#{line_number}" metadata[:absolute_file_path] = absolute_file_path metadata[:rerun_file_path] ||= relative_file_path metadata[:scoped_id] = build_scoped_id_for(absolute_file_path) end def file_path_and_line_number_from(backtrace) first_caller_from_outside_rspec = backtrace.find { |l| l !~ CallerFilter::LIB_REGEX } first_caller_from_outside_rspec ||= backtrace.first /(.+?):(\d+)(?:|:\d+)/.match(first_caller_from_outside_rspec).captures end def description_separator(parent_part, child_part) if parent_part.is_a?(Module) && /^(?:#|::|\.)/.match(child_part.to_s) ''.freeze else ' '.freeze end end def build_description_from(parent_description=nil, my_description=nil) return parent_description.to_s unless my_description return my_description.to_s if parent_description.to_s == '' separator = description_separator(parent_description, my_description) (parent_description.to_s + separator) << my_description.to_s end def build_scoped_id_for(file_path) index = @index_provider.call(file_path).to_s parent_scoped_id = metadata.fetch(:scoped_id) { return index } "#{parent_scoped_id}:#{index}" end def ensure_valid_user_keys RESERVED_KEYS.each do |key| next unless user_metadata.key?(key) raise <<-EOM.gsub(/^\s+\|/, '') |#{"*" * 50} |:#{key} is not allowed | |RSpec reserves some hash keys for its own internal use, |including :#{key}, which is used on: | | #{CallerFilter.first_non_rspec_line}. | |Here are all of RSpec's reserved hash keys: | | #{RESERVED_KEYS.join("\n ")} |#{"*" * 50} EOM end end end # @private class ExampleHash < HashPopulator def self.create(group_metadata, user_metadata, index_provider, description, block) example_metadata = group_metadata.dup group_metadata = Hash.new(&ExampleGroupHash.backwards_compatibility_default_proc do |hash| hash[:parent_example_group] end) group_metadata.update(example_metadata) example_metadata[:execution_result] = Example::ExecutionResult.new example_metadata[:example_group] = group_metadata example_metadata[:shared_group_inclusion_backtrace] = SharedExampleGroupInclusionStackFrame.current_backtrace example_metadata.delete(:parent_example_group) description_args = description.nil? ? [] : [description] hash = new(example_metadata, user_metadata, index_provider, description_args, block) hash.populate hash.metadata end private def described_class metadata[:example_group][:described_class] end def full_description build_description_from( metadata[:example_group][:full_description], metadata[:description] ) end end # @private class ExampleGroupHash < HashPopulator def self.create(parent_group_metadata, user_metadata, example_group_index, *args, &block) group_metadata = hash_with_backwards_compatibility_default_proc if parent_group_metadata group_metadata.update(parent_group_metadata) group_metadata[:parent_example_group] = parent_group_metadata end hash = new(group_metadata, user_metadata, example_group_index, args, block) hash.populate hash.metadata end def self.hash_with_backwards_compatibility_default_proc Hash.new(&backwards_compatibility_default_proc { |hash| hash }) end def self.backwards_compatibility_default_proc(&example_group_selector) Proc.new do |hash, key| case key when :example_group # We commonly get here when rspec-core is applying a previously # configured filter rule, such as when a gem configures: # # RSpec.configure do |c| # c.include MyGemHelpers, :example_group => { :file_path => /spec\/my_gem_specs/ } # end # # It's confusing for a user to get a deprecation at this point in # the code, so instead we issue a deprecation from the config APIs # that take a metadata hash, and MetadataFilter sets this thread # local to silence the warning here since it would be so # confusing. unless RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations] RSpec.deprecate("The `:example_group` key in an example group's metadata hash", :replacement => "the example group's hash directly for the " \ "computed keys and `:parent_example_group` to access the parent " \ "example group metadata") end group_hash = example_group_selector.call(hash) LegacyExampleGroupHash.new(group_hash) if group_hash when :example_group_block RSpec.deprecate("`metadata[:example_group_block]`", :replacement => "`metadata[:block]`") hash[:block] when :describes RSpec.deprecate("`metadata[:describes]`", :replacement => "`metadata[:described_class]`") hash[:described_class] end end end private def described_class candidate = metadata[:description_args].first return candidate unless NilClass === candidate || String === candidate parent_group = metadata[:parent_example_group] parent_group && parent_group[:described_class] end def full_description description = metadata[:description] parent_example_group = metadata[:parent_example_group] return description unless parent_example_group parent_description = parent_example_group[:full_description] separator = description_separator(parent_example_group[:description_args].last, metadata[:description_args].first) parent_description + separator + description end end # @private RESERVED_KEYS = [ :description, :description_args, :described_class, :example_group, :parent_example_group, :execution_result, :last_run_status, :file_path, :absolute_file_path, :rerun_file_path, :full_description, :line_number, :location, :scoped_id, :block, :shared_group_inclusion_backtrace ] end # Mixin that makes the including class imitate a hash for backwards # compatibility. The including class should use `attr_accessor` to # declare attributes. # @private module HashImitatable def self.included(klass) klass.extend ClassMethods end def to_h hash = extra_hash_attributes.dup self.class.hash_attribute_names.each do |name| hash[name] = __send__(name) end hash end (Hash.public_instance_methods - Object.public_instance_methods).each do |method_name| next if [:[], :[]=, :to_h].include?(method_name.to_sym) define_method(method_name) do |*args, &block| issue_deprecation(method_name, *args) hash = hash_for_delegation self.class.hash_attribute_names.each do |name| hash.delete(name) unless instance_variable_defined?(:"@#{name}") end hash.__send__(method_name, *args, &block).tap do # apply mutations back to the object hash.each do |name, value| if directly_supports_attribute?(name) set_value(name, value) else extra_hash_attributes[name] = value end end end end end def [](key) issue_deprecation(:[], key) if directly_supports_attribute?(key) get_value(key) else extra_hash_attributes[key] end end def []=(key, value) issue_deprecation(:[]=, key, value) if directly_supports_attribute?(key) set_value(key, value) else extra_hash_attributes[key] = value end end private def extra_hash_attributes @extra_hash_attributes ||= {} end def directly_supports_attribute?(name) self.class.hash_attribute_names.include?(name) end def get_value(name) __send__(name) end def set_value(name, value) __send__(:"#{name}=", value) end def hash_for_delegation to_h end def issue_deprecation(_method_name, *_args) # no-op by default: subclasses can override end # @private module ClassMethods def hash_attribute_names @hash_attribute_names ||= [] end def attr_accessor(*names) hash_attribute_names.concat(names) super end end end # @private # Together with the example group metadata hash default block, # provides backwards compatibility for the old `:example_group` # key. In RSpec 2.x, the computed keys of a group's metadata # were exposed from a nested subhash keyed by `[:example_group]`, and # then the parent group's metadata was exposed by sub-subhash # keyed by `[:example_group][:example_group]`. # # In RSpec 3, we reorganized this to that the computed keys are # exposed directly of the group metadata hash (no nesting), and # `:parent_example_group` returns the parent group's metadata. # # Maintaining backwards compatibility was difficult: we wanted # `:example_group` to return an object that: # # * Exposes the top-level metadata keys that used to be nested # under `:example_group`. # * Supports mutation (rspec-rails, for example, assigns # `metadata[:example_group][:described_class]` when you use # anonymous controller specs) such that changes are written # back to the top-level metadata hash. # * Exposes the parent group metadata as # `[:example_group][:example_group]`. class LegacyExampleGroupHash include HashImitatable def initialize(metadata) @metadata = metadata parent_group_metadata = metadata.fetch(:parent_example_group) { {} }[:example_group] self[:example_group] = parent_group_metadata if parent_group_metadata end def to_h super.merge(@metadata) end private def directly_supports_attribute?(name) name != :example_group end def get_value(name) @metadata[name] end def set_value(name, value) @metadata[name] = value end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/backtrace_formatter.rb0000664000000000000000000000373714557677674026034 0ustar rootrootmodule RSpec module Core # @private class BacktraceFormatter # @private attr_accessor :exclusion_patterns, :inclusion_patterns def initialize @full_backtrace = false patterns = %w[ /lib\d*/ruby/ bin/ exe/rspec /lib/bundler/ /exe/bundle: ] patterns << "org/jruby/" if RUBY_PLATFORM == 'java' patterns.map! { |s| Regexp.new(s.gsub("/", File::SEPARATOR)) } @exclusion_patterns = [Regexp.union(RSpec::CallerFilter::IGNORE_REGEX, *patterns)] @inclusion_patterns = [] return unless matches?(@exclusion_patterns, File.join(Dir.getwd, "lib", "foo.rb:13")) inclusion_patterns << Regexp.new(Dir.getwd) end attr_writer :full_backtrace def full_backtrace? @full_backtrace || exclusion_patterns.empty? end def filter_gem(gem_name) sep = File::SEPARATOR exclusion_patterns << /#{sep}#{gem_name}(-[^#{sep}]+)?#{sep}/ end def format_backtrace(backtrace, options={}) return [] unless backtrace return backtrace if options[:full_backtrace] || backtrace.empty? backtrace.map { |l| backtrace_line(l) }.compact. tap do |filtered| if filtered.empty? filtered.concat backtrace filtered << "" filtered << " Showing full backtrace because every line was filtered out." filtered << " See docs for RSpec::Configuration#backtrace_exclusion_patterns and" filtered << " RSpec::Configuration#backtrace_inclusion_patterns for more information." end end end def backtrace_line(line) Metadata.relative_path(line) unless exclude?(line) end def exclude?(line) return false if @full_backtrace matches?(exclusion_patterns, line) && !matches?(inclusion_patterns, line) end private def matches?(patterns, line) patterns.any? { |p| line =~ p } end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/shell_escape.rb0000664000000000000000000000302314557677674024445 0ustar rootrootmodule RSpec module Core # @private # Deals with the fact that `shellwords` only works on POSIX systems. module ShellEscape module_function def quote(argument) "'#{argument.to_s.gsub("'", "\\\\'")}'" end if RSpec::Support::OS.windows? # :nocov: alias escape quote # :nocov: else require 'shellwords' def escape(shell_command) Shellwords.escape(shell_command.to_s) end end # Known shells that require quoting: zsh, csh, tcsh. # # Feel free to add other shells to this list that are known to # allow `rspec ./some_spec.rb[1:1]` syntax without quoting the id. # # @private SHELLS_ALLOWING_UNQUOTED_IDS = %w[ bash ksh fish ] def conditionally_quote(id) return id if shell_allows_unquoted_ids? quote(id) end def shell_allows_unquoted_ids? # Note: ENV['SHELL'] isn't necessarily the shell the user is currently running. # According to http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html: # "This variable shall represent a pathname of the user's preferred command language interpreter." # # It's the best we can easily do, though. We err on the side of safety (quoting # the id when not actually needed) so it's not a big deal if the user is actually # using a different shell. SHELLS_ALLOWING_UNQUOTED_IDS.include?(ENV['SHELL'].to_s.split('/').last) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/project_initializer.rb0000664000000000000000000000242214557677674026071 0ustar rootrootRSpec::Support.require_rspec_support "directory_maker" module RSpec module Core # @private # Generates conventional files for an RSpec project. class ProjectInitializer attr_reader :destination, :stream, :template_path DOT_RSPEC_FILE = '.rspec' SPEC_HELPER_FILE = 'spec/spec_helper.rb' def initialize(opts={}) @destination = opts.fetch(:destination, Dir.getwd) @stream = opts.fetch(:report_stream, $stdout) @template_path = opts.fetch(:template_path) do File.expand_path("../project_initializer", __FILE__) end end def run copy_template DOT_RSPEC_FILE copy_template SPEC_HELPER_FILE end private def copy_template(file) destination_file = File.join(destination, file) return report_exists(file) if File.exist?(destination_file) report_creating(file) RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(destination_file)) File.open(destination_file, 'w') do |f| f.write File.read(File.join(template_path, file)) end end def report_exists(file) stream.puts " exist #{file}" end def report_creating(file) stream.puts " create #{file}" end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/did_you_mean.rb0000664000000000000000000000252314557677674024456 0ustar rootrootmodule RSpec module Core # @private # Wrapper around Ruby's `DidYouMean::SpellChecker` when available to provide file name suggestions. class DidYouMean attr_reader :relative_file_name def initialize(relative_file_name) @relative_file_name = relative_file_name end if defined?(::DidYouMean::SpellChecker) # provide probable suggestions def call checker = ::DidYouMean::SpellChecker.new(:dictionary => Dir["spec/**/*.rb"]) probables = checker.correct(relative_file_name.sub('./', ''))[0..2] return '' unless probables.any? formats probables end else # return a hint if API for ::DidYouMean::SpellChecker not supported def call "\nHint: Install the `did_you_mean` gem in order to provide suggestions for similarly named files." end end private def formats(probables) rspec_format = probables.map { |s, _| "rspec ./#{s}" } red_font(top_and_tail rspec_format) end def top_and_tail(rspec_format) spaces = ' ' * 20 rspec_format.insert(0, ' - Did you mean?').join("\n#{spaces}") + "\n" end def red_font(mytext) colorizer = ::RSpec::Core::Formatters::ConsoleCodes colorizer.wrap mytext, :failure end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core/dsl.rb0000664000000000000000000000550514557677674022607 0ustar rootrootmodule RSpec module Core # DSL defines methods to group examples, most notably `describe`, # and exposes them as class methods of {RSpec}. They can also be # exposed globally (on `main` and instances of `Module`) through # the {Configuration} option `expose_dsl_globally`. # # By default the methods `describe`, `context` and `example_group` # are exposed. These methods define a named context for one or # more examples. The given block is evaluated in the context of # a generated subclass of {RSpec::Core::ExampleGroup}. # # ## Examples: # # RSpec.describe "something" do # context "when something is a certain way" do # it "does something" do # # example code goes here # end # end # end # # @see ExampleGroup # @see ExampleGroup.example_group module DSL # @private def self.example_group_aliases @example_group_aliases ||= [] end # @private def self.exposed_globally? @exposed_globally ||= false end # @private def self.expose_example_group_alias(name) return if example_group_aliases.include?(name) example_group_aliases << name (class << RSpec; self; end).__send__(:define_method, name) do |*args, &example_group_block| group = RSpec::Core::ExampleGroup.__send__(name, *args, &example_group_block) RSpec.world.record(group) group end expose_example_group_alias_globally(name) if exposed_globally? end class << self # @private attr_accessor :top_level end # Adds the describe method to Module and the top level binding. # @api private def self.expose_globally! return if exposed_globally? example_group_aliases.each do |method_name| expose_example_group_alias_globally(method_name) end @exposed_globally = true end # Removes the describe method from Module and the top level binding. # @api private def self.remove_globally! return unless exposed_globally? example_group_aliases.each do |method_name| change_global_dsl { undef_method method_name } end @exposed_globally = false end # @private def self.expose_example_group_alias_globally(method_name) change_global_dsl do remove_method(method_name) if method_defined?(method_name) define_method(method_name) { |*a, &b| ::RSpec.__send__(method_name, *a, &b) } end end # @private def self.change_global_dsl(&changes) (class << top_level; self; end).class_exec(&changes) Module.class_exec(&changes) end end end end # Capture main without an eval. ::RSpec::Core::DSL.top_level = self ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/core.rb0000664000000000000000000001464714557677674022034 0ustar rootroot# rubocop:disable Style/GlobalVars $_rspec_core_load_started_at = Time.now # rubocop:enable Style/GlobalVars require "rspec/support" RSpec::Support.require_rspec_support "caller_filter" RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative f } %w[ version warnings set flat_map filter_manager dsl notifications reporter hooks memoized_helpers metadata metadata_filter pending formatters ordering world configuration option_parser configuration_options runner invocations example shared_example_group example_group ].each { |name| RSpec::Support.require_rspec_core name } # Namespace for all core RSpec code. module RSpec autoload :SharedContext, 'rspec/core/shared_context' extend RSpec::Core::Warnings class << self # Setters for shared global objects # @api private attr_writer :configuration, :world end # Used to ensure examples get reloaded and user configuration gets reset to # defaults between multiple runs in the same process. # # Users must invoke this if they want to have the configuration reset when # they use the runner multiple times within the same process. Users must deal # themselves with re-configuration of RSpec before run. def self.reset RSpec::ExampleGroups.remove_all_constants @world = nil @configuration = nil end # Used to ensure examples get reloaded between multiple runs in the same # process and ensures user configuration is persisted. # # Users must invoke this if they want to clear all examples but preserve # current configuration when they use the runner multiple times within the # same process. def self.clear_examples world.reset configuration.reset_reporter configuration.start_time = ::RSpec::Core::Time.now configuration.reset_filters end # Returns the global [Configuration](RSpec/Core/Configuration) object. While # you _can_ use this method to access the configuration, the more common # convention is to use [RSpec.configure](RSpec#configure-class_method). # # @example # RSpec.configuration.drb_port = 1234 # @see RSpec.configure # @see Core::Configuration def self.configuration @configuration ||= RSpec::Core::Configuration.new end # Yields the global configuration to a block. # @yield [Configuration] global configuration # # @example # RSpec.configure do |config| # config.add_formatter 'documentation' # end # @see Core::Configuration def self.configure yield configuration if block_given? end # The example being executed. # # The primary audience for this method is library authors who need access # to the example currently being executed and also want to support all # versions of RSpec 2 and 3. # # @example # # RSpec.configure do |c| # # context.example is deprecated, but RSpec.current_example is not # # available until RSpec 3.0. # fetch_current_example = RSpec.respond_to?(:current_example) ? # proc { RSpec.current_example } : proc { |context| context.example } # # c.before(:example) do # example = fetch_current_example.call(self) # # # ... # end # end # def self.current_example RSpec::Support.thread_local_data[:current_example] end # Set the current example being executed. # @api private def self.current_example=(example) RSpec::Support.thread_local_data[:current_example] = example end # Set the current scope rspec is executing in # @api private def self.current_scope=(scope) RSpec::Support.thread_local_data[:current_scope] = scope end RSpec.current_scope = :suite # Get the current RSpec execution scope # # Returns (in order of lifecycle): # * `:suite` as an initial value, this is outside of the test lifecycle. # * `:before_suite_hook` during `before(:suite)` hooks. # * `:before_context_hook` during `before(:context)` hooks. # * `:before_example_hook` during `before(:example)` hooks and `around(:example)` before `example.run`. # * `:example` within the example run. # * `:after_example_hook` during `after(:example)` hooks and `around(:example)` after `example.run`. # * `:after_context_hook` during `after(:context)` hooks. # * `:after_suite_hook` during `after(:suite)` hooks. # * `:suite` as a final value, again this is outside of the test lifecycle. # # Reminder, `:context` hooks have `:all` alias and `:example` hooks have `:each` alias. # @return [Symbol] def self.current_scope RSpec::Support.thread_local_data[:current_scope] end # @private # Internal container for global non-configuration data. def self.world @world ||= RSpec::Core::World.new end # Namespace for the rspec-core code. module Core autoload :ExampleStatusPersister, "rspec/core/example_status_persister" autoload :Profiler, "rspec/core/profiler" autoload :DidYouMean, "rspec/core/did_you_mean" # @private # This avoids issues with reporting time caused by examples that # change the value/meaning of Time.now without properly restoring # it. class Time class << self define_method(:now, &::Time.method(:now)) end end # @private path to executable file. def self.path_to_executable @path_to_executable ||= File.expand_path('../../../exe/rspec', __FILE__) end end # @private MODULES_TO_AUTOLOAD = { :Matchers => "rspec/expectations", :Expectations => "rspec/expectations", :Mocks => "rspec/mocks" } # @private def self.const_missing(name) # Load rspec-expectations when RSpec::Matchers is referenced. This allows # people to define custom matchers (using `RSpec::Matchers.define`) before # rspec-core has loaded rspec-expectations (since it delays the loading of # it to allow users to configure a different assertion/expectation # framework). `autoload` can't be used since it works with ruby's built-in # require (e.g. for files that are available relative to a load path dir), # but not with rubygems' extended require. # # As of rspec 2.14.1, we no longer require `rspec/mocks` and # `rspec/expectations` when `rspec` is required, so we want # to make them available as an autoload. require MODULES_TO_AUTOLOAD.fetch(name) { return super } ::RSpec.const_get(name) end Core::DSL.expose_globally! Core::SharedExampleGroup::TopLevelDSL.expose_globally! end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-core/lib/rspec/autorun.rb0000664000000000000000000000012714557677674022565 0ustar rootrootrequire 'rspec/core' # Ensure the default config is loaded RSpec::Core::Runner.autorun ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/0000775000000000000000000000000014567461030020411 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/demo.rb0000664000000000000000000000031614557700001021653 0ustar rootrootrequire './lib/rspec/expectations' class IsolatedTest include RSpec::Matchers def test expect(nil).to(eq("")) end end RSpec::Expectations::Syntax.enable_expect(IsolatedTest) IsolatedTest.new.test ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.rubocop_rspec_base.yml0000664000000000000000000001500514557700001025043 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. # This file contains defaults for RSpec projects. Individual projects # can customize by inheriting this file and overriding particular settings. Layout/AccessModifierIndentation: Enabled: false # "Use alias_method instead of alias" # We're fine with `alias`. Style/Alias: Enabled: false # "Avoid the use of the case equality operator ===" # We prefer using `Class#===` over `Object#is_a?` because `Class#===` # is less likely to be monkey patched than `is_a?` on a user object. Style/CaseEquality: Enabled: false # Warns when the class is excessively long. Metrics/ClassLength: Max: 100 Style/CollectionMethods: PreferredMethods: reduce: 'inject' # Over time we'd like to get this down, but this is what we're at now. Metrics/CyclomaticComplexity: Max: 10 # We use YARD to enforce documentation. It works better than rubocop's # enforcement...rubocop complains about the places we re-open # `RSpec::Expectations` and `RSpec::Matchers` w/o having doc commments. Style/Documentation: Enabled: false # We still support 1.8.7 which requires trailing dots Layout/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: Enabled: false # each_with_object is unavailable on 1.8.7 so we have to disable this one. Style/EachWithObject: Enabled: false Style/FormatString: EnforcedStyle: percent # As long as we support ruby 1.8.7 we have to use hash rockets. Style/HashSyntax: EnforcedStyle: hash_rockets # We can't use the new lambda syntax, since we still support 1.8.7. Style/Lambda: Enabled: false # Over time we'd like to get this down, but this is what we're at now. Layout/LineLength: Max: 100 # Over time we'd like to get this down, but this is what we're at now. Metrics/MethodLength: Max: 15 # Who cares what we call the argument for binary operator methods? Naming/BinaryOperatorParameterName: Enabled: false Style/PercentLiteralDelimiters: PreferredDelimiters: '%': () # double-quoted string '%i': '[]' # array of symbols '%q': () # single-quoted string '%Q': () # double-quoted string '%r': '{}' # regular expression pattern '%s': () # a symbol '%w': '[]' # array of single-quoted strings '%W': '[]' # array of double-quoted strings '%x': () # a shell command as a string # We have too many special cases where we allow generator methods or prefer a # prefixed predicate due to it's improved readability. Naming/PredicateName: Enabled: false # On 1.8 `proc` is `lambda`, so we use `Proc.new` to ensure we get real procs on all supported versions. # http://batsov.com/articles/2014/02/04/the-elements-of-style-in-ruby-number-12-proc-vs-proc-dot-new/ Style/Proc: Enabled: false # Exceptions should be rescued with `Support::AllExceptionsExceptOnesWeMustNotRescue` Lint/RescueException: Enabled: true # We haven't adopted the `fail` to signal exceptions vs `raise` for re-raises convention. Style/SignalException: Enabled: false # We've tended to use no space, so it's less of a change to stick with that. Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space # We don't care about single vs double qoutes. Style/StringLiterals: Enabled: false # This rule favors constant names from the English standard library which we don't load. Style/SpecialGlobalVars: Enabled: false Style/TrailingCommaInArrayLiteral: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingCommaInArguments: Enabled: false Style/TrivialAccessors: AllowDSLWriters: true AllowPredicates: true ExactNameMatch: true Style/ParallelAssignment: Enabled: false Layout/EmptyLineBetweenDefs: Enabled: false Layout/FirstParameterIndentation: Enabled: false Layout/ParameterAlignment: EnforcedStyle: with_first_parameter Layout/SpaceInsideBlockBraces: Enabled: false Layout/SpaceInsideParens: Enabled: false Naming/ConstantName: Enabled: false Style/ClassCheck: Enabled: false Style/ConditionalAssignment: Enabled: false Style/EmptyMethod: Enabled: false Style/FormatStringToken: Enabled: false Style/GuardClause: Enabled: false Style/IdenticalConditionalBranches: Enabled: false Style/IfUnlessModifier: Enabled: false Style/IfUnlessModifierOfIfUnless: Enabled: false Lint/MissingSuper: Enabled: false Style/MissingRespondToMissing: Enabled: false Style/MixinUsage: Enabled: false Style/MultipleComparison: Enabled: false Style/MutableConstant: Enabled: false Style/NestedModifier: Enabled: false Style/NestedParenthesizedCalls: Enabled: false Style/NumericPredicate: Enabled: false Style/RedundantParentheses: Enabled: false Style/StringLiteralsInInterpolation: Enabled: false Style/SymbolArray: Enabled: false Style/SymbolProc: Enabled: false Style/YodaCondition: Enabled: false Style/ZeroLengthPredicate: Enabled: false Layout/ClosingParenthesisIndentation: Enabled: false Layout/ExtraSpacing: Enabled: false Layout/MultilineMethodCallBraceLayout: Enabled: false Layout/MultilineMethodCallIndentation: Enabled: false Layout/MultilineOperationIndentation: Enabled: false Layout/SpaceAroundBlockParameters: Enabled: false Layout/SpaceAroundOperators: Enabled: false Layout/SpaceBeforeComma: Enabled: false Style/BlockDelimiters: Enabled: false Style/EmptyCaseCondition: Enabled: false Style/MultilineIfModifier: Enabled: false Style/RescueStandardError: Enabled: false Style/StderrPuts: Enabled: false Style/TernaryParentheses: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Layout/AssignmentIndentation: Enabled: false Layout/EmptyLineAfterMagicComment: Enabled: false Layout/FirstArrayElementIndentation: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/SpaceInsidePercentLiteralDelimiters: Enabled: false Style/EmptyElse: Enabled: false Style/IfInsideElse: Enabled: false Style/RedundantReturn: Enabled: false Style/StructInheritance: Enabled: false Naming/VariableNumber: Enabled: false Layout/SpaceInsideStringInterpolation: Enabled: false Style/DateTime: Enabled: false Style/ParenthesesAroundCondition: Enabled: false Layout/EmptyLinesAroundBlockBody: Enabled: false Lint/ImplicitStringConcatenation: Enabled: false Lint/NestedMethodDefinition: Enabled: false Style/RegexpLiteral: Enabled: false Style/TrailingUnderscoreVariable: Enabled: false Layout/EmptyLinesAroundAccessModifier: Enabled: false ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/ISSUE_TEMPLATE.md0000664000000000000000000000103614557700001023107 0ustar rootroot ### Subject of the issue ### Your environment * Ruby version: * rspec-expectations version: ### Steps to reproduce ### Expected behavior ### Actual behavior ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/DEVELOPMENT.md0000664000000000000000000001156114557700001022512 0ustar rootroot # Development Setup Generally speaking, you only need to clone the project and install the dependencies with [Bundler](https://bundler.io/). You can either get a full RSpec development environment using [rspec-dev](https://github.com/rspec/rspec-dev#README) or you can set this project up individually. ## Setting up rspec-expectations individually For most contributors, setting up the project individually will be simpler. Unless you have a specific reason to use rspec-dev, we recommend using this approach. Clone the repo: ``` $ git clone git@github.com:rspec/rspec-expectations.git ``` Install the dependencies using [Bundler](https://bundler.io/): ``` $ cd rspec-expectations $ bundle install ``` To minimize boot time and to ensure we don't depend upon any extra dependencies loaded by Bundler, our CI builds avoid loading Bundler at runtime by using Bundler's [`--standalone option`](https://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone). While not strictly necessary (many/most of our contributors do not do this!), if you want to exactly reproduce our CI builds you'll want to do the same: ``` $ bundle install --standalone --binstubs ``` The `--binstubs` option creates the `bin/rspec` file that, like `bundle exec rspec`, will load all the versions specified in `Gemfile.lock` without loading bundler at runtime! ## Using rspec-dev See the [rspec-dev README](https://github.com/rspec/rspec-dev#README) for setup instructions. The rspec-dev project contains many rake tasks for helping manage an RSpec development environment, making it easy to do things like: * Change branches across all repos * Update all repos with the latest code from `main` * Cut a new release across all repos * Push out updated build scripts to all repos These sorts of tasks are essential for the RSpec maintainers but will probably be unnecessary complexity if you're just contributing to one repository. If you are getting setup to make your first contribution, we recommend you take the simpler route of setting up rspec-expectations individually. ## Gotcha: Version mismatch from sibling repos The [Gemfile](Gemfile) is designed to be flexible and support using the other RSpec repositories either from a local sibling directory (e.g. `../rspec-`) or, if there is no such directory, directly from git. This generally does the "right thing", but can be a gotcha in some situations. For example, if you are setting up `rspec-core`, and you happen to have an old clone of `rspec-expectations` in a sibling directory, it'll be used even though it might be months or years out of date, which can cause confusing failures. To avoid this problem, you can either `export USE_GIT_REPOS=1` to force the use of `:git` dependencies instead of local dependencies, or update the code in the sibling directory. rspec-dev contains rake tasks to help you keep all repos in sync. ## Extra Gems If you need additional gems for any tasks---such as `benchmark-ips` for benchmarking or `byebug` for debugging---you can create a `Gemfile-custom` file containing those gem declarations. The `Gemfile` evaluates that file if it exists, and it is git-ignored. # Running the build The [Travis CI build](https://travis-ci.org/rspec/rspec-expectations) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` See [build detail](BUILD_DETAIL.md) for more detail. # What to Expect To ensure high, uniform code quality, all code changes (including changes from the maintainers!) are subject to a pull request code review. We'll often ask for clarification or suggest alternate ways to do things. Our code reviews are intended to be a two-way conversation. Here's a short, non-exhaustive checklist of things we typically ask contributors to do before PRs are ready to merge. It can help get your PR merged faster if you do these in advance! - [ ] New behavior is covered by tests and all tests are passing. - [ ] No Ruby warnings are issued by your changes. - [ ] Documentation reflects changes and renders as intended. - [ ] RuboCop passes (e.g. `bundle exec rubocop lib`). - [ ] Commits are squashed into a reasonable number of logical changesets that tell an easy-to-follow story. - [ ] No changelog entry is necessary (we'll add it as part of the merge process!) # Adding Docs RSpec uses [YARD](https://yardoc.org/) for its API documentation. To ensure the docs render well, we recommend running a YARD server and viewing your edits in a browser. To run a YARD server: ``` $ bundle exec yard server --reload # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard server --reload ``` Then navigate to `localhost:8808` to view the rendered docs. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/0000775000000000000000000000000014557700001022517 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/cloning_matchers.rb0000664000000000000000000000047514557700001026371 0ustar rootrootrequire 'benchmark' require 'rspec/expectations' include RSpec::Matchers n = 1_000_000 matcher = eq(3) Benchmark.bm do |x| x.report do n.times { matcher.clone } end end __END__ We can do about 1000 clones per ms: user system total real 1.080000 0.030000 1.110000 ( 1.120009) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/output_stringio_vs_tempfile.rb0000664000000000000000000000173214557700001030722 0ustar rootrootrequire 'rubygems' require 'bundler/setup' require 'benchmark' require 'rspec/expectations' include RSpec::Matchers n = 100_000 Benchmark.bm(25) do |bm| bm.report("to_stdout with StringIO") do n.times { expect {}.not_to output('foo').to_stdout } end bm.report("to_stdout with Tempfile") do n.times { expect {}.not_to output('foo').to_stdout_from_any_process } end bm.report("to_stderr with StringIO") do n.times { expect {}.not_to output('foo').to_stderr } end bm.report("to_stderr with Tempfile") do n.times { expect {}.not_to output('foo').to_stderr_from_any_process } end end # user system total real # to_stdout with StringIO 0.470000 0.010000 0.480000 ( 0.467317) # to_stdout with Tempfile 8.920000 7.420000 16.340000 ( 16.355174) # to_stderr with StringIO 0.460000 0.000000 0.460000 ( 0.454059) # to_stderr with Tempfile 8.930000 7.560000 16.490000 ( 16.494696) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/autoload_v_require.rb0000664000000000000000000000115314557700001026735 0ustar rootrootrequire 'benchmark' n = 10 Benchmark.benchmark do |bm| 3.times do bm.report do n.times do `bin/rspec benchmarks/example_spec.rb` end end end end # Before autoloading matcher class files # 0.000000 0.010000 8.800000 ( 8.906383) # 0.010000 0.010000 8.880000 ( 8.980907) # 0.000000 0.010000 8.820000 ( 8.918083) # # After autoloading matcher class files # 0.000000 0.010000 8.610000 ( 8.701434) # 0.010000 0.010000 8.620000 ( 8.741811) # 0.000000 0.000000 8.580000 ( 8.677235) # # Roughly 2.5% improvement in load time (every bit counts!) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/example_spec.rb0000664000000000000000000000023014557700001025504 0ustar rootrootdescribe "something" do it "does something that passes" do 1.should eq(1) end it "does something that fails" do 1.should eq(2) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/method_to_proc.rb0000664000000000000000000000420014557700001026045 0ustar rootrootrequire 'benchmark' n = 10_000_000 puts "3 runs of #{n} times running #{RUBY_ENGINE}/#{RUBY_VERSION}" def foo(x); end def extract_method_proc(&b); b; end Benchmark.benchmark do |bm| puts "calling foo = method(:foo).to_proc" foo_proc = method(:foo).to_proc 3.times do bm.report do n.times { foo_proc.call(1) } end end puts "calling Proc.new { |x| foo(x) }" foo_proc = extract_method_proc { |x| foo(x) } 3.times do bm.report do n.times { foo_proc.call(1) } end end end __END__ Surprisingly, `Method#to_proc` is slower, except on 1.9.3 where it's a wash. 3 runs of 10000000 times running ruby/2.1.1 calling foo = method(:foo).to_proc 2.190000 0.010000 2.200000 ( 2.206627) 2.370000 0.010000 2.380000 ( 2.391100) 2.190000 0.000000 2.190000 ( 2.193119) calling Proc.new { |x| foo(x) } 1.640000 0.000000 1.640000 ( 1.648841) 1.610000 0.000000 1.610000 ( 1.617186) 1.590000 0.010000 1.600000 ( 1.600570) 3 runs of 10000000 times running ruby/2.0.0 calling foo = method(:foo).to_proc 2.170000 0.010000 2.180000 ( 2.192418) 2.140000 0.000000 2.140000 ( 2.141015) 2.150000 0.010000 2.160000 ( 2.172794) calling Proc.new { |x| foo(x) } 1.680000 0.000000 1.680000 ( 1.686904) 1.650000 0.000000 1.650000 ( 1.654465) 1.640000 0.000000 1.640000 ( 1.648229) 3 runs of 10000000 times running ruby/1.9.3 calling foo = method(:foo).to_proc 2.440000 0.010000 2.450000 ( 2.457211) 2.430000 0.000000 2.430000 ( 2.450140) 2.480000 0.010000 2.490000 ( 2.496520) calling Proc.new { |x| foo(x) } 2.400000 0.000000 2.400000 ( 2.415641) 2.480000 0.000000 2.480000 ( 2.489564) 2.460000 0.000000 2.460000 ( 2.477368) 3 runs of 10000000 times running ruby/1.9.2 calling foo = method(:foo).to_proc 2.490000 0.010000 2.500000 ( 2.502401) 2.580000 0.000000 2.580000 ( 2.589306) 2.310000 0.010000 2.320000 ( 2.328342) calling Proc.new { |x| foo(x) } 1.860000 0.000000 1.860000 ( 1.866537) 1.860000 0.000000 1.860000 ( 1.871056) 1.850000 0.010000 1.860000 ( 1.857426) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/caller_vs_raise_for_backtrace.rb0000664000000000000000000000411514557700001031047 0ustar rootrootrequire 'benchmark/ips' def create_stack_trace(n, &block) return create_stack_trace(n - 1, &block) if n > 0 yield end [10, 50, 100].each do |frames| create_stack_trace(frames) do Benchmark.ips do |x| x.report("use caller (#{caller.count} frames)") do exception = RuntimeError.new("boom") exception.set_backtrace caller exception.backtrace end x.report("use raise (#{caller.count} frames)") do exception = begin raise "boom" rescue => e e end exception.backtrace end x.compare! end end end __END__ Calculating ------------------------------------- use caller (16 frames) 4.986k i/100ms use raise (16 frames) 4.255k i/100ms ------------------------------------------------- use caller (16 frames) 52.927k (± 9.9%) i/s - 264.258k use raise (16 frames) 50.079k (±10.1%) i/s - 251.045k Comparison: use caller (16 frames): 52927.3 i/s use raise (16 frames): 50078.6 i/s - 1.06x slower Calculating ------------------------------------- use caller (56 frames) 2.145k i/100ms use raise (56 frames) 2.065k i/100ms ------------------------------------------------- use caller (56 frames) 22.282k (± 9.3%) i/s - 111.540k use raise (56 frames) 21.428k (± 9.9%) i/s - 107.380k Comparison: use caller (56 frames): 22281.5 i/s use raise (56 frames): 21428.1 i/s - 1.04x slower Calculating ------------------------------------- use caller (106 frames) 1.284k i/100ms use raise (106 frames) 1.253k i/100ms ------------------------------------------------- use caller (106 frames) 12.437k (±10.6%) i/s - 62.916k use raise (106 frames) 10.873k (±12.6%) i/s - 53.879k Comparison: use caller (106 frames): 12437.4 i/s use raise (106 frames): 10873.2 i/s - 1.14x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/include_v_superclass.rb0000664000000000000000000000134114557700001027257 0ustar rootrootrequire 'benchmark' n = 10_000 class Foo; end module Bar; end Benchmark.benchmark do |bm| puts "Class.new(Foo)" 3.times do bm.report do n.times do Class.new(Foo) end end end puts "Class.new { include Bar }" 3.times do bm.report do n.times do Class.new { include Bar } end end end end # $ ruby benchmarks/include_v_superclass.rb # Class.new(Foo) # 0.030000 0.000000 0.030000 ( 0.033536) # 0.020000 0.000000 0.020000 ( 0.022077) # 0.040000 0.010000 0.050000 ( 0.035813) # Class.new { include Bar } # 0.040000 0.000000 0.040000 ( 0.041427) # 0.040000 0.000000 0.040000 ( 0.039019) # 0.030000 0.000000 0.030000 ( 0.037018) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/count_vs_select_size.rb0000664000000000000000000000536414557700001027305 0ustar rootrootrequire 'benchmark/ips' [10, 100, 1000, 10_000, 100_000].each do |array_size| array = (1..array_size).to_a Benchmark.ips do |ips| ips.report("#select { true }.size for #{array_size}") do array.select { true }.size end ips.report("#count { true } for #{array_size}") do array.count { true } end end end __END__ ruby benchmarks/count_vs_select_size.rb (git)-[main] Warming up -------------------------------------- #select { true }.size for 10 129.033k i/100ms #count { true } for 10 168.627k i/100ms Calculating ------------------------------------- #select { true }.size for 10 1.397M (± 6.8%) i/s - 6.968M in 5.011533s #count { true } for 10 1.716M (± 7.8%) i/s - 8.600M in 5.048212s Warming up -------------------------------------- #select { true }.size for 100 16.633k i/100ms #count { true } for 100 19.215k i/100ms Calculating ------------------------------------- #select { true }.size for 100 170.209k (± 8.1%) i/s - 848.283k in 5.036749s #count { true } for 100 212.102k (± 4.1%) i/s - 1.076M in 5.081653s Warming up -------------------------------------- #select { true }.size for 1000 1.650k i/100ms #count { true } for 1000 1.803k i/100ms Calculating ------------------------------------- #select { true }.size for 1000 15.651k (±17.0%) i/s - 75.900k in 5.073128s #count { true } for 1000 20.613k (± 5.6%) i/s - 104.574k in 5.091257s Warming up -------------------------------------- #select { true }.size for 10000 146.000 i/100ms #count { true } for 10000 202.000 i/100ms Calculating ------------------------------------- #select { true }.size for 10000 1.613k (± 8.4%) i/s - 8.030k in 5.014577s #count { true } for 10000 2.031k (± 4.8%) i/s - 10.302k in 5.085695s Warming up -------------------------------------- #select { true }.size for 100000 15.000 i/100ms #count { true } for 100000 21.000 i/100ms Calculating ------------------------------------- #select { true }.size for 100000 170.963 (± 4.1%) i/s - 855.000 in 5.010050s #count { true } for 100000 211.185 (± 4.7%) i/s - 1.071k in 5.083109s ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/matcher_dsl_vs_classes.rb0000664000000000000000000001156514557700001027566 0ustar rootrootrequire 'benchmark' require 'rspec/expectations' include RSpec::Expectations include RSpec::Matchers RSpec::Matchers.define :eq_using_dsl do |expected| match do |actual| actual == expected end end n = 1000 puts "3 runs of #{n} times for each example running #{RUBY_ENGINE}/#{RUBY_VERSION}" puts "passing examples: 5.should eq(5)" puts "* using the DSL" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do 5.should eq_using_dsl(5) end end end end puts puts "* using a class" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do 5.should eq(5) end end end end puts puts "failing examples: 5.should eq(3)" puts "* using the DSL" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do 5.should eq_using_dsl(3) rescue nil end end end end puts puts "* using a class" Benchmark.benchmark do |bm| 3.times do bm.report do n.times do 5.should eq(3) rescue nil end end end end # 3 runs of 1000 times for each example running ruby/1.8.7 # passing examples: 5.should eq(5) # * using the DSL # 0.340000 0.000000 0.340000 ( 0.342052) # 0.330000 0.010000 0.340000 ( 0.340618) # 0.340000 0.000000 0.340000 ( 0.339149) # # * using a class # 0.000000 0.000000 0.000000 ( 0.003762) # 0.010000 0.000000 0.010000 ( 0.004192) # 0.000000 0.000000 0.000000 ( 0.003791) # # failing examples: 5.should eq(3) # * using the DSL # 0.380000 0.000000 0.380000 ( 0.384415) # 0.380000 0.010000 0.390000 ( 0.381604) # 0.370000 0.000000 0.370000 ( 0.380255) # # * using a class # 0.040000 0.000000 0.040000 ( 0.034528) # 0.030000 0.000000 0.030000 ( 0.032021) # 0.060000 0.010000 0.070000 ( 0.067579) # # 3 runs of 1000 times for each example running ruby/1.9.2 # passing examples: 5.should eq(5) # * using the DSL # 0.250000 0.010000 0.260000 ( 0.249692) # 0.250000 0.000000 0.250000 ( 0.253856) # 0.230000 0.000000 0.230000 ( 0.232787) # # * using a class # 0.000000 0.000000 0.000000 ( 0.001069) # 0.000000 0.000000 0.000000 ( 0.001041) # 0.000000 0.000000 0.000000 ( 0.001023) # # failing examples: 5.should eq(3) # * using the DSL # 0.370000 0.000000 0.370000 ( 0.377139) # 0.360000 0.010000 0.370000 ( 0.358379) # 0.370000 0.000000 0.370000 ( 0.373795) # # * using a class # 0.060000 0.010000 0.070000 ( 0.073325) # 0.050000 0.000000 0.050000 ( 0.053562) # 0.070000 0.000000 0.070000 ( 0.075382) # # 3 runs of 1000 times for each example running ruby/1.9.3 # passing examples: 5.should eq(5) # * using the DSL # 0.210000 0.000000 0.210000 ( 0.219539) # 0.220000 0.010000 0.230000 ( 0.217905) # 0.220000 0.000000 0.220000 ( 0.219657) # # * using a class # 0.000000 0.000000 0.000000 ( 0.001054) # 0.000000 0.000000 0.000000 ( 0.001048) # 0.000000 0.000000 0.000000 ( 0.001035) # # failing examples: 5.should eq(3) # * using the DSL # 0.350000 0.000000 0.350000 ( 0.351742) # 0.360000 0.000000 0.360000 ( 0.362456) # 0.340000 0.010000 0.350000 ( 0.351098) # # * using a class # 0.080000 0.000000 0.080000 ( 0.079964) # 0.080000 0.000000 0.080000 ( 0.076579) # 0.070000 0.000000 0.070000 ( 0.080587) # # 3 runs of 1000 times for each example running rbx/1.8.7 # passing examples: 5.should eq(5) # * using the DSL # 1.926107 0.009784 1.935891 ( 1.629354) # 0.583860 0.004390 0.588250 ( 0.580396) # 0.868571 0.003510 0.872081 ( 0.796644) # # * using a class # 0.002652 0.000013 0.002665 ( 0.002679) # 0.001845 0.000016 0.001861 ( 0.001848) # 0.002656 0.000010 0.002666 ( 0.001823) # # failing examples: 5.should eq(3) # * using the DSL # 0.694148 0.002006 0.696154 ( 0.648551) # 1.063773 0.004653 1.068426 ( 0.998837) # 0.643594 0.001356 0.644950 ( 0.638358) # # * using a class # 0.020139 0.000036 0.020175 ( 0.020161) # 0.097540 0.000575 0.098115 ( 0.084680) # 0.058366 0.000269 0.058635 ( 0.044372) # # 3 runs of 1000 times for each example running jruby/1.8.7 # passing examples: 5.should eq(5) # * using the DSL # 0.355000 0.000000 0.355000 ( 0.355000) # 0.261000 0.000000 0.261000 ( 0.261000) # 0.242000 0.000000 0.242000 ( 0.242000) # # * using a class # 0.007000 0.000000 0.007000 ( 0.007000) # 0.004000 0.000000 0.004000 ( 0.004000) # 0.001000 0.000000 0.001000 ( 0.001000) # # failing examples: 5.should eq(3) # * using the DSL # 0.507000 0.000000 0.507000 ( 0.507000) # 0.468000 0.000000 0.468000 ( 0.468000) # 0.476000 0.000000 0.476000 ( 0.476000) # # * using a class # 0.259000 0.000000 0.259000 ( 0.259000) # 0.521000 0.000000 0.521000 ( 0.521000) # 0.244000 0.000000 0.244000 ( 0.244000) # ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/set_vs_array_include.rb0000664000000000000000000000501514557700001027251 0ustar rootrootrequire 'benchmark' require 'set' n = 10_000_000 array = [ :@name, :@declarations, :@diffable, :@messages, :@match_block, :@match_for_should_not_block, :@expected_exception ] set = array.to_set puts "Positive examples: " Benchmark.bm(25) do |x| array.each_with_index do |var, i| x.report("set.include?(item #{i}) ") do n.times { set.include?(var) } end x.report("array.include?(item #{i})") do n.times { array.include?(var) } end puts "=" * 80 end end puts "\n\nNegative examples: " Benchmark.bm(5) do |x| x.report("set ") do n.times { set.include?(:@other) } end x.report("array") do n.times { array.include?(:@other) } end end # Positive examples: # user system total real # set.include?(item 0) 2.000000 0.010000 2.010000 ( 1.999305) # array.include?(item 0) 1.170000 0.000000 1.170000 ( 1.173168) # ================================================================================ # set.include?(item 1) 2.020000 0.000000 2.020000 ( 2.016389) # array.include?(item 1) 1.580000 0.000000 1.580000 ( 1.585301) # ================================================================================ # set.include?(item 2) 1.980000 0.010000 1.990000 ( 1.984699) # array.include?(item 2) 2.170000 0.000000 2.170000 ( 2.167163) # ================================================================================ # set.include?(item 3) 2.110000 0.010000 2.120000 ( 2.125914) # array.include?(item 3) 2.450000 0.000000 2.450000 ( 2.445224) # ================================================================================ # set.include?(item 4) 2.090000 0.010000 2.100000 ( 2.094182) # array.include?(item 4) 2.920000 0.000000 2.920000 ( 2.924850) # ================================================================================ # set.include?(item 5) 2.000000 0.000000 2.000000 ( 2.000656) # array.include?(item 5) 3.540000 0.010000 3.550000 ( 3.547563) # ================================================================================ # set.include?(item 6) 2.030000 0.000000 2.030000 ( 2.032430) # array.include?(item 6) 3.800000 0.010000 3.810000 ( 3.810014) # ================================================================================ # Negative examples: # user system total real # set 1.940000 0.000000 1.940000 ( 1.941780) # array 4.240000 0.010000 4.250000 ( 4.238137) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/gsub_vs_tr_single_character.rb0000664000000000000000000000116114557700001030575 0ustar rootrootrequire 'benchmark/ips' Benchmark.ips do |x| y = '1_2_3_4_5_6_7_8_9_10' x.report('gsub') do |_times| y.tr('_', ' ') end x.report('tr') do |_times| y.tr('_', ' ') end x.compare! end __END__ Calculating ------------------------------------- gsub 29.483k i/100ms tr 79.170k i/100ms ------------------------------------------------- gsub 10.420B (±23.7%) i/s - 31.106B tr 78.139B (±20.6%) i/s - 129.289B Comparison: tr: 78139428607.9 i/s gsub: 10419757735.7 i/s - 7.50x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/default_messages_as_methods_v_blocks.rb0000664000000000000000000000073414557700001032453 0ustar rootrootrequire 'benchmark' require 'rspec/expectations' include RSpec::Expectations include RSpec::Matchers RSpec::Matchers.define :eq_using_dsl do |expected| match do |actual| actual == expected end end n = 10_000 Benchmark.benchmark do |bm| 3.times do bm.report do n.times do eq_using_dsl(5).tap do |m| m.description m.failure_message_for_should m.failure_message_for_should_not end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/0000775000000000000000000000000014557700001025011 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/rubyprof/0000775000000000000000000000000014557700001026661 5ustar rootroot././@LongLink0000644000000000000000000000016100000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/rubyprof/passing_with_distinct_items.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/rubyprof/passing_with_disti0000664000000000000000000000033514557700001032500 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'rspec/expectations' require 'securerandom' extend RSpec::Matchers actual = Array.new(1000) { SecureRandom.uuid } expected = actual.shuffle expect(actual).to match_array(expected) ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/failing_with_distinct_items.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/failing_with_distinct_items0000664000000000000000000001433714557700001032512 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'benchmark' require 'rspec/expectations' require 'securerandom' extend RSpec::Matchers sizes = [10, 100, 1000, 2000, 4000] puts "rspec-expectations #{RSpec::Expectations::Version::STRING} -- #{RUBY_ENGINE}/#{RUBY_VERSION}" puts puts "Failing `match_array` expectation with lists of distinct strings having 1 unmatched pair" puts Benchmark.benchmark do |bm| sizes.each do |size| actual = Array.new(size) { SecureRandom.uuid } expecteds = Array.new(3) do array = actual.shuffle # replace one entry with a different value array[rand(array.length)] = SecureRandom.uuid array end expecteds.each do |expected| bm.report("#{size.to_s.rjust(5)} items") do begin expect(actual).to match_array(expected) rescue RSpec::Expectations::ExpectationNotMetError else raise "did not fail but should have" end end end end end __END__ Before new composable matchers algo: 10 items 0.000000 0.000000 0.000000 ( 0.000813) 10 items 0.000000 0.000000 0.000000 ( 0.000099) 10 items 0.000000 0.000000 0.000000 ( 0.000127) 100 items 0.000000 0.000000 0.000000 ( 0.000707) 100 items 0.000000 0.000000 0.000000 ( 0.000612) 100 items 0.000000 0.000000 0.000000 ( 0.000600) 1000 items 0.040000 0.000000 0.040000 ( 0.038679) 1000 items 0.040000 0.000000 0.040000 ( 0.041379) 1000 items 0.040000 0.000000 0.040000 ( 0.036680) 2000 items 0.130000 0.000000 0.130000 ( 0.131681) 2000 items 0.120000 0.000000 0.120000 ( 0.123664) 2000 items 0.130000 0.000000 0.130000 ( 0.128799) 4000 items 0.490000 0.000000 0.490000 ( 0.489446) 4000 items 0.510000 0.000000 0.510000 ( 0.511915) 4000 items 0.480000 0.010000 0.490000 ( 0.477616) After: 10 items 0.000000 0.000000 0.000000 ( 0.001382) 10 items 0.000000 0.000000 0.000000 ( 0.000156) 10 items 0.000000 0.000000 0.000000 ( 0.000161) 100 items 0.010000 0.000000 0.010000 ( 0.005052) 100 items 0.000000 0.000000 0.000000 ( 0.004991) 100 items 0.010000 0.000000 0.010000 ( 0.004984) 1000 items 0.470000 0.000000 0.470000 ( 0.470043) 1000 items 0.500000 0.000000 0.500000 ( 0.499316) 1000 items 0.490000 0.000000 0.490000 ( 0.488582) 2000 items 1.910000 0.000000 1.910000 ( 1.917279) 2000 items 1.930000 0.010000 1.940000 ( 1.931002) 2000 items 1.920000 0.000000 1.920000 ( 1.928989) 4000 items 7.860000 0.010000 7.870000 ( 7.881995) 4000 items 7.980000 0.010000 7.990000 ( 8.003643) 4000 items 8.000000 0.010000 8.010000 ( 8.031382) With "smaller subproblem" optimization: (about 25% slower) 10 items 0.010000 0.000000 0.010000 ( 0.001331) 10 items 0.000000 0.000000 0.000000 ( 0.000175) 10 items 0.000000 0.000000 0.000000 ( 0.000165) 100 items 0.000000 0.000000 0.000000 ( 0.006137) 100 items 0.010000 0.000000 0.010000 ( 0.005880) 100 items 0.000000 0.000000 0.000000 ( 0.005950) 1000 items 0.630000 0.000000 0.630000 ( 0.634294) 1000 items 0.620000 0.000000 0.620000 ( 0.622427) 1000 items 0.640000 0.000000 0.640000 ( 0.641505) 2000 items 2.420000 0.000000 2.420000 ( 2.419876) 2000 items 2.430000 0.000000 2.430000 ( 2.442544) 2000 items 2.380000 0.010000 2.390000 ( 2.385106) 4000 items 9.780000 0.010000 9.790000 ( 9.811499) 4000 items 9.670000 0.010000 9.680000 ( 9.688799) 4000 items 9.710000 0.010000 9.720000 ( 9.743054) With "implement `values_match?` ourselves" optimization: (more than twice as fast!) 10 items 0.000000 0.000000 0.000000 ( 0.001189) 10 items 0.000000 0.000000 0.000000 ( 0.000149) 10 items 0.000000 0.000000 0.000000 ( 0.000130) 100 items 0.000000 0.000000 0.000000 ( 0.002927) 100 items 0.000000 0.000000 0.000000 ( 0.002856) 100 items 0.010000 0.000000 0.010000 ( 0.003028) 1000 items 0.250000 0.000000 0.250000 ( 0.245146) 1000 items 0.240000 0.000000 0.240000 ( 0.246291) 1000 items 0.320000 0.000000 0.320000 ( 0.315192) 2000 items 1.120000 0.000000 1.120000 ( 1.128162) 2000 items 1.030000 0.000000 1.030000 ( 1.034982) 2000 items 1.060000 0.000000 1.060000 ( 1.063870) 4000 items 4.530000 0.000000 4.530000 ( 4.556346) 4000 items 4.400000 0.010000 4.410000 ( 4.414447) 4000 items 4.410000 0.000000 4.410000 ( 4.417440) With e === a || a == e || values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.001466) 10 items 0.000000 0.000000 0.000000 ( 0.000258) 10 items 0.000000 0.000000 0.000000 ( 0.000251) 100 items 0.020000 0.000000 0.020000 ( 0.012369) 100 items 0.010000 0.000000 0.010000 ( 0.012345) 100 items 0.010000 0.000000 0.010000 ( 0.012744) 1000 items 1.180000 0.000000 1.180000 ( 1.187754) 1000 items 1.200000 0.000000 1.200000 ( 1.198681) 1000 items 1.210000 0.000000 1.210000 ( 1.210159) 2000 items 4.760000 0.000000 4.760000 ( 4.764911) 2000 items 4.760000 0.000000 4.760000 ( 4.757022) 2000 items 4.760000 0.000000 4.760000 ( 4.771776) 4000 items 19.070000 0.010000 19.080000 ( 19.077930) 4000 items 19.090000 0.010000 19.100000 ( 19.104171) 4000 items 19.260000 0.010000 19.270000 ( 19.289653) With values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.001462) 10 items 0.000000 0.000000 0.000000 ( 0.000253) 10 items 0.000000 0.000000 0.000000 ( 0.000244) 100 items 0.010000 0.000000 0.010000 ( 0.011913) 100 items 0.010000 0.000000 0.010000 ( 0.011858) 100 items 0.020000 0.000000 0.020000 ( 0.011992) 1000 items 1.210000 0.000000 1.210000 ( 1.226960) 1000 items 1.140000 0.000000 1.140000 ( 1.147002) 1000 items 1.180000 0.000000 1.180000 ( 1.194010) 2000 items 4.690000 0.010000 4.700000 ( 4.740503) 2000 items 4.680000 0.000000 4.680000 ( 4.676084) 2000 items 4.570000 0.000000 4.570000 ( 4.581262) 4000 items 18.450000 0.010000 18.460000 ( 18.532578) 4000 items 18.400000 0.010000 18.410000 ( 18.520454) 4000 items 18.490000 0.020000 18.510000 ( 18.592491) ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/passing_with_distinct_items.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/passing_with_distinct_items0000664000000000000000000001552314557700001032543 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'benchmark' require 'rspec/expectations' require 'securerandom' extend RSpec::Matchers sizes = [10, 100, 1000, 2000, 4000] puts "rspec-expectations #{RSpec::Expectations::Version::STRING} -- #{RUBY_ENGINE}/#{RUBY_VERSION}" puts puts "Passing `match_array` expectation with lists of distinct strings" puts Benchmark.benchmark do |bm| sizes.each do |size| actual = Array.new(size) { SecureRandom.uuid } expecteds = Array.new(3) { actual.shuffle } expecteds.each do |expected| bm.report("#{size.to_s.rjust(5)} items") do expect(actual).to match_array(expected) end end end end __END__ Before new composable matchers algo: 10 items 0.000000 0.000000 0.000000 ( 0.000857) 10 items 0.000000 0.000000 0.000000 ( 0.000029) 10 items 0.000000 0.000000 0.000000 ( 0.000018) 100 items 0.000000 0.000000 0.000000 ( 0.000334) 100 items 0.000000 0.000000 0.000000 ( 0.000372) 100 items 0.000000 0.000000 0.000000 ( 0.000331) 1000 items 0.030000 0.000000 0.030000 ( 0.029778) 1000 items 0.030000 0.000000 0.030000 ( 0.030566) 1000 items 0.030000 0.000000 0.030000 ( 0.033150) 2000 items 0.140000 0.000000 0.140000 ( 0.141719) 2000 items 0.120000 0.000000 0.120000 ( 0.124348) 2000 items 0.120000 0.000000 0.120000 ( 0.121202) 4000 items 0.490000 0.000000 0.490000 ( 0.500631) 4000 items 0.470000 0.000000 0.470000 ( 0.468477) 4000 items 0.490000 0.010000 0.500000 ( 0.492957) After: 10 items 0.000000 0.000000 0.000000 ( 0.001165) 10 items 0.000000 0.000000 0.000000 ( 0.000131) 10 items 0.000000 0.000000 0.000000 ( 0.000127) 100 items 0.000000 0.000000 0.000000 ( 0.005636) 100 items 0.010000 0.000000 0.010000 ( 0.004881) 100 items 0.000000 0.000000 0.000000 ( 0.004676) 1000 items 0.500000 0.000000 0.500000 ( 0.505676) 1000 items 0.490000 0.000000 0.490000 ( 0.483469) 1000 items 0.490000 0.000000 0.490000 ( 0.497841) 2000 items 1.950000 0.000000 1.950000 ( 1.966324) 2000 items 1.970000 0.000000 1.970000 ( 1.975567) 2000 items 1.900000 0.000000 1.900000 ( 1.902315) 4000 items 7.650000 0.010000 7.660000 ( 7.672907) 4000 items 7.720000 0.010000 7.730000 ( 7.735615) 4000 items 7.730000 0.000000 7.730000 ( 7.756837) With "smaller subproblem" optimization: (about 20% slower) 10 items 0.000000 0.000000 0.000000 ( 0.001099) 10 items 0.000000 0.000000 0.000000 ( 0.000110) 10 items 0.000000 0.000000 0.000000 ( 0.000102) 100 items 0.010000 0.000000 0.010000 ( 0.005462) 100 items 0.010000 0.000000 0.010000 ( 0.005433) 100 items 0.000000 0.000000 0.000000 ( 0.005409) 1000 items 0.570000 0.000000 0.570000 ( 0.569302) 1000 items 0.570000 0.000000 0.570000 ( 0.577496) 1000 items 0.560000 0.000000 0.560000 ( 0.555496) 2000 items 2.330000 0.000000 2.330000 ( 2.325537) 2000 items 2.450000 0.000000 2.450000 ( 2.464415) 2000 items 2.470000 0.000000 2.470000 ( 2.472999) 4000 items 9.380000 0.010000 9.390000 ( 9.406678) 4000 items 9.320000 0.010000 9.330000 ( 9.340727) 4000 items 9.330000 0.010000 9.340000 ( 9.358326) With "implement `values_match?` ourselves" optimization: (about twice as fast!) 10 items 0.000000 0.000000 0.000000 ( 0.001113) 10 items 0.000000 0.000000 0.000000 ( 0.000074) 10 items 0.000000 0.000000 0.000000 ( 0.000071) 100 items 0.000000 0.000000 0.000000 ( 0.002558) 100 items 0.010000 0.000000 0.010000 ( 0.002528) 100 items 0.000000 0.000000 0.000000 ( 0.002555) 1000 items 0.300000 0.000000 0.300000 ( 0.306318) 1000 items 0.260000 0.000000 0.260000 ( 0.253526) 1000 items 0.240000 0.000000 0.240000 ( 0.246096) 2000 items 1.070000 0.000000 1.070000 ( 1.065989) 2000 items 1.040000 0.000000 1.040000 ( 1.047495) 2000 items 1.080000 0.000000 1.080000 ( 1.078392) 4000 items 4.520000 0.000000 4.520000 ( 4.529568) 4000 items 4.570000 0.010000 4.580000 ( 4.597785) 4000 items 5.030000 0.010000 5.040000 ( 5.079452) With `match_when_sorted?` optimization: (many orders of magnitude faster!) 10 items 0.010000 0.000000 0.010000 ( 0.002044) 10 items 0.000000 0.000000 0.000000 ( 0.000038) 10 items 0.000000 0.000000 0.000000 ( 0.000031) 100 items 0.000000 0.000000 0.000000 ( 0.000149) 100 items 0.000000 0.000000 0.000000 ( 0.000137) 100 items 0.000000 0.000000 0.000000 ( 0.000136) 1000 items 0.000000 0.000000 0.000000 ( 0.001426) 1000 items 0.000000 0.000000 0.000000 ( 0.001369) 1000 items 0.000000 0.000000 0.000000 ( 0.001355) 2000 items 0.010000 0.000000 0.010000 ( 0.003304) 2000 items 0.000000 0.000000 0.000000 ( 0.002192) 2000 items 0.000000 0.000000 0.000000 ( 0.002849) 4000 items 0.000000 0.000000 0.000000 ( 0.007730) 4000 items 0.010000 0.000000 0.010000 ( 0.006074) 4000 items 0.010000 0.000000 0.010000 ( 0.006514) With e === a || a == e || values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.002202) 10 items 0.000000 0.000000 0.000000 ( 0.000054) 10 items 0.000000 0.000000 0.000000 ( 0.000046) 100 items 0.000000 0.000000 0.000000 ( 0.000203) 100 items 0.000000 0.000000 0.000000 ( 0.000199) 100 items 0.000000 0.000000 0.000000 ( 0.000192) 1000 items 0.010000 0.000000 0.010000 ( 0.001438) 1000 items 0.000000 0.000000 0.000000 ( 0.001419) 1000 items 0.000000 0.000000 0.000000 ( 0.001474) 2000 items 0.010000 0.000000 0.010000 ( 0.003341) 2000 items 0.000000 0.000000 0.000000 ( 0.003224) 2000 items 0.000000 0.000000 0.000000 ( 0.003251) 4000 items 0.010000 0.000000 0.010000 ( 0.007156) 4000 items 0.010000 0.000000 0.010000 ( 0.006715) 4000 items 0.000000 0.000000 0.000000 ( 0.006676) With values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.001173) 10 items 0.000000 0.000000 0.000000 ( 0.000051) 10 items 0.000000 0.000000 0.000000 ( 0.000026) 100 items 0.000000 0.000000 0.000000 ( 0.000171) 100 items 0.000000 0.000000 0.000000 ( 0.000138) 100 items 0.000000 0.000000 0.000000 ( 0.000136) 1000 items 0.010000 0.000000 0.010000 ( 0.001506) 1000 items 0.000000 0.000000 0.000000 ( 0.001486) 1000 items 0.000000 0.000000 0.000000 ( 0.001510) 2000 items 0.010000 0.000000 0.010000 ( 0.003153) 2000 items 0.000000 0.010000 0.010000 ( 0.003883) 2000 items 0.000000 0.000000 0.000000 ( 0.003199) 4000 items 0.010000 0.000000 0.010000 ( 0.007178) 4000 items 0.000000 0.000000 0.000000 ( 0.006629) 4000 items 0.010000 0.000000 0.010000 ( 0.006435) ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/passing_with_duplicate_items.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/passing_with_duplicate_item0000664000000000000000000001322514557700001032506 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'benchmark' require 'rspec/expectations' extend RSpec::Matchers sizes = [10, 100, 1000, 2000] puts "rspec-expectations #{RSpec::Expectations::Version::STRING} -- #{RUBY_ENGINE}/#{RUBY_VERSION}" puts puts "Passing `match_array` expectation with lists of integers including duplicate values" puts Benchmark.benchmark do |bm| sizes.each do |size| actual = Array.new(size) { rand(size / 2) } expecteds = Array.new(3) { actual.shuffle } expecteds.each do |expected| bm.report("#{size.to_s.rjust(5)} items") do expect(actual).to match_array(expected) end end end end __END__ Before new composable matchers algo: 10 items 0.000000 0.000000 0.000000 ( 0.000665) 10 items 0.000000 0.000000 0.000000 ( 0.000027) 10 items 0.000000 0.000000 0.000000 ( 0.000015) 100 items 0.000000 0.000000 0.000000 ( 0.000250) 100 items 0.000000 0.000000 0.000000 ( 0.000176) 100 items 0.000000 0.000000 0.000000 ( 0.000181) 1000 items 0.010000 0.000000 0.010000 ( 0.013612) 1000 items 0.020000 0.000000 0.020000 ( 0.013409) 1000 items 0.020000 0.000000 0.020000 ( 0.018222) 2000 items 0.060000 0.000000 0.060000 ( 0.057428) 2000 items 0.060000 0.000000 0.060000 ( 0.058242) 2000 items 0.060000 0.000000 0.060000 ( 0.063026) After: 10 items 0.000000 0.000000 0.000000 ( 0.001835) 10 items 0.000000 0.000000 0.000000 ( 0.000327) 10 items 0.000000 0.000000 0.000000 ( 0.000336) 100 items 0.030000 0.000000 0.030000 ( 0.025134) 100 items 0.030000 0.000000 0.030000 ( 0.032476) 100 items 0.020000 0.000000 0.020000 ( 0.024273) 1000 items 2.600000 0.040000 2.640000 ( 2.649328) 1000 items 2.510000 0.020000 2.530000 ( 2.523448) 1000 items 2.470000 0.000000 2.470000 ( 2.476770) 2000 items 11.590000 0.110000 11.700000 ( 11.719525) 2000 items 10.750000 0.080000 10.830000 ( 10.845655) 2000 items 11.140000 0.080000 11.220000 ( 11.241852) With "smaller subproblem" optimization: (about 35% faster) 10 items 0.000000 0.000000 0.000000 ( 0.001236) 10 items 0.000000 0.000000 0.000000 ( 0.000278) 10 items 0.000000 0.000000 0.000000 ( 0.000293) 100 items 0.010000 0.000000 0.010000 ( 0.013229) 100 items 0.020000 0.000000 0.020000 ( 0.013932) 100 items 0.020000 0.000000 0.020000 ( 0.019739) 1000 items 1.580000 0.030000 1.610000 ( 1.622586) 1000 items 1.670000 0.020000 1.690000 ( 1.683174) 1000 items 1.570000 0.010000 1.580000 ( 1.588718) 2000 items 7.030000 0.100000 7.130000 ( 7.139178) 2000 items 7.220000 0.090000 7.310000 ( 7.328606) 2000 items 6.930000 0.130000 7.060000 ( 7.070295) With "implement `values_match?` ourselves" optimization: (about 20% faster) 10 items 0.000000 0.000000 0.000000 ( 0.001352) 10 items 0.000000 0.000000 0.000000 ( 0.000313) 10 items 0.000000 0.000000 0.000000 ( 0.000298) 100 items 0.010000 0.000000 0.010000 ( 0.011200) 100 items 0.010000 0.000000 0.010000 ( 0.013465) 100 items 0.020000 0.000000 0.020000 ( 0.021589) 1000 items 1.320000 0.030000 1.350000 ( 1.350071) 1000 items 1.280000 0.020000 1.300000 ( 1.298206) 1000 items 1.370000 0.010000 1.380000 ( 1.392149) 2000 items 6.120000 0.110000 6.230000 ( 6.252104) 2000 items 6.170000 0.090000 6.260000 ( 6.270807) 2000 items 5.910000 0.150000 6.060000 ( 6.066389) With `match_when_sorted?` optimization: (many orders of magnitude faster!) 10 items 0.000000 0.000000 0.000000 ( 0.001134) 10 items 0.000000 0.000000 0.000000 ( 0.000029) 10 items 0.000000 0.000000 0.000000 ( 0.000020) 100 items 0.000000 0.000000 0.000000 ( 0.000070) 100 items 0.000000 0.000000 0.000000 ( 0.000066) 100 items 0.000000 0.000000 0.000000 ( 0.000065) 1000 items 0.000000 0.000000 0.000000 ( 0.000612) 1000 items 0.000000 0.000000 0.000000 ( 0.000608) 1000 items 0.000000 0.000000 0.000000 ( 0.000613) 2000 items 0.010000 0.000000 0.010000 ( 0.001235) 2000 items 0.000000 0.000000 0.000000 ( 0.001282) 2000 items 0.000000 0.000000 0.000000 ( 0.001227) With e === a || a == e || values_match?(e,a) 10 items 0.010000 0.000000 0.010000 ( 0.001258) 10 items 0.000000 0.000000 0.000000 ( 0.000034) 10 items 0.000000 0.000000 0.000000 ( 0.000027) 100 items 0.000000 0.000000 0.000000 ( 0.000124) 100 items 0.000000 0.000000 0.000000 ( 0.000151) 100 items 0.000000 0.000000 0.000000 ( 0.000121) 1000 items 0.000000 0.000000 0.000000 ( 0.001212) 1000 items 0.000000 0.000000 0.000000 ( 0.001193) 1000 items 0.000000 0.000000 0.000000 ( 0.001293) 2000 items 0.000000 0.000000 0.000000 ( 0.002433) 2000 items 0.010000 0.000000 0.010000 ( 0.002351) 2000 items 0.000000 0.000000 0.000000 ( 0.002404) With values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.001202) 10 items 0.000000 0.000000 0.000000 ( 0.000028) 10 items 0.000000 0.000000 0.000000 ( 0.000024) 100 items 0.000000 0.000000 0.000000 ( 0.000147) 100 items 0.000000 0.000000 0.000000 ( 0.000122) 100 items 0.000000 0.000000 0.000000 ( 0.000142) 1000 items 0.000000 0.000000 0.000000 ( 0.001201) 1000 items 0.000000 0.000000 0.000000 ( 0.001233) 1000 items 0.000000 0.000000 0.000000 ( 0.001221) 2000 items 0.010000 0.000000 0.010000 ( 0.002382) 2000 items 0.000000 0.000000 0.000000 ( 0.002353) 2000 items 0.000000 0.000000 0.000000 ( 0.002371) ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/failing_with_duplicate_items.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/match_array/failing_with_duplicate_item0000664000000000000000000001116114557700001032450 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'benchmark' require 'rspec/expectations' extend RSpec::Matchers sizes = [10, 100, 1000] puts "rspec-expectations #{RSpec::Expectations::Version::STRING} -- #{RUBY_ENGINE}/#{RUBY_VERSION}" puts puts "Failing `match_array` expectation with lists of integers (w/dups) having 1 unmatched pair" puts Benchmark.benchmark do |bm| sizes.each do |size| actual = Array.new(size) { rand(size / 2) } expecteds = Array.new(3) do array = actual.shuffle array[rand(array.length)] = 9_999_999 array end expecteds.each do |expected| bm.report("#{size.to_s.rjust(5)} items") do begin expect(actual).to match_array(expected) rescue RSpec::Expectations::ExpectationNotMetError else raise "did not fail but should have" end end end end end __END__ Before new composable matchers algo: 10 items 0.000000 0.000000 0.000000 ( 0.000711) 10 items 0.000000 0.000000 0.000000 ( 0.000079) 10 items 0.000000 0.000000 0.000000 ( 0.000080) 20 items 0.000000 0.000000 0.000000 ( 0.000105) 20 items 0.000000 0.000000 0.000000 ( 0.000122) 20 items 0.000000 0.000000 0.000000 ( 0.000101) 25 items 0.000000 0.000000 0.000000 ( 0.000125) 25 items 0.000000 0.000000 0.000000 ( 0.000137) 25 items 0.000000 0.000000 0.000000 ( 0.000116) After: This varies widly based on the inputs. One run: 10 items 0.010000 0.000000 0.010000 ( 0.005884) 10 items 0.000000 0.000000 0.000000 ( 0.004429) 10 items 0.000000 0.000000 0.000000 ( 0.004733) 20 items 2.040000 0.000000 2.040000 ( 2.049461) 20 items 2.080000 0.010000 2.090000 ( 2.087983) 20 items 1.950000 0.000000 1.950000 ( 1.950013) 25 items 10.240000 0.020000 10.260000 ( 10.280575) 25 items 10.390000 0.010000 10.400000 ( 10.433754) 25 items 10.250000 0.020000 10.270000 ( 10.311604) Another run: 10 items 0.010000 0.010000 0.020000 ( 0.015355) 10 items 0.010000 0.000000 0.010000 ( 0.010347) 10 items 0.020000 0.000000 0.020000 ( 0.013657) 20 items 36.140000 0.030000 36.170000 ( 36.236651) 20 items 36.010000 0.040000 36.050000 ( 36.098006) 20 items 35.990000 0.030000 36.020000 ( 36.071397) (I lost patience and didn't wait for it to finish 25 items...) With "smaller subproblem" optimization: (way faster!) 10 items 0.000000 0.000000 0.000000 ( 0.001411) 10 items 0.000000 0.000000 0.000000 ( 0.000615) 10 items 0.000000 0.000000 0.000000 ( 0.000413) 20 items 0.000000 0.000000 0.000000 ( 0.000947) 20 items 0.000000 0.000000 0.000000 ( 0.001725) 20 items 0.000000 0.000000 0.000000 ( 0.001345) 25 items 0.010000 0.000000 0.010000 ( 0.002348) 25 items 0.000000 0.000000 0.000000 ( 0.002836) 25 items 0.000000 0.000000 0.000000 ( 0.002721) With "implement `values_match?` ourselves" optimization: (about twice as fast!) 10 items 0.000000 0.000000 0.000000 ( 0.002450) 10 items 0.000000 0.000000 0.000000 ( 0.000857) 10 items 0.000000 0.000000 0.000000 ( 0.000883) 100 items 0.040000 0.000000 0.040000 ( 0.043661) 100 items 0.060000 0.000000 0.060000 ( 0.053046) 100 items 0.040000 0.010000 0.050000 ( 0.051760) 1000 items 3.620000 0.060000 3.680000 ( 3.688289) 1000 items 2.600000 0.020000 2.620000 ( 2.628405) 1000 items 4.660000 0.040000 4.700000 ( 4.712196) With e === a || a == e || values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.001992) 10 items 0.000000 0.000000 0.000000 ( 0.000821) 10 items 0.000000 0.000000 0.000000 ( 0.000794) 100 items 0.060000 0.000000 0.060000 ( 0.068597) 100 items 0.060000 0.000000 0.060000 ( 0.056409) 100 items 0.070000 0.010000 0.080000 ( 0.072950) 1000 items 4.090000 0.100000 4.190000 ( 4.218107) 1000 items 3.000000 0.050000 3.050000 ( 3.070019) 1000 items 6.040000 0.070000 6.110000 ( 6.102311) With values_match?(e,a) 10 items 0.000000 0.000000 0.000000 ( 0.002177) 10 items 0.000000 0.000000 0.000000 ( 0.001201) 10 items 0.000000 0.000000 0.000000 ( 0.000928) 100 items 0.050000 0.000000 0.050000 ( 0.051785) 100 items 0.040000 0.000000 0.040000 ( 0.032323) 100 items 0.040000 0.000000 0.040000 ( 0.046934) 1000 items 4.050000 0.100000 4.150000 ( 4.175914) 1000 items 3.040000 0.050000 3.090000 ( 3.130656) 1000 items 4.110000 0.050000 4.160000 ( 4.161170) ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/2.x_vs_3.x_matcher_dsl_implementation.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/2.x_vs_3.x_matcher_dsl_implementation.r0000664000000000000000000002356614557700001032177 0ustar rootroot$LOAD_PATH.unshift "./lib" require 'benchmark' require 'rspec/expectations' include RSpec::Expectations include RSpec::Matchers n = 1000 puts "3 runs of #{n} times for each example running rspec-expectations #{RSpec::Expectations::Version::STRING} -- #{RUBY_ENGINE}/#{RUBY_VERSION}" puts "Defining a custom matcher" Benchmark.benchmark do |bm| 3.times do |i| bm.report do n.times do |j| RSpec::Matchers.define :"define_matcher_#{i}_#{j}" do match {} end end end end end puts "Getting an instance of a custom matcher" RSpec::Matchers.define :be_a_multiple_of do |x| match { |actual| (actual % x).zero? } end Benchmark.benchmark do |bm| 3.times do bm.report do n.times do |i| be_a_multiple_of(i) end end end end puts "Using a previously gotten custom matcher instance -- positive match" Benchmark.benchmark do |bm| 1.upto(3) do |i| matcher = be_a_multiple_of(i) bm.report do n.times do |j| expect(i * j).to matcher end end end end puts "Using a previously gotten custom matcher instance -- negative match" Benchmark.benchmark do |bm| 2.upto(4) do |i| matcher = be_a_multiple_of(i) bm.report do n.times do |j| begin expect(1 + i * j).to matcher rescue RSpec::Expectations::ExpectationNotMetError end end end end end =begin Results are below for: - MRI 2.0.0, MRI 1.9.3, JRuby 1.7.4 - Against 2.14.3, 3.0.0.pre before matcher DSL rewrite, 3.0.0.pre after matcher DSL rewrite Conclusions: * Getting an instance of a custom matcher was insanely slow in 2.x, and it looks like the `making_declared_methods_public` hack for 1.8.6 was the primary source of that. Without that, getting an instance of a matcher is ~20x faster. To see what changed between 2.14.3 and the commit used for this benchmark, go to: https://github.com/rspec/rspec-expectations/compare/v2.14.3...4c47e4c43ee6961c755d325e73181b1f5b6bf097#diff-a51020971ade2c87f1d5b93f20d711c7L6 * With our new custom matcher DSL, using a matcher is approximately the same perf. However, defining a matcher is a little bit faster, and getting an instance of an already defined matcher is about 10x faster. Overall, this is definitely a net win. Results: 3 runs of 1000 times for each example running rspec-expectations 2.14.3 -- ruby/2.0.0 Defining a custom matcher 0.010000 0.000000 0.010000 ( 0.004612) 0.000000 0.000000 0.000000 ( 0.004674) 0.000000 0.000000 0.000000 ( 0.004944) Getting an instance of a custom matcher 1.470000 0.010000 1.480000 ( 1.472602) 1.420000 0.000000 1.420000 ( 1.426760) 1.440000 0.000000 1.440000 ( 1.442283) Using a previously gotten custom matcher instance -- positive match 0.000000 0.000000 0.000000 ( 0.002213) 0.000000 0.000000 0.000000 ( 0.002019) 0.000000 0.000000 0.000000 ( 0.001884) Using a previously gotten custom matcher instance -- negative match 0.020000 0.000000 0.020000 ( 0.019378) 0.030000 0.000000 0.030000 ( 0.027001) 0.020000 0.010000 0.030000 ( 0.022310) 3 runs of 1000 times for each example running rspec-expectations 2.14.3 -- ruby/1.9.3 Defining a custom matcher 0.000000 0.000000 0.000000 ( 0.004455) 0.010000 0.000000 0.010000 ( 0.004849) 0.010000 0.000000 0.010000 ( 0.010495) Getting an instance of a custom matcher 1.690000 0.010000 1.700000 ( 1.696415) 1.550000 0.000000 1.550000 ( 1.556858) 1.550000 0.000000 1.550000 ( 1.554830) Using a previously gotten custom matcher instance -- positive match 0.000000 0.000000 0.000000 ( 0.002161) 0.000000 0.000000 0.000000 ( 0.002038) 0.010000 0.000000 0.010000 ( 0.002091) Using a previously gotten custom matcher instance -- negative match 0.050000 0.010000 0.060000 ( 0.060512) 0.050000 0.000000 0.050000 ( 0.064532) 0.060000 0.010000 0.070000 ( 0.062206) 3 runs of 1000 times for each example running rspec-expectations 2.14.3 -- jruby/1.9.3 Defining a custom matcher 0.660000 0.010000 0.670000 ( 0.299000) 0.280000 0.000000 0.280000 ( 0.178000) 0.220000 0.010000 0.230000 ( 0.143000) Getting an instance of a custom matcher 1.970000 0.030000 2.000000 ( 1.389000) 1.340000 0.030000 1.370000 ( 0.907000) 0.820000 0.030000 0.850000 ( 0.795000) Using a previously gotten custom matcher instance -- positive match 0.110000 0.000000 0.110000 ( 0.058000) 0.050000 0.000000 0.050000 ( 0.036000) 0.030000 0.000000 0.030000 ( 0.030000) Using a previously gotten custom matcher instance -- negative match 0.930000 0.010000 0.940000 ( 0.474000) 0.620000 0.000000 0.620000 ( 0.376000) 0.390000 0.000000 0.390000 ( 0.279000) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre (before DSL rewrite) -- ruby/2.0.0 Defining a custom matcher 0.010000 0.000000 0.010000 ( 0.004719) 0.000000 0.000000 0.000000 ( 0.004424) 0.010000 0.000000 0.010000 ( 0.005562) Getting an instance of a custom matcher 0.050000 0.000000 0.050000 ( 0.059949) 0.060000 0.000000 0.060000 ( 0.058208) 0.060000 0.010000 0.070000 ( 0.067402) Using a previously gotten custom matcher instance -- positive match 0.010000 0.000000 0.010000 ( 0.001696) 0.000000 0.000000 0.000000 ( 0.001558) 0.000000 0.000000 0.000000 ( 0.001488) Using a previously gotten custom matcher instance -- negative match 0.020000 0.000000 0.020000 ( 0.021522) 0.030000 0.000000 0.030000 ( 0.027728) 0.020000 0.000000 0.020000 ( 0.026185) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre (before DSL rewrite) -- ruby/1.9.3 Defining a custom matcher 0.010000 0.000000 0.010000 ( 0.004650) 0.000000 0.000000 0.000000 ( 0.004658) 0.010000 0.000000 0.010000 ( 0.011111) Getting an instance of a custom matcher 0.050000 0.010000 0.060000 ( 0.047230) 0.060000 0.000000 0.060000 ( 0.065500) 0.070000 0.000000 0.070000 ( 0.073099) Using a previously gotten custom matcher instance -- positive match 0.000000 0.000000 0.000000 ( 0.002007) 0.000000 0.000000 0.000000 ( 0.002370) 0.010000 0.000000 0.010000 ( 0.002121) Using a previously gotten custom matcher instance -- negative match 0.070000 0.010000 0.080000 ( 0.078960) 0.060000 0.000000 0.060000 ( 0.061351) 0.060000 0.000000 0.060000 ( 0.069949) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre (before DSL rewrite) -- jruby/1.9.3 Defining a custom matcher 0.730000 0.010000 0.740000 ( 0.303000) 0.240000 0.010000 0.250000 ( 0.153000) 0.210000 0.000000 0.210000 ( 0.140000) Getting an instance of a custom matcher 0.940000 0.010000 0.950000 ( 0.538000) 0.510000 0.000000 0.510000 ( 0.174000) 0.160000 0.000000 0.160000 ( 0.090000) Using a previously gotten custom matcher instance -- positive match 0.120000 0.000000 0.120000 ( 0.053000) 0.040000 0.000000 0.040000 ( 0.025000) 0.030000 0.000000 0.030000 ( 0.026000) Using a previously gotten custom matcher instance -- negative match 0.970000 0.010000 0.980000 ( 0.458000) 0.480000 0.010000 0.490000 ( 0.314000) 0.360000 0.000000 0.360000 ( 0.269000) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre -- ruby/2.0.0 Defining a custom matcher 0.000000 0.000000 0.000000 ( 0.003138) 0.000000 0.000000 0.000000 ( 0.003083) 0.010000 0.000000 0.010000 ( 0.003448) Getting an instance of a custom matcher 0.000000 0.000000 0.000000 ( 0.007273) 0.010000 0.000000 0.010000 ( 0.007096) 0.020000 0.000000 0.020000 ( 0.021662) Using a previously gotten custom matcher instance -- positive match 0.000000 0.000000 0.000000 ( 0.002582) 0.000000 0.000000 0.000000 ( 0.001832) 0.010000 0.000000 0.010000 ( 0.001588) Using a previously gotten custom matcher instance -- negative match 0.010000 0.000000 0.010000 ( 0.017756) 0.030000 0.000000 0.030000 ( 0.021225) 0.020000 0.010000 0.030000 ( 0.021281) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre -- ruby/1.9.3 Defining a custom matcher 0.000000 0.000000 0.000000 ( 0.002903) 0.000000 0.000000 0.000000 ( 0.002919) 0.010000 0.000000 0.010000 ( 0.008956) Getting an instance of a custom matcher 0.010000 0.000000 0.010000 ( 0.006640) 0.000000 0.000000 0.000000 ( 0.006557) 0.010000 0.000000 0.010000 ( 0.007869) Using a previously gotten custom matcher instance -- positive match 0.010000 0.000000 0.010000 ( 0.003332) 0.000000 0.000000 0.000000 ( 0.003288) 0.000000 0.000000 0.000000 ( 0.002769) Using a previously gotten custom matcher instance -- negative match 0.070000 0.010000 0.080000 ( 0.075547) 0.050000 0.000000 0.050000 ( 0.053149) 0.060000 0.010000 0.070000 ( 0.062583) 3 runs of 1000 times for each example running rspec-expectations 3.0.0.pre -- jruby/1.9.3 Defining a custom matcher 0.780000 0.020000 0.800000 ( 0.316000) 0.170000 0.010000 0.180000 ( 0.139000) 0.220000 0.000000 0.220000 ( 0.135000) Getting an instance of a custom matcher 0.340000 0.000000 0.340000 ( 0.183000) 0.230000 0.010000 0.240000 ( 0.131000) 0.180000 0.000000 0.180000 ( 0.104000) Using a previously gotten custom matcher instance -- positive match 0.170000 0.000000 0.170000 ( 0.076000) 0.070000 0.000000 0.070000 ( 0.049000) 0.110000 0.000000 0.110000 ( 0.047000) Using a previously gotten custom matcher instance -- negative match 0.970000 0.010000 0.980000 ( 0.461000) 0.410000 0.000000 0.410000 ( 0.316000) 0.350000 0.010000 0.360000 ( 0.256000) =end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/benchmarks/include_matcher.rb0000664000000000000000000001532514557700001026200 0ustar rootrootrequire 'benchmark/ips' require 'rspec/expectations' include RSpec::Matchers module RSpec module Matchers module BuiltIn class OldInclude < BaseMatcher def initialize(*expected) @expected = expected end def matches?(actual) @actual = actual perform_match(:all?, :all?) end def does_not_match?(actual) @actual = actual perform_match(:none?, :any?) end def description described_items = surface_descriptions_in(expected) item_list = EnglishPhrasing.list(described_items) improve_hash_formatting "include#{item_list}" end def failure_message improve_hash_formatting(super) + invalid_object_message end def failure_message_when_negated improve_hash_formatting(super) + invalid_object_message end def diffable? !diff_would_wrongly_highlight_matched_item? end private def invalid_object_message return '' if actual.respond_to?(:include?) ", but it does not respond to `include?`" end def perform_match(predicate, hash_subset_predicate) return false unless actual.respond_to?(:include?) expected.__send__(predicate) do |expected_item| if comparing_hash_to_a_subset?(expected_item) expected_item.__send__(hash_subset_predicate) do |(key, value)| actual_hash_includes?(key, value) end elsif comparing_hash_keys?(expected_item) actual_hash_has_key?(expected_item) else actual_collection_includes?(expected_item) end end end def comparing_hash_to_a_subset?(expected_item) actual.is_a?(Hash) && expected_item.is_a?(Hash) end def actual_hash_includes?(expected_key, expected_value) actual_value = actual.fetch(expected_key) { return false } values_match?(expected_value, actual_value) end def comparing_hash_keys?(expected_item) actual.is_a?(Hash) && !expected_item.is_a?(Hash) end def actual_hash_has_key?(expected_key) actual.key?(expected_key) || actual.keys.any? { |key| values_match?(expected_key, key) } end def actual_collection_includes?(expected_item) return true if actual.include?(expected_item) return false unless actual.respond_to?(:any?) actual.any? { |value| values_match?(expected_item, value) } end def diff_would_wrongly_highlight_matched_item? return false unless actual.is_a?(String) && expected.is_a?(Array) lines = actual.split("\n") expected.any? do |str| actual.include?(str) && lines.none? { |line| line == str } end end end end def old_include(*expected) BuiltIn::OldInclude.new(*expected) end end end array_sizes = [10, 50, 100, 500] # *maniacal laugh* class << self; alias_method :inc, :include; remove_method :include; end Benchmark.ips do |x| x.report("Old `to include` successes") do array_sizes.each do |n| expect([*1..n]).to old_include(*n/2..n) end end x.report("New `to include` successes") do array_sizes.each do |n| expect([*1..n]).to include(*n/2..n) end end x.compare! end Benchmark.ips do |x| x.report("Old `to include` failures") do array_sizes.each do |n| begin expect([*1..n]).to old_include(*n+1..n*1.5) rescue RSpec::Expectations::ExpectationNotMetError end end end x.report("New `to include` failures") do array_sizes.each do |n| begin expect([*1..n]).to include(*n+1..n*1.5) rescue RSpec::Expectations::ExpectationNotMetError end end end x.compare! end Benchmark.ips do |x| x.report("Old `to not include` successes") do array_sizes.each do |n| expect([*1..n]).to_not old_include(*n+1..n*1.5) end end x.report("New `to not include` successes") do array_sizes.each do |n| expect([*1..n]).to_not include(*n+1..n*1.5) end end x.compare! end Benchmark.ips do |x| x.report("Old `to not include` failures") do array_sizes.each do |n| begin expect([*1..n]).to_not old_include(*n/2..n) rescue RSpec::Expectations::ExpectationNotMetError end end end x.report("New `to not include` failures") do array_sizes.each do |n| begin expect([*1..n]).to_not include(*n/2..n) rescue RSpec::Expectations::ExpectationNotMetError end end end x.compare! end __END__ Calculating ------------------------------------- Old `to include` successes 30.000 i/100ms New `to include` successes 28.000 i/100ms ------------------------------------------------- Old `to include` successes 307.740 (± 4.2%) i/s - 1.560k New `to include` successes 299.321 (± 2.7%) i/s - 1.512k Comparison: Old `to include` successes: 307.7 i/s New `to include` successes: 299.3 i/s - 1.03x slower Calculating ------------------------------------- Old `to include` failures 2.000 i/100ms New `to include` failures 1.000 i/100ms ------------------------------------------------- Old `to include` failures 20.611 (± 4.9%) i/s - 104.000 New `to include` failures 2.990 (± 0.0%) i/s - 15.000 Comparison: Old `to include` failures: 20.6 i/s New `to include` failures: 3.0 i/s - 6.89x slower Calculating ------------------------------------- Old `to not include` successes 1.000 i/100ms New `to not include` successes 1.000 i/100ms ------------------------------------------------- Old `to not include` successes 3.505 (± 0.0%) i/s - 18.000 New `to not include` successes 3.475 (± 0.0%) i/s - 18.000 Comparison: Old `to not include` successes: 3.5 i/s New `to not include` successes: 3.5 i/s - 1.01x slower Calculating ------------------------------------- Old `to not include` failures 2.000 i/100ms New `to include` failures 1.000 i/100ms ------------------------------------------------- Old `to not include` failures 21.187 (± 4.7%) i/s - 106.000 New `to include` failures 19.899 (± 5.0%) i/s - 100.000 Comparison: Old `to not include` failures: 21.2 i/s New `to include` failures: 19.9 i/s - 1.06x slower ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Should.md0000664000000000000000000001064614557700001022171 0ustar rootroot# `should` and `should_not` syntax From the beginning RSpec::Expectations provided `should` and `should_not` methods to define expectations on any object. In version 2.11 `expect` method was introduced which is now the recommended way to define expectations on an object. ### Why switch over from `should` to `expect` #### Fix edge case issues `should` and `should_not` work by being added to every object. However, RSpec does not own every object and cannot ensure they work consistently on every object. In particular, they can lead to surprising failures when used with BasicObject-subclassed proxy objects. `expect` avoids these problems altogether by not needing to be available on all objects. #### Unification of block and value syntaxes Before version 2.11 `expect` was just a more readable alternative for block expectations. Since version 2.11 `expect` can be used for both block and value expectations. ```ruby expect(actual).to eq(expected) expect { ... }.to raise_error(ErrorClass) ``` See [http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax](http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax) For a detailed explanation ### One-liners The one-liner syntax supported by [rspec-core](http://rubydoc.info/gems/rspec-core) uses `should` even when `config.syntax = :expect`. It reads better than the alternative, and does not require a global monkey patch: ```ruby describe User do it { should validate_presence_of :email } end ``` It can also be expressed with the `is_expected` syntax: ```ruby describe User do it { is_expected.to validate_presence_of :email } end ``` ### Using either `expect` or `should` or both By default, both `expect` and `should` syntaxes are available. In the future, the default may be changed to only enable the `expect` syntax. If you want your project to only use any one of these syntaxes, you can configure it: ```ruby RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect # disables `should` # or c.syntax = :should # disables `expect` # or c.syntax = [:should, :expect] # default, enables both `should` and `expect` end end ``` See [RSpec::Expectations::Syntax#expect](http://rubydoc.info/gems/rspec-expectations/RSpec/Expectations/Syntax:expect) for more information. ## Usage The `should` and `should_not` methods can be used to define expectations on any object. ```ruby actual.should eq expected actual.should be > 3 [1, 2, 3].should_not include 4 ``` ## Using Built-in matchers ### Equivalence ```ruby actual.should eq(expected) # passes if actual == expected actual.should == expected # passes if actual == expected actual.should_not eql(expected) # passes if actual.eql?(expected) ``` Note: we recommend the `eq` matcher over `==` to avoid Ruby's "== in a useless context" warning when the `==` matcher is used anywhere but the last statement of an example. ### Identity ```ruby actual.should be(expected) # passes if actual.equal?(expected) actual.should_not equal(expected) # passes if actual.equal?(expected) ``` ### Comparisons ```ruby actual.should be > expected actual.should be >= expected actual.should be <= expected actual.should be < expected actual.should be_within(delta).of(expected) ``` ### Regular expressions ```ruby actual.should match(/expression/) actual.should =~ /expression/ ``` ### Types/classes ```ruby actual.should be_an_instance_of(expected) actual.should_not be_a_kind_of(expected) ``` ### Truthiness ```ruby actual.should be_true # passes if actual is truthy (not nil or false) actual.should be_false # passes if actual is falsy (nil or false) actual.should be_nil # passes if actual is nil ``` ### Predicate matchers ```ruby actual.should be_xxx # passes if actual.xxx? actual.should_not have_xxx(:arg) # passes if actual.has_xxx?(:arg) ``` ### Ranges (Ruby >= 1.9 only) ```ruby (1..10).should cover(3) ``` ### Collection membership ```ruby actual.should include(expected) actual.should start_with(expected) actual.should end_with(expected) ``` #### Examples ```ruby [1,2,3].should include(1) [1,2,3].should include(1, 2) [1,2,3].should start_with(1) [1,2,3].should start_with(1,2) [1,2,3].should end_with(3) [1,2,3].should end_with(2,3) {:a => 'b'}.should include(:a => 'b') "this string".should include("is str") "this string".should start_with("this") "this string".should end_with("ring") ``` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/0000775000000000000000000000000014557700001021706 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/cucumber.sh0000775000000000000000000000034214557700001024051 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh run_cukes ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/run_build0000775000000000000000000000151714557700001023623 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "binstub check" check_binstubs fold "specs" run_specs_and_record_done if additional_specs_available; then fold "additional specs" run_additional_specs fi fold "cukes" run_cukes if documentation_enforced; then fold "doc check" check_documentation_coverage fi if supports_cross_build_checks; then fold "one-by-one specs" run_specs_one_by_one export NO_COVERAGE=true run_all_spec_suites else echo "Skipping the rest of the build on non-MRI rubies" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/update_rubygems_and_install_bundler0000775000000000000000000000122514557700001031116 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh if is_ruby_31_plus; then echo "Installing rubygems 3.3.6 / bundler 2.3.6" yes | gem update --system '3.3.6' yes | gem install bundler -v '2.3.6' elif is_ruby_23_plus; then echo "Installing rubygems 3.2.22 / bundler 2.2.22" yes | gem update --system '3.2.22' yes | gem install bundler -v '2.2.22' else echo "Warning installing older versions of Rubygems / Bundler" gem update --system '2.7.8' gem install bundler -v '1.17.3' fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/functions.sh0000664000000000000000000001404014557700001024251 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source $SCRIPT_DIR/ci_functions.sh source $SCRIPT_DIR/predicate_functions.sh # If JRUBY_OPTS isn't set, use these. # see https://docs.travis-ci.com/user/ci-environment/ export JRUBY_OPTS=${JRUBY_OPTS:-"--server -Xcompile.invokedynamic=false"} SPECS_HAVE_RUN_FILE=specs.out MAINTENANCE_BRANCH=`cat maintenance-branch` # Don't allow rubygems to pollute what's loaded. Also, things boot faster # without the extra load time of rubygems. Only works on MRI Ruby 1.9+ if is_mri_192_plus; then export RUBYOPT="--disable=gem" fi function clone_repo { if [ ! -d $1 ]; then # don't clone if the dir is already there if [ -z "$2" ]; then BRANCH_TO_CLONE="${MAINTENANCE_BRANCH?}"; else BRANCH_TO_CLONE="$2"; fi; ci_retry eval "git clone https://github.com/rspec/$1 --depth 1 --branch ${BRANCH_TO_CLONE?}" fi; } function run_specs_and_record_done { local rspec_bin=bin/rspec # rspec-core needs to run with a special script that loads simplecov first, # so that it can instrument rspec-core's code before rspec-core has been loaded. if [ -f script/rspec_with_simplecov ] && is_mri; then rspec_bin=script/rspec_with_simplecov fi; echo "${PWD}/bin/rspec" $rspec_bin spec --backtrace --format progress --profile --format progress --out $SPECS_HAVE_RUN_FILE } function run_cukes { if [ -d features ]; then # 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 # # Note that we delay setting this until we run the cukes because we've seen # spec failures in our spec suite due to problems with this mode. export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "${PWD}/bin/cucumber" if is_mri_192; then # For some reason we get SystemStackError on 1.9.2 when using # the bin/cucumber approach below. That approach is faster # (as it avoids the bundler tax), so we use it on rubies where we can. bundle exec cucumber --strict elif is_jruby; then # For some reason JRuby doesn't like our improved bundler setup RUBYOPT="-I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict else # Prepare RUBYOPT for scenarios that are shelling out to ruby, # and PATH for those that are using `rspec` or `rake`. RUBYOPT="${RUBYOPT} -I${PWD}/../bundle -rbundler/setup" \ PATH="${PWD}/bin:$PATH" \ bin/cucumber --strict fi fi } function run_specs_one_by_one { echo "Running each spec file, one-by-one..." for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done } function run_spec_suite_for { if [ ! -f ../$1/$SPECS_HAVE_RUN_FILE ]; then # don't rerun specs that have already run if [ -d ../$1 ]; then echo "Running specs for $1" pushd ../$1 unset BUNDLE_GEMFILE bundle_install_flags=`cat .github/workflows/ci.yml | grep "bundle install" | sed 's/.* bundle install//'` ci_retry eval "(unset RUBYOPT; exec bundle install $bundle_install_flags)" ci_retry eval "(unset RUBYOPT; exec bundle binstubs --all)" run_specs_and_record_done popd else echo "" echo "WARNING: The ../$1 directory does not exist. Usually the" echo "build cds into that directory and run the specs to ensure" echo "the specs still pass with your latest changes, but we are" echo "going to skip that step." echo "" fi; fi; } function check_binstubs { echo "Checking required binstubs" local success=0 local binstubs="" local gems="" if [ ! -x ./bin/rspec ]; then binstubs="$binstubs bin/rspec" gems="$gems rspec-core" success=1 fi if [ ! -x ./bin/rake ]; then binstubs="$binstubs bin/rake" gems="$gems rake" success=1 fi if [ -d features ]; then if [ ! -x ./bin/cucumber ]; then binstubs="$binstubs bin/cucumber" gems="$gems cucumber" success=1 fi fi if [ $success -eq 1 ]; then echo echo "Missing binstubs:$binstubs" echo "Install missing binstubs using one of the following:" echo echo " # Create the missing binstubs" echo " $ bundle binstubs$gems" echo echo " # To binstub all gems" echo " $ bundle binstubs --all" fi return $success } function check_documentation_coverage { echo "bin/yard stats --list-undoc" bin/yard stats --list-undoc | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') coverage ||= line[/([\d\.]+)% documented/, 1] puts line end unless Float(coverage) == 100 puts \"\n\nMissing documentation coverage (currently at #{coverage}%)\" exit(1) end if has_warnings puts \"\n\nYARD emitted documentation warnings.\" exit(1) end " # Some warnings only show up when generating docs, so do that as well. bin/yard doc --no-cache | ruby -e " while line = gets has_warnings ||= line.start_with?('[warn]:') has_errors ||= line.start_with?('[error]:') puts line end if has_warnings || has_errors puts \"\n\nYARD emitted documentation warnings or errors.\" exit(1) end " } function check_style_and_lint { echo "bin/rubocop lib" eval "(unset RUBYOPT; exec bin/rubocop lib)" } function run_all_spec_suites { fold "rspec-core specs" run_spec_suite_for "rspec-core" fold "rspec-expectations specs" run_spec_suite_for "rspec-expectations" fold "rspec-mocks specs" run_spec_suite_for "rspec-mocks" if rspec_rails_compatible; then if ! is_ruby_27_plus; then export RAILS_VERSION='~> 6.1.0' fi fold "rspec-rails specs" run_spec_suite_for "rspec-rails" fi if rspec_support_compatible; then fold "rspec-support specs" run_spec_suite_for "rspec-support" fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/legacy_setup.sh0000775000000000000000000000077214557700001024737 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh bundle install --standalone --binstubs --without coverage documentation if [ -x ./bin/rspec ]; then echo "RSpec bin detected" else if [ -x ./exe/rspec ]; then cp ./exe/rspec ./bin/rspec echo "RSpec restored from exe" else echo "No RSpec bin available" exit 1 fi fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/ci_functions.sh0000664000000000000000000000376314557700001024736 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. # Taken from: # https://github.com/travis-ci/travis-build/blob/e9314616e182a23e6a280199cd9070bfc7cae548/lib/travis/build/script/templates/header.sh#L34-L53 ci_retry() { local result=0 local count=1 while [ $count -le 3 ]; do [ $result -ne 0 ] && { echo -e "\n\033[33;1mThe command \"$@\" failed. Retrying, $count of 3.\033[0m\n" >&2 } "$@" result=$? [ $result -eq 0 ] && break count=$(($count + 1)) sleep 1 done [ $count -eq 3 ] && { echo "\n\033[33;1mThe command \"$@\" failed 3 times.\033[0m\n" >&2 } return $result } # Taken from https://github.com/vcr/vcr/commit/fa96819c92b783ec0c794f788183e170e4f684b2 # and https://github.com/vcr/vcr/commit/040aaac5370c68cd13c847c076749cd547a6f9b1 nano_cmd="$(type -p gdate date | head -1)" nano_format="+%s%N" [ "$(uname -s)" != "Darwin" ] || nano_format="${nano_format/%N/000000000}" travis_time_start() { travis_timer_id=$(printf %08x $(( RANDOM * RANDOM ))) travis_start_time=$($nano_cmd -u "$nano_format") printf "travis_time:start:%s\r\e[0m" $travis_timer_id } travis_time_finish() { local travis_end_time=$($nano_cmd -u "$nano_format") local duration=$(($travis_end_time-$travis_start_time)) printf "travis_time:end:%s:start=%s,finish=%s,duration=%s\r\e[0m" \ $travis_timer_id $travis_start_time $travis_end_time $duration } fold() { local name="$1" local status=0 shift 1 if [ -n "$TRAVIS" ]; then printf "travis_fold:start:%s\r\e[0m" "$name" travis_time_start else echo "============= Starting $name ===============" fi "$@" status=$? [ -z "$TRAVIS" ] || travis_time_finish if [ "$status" -eq 0 ]; then if [ -n "$TRAVIS" ]; then printf "travis_fold:end:%s\r\e[0m" "$name" else echo "============= Ending $name ===============" fi else STATUS="$status" fi return $status } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/predicate_functions.sh0000664000000000000000000000555114557700001026300 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. function is_mri { if ruby -e "exit(!defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_ruby_head { # This checks for the presence of our CI's ruby-head env variable if [ -z ${RUBY_HEAD+x} ]; then return 1 else return 0 fi; } function supports_cross_build_checks { if is_mri; then # We don't run cross build checks on ruby-head if is_ruby_head; then return 1 else return 0 fi else return 1 fi } function is_jruby { if ruby -e "exit(defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java')"; then # RUBY_ENGINE only returns 'ruby' on MRI. # MRI 1.8.7 lacks the constant but all other rubies have it (including JRuby in 1.8 mode) return 0 else return 1 fi; } function is_mri_192 { if is_mri; then if ruby -e "exit(RUBY_VERSION == '1.9.2')"; then return 0 else return 1 fi else return 1 fi } function is_mri_192_plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 1.8)"; then return 0 else return 1 fi else return 1 fi } function is_mri_2plus { if is_mri; then if ruby -e "exit(RUBY_VERSION.to_f > 2.0)"; then return 0 else return 1 fi else return 1 fi } function is_ruby_23_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.3)"; then return 0 else return 1 fi } function is_ruby_25_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.5)"; then return 0 else return 1 fi } function is_ruby_27_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 2.7)"; then return 0 else return 1 fi } function is_ruby_31_plus { if ruby -e "exit(RUBY_VERSION.to_f >= 3.1)"; then return 0 else return 1 fi } function rspec_rails_compatible { if is_ruby_25_plus; then # TODO remove when RSpec-Rails build is 3.1 safe by default if is_ruby_31_plus; then return 1 else return 0 fi else return 1 fi } function rspec_support_compatible { if [ "$MAINTENANCE_BRANCH" != "2-99-maintenance" ] && [ "$MAINTENANCE_BRANCH" != "2-14-maintenance" ]; then return 0 else return 1 fi } function additional_specs_available { type run_additional_specs > /dev/null 2>&1 return $? } function documentation_enforced { if [ -x ./bin/yard ]; then if is_mri_2plus; then return 0 else return 1 fi else return 1 fi } function style_and_lint_enforced { if is_ruby_head; then return 1 else if [ -x ./bin/rubocop ]; then return 0 else return 1 fi fi } ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/run_rubocop0000775000000000000000000000063614557700001024176 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh # Allow repos to override the default functions and add their own if [ -f script/custom_build_functions.sh ]; then source script/custom_build_functions.sh fi fold "rubocop" check_style_and_lint ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/script/clone_all_rspec_repos0000775000000000000000000000111014557700001026161 0ustar rootroot#!/bin/bash # This file was generated on 2023-12-25T16:07:49+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. set -e source script/functions.sh if is_mri; then pushd .. clone_repo "rspec" clone_repo "rspec-core" clone_repo "rspec-expectations" clone_repo "rspec-mocks" clone_repo "rspec-rails" "6-1-maintenance" if rspec_support_compatible; then clone_repo "rspec-support" fi popd else echo "Not cloning all repos since we are not on MRI and they are only needed for the MRI build" fi ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/LICENSE.md0000664000000000000000000000230114557700001022002 0ustar rootrootThe MIT License (MIT) ===================== * Copyright © 2012 David Chelimsky, Myron Marston * Copyright © 2006 David Chelimsky, The RSpec Development Team * Copyright © 2005 Steven Baker 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. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.rubocop.yml0000664000000000000000000000435014557700001022656 0ustar rootrootinherit_from: - .rubocop_todo.yml - .rubocop_rspec_base.yml AllCops: TargetRubyVersion: 2.4 DisplayCopNames: true Exclude: - bin/* - tmp/**/* # Over time we'd like to get this down, but this is what we're at now. Layout/LineLength: Max: 186 # Offense count: 1 Style/BlockComments: Enabled: false Style/ClassAndModuleChildren: Exclude: - spec/**/* Style/EvalWithLocation: Exclude: - spec/rspec/matchers/built_in/respond_to_spec.rb Style/MultilineBlockChain: Exclude: - spec/**/* Style/RescueModifier: Exclude: - spec/**/* - benchmarks/**/* Style/Semicolon: Enabled: false Style/SingleLineMethods: Exclude: - spec/**/* - benchmarks/**/* # We have some situations where we need to use `raise ExceptionClass.new(argument)`. Style/RaiseArgs: Enabled: false Style/FrozenStringLiteralComment: EnforcedStyle: never Exclude: - REPORT_TEMPLATE.md Style/PercentLiteralDelimiters: PreferredDelimiters: default: [] '%r': '||' Style/WordArray: Enabled: false Security/Eval: Exclude: - Gemfile Metrics/AbcSize: Max: 27 # Offense count: 2 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: Max: 96 Exclude: - spec/**/* # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: Max: 239 Exclude: - spec/**/* # Offense count: 4 Metrics/PerceivedComplexity: Max: 14 Layout/AccessModifierIndentation: Exclude: - 'lib/rspec/expectations/syntax.rb' # Too much diff to fix # Offense count: 7 Layout/ParameterAlignment: Enabled: false Layout/SpaceInsideArrayLiteralBrackets: Exclude: - spec/rspec/matchers/built_in/contain_exactly_spec.rb Layout/SpaceInsideParens: Exclude: - spec/rspec/matchers/built_in/* Lint/AmbiguousBlockAssociation: Exclude: - spec/**/* Lint/AmbiguousRegexpLiteral: Exclude: - 'features/step_definitions/*' Lint/SuppressedException: Exclude: - benchmarks/**/* # Offense count: 3 Lint/IneffectiveAccessModifier: Exclude: - 'lib/rspec/matchers.rb' - 'lib/rspec/matchers/built_in/compound.rb' Lint/InheritException: Exclude: - 'lib/rspec/expectations.rb' Bundler/DuplicatedGem: Enabled: false Bundler/OrderedGems: Enabled: false ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Changelog.md0000664000000000000000000015100214557700001022612 0ustar rootroot### Development [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.3...main) ### 3.13.0 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.4...v3.13.0) Enhancements: * Update `eq` and `eql` matchers to better highlight difference in string encoding. (Alan Foster, #1425) ### 3.12.4 / 2024-02-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.3...v3.12.4) Bug Fixes: * Fix the diff for redefined `actual` and reassigned `@actual` in compound expectations failure messages. (Phil Pirozhkov, #1440) ### 3.12.3 / 2023-04-20 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.2...v3.12.3) Bug Fixes: * Fix `include` matcher when fuzzy matching on keys with a hash-like actual which has a non standard `key?` method which may raise. (Jon Rowe, #1416) ### 3.12.2 / 2023-01-07 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.1...v3.12.2) Bug Fixes: * Prevent deprecation warning when using the `exist` matcher with `Dir`. (Steve Dierker, #1398) ### 3.12.1 / 2022-12-16 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.0...v3.12.1) Bug Fixes: * Pass keyword arguments through to aliased (and thus negated) matchers. (Jon Rowe, #1394) * When handling failures in an aggregated_failures block (or example) prevent the failure list leaking out. (Maciek Rząsa, #1392) ### 3.12.0 / 2022-10-26 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.1...v3.12.0) Enhancements: * Add `an_array_matching` alias for `match_array` to improve readability as an argument matcher. (Mark Schneider, #1361) ### 3.11.1 / 2022-09-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.0...v3.11.1) Bug Fixes: * Allow the `contain_exactly` matcher to be reused by resetting its internals on `matches?` (@bclayman-sq, #1326) * Using the exist matcher on `FileTest` no longer produces a deprecation warning. (Ryo Nakamura, #1383) ### 3.11.0 / 2022-02-09 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.2...v3.11.0) Enhancements: * Return `true` from `aggregate_failures` when no exception occurs. (Jon Rowe, #1225) Deprecations: * Print a deprecation message when using the implicit block expectation syntax. (Phil Pirozhkov, #1139) ### 3.10.2 / 2022-01-14 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.1...v3.10.2) Bug Fixes: * Fix support for dynamic matchers for expectation target checks (Phil Pirozhkov, #1294) * Fix `expect(array).to include(hash).times`, previously this would fail due to matching the entire array as a single hash, rather than a member of the hash. (Slava Kardakov, #1322) * Ensure `raise_error` matches works with the `error_highlight` option from Ruby 3.1. (Peter Goldstein, #1339) ### 3.10.1 / 2020-12-27 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.0...v3.10.1) Bug Fixes: * Allow JRuby 9.2.x.x to generate backtraces normally rather than via our backfill workaround. (#1230, Jon Rowe) ### 3.10.0 / 2020-10-30 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.10.0) Enhancements: * Allow `include` matcher to be chained with `once`, `at_least`, etc. for simple cases. (Marc-André Lafortune, #1168) * Add an explicit warning when `nil` is passed to `raise_error`. (Phil Pirozhkov, #1143) * Improve `include` matcher's composability. (Phil Pirozhkov, #1155) * Mocks expectations can now set a custom failure message. (Benoit Tigeot and Nicolas Zermati, #1156) * `aggregate_failures` now shows the backtrace line for each failure. (Fabricio Bedin, #1163) * Support multiple combinations of `yield_control` modifiers like `at_least`, `at_most`. (Jon Rowe, #1169) * Dynamic `have_` matchers now have output consistent with other dynamic matchers. (Marc-André Lafortune, #1195) * New config option `strict_predicate_matchers` allows predicate matcher to be strict (i.e. match for `true` or `false`) instead of the default (match truthy vs `false` or `nil`). (Marc-André Lafortune, #1196) ### 3.9.4 / 2020-10-29 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.9.4) Bug Fixes: * Fix regression with `be_` and `have_` matchers and arguments implementing `to_hash` were they would act like keywords and be cast to a hash. (Jon Rowe, #1222) ### 3.9.3 / 2020-10-23 Bug Fixes: * Swap the comparison of the delta vs the expected for the `be_within` matcher allowing more complicated oobjects to be compared providing they provide `abs` and other comparison methods. (Kelly Stannard, #1182) * Properly format expected in the description of the `be_within` matcher. (Jon Rowe, #1185) * Remove warning when using keyword arguments with `be_` and `have_` matchers on 2.7.x (Jon Rowe, #1187) * Prevent formatting a single hash as a list of key value pairs in default failure messages for custom matches (fixes formatting in `EnglishPhrasing#list`). (Robert Eshleman, #1193) * Prevent errors from causing false positives when using `be ` comparison, e.g. `expect(1).not_to be < 'a'` will now correctly fail rather than pass. (Jon Rowe, #1208) ### 3.9.2 / 2020-05-08 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.1...v3.9.2) Bug Fixes: * Issue a proper `ArgumentError` when invalid arguments are given to `yield_control` modifiers such as `at_least` et al. (Marc-André Lafortune, #1167) * Prevent Ruby 2.7 keyword arguments warning from being issued by custom matcher definitions. (Jon Rowe, #1176) ### 3.9.1 / 2020-03-13 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.0...v3.9.1) Bug Fixes: * Issue an improved warning when using `respond_to(...).with(n).arguments` and ignore the warning when using with `have_attributes(...)`. (Jon Rowe, #1164) ### 3.9.0 / 2019-10-08 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.6...v3.9.0) Enhancements: * The `respond_to` matcher now uses the signature from `initialize` to validate checks for `new` (unless `new` is non standard). (Jon Rowe, #1072) * Generated descriptions for matchers now use `is expected to` rather than `should` in line with our preferred DSL. (Pete Johns, #1080, rspec/rspec-core#2572) * Add the ability to re-raise expectation errors when matching with `match_when_negated` blocks. (Jon Rowe, #1130) * Add a warning when an empty diff is produce due to identical inspect output. (Benoit Tigeot, #1126) ### 3.8.6 / 2019-10-07 Bug Fixes: * Revert #1125 due to the change being incompatible with our semantic versioning policy. ### 3.8.5 / 2019-10-02 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.4...v3.8.5) Bug Fixes: * Prevent unsupported implicit block expectation syntax from being used. (Phil Pirozhkov, #1125) ### 3.8.4 / 2019-06-10 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.3...v3.8.4) Bug Fixes: * Prevent false negatives when checking objects for the methods required to run the the `be_an_instance_of` and `be_kind_of` matchers. (Nazar Matus, #1112) ### 3.8.3 / 2019-04-20 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.2...v3.8.3) Bug Fixes: * Prevent composed `all` matchers from leaking into their siblings leading to duplicate failures. (Jamie English, #1086) * Prevent objects which change their hash on comparison from failing change checks. (Phil Pirozhkov, #1100) * Issue an `ArgumentError` rather than a `NoMethodError` when `be_an_instance_of` and `be_kind_of` matchers encounter objects not supporting those methods. (Taichi Ishitani, #1107) ### 3.8.2 / 2018-10-09 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.1...v3.8.2) Bug Fixes: * Change `include` matcher to rely on a `respond_to?(:include?)` check rather than a direct Hash comparison before calling `to_hash` to convert to a hash. (Jordan Owens, #1073) * Prevent unexpected call stack jumps from causing an obscure error (`IndexError`), and replace that error with a proper informative message. (Jon Rowe, #1076) ### 3.8.1 / 2018-08-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.0...v3.8.1) Bug Fixes: * Fix regression in `include` matcher so stopped `expect(hash.with_indifferent_access).to include(:symbol_key)` from working. (Eito Katagiri, #1069) ### 3.8.0 / 2018-08-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.7.0...v3.8.0) Enhancements: * Improve failure message of `change(receiver, :message)` by including the receiver as `SomeClass#some_message`. (Tomohiro Hashidate, #1005) * Improve `change` matcher so that it can correctly detect changes in deeply nested mutable objects (such as arrays-of-hashes-of-arrays). The improved logic uses the before/after `hash` value to see if the object has been mutated, rather than shallow duping the object. (Myron Marston, #1034) * Improve `include` matcher so that pseudo-hash objects (e.g. objects that decorate a hash using a `SimpleDelegator` or similar) are treated as a hash, as long as they implement `to_hash`. (Pablo Brasero, #1012) * Add `max_formatted_output_length=` to configuration, allowing changing the length at which we truncate large output strings. (Sam Phippen #951, Benoit Tigeot #1056) * Improve error message when passing a matcher that doesn't support block expectations to a block based `expect`. (@nicktime, #1066) ### 3.7.0 / 2017-10-17 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.6.0...v3.7.0) Enhancements: * Improve compatibility with `--enable-frozen-string-literal` option on Ruby 2.3+. (Pat Allan, #997) ### 3.6.0 / 2017-05-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.6.0.beta2...v3.6.0) Enhancements: * Treat NoMethodError as a failure for comparison matchers. (Jon Rowe, #972) * Allow for scoped aliased and negated matchers--just call `alias_matcher` or `define_negated_matcher` from within an example group. (Markus Reiter, #974) * Improve failure message of `change` matcher with block and `satisfy` matcher by including the block snippet instead of just describing it as `result` or `block` when Ripper is available. (Yuji Nakayama, #987) Bug Fixes: * Fix `yield_with_args` and `yield_successive_args` matchers so that they compare expected to actual args at the time the args are yielded instead of at the end, in case the method that is yielding mutates the arguments after yielding. (Alyssa Ross, #965) ### 3.6.0.beta2 / 2016-12-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.6.0.beta1...v3.6.0.beta2) Bug Fixes: * Using the exist matcher on `File` no longer produces a deprecation warning. (Jon Rowe, #954) ### 3.6.0.beta1 / 2016-10-09 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.5.0...v3.6.0.beta1) Bug Fixes: * Fix `contain_exactly` to work correctly with ranges. (Myron Marston, #940) * Fix `change` to work correctly with sets. (Marcin Gajewski, #939) ### 3.5.0 / 2016-07-01 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.5.0.beta4...v3.5.0) Enhancements: * Add support for keyword arguments to the `respond_to` matcher. (Rob Smith, #915). ### 3.5.0.beta4 / 2016-06-05 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.5.0.beta3...v3.5.0.beta4) Bug Fixes: * Fix `include` matcher so that it provides a valid diff for hashes. (Yuji Nakayama, #916) ### 3.5.0.beta3 / 2016-04-02 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.5.0.beta2...v3.5.0.beta3) Enhancements: * Make `rspec/expectations/minitest_integration` work on Minitest::Spec 5.6+. (Myron Marston, #904) * Add an alias `having_attributes` for `have_attributes` matcher. (Yuji Nakayama, #905) * Improve `change` matcher error message when block is mis-used. (Alex Altair, #908) ### 3.5.0.beta2 / 2016-03-10 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.5.0.beta1...v3.5.0.beta2) Enhancements: * Add the ability to raise an error on encountering false positives via `RSpec::Configuration#on_potential_false_positives = :raise`. (Jon Rowe, #900) * When using the custom matcher DSL, support new `notify_expectation_failures: true` option for the `match` method to allow expectation failures to be raised as normal instead of being converted into a `false` return value for `matches?`. (Jon Rowe, #892) Bug Fixes: * Allow `should` deprecation check to work on `BasicObject`s. (James Coleman, #898) ### 3.5.0.beta1 / 2016-02-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.4.0...v3.5.0.beta1) Enhancements: * Make `match_when_negated` in custom matcher DSL support use of expectations within the match logic. (Chris Arcand, #789) Bug Fixes: * Return `true` as expected from passing negated expectations (such as `expect("foo").not_to eq "bar"`), so they work properly when used within a `match` or `match_when_negated` block. (Chris Arcand, #789) ### 3.4.0 / 2015-11-11 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.3.1...v3.4.0) Enhancements: * Warn when `RSpec::Matchers` is included in a superclass after it has already been included in a subclass on MRI 1.9, since that situation can cause uses of `super` to trigger infinite recursion. (Myron Marston, #816) * Stop rescuing `NoMemoryError`, `SignalExcepetion`, `Interrupt` and `SystemExit`. It is dangerous to interfere with these. (Myron Marston, #845) * Add `#with_captures` to the match matcher which allows a user to specify expected captures when matching a regex against a string. (Sam Phippen, #848) * Always print compound failure messages in the multi-line form. Trying to print it all on a single line didn't read very well. (Myron Marston, #859) Bug Fixes: * Fix failure message from dynamic predicate matchers when the object does not respond to the predicate so that it is inspected rather than relying upon its `to_s` -- that way for `nil`, `"nil"` is printed rather than an empty string. (Myron Marston, #841) * Fix SystemStackError raised when diffing an Enumerable object whose `#each` includes the object itself. (Yuji Nakayama, #857) ### 3.3.1 / 2015-07-15 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.3.0...v3.3.1) Bug Fixes: * Fix `be >`, `be <`, etc so that it fails rather than allowing an argument error to be raised when compared against an object of the wrong type. This allows it to be used in composed matcher expressions against heterogeneous objects. (Dennis Günnewig, #809) * Fix `respond_to` to work properly on target objects that redefine the `method` method. (unmanbearpig, #821) ### 3.3.0 / 2015-06-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.1...v3.3.0) Enhancements: * Expose `RSpec::Matchers::EnglishPhrasing` to make it easier to write nice failure messages in custom matchers. (Jared Beck, #736) * Add `RSpec::Matchers::FailMatchers`, a mixin which provides `fail`, `fail_with` and `fail_including` matchers for use in specifying that an expectation fails for use by extension/plugin authors. (Charlie Rudolph, #729) * Avoid loading `tempfile` (and its dependencies) unless it is absolutely needed. (Myron Marston, #735) * Improve failure output when attempting to use `be_true` or `be_false`. (Tim Wade, #744) * Define `RSpec::Matchers#respond_to_missing?` so that `RSpec::Matchers#respond_to?` and `RSpec::Matchers#method` handle dynamic predicate matchers. (Andrei Botalov, #751) * Use custom Time/DateTime/BigDecimal formatting for all matchers so they are consistently represented in failure messages. (Gavin Miller, #740) * Add configuration to turn off warnings about matcher combinations that may cause false positives. (Jon Rowe, #768) * Warn when using a bare `raise_error` matcher that you may be subject to false positives. (Jon Rowe, #768) * Warn rather than raise when using the`raise_error` matcher in negative expectations that may be subject to false positives. (Jon Rowe, #775) * Improve failure message for `include(a, b, c)` so that if `a` and `b` are included the failure message only mentions `c`. (Chris Arcand, #780) * Allow `satisfy` matcher to take an optional description argument that will be used in the `description`, `failure_message` and `failure_message_when_negated` in place of the undescriptive "sastify block". (Chris Arcand, #783) * Add new `aggregate_failures` API that allows multiple independent expectations to all fail and be listed in the failure output, rather than the example aborting on the first failure. (Myron Marston, #776) * Improve `raise_error` matcher so that it can accept a matcher as a single argument that matches the message. (Time Wade, #782) Bug Fixes: * Make `contain_exactly` / `match_array` work with strict test doubles that have not defined `<=>`. (Myron Marston, #758) * Fix `include` matcher so that it omits the diff when it would confusingly highlight items that are actually included but are not an exact match in a line-by-line diff. (Tim Wade, #763) * Fix `match` matcher so that it does not blow up when matching a string or regex against another matcher (rather than a string or regex). (Myron Marston, #772) * Silence whitespace-only diffs. (Myron Marston, #801) ### 3.2.1 / 2015-04-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.2.0...v3.2.1) Bug Fixes: * Prevent `Range`s from being enumerated when generating matcher descriptions. (Jon Rowe, #755) * Ensure exception messages are compared as strings in the `raise_error` matcher. (Jon Rowe, #755) ### 3.2.0 / 2015-02-03 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.2...v3.2.0) Enhancements: * Add `block_arg` method to custom matcher API, which allows you to access the block passed to a custom matcher, if there is one. (Mike Dalton, #645) * Provide more detail in failure message of `yield_control` matcher. (Jon Rowe, #650) * Add a shorthand syntax for `chain` in the matcher DSL which assigns values for use elsewhere, for example `chain :and_smaller_than, :small_value` creates an `attr_reader` for `small_value` (Tom Stuart, #644) * Provide a more helpful deprecation message when using the `should` syntax. (Elia Schito, #663) * Provide more detail in the `have_attributes` matcher failure message. (Jon Rowe, #668) * Make the `have_attributes` matcher diffable. (Jon Rowe, Alexey Fedorov, #668) * Add `output(...).to_std(out|err)_from_any_process` as alternatives to `output(...).to_std(out|err)`. The latter doesn't work when a sub process writes to the named stream but is much faster. (Alex Genco, #700) * Improve compound matchers (created by `and` and `or`) so that diffs are included in failures when one or more of their matchers are diffable. (Alexey Fedorov, #713) Bug Fixes: * Avoid calling `private_methods` from the `be` predicate matcher on the target object if the object publicly responds to the predicate method. This avoids a possible error that can occur if the object raises errors from `private_methods` (which can happen with celluloid objects). (@chapmajs, #670) * Make `yield_control` (with no modifier) default to `at_least(:once)` rather than raising a confusing error when multiple yields are encountered. (Myron Marston, #675) * Fix "instance variable @color not initialized" warning when using rspec-expectations outside of an rspec-core context. (Myron Marston, #689) * Fix `start_with` and `end_with` to work properly when checking a string against an array of strings. (Myron Marston, #690) * Don't use internally delegated matchers when generating descriptions for examples without doc strings. (Myron Marston, #692) ### 3.1.2 / 2014-09-26 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.1...v3.1.2) Bug Fixes: * Fix `define_negated_matcher` so that matchers that support fluent interfaces continue to be negated after you use the chained method. (Myron Marston, #656) * Fix `define_negated_matcher` so that the matchers fail with an appropriate failure message. (Myron Marston, #659) ### 3.1.1 / 2014-09-15 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.1.0...v3.1.1) Bug Fixes: * Fix regression in `all` matcher in 3.1.0 that prevented it from working on objects that are not `Enumerable` but do implement `each_with_index` (such as an ActiveRecord proxy). (Jori Hardman, #647) ### 3.1.0 / 2014-09-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.4...v3.1.0) Enhancements: * Add `have_attributes` matcher, that passes if actual's attribute values match the expected attributes hash: `Person = Struct.new(:name, :age)` `person = Person.new("Bob", 32)` `expect(person).to have_attributes(:name => "Bob", :age => 32)`. (Adam Farhi, #571) * Extended compound matcher support to block matchers, for cases like: `expect { ... }.to change { x }.to(3).and change { y }.to(4)`. (Myron Marston, #567) * Include chained methods in custom matcher description and failure message when new `include_chain_clauses_in_custom_matcher_descriptions` config option is enabled. (Dan Oved, #600) * Add `thrice` modifier to `yield_control` matcher as a synonym for `exactly(3).times`. (Dennis Taylor, #615) * Add `RSpec::Matchers.define_negated_matcher`, which defines a negated version of the named matcher. (Adam Farhi, Myron Marston, #618) * Document and support negation of `contain_exactly`/`match_array`. (Jon Rowe, #626). Bug Fixes: * Rename private `LegacyMacherAdapter` constant to `LegacyMatcherAdapter` to fix typo. (Abdelkader Boudih, #563) * Fix `all` matcher so that it fails properly (rather than raising a `NoMethodError`) when matched against a non-enumerable. (Hao Su, #622) ### 3.0.4 / 2014-08-14 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.3...v3.0.4) Bug Fixes: * Fix `start_with` and `end_with` so that they work properly with structs. (Myron Marston, #620) * Fix failure message generation so that structs are printed properly in failures. Previously failure messages would represent them as an array. (Myron Marston, #620) * Fix composable matcher support so that it does not wrongly treat structs as arrays. (Myron Marston, #620) ### 3.0.3 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.2...v3.0.3) Bug Fixes: * Fix issue with detection of generic operator matchers so they work correctly when undefined. (Myron Marston, #597) * Don't inadvertently define `BasicObject` in 1.8.7. (Chris Griego, #603) * Fix `include` matcher so that it fails gracefully when matched against an object that does not respond to `include?`. (Myron Marston, #607) ### 3.0.2 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.1...v3.0.2) Bug Fixes: * Fix regression in `contain_exactly` (AKA `match_array`) that caused it to wrongly pass when the expected array was empty. (Myron Marston, #581) * Provide a better error message when you use the `change(obj, :msg)` form of the change matcher but forget the message argument. (Alex Sunderland, #585) * Make the `contain_exactly` matcher work with arrays that contain hashes in arbitrary ordering. (Sam Phippen, #578) ### 3.0.1 / 2014-06-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0...v3.0.1) Bug Fixes: * Add a missing `require` that would cause the `respond_to` matcher to fail when used in a project where the rest of RSpec (e.g. core and expecatations) weren't being used. (Myron Marston, #566) * Structs are no longer treated as arrays when diffed. (Jon Rowe, #576) ### 3.0.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.rc1...v3.0.0) No code changes. Just taking it out of pre-release. ### 3.0.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.beta2...v3.0.0.rc1) Breaking Changes for 3.0.0: * Remove `matcher_execution_context` attribute from DSL-defined custom matchers. (Myron Marston) * Remove `RSpec::Matchers::Pretty#_pretty_print`. (Myron Marston) * Remove `RSpec::Matchers::Pretty#expected_to_sentence`. (Myron Marston) * Rename `RSpec::Matchers::Configuration` constant to `RSpec::Expectations::Configuration`. (Myron Marston) * Prevent `have_xyz` predicate matchers using private methods. (Adrian Gonzalez) * Block matchers must now implement `supports_block_expectations?`. (Myron Marston) * Stop supporting `require 'rspec-expectations'`. Use `require 'rspec/expectations'` instead. (Myron Marston) Bug Fixes: * Fix `NoMethodError` triggered by beta2 when `YARD` was loaded in the test environment. (Myron Marston) * Fix `be_xyz` matcher to accept a `do...end` block. (Myron Marston) * Fix composable matcher failure message generation logic so that it does not blow up when given `$stdout` or `$stderr`. (Myron Marston) * Fix `change` matcher to work properly with `IO` objects. (Myron Marston) * Fix `exist` matcher so that it can be used in composed matcher expressions involving objects that do not implement `exist?` or `exists?`. (Daniel Fone) * Fix composable matcher match logic so that it clones matchers before using them in order to work properly with matchers that use internal memoization based on a given `actual` value. (Myron Marston) * Fix `be_xyz` and `has_xyz` predicate matchers so that they can be used in composed matcher expressions involving objects that do not implement the predicate method. (Daniel Fone) Enhancements: * Document the remaining public APIs. rspec-expectations now has 100% of the public API documented and will remain that way (as new undocumented methods will fail the build). (Myron Marston) * Improve the formatting of BigDecimal objects in `eq` matcher failure messages. (Daniel Fone) * Improve the failure message for `be_xyz` predicate matchers so that it includes the `inspect` output of the receiver. (Erik Michaels-Ober, Sam Phippen) * Add `all` matcher, to allow you to specify that a given matcher matches all elements in a collection: `expect([1, 3, 5]).to all( be_odd )`. (Adam Farhi) * Add boolean aliases (`&`/`|`) for compound operators (`and`/`or`). (Adam Farhi) * Give users a clear error when they wrongly use a value matcher in a block expectation expression (e.g. `expect { 3 }.to eq(3)`) or vice versa. (Myron Marston) ### 3.0.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.0.beta1...v3.0.0.beta2) Breaking Changes for 3.0.0: * Remove deprecated support for accessing the `RSpec` constant using `Rspec` or `Spec`. (Myron Marston) * Remove deprecated `RSpec::Expectations.differ=`. (Myron Marston) * Remove support for deprecated `expect(...).should`. (Myron Marston) * Explicitly disallow `expect { }.not_to change { }` with `by`, `by_at_least`, `by_at_most` or `to`. These have never been supported but did not raise explicit errors. (Myron Marston) * Provide `===` rather than `==` as an alias of `matches?` for all matchers. The semantics of `===` are closer to an RSpec matcher than `==`. (Myron Marston) * Remove deprecated `RSpec::Matchers::OperatorMatcher` constant. (Myron Marston) * Make `RSpec::Expectations::ExpectationNotMetError` subclass `Exception` rather than `StandardError` so they can bypass a bare `rescue` in end-user code (e.g. when an expectation is set from within a rspec-mocks stub implementation). (Myron Marston) * Remove Test::Unit and Minitest 4.x integration. (Myron Marston) Enhancements: * Simplify the failure message of the `be` matcher when matching against: `true`, `false` and `nil`. (Sam Phippen) * Update matcher protocol and custom matcher DSL to better align with the newer `expect` syntax. If you want your matchers to maintain compatibility with multiple versions of RSpec, you can alias the new names to the old. (Myron Marston) * `failure_message_for_should` => `failure_message` * `failure_message_for_should_not` => `failure_message_when_negated` * `match_for_should` => `match` * `match_for_should_not` => `match_when_negated` * Improve generated descriptions from `change` matcher. (Myron Marston) * Add support for compound matcher expressions using `and` and `or`. Simply chain them off of any existing matcher to create an expression like `expect(alphabet).to start_with("a").and end_with("z")`. (Eloy Espinaco) * Add `contain_exactly` as a less ambiguous version of `match_array`. Note that it expects the expected array to be splatted as individual args: `expect(array).to contain_exactly(1, 2)` is the same as `expect(array).to match_array([1, 2])`. (Myron Marston) * Update `contain_exactly`/`match_array` so that it can match against other non-array collections (such as a `Set`). (Myron Marston) * Update built-in matchers so that they can accept matchers as arguments to allow you to compose matchers in arbitrary ways. (Myron Marston) * Add `RSpec::Matchers::Composable` mixin that can be used to make a custom matcher composable as well. Note that custom matchers defined via `RSpec::Matchers.define` already have this. (Myron Marston) * Define noun-phrase aliases for built-in matchers, which can be used when creating composed matcher expressions that read better and provide better failure messages. (Myron Marston) * Add `RSpec::Matchers.alias_matcher` so users can define their own matcher aliases. The `description` of the matcher will reflect the alternate matcher name. (Myron Marston) * Add explicit `be_between` matcher. `be_between` has worked for a long time as a dynamic predicate matcher, but the failure message was suboptimal. The new matcher provides a much better failure message. (Erik Michaels-Ober) * Enhance the `be_between` matcher to allow for `inclusive` or `exclusive` comparison (e.g. inclusive of min/max or exclusive of min/max). (Pedro Gimenez) * Make failure message for `not_to be #{operator}` less confusing by only saying it's confusing when comparison operators are used. (Prathamesh Sonpatki) * Improve failure message of `eq` matcher when `Time` or `DateTime` objects are used so that the full sub-second precision is included. (Thomas Holmes, Jeff Wallace) * Add `output` matcher for expecting that a block outputs `to_stdout` or `to_stderr`. (Luca Pette, Matthias Günther) * Forward a provided block on to the `has_xyz?` method call when the `have_xyz` matcher is used. (Damian Galarza) * Provide integration with Minitest 5.x. Require `rspec/expectations/minitest_integration` after loading minitest to use rspec-expectations with minitest. (Myron Marston) Bug Fixes: * Fix wrong matcher descriptions with falsey expected value (yujinakayama) * Fix `expect { }.not_to change { }.from(x)` so that the matcher only passes if the starting value is `x`. (Tyler Rick, Myron Marston) * Fix hash diffing, so that it colorizes properly and doesn't consider trailing commas when performing the diff. (Jared Norman) * Fix built-in matchers to fail normally rather than raising `ArgumentError` when given an object of the wrong type to match against, so that they work well in composite matcher expressions like `expect([1.51, "foo"]).to include(a_string_matching(/foo/), a_value_within(0.1).of(1.5))`. (Myron Marston) Deprecations: * Retain support for RSpec 2 matcher protocol (e.g. for matchers in 3rd party extension gems like `shoulda`), but it will print a deprecation warning. (Myron Marston) ### 3.0.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.2...v3.0.0.beta1) Breaking Changes for 3.0.0: * Remove explicit support for 1.8.6. (Jon Rowe) * Remove the deprecated `be_close` matcher, preferring `be_within` instead. (Sam Phippen) * Remove the deprecated `have`, `have_at_least` and `have_at_most` matchers. You can continue using those matchers through https://github.com/rspec/rspec-collection_matchers, or you can rewrite your expectations with something like `expect(your_object.size).to eq(num)`. (Hugo Baraúna) * Rename `be_true` and `be_false` to `be_truthy` and `be_falsey`. (Sam Phippen) * Make `expect { }.to_not raise_error(SomeSpecificClass, message)`, `expect { }.to_not raise_error(SomeSpecificClass)` and `expect { }.to_not raise_error(message)` invalid, since they are prone to hiding failures. Instead, use `expect { }.to_not raise_error` (with no args). (Sam Phippen) * Within `RSpec::Matchers.define` blocks, helper methods made available either via `def self.helper` or `extend HelperModule` are no longer available to the `match` block (or any of the others). Instead `include` your helper module and define the helper method as an instance method. (Myron Marston) * Force upgrading Diff::LCS for encoding compatability with diffs. (Jon Rowe) Enhancements: * Support `do..end` style block with `raise_error` matcher. (Yuji Nakayama) * Rewrote custom matcher DSL to simplify its implementation and solve a few issues. (Myron Marston) * Allow early `return` from within custom matcher DSL blocks. (Myron Marston) * The custom matcher DSL's `chain` can now accept a block. (Myron Marston) * Support setting an expectation on a `raise_error` matcher via a chained `with_message` method call. (Sam Phippen) Bug Fixes: * Allow `include` and `match` matchers to be used from within a DSL-defined custom matcher's `match` block. (Myron Marston) * Correct encoding error message on diff failure (Jon Rowe) Deprecations: * Using the old `:should` syntax without explicitly configuring it is deprecated. It will continue to work but will emit a deprecation warning in RSpec 3 if you do not explicitly enable it. (Sam Phippen) ### 2.99.2 / 2014-07-21 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.1...v2.99.2) Bug Fixes: * Fix regression in `Expectations#method_handle_for` where proxy objects with method delegated would wrongly not return a method handle. (Jon Rowe, #594) * Fix issue with detection of generic operator matchers so they work correctly when undefined. (Myron Marston, #597) ### 2.99.1 / 2014-06-19 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0...v2.99.1) Bug Fixes: * Fix typo in custom matcher `expected` deprecation warning -- it's `expected_as_array`, not `expected_array`. (Frederick Cheung, #562) ### 2.99.0 / 2014-06-01 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.rc1...v2.99.0) Enhancements: * Special case deprecation message for `errors_on` with `rspec-rails` to be more useful. (Aaron Kromer) ### 2.99.0.rc1 / 2014-05-18 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta2...2.99.0.rc1) Deprecations: * Deprecate `matcher_execution_context` attribute on DSL-defined custom matchers. (Myron Marston) * Deprecate `RSpec::Matchers::Pretty#_pretty_print`. (Myron Marston) * Deprecate `RSpec::Matchers::Pretty#expected_to_sentence`. (Myron Marston) * Deprecate `RSpec::Matchers::Configuration` in favor of `RSpec::Expectations::Configuration`. (Myron Marston) * Deprecate `be_xyz` predicate matcher on an object that doesn't respond to `xyz?` or `xyzs?`. (Daniel Fone) * Deprecate `have_xyz` matcher on an object that doesn't respond to `has_xyz?`. (Daniel Fone) * Deprecate `have_xyz` matcher on an object that has a private method `has_xyz?`. (Jon Rowe) * Issue a deprecation warning when a block expectation expression is used with a matcher that doesn't explicitly support block expectations via `supports_block_expectations?`. (Myron Marston) * Deprecate `require 'rspec-expectations'`. Use `require 'rspec/expectations'` instead. (Myron Marston) ### 2.99.0.beta2 / 2014-02-17 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta1...v2.99.0.beta2) Deprecations: * Deprecate chaining `by`, `by_at_least`, `by_at_most` or `to` off of `expect { }.not_to change { }`. The docs have always said these are not supported for the negative form but now they explicitly raise errors in RSpec 3. (Myron Marston) * Change the semantics of `expect { }.not_to change { x }.from(y)`. In RSpec 2.x, this expectation would only fail if `x` started with the value of `y` and changed. If it started with a different value and changed, it would pass. In RSpec 3, it will pass only if the value starts at `y` and it does not change. (Myron Marston) * Deprecate `matcher == value` as an alias for `matcher.matches?(value)`, in favor of `matcher === value`. (Myron Marston) * Deprecate `RSpec::Matchers::OperatorMatcher` in favor of `RSpec::Matchers::BuiltIn::OperatorMatcher`. (Myron Marston) * Deprecate auto-integration with Test::Unit and minitest. Instead, include `RSpec::Matchers` in the appropriate test case base class yourself. (Myron Marston) * Deprecate treating `#expected` on a DSL-generated custom matcher as an array when only 1 argument is passed to the matcher method. In RSpec 3 it will be the single value in order to make diffs work properly. (Jon Rowe) ### 2.99.0.beta1 / 2013-11-07 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.99.0.beta1) Deprecations * Deprecate `have`, `have_at_least` and `have_at_most`. You can continue using those matchers through https://github.com/rspec/rspec-collection_matchers, or you can rewrite your expectations with something like `expect(your_object.size).to eq(num)`. (Hugo Baraúna) * Deprecate `be_xyz` predicate matcher when `xyz?` is a private method. (Jon Rowe) * Deprecate `be_true`/`be_false` in favour of `be_truthy`/`be_falsey` (for Ruby's conditional semantics) or `be true`/`be false` (for exact equality). (Sam Phippen) * Deprecate calling helper methods from a custom matcher with the wrong scope. (Myron Marston) * `def self.foo` / `extend Helper` can be used to add macro methods (e.g. methods that call the custom matcher DSL methods), but should not be used to define helper methods called from within the DSL blocks. * `def foo` / `include Helper` is the opposite: it's for helper methods callable from within a DSL block, but not for defining macros. * RSpec 2.x allowed helper methods defined either way to be used for either purpose, but RSpec 3.0 will not. ### 2.14.5 / 2014-02-01 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.14.5) Bug fixes * Fix wrong matcher descriptions with falsey expected value (yujinakayama) ### 2.14.4 / 2013-11-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.3...v2.14.4) Bug fixes * Make the `match` matcher produce a diff output. (Jon Rowe, Ben Moss) * Choose encoding for diff's more intelligently, and when all else fails fall back to default internal encoding with replacing characters. (Jon Rowe) ### 2.14.3 / 2013-09-22 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.2...v2.14.3) Bug fixes * Fix operator matchers (`should` syntax) when `method` is redefined on target. (Brandon Turner) * Fix diffing of hashes with object based keys. (Jon Rowe) * Fix operator matchers (`should` syntax) when operator is defined via `method_missing` (Jon Rowe) ### 2.14.2 / 2013-08-14 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.1...v2.14.2) Bug fixes * Fix `be_` matcher to not support operator chaining like the `be` matcher does (e.g. `be == 5`). This led to some odd behaviors since `be_ == anything` returned a `BeComparedTo` matcher and was thus always truthy. This was a consequence of the implementation (e.g. subclassing the basic `Be` matcher) and was not intended behavior. (Myron Marston). * Fix `change` matcher to compare using `==` in addition to `===`. This is important for an expression like: `expect {}.to change { a.class }.from(ClassA).to(ClassB)` because `SomeClass === SomeClass` returns false. (Myron Marston) ### 2.14.1 / 2013-08-08 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.0...2.14.1) Bug fixes * Ensure diff output uses the same encoding as the encoding of the string being diff'd to prevent `Encoding::UndefinedConversionError` errors (Jon Rowe). ### 2.14.0 / 2013-07-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.0.rc1...v2.14.0) Bug fixes * Values that are not matchers use `#inspect`, rather than `#description` for documentation output (Andy Lindeman, Sam Phippen). * Make `expect(a).to be_within(x).percent_of(y)` work with negative y (Katsuhiko Nishimra). * Make the `be_predicate` matcher work as expected used with `expect{...}.to change...` (Sam Phippen). ### 2.14.0.rc1 / 2013-05-27 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.13.0...v2.14.0.rc1) Enhancements * Enhance `yield_control` so that you can specify an exact or relative number of times: `expect { }.to yield_control.exactly(3).times`, `expect { }.to yield_control.at_least(2).times`, etc (Bartek Borkowski). * Make the differ that is used when an expectation fails better handle arrays by splitting each element of the array onto its own line. (Sam Phippen) * Accept duck-typed strings that respond to `:to_str` as expectation messages. (Toby Ovod-Everett) Bug fixes * Fix differ to not raise errors when dealing with differently-encoded strings (Jon Rowe). * Fix `expect(something).to be_within(x).percent_of(y)` where x and y are both integers (Sam Phippen). * Fix `have` matcher to handle the fact that on ruby 2.0, `Enumerator#size` may return nil (Kenta Murata). * Fix `expect { raise s }.to raise_error(s)` where s is an error instance on ruby 2.0 (Sam Phippen). * Fix `expect(object).to raise_error` passing. This now warns the user and fails the spec (tomykaira). Deprecations * Deprecate `expect { }.not_to raise_error(SpecificErrorClass)` or `expect { }.not_to raise_error("some specific message")`. Using these was prone to hiding failures as they would allow _any other error_ to pass. (Sam Phippen and David Chelimsky) ### 2.13.0 / 2013-02-23 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.12.1...v2.13.0) Enhancements * Add support for percent deltas to `be_within` matcher: `expect(value).to be_within(10).percent_of(expected)` (Myron Marston). * Add support to `include` matcher to allow it to be given a list of matchers as the expecteds to match against (Luke Redpath). Bug fixes * Fix `change` matcher so that it dups strings in order to handle mutated strings (Myron Marston). * Fix `should be =~ /some regex/` / `expect(...).to be =~ /some regex/`. Previously, these either failed with a confusing `undefined method matches?' for false:FalseClass` error or were no-ops that didn't actually verify anything (Myron Marston). * Add compatibility for diff-lcs 1.2 and relax the version constraint (Peter Goldstein). * Fix DSL-generated matchers to allow multiple instances of the same matcher in the same example to have different description and failure messages based on the expected value (Myron Marston). * Prevent `undefined method #split for Array` error when dumping the diff of an array of multiline strings (Myron Marston). * Don't blow up when comparing strings that are in an encoding that is not ASCII compatible (Myron Marston). * Remove confusing "Check the implementation of #==" message printed for empty diffs (Myron Marston). ### 2.12.1 / 2012-12-15 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.12.0...v2.12.1) Bug fixes * Improve the failure message for an expression like `{}.should =~ {}`. (Myron Marston and Andy Lindeman) * Provide a `match_regex` alias so that custom matchers built using the matcher DSL can use it (since `match` is a different method in that context). (Steven Harman) ### 2.12.0 / 2012-11-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.3...v2.12.0) Enhancements * Colorize diffs if the `--color` option is configured. (Alex Coplan) * Include backtraces in unexpected errors handled by `raise_error` matcher (Myron Marston) * Print a warning when users accidentally pass a non-string argument as an expectation message (Sam Phippen) * `=~` and `match_array` matchers output a more useful error message when the actual value is not an array (or an object that responds to `#to_ary`) (Sam Phippen) Bug fixes * Fix `include` matcher so that `expect({}).to include(:a => nil)` fails as it should (Sam Phippen). * Fix `be_an_instance_of` matcher so that `Class#to_s` is used in the description rather than `Class#inspect`, since some classes (like `ActiveRecord::Base`) define a long, verbose `#inspect`. (Tom Stuart) ### 2.11.3 / 2012-09-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.2...v2.11.3) Bug fixes * Fix (and deprecate) `expect { }.should` syntax so that it works even though it was never a documented or intended syntax. It worked as a consequence of the implementation of `expect` in RSpec 2.10 and earlier. (Myron Marston) * Ensure #== is defined on built in matchers so that they can be composed. For example: expect { user.emailed! }.to change { user.last_emailed_at }.to be_within(1.second).of(Time.zone.now) ### 2.11.2 / 2012-07-25 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.1...v2.11.2) Bug fixes * Define `should` and `should_not` on `Object` rather than `BasicObject` on MacRuby. On MacRuby, `BasicObject` is defined but is not the root of the object hierarchy. (Gabriel Gilder) ### 2.11.1 / 2012-07-08 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.11.0...v2.11.1) Bug fixes * Constrain `actual` in `be_within` matcher to values that respond to `-` instead of requiring a specific type. * `Time`, for example, is a legit alternative. ### 2.11.0 / 2012-07-07 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.10.0...v2.11.0) Enhancements * Expand `expect` syntax so that it supports expections on bare values in addition to blocks (Myron Marston). * Add configuration options to control available expectation syntaxes (Myron Marston): * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = :expect }` * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = :should }` * `RSpec.configuration.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }` * `RSpec.configuration.add_should_and_should_not_to Delegator` Bug fixes * Allow only `Numeric` values to be the "actual" in the `be_within` matcher. This prevents confusing error messages. (Su Zhang @zhangsu) * Define `should` and `should_not` on `BasicObject` rather than `Kernel` on 1.9. This makes `should` and `should_not` work properly with `BasicObject`-subclassed proxy objects like `Delegator`. (Myron Marston) ### 2.10.0 / 2012-05-03 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.9.1...v2.10.0) Enhancements * Add new `start_with` and `end_with` matchers (Jeremy Wadsack) * Add new matchers for specifying yields (Myron Marston): * `expect {...}.to yield_control` * `expect {...}.to yield_with_args(1, 2, 3)` * `expect {...}.to yield_with_no_args` * `expect {...}.to yield_successive_args(1, 2, 3)` * `match_unless_raises` takes multiple exception args Bug fixes * Fix `be_within` matcher to be inclusive of delta. * Fix message-specific specs to pass on Rubinius (John Firebaugh) ### 2.9.1 / 2012-04-03 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.9.0...v2.9.1) Bug fixes * Provide a helpful message if the diff between two objects is empty. * Fix bug diffing single strings with multiline strings. * Fix for error with using custom matchers inside other custom matchers (mirasrael) * Fix using execution context methods in nested DSL matchers (mirasrael) ### 2.9.0 / 2012-03-17 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0...v2.9.0) Enhancements * Move built-in matcher classes to RSpec::Matchers::BuiltIn to reduce pollution of RSpec::Matchers (which is included in every example). * Autoload files with matcher classes to improve load time. Bug fixes * Align `respond_to?` and `method_missing` in DSL-defined matchers. * Clear out user-defined instance variables between invocations of DSL-defined matchers. * Dup the instance of a DSL generated matcher so its state is not changed by subsequent invocations. * Treat expected args consistently across positive and negative expectations (thanks to Ralf Kistner for the heads up) ### 2.8.0 / 2012-01-04 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0.rc2...v2.8.0) Enhancements * Better diff output for Hash (Philippe Creux) * Eliminate Ruby warnings (Olek Janiszewski) ### 2.8.0.rc2 / 2011-12-19 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.8.0.rc1...v2.8.0.rc2) No changes for this release. Just releasing with the other rspec gems. ### 2.8.0.rc1 / 2011-11-06 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.7.0...v2.8.0.rc1) Enhancements * Use classes for the built-in matchers (they're faster). * Eliminate Ruby warnings (Matijs van Zuijlen) ### 2.7.0 / 2011-10-16 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.6.0...v2.7.0) Enhancements * `HaveMatcher` converts argument using `to_i` (Alex Bepple & Pat Maddox) * Improved failure message for the `have_xxx` matcher (Myron Marston) * `HaveMatcher` supports `count` (Matthew Bellantoni) * Change matcher dups `Enumerable` before the action, supporting custom `Enumerable` types like `CollectionProxy` in Rails (David Chelimsky) Bug fixes * Fix typo in `have(n).xyz` documentation (Jean Boussier) * fix `safe_sort` for ruby 1.9.2 (`Kernel` now defines `<=>` for Object) (Peter van Hardenberg) ### 2.6.0 / 2011-05-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.5.0...v2.6.0) Enhancements * `change` matcher accepts regexps (Robert Davis) * better descriptions for `have_xxx` matchers (Magnus Bergmark) * `range.should cover(*values)` (Anders Furseth) Bug fixes * Removed non-ascii characters that were choking rcov (Geoffrey Byers) * change matcher dups arrays and hashes so their before/after states can be compared correctly. * Fix the order of inclusion of RSpec::Matchers in Test::Unit::TestCase and MiniTest::Unit::TestCase to prevent a SystemStackError (Myron Marston) ### 2.5.0 / 2011-02-05 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.4.0...v2.5.0) Enhancements * `should exist` works with `exist?` or `exists?` (Myron Marston) * `expect { ... }.not_to do_something` (in addition to `to_not`) Documentation * improved docs for raise_error matcher (James Almond) ### 2.4.0 / 2011-01-02 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.3.0...v2.4.0) No functional changes in this release, which was made to align with the rspec-core-2.4.0 release. Enhancements * improved RDoc for change matcher (Jo Liss) ### 2.3.0 / 2010-12-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.2.1...v2.3.0) Enhancements * diff strings when include matcher fails (Mike Sassak) ### 2.2.0 / 2010-11-28 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.1.0...v2.2.0) ### 2.1.0 / 2010-11-07 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.1...v2.1.0) Enhancements * `be_within(delta).of(expected)` matcher (Myron Marston) * Lots of new Cucumber features (Myron Marston) * Raise error if you try `should != expected` on Ruby-1.9 (Myron Marston) * Improved failure messages from `throw_symbol` (Myron Marston) Bug fixes * Eliminate hard dependency on `RSpec::Core` (Myron Marston) * `have_matcher` - use pluralize only when ActiveSupport inflections are indeed defined (Josep M Bach) * throw_symbol matcher no longer swallows exceptions (Myron Marston) * fix matcher chaining to avoid name collisions (Myron Marston) ### 2.0.0 / 2010-10-10 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.rc...v2.0.0) Enhancements * Add match_for_should_not method to matcher DSL (Myron Marston) Bug fixes * `respond_to` matcher works correctly with `should_not` with multiple methods (Myron Marston) * `include` matcher works correctly with `should_not` with multiple values (Myron Marston) ### 2.0.0.rc / 2010-10-05 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.beta.22...v2.0.0.rc) Enhancements * `require 'rspec/expectations'` in a T::U or MiniUnit suite (Josep M. Bach) Bug fixes * change by 0 passes/fails correctly (Len Smith) * Add description to satisfy matcher ### 2.0.0.beta.22 / 2010-09-12 [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v2.0.0.beta.20...v2.0.0.beta.22) Enhancements * diffing improvements * diff multiline strings * don't diff single line strings * don't diff numbers (silly) * diff regexp + multiline string Bug fixes * `should[_not]` change now handles boolean values correctly ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/CODE_OF_CONDUCT.md0000664000000000000000000000544414557700001023210 0ustar rootroot # Contributor Code of Conduct For the purpose of building a welcoming, harassment-free community that values contributions from anyone, the RSpec project has adopted the following code of conduct. All contributors and participants (including maintainers!) are expected to abide by its terms. As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the project maintainers listed at https://rspec.info/about/. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/3/0/ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Gemfile0000664000000000000000000000553214557700001021702 0ustar rootrootsource "https://rubygems.org" gemspec branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp %w[rspec rspec-core rspec-mocks rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path else gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end if RUBY_VERSION < '1.9.3' gem 'rake', '< 11.0.0' # rake 11 requires Ruby 1.9.3 or later elsif RUBY_VERSION < '2.0.0' gem 'rake', '< 12.0.0' # rake 12 requires Ruby 2.0.0 or later elsif RUBY_VERSION < '2.2.0' gem 'rake', '12.3.2' else gem 'rake', '>= 12.3.3' end if ENV['DIFF_LCS_VERSION'] gem 'diff-lcs', ENV['DIFF_LCS_VERSION'] else gem 'diff-lcs', '~> 1.4', '>= 1.4.3' end gem 'coderay' # for syntax highlighting gem 'yard', '~> 0.9.24', :require => false ### deps for rdoc.info group :documentation do gem 'redcarpet', :platform => :mri gem 'github-markup', :platform => :mri end group :coverage do gem 'simplecov' end if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java' gem 'json', '< 2.0.0' # is a dependency of simplecov else gem 'json', '> 2.3.0' end # allow gems to be installed on older rubies and/or windows if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.10' elsif RUBY_VERSION < '2.4.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem 'ffi', '< 1.15' elsif RUBY_VERSION < '1.9' gem 'ffi', '< 1.9.19' # ffi dropped Ruby 1.8 support in 1.9.19 elsif RUBY_VERSION < '2.0' gem 'ffi', '< 1.11.0' # ffi dropped Ruby 1.9 support in 1.11.0 else gem 'ffi', '> 1.9.24' # prevent Github security vulnerability warning end if RUBY_VERSION <= '2.3.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/) gem "childprocess", "< 1.0.0" elsif RUBY_VERSION < '2.0.0' gem "childprocess", "< 1.0.0" else gem "childprocess", "> 1.0.0" end if RUBY_VERSION < '2.0.0' gem 'thor', '< 1.0.0' else gem 'thor', '> 1.0.0' end if RUBY_VERSION < '1.9.2' gem 'contracts', '~> 0.15.0' # is a dependency of aruba end # Version 5.12 of minitest requires Ruby 2.4 if RUBY_VERSION < '2.4.0' gem 'minitest', '< 5.12.0' end platforms :jruby do if RUBY_VERSION < '1.9.0' # Pin jruby-openssl on older J Ruby gem "jruby-openssl", "< 0.10.0" else gem "jruby-openssl" end end if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' gem 'rubocop', "~> 1.0", "< 1.12" end if RUBY_VERSION < '2.0.0' gem 'cucumber', "<= 1.3.22" elsif !ENV['DIFF_LCS_VERSION'].to_s.empty? && ENV['DIFF_LCS_VERSION'].scan(/\d\.\d/).first.to_f < 1.5 # Older version of diff-lcs cause a downstream error with cucumber and modern rails gem "activesupport", "< 7" end eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom') ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Gemfile-custom.sample0000664000000000000000000000051114557700001024462 0ustar rootrootgroup :development do gem 'interactive_rspec' gem 'guard-rspec', '~> 1.2.1' gem 'growl', '1.0.3' gem 'spork', '0.9.0' platform :mri do gem 'rb-fsevent', '~> 0.9.0' gem 'ruby-prof', '~> 0.10.0' case RUBY_VERSION when /^1.8/ gem 'ruby-debug' when /^1.9/ gem 'debugger' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/REPORT_TEMPLATE.md0000664000000000000000000000211714557700001023233 0ustar rootroot # Report template ```ruby # frozen_string_literal: true begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "rspec", "3.7.0" # Activate the gem and version you are reporting the issue against. end puts "Ruby version is: #{RUBY_VERSION}" require 'rspec/autorun' RSpec.describe 'additions' do it 'returns 2' do expect(1 + 1).to eq(2) end it 'returns 1' do expect(3 - 1).to eq(-1) end end ``` Simply copy the content of the appropriate template into a `.rb` file on your computer and make the necessary changes to demonstrate the issue. You can execute it by running `ruby rspec_report.rb` in your terminal. You can then share your executable test case as a [gist](https://gist.github.com), or simply paste the content into the issue description. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.document0000664000000000000000000000006014557700001022215 0ustar rootrootlib/**/*.rb - README.md LICENSE.md Changelog.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.yardopts0000664000000000000000000000011414557700001022244 0ustar rootroot--exclude features --no-private --markup markdown - Changelog.md LICENSE.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.rspec0000664000000000000000000000004114557700001021512 0ustar rootroot--warnings --require spec_helper ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.rubocop_todo.yml0000664000000000000000000002515714557700001023713 0ustar rootroot# This configuration was generated by # `rubocop --auto-gen-config` # on 2022-01-09 00:30:11 UTC using RuboCop version 1.11.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: with_first_argument, with_fixed_indentation Layout/ArgumentAlignment: Exclude: - 'spec/rspec/expectations/handler_spec.rb' - 'spec/rspec/expectations_spec.rb' - 'spec/rspec/matchers/built_in/yield_spec.rb' # Offense count: 15 # Cop supports --auto-correct. Layout/ClosingHeredocIndentation: Exclude: - 'lib/rspec/matchers/built_in/equal.rb' - 'lib/rspec/matchers/generated_descriptions.rb' - 'spec/rspec/matchers/built_in/all_spec.rb' - 'spec/rspec/matchers/built_in/contain_exactly_spec.rb' - 'spec/rspec/matchers/built_in/equal_spec.rb' # Offense count: 68 # Cop supports --auto-correct. Layout/EmptyLineAfterGuardClause: Enabled: false # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: AllowAliasSyntax, AllowedMethods. # AllowedMethods: alias_method, public, protected, private Layout/EmptyLinesAroundAttributeAccessor: Exclude: - 'lib/rspec/expectations/configuration.rb' - 'spec/rspec/matchers/built_in/be_between_spec.rb' # Offense count: 17 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses Layout/FirstArgumentIndentation: Exclude: - 'spec/rspec/expectations/failure_aggregator_spec.rb' - 'spec/rspec/matchers/aliases_spec.rb' - 'spec/rspec/matchers/built_in/compound_spec.rb' - 'spec/rspec/matchers/composable_spec.rb' - 'spec/rspec/matchers/expecteds_for_multiple_diffs_spec.rb' - 'spec/rspec/matchers_spec.rb' # Offense count: 12 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table # SupportedColonStyles: key, separator, table # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit Layout/HashAlignment: Exclude: - 'lib/rspec/expectations/configuration.rb' - 'rspec-expectations.gemspec' - 'spec/rspec/expectations/handler_spec.rb' - 'spec/rspec/matchers/composable_spec.rb' - 'spec/rspec/matchers/description_generation_spec.rb' # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: Width, IgnoredPatterns. Layout/IndentationWidth: Exclude: - 'lib/rspec/matchers/built_in/be.rb' - 'lib/rspec/matchers/built_in/be_kind_of.rb' - 'lib/rspec/matchers/built_in/start_or_end_with.rb' - 'lib/rspec/matchers/dsl.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideHashLiteralBraces: Exclude: - 'spec/rspec/matchers/built_in/be_spec.rb' # Offense count: 10 # Configuration parameters: AllowedMethods. # AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'spec/rspec/matchers/built_in/be_between_spec.rb' - 'spec/rspec/matchers/built_in/be_spec.rb' - 'spec/rspec/matchers/built_in/have_attributes_spec.rb' - 'spec/rspec/matchers/built_in/include_spec.rb' - 'spec/rspec/matchers/built_in/raise_error_spec.rb' - 'spec/rspec/matchers/description_generation_spec.rb' - 'spec/rspec/matchers/expecteds_for_multiple_diffs_spec.rb' # Offense count: 2 Lint/FloatComparison: Exclude: - 'spec/rspec/matchers/built_in/operators_spec.rb' - 'spec/spec_helper.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowedImplicitNamespaces. # AllowedImplicitNamespaces: Gem Lint/RaiseException: Exclude: - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Lint/RedundantCopDisableDirective: Exclude: - 'spec/rspec/matchers/built_in/change_spec.rb' - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/RedundantRequireStatement: Exclude: - 'spec/rspec/matchers/built_in/eq_spec.rb' # Offense count: 2 Lint/StructNewOverride: Exclude: - 'spec/rspec/expectations/syntax_spec.rb' # Offense count: 1 # Configuration parameters: AllowComments. Lint/SuppressedException: Exclude: - 'benchmarks/**/*' - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 3 # Configuration parameters: IgnoredPatterns. # IgnoredPatterns: (?-mix:(exactly|at_least|at_most)\(\d+\)\.times) Lint/UnreachableLoop: Exclude: - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: - 'spec/rspec/matchers/built_in/be_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: Exclude: - 'spec/rspec/expectations/failure_aggregator_spec.rb' - 'spec/rspec/matchers/built_in/be_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowComments. Lint/UselessMethodDefinition: Exclude: - 'lib/rspec/matchers.rb' # Offense count: 3 # Cop supports --auto-correct. Lint/UselessTimes: Exclude: - 'spec/rspec/matchers/built_in/yield_spec.rb' # Offense count: 1 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 27 # Offense count: 69 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: Exclude: - 'benchmarks/caller_vs_raise_for_backtrace.rb' - 'benchmarks/method_to_proc.rb' - 'lib/rspec/expectations/minitest_integration.rb' - 'lib/rspec/matchers/built_in/count_expectation.rb' - 'lib/rspec/matchers/built_in/equal.rb' - 'lib/rspec/matchers/built_in/operators.rb' - 'lib/rspec/matchers/built_in/respond_to.rb' - 'spec/rspec/matchers/aliased_matcher_spec.rb' - 'spec/rspec/matchers/built_in/equal_spec.rb' - 'spec/rspec/matchers/built_in/respond_to_spec.rb' - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: Exclude: - 'lib/rspec/matchers/built_in/base_matcher.rb' - 'lib/rspec/matchers/built_in/raise_error.rb' - 'lib/rspec/matchers/built_in/throw_symbol.rb' - 'lib/rspec/matchers/dsl.rb' # Offense count: 1 # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Exclude: - 'lib/rspec/matchers/built_in/base_matcher.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'spec/rspec/matchers/built_in/has_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/CaseLikeIf: Exclude: - 'lib/rspec/matchers/built_in/has.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. # IgnoredMethods: ==, equal?, eql? Style/ClassEqualityComparison: Exclude: - 'spec/rspec/matchers/aliases_spec.rb' - 'spec/support/matchers.rb' # Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: Keywords. # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE Style/CommentAnnotation: Exclude: - 'lib/rspec/expectations/handler.rb' - 'spec/rspec/matchers/built_in/respond_to_spec.rb' - 'spec/rspec/matchers/dsl_spec.rb' - 'spec/support/shared_examples/block_matcher.rb' - 'spec/support/shared_examples/matcher.rb' # Offense count: 1 # Cop supports --auto-correct. Style/EmptyLiteral: Exclude: - 'spec/rspec/matchers/built_in/include_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Style/ExpandPathArguments: Exclude: - 'Gemfile' - 'rspec-expectations.gemspec' # Offense count: 2 # Cop supports --auto-correct. Style/ExplicitBlockArgument: Exclude: - 'spec/rspec/matchers/built_in/all_spec.rb' - 'spec/rspec/matchers/built_in/contain_exactly_spec.rb' # Offense count: 5 # Cop supports --auto-correct. Style/GlobalStdStream: Exclude: - 'spec/rspec/matchers/built_in/change_spec.rb' - 'spec/rspec/matchers/composable_spec.rb' # Offense count: 7 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/rspec/matchers/built_in/contain_exactly.rb' - 'lib/rspec/matchers/built_in/has.rb' - 'lib/rspec/matchers/built_in/raise_error.rb' - 'lib/rspec/matchers/dsl.rb' - 'lib/rspec/matchers/matcher_delegator.rb' - 'spec/rspec/matchers/built_in/compound_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'spec/spec_helper.rb' # Offense count: 24 # Cop supports --auto-correct. Style/RedundantRegexpEscape: Exclude: - 'lib/rspec/matchers/built_in/throw_symbol.rb' - 'spec/rspec/matchers/built_in/raise_error_spec.rb' - 'spec/rspec/matchers/composable_spec.rb' - 'spec/rspec/matchers/dsl_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Style/RedundantSelf: Exclude: - 'spec/rspec/matchers/built_in/be_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - 'lib/rspec/matchers/built_in/operators.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowModifier. Style/SoleNestedConditional: Exclude: - 'spec/rspec/expectations/failure_aggregator_spec.rb' # Offense count: 7 # Cop supports --auto-correct. Style/StringConcatenation: Exclude: - 'lib/rspec/matchers/built_in/all.rb' - 'lib/rspec/matchers/built_in/be.rb' - 'lib/rspec/matchers/built_in/compound.rb' - 'lib/rspec/matchers/built_in/contain_exactly.rb' - 'lib/rspec/matchers/built_in/yield.rb' - 'spec/rspec/matchers/aliased_matcher_spec.rb' ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/maintenance-branch0000664000000000000000000000002114557700001024033 0ustar rootroot3-13-maintenance ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/README.md0000664000000000000000000002212614557700001021664 0ustar rootroot# RSpec Expectations [![Build Status](https://github.com/rspec/rspec-expectations/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-expectations/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations) RSpec::Expectations lets you express expected outcomes on an object in an example. ```ruby expect(account.balance).to eq(Money.new(37.42, :USD)) ``` ## Install If you want to use rspec-expectations with rspec, just install the rspec gem and RubyGems will also install rspec-expectations for you (along with rspec-core and rspec-mocks): gem install rspec Want to run against the `main` branch? You'll need to include the dependent RSpec repos as well. Add the following to your `Gemfile`: ```ruby %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib| gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main' end ``` If you want to use rspec-expectations with another tool, like Test::Unit, Minitest, or Cucumber, you can install it directly: gem install rspec-expectations ## Contributing Once you've set up the environment, you'll need to cd into the working directory of whichever repo you want to work in. From there you can run the specs and cucumber features, and make patches. NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You can treat each RSpec repo as an independent project. - [Build details](BUILD_DETAIL.md) - [Code of Conduct](CODE_OF_CONDUCT.md) - [Detailed contributing guide](CONTRIBUTING.md) - [Development setup guide](DEVELOPMENT.md) ## Basic usage Here's an example using rspec-core: ```ruby RSpec.describe Order do it "sums the prices of the items in its line items" do order = Order.new order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(1.11, :USD) ))) order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(2.22, :USD), :quantity => 2 ))) expect(order.total).to eq(Money.new(5.55, :USD)) end end ``` The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`, `Item` and `Money` classes would be from _your_ code. The last line of the example expresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then the example passes. If not, it fails with a message like: expected: # got: # ## Built-in matchers ### Equivalence ```ruby expect(actual).to eq(expected) # passes if actual == expected expect(actual).to eql(expected) # passes if actual.eql?(expected) expect(actual).not_to eql(not_expected) # passes if not(actual.eql?(expected)) ``` Note: The new `expect` syntax no longer supports the `==` matcher. ### Identity ```ruby expect(actual).to be(expected) # passes if actual.equal?(expected) expect(actual).to equal(expected) # passes if actual.equal?(expected) ``` ### Comparisons ```ruby expect(actual).to be > expected expect(actual).to be >= expected expect(actual).to be <= expected expect(actual).to be < expected expect(actual).to be_within(delta).of(expected) ``` ### Regular expressions ```ruby expect(actual).to match(/expression/) ``` Note: The new `expect` syntax no longer supports the `=~` matcher. ### Types/classes ```ruby expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected expect(actual).to be_a(expected) # passes if actual.kind_of?(expected) expect(actual).to be_an(expected) # an alias for be_a expect(actual).to be_a_kind_of(expected) # another alias ``` ### Truthiness ```ruby expect(actual).to be_truthy # passes if actual is truthy (not nil or false) expect(actual).to be true # passes if actual == true expect(actual).to be_falsy # passes if actual is falsy (nil or false) expect(actual).to be false # passes if actual == false expect(actual).to be_nil # passes if actual is nil expect(actual).to_not be_nil # passes if actual is not nil ``` ### Expecting errors ```ruby expect { ... }.to raise_error expect { ... }.to raise_error(ErrorClass) expect { ... }.to raise_error("message") expect { ... }.to raise_error(ErrorClass, "message") ``` ### Expecting throws ```ruby expect { ... }.to throw_symbol expect { ... }.to throw_symbol(:symbol) expect { ... }.to throw_symbol(:symbol, 'value') ``` ### Yielding ```ruby expect { |b| 5.tap(&b) }.to yield_control # passes regardless of yielded args expect { |b| yield_if_true(true, &b) }.to yield_with_no_args # passes only if no args are yielded expect { |b| 5.tap(&b) }.to yield_with_args(5) expect { |b| 5.tap(&b) }.to yield_with_args(Integer) expect { |b| "a string".tap(&b) }.to yield_with_args(/str/) expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) ``` ### Predicate matchers ```ruby expect(actual).to be_xxx # passes if actual.xxx? expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg) ``` ### Ranges (Ruby >= 1.9 only) ```ruby expect(1..10).to cover(3) ``` ### Collection membership ```ruby # exact order, entire collection expect(actual).to eq(expected) # exact order, partial collection (based on an exact position) expect(actual).to start_with(expected) expect(actual).to end_with(expected) # any order, entire collection expect(actual).to match_array(expected) # You can also express this by passing the expected elements # as individual arguments expect(actual).to contain_exactly(expected_element1, expected_element2) # any order, partial collection expect(actual).to include(expected) ``` #### Examples ```ruby expect([1, 2, 3]).to eq([1, 2, 3]) # Order dependent equality check expect([1, 2, 3]).to include(1) # Exact ordering, partial collection matches expect([1, 2, 3]).to include(2, 3) # expect([1, 2, 3]).to start_with(1) # As above, but from the start of the collection expect([1, 2, 3]).to start_with(1, 2) # expect([1, 2, 3]).to end_with(3) # As above but from the end of the collection expect([1, 2, 3]).to end_with(2, 3) # expect({:a => 'b'}).to include(:a => 'b') # Matching within hashes expect("this string").to include("is str") # Matching within strings expect("this string").to start_with("this") # expect("this string").to end_with("ring") # expect([1, 2, 3]).to contain_exactly(2, 3, 1) # Order independent matches expect([1, 2, 3]).to match_array([3, 2, 1]) # # Order dependent compound matchers expect( [{:a => 'hash'},{:a => 'another'}] ).to match([a_hash_including(:a => 'hash'), a_hash_including(:a => 'another')]) ``` ## `should` syntax In addition to the `expect` syntax, rspec-expectations continues to support the `should` syntax: ```ruby actual.should eq expected actual.should be > 3 [1, 2, 3].should_not include 4 ``` See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/main/Should.md) ## Compound Matcher Expressions You can also create compound matcher expressions using `and` or `or`: ``` ruby expect(alphabet).to start_with("a").and end_with("z") expect(stoplight.color).to eq("red").or eq("green").or eq("yellow") ``` ## Composing Matchers Many of the built-in matchers are designed to take matchers as arguments, to allow you to flexibly specify only the essential aspects of an object or data structure. In addition, all of the built-in matchers have one or more aliases that provide better phrasing for when they are used as arguments to another matcher. ### Examples ```ruby expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) ) expect { s = "barn" }.to change { s } .from( a_string_matching(/foo/) ) .to( a_string_matching(/bar/) ) expect(["barn", 2.45]).to contain_exactly( a_value_within(0.1).of(2.5), a_string_starting_with("bar") ) expect(["barn", "food", 2.45]).to end_with( a_string_matching("foo"), a_value > 2 ) expect(["barn", 2.45]).to include( a_string_starting_with("bar") ) expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/)) hash = { :a => { :b => ["foo", 5], :c => { :d => 2.05 } } } expect(hash).to match( :a => { :b => a_collection_containing_exactly( a_string_starting_with("f"), an_instance_of(Integer) ), :c => { :d => (a_value < 3) } } ) expect { |probe| [1, 2, 3].each(&probe) }.to yield_successive_args( a_value < 2, 2, a_value > 2 ) ``` ## Usage outside rspec-core You always need to load `rspec/expectations` even if you only want to use one part of the library: ```ruby require 'rspec/expectations' ``` Then simply include `RSpec::Matchers` in any class: ```ruby class MyClass include RSpec::Matchers def do_something(arg) expect(arg).to be > 0 # do other stuff end end ``` ## Also see * [https://github.com/rspec/rspec](https://github.com/rspec/rspec) * [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core) * [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks) * [https://github.com/rspec/rspec-rails](https://github.com/rspec/rspec-rails) ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Rakefile0000664000000000000000000000215014557700001022045 0ustar rootrootrequire 'bundler' Bundler.setup Bundler::GemHelper.install_tasks require 'rake' require 'rspec/core/rake_task' require 'rspec/expectations/version' require 'cucumber/rake/task' Cucumber::Rake::Task.new(:cucumber) if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' require 'rubocop/rake_task' RuboCop::RakeTask.new(:rubocop) end desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.ruby_opts = %w[-w] end namespace :clobber do desc "delete generated .rbc files" task :rbc do sh 'find . -name "*.rbc" | xargs rm' end end desc "delete generated files" task :clobber => ["clobber:rbc"] do rm_rf 'doc' rm_rf '.yardoc' rm_rf 'pkg' rm_rf 'tmp' rm_rf 'coverage' end if RUBY_VERSION >= '2.4' && RUBY_ENGINE == 'ruby' task :default => [:spec, :cucumber, :rubocop] else task :default => [:spec, :cucumber] end task :verify_private_key_present do private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') unless File.exist?(private_key) raise "Your private key is not present. This gem should not be built without it." end end task :build => :verify_private_key_present ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/0000775000000000000000000000000014557700001021334 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/0000775000000000000000000000000014557700001022450 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations_spec.rb0000664000000000000000000000164414557700001026522 0ustar rootrootrequire 'rspec/support/spec/library_wide_checks' RSpec.describe "RSpec::Expectations" do allowed_loaded_features = [ /stringio/, # Used by `output` matcher. Can't be easily avoided. /rbconfig/ # required by rspec-support ] # Truffleruby cext files allowed_loaded_features << /\/truffle\/cext/ if RSpec::Support::Ruby.truffleruby? it_behaves_like "library wide checks", "rspec-expectations", :preamble_for_lib => [ # We define minitest constants because rspec/expectations/minitest_integration # expects these constants to already be defined. "module Minitest; class Assertion; end; module Test; end; end", 'require "rspec/expectations"' ], :allowed_loaded_feature_regexps => allowed_loaded_features it 'does not allow expectation failures to be caught by a bare rescue' do expect { expect(2).to eq(3) rescue nil }.to fail_including("expected: 3") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/0000775000000000000000000000000014557700001025156 5ustar rootroot././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/block_snippet_extractor_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/block_snippet_extractor_sp0000664000000000000000000002110614557700001032532 0ustar rootrootrequire 'rspec/expectations/block_snippet_extractor' module RSpec::Expectations RSpec.describe BlockSnippetExtractor, :if => RSpec::Support::RubyFeatures.ripper_supported? do subject(:extractor) do BlockSnippetExtractor.new(proc_object, 'target_method') end let(:proc_object) do @proc_object end def target_method(*, &block) @proc_object = block end def another_method(*) end before do expression end describe '.try_extracting_single_line_body_of' do subject(:try_extracting_single_line_body) do BlockSnippetExtractor.try_extracting_single_line_body_of(proc_object, 'target_method') end context 'with a single line body block' do let(:expression) do target_method { 1.positive? } end it 'returns the body' do expect(try_extracting_single_line_body).to eq('1.positive?') end end context 'with a multiline body block' do let(:expression) do target_method do 1.positive? 2.negative? end end it 'returns nil' do expect(try_extracting_single_line_body).to be_nil end end context 'when the block snippet cannot be extracted due to ambiguity' do let(:expression) do target_method { 1.positive? }; dummy_object.target_method { 2.negative? } end let(:dummy_object) do double('dummy_object', :target_method => nil) end it 'returns nil' do expect(try_extracting_single_line_body).to be_nil end end end describe '#body_content_lines' do subject(:body_content_lines) do extractor.body_content_lines end context 'with `target_method {}`' do let(:expression) do target_method {} end it 'returns empty lines' do expect(body_content_lines).to eq([]) end end context 'with `target_method { body }`' do let(:expression) do target_method { 1.positive? } end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with `target_method do body end`' do let(:expression) do target_method do 1.positive? end end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with `target_method { |arg1, arg2| body }`' do let(:expression) do target_method { |_arg1, _arg2| 1.positive? } end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with `target_method(:arg1, :arg2) { body }`' do let(:expression) do target_method(:arg1, :arg2) { 1.positive? } end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with `target_method(:arg1,:arg2){|arg1,arg2|body}`' do let(:expression) do target_method(:arg1, :arg2) { |_arg1, _arg2|1.positive? } end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with a multiline block containing a single line body' do let(:expression) do target_method do 1.positive? end end it 'returns the body content lines' do expect(body_content_lines).to eq(['1.positive?']) end end context 'with a multiline body block' do let(:expression) do target_method do 1.positive? 2.negative? end end it 'returns the body content lines' do expect(body_content_lines).to eq([ '1.positive?', '2.negative?' ]) end end context 'with `target_method { { :key => "value" } }`' do let(:expression) do target_method { { :key => "value" } } end it 'does not confuse the hash curly with the block closer' do expect(body_content_lines).to eq(['{ :key => "value" }']) end end context 'with a do-end block containing another do-end block' do let(:expression) do target_method do 2.times do |index| puts index end end end it 'does not confuse the inner `end` with the outer `end`' do expect(body_content_lines).to eq([ '2.times do |index|', 'puts index', 'end' ]) end end context "when there's another method invocation on the same line before the target" do let(:expression) do another_method { 2.negative? }; target_method { 1.positive? } end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context "when there's another method invocation on the same line after the target" do let(:expression) do target_method { 1.positive? }; another_method { 2.negative? } end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context "when there's another method invocation with the same name on the same line before the target" do let(:expression) do dummy_object.target_method { 2.negative? }; target_method { 1.positive? } end let(:dummy_object) do double('dummy_object', :target_method => nil) end it 'raises AmbiguousTargetError' do expect { body_content_lines }.to raise_error(BlockSnippetExtractor::AmbiguousTargetError) end end context "when there's another method invocation with the same name on the same line after the target" do let(:expression) do target_method { 1.positive? }; dummy_object.target_method { 2.negative? } end let(:dummy_object) do double('dummy_object', :target_method => nil) end it 'raises AmbiguousTargetError' do expect { body_content_lines }.to raise_error(BlockSnippetExtractor::AmbiguousTargetError) end end context "when there's another method invocation with the same name without block on the same line before the target" do let(:expression) do dummy_object.target_method; target_method { 1.positive? } end let(:dummy_object) do double('dummy_object', :target_method => nil) end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context "when there's another method invocation with the same name without block on the same line after the target" do let(:expression) do target_method { 1.positive? }; dummy_object.target_method end let(:dummy_object) do double('dummy_object', :target_method => nil) end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context 'when a hash is given as an argument' do let(:expression) do target_method({ :key => "value" }) { 1.positive? } end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context 'when another method invocation with block is given as an argument' do let(:expression) do target_method(another_method { 2.negative? }) { 1.positive? } end it 'correctly extracts the target snippet' do expect(body_content_lines).to eq(['1.positive?']) end end context "when the block literal is described on different line with the method invocation" do let(:expression) do block = proc { 1.positive? } target_method(&block) end it 'raises TargetNotFoundError' do expect { body_content_lines }.to raise_error(BlockSnippetExtractor::TargetNotFoundError) end end context 'with &:symbol syntax' do let(:expression) do target_method(&:positive?) end it 'raises TargetNotFoundError' do expect { body_content_lines }.to raise_error(BlockSnippetExtractor::TargetNotFoundError) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/syntax_spec.rb0000664000000000000000000000622714557700001030052 0ustar rootrootmodule RSpec module Expectations RSpec.describe Syntax do context "when passing a message to an expectation" do let(:warner) { ::Kernel } let(:string_like_object) do Struct.new(:to_str, :to_s).new(*(["Ceci n'est pas une Chaine."]*2)) end let(:insufficiently_string_like_object) do Struct.new(:to_s).new("Ceci n'est pas une Chaine.") end let(:callable_object) do Struct.new(:call).new("Ceci n'est pas une Chaine.") end describe "expect(...).to" do it "prints a warning when the message object isn't a String" do expect(warner).to receive(:warn).with(/ignoring.*message/) expect(3).to eq(3), :not_a_string end it "doesn't print a warning when message is a String" do expect(warner).not_to receive(:warn) expect(3).to eq(3), "a string" end it "doesn't print a warning when message responds to to_str" do expect(warner).not_to receive(:warn) expect(3).to eq(3), string_like_object end it "prints a warning when the message object handles to_s but not to_str" do expect(warner).to receive(:warn).with(/ignoring.*message/) expect(3).to eq(3), insufficiently_string_like_object end it "doesn't print a warning when message responds to call" do expect(warner).not_to receive(:warn) expect(3).to eq(3), callable_object end end describe "expect(...).not_to" do it "prints a warning when the message object isn't a String" do expect(warner).to receive(:warn).with(/ignoring.*message/) expect(3).not_to eq(4), :not_a_string end it "doesn't print a warning when message is a String" do expect(warner).not_to receive(:warn) expect(3).not_to eq(4), "a string" end it "doesn't print a warning when message responds to to_str" do expect(warner).not_to receive(:warn) expect(3).not_to eq(4), string_like_object end it "prints a warning when the message object handles to_s but not to_str" do expect(warner).to receive(:warn).with(/ignoring.*message/) expect(3).not_to eq(4), insufficiently_string_like_object end it "doesn't print a warning when message responds to call" do expect(warner).not_to receive(:warn) expect(3).not_to eq(4), callable_object end end end describe "enabling the should syntax on something other than the default syntax host" do include_context "with the default expectation syntax" it "continues to warn about the should syntax" do my_host = Class.new expect(RSpec).to receive(:deprecate) Syntax.enable_should(my_host) 3.should eq 3 end end end end RSpec.describe Expectations do it "does not inadvertently define BasicObject on 1.8", :if => RUBY_VERSION.to_f < 1.9 do expect(defined?(::BasicObject)).to be nil end end end ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/minitest_integration_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/minitest_integration_spec.0000664000000000000000000000113314557700001032426 0ustar rootrootmodule RSpec RSpec.describe Matchers do let(:sample_matchers) do [:be, :be_instance_of, :be_kind_of] end context "once required", :slow do include MinitestIntegration it "includes itself in Minitest::Test, and sets up our exceptions to be counted as assertion failures" do with_minitest_loaded do minitest_case = ::Minitest::Test.allocate expect(minitest_case).to respond_to(*sample_matchers) expect(RSpec::Expectations::ExpectationNotMetError).to be ::Minitest::Assertion end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/failure_aggregator_spec.rb0000664000000000000000000004233114557700001032351 0ustar rootrootmodule RSpec::Expectations RSpec.describe FailureAggregator, "when used via `aggregate_failures`" do it 'does not raise an error when no expectations fail' do expect { aggregate_failures do expect(1).to be_odd expect(2).to be_even expect(3).to be_odd end }.not_to raise_error end it 'returns true when no expectations fail' do expect( aggregate_failures do expect(1).to be_odd expect(2).to be_even expect(3).to be_odd end ).to eq true end it 'aggregates multiple failures into one exception that exposes all the failures' do expect { aggregate_failures('block label', :some => :metadata) do expect(1).to be_even expect(2).to be_odd expect(3).to be_even end }.to raise_error(an_object_having_attributes( :class => MultipleExpectationsNotMetError, :failures => [ an_object_having_attributes(:message => "expected `1.even?` to return true, got false"), an_object_having_attributes(:message => "expected `2.odd?` to return true, got false"), an_object_having_attributes(:message => "expected `3.even?` to return true, got false") ], :other_errors => [], :aggregation_block_label => 'block label', :aggregation_metadata => { :some => :metadata } )) end it 'ensures the exposed failures have backtraces' do aggregation_line = __LINE__ + 2 expect { aggregate_failures do expect(1).to be_even expect(2).to be_odd expect(3).to be_even end }.to raise_error do |error| expect(error.failures.map(&:backtrace)).to match [ a_collection_including(a_string_including(__FILE__, (aggregation_line + 1).to_s)), a_collection_including(a_string_including(__FILE__, (aggregation_line + 2).to_s)), a_collection_including(a_string_including(__FILE__, (aggregation_line + 3).to_s)) ] end end def common_contiguous_frame_percent(failure, aggregate) failure_frames = failure.backtrace.reverse aggregate_frames = aggregate.backtrace.reverse first_differing_index = failure_frames.zip(aggregate_frames).index { |f, a| f != a } 100 * (first_differing_index / failure_frames.count.to_f) end it 'ensures the sub-failure backtraces are in a form that overlaps with the aggregated failure backtrace' do if RSpec::Support::Ruby.jruby? pending "This is broken on 9.2.x.x" unless RSpec::Support::Ruby.jruby_version < '9.2.0.0' end # On JRuby, `caller` and `raise` backtraces can differ significantly -- # I've seen one include java frames but not the other -- and as a result, # the backtrace truncation rspec-core does (based on the common part) fails # and produces undesirable output. This spec is a guard against that. expect { aggregate_failures do expect(1).to be_even expect(2).to be_odd end }.to raise_error do |error| failure_1, failure_2 = error.failures expect(common_contiguous_frame_percent(failure_1, error)).to be > 70 expect(common_contiguous_frame_percent(failure_2, error)).to be > 70 end end def notify_error_with(backtrace) exception = Exception.new exception.set_backtrace backtrace RSpec::Support.notify_failure(exception) end it 'does not stomp the backtrace on failures that have it' do backtrace = ["./foo.rb:13"] expect { aggregate_failures do notify_error_with(backtrace) notify_error_with(backtrace) end }.to raise_error do |error| expect(error.failures.map(&:backtrace)).to eq([backtrace, backtrace]) end end it 'supports nested `aggregate_failures` blocks' do expect { aggregate_failures("outer") do aggregate_failures("inner 2") do expect(2).to be_odd expect(3).to be_even end aggregate_failures("inner 1") do expect(1).to be_even end expect(1).to be_even end }.to raise_error do |error| aggregate_failures("failure expectations") do expect(error.failures.count).to eq(3) expect(error.failures[0]).to be_an_instance_of(RSpec::Expectations::MultipleExpectationsNotMetError) expect(error.failures[0].failures.count).to eq(2) expect(error.failures[1]).to be_an_instance_of(RSpec::Expectations::ExpectationNotMetError) expect(error.failures[2]).to be_an_instance_of(RSpec::Expectations::ExpectationNotMetError) end end end it 'raises a normal `ExpectationNotMetError` when only one expectation fails' do expect { aggregate_failures do expect(1).to be_odd expect(2).to be_odd expect(3).to be_odd end }.to fail_with("expected `2.odd?` to return true, got false") end context "when multiple exceptions are notified with the same `:source_id`" do it 'keeps only the first' do expect { aggregate_failures do RSpec::Support.notify_failure(StandardError.new("e1"), :source_id => "1") RSpec::Support.notify_failure(StandardError.new("e2"), :source_id => "2") RSpec::Support.notify_failure(StandardError.new("e3"), :source_id => "1") RSpec::Support.notify_failure(StandardError.new("e4"), :source_id => "1") end }.to raise_error do |e| expect(e.failures).to match [ an_object_having_attributes(:message => "e1"), an_object_having_attributes(:message => "e2") ] end end end context "when an error other than an expectation failure occurs" do def expect_error_included_in_aggregated_failure(error) expect { aggregate_failures do expect(2).to be_odd raise error end }.to raise_error(an_object_having_attributes( :class => MultipleExpectationsNotMetError, :failures => [an_object_having_attributes( :message => "expected `2.odd?` to return true, got false" )], :other_errors => [error] )) end it "includes the error in the raised aggregated failure when an expectation failed as well" do expect_error_included_in_aggregated_failure StandardError.new("boom") end it "handles direct `Exceptions` and not just `StandardError` and descendents" do expect_error_included_in_aggregated_failure Exception.new("boom") end it "allows the error to propagate as-is if there have been no expectation failures so far" do error = StandardError.new("boom") expect { aggregate_failures do raise error end }.to raise_error(error) end it "prevents later expectations from even running" do error = StandardError.new("boom") later_expectation_executed = false expect { aggregate_failures do raise error later_expectation_executed = true # rubocop:disable Lint/UnreachableCode expect(1).to eq(1) end }.to raise_error(error) expect(later_expectation_executed).to be false end it 'provides an `all_exceptions` array containing failures and other errors' do error = StandardError.new("boom") expect { aggregate_failures do expect(2).to be_odd raise error end }.to raise_error do |aggregate_error| expect(aggregate_error).to have_attributes( :class => MultipleExpectationsNotMetError, :all_exceptions => [ an_object_having_attributes(:message => "expected `2.odd?` to return true, got false"), error ] ) end end end context "when an expectation failure happens in another thread" do # On Ruby 2.5+, the new `report_on_exception` causes the errors in the threads # to print warnings, which our rspec-support test harness converts into a test # failure since we want to enforce warnings-free code. To prevent the warning, # we need to disable the setting here. if Thread.respond_to?(:report_on_exception) around do |example| orig = Thread.report_on_exception Thread.report_on_exception = false example.run Thread.report_on_exception = orig end end it "includes the failure in the failures array if there are other failures" do expect { aggregate_failures do expect(1).to be_even Thread.new { expect(2).to be_odd }.join end }.to raise_error(an_object_having_attributes( :class => MultipleExpectationsNotMetError, :failures => [ an_object_having_attributes(:message => "expected `1.even?` to return true, got false"), an_object_having_attributes(:message => "expected `2.odd?` to return true, got false") ], :other_errors => [] )) end it "propagates it as-is if there are no other failures or errors" do expect { aggregate_failures { Thread.new { expect(2).to be_odd }.join } }.to fail_with("expected `2.odd?` to return true, got false") end end describe 'with MockExpectationError' do it 'does not allow modifications of the failure list in the test example' do expect { aggregate_failures do dbl = double array = dbl.get(2) array << :foo end }.to raise_error( be_a(MultipleExpectationsNotMetError).and have_attributes( :failures => [ be_a(RSpec::Mocks::MockExpectationError) ], :other_errors => [ # Checking only the class name, not the full message, because the hehaviour differes bettern Ruby 2 and 3. # Ruby 3 uses #inspect in NoMethodError, while Ruby 2.x uses format that I can't override: # NoMethodError (undefined method `<<' for #) # even if I override #to_s be_a(NoMethodError).and(have_attributes(:message => /AggregatedFailure/)) ] ) ) end end describe "message formatting" do it "enumerates the failures with an index label, the path of each failure and a blank line in between" do expect { aggregate_failures do expect(1).to be_even expect(2).to be_odd expect(3).to be_even end }.to fail_including { dedent <<-EOS } | 1) expected `1.even?` to return true, got false | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 6}#{exception_complement(5)} | | 2) expected `2.odd?` to return true, got false | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 8}#{exception_complement(5)} | | 3) expected `3.even?` to return true, got false | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 10}#{exception_complement(5)} EOS end it 'mentions how many failures there are' do expect { aggregate_failures do expect(1).to be_even expect(2).to be_odd expect(3).to be_even end }.to fail_including { dedent <<-EOS } |Got 3 failures from failure aggregation block: | | 1) expected `1.even?` to return true, got false EOS end it 'allows the user to name the `aggregate_failures` block' do expect { aggregate_failures("testing odd vs even") do expect(1).to be_even expect(2).to be_odd expect(3).to be_even end }.to fail_including { dedent <<-EOS } |Got 3 failures from failure aggregation block "testing odd vs even": | | 1) expected `1.even?` to return true, got false EOS end context "when another error has occcured" do it 'includes it in the failure message' do expect { aggregate_failures do expect(1).to be_even raise "boom" end }.to fail_including { dedent <<-EOS } |Got 1 failure and 1 other error from failure aggregation block: | | 1) expected `1.even?` to return true, got false | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 7}#{exception_complement(6)} | | 2) RuntimeError: boom | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 9}#{exception_complement(6)} EOS end end context "when the failure messages have multiple lines" do RSpec::Matchers.define :fail_with_multiple_lines do match { false } failure_message do |actual| "line 1\n#{actual}\nline 3" end end it "indents them appropriately so that they still line up" do expect { aggregate_failures do expect(:a).to fail_with_multiple_lines expect(:b).to fail_with_multiple_lines end }.to fail_including { dedent <<-EOS } | 1) line 1 | a | line 3 | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 7}#{exception_complement(6)} | | 2) line 1 | b | line 3 | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 11}#{exception_complement(6)} EOS end it 'accounts for the width of the index when indenting' do expect { aggregate_failures do 1.upto(10) do |i| expect(i).to fail_with_multiple_lines end end }.to fail_including { dedent <<-EOS } | 9) line 1 | 9 | line 3 | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 7}#{exception_complement(7)} | | 10) line 1 | 10 | line 3 | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 12}#{exception_complement(7)} EOS end end context "when the failure messages starts and ends with line breaks (as the `eq` failure message does)" do before do expect { expect(1).to eq(2) }.to fail_with( a_string_starting_with("\n") & ending_with("\n") ) end it 'strips the excess line breaks so that it formats well' do expect { aggregate_failures do expect(1).to eq 2 expect(1).to eq 3 expect(1).to eq 4 end }.to fail_including { dedent <<-EOS } | 1) expected: 2 | got: 1 | | (compared using ==) | | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 10}#{exception_complement(6)} | | 2) expected: 3 | got: 1 | | (compared using ==) | | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 16}#{exception_complement(6)} | | 3) expected: 4 | got: 1 | | (compared using ==) | | ./spec/rspec/expectations/failure_aggregator_spec.rb:#{__LINE__ - 22}#{exception_complement(6)} EOS end end # Use a normal `expect(...).to include` expectation rather than # a composed matcher here. This provides better failure output # because `MultipleExpectationsNotMetError#message` is lazily # computed (rather than being computed in `initialize` and passed # to `super`), which causes the `inspect` output of the exception # to not include the message for some reason. def fail_including fail { |e| expect(e.message).to include(yield) } end # Each Ruby version return a different exception complement. # This method gets the current version and return the # right complement. if RSpec::Support::Ruby.mri? && RUBY_VERSION > "1.8.7" def exception_complement(block_levels) ":in `block (#{block_levels} levels) in '" end elsif RSpec::Support::Ruby.mri? def exception_complement(block_levels) "" end elsif RSpec::Support::Ruby.truffleruby? def exception_complement(block_levels) ":in `block (#{block_levels} levels) in '" end elsif RUBY_VERSION > "2.0.0" def exception_complement(block_levels) ":in `block in Expectations'" end else def exception_complement(block_levels) ":in `Expectations'" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/extensions/0000775000000000000000000000000014557700001027355 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/extensions/kernel_spec.rb0000664000000000000000000000477714557700001032213 0ustar rootrootRSpec.describe Object, "#should" do before(:example) do @target = "target" @matcher = double("matcher", :supports_value_expectations? => true) allow(@matcher).to receive(:matches?).and_return(true) allow(@matcher).to receive(:failure_message) end it "accepts and interacts with a matcher" do expect(@matcher).to receive(:matches?).with(@target).and_return(true) expect(@target).to @matcher end it "asks for a failure_message when matches? returns false" do expect(@matcher).to receive(:matches?).with(@target).and_return(false) expect(@matcher).to receive(:failure_message).and_return("the failure message") expect { expect(@target).to @matcher }.to fail_with("the failure message") end context "on interpreters that have BasicObject", :if => defined?(BasicObject) do let(:proxy_class) do Class.new(BasicObject) do def initialize(target) @target = target end def proxied? true end def respond_to?(method, *args) method.to_sym == :proxied? || @target.respond_to?(symbol, *args) end def method_missing(name, *args) @target.send(name, *args) end end end it 'works properly on BasicObject-subclassed proxy objects' do expect(proxy_class.new(Object.new)).to be_proxied end it 'does not break the deprecation check on BasicObject-subclassed proxy objects' do begin should_enabled = RSpec::Expectations::Syntax.should_enabled? RSpec::Expectations::Syntax.enable_should unless should_enabled proxy_class.new(BasicObject.new).should be_proxied ensure RSpec::Expectations::Syntax.disable_should if should_enabled end end end end RSpec.describe Object, "#should_not" do before(:example) do @target = "target" @matcher = double("matcher", :supports_value_expectations? => true) end it "accepts and interacts with a matcher" do expect(@matcher).to receive(:matches?).with(@target).and_return(false) allow(@matcher).to receive(:failure_message_when_negated) expect(@target).not_to @matcher end it "asks for a failure_message_when_negated when matches? returns true" do expect(@matcher).to receive(:matches?).with(@target).and_return(true) expect(@matcher).to receive(:failure_message_when_negated).and_return("the failure message for should not") expect { expect(@target).not_to @matcher }.to fail_with("the failure message for should not") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/handler_spec.rb0000664000000000000000000002257214557700001030142 0ustar rootrootmodule ExampleExpectations class ArbitraryMatcher def initialize(*args, &block) if args.last.is_a? Hash @expected = args.last[:expected] end @expected = yield if block @block = block end def matches?(target) @target = target return @expected == target end def with(new_value) @expected = new_value self end def failure_message "expected #{@expected}, got #{@target}" end def failure_message_when_negated "expected not #{@expected}, got #{@target}" end end class PositiveOnlyMatcher < ArbitraryMatcher undef failure_message_when_negated rescue nil end def arbitrary_matcher(*args, &block) ArbitraryMatcher.new(*args, &block) end def positive_only_matcher(*args, &block) PositiveOnlyMatcher.new(*args, &block) end end module RSpec module Expectations RSpec.describe PositiveExpectationHandler do include ExampleExpectations it "handles submitted args" do expect(5).to arbitrary_matcher(:expected => 5) expect(5).to arbitrary_matcher(:expected => "wrong").with(5) expect { expect(5).to arbitrary_matcher(:expected => 4) }.to fail_with("expected 4, got 5") expect { expect(5).to arbitrary_matcher(:expected => 5).with(4) }.to fail_with("expected 4, got 5") expect(5).not_to arbitrary_matcher(:expected => 4) expect(5).not_to arbitrary_matcher(:expected => 5).with(4) expect { expect(5).not_to arbitrary_matcher(:expected => 5) }.to fail_with("expected not 5, got 5") expect { expect(5).not_to arbitrary_matcher(:expected => 4).with(5) }.to fail_with("expected not 5, got 5") end it "handles the submitted block" do expect(5).to arbitrary_matcher { 5 } expect(5).to arbitrary_matcher(:expected => 4) { 5 } expect(5).to arbitrary_matcher(:expected => 4).with(5) { 3 } end describe "#handle_matcher" do it "asks the matcher if it matches" do matcher = double("matcher") actual = Object.new expect(matcher).to receive(:matches?).with(actual).and_return(true) RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher) end it "returns the match value" do matcher = double("matcher") actual = Object.new expect(matcher).to receive(:matches?).with(actual).and_return(:this_value) expect(RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher)).to eq :this_value end it "calls failure_message if the matcher implements it" do matcher = double("matcher", :failure_message => "message", :matches? => false) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("message") RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher) end it "calls fail if matcher.diffable?" do matcher = double("matcher", :diffable? => true, :failure_message => "message", :matches? => false, :expected => 1, :actual => 2 ) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("message", 1, 2) RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher) end it "calls failure_message if the matcher does not implement failure_message" do matcher = double("matcher", :failure_message => "message", :matches? => false) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("message") RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher) end it "uses the custom failure message when one is provided" do matcher = double("matcher", :failure_message => "message", :matches? => false) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("custom") RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher, "custom") end it "uses the custom failure message when one is provided as a callable object" do matcher = double("matcher", :failure_message => "message", :matches? => false) actual = Object.new failure_message = double("failure message", :call => "custom") expect(::RSpec::Expectations).to receive(:fail_with).with("custom") RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher, failure_message) end it "add custom failure message to mock matcher if there is one" do error_generator = instance_double("RSpec::Mocks::ErrorGenerator", :opts => { :message => {} }) verifying_message_expectation = instance_double( "RSpec::Mocks::VerifyingMessageExpectation", :error_generator => error_generator ) matcher = double("matcher", :failure_message => "message", :matches? => verifying_message_expectation) actual = Object.new handle_matcher_result = RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher, "custom") expect(handle_matcher_result.error_generator.opts).to eq({ :message => "custom" }) end end end RSpec.describe NegativeExpectationHandler do describe "#handle_matcher" do context "when the matcher responds to `does_not_match?`" do it "returns true when `does_not_match?` returns true" do matcher = double("matcher") actual = Object.new expect(matcher).to receive(:does_not_match?).with(actual).and_return(true) expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to be_truthy end it "raises an expectation failure when `does_not_match?` returns false" do matcher = double("matcher", :failure_message_when_negated => "Error!") actual = Object.new expect(matcher).to receive(:does_not_match?).with(actual).and_return(false) expect { RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher) }.to raise_error(RSpec::Expectations::ExpectationNotMetError, "Error!") end end context "when the matcher does not respond to `does_not_match?`" do it "returns true when `matches?` returns false" do matcher = double("matcher") actual = Object.new expect(matcher).to receive(:matches?).with(actual).and_return(false) expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to be_truthy end it "raises an expectation failure when `matches?` returns true" do matcher = double("matcher", :failure_message_when_negated => "Error!") actual = Object.new expect(matcher).to receive(:matches?).with(actual).and_return(true) expect { RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher) }.to raise_error(RSpec::Expectations::ExpectationNotMetError, "Error!") end end it "calls fail if matcher.diffable?" do matcher = double("matcher", :diffable? => true, :failure_message_when_negated => "message", :matches? => true, :expected => 1, :actual => 2 ) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("message", 1, 2) RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher) end it "uses the custom failure message when one is provided" do matcher = double("matcher", :failure_message_when_negated => "message", :matches? => true) actual = Object.new expect(::RSpec::Expectations).to receive(:fail_with).with("custom") RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher, "custom") end it "uses the custom failure message when one is provided as a callable object" do matcher = double("matcher", :failure_message_when_negated => "message", :matches? => true) actual = Object.new failure_message = double("failure message", :call => "custom") expect(::RSpec::Expectations).to receive(:fail_with).with("custom") RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher, failure_message) end it "add custom failure message to mock matcher if there is one" do error_generator = instance_double("RSpec::Mocks::ErrorGenerator", :opts => { :message => {} }) verifying_message_expectation = instance_double( "RSpec::Mocks::VerifyingMessageExpectation", :error_generator => error_generator ) matcher = double( "matcher", :failure_message_when_negated => "custom", :does_not_match? => verifying_message_expectation ) actual = Object.new handle_matcher_result = RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher, "custom") expect(handle_matcher_result.error_generator.opts).to eq({ :message => "custom" }) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/fail_with_spec.rb0000664000000000000000000000427114557700001030467 0ustar rootrootRSpec.describe RSpec::Expectations, "#fail_with" do let(:differ) { double("differ") } before(:example) do allow(RSpec::Matchers.configuration).to receive_messages(:color? => false) allow(RSpec::Expectations).to receive(:differ) { differ } end it "includes a diff if expected and actual are diffable" do expect(differ).to receive(:diff).and_return("diff text") expect { RSpec::Expectations.fail_with "message", "abc", "def" }.to fail_with("message\nDiff:diff text") end it "does not include the diff if expected and actual are not diffable" do expect(differ).to receive(:diff).and_return("") expect { RSpec::Expectations.fail_with "message", "abc", "def" }.to fail_with("message") end it "raises an error if message is not present" do expect(differ).not_to receive(:diff) expect { RSpec::Expectations.fail_with nil }.to raise_error(ArgumentError, /Failure message is nil\./) end end RSpec.describe RSpec::Expectations, "#fail_with with matchers" do include RSpec::Support::Spec::DiffHelpers before do allow(RSpec::Matchers.configuration).to receive_messages(:color? => false) end it "uses matcher descriptions in place of matchers in diffs" do expected = [a_string_matching(/foo/), a_string_matching(/bar/)] actual = ["poo", "car"] expected_diff = dedent(<<-EOS) | |@@ #{one_line_header} @@ |-["poo", "car"] |+[(a string matching /foo/), (a string matching /bar/)] | EOS expect { RSpec::Expectations.fail_with "message", actual, expected }.to fail_with("message\nDiff:#{expected_diff}") end end RSpec.describe RSpec::Expectations, "#fail_with with --color" do include RSpec::Support::Spec::DiffHelpers before do allow(RSpec::Matchers.configuration).to receive_messages(:color? => true) end it "tells the differ to use color" do expected = "foo bar baz\n" actual = "foo bang baz\n" expected_diff = "\e[0m\n\e[0m\e[34m@@ #{one_line_header} @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m" expect { RSpec::Expectations.fail_with "message", actual, expected }.to fail_with("message\nDiff:#{expected_diff}") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/configuration_spec.rb0000664000000000000000000002414114557700001031366 0ustar rootrootmodule RSpec module Expectations RSpec.describe Configuration do let(:config) { Configuration.new } describe "#backtrace_formatter" do let(:original_backtrace) { %w[ clean-me/a.rb other/file.rb clean-me/b.rb ] } let(:cleaned_backtrace) { %w[ other/file.rb ] } let(:formatted_backtrace) do config.backtrace_formatter.format_backtrace(original_backtrace) end before do @old_patterns = RSpec.configuration.backtrace_exclusion_patterns @orig_full_backtrace = RSpec.configuration.full_backtrace? RSpec.configuration.full_backtrace = false RSpec.configuration.backtrace_exclusion_patterns = [/clean-me/] end after do RSpec.configuration.backtrace_exclusion_patterns = @old_patterns RSpec.configuration.full_backtrace = @orig_full_backtrace end it "defaults to rspec-core's backtrace formatter when rspec-core is loaded" do expect(config.backtrace_formatter).to be(RSpec.configuration.backtrace_formatter) expect(formatted_backtrace).to eq(cleaned_backtrace) end it "defaults to a null formatter when rspec-core is not loaded" do RSpec::Mocks.with_temporary_scope do rspec_dup = ::RSpec.dup class << rspec_dup; undef configuration; end stub_const("RSpec", rspec_dup) expect(formatted_backtrace).to eq(original_backtrace) end end it "can be set to another backtrace formatter" do config.backtrace_formatter = double(:format_backtrace => ['a']) expect(formatted_backtrace).to eq(['a']) end end context 'on an interpreter that does not provide BasicObject', :uses_should, :unless => defined?(::BasicObject) do def with_delegate in_sub_process_if_possible do require 'delegate' RSpec::Expectations::Syntax.disable_should(Delegator) yield end end let(:klass) do Class.new(SimpleDelegator) do def delegated?; true; end end end let(:instance) { klass.new(Object.new) } it 'provides a means to manually add it Delegator' do with_delegate do instance.should_not respond_to(:delegated?) # because #should is being delegated... config.add_should_and_should_not_to Delegator instance.should respond_to(:delegated?) # now it should work! end end end describe "#include_chain_clauses_in_custom_matcher_descriptions?" do it "is false by default" do expect(config.include_chain_clauses_in_custom_matcher_descriptions?).to be false end it "can be set to true" do config.include_chain_clauses_in_custom_matcher_descriptions = true expect(config.include_chain_clauses_in_custom_matcher_descriptions?).to be true end it "can be set back to false" do config.include_chain_clauses_in_custom_matcher_descriptions = true config.include_chain_clauses_in_custom_matcher_descriptions = false expect(config.include_chain_clauses_in_custom_matcher_descriptions?).to be false end end describe "#max_formatted_output_length=" do before do @orig_max_formatted_output_length = RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length end after do config.max_formatted_output_length = @orig_max_formatted_output_length end let(:object_with_large_inspect_string) { Struct.new(:value).new("a"*300) } it "sets the maximum object formatter length" do config.max_formatted_output_length = 10 expect(RSpec::Support::ObjectFormatter.format(object_with_large_inspect_string)).to eq("#") end it "formats the entire object when set to nil" do config.max_formatted_output_length = nil expect(RSpec::Support::ObjectFormatter.format(object_with_large_inspect_string)).to eq(object_with_large_inspect_string.inspect) end end describe "#warn_about_potential_false_positives?" do it "is true by default" do expect(config.warn_about_potential_false_positives?).to be true end it "can be set to false" do config.warn_about_potential_false_positives = false expect(config.warn_about_potential_false_positives?).to be false end it "can be set back to true" do config.warn_about_potential_false_positives = false config.warn_about_potential_false_positives = true expect(config.warn_about_potential_false_positives?).to be true end end describe '#on_potential_false_positives' do it 'is set to :warn by default' do expect(config.on_potential_false_positives).to eq :warn end it 'can be set to :nothing' do config.on_potential_false_positives = :nothing expect(config.on_potential_false_positives).to eq :nothing end it 'can be set back to :warn' do config.on_potential_false_positives = :nothing config.on_potential_false_positives = :warn expect(config.on_potential_false_positives).to eq :warn end it 'can be set to :raise' do config.on_potential_false_positives = :raise expect(config.on_potential_false_positives).to eq :raise end end shared_examples "configuring the expectation syntax" do before do @orig_syntax = RSpec::Matchers.configuration.syntax end after do configure_syntax(@orig_syntax) end it 'can limit the syntax to :should' do configure_syntax :should configured_syntax.should eq([:should]) 3.should eq(3) 3.should_not eq(4) lambda { expect(6).to eq(6) }.should raise_error(NameError) end it 'is a no-op when configured to :should twice' do configure_syntax :should method_added_count = 0 allow(Expectations::Syntax.default_should_host).to receive(:method_added) { method_added_count += 1 } configure_syntax :should method_added_count.should eq(0) end it 'can limit the syntax to :expect' do configure_syntax :expect expect(configured_syntax).to eq([:expect]) expect(3).to eq(3) expect { 3.should eq(3) }.to raise_error(NameError) expect { 3.should_not eq(3) }.to raise_error(NameError) end it 'is a no-op when configured to :expect twice' do allow(RSpec::Matchers).to receive(:method_added).and_raise("no methods should be added here") configure_syntax :expect configure_syntax :expect end describe "`:should` being enabled by default deprecation" do before { configure_default_syntax } it "warns when the should syntax is called by default" do expected_arguments = [ /Using.*without explicitly enabling/, { :replacement => "the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }`" } ] expect(RSpec).to receive(:deprecate).with(*expected_arguments) 3.should eq(3) end it "includes the call site in the deprecation warning by default" do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) 3.should eq(3) end it "does not warn when only the should syntax is explicitly configured" do configure_syntax(:should) RSpec.should_not receive(:deprecate) 3.should eq(3) end it "does not warn when both the should and expect syntaxes are explicitly configured" do configure_syntax([:should, :expect]) expect(RSpec).not_to receive(:deprecate) 3.should eq(3) end end it 'can re-enable the :should syntax' do configure_syntax :expect configure_syntax [:should, :expect] configured_syntax.should eq([:should, :expect]) 3.should eq(3) 3.should_not eq(4) expect(3).to eq(3) end it 'can re-enable the :expect syntax' do configure_syntax :should configure_syntax [:should, :expect] configured_syntax.should eq([:should, :expect]) 3.should eq(3) 3.should_not eq(4) expect(3).to eq(3) end end def configure_default_syntax RSpec::Matchers.configuration.reset_syntaxes_to_default end describe "configuring rspec-expectations directly" do it_behaves_like "configuring the expectation syntax" do def configure_syntax(syntax) RSpec::Matchers.configuration.syntax = syntax end def configured_syntax RSpec::Matchers.configuration.syntax end end end describe "configuring using the rspec-core config API" do it_behaves_like "configuring the expectation syntax" do def configure_syntax(syntax) RSpec.configure do |rspec| rspec.expect_with :rspec do |c| c.syntax = syntax end end end def configured_syntax RSpec.configure do |rspec| rspec.expect_with :rspec do |c| return c.syntax end end end end end it 'enables both syntaxes by default' do # This is kinda a hack, but since we want to enforce use of # the expect syntax within our specs here, we have modified the # config setting, which makes it hard to get at the original # default value. in spec_helper.rb we store the default value # in $default_expectation_syntax so we can use it here. expect($default_expectation_syntax).to contain_exactly(:expect, :should) # rubocop:disable Style/GlobalVars end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/expectations/expectation_target_spec.rb0000664000000000000000000001137714557700001032417 0ustar rootrootmodule RSpec module Expectations RSpec.describe ExpectationTarget do context 'when constructed via #expect' do it 'constructs a new instance targetting the given argument' do expect(expect(7).target).to eq(7) end it 'constructs a new instance targetting the given block' do block = lambda {} expect(expect(&block).target).to be(block) end it 'raises an ArgumentError when given an argument and a block' do expect { expect(7) {} }.to raise_error(ArgumentError) end it 'raises a wrong number of args ArgumentError when given two args' do expect { expect(1, 2) }.to raise_error(ArgumentError, /wrong number of arg/) end it 'raises an ArgumentError when given neither an argument nor a block' do expect { expect }.to raise_error(ArgumentError) end it 'can be passed nil' do expect(expect(nil).target).to be_nil end it 'passes a valid positive expectation' do expect(5).to eq(5) end it 'passes a valid negative expectation' do expect(5).not_to eq(4) end it 'passes a valid negative expectation with a split infinitive' do expect(5).to_not eq(4) end it 'fails an invalid positive expectation' do expect { expect(5).to eq(4) }.to fail_with(/expected: 4.*got: 5/m) end it 'fails an invalid negative expectation' do message = /expected 5 not to be a kind of Integer/ expect { expect(5).not_to be_an(Integer) }.to fail_with(message) end it 'fails an invalid negative expectation with a split infinitive' do message = /expected 5 not to be a kind of Integer/ expect { expect(5).to_not be_an(Integer) }.to fail_with(message) end it 'does not support operator matchers from #to' do expect { expect(3).to == 3 }.to raise_error(ArgumentError) end it 'does not support operator matchers from #not_to' do expect { expect(3).not_to == 4 }.to raise_error(ArgumentError) end end context "when passed a block" do it 'can be used with a block matcher' do expect {}.not_to raise_error end context 'when passed a value matcher' do not_a_block_matcher_error = /You must pass an argument rather than a block to `expect` to use the provided matcher/ it 'raises an error that directs the user to pass an arg rather than a block' do expect { expect {}.to be_an(Object) }.to fail_with(not_a_block_matcher_error) expect { expect {}.not_to be_nil }.to fail_with(not_a_block_matcher_error) expect { expect {}.to_not be_nil }.to fail_with(not_a_block_matcher_error) end it 'assumes a custom matcher that does not define `supports_block_expectations?` is not a block matcher (since it is relatively rare)' do custom_matcher = Module.new do def self.matches?(_value); true; end def self.description; "foo"; end end expect(3).to custom_matcher # to show the custom matcher can be used as a matcher expect { expect { 3 }.to custom_matcher }.to fail_with(not_a_block_matcher_error) end def new_non_dsl_matcher(&method_defs) Module.new do def self.matches?(object); end def self.failure_message; end module_eval(&method_defs) end end it "uses the matcher's `description` in the error message" do custom_matcher = new_non_dsl_matcher do def self.supports_block_expectations?; false; end def self.description; "matcher-description"; end end expect { expect {}.to custom_matcher }.to fail_with(/\(matcher-description\)/) end context 'when the matcher does not define `description` (since it is an optional part of the protocol)' do it 'uses `inspect` in the error message instead' do custom_matcher = new_non_dsl_matcher do def self.supports_block_expectations?; false; end def self.inspect; "matcher-inspect"; end end expect { expect {}.to custom_matcher }.to fail_with(/\(matcher-inspect\)/) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers_spec.rb0000664000000000000000000001225614557700001025623 0ustar rootrootmain = self RSpec.describe RSpec::Matchers do include ::RSpec::Support::InSubProcess describe ".configuration" do it 'returns a memoized configuration instance' do expect(RSpec::Matchers.configuration).to be_a(RSpec::Expectations::Configuration) expect(RSpec::Matchers.configuration).to be(RSpec::Matchers.configuration) end end it 'can be mixed into `main`' do in_sub_process do allow_warning if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' main.instance_eval do include RSpec::Matchers include RSpec::Matchers::FailMatchers expect(3).to eq(3) expect(3).to be_odd expect { expect(4).to be_zero }.to fail_with("expected `4.zero?` to return true, got false") end end end context "when included into a superclass after a subclass has already included it" do if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' desc_start = "print" matcher_method = :output else desc_start = "does not print" matcher_method = :avoid_outputting end it "#{desc_start} a warning so the user is made aware of the MRI 1.9 bug that can cause infinite recursion" do superclass = stub_const("Superclass", Class.new) stub_const("Subclass", Class.new(superclass) { include RSpec::Matchers }) expect { superclass.send(:include, RSpec::Matchers) }.to send(matcher_method, a_string_including( "Superclass", "Subclass", "has been included" )).to_stderr end it "does not warn when this is a re-inclusion" do superclass = stub_const("Superclass", Class.new { include RSpec::Matchers }) stub_const("Subclass", Class.new(superclass) { include RSpec::Matchers }) expect { superclass.send(:include, RSpec::Matchers) }.to avoid_outputting.to_stderr end end describe "#respond_to?" do it "handles dynamic matcher methods" do expect(self).to respond_to(:be_happy, :have_eyes_closed) end it "supports the optional `include_private` arg" do expect(respond_to?(:puts, true)).to eq true expect(respond_to?(:puts, false)).to eq false expect(respond_to?(:puts)).to eq false end it "allows `method` to get dynamic matcher methods", :if => RUBY_VERSION.to_f >= 1.9 do expect(method(:be_happy).call).to be_a(be_happy.class) end end end module RSpec module Matchers RSpec.describe ".is_a_matcher?" do it 'does not match BasicObject', :if => RUBY_VERSION.to_f > 1.8 do expect(RSpec::Matchers.is_a_matcher?(BasicObject.new)).to eq(false) end it 'is registered with RSpec::Support' do expect(RSpec::Support.is_a_matcher?(be_even)).to eq(true) end it 'does not match a multi-element array' do # our original implementation regsitered the matcher definition as # `&RSpec::Matchers.method(:is_a_matcher?)`, which has a bug # on 1.8.7: # # irb(main):001:0> def foo(x); end # => nil # irb(main):002:0> method(:foo).call([1, 2, 3]) # => nil # irb(main):003:0> method(:foo).to_proc.call([1, 2, 3]) # ArgumentError: wrong number of arguments (3 for 1) # from (irb):1:in `foo' # from (irb):1:in `to_proc' # from (irb):3:in `call' # # This spec guards against a regression for that case. expect(RSpec::Support.is_a_matcher?([1, 2, 3])).to eq(false) end end RSpec.describe "built in matchers" do let(:matchers) do BuiltIn.constants.map { |n| BuiltIn.const_get(n) }.select do |m| m.method_defined?(:matches?) && m.method_defined?(:failure_message) end end specify "they all have defined #=== so they can be composable" do missing_threequals = matchers.select do |m| m.instance_method(:===).owner == ::Kernel end # This spec is merely to make sure we don't forget to make # a built-in matcher implement `===`. It doesn't check the # semantics of that. Use the "an RSpec value matcher" and # "an RSpec block-only matcher" shared example groups to # actually check the semantics. expect(missing_threequals).to eq([]) end specify "they all have defined #and and #or so they support compound expectations" do noncompound_matchers = matchers.reject do |m| m.method_defined?(:and) || m.method_defined?(:or) end expect(noncompound_matchers).to eq([]) end shared_examples "a well-behaved method_missing hook" do include MinitestIntegration it "raises a NoMethodError (and not SystemStackError) for an undefined method" do with_minitest_loaded do expect { subject.some_undefined_method }.to raise_error(NoMethodError) end end end describe "RSpec::Matchers method_missing hook", :slow do subject { self } it_behaves_like "a well-behaved method_missing hook" context 'when invoked in a Minitest::Test' do subject { Minitest::Test.allocate } it_behaves_like "a well-behaved method_missing hook" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/0000775000000000000000000000000014557700001024256 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/multi_matcher_diff_spec.rb0000664000000000000000000001025714557700001031447 0ustar rootrootmodule RSpec module Matchers RSpec.describe MultiMatcherDiff do before do stub_const("::RSpec::Matchers::MultiMatcherDiff::DESCRIPTION_MAX_LENGTH", 30) end class FakeDiffer def self.diff(actual, expected) [actual, expected].inspect end end let(:differ) { FakeDiffer } let(:message) { "a message" } let(:actual) { "actual value" } let(:wrapped_value) { described_class.from("expected value", actual) } def create_matcher(stubs) instance_double(BuiltIn::BaseMatcher, stubs.merge( :matches? => true, :actual => actual, :failure_message => "" )) end let(:matcher_1) { create_matcher(:description => "matcher 1 description", :expected => "expected 1") } let(:matcher_2) { create_matcher(:description => "matcher 2 description", :expected => "expected 2") } let(:matcher_3) { create_matcher(:description => "matcher 3 description", :expected => "expected 3") } let(:long_description) { "a very very long description for my custom smart matcher, which can be used for everything" } let(:truncated_description) { "a very very long descriptio..." } let(:matcher_with_long_description) { create_matcher(:description => long_description, :expected => "expected value") } describe ".from" do it "wraps provided value in MultiMatcherDiff" do expect(wrapped_value).to be_a(described_class) end it "returns original value if it was already wrapped" do expect(described_class.from(wrapped_value, actual)).to be(wrapped_value) end end describe ".for_many_matchers" do let(:wrapped_value) { described_class.for_many_matchers([matcher_1, matcher_2, matcher_3]) } it "has a diff for all matchers with their description" do expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message |Diff for (matcher 1 description):["actual value", "expected 1"] |Diff for (matcher 2 description):["actual value", "expected 2"] |Diff for (matcher 3 description):["actual value", "expected 3"] EOS end end describe "#message_with_diff" do it "returns a message warning if the diff is empty" do allow(FakeDiffer).to receive(:diff) { "\e[0m\n\e[0m" } expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message |Diff: | EOS end it "returns just provided message if diff is just whitespace" do allow(FakeDiffer).to receive(:diff) { " \n \t" } expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message EOS end it "returns regular message with diff when single expected" do expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message |Diff:["actual value", "expected value"] EOS end it "returns message with diff and matcher description when single expected with matcher" do matcher = include("expected value") matcher.matches?(actual) wrapped_value = described_class.for_many_matchers([matcher]) expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message |Diff for (include "expected value"):["actual value", ["expected value"]] EOS end it "returns message with diff and truncated matcher description if it is too long" do wrapped_value = described_class.for_many_matchers([matcher_with_long_description]) expect(wrapped_value.message_with_diff( message, differ )).to eq(dedent <<-EOS) |a message |Diff for (#{truncated_description}):["actual value", "expected value"] EOS end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/english_phrasing_spec.rb0000664000000000000000000000540114557700001031141 0ustar rootrootmodule RSpec module Matchers RSpec.describe EnglishPhrasing do describe ".split_words" do it "replaces underscores with spaces" do expect( described_class.split_words(:banana_creme_pie) ).to eq("banana creme pie") end it "first casts its argument to string" do arg = double(:to_s => "banana") expect(described_class.split_words(arg)).to eq("banana") end end describe ".list" do context "given nil" do it "returns value from inspect, and a leading space" do expect(described_class.list(nil)).to eq(" nil") end end context "given a Struct" do it "returns value from inspect, and a leading space" do banana = Struct.new("Banana", :flavor).new expect( described_class.list(banana) ).to eq(" #{banana.inspect}") end end context "given a Hash" do it "returns value from inspect, and a leading space" do banana = { :flavor => 'Banana' } expect( described_class.list(banana) ).to eq(" #{banana.inspect}") end end context "given an Enumerable other than a Hash" do before do allow(RSpec::Support::ObjectFormatter).to( receive(:format).and_return("Banana") ) end context "with zero items" do it "returns the empty string" do expect(described_class.list([])).to eq("") end end context "with one item" do let(:list) { [double] } it "returns description, and a leading space" do expect(described_class.list(list)).to eq(" Banana") expect(RSpec::Support::ObjectFormatter).to( have_received(:format).once ) end end context "with two items" do let(:list) { [double, double] } it "returns descriptions, and a leading space" do expect(described_class.list(list)).to eq(" Banana and Banana") expect(RSpec::Support::ObjectFormatter).to( have_received(:format).twice ) end end context "with three items" do let(:list) { [double, double, double] } it "returns descriptions, and a leading space" do expect( described_class.list(list) ).to eq(" Banana, Banana, and Banana") expect(RSpec::Support::ObjectFormatter).to( have_received(:format).exactly(3).times ) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/dsl_spec.rb0000664000000000000000000012435314557700001026407 0ustar rootrootRSpec.describe "a matcher defined using the matcher DSL" do def question? :answer end def ok "ok" end it "supports calling custom matchers from within other custom matchers" do RSpec::Matchers.define :be_ok do match { |actual| actual == ok } end RSpec::Matchers.define :be_well do match { |actual| expect(actual).to be_ok } end expect(ok).to be_well end it "has access to methods available in the scope of the example" do RSpec::Matchers.define(:matcher_a) {} expect(matcher_a.question?).to eq(:answer) end it "raises when method is missing from local scope as well as matcher" do RSpec::Matchers.define(:matcher_b) {} expect { matcher_b.i_dont_exist }.to raise_error(NameError) end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it 'supports the use of required keyword arguments in definition block' do RSpec::Matchers.define(:match_required_kw) do |bar:| match { expect(actual).to eq bar } end expect(1).to match_required_kw(bar: 1) end def kw(a:) a end it "supports the use of required keyword arguments on methods" do RSpec::Matchers.define(:matcher_required_kw_on_method) {} expect(matcher_required_kw_on_method.kw(a: 1)).to eq(1) end CODE end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it 'supports the use of optional keyword arguments in definition block' do RSpec::Matchers.define(:match_optional_kw) do |bar: nil| match { expect(actual).to eq bar } end expect(1).to match_optional_kw(bar: 1) end def optional_kw(a: nil) a end it "supports the use of optional keyword arguments on methods" do RSpec::Matchers.define(:matcher_optional_kw_on_method) {} expect(matcher_optional_kw_on_method.optional_kw(a: 1)).to eq(1) end CODE end it "clears user instance variables between invocations" do RSpec::Matchers.define(:be_just_like) do |expected| match do |actual| @foo ||= expected @foo == actual end end expect(3).to be_just_like(3) expect(4).to be_just_like(4) end describe '#block_arg' do before(:context) do RSpec::Matchers.define :be_lazily_equal_to do match { actual == block_arg.call } description do "be lazily equal to #{block_arg.call}" end end end it "it is used in a passing condition" do expect(1).to be_lazily_equal_to { 1 } end it "it is used in a failing condition" do expect { expect(1).to be_lazily_equal_to { 2 } }.to fail_with(/be lazily equal to 2/) end end it "warns when passing block to the block of define", :if => (RUBY_VERSION.to_f > 1.8) do expect(RSpec).to receive(:warning).with(/be_warning.*a_block.*block_arg/) RSpec::Matchers.define :be_warning do |&a_block| match { a_block } end end describe "#respond_to?" do it "returns true for methods in example scope" do RSpec::Matchers.define(:matcher_c) {} expect(matcher_c).to respond_to(:question?) end it "returns false for methods not defined in matcher or example scope" do RSpec::Matchers.define(:matcher_d) {} expect(matcher_d).not_to respond_to(:i_dont_exist) end end end class UnexpectedError < StandardError; end module MatcherHelperModule def self.included(base) base.module_exec do def included_method; end end end def self.extended(base) base.instance_exec do def extended_method; end end end def greeting "Hello, World" end end module RSpec::Matchers::DSL RSpec.describe "#alias_matcher" do describe "an alias matcher defined in the current scope" do alias_matcher :be_untrue_in_this_scope, :be_falsy it "is available only in the current scope" do expect(false).to be_untrue_in_this_scope end end describe "an aliased matcher defined in another scope" do it "is not available in the current scope" do expect { expect(false).to be_untrue_in_this_scope }.to fail_with("expected false to respond to `untrue_in_this_scope?`") end end end RSpec.describe "#define_negated_matcher" do describe "a negated matcher defined in the current scope" do define_negated_matcher :be_untrue_in_this_scope, :be_truthy it "is available only in the current scope" do expect(false).to be_untrue_in_this_scope end end describe "a negated matcher defined in another scope" do it "is not available in the current scope" do expect { expect(false).to be_untrue_in_this_scope }.to fail_with("expected false to respond to `untrue_in_this_scope?`") end end end RSpec.describe Matcher do def new_matcher(name, *expected, &block) RSpec::Matchers::DSL::Matcher.new(name, block, self, *expected) end it_behaves_like "an RSpec value matcher", :valid_value => 1, :invalid_value => 2 do let(:matcher) do new_matcher(:equal_to_1) do match { |v| v == 1 } end end end it "can be stored aside and used later" do # Supports using rspec-expectation matchers as argument matchers in # rspec-mocks. RSpec::Matchers.define :example_matcher do |expected| match do |actual| actual == expected end end m1 = example_matcher(1) m2 = example_matcher(2) expect(m1.matches?(1)).to be_truthy expect(m2.matches?(2)).to be_truthy end context 'using deprecated APIs' do before { allow_deprecation } describe "failure_message_for_should" do let(:matcher) do new_matcher(:foo) do match { false } failure_message_for_should { "failed" } end end line = __LINE__ - 3 it 'defines the failure message for a positive expectation' do expect { expect(nil).to matcher }.to fail_with("failed") end it 'prints a deprecation warning' do expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should/) matcher end end describe "failure_message_for_should_not" do let(:matcher) do new_matcher(:foo) do match { true } failure_message_for_should_not { "failed" } end end line = __LINE__ - 3 it 'defines the failure message for a negative expectation' do expect { expect(nil).not_to matcher }.to fail_with("failed") end it 'prints a deprecation warning' do expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should_not/) matcher end end describe "match_for_should" do let(:matcher) do new_matcher(:foo) do match_for_should { |arg| arg } end end line = __LINE__ - 3 it 'defines the positive expectation match logic' do expect(true).to matcher expect { expect(false).to matcher }.to fail_with(/foo/) end it 'prints a deprecation warning' do expect_deprecation_with_call_site(__FILE__, line, /match_for_should/) matcher end end describe "match_for_should_not" do let(:matcher) do new_matcher(:foo) do match_for_should_not { |arg| !arg } end end line = __LINE__ - 3 it 'defines the positive expectation match logic' do expect(false).not_to matcher expect { expect(true).not_to matcher }.to fail_with(/foo/) end it 'prints a deprecation warning' do expect_deprecation_with_call_site(__FILE__, line, /match_for_should_not/) matcher end end end context "with an included module" do let(:matcher) do new_matcher(:be_a_greeting) do include MatcherHelperModule match { |actual| actual == greeting } end end it "has access to the module's methods" do matcher.matches?("Hello, World") end it "runs the module's included hook" do expect(matcher).to respond_to(:included_method) end it "does not run the module's extended hook" do expect(matcher).not_to respond_to(:extended_method) end it 'allows multiple modules to be included at once' do m = new_matcher(:multiple_modules) do include Enumerable include Comparable end expect(m).to be_a(Enumerable) expect(m).to be_a(Comparable) end end context "without overrides" do let(:matcher) do new_matcher(:be_a_multiple_of, 3) do |multiple| match do |actual| actual % multiple == 0 end end end it "provides a default description" do expect(matcher.description).to eq "be a multiple of 3" end it "provides a default positive expectation failure message" do expect { expect(8).to matcher }.to fail_with 'expected 8 to be a multiple of 3' end it "provides a default negative expectation failure message" do expect { expect(9).to_not matcher }.to fail_with 'expected 9 not to be a multiple of 3' end end context "without overrides with chained matchers" do let(:matcher) do new_matcher(:be_bigger_than, 5) do |five| match do |to_match| (to_match > five) && smaller_than_ceiling?(to_match) && divisible_by_divisor?(to_match) end match_when_negated do |to_match| (to_match <= five) || greater_than_ceiling(to_match) && not_divisible_by_divisor?(to_match) end chain :and_smaller_than do |ceiling| @ceiling = ceiling end chain :and_divisible_by do |divisor| @divisor = divisor end private def smaller_than_ceiling?(to_match) to_match < @ceiling end def greater_than_ceiling(to_match) to_match >= @ceiling end def divisible_by_divisor?(to_match) @divisor % to_match == 0 end def not_divisible_by_divisor?(to_match) @divisor % to_match != 0 end end end context "when the matchers are chained" do include_context "isolate include_chain_clauses_in_custom_matcher_descriptions" context "without include_chain_clauses_in_custom_matcher_descriptions configured" do before { RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions = false } let(:match) { matcher.and_smaller_than(10).and_divisible_by(3) } it "provides a default description that does not include any of the chained matchers' descriptions" do expect(match.description).to eq 'be bigger than 5' end it "provides a default positive expectation failure message that does not include any of the chained matchers' descriptions" do expect { expect(8).to match }.to fail_with 'expected 8 to be bigger than 5' end it "provides a default negative expectation failure message that does not include the any of the chained matchers's descriptions" do expect { expect(9).to_not match }.to fail_with 'expected 9 not to be bigger than 5' end end context "with include_chain_clauses_in_custom_matcher_descriptions configured to be true" do before do expect(RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions?).to be true end it "provides a default description that includes the chained matchers' descriptions in they were used" do expect(matcher.and_divisible_by(3).and_smaller_than(29).and_smaller_than(20).and_divisible_by(5).description).to \ eq 'be bigger than 5 and divisible by 3 and smaller than 29 and smaller than 20 and divisible by 5' end it "provides a default positive expectation failure message that includes the chained matchers' failures" do expect { expect(30).to matcher.and_smaller_than(29).and_divisible_by(3) }.to \ fail_with 'expected 30 to be bigger than 5 and smaller than 29 and divisible by 3' end it "provides a default negative expectation failure message that includes the chained matchers' failures" do expect { expect(21).to_not matcher.and_smaller_than(29).and_divisible_by(3) }.to \ fail_with 'expected 21 not to be bigger than 5 and smaller than 29 and divisible by 3' end end it 'only decides if to include the chained clauses at the time description is invoked' do matcher.and_divisible_by(3) expect { RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions = false }.to change { matcher.description }. from('be bigger than 5 and divisible by 3'). to('be bigger than 5') end end end context "with separate match logic for positive and negative expectations" do let(:matcher) do new_matcher(:to_be_composed_of, 7, 11) do |a, b| match do |actual| actual == a * b end match_when_negated do |actual| actual == a + b end end end it "invokes the match block for #matches?" do expect(matcher.matches?(77)).to be_truthy expect(matcher.matches?(18)).to be_falsey end it "invokes the match_when_negated block for #does_not_match?" do expect(matcher.does_not_match?(77)).to be_falsey expect(matcher.does_not_match?(18)).to be_truthy end it "provides a default failure message for negative expectations" do matcher.does_not_match?(77) expect(matcher.failure_message_when_negated).to eq "expected 77 not to to be composed of 7 and 11" end it 'can access helper methods from `match_when_negated`' do matcher = new_matcher(:be_foo) do def foo :foo end match_when_negated do |actual| actual != foo end end expect(matcher.does_not_match?(:bar)).to be true end end it "allows helper methods to be defined with #define_method to have access to matcher parameters" do matcher = new_matcher(:name, 3, 4) do |a, b| define_method(:sum) { a + b } end expect(matcher.sum).to eq 7 end it "is not diffable by default" do matcher = new_matcher(:name) {} expect(matcher).not_to be_diffable end it "is diffable when told to be" do matcher = new_matcher(:name) { diffable } expect(matcher).to be_diffable end it 'handles multiline string diffs' do actual = "LINE1\nline2\n" expected = "line1\nline2\n" matcher = new_matcher(:custom_match, expected) do match { |act| act == expected } diffable end diff = nil begin allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false) expect(actual).to matcher rescue RSpec::Expectations::ExpectationNotMetError => e diff = e.message.sub(/\A.*Diff:/m, "Diff:").gsub(/^\s*/, '') end if Diff::LCS::VERSION.to_f < 1.4 expected_diff = "Diff:\n@@ -1,3 +1,3 @@\n-line1\n+LINE1\nline2\n" else expected_diff = "Diff:\n@@ -1 +1 @@\n-line1\n+LINE1\n" end expect(diff).to eq expected_diff end it 'does not confuse the diffability of different matchers' do # Necessary to guard against a regression that involved # using a class variable to store the diffable state, # which had the side effect of causing all custom matchers # to share that state m1 = new_matcher(:m1) { diffable } m2 = new_matcher(:m2) {} m3 = new_matcher(:m3) { diffable } expect(m1).to be_diffable expect(m2).not_to be_diffable expect(m3).to be_diffable end it "provides expected" do matcher = new_matcher(:name, "expected string") {} expect(matcher.expected).to eq 'expected string' end it "provides expected when there is more than one argument" do matcher = new_matcher(:name, "expected string", "another arg") {} expect(matcher.expected).to eq ['expected string', "another arg"] end it "provides expected_as_array which returns an array regardless of expected" do matcher = new_matcher(:name, "expected string") {} expect(matcher.expected_as_array).to eq ['expected string'] matcher = new_matcher(:name, "expected\nstring") {} expect(matcher.expected_as_array).to eq ["expected\nstring"] matcher = new_matcher(:name, "expected string", "another arg") {} expect(matcher.expected_as_array).to eq ['expected string', "another arg"] end it "provides actual when `match` is used" do matcher = new_matcher(:name, 'expected string') do match { |actual| } end matcher.matches?('actual string') expect(matcher.actual).to eq 'actual string' end it "provides actual when the `match` block accepts splat args" do matcher = new_matcher(:actual) do match { |*actual| actual == [5] } end expect(matcher.matches?(5)).to be true expect(matcher.matches?(4)).to be false end it 'allows an early `return` to be used from a `match` block' do matcher = new_matcher(:with_return, 5) do |expected| match { |actual| return true if expected == actual } end expect(matcher.matches?(5)).to be true expect(matcher.matches?(4)).to be_falsey end it 'provides actual when `match_unless_raises` is used' do matcher = new_matcher(:name, 'expected string') do match_unless_raises(SyntaxError) { |actual| } end matcher.matches?('actual string') expect(matcher.actual).to eq 'actual string' end it 'allows an early `return` to be used from a `match_unless_raises` block' do matcher = new_matcher(:with_return) do match_unless_raises(ArgumentError) do |actual| return actual if [true, false].include?(actual) raise ArgumentError end end expect(matcher.matches?(true)).to be true # It should match even if it returns false, because no error was raised. expect(matcher.matches?(false)).to be true expect(matcher.matches?(4)).to be_falsey end it 'provides actual when `match_when_negated` is used' do matcher = new_matcher(:name, 'expected string') do match_when_negated { |actual| } end matcher.does_not_match?('actual string') expect(matcher.actual).to eq 'actual string' end it 'allows an early `return` to be used from a `match_when_negated` block' do matcher = new_matcher(:with_return, 5) do |expected| match_when_negated { |actual| return true if expected != actual } end expect(matcher.does_not_match?(5)).to be_falsey expect(matcher.does_not_match?(4)).to be true end context "wrapping another expectation in a `match` block" do context "with a positive expectation" do let(:matcher) do new_matcher(:name, "value") do |expected| match do |actual| expect(actual).to eq expected end end end specify "`match?` returns true if the wrapped expectation passes" do expect(matcher.matches?('value')).to be_truthy end specify "`match?` returns false if the wrapped expectation fails" do expect(matcher.matches?('other value')).to be_falsey end end context "with a negative expectation" do let(:matcher) do new_matcher(:name, "purposely_the_same") do |expected| match do |actual| expect(actual).not_to eq expected end end end specify "`match?` returns true if the wrapped expectation passes" do expect(matcher.matches?('purposely_different')).to be_truthy end specify "`match?` returns false if the wrapped expectation fails" do expect(matcher.matches?('purposely_the_same')).to be_falsey end end it "can use the `include` matcher from a `match` block" do RSpec::Matchers.define(:descend_from) do |mod| match do |klass| expect(klass.ancestors).to include(mod) end end expect(Integer).to descend_from(Object) expect(Integer).not_to descend_from(Array) expect { expect(Integer).to descend_from(Array) }.to fail_with(/expected Integer to descend from Array/) expect { expect(Integer).not_to descend_from(Object) }.to fail_with(/expected Integer not to descend from Object/) end it "can use the `match` matcher from a `match` block" do RSpec::Matchers.define(:be_a_phone_number_string) do match do |string| expect(string).to match(/\A\d{3}\-\d{3}\-\d{4}\z/) end end expect("206-123-1234").to be_a_phone_number_string expect("foo").not_to be_a_phone_number_string expect { expect("foo").to be_a_phone_number_string }.to fail_with(/expected "foo" to be a phone number string/) expect { expect("206-123-1234").not_to be_a_phone_number_string }.to fail_with(/expected "206-123-1234" not to be a phone number string/) end context "when used within an `aggregate_failures` block" do it 'does not aggregate the inner expectation failure' do use_an_internal_expectation = new_matcher(:use_an_internal_expectation) do match do |actual| expect(actual).to end_with "z" end end expect { aggregate_failures do expect(1).to be_even expect("foo").to use_an_internal_expectation end }.to fail do |error| expect(error).to have_attributes(:failures => [ an_object_having_attributes(:message => "expected `1.even?` to return true, got false"), an_object_having_attributes(:message => 'expected "foo" to use an internal expectation') ]) end end it 'does not aggregate the inner expectation failure (negation)' do use_an_internal_expectation = new_matcher(:use_an_internal_expectation) do match_when_negated do |actual| expect(actual).not_to end_with "o" end end expect { aggregate_failures do expect(1).to be_even expect("foo").not_to use_an_internal_expectation end }.to fail do |error| expect(error).to have_attributes(:failures => [ an_object_having_attributes(:message => "expected `1.even?` to return true, got false"), an_object_having_attributes(:message => 'expected "foo" not to use an internal expectation') ]) end end it 'still raises the expectation failure internally in case the matcher relies upon rescuing the error' do error_rescued = false rescue_failure = new_matcher(:rescue_failure) do match do |actual| begin expect(actual).to eq(2) rescue RSpec::Expectations::ExpectationNotMetError error_rescued = true end end end begin aggregate_failures do expect(1).to rescue_failure end rescue RSpec::Expectations::ExpectationNotMetError # rubocop:disable Lint/SuppressedException end expect(error_rescued).to be true end end end context "wrapping another expectation in a `match_when_negated` block" do context "with a positive expectation" do let(:matcher) do new_matcher(:name, "purposely_the_same") do |expected| match_when_negated do |actual| expect(actual).to eq expected end end end specify "`does_not_match?` returns true if the wrapped expectation passes" do expect(matcher.does_not_match?('purposely_the_same')).to be_truthy end specify "`does_not_match?` returns false if the wrapped expectation fails" do expect(matcher.does_not_match?('purposely_different')).to be_falsey end end context "with a negative expectation" do let(:matcher) do new_matcher(:name, "value") do |expected| match_when_negated do |actual| expect(actual).not_to eq expected end end end specify "`does_not_match?` returns true if the wrapped expectation passes" do expect(matcher.does_not_match?('other value')).to be_truthy end specify "`does_not_match?` returns false if the wrapped expectation fails" do expect(matcher.does_not_match?('value')).to be_falsey end end end context "with overrides" do let(:matcher) do new_matcher(:be_boolean, true) do |boolean| match do |actual| actual end description do |actual| "be the boolean #{boolean} (actual was #{actual})" end failure_message do |actual| "expected #{actual} to be the boolean #{boolean}" end failure_message_when_negated do |actual| "expected #{actual} not to be the boolean #{boolean}" end end end it "does not hide result of match block when true" do expect(matcher.matches?(true)).to be_truthy end it "does not hide result of match block when false" do expect(matcher.matches?(false)).to be_falsey end it "overrides the description (which yields `actual`)" do matcher.matches?(true) expect(matcher.description).to eq "be the boolean true (actual was true)" end it "overrides the failure message for positive expectations" do matcher.matches?(false) expect(matcher.failure_message).to eq "expected false to be the boolean true" end it "overrides the failure message for negative expectations" do matcher.matches?(true) expect(matcher.failure_message_when_negated).to eq "expected true not to be the boolean true" end it 'can access helper methods from `description`' do matcher = new_matcher(:desc) do def subdesc() "sub description" end description { "Desc (#{subdesc})" } end expect(matcher.description).to eq("Desc (sub description)") end it 'can access helper methods from `failure_message`' do matcher = new_matcher(:positive_failure_message) do def helper() "helper" end failure_message { helper } end expect(matcher.failure_message).to eq("helper") end it 'can access helper methods from `failure_message_when_negated`' do matcher = new_matcher(:negative_failure_message) do def helper() "helper" end failure_message_when_negated { helper } end expect(matcher.failure_message_when_negated).to eq("helper") end it 'can exit early with a `return` from `description` just like in a method' do matcher = new_matcher(:desc) do description { return "Desc" } end expect(matcher.description).to eq("Desc") end it 'can exit early with a `return` from `failure_message` just like in a method' do matcher = new_matcher(:positive_failure_message) do failure_message { return "msg" } end expect(matcher.failure_message).to eq("msg") end it 'can exit early with a `return` from `failure_message_when_negated` just like in a method' do matcher = new_matcher(:negative_failure_message) do failure_message_when_negated { return "msg" } end expect(matcher.failure_message_when_negated).to eq("msg") end end context "with description override and chained matcher" do context "by default" do let(:matcher) do new_matcher(:be_even) do match do |to_match| to_match.even? && (to_match % @divisible_by == 0) end chain :and_divisible_by do |divisible_by| @divisible_by = divisible_by end description { super() + " and divisible by #{@divisible_by}" } end end context "with include_chain_clauses_in_custom_matcher_descriptions configured to false" do include_context "isolate include_chain_clauses_in_custom_matcher_descriptions" before { RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions = false } it "provides a default description that does not include any of the chained matchers' descriptions" do expect(matcher.and_divisible_by(10).description).to eq 'be even and divisible by 10' end end context "with include_chain_clauses_in_custom_matcher_descriptions configured to true" do it "provides a default description that does includes the chained matchers' descriptions" do expect(matcher.and_divisible_by(10).description).to eq 'be even and divisible by 10 and divisible by 10' end end end end context "matching blocks" do it 'cannot match blocks by default' do matcher = new_matcher(:foo) { match { true } } expect(3).to matcher expect { expect { 3 }.to matcher }.to fail_with(/must pass an argument/) end it 'can match blocks if it declares `supports_block_expectations`' do matcher = new_matcher(:foo) do match { true } supports_block_expectations end expect(3).to matcher expect { 3 }.to matcher end it 'will not swallow expectation errors from blocks when told to' do matcher = new_matcher(:foo) do match(:notify_expectation_failures => true) do |actual| actual.call true end supports_block_expectations end expect { expect { raise RSpec::Expectations::ExpectationNotMetError.new('original') }.to matcher }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /original/) end end context "matching blocks when negated" do it 'cannot match blocks by default' do matcher = new_matcher(:foo) { match_when_negated { true } } expect(3).to_not matcher expect { expect { 3 }.to_not matcher }.to fail_with(/must pass an argument/) end it 'can match blocks if it declares `supports_block_expectations`' do matcher = new_matcher(:foo) do match_when_negated { true } supports_block_expectations end expect(3).to_not matcher expect { 3 }.to_not matcher end it 'will not swallow expectation errors from blocks when told to' do matcher = new_matcher(:foo) do match_when_negated(:notify_expectation_failures => true) do |actual| actual.call true end supports_block_expectations end expect { expect { raise RSpec::Expectations::ExpectationNotMetError.new('original') }.to_not matcher }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /original/) end end context "#new" do it "passes matches? arg to match block" do matcher = new_matcher(:ignore) do match do |actual| actual == 5 end end expect(matcher.matches?(5)).to be_truthy end it "exposes arg submitted through #new to matcher block" do matcher = new_matcher(:ignore, 4) do |expected| match do |actual| actual > expected end end expect(matcher.matches?(5)).to be_truthy end end context "with no args" do let(:matcher) do new_matcher(:matcher_name) do match do |actual| actual == 5 end end end it "matches" do expect(matcher.matches?(5)).to be_truthy end it "describes" do expect(matcher.description).to eq "matcher name" end end context "with 1 arg" do let(:matcher) do new_matcher(:matcher_name, 1) do |expected| match do |actual| actual == 5 && expected == 1 end end end it "matches" do expect(matcher.matches?(5)).to be_truthy end it "describes" do expect(matcher.description).to eq "matcher name 1" end end context "with multiple args" do let(:matcher) do new_matcher(:matcher_name, 1, 2, 3, 4) do |a, b, c, d| match do |sum| a + b + c + d == sum end end end it "matches" do expect(matcher.matches?(10)).to be_truthy end it "describes" do expect(matcher.description).to eq "matcher name 1, 2, 3, and 4" end end it "supports helper methods" do matcher = new_matcher(:be_similar_to, [1, 2, 3]) do |sample| match do |actual| similar?(sample, actual) end def similar?(a, b) a.sort == b.sort end end expect(matcher.matches?([2, 3, 1])).to be_truthy end it "supports fluent interface" do matcher = new_matcher(:first_word) do def second_word self end end expect(matcher.second_word).to eq matcher end it "treats method missing normally for undeclared methods" do matcher = new_matcher(:ignore) {} expect { matcher.non_existent_method }.to raise_error(NoMethodError) end it "has access to other matchers" do matcher = new_matcher(:ignore, 3) do |expected| match do |actual| extend RSpec::Matchers expect(actual).to eql(5 + expected) end end expect(matcher.matches?(8)).to be_truthy end context 'when multiple instances of the same matcher are used in the same example' do RSpec::Matchers.define(:be_like_a) do |expected| match { |actual| actual == expected } description { "be like a #{expected}" } failure_message { "expected to be like a #{expected}" } failure_message_when_negated { "expected not to be like a #{expected}" } end # Note: these bugs were only exposed when creating both instances # first, then checking their descriptions/failure messages. # # That's why we eager-instantiate them here. let!(:moose) { be_like_a("moose") } let!(:horse) { be_like_a("horse") } it 'allows them to use the expected value in the description' do expect(horse.description).to eq("be like a horse") expect(moose.description).to eq("be like a moose") end it 'allows them to use the expected value in the positive failure message' do expect(moose.failure_message).to eq("expected to be like a moose") expect(horse.failure_message).to eq("expected to be like a horse") end it 'allows them to use the expected value in the negative failure message' do expect(moose.failure_message_when_negated).to eq("expected not to be like a moose") expect(horse.failure_message_when_negated).to eq("expected not to be like a horse") end it 'allows them to match separately' do expect("moose").to moose expect("horse").to horse expect("horse").not_to moose expect("moose").not_to horse end end describe "#match_unless_raises" do context "with an assertion" do mod = Module.new do def assert_equal(a, b) raise UnexpectedError.new("#{b} does not equal #{a}") unless a == b end end let(:matcher) do new_matcher(:equal, 4) do |expected| include mod match_unless_raises UnexpectedError do assert_equal expected, actual end end end context "with passing assertion" do it "passes" do expect(matcher.matches?(4)).to be_truthy end end context "with failing assertion" do it "fails" do expect(matcher.matches?(5)).to be_falsey end it "provides the raised exception" do matcher.matches?(5) expect(matcher.rescued_exception.message).to eq("5 does not equal 4") end end end context "with an unexpected error" do it "raises the error" do matcher = new_matcher(:foo, :bar) do |_expected| match_unless_raises SyntaxError do |_actual| raise "unexpected exception" end end expect { matcher.matches?(:bar) }.to raise_error("unexpected exception") end end context "without a specified error class" do let(:matcher) do new_matcher(:foo) do match_unless_raises do |actual| raise Exception unless actual == 5 end end end it 'passes if no error is raised' do expect(matcher.matches?(5)).to be true end it 'fails if an exception is raised' do expect(matcher.matches?(4)).to be false end end end it "can define chainable methods" do matcher = new_matcher(:name) do chain(:expecting) do |expected_value| @expected_value = expected_value end match { |actual| actual == @expected_value } end expect(matcher.expecting('value').matches?('value')).to be_truthy expect(matcher.expecting('value').matches?('other value')).to be_falsey end it "can define chainable setters" do matcher = new_matcher(:name) do chain(:expecting, :expected_value) match { |actual| actual == expected_value } end expect(matcher.expecting('value').matches?('value')).to be_truthy expect(matcher.expecting('value').matches?('other value')).to be_falsey end it "can define chainable setters for several attributes" do matcher = new_matcher(:name) do chain(:expecting, :expected_value, :min_value, :max_value) match { |actual| actual == expected_value && actual >= min_value && actual <= max_value } end expect(matcher.expecting('value', 'apple', 'zebra').matches?('value')).to be_truthy expect(matcher.expecting('value', 'apple', 'zebra').matches?('other value')).to be_falsey expect(matcher.expecting('other value', 'parrot', 'zebra').matches?('other value')).to be_falsey end it "raises when neither a `chain` block nor attribute name is provided" do expect do new_matcher(:name) do chain(:expecting) end end.to raise_error(ArgumentError) end it "raises when both a `chain` block and attribute name are provided" do expect do new_matcher(:name) do chain(:expecting, :expected_value) do |expected_value| @expected_value = expected_value end end end.to raise_error(ArgumentError) end it 'can use an early return from a `chain` block' do matcher = new_matcher(:name) do chain(:expecting) do |expected_value| @expected_value = expected_value return end match { |actual| actual == @expected_value } end expect(matcher.expecting('value').matches?('value')).to be_truthy expect(matcher.expecting('value').matches?('other value')).to be_falsey end it 'allows chainable methods to accept blocks' do matcher = new_matcher(:name) do chain(:for_block) { |&b| @block = b } match { |value| @block.call == value } end expect(matcher.for_block { 5 }.matches?(5)).to be true expect(matcher.for_block { 3 }.matches?(4)).to be false end it "prevents name collisions on chainable methods from different matchers" do m1 = new_matcher(:m1) { chain(:foo) { raise "foo in m1" } } m2 = new_matcher(:m2) { chain(:foo) { raise "foo in m2" } } expect { m1.foo }.to raise_error("foo in m1") expect { m2.foo }.to raise_error("foo in m2") end context "defined using the dsl" do def a_method_in_the_example "method defined in the example" end it "can access methods in the running example" do |example| RSpec::Matchers.define(:__access_running_example) do match do |_actual| a_method_in_the_example == "method defined in the example" end end expect(example).to __access_running_example end it 'can get a method object for methods in the running example', :if => (RUBY_VERSION.to_f > 1.8) do matcher = new_matcher(:get_method_object) {} method = matcher.method(:a_method_in_the_example) expect(method.call).to eq("method defined in the example") end it 'indicates that it responds to a method from the running example' do matcher = new_matcher(:respond_to) {} expect(matcher).to respond_to(:a_method_in_the_example) expect(matcher).not_to respond_to(:a_method_not_in_the_example) end it "raises NoMethodError for methods not in the running_example" do |example| RSpec::Matchers.define(:__raise_no_method_error) do match do |_actual| self.a_method_not_in_the_example == "method defined in the example" # rubocop:disable Style/RedundantSelf RuboCop bug, should disappear on version update end end expected_msg = "RSpec::Matchers::DSL::Matcher" expected_msg = "#{expected_msg} __raise_no_method_error" unless rbx? || RUBY_VERSION.to_f > 3.2 expect { expect(example).to __raise_no_method_error }.to raise_error(NoMethodError, /#{expected_msg}/) end def rbx? defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/legacy_spec.rb0000664000000000000000000000746014557700001027070 0ustar rootrootmodule RSpec module Matchers RSpec.describe "Legacy matchers" do it 'still provides a `LegacyMacherAdapter` constant because 3.0 was released with ' \ 'it and it would be a SemVer violation to remove it before 4.0' do expect(Expectations::LegacyMacherAdapter).to be(Expectations::LegacyMatcherAdapter) end shared_examples "a matcher written against a legacy protocol" do |matcher_class| matcher = matcher_class.new before { allow_deprecation } backwards_compat_matcher = Class.new(matcher_class) do def failure_message; "failure when positive"; end def failure_message_when_negated; "failure when negative"; end end.new it 'is still considered to be a matcher' do expect(Matchers.is_a_matcher?(matcher)).to be true end context 'when matched positively' do it 'returns the positive expectation failure message' do expect { expect(false).to matcher }.to fail_with("failure when positive") end it 'warns about the deprecated protocol' do expect_warn_deprecation(/legacy\s+RSpec\s+matcher.+#{__FILE__}:#{__LINE__ + 1}/m) expect(true).to matcher end it 'does not warn when it also defines the current methods (i.e. to be compatible on multiple RSpec versions)' do expect_no_deprecations expect { expect(false).to backwards_compat_matcher }.to fail_with("failure when positive") end end context 'when matched negatively' do it 'returns the negative expectation failure message' do expect { expect(true).not_to matcher }.to fail_with("failure when negative") end it 'warns about the deprecated protocol' do expect_warn_deprecation(/legacy\s+RSpec\s+matcher.+#{__FILE__}:#{__LINE__ + 1}/m) expect(false).not_to matcher end it 'does not warn when it also defines the current methods (i.e. to be compatible on multiple RSpec versions)' do expect_no_deprecations expect { expect(true).not_to backwards_compat_matcher }.to fail_with("failure when negative") end def pending_on_rbx return unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' pending "intermittently fails on RBX due to https://github.com/rubinius/rubinius/issues/2845" end it 'calls `does_not_match?` if it is defined on the matcher' do pending_on_rbx called = false with_does_not_match = Class.new(matcher_class) do define_method(:does_not_match?) { |actual| called = true; !actual } end.new expect(false).not_to with_does_not_match expect(called).to be true end end end context "written using the RSpec 2.x `failure_message_for_should` and `failure_message_for_should_not` protocol" do matcher_class = Class.new do def matches?(actual); actual; end def failure_message_for_should; "failure when positive"; end def failure_message_for_should_not; "failure when negative"; end end it_behaves_like "a matcher written against a legacy protocol", matcher_class end context "written using the older `failure_message` and `negative_failure_message` protocol" do matcher_class = Class.new do def matches?(actual); actual; end def failure_message; "failure when positive"; end def negative_failure_message; "failure when negative"; end end it_behaves_like "a matcher written against a legacy protocol", matcher_class end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/description_generation_spec.rb0000664000000000000000000001626214557700001032362 0ustar rootrootRSpec.describe 'a matcher is expected to be able to have its description generated' do after(:example) do RSpec::Matchers.clear_generated_description end example "expect(...).to eq expected" do expect("this").to eq "this" expect(RSpec::Matchers.generated_description).to eq "is expected to eq \"this\"" end example "expect(...).to not eq expected" do expect("this").not_to eq "that" expect(RSpec::Matchers.generated_description).to eq "is expected not to eq \"that\"" end example "expect(...).to be empty (arbitrary predicate)" do expect([]).to be_empty expect(RSpec::Matchers.generated_description).to eq "is expected to be empty" end example "expect(...).to not be empty (arbitrary predicate)" do expect([1]).not_to be_empty expect(RSpec::Matchers.generated_description).to eq "is expected not to be empty" end example "expect(...).to be truthy" do expect(true).to be_truthy expect(RSpec::Matchers.generated_description).to eq "is expected to be truthy" end example "expect(...).to be falsey" do expect(false).to be_falsey expect(RSpec::Matchers.generated_description).to eq "is expected to be falsey" end example "expect(...).to be nil" do expect(nil).to be_nil expect(RSpec::Matchers.generated_description).to eq "is expected to be nil" end example "expect(...).to be > n" do expect(5).to be > 3 expect(RSpec::Matchers.generated_description).to eq "is expected to be > 3" end example "expect(...).to be between min and max" do expect(10).to be_between(0, 10) expect(RSpec::Matchers.generated_description).to eq "is expected to be between 0 and 10 (inclusive)" end example "expect(...).to be exclusively between min and max" do expect(9).to be_between(0, 10).exclusive expect(RSpec::Matchers.generated_description).to eq "is expected to be between 0 and 10 (exclusive)" end example "expect(...).to be predicate arg1, arg2 and arg3" do class Parent; end class Child < Parent def child_of?(*parents) parents.all? { |parent| is_a?(parent) } end end expect(Child.new).to be_a_child_of(Parent, Object) expect(RSpec::Matchers.generated_description).to eq "is expected to be a child of Parent and Object" end example "expect(...).to equal" do expected = "expected" expect(expected).to equal(expected) expect(RSpec::Matchers.generated_description).to eq "is expected to equal \"expected\"" end example "expect(...).not_to equal" do expect(5).not_to equal(37) expect(RSpec::Matchers.generated_description).to eq "is expected not to equal 37" end example "expect(...).to eql" do expect("string").to eql("string") expect(RSpec::Matchers.generated_description).to eq "is expected to eql \"string\"" end example "expect(...).not_to eql" do expect("a").not_to eql(:a) expect(RSpec::Matchers.generated_description).to eq "is expected not to eql :a" end example "expect(...).to have_key" do expect({ :a => "a" }).to have_key(:a) expect(RSpec::Matchers.generated_description).to eq "is expected to have key :a" end example "expect(...).to have_some_method" do object = Object.new def object.has_eyes_closed?; true; end expect(object).to have_eyes_closed expect(RSpec::Matchers.generated_description).to eq 'is expected to have eyes closed' end example "expect(...).to have_some_method(args*)" do object = Object.new def object.has_taste_for?(*_args); true; end expect(object).to have_taste_for("wine", "cheese") expect(RSpec::Matchers.generated_description).to eq 'is expected to have taste for "wine" and "cheese"' end example "expect(...).to include(x)" do expect([1, 2, 3]).to include(3) expect(RSpec::Matchers.generated_description).to eq "is expected to include 3" end example "expect(...).to include(x) when x responds to description but is not a matcher" do obj = double(:description => "description", :inspect => "inspect") expect([obj]).to include(obj) expect(RSpec::Matchers.generated_description).to eq "is expected to include inspect" end example "expect(...).to include(x) when x responds to description and is a matcher" do matcher = double(:description => "description", :matches? => true, :failure_message => "") expect([matcher]).to include(matcher) expect(RSpec::Matchers.generated_description).to eq "is expected to include (description)" end example "expect(array).to contain_exactly(1, 2, 3)" do expect([1, 2, 3]).to contain_exactly(1, 2, 3) expect(RSpec::Matchers.generated_description).to eq "is expected to contain exactly 1, 2, and 3" end example "expect(...).to match" do expect("this string").to match(/this string/) expect(RSpec::Matchers.generated_description).to eq "is expected to match /this string/" end example "expect(...).to raise_error" do expect { raise 'foo' }.to raise_error Exception expect(RSpec::Matchers.generated_description).to eq "is expected to raise Exception" end example "expect(...).to raise_error with class" do expect { raise }.to raise_error(RuntimeError) expect(RSpec::Matchers.generated_description).to eq "is expected to raise RuntimeError" end example "expect(...).to raise_error with class and message" do expect { raise "there was an error" }.to raise_error(RuntimeError, "there was an error") expect(RSpec::Matchers.generated_description).to eq "is expected to raise RuntimeError with \"there was an error\"" end example "expect(...).to respond_to" do expect([]).to respond_to(:insert) expect(RSpec::Matchers.generated_description).to eq "is expected to respond to #insert" end example "expect(...).to throw symbol" do expect { throw :what_a_mess }.to throw_symbol expect(RSpec::Matchers.generated_description).to eq "is expected to throw a Symbol" end example "expect(...).to throw symbol (with named symbol)" do expect { throw :what_a_mess }.to throw_symbol(:what_a_mess) expect(RSpec::Matchers.generated_description).to eq "is expected to throw :what_a_mess" end example "expect(...).to matcher_that_delegates_to_an_internal_expectation" do expect(1).to matcher_that_delegates_to_an_internal_expectation expect(RSpec::Matchers.generated_description).to eq "is expected to matcher that delegates to an internal expectation" end example "expect(...).not_to matcher_that_delegates_to_an_internal_expectation" do expect(1).not_to matcher_that_delegates_to_an_internal_expectation expect(RSpec::Matchers.generated_description).to eq "is expected not to matcher that delegates to an internal expectation" end RSpec::Matchers.define :matcher_that_delegates_to_an_internal_expectation do match { expect(1).to eq(1) } match_when_negated { expect(1).to eq(1) } end end RSpec.describe "a Matcher with no description" do it "provides a helpful message when used in a string-less example block" do matcher = Class.new do def matches?(_ignore); true; end def failure_message; ""; end end.new expect(5).to matcher expect(RSpec::Matchers.generated_description).to match(/When you call.*description method/m) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/0000775000000000000000000000000014557700001026063 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/match_spec.rb0000664000000000000000000001104514557700001030517 0ustar rootrootRSpec.describe "expect(...).to match(expected)" do include RSpec::Support::Spec::DiffHelpers it_behaves_like "an RSpec value matcher", :valid_value => 'ab', :invalid_value => 'bc' do let(:matcher) { match(/a/) } end it "passes when target (String) matches expected (Regexp)" do expect("string").to match(/tri/) end it "passes when target (Regexp) matches expected (String)" do expect(/tri/).to match("string") end it "passes when target (Regexp) matches expected (Regexp)" do expect(/tri/).to match(/tri/) end it "passes when target (String) matches expected (a matcher)" do expect("string").to match(a_string_including("str")) end it "passes when target (Regexp) matches expected (a matcher)" do expect(/foo/).to match(be_a Regexp) end it "passes when target (String) matches expected (String)" do expect("string").to match("tri") end it "fails when target (String) does not match expected (Regexp)" do expect { expect("string").to match(/rings/) }.to fail_with a_string_starting_with 'expected "string" to match /rings/' end it "fails when target (Regexp) does not match expected (String)" do expect { expect(/rings/).to match("string") }.to fail_with a_string_starting_with 'expected /rings/ to match "string"' end it "fails when target (String) does not match expected (a matcher)" do expect { expect("string").to match(a_string_including("foo")) }.to fail_with(a_string_starting_with 'expected "string" to match (a string including "foo")') end it "fails when target (Regexp) does not match expected (a matcher)" do expect { expect(/foo/).to match(be_a_kind_of String) }.to fail_with(a_string_starting_with 'expected /foo/ to match (be a kind of String)') end it "fails when target (String) does not match expected (String)" do expect { expect("string").to match("rings") }.to fail end it "provides message, expected and actual on failure" do matcher = match(/rings/) matcher.matches?("string") expect(matcher.failure_message).to eq "expected \"string\" to match /rings/" end it "provides a diff on failure" do allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false) failure_message_that_includes_diff = %r| \s*Diff: \s*@@ #{Regexp.escape one_line_header} @@ \s*-/bar/ \s*\+"foo"| expect { expect("foo").to match(/bar/) }.to fail_with(failure_message_that_includes_diff) end context "when passed a data structure with matchers" do it 'passes when the matchers match' do expect(["food", 1.1]).to match([a_string_matching(/foo/), a_value_within(0.2).of(1)]) end it 'fails when the matchers do not match' do expect { expect(["fod", 1.1]).to match([a_string_matching(/foo/), a_value_within(0.2).of(1)]) }.to fail_with('expected ["fod", 1.1] to match [(a string matching /foo/), (a value within 0.2 of 1)]') end it 'provides a description' do description = match([a_string_matching(/foo/), a_value_within(0.2).of(1)]).description expect(description).to eq("match [(a string matching /foo/), (a value within 0.2 of 1)]") end end end RSpec.describe "expect(...).not_to match(expected)" do it "passes when target (String) matches does not match (Regexp)" do expect("string").not_to match(/rings/) end it "passes when target (String) matches does not match (String)" do expect("string").not_to match("rings") end it "fails when target (String) matches expected (Regexp)" do expect { expect("string").not_to match(/tri/) }.to fail_with a_string_starting_with 'expected "string" not to match /tri/' end it "fails when target (String) matches expected (String)" do expect { expect("string").not_to match("tri") }.to fail_with a_string_starting_with 'expected "string" not to match "tri"' end it "provides message, expected and actual on failure" do matcher = match(/tri/) matcher.matches?("string") expect(matcher.failure_message_when_negated).to eq "expected \"string\" not to match /tri/" end context "when passed a data structure with matchers" do it 'passes when the matchers match' do expect(["food", 1.1]).not_to match([a_string_matching(/fod/), a_value_within(0.2).of(1)]) end it 'fails when the matchers do not match' do expect { expect(["fod", 1.1]).not_to match([a_string_matching(/fod/), a_value_within(0.2).of(1)]) }.to fail_with('expected ["fod", 1.1] not to match [(a string matching /fod/), (a value within 0.2 of 1)]') end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/cover_spec.rb0000664000000000000000000000372714557700001030551 0ustar rootrootif (1..2).respond_to?(:cover?) RSpec.describe "expect(...).to cover(expected)" do it_behaves_like "an RSpec value matcher", :valid_value => (1..10), :invalid_value => (20..30) do let(:matcher) { cover(5) } end context "for a range target" do it "passes if target covers expected" do expect((1..10)).to cover(5) end it "fails if target does not cover expected" do expect { expect((1..10)).to cover(11) }.to fail_with("expected 1..10 to cover 11") end end end RSpec.describe "expect(...).to cover(with, multiple, args)" do context "for a range target" do it "passes if target covers all items" do expect((1..10)).to cover(4, 6) end it "fails if target does not cover any one of the items" do expect { expect((1..10)).to cover(4, 6, 11) }.to fail_with("expected 1..10 to cover 4, 6, and 11") end end end RSpec.describe "expect(...).not_to cover(expected)" do context "for a range target" do it "passes if target does not cover expected" do expect((1..10)).not_to cover(11) end it "fails if target covers expected" do expect { expect((1..10)).not_to cover(5) }.to fail_with("expected 1..10 not to cover 5") end end end RSpec.describe "expect(...).not_to cover(with, multiple, args)" do context "for a range target" do it "passes if the target does not cover any of the expected" do expect((1..10)).not_to cover(11, 12, 13) end it "fails if the target covers all of the expected" do expect { expect((1..10)).not_to cover(4, 6) }.to fail_with("expected 1..10 not to cover 4 and 6") end it "fails if the target covers some (but not all) of the expected" do expect { expect((1..10)).not_to cover(5, 11) }.to fail_with("expected 1..10 not to cover 5 and 11") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/eql_spec.rb0000664000000000000000000000517514557700001030213 0ustar rootrootmodule RSpec module Matchers RSpec.describe "eql" do it_behaves_like "an RSpec value matcher", :valid_value => 1, :invalid_value => 2 do let(:matcher) { eql(1) } end it "is diffable" do expect(eql(1)).to be_diffable end it "matches when actual.eql?(expected)" do expect(1).to eql(1) end it "does not match when !actual.eql?(expected)" do expect(1).not_to eql(2) end it "describes itself" do matcher = eql(1) matcher.matches?(1) expect(matcher.description).to eq "eql 1" end it "provides message, expected and actual on #failure_message" do matcher = eql("1") matcher.matches?(1) expect(matcher.failure_message).to eq "\nexpected: \"1\"\n got: 1\n\n(compared using eql?)\n" end it "provides message, expected and actual on #negative_failure_message" do matcher = eql(1) matcher.matches?(1) expect(matcher.failure_message_when_negated).to eq "\nexpected: value != 1\n got: 1\n\n(compared using eql?)\n" end # Older versions of Ruby such as less than 1.9 do not have String#encoding available, they are an array of bytes if String.method_defined?(:encoding) context "with String encoding as UTF-16LE" do it "provides message, expected and actual on #failure_message when string encoding is the same" do matcher = eql('abc'.encode('UTF-16LE')) matcher.matches?('def'.encode('UTF-16LE')) expect(matcher.failure_message).to eq "\nexpected: \"abc\"\n got: \"def\"\n\n(compared using eql?)\n" end it "matches when actual is BINARY encoding and expected is UTF-8 encoding with the same chars" do expect('abc'.encode('BINARY')).to eq 'abc'.encode('UTF-8') end it "provides message, expected and actual with encoding details on #failure_message when string encoding is different" do matcher = eql('abc'.encode('UTF-16LE')) matcher.matches?('abc'.force_encoding('ASCII-8BIT')) expect(matcher.failure_message).to eq "\nexpected: # \"abc\"\n got: # \"abc\"\n\n(compared using eql?)\n" end it "provides message, expected and actual on #negative_failure_message" do matcher = eql('abc'.encode('UTF-16LE')) matcher.matches?('abc'.encode('UTF-16LE')) expect(matcher.failure_message_when_negated).to eq "\nexpected: value != \"abc\"\n got: \"abc\"\n\n(compared using eql?)\n" end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/throw_symbol_spec.rb0000664000000000000000000001277014557700001032161 0ustar rootrootmodule RSpec::Matchers::BuiltIn RSpec.describe ThrowSymbol do it_behaves_like "an RSpec block-only matcher" do def valid_block throw :foo end def invalid_block end let(:matcher) { throw_symbol(:foo) } end describe "with no args" do before(:example) { @matcher = throw_symbol } it "matches if any Symbol is thrown" do expect(@matcher.matches?(lambda { throw :sym })).to be_truthy end it "matches if any Symbol is thrown with an arg" do expect(@matcher.matches?(lambda { throw :sym, "argument" })).to be_truthy end it "does not match if no Symbol is thrown" do expect(@matcher.matches?(lambda {})).to be_falsey end it "provides a failure message" do @matcher.matches?(lambda {}) expect(@matcher.failure_message).to eq "expected a Symbol to be thrown, got nothing" end it "provides a negative failure message" do @matcher.matches?(lambda { throw :sym }) expect(@matcher.failure_message_when_negated).to eq "expected no Symbol to be thrown, got :sym" end end describe "with a symbol" do before(:example) { @matcher = throw_symbol(:sym) } it "matches if correct Symbol is thrown" do expect(@matcher.matches?(lambda { throw :sym })).to be_truthy end it "matches if correct Symbol is thrown with an arg" do expect(@matcher.matches?(lambda { throw :sym, "argument" })).to be_truthy end it "does not match if no Symbol is thrown" do expect(@matcher.matches?(lambda {})).to be_falsey end it "does not match if correct Symbol is thrown" do expect(@matcher.matches?(lambda { throw :other_sym })).to be_falsey end it "provides a failure message when no Symbol is thrown" do @matcher.matches?(lambda {}) expect(@matcher.failure_message).to eq "expected :sym to be thrown, got nothing" end it "provides a failure message when wrong Symbol is thrown" do @matcher.matches?(lambda { throw :other_sym }) expect(@matcher.failure_message).to eq "expected :sym to be thrown, got :other_sym" end it "provides a negative failure message" do @matcher.matches?(lambda { throw :sym }) expect(@matcher.failure_message_when_negated).to eq "expected :sym not to be thrown, got :sym" end it "only matches NameErrors raised by uncaught throws" do expect { expect(@matcher.matches?(lambda { sym })).to be_falsey }.to raise_error(NameError) end end describe "with a symbol and an arg" do before(:example) { @matcher = throw_symbol(:sym, "a") } it "matches if correct Symbol and args are thrown" do expect(@matcher.matches?(lambda { throw :sym, "a" })).to be_truthy end it "does not match if nothing is thrown" do expect(@matcher.matches?(lambda {})).to be_falsey end it "does not match if other Symbol is thrown" do expect(@matcher.matches?(lambda { throw :other_sym, "a" })).to be_falsey end it "does not match if no arg is thrown" do expect(@matcher.matches?(lambda { throw :sym })).to be_falsey end it "does not match if wrong arg is thrown" do expect(@matcher.matches?(lambda { throw :sym, "b" })).to be_falsey end it "provides a failure message when no Symbol is thrown" do @matcher.matches?(lambda {}) expect(@matcher.failure_message).to eq 'expected :sym with "a" to be thrown, got nothing' end it "provides a failure message when wrong Symbol is thrown" do @matcher.matches?(lambda { throw :other_sym }) expect(@matcher.failure_message).to eq 'expected :sym with "a" to be thrown, got :other_sym' end it "provides a failure message when wrong arg is thrown" do @matcher.matches?(lambda { throw :sym, "b" }) expect(@matcher.failure_message).to eq 'expected :sym with "a" to be thrown, got :sym with "b"' end it "provides a failure message when no arg is thrown" do @matcher.matches?(lambda { throw :sym }) expect(@matcher.failure_message).to eq 'expected :sym with "a" to be thrown, got :sym with no argument' end it "provides a negative failure message" do @matcher.matches?(lambda { throw :sym }) expect(@matcher.failure_message_when_negated).to eq 'expected :sym with "a" not to be thrown, got :sym with no argument' end it "only matches NameErrors raised by uncaught throws" do expect { expect(@matcher.matches?(lambda { sym })).to be_falsey }.to raise_error(NameError) end it "raises other errors" do expect { @matcher.matches?(lambda { raise "Boom" }) }.to raise_error(/Boom/) end end describe "composing with other matchers" do it 'passes when the matcher matches the thrown arg' do expect { throw :foo, "bar" }.to throw_symbol(:foo, a_string_matching(/bar/)) end it 'fails when the matcher does not match the thrown arg' do expect { expect { throw :foo, "bar" }.to throw_symbol(:foo, a_string_matching(/foo/)) }.to fail_with('expected :foo with a string matching /foo/ to be thrown, got :foo with "bar"') end it 'provides a description' do description = throw_symbol(:foo, a_string_matching(/bar/)).description expect(description).to eq("throw :foo with a string matching /bar/") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/all_spec.rb0000664000000000000000000001777314557700001030211 0ustar rootrootmodule RSpec::Matchers::BuiltIn RSpec.describe All do it_behaves_like 'an RSpec value matcher', :valid_value => ['A', 'A', 'A'], :invalid_value => ['A', 'A', 'B'], :disallows_negation => true do let(:matcher) { all( eq('A') ) } end describe 'description' do it 'provides a description' do matcher = all( eq('A') ) expect(matcher.description).to eq 'all eq "A"' end end context 'when single matcher is given' do describe 'expect(...).to all(expected)' do it 'can pass' do expect(['A', 'A', 'A']).to all( eq('A') ) end describe 'failure message' do context 'when the matcher has single-line failure message' do it 'returns the index of the failed object' do expect { expect(['A', 'A', 'A', 5, 'A']).to all( be_a(String) ) }.to fail_with(dedent <<-EOS) |expected ["A", "A", "A", 5, "A"] to all be a kind of String | | object at index 3 failed to match: | expected 5 to be a kind of String EOS end it 'returns the indexes of all failed objects, not just the first one' do expect { expect(['A', 'A', 'A', 5, 6]).to all( be_a(String) ) }.to fail_with(dedent <<-EOS) |expected ["A", "A", "A", 5, 6] to all be a kind of String | | object at index 3 failed to match: | expected 5 to be a kind of String | | object at index 4 failed to match: | expected 6 to be a kind of String EOS end end context 'when the matcher has multi-line failure message' do it 'returns the index of the failed object' do expect { expect(['A', 'A', 'A', 'C', 'A']).to all( eq('A') ) }.to fail_with(dedent <<-EOS) |expected ["A", "A", "A", "C", "A"] to all eq "A" | | object at index 3 failed to match: | expected: "A" | got: "C" | | (compared using ==) EOS end it 'returns the indexes of all failed objects, not just the first one' do expect { expect(['A', 'B', 'A', 'C', 'A']).to all( eq('A') ) }.to fail_with(dedent <<-EOS) |expected ["A", "B", "A", "C", "A"] to all eq "A" | | object at index 1 failed to match: | expected: "A" | got: "B" | | (compared using ==) | | object at index 3 failed to match: | expected: "A" | got: "C" | | (compared using ==) EOS end end end end end context 'when composed matcher is given' do describe 'expect(...).to all(expected)' do it 'can pass' do expect([3, 4, 7, 8]).to all( be_between(2, 5).or be_between(6, 9) ) end end describe 'failure message' do context 'when a single object fails' do it 'returns the index of the failed object for the composed matcher' do expect { expect([3, 4, 7, 28]).to all( be_between(2, 5).or be_between(6, 9) ) }.to fail_with(dedent <<-EOS) |expected [3, 4, 7, 28] to all be between 2 and 5 (inclusive) or be between 6 and 9 (inclusive) | | object at index 3 failed to match: | expected 28 to be between 2 and 5 (inclusive) | | ...or: | | expected 28 to be between 6 and 9 (inclusive) EOS end end context 'when a multiple objects fails' do it 'returns the indexes of the failed objects for the composed matcher, not just the first one' do expect { expect([3, 4, 27, 22]).to all( be_between(2, 5).or be_between(6, 9) ) }.to fail_with(dedent <<-EOS) |expected [3, 4, 27, 22] to all be between 2 and 5 (inclusive) or be between 6 and 9 (inclusive) | | object at index 2 failed to match: | expected 27 to be between 2 and 5 (inclusive) | | ...or: | | expected 27 to be between 6 and 9 (inclusive) | | object at index 3 failed to match: | expected 22 to be between 2 and 5 (inclusive) | | ...or: | | expected 22 to be between 6 and 9 (inclusive) EOS end end end end context 'when composed in another matcher' do it 'returns the indexes of the failed objects only' do expect { expect([[false], [true]]).to all( all( be(true) ) ) }.to fail_with(dedent <<-EOS) |expected [[false], [true]] to all all equal true | | object at index 0 failed to match: | expected [false] to all equal true | | object at index 0 failed to match: | expected true | got false EOS end end shared_examples "making a copy" do |copy_method| context "when making a copy via `#{copy_method}`" do let(:base_matcher) { eq(3) } let(:all_matcher) { all( base_matcher ) } let(:copied_matcher) { all_matcher.__send__(copy_method) } it "uses a copy of the base matcher" do expect(copied_matcher).not_to equal(all_matcher) expect(copied_matcher.matcher).not_to equal(base_matcher) expect(copied_matcher.matcher).to be_a(base_matcher.class) expect(copied_matcher.matcher.expected).to eq(3) end context 'when using a custom matcher' do let(:base_matcher) { custom_include(3) } it 'copies custom matchers properly so they can work even though they have singleton behavior' do expect(copied_matcher).not_to equal(all_matcher) expect(copied_matcher.matcher).not_to equal(base_matcher) expect([[3]]).to copied_matcher expect { expect([[4]]).to copied_matcher }.to fail_including("expected [4]") end end end end include_examples 'making a copy', :clone include_examples 'making a copy', :dup context "when using a matcher instance that memoizes state multiple times in a composed expression" do it "works properly in spite of the memoization" do expect { expect(["foo", "bar", "a"]).to all( have_string_length(3) ) }.to fail end context "when passing a compound expression" do it "works properly in spite of the memoization" do expect { expect(["foo", "bar", "a"]).to all( have_string_length(2).or have_string_length(3) ) }.to fail end end end context 'when the actual data does not define #each_with_index' do let(:actual) { 5 } it 'returns a failure message' do expect { expect(actual).to all(be_a(String)) }.to fail_with("expected #{actual.inspect} to all be a kind of String, but was not iterable") end end context 'when the actual data does not include enumerable but defines #each_with_index' do let(:actual) do obj = Object.new def obj.each_with_index(&_block); [5].each_with_index { |o, i| yield(o, i) }; end obj end it 'passes properly' do expect(actual).to all(be_a(Integer)) end it 'fails properly' do expect { expect(actual).to all(be_even) }.to fail_with(/to all be even/) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/yield_spec.rb0000664000000000000000000007506414557700001030544 0ustar rootrootmodule YieldHelpers # these helpers are prefixed with an underscore to prevent # collisions with the matchers (some of which have the same names) def _dont_yield end def _yield_with_no_args yield end def _yield_with_args(*args) yield(*args) end end class InstanceEvaler def yield_with_no_args(&block) instance_exec(&block) end def yield_with_args(*args, &block) instance_exec(*args, &block) end def each_arg(*args, &block) args.each do |arg| instance_exec(arg, &block) end end end # NOTE: `yield` passes a probe to expect an that probe should be passed # to expectation target. This is different from the other block matchers. # Due to strict requirement in Ruby 1.8 to call a block with arguments if # the block is declared to accept them. To work around this limitation, # this example group overrides the default definition of expectations # and lambdas that take the expectation target in a way that they accept # a probe. RSpec.shared_examples "an RSpec probe-yielding block-only matcher" do |*options| include_examples "an RSpec block-only matcher", { :expects_lambda => true }.merge(options.first || {}) do let(:valid_expectation) { expect { |block| valid_block(&block) } } let(:invalid_expectation) { expect { |block| invalid_block(&block) } } let(:valid_block_lambda) { lambda { |block| valid_block(&block) } } let(:invalid_block_lambda) { lambda { |block| invalid_block(&block) } } end end RSpec.describe "yield_control matcher" do include YieldHelpers extend YieldHelpers it_behaves_like "an RSpec probe-yielding block-only matcher", :failure_message_uses_no_inspect => true do let(:matcher) { yield_control } def valid_block(&block) _yield_with_no_args(&block) end def invalid_block(&block) _dont_yield(&block) end end it 'has a description' do expect(yield_control.description).to eq("yield control") end describe "expect {...}.to yield_control" do it 'passes if the block yields, regardless of the number of yielded arguments or the number of yields' do expect { |b| _yield_with_no_args(&b) }.to yield_control expect { |b| _yield_with_args(1, 2, &b) }.to yield_control expect { |b| 1.upto(10, &b) }.to yield_control end it 'passes if the block yields using instance_exec' do expect { |b| InstanceEvaler.new.yield_with_no_args(&b) }.to yield_control end it 'fails if the block does not yield' do expect { expect { |b| _dont_yield(&b) }.to yield_control }.to fail_with(/expected given block to yield control but/) end it 'fails if the block does not yield the correct number of times' do expect { expect { |b| 0.times.each(&b) }.to yield_control.at_least(:once) }.to fail_with(/expected given block to yield control at least once but did not yield/) expect { expect { |b| 2.times.each(&b) }.to yield_control.at_most(:once) }.to fail_with(/expected given block to yield control at most once but yielded twice/) expect { expect { |b| 1.times.each(&b) }.to yield_control.at_least(:twice) }.to fail_with(/expected given block to yield control at least twice but yielded once/) expect { expect { |b| 3.times.each(&b) }.to yield_control.at_least(:once).at_most(2) }.to fail_with(/expected given block to yield control between 1 and 2 times but yielded 3 times/) expect { expect { |b| 0.times.each(&b) }.to yield_control }.to fail_with(/expected given block to yield control but did not yield/) end it 'does not return a meaningful value from the block' do val = nil expect { |b| val = _yield_with_args(&b) }.to yield_control expect(val).to be_nil end it 'raises an error if given an invalid count argument' do expect { yield_control.exactly('2') }.to raise_error(ArgumentError) expect { yield_control.at_least(:trice_with_typo) }.to raise_error(ArgumentError) expect { yield_control.at_most(nil) }.to raise_error(ArgumentError) expect { yield_control.at_least(2).at_least(1) }.to raise_error(ArgumentError) expect { yield_control.at_most(2).at_most(1) }.to raise_error(ArgumentError) expect { yield_control.at_most(2).at_least(1).at_most(1) }.to raise_error(ArgumentError) expect { yield_control.at_most(1).at_least(2) }.to raise_error(ArgumentError) expect { yield_control.at_least(2).at_most(1) }.to raise_error(ArgumentError) end it 'is supports multiple calls to compatible count constraints' do expect { |b| 1.upto(4, &b) }.to yield_control.at_least(3).at_most(4).times expect { |b| 1.upto(2, &b) }.not_to yield_control.at_least(3).at_most(4).times end it 'raises an error on multiple incompatible calls to count constraints' do expect { yield_control.once.twice }.to raise_error(/multiple/i) end context "with exact count" do it 'fails if the block yields wrong number of times' do expect { expect { |b| [1, 2].each(&b) }.to yield_control.once }.to fail_with(/expected given block to yield control once but yielded twice/) expect { expect { |b| [1, 2, 3].each(&b) }.to yield_control.twice }.to fail_with(/expected given block to yield control twice but yielded 3 times/) expect { expect { |b| [1, 2].each(&b) }.to yield_control.thrice }.to fail_with(/expected given block to yield control 3 times/) end it 'passes if the block yields the specified number of times' do expect { |b| [1].each(&b) }.to yield_control.once expect { |b| [1, 2].each(&b) }.to yield_control.twice expect { |b| [1, 2, 3].each(&b) }.to yield_control.thrice expect { |b| [1, 2, 3, 4].each(&b) }.to yield_control.exactly(4).times end end context "with at_least count" do it 'passes if the block yields the given number of times' do expect { |b| [1, 2].each(&b) }.to yield_control.at_least(2).times expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_least(3).times end it 'passes if the block yields more times' do expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_least(2).times expect { |b| [1, 2, 3, 4].each(&b) }.to yield_control.at_least(3).times end it 'allows :once, :twice, and :thrice to be passed as counts' do expect { |b| [1].each(&b) }.to yield_control.at_least(:once) expect { |b| [1, 2].each(&b) }.to yield_control.at_least(:once) expect { expect { |b| [].each(&b) }.to yield_control.at_least(:once) }.to fail_with(/at least once/) expect { |b| [1, 2].each(&b) }.to yield_control.at_least(:twice) expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_least(:twice) expect { expect { |b| [1].each(&b) }.to yield_control.at_least(:twice) }.to fail_with(/at least twice/) expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_least(:thrice) expect { |b| [1, 2, 3, 4].each(&b) }.to yield_control.at_least(:thrice) expect { expect { |b| [1, 2].each(&b) }.to yield_control.at_least(:thrice) }.to fail_with(/at least 3 times/) end it 'fails if the block yields too few times' do expect { expect { |b| _yield_with_no_args(&b) }.to yield_control.at_least(2).times }.to fail_with(/expected given block to yield control at least twice/) end end context "with at_most count" do it 'passes if the block yields the given number of times' do expect { |b| [1, 2].each(&b) }.to yield_control.at_most(2).times expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_most(3).times end it 'passes if the block yields fewer times' do expect { |b| [1, 2].each(&b) }.to yield_control.at_most(3).times end it 'allows :once, :twice, and :thrice to be passed as counts' do expect { |b| [1].each(&b) }.to yield_control.at_most(:once) expect { expect { |b| [1, 2].each(&b) }.to yield_control.at_most(:once) }.to fail_with(/expected given block to yield control at most once/) expect { |b| [1, 2].each(&b) }.to yield_control.at_most(:twice) expect { expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_most(:twice) }.to fail_with(/expected given block to yield control at most twice/) expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_most(:thrice) expect { expect { |b| [1, 2, 3, 4].each(&b) }.to yield_control.at_most(:thrice) }.to fail_with(/expected given block to yield control at most 3 times/) end it 'fails if the block yields too many times' do expect { expect { |b| [1, 2, 3].each(&b) }.to yield_control.at_most(2).times }.to fail_with(/expected given block to yield control at most twice/) end end end describe "expect {...}.not_to yield_control" do it 'passes if the block does not yield' do expect { |b| _dont_yield(&b) }.not_to yield_control end it 'fails if the block does yield' do expect { expect { |b| _yield_with_no_args(&b) }.not_to yield_control }.to fail_with(/expected given block not to yield control/) end it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect {}.not_to yield_control }.to raise_error(/expect block must accept an argument/) end it 'still works when the block uses an arg splat' do expect { |*args| _dont_yield(&args.first) }.not_to yield_control end it 'raises an error if the expect block arg is not passed to a method as a block' do expect { expect { |b| }.not_to yield_control }.to raise_error(/must pass the argument.*as a block/) end end end RSpec.describe "yield_with_no_args matcher" do include YieldHelpers extend YieldHelpers it_behaves_like "an RSpec probe-yielding block-only matcher" do let(:matcher) { yield_with_no_args } def valid_block(&block) _yield_with_no_args(&block) end def invalid_block(&block) _yield_with_args(1, &block) end end it 'has a description' do expect(yield_with_no_args.description).to eq("yield with no args") end it 'does not return a meaningful value from the block' do val = nil expect { |b| val = _yield_with_no_args(&b) }.to yield_with_no_args expect(val).to be_nil end describe "expect {...}.to yield_with_no_args" do it 'passes if the block yields with no args' do expect { |b| _yield_with_no_args(&b) }.to yield_with_no_args end it 'passes if the block yields with no args using instance_exec' do expect { |b| InstanceEvaler.new.yield_with_no_args(&b) }.to yield_with_no_args end it 'fails if the block does not yield' do expect { expect { |b| _dont_yield(&b) }.to yield_with_no_args }.to fail_with(/expected given block to yield with no arguments, but did not yield/) end it 'fails if the block yields with args' do expect { expect { |b| _yield_with_args(1, &b) }.to yield_with_no_args }.to fail_with(/expected given block to yield with no arguments, but yielded with arguments/) end it 'fails if the block yields with arg false' do expect { expect { |b| _yield_with_args(false, &b) }.to yield_with_no_args }.to fail_with(/expected given block to yield with no arguments, but yielded with arguments/) end it 'raises an error if it yields multiple times' do expect { expect { |b| [1, 2].each(&b) }.to yield_with_no_args }.to raise_error(/not designed.*yields multiple times/) end end describe "expect {...}.not_to yield_with_no_args" do it "passes if the block does not yield" do expect { |b| _dont_yield(&b) }.not_to yield_with_no_args end it "passes if the block yields with args" do expect { |b| _yield_with_args(1, &b) }.not_to yield_with_no_args end it "fails if the block yields with no args" do expect { expect { |b| _yield_with_no_args(&b) }.not_to yield_with_no_args }.to fail_with(/expected given block not to yield with no arguments, but did/) end it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect {}.not_to yield_with_no_args }.to raise_error(/expect block must accept an argument/) end it 'raises an error if the expect block arg is not passed to a method as a block' do expect { expect { |b| }.not_to yield_with_no_args }.to raise_error(/must pass the argument.*as a block/) end end end RSpec.describe "yield_with_args matcher" do include YieldHelpers extend YieldHelpers it_behaves_like "an RSpec probe-yielding block-only matcher" do let(:matcher) { yield_with_args(1) } def valid_block(&block) _yield_with_args(1, &block) end def invalid_block(&block) _yield_with_args(2, &block) end end it 'has a description' do expect(yield_with_args.description).to eq("yield with args") expect(yield_with_args(1, 3).description).to eq("yield with args(1, 3)") expect(yield_with_args(false).description).to eq("yield with args(false)") end it 'does not return a meaningful value from the block' do val = nil expect { |b| val = _yield_with_args(1, &b) }.to yield_with_args(1) expect(val).to be_nil end describe "expect {...}.to yield_with_args" do it 'passes if the block yields with arguments' do expect { |b| _yield_with_args(1, &b) }.to yield_with_args end it 'passes if the matchers match at yield time only' do expect { |b| val = [] _yield_with_args(val, &b) val << 1 }.to yield_with_args(be_empty) end it 'fails if the block does not yield' do expect { expect { |b| _dont_yield(&b) }.to yield_with_args }.to fail_with(/expected given block to yield with arguments, but did not yield/) end it 'fails if the block yields with no arguments' do expect { expect { |b| _yield_with_no_args(&b) }.to yield_with_args }.to fail_with(/expected given block to yield with arguments, but yielded with no arguments/) end it 'fails if the matchers match at return time only' do expect { expect { |b| val = [1] _yield_with_args(val, &b) val.clear }.to yield_with_args(be_empty) }.to fail_with(dedent <<-EOS) |expected given block to yield with arguments, but yielded with unexpected arguments |expected: [(be empty)] | got: [[1]] EOS end it 'raises an error if it yields multiple times' do expect { expect { |b| [1, 2].each(&b) }.to yield_with_args }.to raise_error(/not designed.*yields multiple times/) end end describe "expect {...}.not_to yield_with_args" do it 'fails if the block yields with arguments' do expect { expect { |b| _yield_with_args(1, &b) }.not_to yield_with_args }.to fail_with(/expected given block not to yield with arguments, but did/) end it 'fails if the matchers match at yield time only' do expect { expect { |b| val = [] _yield_with_args(val, &b) val << 1 }.not_to yield_with_args(be_empty) }.to fail_with(dedent <<-EOS) |expected given block not to yield with arguments, but yielded with expected arguments |expected not: [(be empty)] | got: [[]] EOS end it 'passes if the block does not yield' do expect { |b| _dont_yield(&b) }.not_to yield_with_args end it 'passes if the block yields with no arguments' do expect { |b| _yield_with_no_args(&b) }.not_to yield_with_args end it 'passes if the matchers match at return time only' do expect { |b| val = [1] _yield_with_args(val, &b) val.clear }.not_to yield_with_args(be_empty) end it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect {}.not_to yield_with_args }.to raise_error(/expect block must accept an argument/) end it 'raises an error if the expect block arg is not passed to a method as a block' do expect { expect { |b| }.not_to yield_with_args }.to raise_error(/must pass the argument.*as a block/) end end describe "expect {...}.to yield_with_args(3, 17)" do it 'passes if the block yields with the given arguments' do expect { |b| _yield_with_args(3, 17, &b) }.to yield_with_args(3, 17) end it 'passes if the block yields with the given arguments using instance_exec' do expect { |b| InstanceEvaler.new.yield_with_args(3, 17, &b) }.to yield_with_args(3, 17) end it 'fails if the block does not yield' do expect { expect { |b| _dont_yield(&b) }.to yield_with_args(3, 17) }.to fail_with(/expected given block to yield with arguments, but did not yield/) end it 'fails if the block yields with no arguments' do expect { expect { |b| _yield_with_no_args(&b) }.to yield_with_args(3, 17) }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end it 'fails if the block yields with different arguments' do expect { expect { |b| _yield_with_args("a", "b", &b) }.to yield_with_args("a", "c") }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end end describe "expect {...}.to yield_with_args(matcher, matcher)" do it 'passes when the matchers match the args' do expect { |b| _yield_with_args(1.1, "food", &b) }.to yield_with_args(a_value_within(0.2).of(1), a_string_matching(/foo/)) end it 'provides a description' do description = yield_with_args(a_value_within(0.2).of(1), a_string_matching(/foo/)).description expect(description).to eq("yield with args(a value within 0.2 of 1, a string matching /foo/)") end it 'fails with a useful error message when the matchers do not match the args' do expect { expect { |b| _yield_with_args(2.1, "food", &b) }.to yield_with_args(a_value_within(0.2).of(1), a_string_matching(/foo/)) }.to fail_with(dedent <<-EOS) |expected given block to yield with arguments, but yielded with unexpected arguments |expected: [(a value within 0.2 of 1), (a string matching /foo/)] | got: [2.1, "food"] EOS end end describe "expect {...}.not_to yield_with_args(3, 17)" do it 'passes if the block yields with different arguments' do expect { |b| _yield_with_args("a", "b", &b) }.not_to yield_with_args("a", "c") end it 'fails if the block yields with the given arguments' do expect { expect { |b| _yield_with_args("a", "b", &b) }.not_to yield_with_args("a", "b") }.to fail_with(/expected given block not to yield with arguments, but yielded with expected arguments/) end end describe "expect {...}.not_to yield_with_args(matcher, matcher)" do it 'passes when the matchers do not match the args' do expect { |b| _yield_with_args(2.1, "food", &b) }.not_to yield_with_args(a_value_within(0.2).of(1), a_string_matching(/foo/)) end it 'fails with a useful error message when the matchers do not match the args' do expect { expect { |b| _yield_with_args(1.1, "food", &b) }.not_to yield_with_args(a_value_within(0.2).of(1), a_string_matching(/foo/)) }.to fail_with(dedent <<-EOS) |expected given block not to yield with arguments, but yielded with expected arguments |expected not: [(a value within 0.2 of 1), (a string matching /foo/)] | got: [1.1, "food"] EOS end end describe "expect {...}.to yield_with_args( false )" do it 'passes if the block yields with the given arguments' do expect { |b| _yield_with_args(false, &b) }.to yield_with_args(false) end it 'passes if the block yields with the given arguments using instance_exec' do expect { |b| InstanceEvaler.new.yield_with_args(false, &b) }.to yield_with_args(false) end it 'fails if the block does not yield' do expect { expect { |b| _dont_yield(&b) }.to yield_with_args(false) }.to fail_with(/expected given block to yield with arguments, but did not yield/) end it 'fails if the block yields with no arguments' do expect { expect { |b| _yield_with_no_args(&b) }.to yield_with_args(false) }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end it 'fails if the block yields with different arguments' do expect { expect { |b| _yield_with_args(false, &b) }.to yield_with_args(true) }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end end describe "expect {...}.to yield_with_args(/reg/, /ex/)" do it "passes if the block yields strings matching the regexes" do expect { |b| _yield_with_args("regular", "expression", &b) }.to yield_with_args(/reg/, /ex/) end it "fails if the block yields strings that do not match the regexes" do expect { expect { |b| _yield_with_args("no", "match", &b) }.to yield_with_args(/reg/, /ex/) }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end end describe "expect {...}.to yield_with_args(String, Integer)" do it "passes if the block yields objects of the given classes" do expect { |b| _yield_with_args("string", 15, &b) }.to yield_with_args(String, Integer) end it "passes if the block yields the given classes" do expect { |b| _yield_with_args(String, Integer, &b) }.to yield_with_args(String, Integer) end it "fails if the block yields objects of different classes" do expect { expect { |b| _yield_with_args(15, "string", &b) }.to yield_with_args(String, Integer) }.to fail_with(/expected given block to yield with arguments, but yielded with unexpected arguments/) end end end RSpec.describe "yield_successive_args matcher" do include YieldHelpers extend YieldHelpers it_behaves_like "an RSpec probe-yielding block-only matcher" do let(:matcher) { yield_successive_args(1, 2) } def valid_block(&block) [1, 2].each(&block) end def invalid_block(&block) [3, 4].each(&block) end end it 'has a description' do expect(yield_successive_args(1, 3).description).to eq("yield successive args(1, 3)") expect(yield_successive_args([:a, 1], [:b, 2]).description).to eq("yield successive args([:a, 1], [:b, 2])") end it 'does not return a meaningful value from the block' do val = nil expect { |b| val = _yield_with_args(1, &b) }.to yield_successive_args(1) expect(val).to be_nil end it "works correctly when the method yields multiple args each time (passing case)" do expect { |block| ['football', 'barstool'].each_with_index(&block) }.to yield_successive_args( [/foo/, 0], [a_string_starting_with('bar'), 1] ) end it "works correctly when the method yields multiple args each time (failing case)" do expect { expect { |block| ['football', 'barstool'].each_with_index(&block) }.to yield_successive_args( [/foo/, 0], [a_string_starting_with('abr'), 1] ) }.to fail_with(dedent <<-EOS) |expected given block to yield successively with arguments, but yielded with unexpected arguments |expected: [[/foo/, 0], [(a string starting with "abr"), 1]] | got: [["football", 0], ["barstool", 1]] EOS end describe "expect {...}.to yield_successive_args([:a, 1], [:b, 2])" do it 'passes when the block successively yields the given args' do expect { |b| [[:a, 1], [:b, 2]].each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) end it 'passes if matched at yield time only' do expect { |b| [[:a, 1], [:b, 2]].each do |val| _yield_with_args(val, &b) val.clear end }.to yield_successive_args([:a, 1], [:b, 2]) end it 'fails when the block does not yield that many times' do expect { expect { |b| [[:a, 1]].each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) }.to fail_with(/but yielded with unexpected arguments/) end it 'fails when the block yields the right number of times but with different arguments' do expect { expect { |b| [[:a, 1], [:b, 3]].each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) }.to fail_with(/but yielded with unexpected arguments/) end it 'fails if matched at return time only' do expect { expect { |b| [[:a, 1], [:b, 2]].each do |eventual| initial = [] _yield_with_args(initial, &b) initial.concat(eventual) end }.to yield_successive_args([:a, 1], [:b, 2]) }.to fail_with(dedent <<-EOS) |expected given block to yield successively with arguments, but yielded with unexpected arguments |expected: [[:a, 1], [:b, 2]] | got: [[], []] EOS end end describe "expect {...}.to yield_successive_args(1, 2, 3)" do it 'passes when the block successively yields the given args' do expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) end it 'passes when the block successively yields the given args using instance_exec' do expect { |b| InstanceEvaler.new.each_arg(1, 2, 3, &b) }.to yield_successive_args(1, 2, 3) end it 'fails when the block does not yield the expected args' do expect { expect { |b| [1, 2, 4].each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) }.to fail_with(/but yielded with unexpected arguments/) end end describe "expect {...}.to yield_successive_args(matcher, matcher)" do it 'passes when the successively yielded args match the matchers' do expect { |b| %w[ food barn ].each(&b) }.to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) end it 'fails when the successively yielded args do not match the matchers' do expect { expect { |b| %w[ barn food ].each(&b) }.to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) }.to fail_with(dedent <<-EOS) |expected given block to yield successively with arguments, but yielded with unexpected arguments |expected: [(a string matching /foo/), (a string matching /bar/)] | got: ["barn", "food"] EOS end it 'provides a description' do description = yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)).description expect(description).to eq("yield successive args(a string matching /foo/, a string matching /bar/)") end end describe "expect {...}.not_to yield_successive_args(1, 2, 3)" do it 'passes when the block does not yield' do expect { |b| _dont_yield(&b) }.not_to yield_successive_args(1, 2, 3) end it 'passes when the block yields the wrong number of times' do expect { |b| [1, 2].each(&b) }.not_to yield_successive_args(1, 2, 3) end it 'passes when the block yields the wrong arguments' do expect { |b| [1, 2, 4].each(&b) }.not_to yield_successive_args(1, 2, 3) end it 'fails when the block yields the given arguments' do expect { expect { |b| [1, 2, 3].each(&b) }.not_to yield_successive_args(1, 2, 3) }.to fail_with(/expected given block not to yield successively/) end it 'fails if the expect block does not accept an argument', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect {}.not_to yield_successive_args(1, 2, 3) }.to raise_error(/expect block must accept an argument/) end it 'raises an error if the expect block arg is not passed to a method as a block' do expect { expect { |b| }.not_to yield_successive_args(1, 2, 3) }.to raise_error(/must pass the argument.*as a block/) end end describe "expect {...}.not_to yield_successive_args(matcher, matcher)" do it 'passes when the successively yielded args do not match the matchers' do expect { |b| %w[ barn food ].each(&b) }.not_to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) end it 'passes when the successively yielded args do not match the matchers (at yield time only)' do expect { |b| %w[ food barn ].each do |eventual| initial = '' _yield_with_args(initial, &b) initial << eventual end }.not_to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) end it 'fails when the successively yielded args match the matchers' do expect { expect { |b| %w[ food barn ].each(&b) }.not_to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) }.to fail_with(dedent <<-EOS) |expected given block not to yield successively with arguments, but yielded with expected arguments |expected not: [(a string matching /foo/), (a string matching /bar/)] | got: ["food", "barn"] EOS end it 'fails when the successively yielded args match the matchers (at yield time only)' do values = %w[ food barn ].collect { |value| value.dup } expect { expect { |b| values.each do |val| _yield_with_args(val, &b) val.sub!(/.+/, '') end }.not_to yield_successive_args(a_string_matching(/foo/), a_string_matching(/bar/)) }.to fail_with(dedent <<-EOS) |expected given block not to yield successively with arguments, but yielded with expected arguments |expected not: [(a string matching /foo/), (a string matching /bar/)] | got: ["food", "barn"] EOS end end describe "expect {...}.to yield_successive_args(String, Integer)" do it "passes if the block successively yields objects of the given classes" do expect { |b| ["string", 15].each(&b) }.to yield_successive_args(String, Integer) end it "passes if the block yields the given classes" do expect { |b| [String, Integer].each(&b) }.to yield_successive_args(String, Integer) end it "fails if the block yields objects of different classes" do expect { expect { |b| [15, "string"].each(&b) }.to yield_successive_args(String, Integer) }.to fail_with(/expected given block to yield successively with arguments/) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/respond_to_spec.rb0000664000000000000000000011122414557700001031577 0ustar rootrootRSpec.describe "expect(...).to respond_to(:sym)" do it_behaves_like "an RSpec value matcher", :valid_value => "s", :invalid_value => 5 do let(:matcher) { respond_to(:upcase) } end it "passes if target responds to :sym" do expect(Object.new).to respond_to(:methods) end it "passes if target responds to :sym but does not implement method" do # This simulates a behaviour of Rails, see #1162. klass = Class.new { def respond_to?(_); true; end } expect(klass.new).to respond_to(:my_method) end it "fails if target does not respond to :sym" do expect { expect("this string").to respond_to(:some_method) }.to fail_with('expected "this string" to respond to :some_method') end end RSpec.describe "expect(...).to respond_to(:sym).with(1).argument" do it "passes if target responds to :sym with 1 arg" do obj = Object.new def obj.foo(arg); end expect(obj).to respond_to(:foo).with(1).argument end it "passes if target responds to any number of arguments" do obj = Object.new def obj.foo(*args); end expect(obj).to respond_to(:foo).with(1).argument end it "passes if target responds to one or more arguments" do obj = Object.new def obj.foo(a, *args); end expect(obj).to respond_to(:foo).with(1).argument end it "verifes the method signature of new as if it was initialize" do klass = Class.new { def initialize(a, b); end; } expect(klass).to respond_to(:new).with(2).arguments end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with(1).argument }.to fail_with(/expected .* to respond to :some_method/) end it "fails if :sym expects 0 args" do obj = Object.new def obj.foo; end expect { expect(obj).to respond_to(:foo).with(1).argument }.to fail_with(/expected # to respond to :foo with 1 argument/) end it "fails if :sym expects 2 args" do obj = Object.new def obj.foo(arg, arg2); end expect { expect(obj).to respond_to(:foo).with(1).argument }.to fail_with(/expected # to respond to :foo with 1 argument/) end it "fails if :sym expects 2 or more args" do obj = Object.new def obj.foo(arg, arg2, *args); end expect { expect(obj).to respond_to(:foo).with(1).argument }.to fail_with(/expected # to respond to :foo with 1 argument/) end it "fails if the method signature of initialize does not match" do klass = Class.new { def initialize(a, b); end; } expect { expect(klass).to respond_to(:new).with(1).arguments }.to fail_with(/expected # to respond to :new with 1 argument/) end it "still works if target has overridden the method method" do obj = Object.new def obj.method; end def obj.other_method(arg); end expect(obj).to respond_to(:other_method).with(1).argument end it "warns that the subject does not have the implementation required when method does not exist" do # This simulates a behaviour of Rails, see #1162. klass = Class.new { def respond_to?(_); true; end } expect { expect(klass.new).to respond_to(:my_method).with(0).arguments }.to raise_error(ArgumentError) end end RSpec.describe "expect(...).to respond_to(:new)" do context "with no tampering" do it "will validate new as if it was initialize" do klass = Class.new { def initialize(a, b, c); end } expect(klass).not_to respond_to(:new).with(2).arguments expect(klass).to respond_to(:new).with(3).arguments end end context "on a class that has redefined `new`" do it "uses the method signature of the redefined `new` for arg verification" do klass = Class.new { def self.new(a); end } expect(klass).to respond_to(:new).with(1).argument expect { expect(klass).to respond_to(:new).with(2).arguments }.to fail_with(/expected # to respond to :new with 2 arguments/) expect { expect(klass).to_not respond_to(:new).with(1).argument }.to fail_with(/expected # not to respond to :new with 1 argument/) end end context "on a class that has undefined `new`" do it "will not respond to new" do klass = Class.new do class << self undef new end end expect { expect(klass).to respond_to(:new) }.to fail_with(/expected .* to respond to :new/) end end context "on a class with a private `new`" do it "will not respond to new" do klass = Class.new { private_class_method :new; def initialize(a, b, c); end } expect(klass).not_to respond_to(:new) end end end RSpec.describe "expect(...).to respond_to(message1, message2)" do it "passes if target responds to both messages" do expect(Object.new).to respond_to('methods', 'inspect') end it "fails if target does not respond to first message" do expect { expect(Object.new).to respond_to('method_one', 'inspect') }.to fail_with(/expected # to respond to "method_one"/) end it "fails if target does not respond to second message" do expect { expect(Object.new).to respond_to('inspect', 'method_one') }.to fail_with(/expected # to respond to "method_one"/) end it "fails if target does not respond to either message" do expect { expect(Object.new).to respond_to('method_one', 'method_two') }.to fail_with(/expected # to respond to "method_one", "method_two"/) end end RSpec.describe "expect(...).to respond_to(:sym).with(2).arguments" do it "passes if target responds to :sym with 2 args" do obj = Object.new def obj.foo(a1, a2); end expect(obj).to respond_to(:foo).with(2).arguments end it "passes if target responds to any number of arguments" do obj = Object.new def obj.foo(*args); end expect(obj).to respond_to(:foo).with(2).arguments end it "passes if target responds to one or more arguments" do obj = Object.new def obj.foo(a, *args); end expect(obj).to respond_to(:foo).with(2).arguments end it "passes if target responds to two or more arguments" do obj = Object.new def obj.foo(a, b, *args); end expect(obj).to respond_to(:foo).with(2).arguments end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with(2).arguments }.to fail_with(/expected .* to respond to :some_method/) end it "fails if :sym expects 0 args" do obj = Object.new def obj.foo; end expect { expect(obj).to respond_to(:foo).with(2).arguments }.to fail_with(/expected # to respond to :foo with 2 arguments/) end it "fails if :sym expects 1 args" do obj = Object.new def obj.foo(arg); end expect { expect(obj).to respond_to(:foo).with(2).arguments }.to fail_with(/expected # to respond to :foo with 2 arguments/) end it "fails if :sym expects 3 or more args" do obj = Object.new def obj.foo(arg, arg2, arg3, *args); end expect { expect(obj).to respond_to(:foo).with(2).arguments }.to fail_with(/expected # to respond to :foo with 2 arguments/) end end RSpec.describe "expect(...).to respond_to(:sym).with(1..2).arguments" do it "passes if target responds to any number of arguments" do obj = Object.new def obj.foo(*args); end expect(obj).to respond_to(:foo).with(1..2).arguments end it "passes if target responds to one or more arguments" do obj = Object.new def obj.foo(a, *args); end expect(obj).to respond_to(:foo).with(1..2).arguments end it "passes if target responds to one or two arguments" do obj = Object.new def obj.foo(a, b=nil); end expect(obj).to respond_to(:foo).with(1..2).arguments end it "passes if target responds to one to three arguments" do obj = Object.new def obj.foo(a, b=nil, c=nil); end expect(obj).to respond_to(:foo).with(1..2).arguments end it "passes if target is new and initialize reponds to arguments" do klass = Class.new { def initialize(arg, arg2=nil, arg3=nil); end } expect(klass).to respond_to(:new).with(1..2).arguments end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with(1..2).arguments }.to fail_with(/expected .* to respond to :some_method/) end it "fails if :sym expects 0 args" do obj = Object.new def obj.foo; end expect { expect(obj).to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected # to respond to :foo with 1..2 arguments/) end it "fails if :sym expects 1 args" do obj = Object.new def obj.foo(arg); end expect { expect(obj).to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected # to respond to :foo with 1..2 arguments/) end it "fails if :sym expects 2 args" do obj = Object.new def obj.foo(a, b); end expect { expect(obj).to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected # to respond to :foo with 1..2 arguments/) end it "fails if :sym expects 3 or more args" do obj = Object.new def obj.foo(arg, arg2, arg3, *args); end expect { expect(obj).to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected # to respond to :foo with 1..2 arguments/) end it "fails when new unless initialize matches the signature" do klass = Class.new { def initialize(arg, arg2, arg3, *args); end } expect { expect(klass).to respond_to(:new).with(1..2).arguments }.to fail_with(/expected # to respond to :new with 1..2 arguments/) end end RSpec.describe "expect(...).to respond_to(:sym).with_unlimited_arguments" do it "passes if target responds to any number of arguments" do obj = Object.new def obj.foo(*args); end expect(obj).to respond_to(:foo).with_unlimited_arguments end it "passes if target responds to a minimum number of arguments" do obj = Object.new def obj.foo(arg, arg2, arg3, *args); end expect(obj).to respond_to(:foo).with(3).arguments.and_unlimited_arguments end it "passes when target is new and initialize responds to any number of arguments" do # note we can't use the metaobject definition for initialize klass_2 = Class.new { def initialize(*args); end } expect(klass_2).to respond_to(:new).with_unlimited_arguments end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with_unlimited_arguments }.to fail_with(/expected .* to respond to :some_method/) end it "fails if :sym expects a minimum number of arguments" do obj = Object.new def obj.some_method(arg, arg2, arg3, *args); end expect { expect(obj).to respond_to(:some_method).with_unlimited_arguments }.to fail_with(/expected .* to respond to :some_method with unlimited arguments/) end it "fails if :sym expects a limited number of arguments" do obj = Object.new def obj.some_method(arg); end expect { expect(obj).to respond_to(:some_method).with_unlimited_arguments }.to fail_with(/expected .* to respond to :some_method with unlimited arguments/) end it "fails when target is new and initialize responds to a set number of arguments" do klass = Class.new { def initialize(a); end } expect { expect(klass).to respond_to(:new).with_unlimited_arguments }.to fail_with(/expected .* to respond to :new with unlimited arguments/) end end RSpec.describe "expect(...).not_to respond_to(:sym)" do it "passes if target does not respond to :sym" do expect(Object.new).not_to respond_to(:some_method) end it "fails if target responds to :sym" do expect { expect(Object.new).not_to respond_to(:methods) }.to fail_with(/expected # not to respond to :methods/) end end RSpec.describe "expect(...).not_to respond_to(:sym).with(1).argument" do it "fails if target responds to :sym with 1 arg" do obj = Object.new def obj.foo(arg); end expect { expect(obj).not_to respond_to(:foo).with(1).argument }.to fail_with(/expected # not to respond to :foo with 1 argument/) end it "fails if target responds to :sym with any number of args" do obj = Object.new def obj.foo(*args); end expect { expect(obj).not_to respond_to(:foo).with(1).argument }.to fail_with(/expected # not to respond to :foo with 1 argument/) end it "fails if target responds to :sym with one or more args" do obj = Object.new def obj.foo(a, *args); end expect { expect(obj).not_to respond_to(:foo).with(1).argument }.to fail_with(/expected # not to respond to :foo with 1 argument/) end it "will fail when target is new and initialize matches the argument signature" do klass = Class.new { def initialize(a); end } expect { expect(klass).to_not respond_to(:new).with(1).argument }.to fail_with(/not to respond to :new with 1 argument/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with(1).argument end it "passes if :sym expects 0 args" do obj = Object.new def obj.foo; end expect(obj).not_to respond_to(:foo).with(1).argument end it "passes if :sym expects 2 args" do obj = Object.new def obj.foo(arg, arg2); end expect(obj).not_to respond_to(:foo).with(1).argument end it "passes if :sym expects 2 or more args" do obj = Object.new def obj.foo(arg, arg2, *args); end expect(obj).not_to respond_to(:foo).with(1).argument end it "will pass when target is new and initialize does not matches the argument signature" do klass = Class.new { def initialize(a, b); end } expect(klass).to_not respond_to(:new).with(1).argument end end RSpec.describe "expect(...).not_to respond_to(message1, message2)" do it "passes if target does not respond to either message1 or message2" do expect(Object.new).not_to respond_to(:some_method, :some_other_method) end it "fails if target responds to message1 but not message2" do expect { expect(Object.new).not_to respond_to(:object_id, :some_method) }.to fail_with(/expected # not to respond to :object_id/) end it "fails if target responds to message2 but not message1" do expect { expect(Object.new).not_to respond_to(:some_method, :object_id) }.to fail_with(/expected # not to respond to :object_id/) end it "fails if target responds to both message1 and message2" do expect { expect(Object.new).not_to respond_to(:class, :object_id) }.to fail_with(/expected # not to respond to :class, :object_id/) end end RSpec.describe "expect(...).not_to respond_to(:sym).with(2).arguments" do it "fails if target responds to :sym with 2 args" do obj = Object.new def obj.foo(a1, a2); end expect { expect(obj).not_to respond_to(:foo).with(2).arguments }.to fail_with(/expected .* not to respond to :foo with 2 arguments/) end it "fails if target responds to :sym with any number args" do obj = Object.new def obj.foo(*args); end expect { expect(obj).not_to respond_to(:foo).with(2).arguments }.to fail_with(/expected .* not to respond to :foo with 2 arguments/) end it "fails if target responds to :sym with one or more args" do obj = Object.new def obj.foo(a, *args); end expect { expect(obj).not_to respond_to(:foo).with(2).arguments }.to fail_with(/expected .* not to respond to :foo with 2 arguments/) end it "fails if target responds to :sym with two or more args" do obj = Object.new def obj.foo(a, b, *args); end expect { expect(obj).not_to respond_to(:foo).with(2).arguments }.to fail_with(/expected .* not to respond to :foo with 2 arguments/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with(2).arguments end it "passes if :sym expects 0 args" do obj = Object.new def obj.foo; end expect(obj).not_to respond_to(:foo).with(2).arguments end it "passes if :sym expects 2 args" do obj = Object.new def obj.foo(arg); end expect(obj).not_to respond_to(:foo).with(2).arguments end it "passes if :sym expects 3 or more args" do obj = Object.new def obj.foo(a, b, c, *arg); end expect(obj).not_to respond_to(:foo).with(2).arguments end end RSpec.describe "expect(...).not_to respond_to(:sym).with(1..2).arguments" do it "fails if target responds to :sym with one or two args" do obj = Object.new def obj.foo(a1, a2=nil); end expect { expect(obj).not_to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected .* not to respond to :foo with 1..2 arguments/) end it "fails if target responds to :sym with any number args" do obj = Object.new def obj.foo(*args); end expect { expect(obj).not_to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected .* not to respond to :foo with 1..2 arguments/) end it "fails if target responds to :sym with one or more args" do obj = Object.new def obj.foo(a, *args); end expect { expect(obj).not_to respond_to(:foo).with(1..2).arguments }.to fail_with(/expected .* not to respond to :foo with 1..2 arguments/) end it "will fail when target is new and initialize matches the argument signature" do klass = Class.new { def initialize(a, *args); end } expect { expect(klass).to_not respond_to(:new).with(1..2).argument }.to fail_with(/not to respond to :new with 1..2 argument/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with(1..2).arguments end it "passes if :sym expects 0 args" do obj = Object.new def obj.foo; end expect(obj).not_to respond_to(:foo).with(1..2).arguments end it "passes if :sym expects 1 arg" do obj = Object.new def obj.foo(arg); end expect(obj).not_to respond_to(:foo).with(1..2).arguments end it "passes if :sym expects 2 args" do obj = Object.new def obj.foo(a, b); end expect(obj).not_to respond_to(:foo).with(1..2).arguments end it "passes if :sym expects 3 or more args" do obj = Object.new def obj.foo(a, b, c, *arg); end expect(obj).not_to respond_to(:foo).with(1..2).arguments end it "passes when target is new and initialize does not match the argument signature" do klass = Class.new { def initialize(a); end } expect(klass).to_not respond_to(:new).with(1..2).argument end end RSpec.describe "expect(...).not_to respond_to(:sym).with_unlimited_arguments" do it "fails if target responds to :sym with any number args" do obj = Object.new def obj.foo(*args); end expect { expect(obj).not_to respond_to(:foo).with_unlimited_arguments }.to fail_with(/expected .* not to respond to :foo with unlimited arguments/) end it "will fail when target is new and initialize has unlimited arguments" do klass = Class.new { def initialize(*args); end } expect { expect(klass).to_not respond_to(:new).with_unlimited_arguments }.to fail_with(/not to respond to :new with unlimited argument/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with_unlimited_arguments end it "passes if :sym expects a limited number of arguments" do obj = Object.new def obj.some_method(arg); end expect(obj).not_to respond_to(:some_method).with_unlimited_arguments end it "passes if :sym expects a minimum number of arguments" do obj = Object.new def obj.some_method(arg, arg2, arg3, *args); end expect(obj).not_to respond_to(:some_method).with_unlimited_arguments end it "passes when target is new and initialize has arguments" do klass = Class.new { def initialize(a, *args); end } expect(klass).to_not respond_to(:new).with_unlimited_arguments end end if RSpec::Support::RubyFeatures.kw_args_supported? RSpec.describe "expect(...).to respond_to(:sym).with_keywords(:foo, :bar)" do it 'passes if target responds to :sym with specified optional keywords' do obj = Object.new eval %{def obj.foo(a: nil, b: nil); end} expect(obj).to respond_to(:foo).with_keywords(:a, :b) end it 'passes if target responds to :sym with any keywords' do obj = Object.new eval %{def obj.foo(**kw_args); end} expect(obj).to respond_to(:foo).with_keywords(:a, :b) end it 'passes if target is :new with keywords' do # note we can't use the metaobject definition for initialize klass = eval %{Class.new { def initialize(a: nil, b: nil); end}} expect(klass).to respond_to(:new).with_keywords(:a, :b) # note we can't use the metaobject definition for initialize klass_2 = eval %{Class.new { def initialize(**kw_args); end}} expect(klass_2).to respond_to(:new).with_keywords(:a, :b) end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with_keywords(:a, :b) }.to fail_with(/expected .* to respond to :some_method with keywords :a and :b/) end it "fails if :sym does not expect specified keywords" do obj = Object.new def obj.foo; end expect { expect(obj).to respond_to(:foo).with_keywords(:a, :b) }.to fail_with(/expected .* to respond to :foo with keywords :a and :b/) end it "fails if :sym does not expect many specified keywords" do obj = Object.new def obj.foo; end expect { expect(obj).to respond_to(:foo).with_keywords(:a, :b, :c, :d, :e, :f) }.to fail_with(/expected .* to respond to :foo with keywords :a, :b, :c, :d, :e, and :f/) end it 'fails if target is :new but initialize does not expect the right keywords' do # note we can't use the metaobject definition for initialize klass = eval %{Class.new { def initialize(a: nil); end}} expect { expect(klass).to respond_to(:new).with_keywords(:a, :b) }.to fail_with(/expected .* to respond to :new with keywords :a and :b/) end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "passes if target responds to :sym with specified required keywords" do obj = Object.new eval %{def obj.foo(a:, b:, c: nil, d: nil); end} expect(obj).to respond_to(:foo).with_keywords(:a, :b) end it "passes if target responds to :sym with keyword arg splat" do obj = Object.new eval %{def obj.foo(**rest); end} expect(obj).to respond_to(:foo).with_keywords(:a, :b) end it 'passes if target is :new and initialize has specified required keywords' do # note we can't use the metaobject definition for initialize klass = eval %{Class.new { def initialize(a:, b:); end}} expect(klass).to respond_to(:new).with_keywords(:a, :b) end it "fails if :sym expects specified optional keywords but expects missing required keywords" do obj = Object.new eval %{def obj.foo(a:, b:, c: nil, d: nil); end} expect { expect(obj).to respond_to(:some_method).with_keywords(:c, :d) }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) end it "fails if target responds to :sym with keyword arg splat but missing required keywords" do obj = Object.new eval %{def obj.foo(a:, b:, **rest); end} expect { expect(obj).to respond_to(:some_method).with_keywords(:c, :d) }.to fail_with(/expected .* to respond to :some_method with keywords :c and :d/) end it 'fails if target is :new and initialize has is missing required keywords' do # note we can't use the metaobject definition for initialize klass = eval %{Class.new { def initialize(a:, b:); end}} expect { expect(klass).to respond_to(:new).with_keywords(:c, :d) }.to fail_with(/expected .* to respond to :new with keywords :c and :d/) end end end RSpec.describe "expect(...).to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do it "passes if target responds to :sym with 2 args and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, b, u: nil, v: nil); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "passes if target responds to :sym with any number of arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(*args, u: nil, v: nil); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "passes if target responds to :sym with one or more arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, *args, u: nil, v: nil); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "passes if target responds to :sym with two or more arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) end it "fails if :sym expects 1 argument" do obj = Object.new eval %{def obj.foo(a, u: nil, v: nil); end} expect { expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) end it "fails if :sym does not expect specified keywords" do obj = Object.new def obj.foo(a, b); end expect { expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "passes if target responds to :sym with 2 args and specified required keywords" do obj = Object.new eval %{def obj.foo(a, b, u:, v:); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "passes if target responds to :sym with 2 args and keyword arg splat" do obj = Object.new eval %{def obj.foo(a, b, **rest); end} expect(obj).to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) end it "passes for new when target responds to initialize with a mixture of arguments" do klass = eval %{Class.new { def initialize(a, b, c:, d: nil); end }} expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) end it "fails if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do obj = Object.new eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} expect { expect(obj).to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected .* to respond to :some_method with 2 arguments and keywords :u and :v/) end it "fails for new when target responds to initialize with the wrong mixture of arguments" do klass = eval %{Class.new { def initialize(a, b, c:); end }} expect { expect(klass).to respond_to(:new).with(2).arguments.and_keywords(:c, :d) }.to fail_with(/expected .* to respond to :new with 2 arguments and keywords :c and :d/) end end end RSpec.describe "expect(...).to respond_to(:sym).with_any_keywords" do it "passes if target responds to any keywords" do obj = Object.new eval %{def obj.foo(**kw_args); end} expect(obj).to respond_to(:foo).with_any_keywords end it "passes when initialize responds to any keywords and we check new" do klass = eval %{Class.new { def initialize(**kw_args); end }} expect(klass).to respond_to(:new).with_any_keywords end it "fails if target does not respond to :sym" do obj = Object.new expect { expect(obj).to respond_to(:some_method).with_any_keywords }.to fail_with(/expected .* to respond to :some_method/) end it "fails if :sym expects a limited set of keywords" do obj = Object.new eval %{def obj.some_method(a: nil, b: nil); end} expect { expect(obj).to respond_to(:some_method).with_any_keywords }.to fail_with(/expected .* to respond to :some_method with any keywords/) end it "fails when initialize expects a limited set of keywords and we check new" do klass = eval %{Class.new { def initialize(a: nil); end }} expect { expect(klass).to respond_to(:new).with_any_keywords }.to fail_with(/expected .* to respond to :new with any keywords/) end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "fails if :sym expects missing required keywords" do obj = Object.new eval %{def obj.some_method(a:, b:, **kw_args); end} expect { expect(obj).to respond_to(:some_method).with_any_keywords }.to fail_with(/expected .* to respond to :some_method with any keywords/) end it "fails if :initialize expects missing required keywords when we test new" do klass = eval %{Class.new { def initialize(a:, **kw_args); end }} eval %{def initialize(a:, b:, **kw_args); end} expect { expect(klass).to respond_to(:new).with_any_keywords }.to fail_with(/expected .* to respond to :new with any keywords/) end end end RSpec.describe "expect(...).not_to respond_to(:sym).with_keywords(:foo, :bar)" do it "fails if target responds to :sym with specified optional keywords" do obj = Object.new eval %{def obj.foo(a: nil, b: nil); end} expect { expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) end it "fails if target responds to :sym with any keywords" do obj = Object.new eval %{def obj.foo(**kw_args); end} expect { expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) end it "fails if target initialize responds to expected keywords when checking new" do klass = eval %{Class.new { def initialize(**kw_args); end }} expect { expect(klass).not_to respond_to(:new).with_keywords(:a, :b) }.to fail_with(/expected .* not to respond to :new with keywords :a and :b/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with_keywords(:a, :b) end it "passes if :sym does not expect specified keywords" do obj = Object.new eval %{def obj.foo(a: nil, b: nil); end} expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "fails if target responds to :sym with specified required keywords" do obj = Object.new eval %{def obj.foo(a:, b:); end} expect { expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) end it "fails if target responds to :sym with keyword arg splat" do obj = Object.new eval %{def obj.foo(**rest); end} expect { expect(obj).not_to respond_to(:foo).with_keywords(:a, :b) }.to fail_with(/expected # not to respond to :foo with keywords :a and :b/) end it "passes if :sym expects missing required keywords" do obj = Object.new eval %{def obj.foo(a:, b:, c: nil, d: nil); end} expect(obj).not_to respond_to(:some_method).with_keywords(:c, :d) end it "passes if :initialize expects missing required keywords for :new" do klass = eval %{Class.new { def initialize(a:, b:, c: nil, d: nil); end }} expect(klass).not_to respond_to(:new).with_keywords(:c, :d) end end end RSpec.describe "expect(...).not_to respond_to(:sym).with(2).arguments.and_keywords(:foo, :bar)" do it "fails if target responds to :sym with 2 args and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, b, u: nil, v: nil); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "fails if target responds to :sym with any number of arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(*args, u: nil, v: nil); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "fails if target responds to :sym with one or more arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, *args, u: nil, v: nil); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "fails if target responds to :sym with two or more arguments and specified optional keywords" do obj = Object.new eval %{def obj.foo(a, b, *args, u: nil, v: nil); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) end it "passes if :sym expects 1 argument" do obj = Object.new eval %{def obj.foo(a, u: nil, v: nil); end} expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) end it "passes if :sym does not expect specified keywords" do obj = Object.new def obj.foo(a, b); end expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "fails if target responds to :sym with 2 args and specified required keywords" do obj = Object.new eval %{def obj.foo(a, b, u:, v:); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "fails if target responds to :sym with 2 args and keyword arg splat" do obj = Object.new eval %{def obj.foo(a, b, **rest); end} expect { expect(obj).not_to respond_to(:foo).with(2).arguments.and_keywords(:u, :v) }.to fail_with(/expected # not to respond to :foo with 2 arguments and keywords :u and :v/) end it "passes if :sym expects 2 arguments and specified optional keywords but expects missing required keywords" do obj = Object.new eval %{def obj.foo(a, b, u: nil, v: nil, x:, y:); end} expect(obj).not_to respond_to(:some_method).with(2).arguments.and_keywords(:u, :v) end end end RSpec.describe "expect(...).not_to respond_to(:sym).with_any_keywords" do it "fails if target responds to any keywords" do obj = Object.new eval %{def obj.foo(**kw_args); end} expect { expect(obj).not_to respond_to(:foo).with_any_keywords }.to fail_with(/expected # not to respond to :foo with any keywords/) end it "passes if target does not respond to :sym" do obj = Object.new expect(obj).not_to respond_to(:some_method).with_any_keywords end it "passes if :sym expects a limited set of keywords" do obj = Object.new eval %{def obj.some_method(a: nil, b: nil); end} expect(obj).not_to respond_to(:some_method).with_any_keywords end if RSpec::Support::RubyFeatures.required_kw_args_supported? it "passes if :sym expects missing required keywords" do obj = Object.new eval %{def obj.some_method(a:, b:, **kw_args); end} expect(obj).not_to respond_to(:some_method).with_any_keywords end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/operators_spec.rb0000664000000000000000000001712414557700001031445 0ustar rootrootclass MethodOverrideObject def method :foo end end class MethodMissingObject < Struct.new(:original) undef == def method_missing(name, *args, &block) original.__send__ name, *args, &block end end RSpec.describe "operator matchers", :uses_should do describe "should ==" do it "delegates message to target" do subject = "apple".dup expect(subject).to receive(:==).with("apple").and_return(true) subject.should == "apple" end it "returns true on success" do subject = "apple" (subject.should == "apple").should be_truthy end it "fails when target.==(actual) returns false" do subject = "apple" expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: "orange"\n got: "apple" (using ==)}, "orange", "apple") subject.should == "orange" end it "works when #method is overridden" do myobj = MethodOverrideObject.new expect { myobj.should == myobj }.to_not raise_error end it "works when implemented via method_missing" do obj = Object.new myobj = MethodMissingObject.new(obj) (myobj.should == obj).nil? # just to avoid `useless use of == in void context` warning myobj.should_not == Object.new end end describe "unsupported operators", :if => RUBY_VERSION.to_f == 1.9 do it "raises an appropriate error for should != expected" do expect { "apple".should != "pear" }.to raise_error(/does not support `should != expected`. Use `should_not == expected`/) end it "raises an appropriate error for should_not != expected" do expect { "apple".should_not != "pear" }.to raise_error(/does not support `should_not != expected`. Use `should == expected`/) end it "raises an appropriate error for should !~ expected" do expect { "apple".should !~ /regex/ }.to raise_error(/does not support `should !~ expected`. Use `should_not =~ expected`/) end it "raises an appropriate error for should_not !~ expected" do expect { "apple".should_not !~ /regex/ }.to raise_error(/does not support `should_not !~ expected`. Use `should =~ expected`/) end end describe "should_not ==" do it "delegates message to target" do subject = "orange".dup expect(subject).to receive(:==).with("apple").and_return(false) subject.should_not == "apple" end it "returns true on success" do subject = "apple" (subject.should_not == "orange").should be_falsey end it "fails when target.==(actual) returns false" do subject = "apple" expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: == "apple"\n got: "apple"), "apple", "apple") subject.should_not == "apple" end end describe "should ===" do it "delegates message to target" do subject = "apple".dup expect(subject).to receive(:===).with("apple").and_return(true) subject.should === "apple" end it "fails when target.===(actual) returns false" do subject = "apple".dup expect(subject).to receive(:===).with("orange").and_return(false) expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: "orange"\n got: "apple" (using ===)}, "orange", "apple") subject.should === "orange" end end describe "should_not ===" do it "delegates message to target" do subject = "orange".dup expect(subject).to receive(:===).with("apple").and_return(false) subject.should_not === "apple" end it "fails when target.===(actual) returns false" do subject = "apple".dup expect(subject).to receive(:===).with("apple").and_return(true) expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: === "apple"\n got: "apple"), "apple", "apple") subject.should_not === "apple" end end describe "should =~" do it "delegates message to target" do subject = "foo".dup expect(subject).to receive(:=~).with(/oo/).and_return(true) subject.should =~ /oo/ end it "fails when target.=~(actual) returns false" do subject = "fu".dup expect(subject).to receive(:=~).with(/oo/).and_return(false) expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: /oo/\n got: "fu" (using =~)}, /oo/, "fu") subject.should =~ /oo/ end end describe "should_not =~" do it "delegates message to target" do subject = "fu".dup expect(subject).to receive(:=~).with(/oo/).and_return(false) subject.should_not =~ /oo/ end it "fails when target.=~(actual) returns false" do subject = "foo".dup expect(subject).to receive(:=~).with(/oo/).and_return(true) expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: =~ /oo/\n got: "foo"), /oo/, "foo") subject.should_not =~ /oo/ end end describe "should >" do it "passes if > passes" do 4.should > 3 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: > 5\n got: 4", 5, 4) 4.should > 5 end end describe "should >=" do it "passes if actual == expected" do 4.should >= 4 end it "passes if actual > expected" do 4.should >= 3 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: >= 5\n got: 4", 5, 4) 4.should >= 5 end end describe "should <" do it "passes if < passes" do 4.should < 5 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: < 3\n got: 4", 3, 4) 4.should < 3 end end describe "should <=" do it "passes if actual == expected" do 4.should <= 4 end it "passes if actual < expected" do 4.should <= 5 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: <= 3\n got: 4", 3, 4) 4.should <= 3 end end describe "OperatorMatcher registry" do let(:custom_klass) { Class.new } let(:custom_subklass) { Class.new(custom_klass) } after { RSpec::Matchers::BuiltIn::OperatorMatcher.unregister(custom_klass, "=~") } it "allows operator matchers to be registered for classes" do RSpec::Matchers::BuiltIn::OperatorMatcher.register(custom_klass, "=~", RSpec::Matchers::BuiltIn::Match) expect(RSpec::Matchers::BuiltIn::OperatorMatcher.get(custom_klass, "=~")).to eq(RSpec::Matchers::BuiltIn::Match) end it "considers ancestors when finding an operator matcher" do RSpec::Matchers::BuiltIn::OperatorMatcher.register(custom_klass, "=~", RSpec::Matchers::BuiltIn::Match) expect(RSpec::Matchers::BuiltIn::OperatorMatcher.get(custom_subklass, "=~")).to eq(RSpec::Matchers::BuiltIn::Match) end it "returns nil if there is no matcher registered for a class" do expect(RSpec::Matchers::BuiltIn::OperatorMatcher.get(custom_klass, "=~")).to be_nil end end describe RSpec::Matchers::BuiltIn::PositiveOperatorMatcher do it "works when the target has implemented #send" do o = Object.new def o.send(*_args); raise "DOH! Library developers shouldn't use #send!" end expect { o.should == o }.not_to raise_error end end describe RSpec::Matchers::BuiltIn::NegativeOperatorMatcher do it "works when the target has implemented #send" do o = Object.new def o.send(*_args); raise "DOH! Library developers shouldn't use #send!" end expect { o.should_not == :foo }.not_to raise_error end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/eq_spec.rb0000664000000000000000000001366414557700001030041 0ustar rootrootmodule RSpec module Matchers RSpec.describe "eq" do it_behaves_like "an RSpec value matcher", :valid_value => 1, :invalid_value => 2 do let(:matcher) { eq(1) } end it "is diffable" do expect(eq(1)).to be_diffable end it "matches when actual == expected" do expect(1).to eq(1) end it "does not match when actual != expected" do expect(1).not_to eq(2) end it "compares by sending == to actual (not expected)" do called = false actual = Class.new do define_method :== do |_other| called = true end end.new expect(actual).to eq :anything # to trigger the matches? method expect(called).to be_truthy end it "describes itself" do matcher = eq(1) matcher.matches?(1) expect(matcher.description).to eq "eq 1" end it "provides message, expected and actual on #failure_message" do matcher = eq("1") matcher.matches?(1) expect(matcher.failure_message).to eq "\nexpected: \"1\"\n got: 1\n\n(compared using ==)\n" end it "provides message, expected and actual on #negative_failure_message" do matcher = eq(1) matcher.matches?(1) expect(matcher.failure_message_when_negated).to eq "\nexpected: value != 1\n got: 1\n\n(compared using ==)\n" end # Older versions of Ruby such as less than 1.9 do not have String#encoding available, they are an array of bytes if String.method_defined?(:encoding) context "with String encoding as UTF-16LE" do it "provides message, expected and actual on #failure_message when string encoding is the same" do matcher = eq('abc'.encode('UTF-16LE')) matcher.matches?('def'.encode('UTF-16LE')) expect(matcher.failure_message).to eq "\nexpected: \"abc\"\n got: \"def\"\n\n(compared using ==)\n" end it "matches when actual is BINARY encoding and expected is UTF-8 encoding with the same chars" do expect('abc'.encode('BINARY')).to eq 'abc'.encode('UTF-8') end it "provides message, expected and actual with encoding details on #failure_message when string encoding is different" do matcher = eq('abc'.encode('UTF-16LE')) matcher.matches?('abc'.force_encoding('ASCII-8BIT')) expect(matcher.failure_message).to eq "\nexpected: # \"abc\"\n got: # \"abc\"\n\n(compared using ==)\n" end it "provides message, expected and actual on #negative_failure_message" do matcher = eq('abc'.encode('UTF-16LE')) matcher.matches?('abc'.encode('UTF-16LE')) expect(matcher.failure_message_when_negated).to eq "\nexpected: value != \"abc\"\n got: \"abc\"\n\n(compared using ==)\n" end end end context "with Time objects" do RSpec::Matchers.define :a_string_with_differing_output do match do |string| time_strings = /expected: (.+)\n.*got: (.+)$/.match(string).captures time_strings.uniq.count == 2 end end let(:time1) { Time.utc(1969, 12, 31, 19, 10, 40, 101) } let(:time2) { Time.utc(1969, 12, 31, 19, 10, 40, 102) } it "provides additional precision on #failure_message" do expect { expect(time1).to eq(time2) }.to fail_with(a_string_with_differing_output) end it "provides additional precision on #negative_failure_message" do expect { expect(time1).to_not eq(time1) }.to fail_with(a_string_with_differing_output) end end it 'fails properly when the actual is an array of multiline strings' do expect { expect(["a\nb", "c\nd"]).to eq([]) }.to fail_including("expected: []") end describe '#description' do # Ruby 1.8.7 produces a less precise output expected_seconds = Time.method_defined?(:nsec) ? '000000000' : '000000' [ [nil, 'eq nil'], [true, 'eq true'], [false, 'eq false'], [:symbol, 'eq :symbol'], [1, 'eq 1'], [1.2, 'eq 1.2'], ['foo', 'eq "foo"'], [/regex/, 'eq /regex/'], [['foo'], 'eq ["foo"]'], [{ :foo => :bar }, 'eq {:foo=>:bar}'], [Class, 'eq Class'], [RSpec, 'eq RSpec'], [Time.utc(2014, 1, 1), "eq 2014-01-01 00:00:00.#{expected_seconds} +0000"], ].each do |expected, expected_description| context "with #{expected.inspect}" do around { |ex| with_env_vars('TZ' => 'UTC', &ex) } if expected.is_a?(Time) it "is \"#{expected_description}\"" do expect(eq(expected).description).to eq expected_description end end end context "with Date.new(2014, 1, 1)" do it "is eq to Date.new(2014, 1, 1).inspect" do in_sub_process_if_possible do require 'date' date = Date.new(2014, 1, 1) expect(eq(date).description).to eq "eq #{date.inspect}" end end end context "with Complex(1, 2)" do it "is eq to Complex(1, 2).inspect" do in_sub_process_if_possible do # complex is available w/o requiring on ruby 1.9+. # Loading it on 1.9+ issues a warning, so we only load it on 1.8.7. require 'complex' if RUBY_VERSION == '1.8.7' complex = Complex(1, 2) expect(eq(complex).description).to eq "eq #{complex.inspect}" end end end context 'with object' do it 'matches with "^eq #$"' do expect(eq(Object.new).description).to match(/^eq #$/) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/compound_spec.rb0000664000000000000000000007263014557700001031256 0ustar rootrootmodule RSpec::Matchers::BuiltIn RSpec.describe Compound do let(:matcher_without_diffable) { include("foo") } before do allow(RSpec::Matchers.configuration).to receive_messages(:color? => false) allow(matcher_without_diffable).to receive(:diffable?).and_raise(NoMethodError) end shared_examples "making a copy" do |compound_method, copy_method| context "when making a copy via `#{copy_method}`" do it "uses a copy of the base matchers" do matcher_1 = include(3) matcher_2 = include(4) compound = matcher_1.__send__(compound_method, matcher_2) copy = compound.__send__(copy_method) expect(copy).not_to equal(compound) expect(copy.matcher_1).not_to equal(matcher_1) expect(copy.matcher_1).to be_a(RSpec::Matchers::BuiltIn::Include) expect(copy.matcher_1.expected).to eq([3]) expect(copy.matcher_2).not_to equal(matcher_2) expect(copy.matcher_2).to be_a(RSpec::Matchers::BuiltIn::Include) expect(copy.matcher_2.expected).to eq([4]) end it "copies custom matchers properly so they can work even though they have singleton behavior" do matcher_1 = custom_include(3) matcher_2 = custom_include(3) compound = matcher_1.__send__(compound_method, matcher_2) copy = compound.__send__(copy_method) expect(copy).not_to equal(compound) expect(copy.matcher_1).not_to equal(matcher_1) expect(copy.matcher_2).not_to equal(matcher_2) expect([3]).to copy expect { expect([4]).to copy }.to fail_including("expected [4]") end end end shared_examples "handles blocks properly" do |meth| define_method :combine do |m1, m2| m1.__send__(meth, m2) end context "when used with a block matcher" do it 'executes the block only once, regardless of how many matchers are compounded' do w, x, y, z = 0, 0, 0, 0 expect { w += 1; x += 2; y += 3; z += 4 }.to( combine( change { w }.to(1), combine( change { x }.to(2), combine( change { y }.to(3), change { z }.to(4) ) ) ) ) end context "does not work when combined with another non-block matcher" do example "with the block matcher first" do expect { x = 0 expect { x += 2 }.to combine(change { x }.to(2), be_a(Proc)) }.to fail_with(/supports_block_expectations/) end example "with the block matcher last" do expect { x = 0 expect { x += 2 }.to combine(be_a(Proc), change { x }.to(2)) }.to fail_with(/supports_block_expectations/) end end context "indicates block expectations are not supported when combined with a custom matcher that does not define `supports_block_expectations?" do let(:non_block_matcher) do Class.new do include ::RSpec::Matchers::Composable def matches?(*); true; end end.new end example "with the block matcher first" do compound = combine(change {}.to(2), non_block_matcher) expect(compound.supports_block_expectations?).to be false end example "with the block matcher last" do compound = combine(non_block_matcher, change {}.to(2)) expect(compound.supports_block_expectations?).to be false end end context "forwards on any matcher block arguments as needed (such as for `yield_with_args`)" do obj = Object.new def obj.foo(print_bar=true) yield "bar" print "printing bar" if print_bar end example "with the matcher that passes block args first" do call_count = 0 expect { |probe| call_count += 1 obj.foo(&probe) }.to combine(yield_with_args(/bar/), output("printing bar").to_stdout) expect(call_count).to eq(1) end example "with the matcher that passes block args last" do call_count = 0 expect { |probe| call_count += 1 obj.foo(&probe) }.to combine(output("printing bar").to_stdout, yield_with_args("bar")) expect(call_count).to eq(1) end it "does not support two matchers that both pass arguments to the block" do expect { expect { |probe| obj.foo(false, &probe) }.to combine(yield_with_args(/bar/), yield_with_args("bar")) }.to raise_error(/cannot be combined/) end end context "when used with `raise_error` (which cannot match against a wrapped block)" do it 'does not work when combined with `throw_symbol` (which also cannot match against a wrapped block)' do expect { expect {}.to combine(raise_error("boom"), throw_symbol(:foo)) }.to raise_error(/cannot be combined/) end it 'works when `raise_error` is first' do x = 0 expect { x += 2 raise "boom" }.to combine(raise_error("boom"), change { x }.to(2)) end it 'works when `raise_error` is last' do x = 0 expect { x += 2 raise "boom" }.to combine(change { x }.to(2), raise_error("boom")) end context "with nested compound matchers" do if meth == :or def expect_block @x = 0 expect do print "a" # for or we need `raise "boom"` and one other # to be wrong, so that only the `output("a").to_stdout` # is correct for these specs to cover the needed # behavior. @x += 3 raise "bom" end end else def expect_block @x = 0 expect do print "a" @x += 2 raise "boom" end end end it 'works when `raise_error` is first in the first compound matcher' do matcher = combine( combine(raise_error("boom"), change { @x }.to(2)), output("a").to_stdout ) expect_block.to matcher end it 'works when `raise_error` is last in the first compound matcher' do matcher = combine( combine(change { @x }.to(2), raise_error("boom")), output("a").to_stdout ) expect_block.to matcher end it 'works when `raise_error` is first in the last compound matcher' do matcher = combine( change { @x }.to(2), combine(raise_error("boom"), output("a").to_stdout) ) expect_block.to matcher end it 'works when `raise_error` is last in the last compound matcher' do matcher = combine( change { @x }.to(2), combine(output("a").to_stdout, raise_error("boom")) ) expect_block.to matcher end end end end context "when given a proc and non block matchers" do it 'does not treat it as a block expectation expression' do p = lambda {} expect(p).to combine(be_a(Proc), be(p)) expect { expect(p).to combine(be_a(Integer), eq(3)) }.to fail_including("expected: 3") end end end context "when used as a composable matcher" do it 'can pass' do expect(["food", "barn"]).to include( a_string_starting_with("f").and(ending_with("d")), a_string_starting_with("b").and(ending_with("n")) ) end it 'can fail' do expect { expect(["foo", "bar"]).to include( a_string_starting_with("f").and(ending_with("d")), a_string_starting_with("b").and(ending_with("n")) ) }.to fail_including('expected ["foo", "bar"] to include (a string starting with "f" and ending with "d") and (a string starting with "b" and ending with "n")') end it 'provides a description' do matcher = include( a_string_starting_with("f").and(ending_with("d")), a_string_starting_with("b").and(ending_with("n")) ) expect(matcher.description).to eq('include (a string starting with "f" and ending with "d") and (a string starting with "b" and ending with "n")') end end describe "expect(...).to matcher.and(other_matcher)" do it_behaves_like "an RSpec value matcher", :valid_value => 3, :invalid_value => 4, :disallows_negation => true do let(:matcher) { eq(3).and be <= 3 } end context 'when using boolean AND `&` alias' do it_behaves_like "an RSpec value matcher", :valid_value => 3, :invalid_value => 4, :disallows_negation => true do let(:matcher) { eq(3) & be_a(Integer) } end end include_examples "making a copy", :and, :dup include_examples "making a copy", :and, :clone it_behaves_like "handles blocks properly", :and context 'when both matchers pass' do it 'passes' do expect(3).to eq(3).and be >= 2 end end it 'has a description composed of both matcher descriptions' do matcher = eq(3).and be >= 2 expect(3).to matcher expect(matcher.description).to eq("eq 3 and be >= 2") end context 'when only the first matcher fails' do it "fails with the first matcher's failure message" do expect { expect(3).to eq(4).and be >= 2 }.to fail_with(dedent <<-EOS) | |expected: 4 | got: 3 | |(compared using ==) | EOS end end context 'when only the second matcher fails' do it "fails with the second matcher's failure message" do expect { expect(3).to be_kind_of(Integer).and eq(4) }.to fail_with(dedent <<-EOS) | |expected: 4 | got: 3 | |(compared using ==) | EOS end end context "when both matchers fail" do context "when both matchers have multi-line failure messages" do it 'fails with a well formatted message containing both sub-messages' do expect { expect(3).to eq(4).and be >= 8 }.to fail_with(dedent <<-EOS) | | expected: 4 | got: 3 | | (compared using ==) | |...and: | | expected: >= 8 | got: 3 EOS end end context "when both matchers have single-line failure messages" do it 'still fails with a multi-line failure message because it reads better than keeping it on a single line' do expect { expect("foo").to start_with("a").and end_with("z") }.to fail_with(dedent <<-EOS) | expected "foo" to start with "a" | |...and: | | expected "foo" to end with "z" EOS end end context "when the first matcher has a multi-line failure message" do it 'fails with a well formatted message containing both sub-messages' do expect { expect("foo").to eq(4).and end_with("z") }.to fail_with(dedent <<-EOS) | | expected: 4 | got: "foo" | | (compared using ==) | |...and: | | expected "foo" to end with "z" EOS end end context "when the second matcher has a multi-line failure message" do it 'fails with a well formatted message containing both sub-messages' do expect { expect("foo").to end_with("z").and eq(4) }.to fail_with(dedent <<-EOS) | expected "foo" to end with "z" | |...and: | | expected: 4 | got: "foo" | | (compared using ==) | EOS end end context "when the first matcher is diffable" do subject { include("foo").and be_a(String) } it 'is diffable' do expect(subject).to be_diffable end context "when only first matcher fails" do it 'fails with a message containing a diff for first matcher' do expected_failure = dedent(<<-EOS) |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bar EOS expect { expect(dedent(<<-EOS)).to subject |baz |bar EOS }.to fail_including(expected_failure) end end context "when only second matcher fails" do subject { include("baz").and be_an(Integer) } it 'fails with a message not containing a diff for first matcher' do expect { expect(dedent(<<-EOS)).to subject |baz |bar EOS }.to fail_with(a_string_excluding "Diff") end end context "when both matcher fail" do subject { include("foo").and eq(35) } it "fails with a message containing a diff with first matcher" do expected_failure = dedent(<<-EOS) | expected "baz\\nbar" to include "foo" | |...and: | | expected: 35 | got: "baz\\nbar" | | (compared using ==) | |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bar EOS expect { expect(dedent(<<-EOS)).to subject |baz |bar EOS }.to fail_including(expected_failure) end end end context "when the first matcher does not implement #diffable?" do subject { matcher_without_diffable.and exist } it 'is not diffable' do expect(subject).not_to be_diffable end end context "when the second matcher does not implement #diffable?" do subject { exist.and matcher_without_diffable } it 'is not diffable' do expect(subject).not_to be_diffable end end context "when the second matcher is diffable" do subject { eq(35).and include("foo") } it 'is diffable' do expect(subject).to be_diffable end it 'fails with a message containing a diff for second matcher' do expected_failure = dedent(<<-EOS) | expected: 35 | got: "baz\\nbar" | | (compared using ==) | |...and: | | expected "baz\\nbar" to include "foo" |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bar EOS expect { expect(dedent(<<-EOS)).to subject |baz |bar EOS }.to fail_including(expected_failure) end end context "when both matchers are diffable" do subject { include("bar").and include("foo") } it 'is diffable' do expect(subject).to be_diffable end it 'fails with a message containing diffs for both matcher' do expected_failure = dedent(<<-EOS) | expected "baz\\nbug" to include "bar" | |...and: | | expected "baz\\nbug" to include "foo" |Diff for (include "bar"): |@@ -1,2 +1,3 @@ |-bar |+baz |+bug | |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bug EOS expect { expect(dedent(<<-EOS)).to subject |baz |bug EOS }.to fail do |error| expect(error.message).to include(expected_failure) end end context 'when matcher transforms the actual' do context 'when the matcher redefines `actual`' do matcher :eq_downcase do |expected| match do |actual| @matcher_internal_actual = actual.downcase values_match? expected, @matcher_internal_actual end def actual @matcher_internal_actual end diffable end it 'shows the redefined value in diff' do expected_failure = dedent(<<-EOS) | expected "HELLO\\nWORLD" to eq downcase "bonjour\\nmonde" | |...and: | | expected "HELLO\\nWORLD" to eq downcase "hola\\nmon" |Diff for (eq downcase "bonjour\\nmonde"): |@@ -1,3 +1,3 @@ |-bonjour |-monde |+hello |+world | |Diff for (eq downcase "hola\\nmon"): |@@ -1,3 +1,3 @@ |-hola |-mon |+hello |+world EOS expect { expect( "HELLO\nWORLD" ).to eq_downcase("bonjour\nmonde").and eq_downcase("hola\nmon") }.to fail do |error| expect(error.message).to include(expected_failure) end end end context 'when the matcher reassigns `@actual`' do matcher :eq_downcase do |expected| match do |actual| @actual = actual.downcase values_match? expected, @actual end diffable end it 'shows the reassigned value in diff' do expected_failure = dedent(<<-EOS) | expected "hello\\nworld" to eq downcase "bonjour\\nmonde" | |...and: | | expected "hello\\nworld" to eq downcase "hola\\nmon" |Diff for (eq downcase "bonjour\\nmonde"): |@@ -1,3 +1,3 @@ |-bonjour |-monde |+hello |+world | |Diff for (eq downcase "hola\\nmon"): |@@ -1,3 +1,3 @@ |-hola |-mon |+hello |+world EOS expect { expect( "HELLO\nWORLD" ).to eq_downcase("bonjour\nmonde").and eq_downcase("hola\nmon") }.to fail do |error| expect(error.message).to include(expected_failure) end end end end end context "when both matchers are not diffable" do subject { be_a(String).and be_truthy } it 'is not diffable' do expect(subject).not_to be_diffable end it 'fails with a message not containing any diff' do expect { expect(35).to subject }.to fail_with(a_string_excluding "Diff") end end end end describe "expect(...).not_to matcher.and(other_matcher)" do it "is not supported" do expect { expect(3).not_to eq(2).and be > 2 }.to raise_error(NotImplementedError, /matcher.and matcher` is not supported/) end end describe "expect(...).to matcher.or(other_matcher)" do it_behaves_like "an RSpec value matcher", :valid_value => 3, :invalid_value => 5, :disallows_negation => true do let(:matcher) { eq(3).or eq(4) } end context 'when using boolean OR `|` alias' do it_behaves_like "an RSpec value matcher", :valid_value => 3, :invalid_value => 5, :disallows_negation => true do let(:matcher) { eq(3) | eq(4) } end end include_examples "making a copy", :or, :dup include_examples "making a copy", :or, :clone it_behaves_like "handles blocks properly", :or it 'has a description composed of both matcher descriptions' do matcher = eq(3).or eq(4) expect(3).to matcher expect(matcher.description).to eq("eq 3 or eq 4") end context 'when both matchers pass' do it 'passes' do expect("foo").to start_with("f").or end_with("o") end end context 'when only the first matcher passes' do it 'passes' do expect("foo").to start_with("f").or end_with("z") end end context 'when only the last matcher passes' do it 'passes' do expect("foo").to start_with("a").or end_with("o") end end context 'when both matchers fail' do context "when both matchers have multi-line failure messages" do it 'fails with a well formatted message containing both sub-messages' do expect { expect(3).to eq(4).or be >= 8 }.to fail_with(dedent <<-EOS) | | expected: 4 | got: 3 | | (compared using ==) | |...or: | | expected: >= 8 | got: 3 EOS end end context "when both matchers have single-line failure messages" do it 'still fails with a multi-line failure message because it reads better than keeping it on a single line' do expect { expect("foo").to start_with("a").or end_with("z") }.to fail_with(dedent <<-EOS) | expected "foo" to start with "a" | |...or: | | expected "foo" to end with "z" EOS end end context "when the first matcher has a multi-line failure message" do it 'fails with a well formatted message containing both sub-messages' do expect { expect("foo").to eq(4).or end_with("z") }.to fail_with(dedent <<-EOS) | | expected: 4 | got: "foo" | | (compared using ==) | |...or: | | expected "foo" to end with "z" EOS end end context "when the second matcher has a multi-line failure message" do it 'fails with a well formatted message containing both sub-messages' do expect { expect("foo").to end_with("z").or eq(4) }.to fail_with(dedent <<-EOS) | expected "foo" to end with "z" | |...or: | | expected: 4 | got: "foo" | | (compared using ==) | EOS end end end context "when first matcher is diffable" do subject { include("foo").or eq(35) } it "is diffable" do expect(subject).to be_diffable end it 'fails with a message containing diff for first matcher' do expected_failure = dedent(<<-EOS) | expected "baz\\nbug" to include "foo" | |...or: | | expected: 35 | got: "baz\\nbug" | | (compared using ==) | |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bug EOS expect { expect(dedent(<<-EOS)).to subject |baz |bug EOS }.to fail_including(expected_failure) end end context "when second matcher is diffable" do subject { eq(35).or include("foo") } it "is diffable" do expect(subject).to be_diffable end it 'fails with a message containing diff for second matcher' do expected_failure = dedent(<<-EOS) | expected: 35 | got: "baz\\nbug" | | (compared using ==) | |...or: | | expected "baz\\nbug" to include "foo" |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bug EOS expect { expect(dedent(<<-EOS)).to subject |baz |bug EOS }.to fail_including(expected_failure) end end context "when both matchers are diffable" do subject { include("foo").or include("buzz") } it "is diffable" do expect(subject).to be_diffable end it 'fails with a message containing diffs for both matcher' do expected_failure = dedent(<<-EOS) | expected "baz\\nbug" to include "foo" | |...or: | | expected "baz\\nbug" to include "buzz" |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+baz |+bug | |Diff for (include "buzz"): |@@ -1,2 +1,3 @@ |-buzz |+baz |+bug EOS expect { expect(dedent(<<-EOS)).to subject |baz |bug EOS }.to fail_including(expected_failure) end end context "when both matchers are not diffable" do subject { be_a(String).or be_an(Integer) } it "is not diffable" do expect(subject).not_to be_diffable end it 'fails with a message containing diffs for both matcher' do expect { expect(true).to subject }.to fail_with(a_string_excluding "Diff") end end end context "when chaining many matchers together" do it 'can pass appropriately' do matcher = start_with("f").and end_with("z").or end_with("o") expect("foo").to matcher expect(matcher.description).to eq('start with "f" and end with "z" or end with "o"') end it 'fails with complete diffs if its matchers are diffable' do matcher = include("bar").and include("buzz").or include("foo") expected_failure = dedent(<<-EOS) | expected "bug\\nsquash" to include "bar" | |...and: | | expected "bug\\nsquash" to include "buzz" | | ...or: | | expected "bug\\nsquash" to include "foo" |Diff for (include "bar"): |@@ -1,2 +1,3 @@ |-bar |+bug |+squash | |Diff for (include "buzz"): |@@ -1,2 +1,3 @@ |-buzz |+bug |+squash | |Diff for (include "foo"): |@@ -1,2 +1,3 @@ |-foo |+bug |+squash EOS expect { expect(dedent(<<-EOS)).to matcher |bug |squash EOS }.to fail do |error| expect(error.message).to include(expected_failure) end end it 'fails with a complete message' do expect { expect(3).to eq(1).and eq(2).and eq(3).and eq(4) }.to fail_with(dedent <<-EOS) | | expected: 1 | got: 3 | | (compared using ==) | |...and: | | expected: 2 | got: 3 | | (compared using ==) | | ...and: | | expected: 4 | got: 3 | | (compared using ==) | EOS end end describe "expect(...).not_to matcher.or(other_matcher)" do it "is not supported" do expect { expect(3).not_to eq(2).or be > 2 }.to raise_error(NotImplementedError, /matcher.or matcher` is not supported/) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/include_spec.rb0000664000000000000000000011305614557700001031053 0ustar rootroot# This class fakes some behavior of # ActiveSupport::HashWithIndifferentAccess. # It doesn't convert recursively. class FakeHashWithIndifferentAccess < Hash class << self def from_hash(hsh) new_hsh = new hsh.each do |key, value| new_hsh[key] = value end new_hsh end end def [](key) super(key.to_s) end def []=(key, value) super(key.to_s, value) end def key?(key) super(key.to_s) end def to_hash new_hsh = ::Hash.new each do |key, value| new_hsh[key] = value end new_hsh end end # Some custom hashes don't support fuzzy matching class CaseInsensitiveHash < Hash class << self def from_hash(hsh) new_hsh = new hsh.each do |key, value| new_hsh[key] = value end new_hsh end end def include?(key) super(key.downcase) end alias :key? :include? end RSpec.describe "#include matcher" do include RSpec::Support::Spec::DiffHelpers it "is diffable" do expect(include("a")).to be_diffable end shared_examples_for "a Hash target" do def build_target(hsh) hsh end def use_string_keys_in_failure_message? false end def convert_key(key) use_string_keys_in_failure_message? ? "\"#{key}\"" : ":#{key}" end it 'passes if target has the expected as a key' do expect(build_target(:key => 'value')).to include(:key) end it 'passes if target has the expected as a key fuzzily matched' do expect(build_target('KEY' => 'value')).to include(match(/key/i)) end it "fails if target does not include expected" do failure_string = %(expected {#{convert_key(:key)} => "value"} to include :other) expect { expect(build_target(:key => 'value')).to include(:other) }.to fail_matching(failure_string) end it "fails if target doesn't have a key and we expect nil" do expect { expect(build_target({})).to include(:something => nil) }.to fail_matching("expected {} to include {:something => nil}") end it 'works even when an entry in the hash overrides #send' do hash = build_target(:key => 'value') def hash.send; :sent; end expect(hash).to include(hash) end it 'provides a valid diff' do allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false) failure_string = if use_string_keys_in_failure_message? dedent(<<-END) |Diff: |@@ -1,3 +1,3 @@ |-:bar => 3, |-:foo => 1, |+"bar" => 2, |+"foo" => 1, END else diff = dedent(<<-END) |Diff: |@@ #{one_line_header(3)} @@ |-:bar => 3, |+:bar => 2, END diff << "\n :foo => 1,\n" if Diff::LCS::VERSION.to_f < 1.4 diff end expect { expect(build_target(:foo => 1, :bar => 2)).to include(:foo => 1, :bar => 3) }.to fail_including(failure_string) end it 'provides a valid diff for fuzzy matchers' do allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false) failure_string = if use_string_keys_in_failure_message? dedent(<<-END) |Diff: |@@ -1,3 +1,3 @@ |-(match /FOO/i) => 1, |-:bar => 3, |+"bar" => 2, |+"foo" => 1, END else dedent(<<-END) |Diff: |@@ -1,3 +1,3 @@ |-(match /FOO/i) => 1, |-:bar => 3, |+:bar => 2, |+:foo => 1, END end expect { expect(build_target(:foo => 1, :bar => 2)).to include(match(/FOO/i) => 1, :bar => 3) }.to fail_including(failure_string) end it 'does not support count constraint' do expect { expect(build_target(:key => 'value')).to include(:other).once }.to raise_error(NotImplementedError) end end describe "expect(...).to include(with_one_arg)" do it_behaves_like "an RSpec value matcher", :valid_value => [1, 2], :invalid_value => [1] do let(:matcher) { include(2) } end context "for an object that does not respond to `include?`" do it 'fails gracefully' do expect { expect(5).to include(1) }.to fail_matching("expected 5 to include 1, but it does not respond to `include?`") expect { expect(5).to include(1).once }.to fail_matching("expected 5 to include 1 once, but it does not respond to `include?`") end end context "for an arbitrary object that responds to `include?`" do it 'delegates to `include?`' do container = double("Container") allow(container).to receive(:include?) { |arg| arg == :stuff } expect(container).to include(:stuff) expect { expect(container).to include(:space) }.to fail_matching("to include :space") end end context "for an arbitrary object that responds to `include?` and `to_hash`" do it "delegates to `include?`" do container = double("Container", :include? => true, :to_hash => { "foo" => "bar" }) expect(container).to receive(:include?).with("foo").and_return(true) expect(container).to include("foo") end end context "for a string target" do it "passes if target includes expected" do expect("abc").to include("a") end it "fails if target does not include expected" do expect { expect("abc").to include("d") }.to fail_matching("expected \"abc\" to include \"d\"") end it "includes a diff when actual is multiline" do expect { expect("abc\ndef").to include("g") }.to fail_matching("expected \"abc\\ndef\" to include \"g\"\nDiff") end it "includes a diff when actual is multiline and there are multiple expecteds" do expect { expect("abc\ndef").to include("g", "h") }.to fail_matching("expected \"abc\\ndef\" to include \"g\" and \"h\"\nDiff") end it "does not diff when lines match but are not an exact match" do expect { expect(" foo\nbar\nbazz").to include("foo", "bar", "gaz") }.to fail_with(a_string_not_matching(/Diff/i)) end context "with exact count" do it 'fails if the block yields wrong number of times' do expect { expect('foo bar foo').to include('foo').once }.to fail_with(/expected "foo bar foo" to include "foo" once but it is included twice/) end it 'passes if the block yields the specified number of times' do expect('fooo bar').to include('oo').once expect('fooo bar').to include('o').thrice expect('fooo ooo oo bar foo').to include('oo').exactly(4).times end end context "with at_least count" do it 'passes if the search term is included at least the number of times' do expect('foo bar foo').to include('foo').at_least(2).times expect('foo bar foo foo').to include('foo').at_least(:twice) end it 'fails if the search term is included too few times' do expect { expect('foo bar foo').to include('foo').at_least(:thrice) }.to fail_with(/expected "foo bar foo" to include "foo" at least 3 times but it is included twice/) end end context "with at_most count" do it 'passes if the search term is included at most the number of times' do expect('foo bar foo').to include('foo').at_most(2).times expect('foo bar').to include('foo').at_most(:twice) end it 'fails if the search term is included too many times' do expect { expect('foo bar foo foo').to include('foo').at_most(:twice) }.to fail_with(/expected "foo bar foo foo" to include "foo" at most twice but it is included 3 times/) end end end context "for an array target" do it "passes if target includes expected" do expect([1, 2, 3]).to include(3) end it "passes if target includes expected fuzzily matched" do expect(["A", "B", "C"]).to include(match(/a/i)) end it "fails if target does not include expected" do expect { expect([1, 2, 3]).to include(4) }.to fail_matching("expected [1, 2, 3] to include 4") end it 'fails when given differing null doubles' do dbl_1 = double.as_null_object dbl_2 = double.as_null_object expect { expect([dbl_1]).to include(dbl_2) }.to fail_matching("expected [#{dbl_1.inspect}] to include") end it 'passes when given the same null double' do dbl = double.as_null_object expect([dbl]).to include(dbl) end context "with exact count" do it 'fails if the block yields wrong number of times' do expect { expect([1, 2, 1]).to include(1).once }.to fail_with('expected [1, 2, 1] to include 1 once but it is included twice') expect { expect([10, 20, 30]).to include(a_value_within(2).of(17)).twice }.to fail_with('expected [10, 20, 30] to include (a value within 2 of 17) twice but it is included 0 times') end it 'passes if the block yields the specified number of times' do expect([1, 2, 1]).to include(1).twice expect([10, 20, 30]).to include(a_value_within(5).of(17)).once expect([{ 'a' => 1 }]).to include('a' => 1).once end end context "with at_least count" do it 'passes if the search term is included at least the number of times' do expect([1, 2, 1]).to include(1).at_least(2).times expect([1, 2, 1, 1]).to include(1).at_least(:twice) end it 'fails if the search term is included too few times' do expect { expect([1, 2, 1]).to include(1).at_least(:thrice) }.to fail_with('expected [1, 2, 1] to include 1 at least 3 times but it is included twice') end end context "with at_most count" do it 'passes if the search term is included at most the number of times' do expect([1, 2, 1]).to include(1).at_most(2).times expect([1, 2]).to include(1).at_most(:twice) end it 'fails if the search term is included too many times' do expect { expect([1, 2, 1, 1]).to include(1).at_most(:twice) }.to fail_with('expected [1, 2, 1, 1] to include 1 at most twice but it is included 3 times') end end end context "for a hash target" do it_behaves_like "a Hash target" end context "for a target that subclasses Hash to treat string/symbol keys interchangeably, but returns a raw hash from #to_hash" do it_behaves_like "a Hash target" do undef :build_target # to prevent "method redefined" warning def build_target(hsh) FakeHashWithIndifferentAccess.from_hash(hsh) end undef :use_string_keys_in_failure_message? # to prevent "method redefined" warning def use_string_keys_in_failure_message? true end end end context "for a target that subclasses Hash to perform custom key checks like downcasing" do it_behaves_like "a Hash target" do undef :build_target # to prevent "method redefined" warning def build_target(hsh) CaseInsensitiveHash.from_hash(hsh) end end end context "for a target that can pass for a hash" do def build_target(hsh) PseudoHash.new(hsh) end around do |example| in_sub_process_if_possible do require 'delegate' class PseudoHash < SimpleDelegator end example.run end end it_behaves_like "a Hash target" end end describe "expect(...).to include(with, multiple, args)" do it "has a description" do matcher = include("a") expect(matcher.description).to eq("include \"a\"") end context "for a string target" do it "passes if target includes all items" do expect("a string").to include("str", "a") end it "fails if target does not include one of the items" do expect { expect("a string").to include("str", "a", "foo") }.to fail_matching('expected "a string" to include "foo"') end it "fails if target does not include two of the items" do expect { expect("a string").to include("nope", "a", "nada", "str") }.to fail_matching('expected "a string" to include "nope" and "nada"') end it "fails if target does not include many of the items" do expect { expect("a string").to include("nope", "a", "nada", "nein", "ing", "str") }.to fail_matching('expected "a string" to include "nope", "nada", and "nein"') end end context "for an array target" do it "passes if target includes all items" do expect([1, 2, 3]).to include(1, 2, 3) end it "passes if target includes all items fuzzily matched" do expect(["A", "B", "C"]).to include(match(/b/i), "A") end it "fails if target does not include one of the items" do expect { expect([1, 2, 3]).to include(1, 2, 4) }.to fail_matching("expected [1, 2, 3] to include 4") end it "fails if target does not include two of the items" do expect { expect([1, 2, 3]).to include(5, 1, 2, 4) }.to fail_matching("expected [1, 2, 3] to include 5 and 4") end it "fails if target does not include many of the items" do expect { expect([1, 2, 3]).to include(5, 1, 6, 2, 4) }.to fail_matching("expected [1, 2, 3] to include 5, 6, and 4") end it 'correctly diffs lists of hashes' do allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false) expect { expect([ { :number => 1 }, { :number => 2 }, { :number => 3 } ]).to include( { :number => 1 }, { :number => 0 }, { :number => 3 } ) }.to fail_including(dedent(<<-END)) |Diff: |@@ #{one_line_header} @@ |-[{:number=>1}, {:number=>0}, {:number=>3}] |+[{:number=>1}, {:number=>2}, {:number=>3}] END end end context "for a hash target" do it 'passes if target includes all items as keys' do expect({ :key => 'value', :other => 'value' }).to include(:key, :other) end it "passes if target includes all items as keys fuzzily matched" do expect({ "A" => "B", "C" => "D" }).to include(match(/c/i), "A") end it 'fails if target does not include one of the items as a key' do expect { expect({ :key => 'value', :this => 'that' }).to include(:key, :nope, :this) }.to fail_with(%r|expected #{hash_inspect :key => "value", :this => "that"} to include :nope|) end it "fails if target does not include two of the items as keys" do expect { expect({ :key => 'value', :this => 'that' }).to include(:nada, :key, :nope, :this) }.to fail_with(%r|expected #{hash_inspect :key => "value", :this => "that"} to include :nada and :nope|) end it "fails if target does not include many of the items as keys" do expect { expect({ :key => 'value', :this => 'that' }).to include(:nada, :key, :nope, :negative, :this) }.to fail_with(%r|expected #{hash_inspect :key => "value", :this => "that"} to include :nada, :nope, and :negative|) end end it 'does not implement count constraints' do expect { expect('').to include('foo', 'bar').once }.to raise_error(NotImplementedError) expect { expect('').to include('foo', 'bar').at_least(:twice) }.to raise_error(NotImplementedError) expect { expect('').to include('foo', 'bar').at_most(:twice) }.to raise_error(NotImplementedError) end end describe "expect(...).not_to include(expected)" do context "for an object that does not respond to `include?`" do it 'fails gracefully' do expect { expect(5).not_to include(1) }.to fail_matching("expected 5 not to include 1, but it does not respond to `include?`") end end context "for an arbitrary object that responds to `include?`" do it 'delegates to `include?`' do container = double("Container") allow(container).to receive(:include?) { |arg| arg == :stuff } expect(container).not_to include(:space) expect { expect(container).not_to include(:stuff) }.to fail_matching("not to include :stuff") end end context "for a string target" do it "passes if target does not include expected" do expect("abc").not_to include("d") end it "fails if target includes expected" do expect { expect("abc").not_to include("c") }.to fail_with("expected \"abc\" not to include \"c\"") end context "with exact count" do it 'passes if the block yields wrong number of times' do expect('foo bar foo').not_to include('foo').once end it 'fails if the block yields the specified number of times' do expect { expect('fooo bar').not_to include('oo').once }.to fail_with(/expected "fooo bar" not to include "oo" once but it is included once/) end end context "with at_least count" do it 'fails if the search term is included at least the number of times' do expect { expect('foo bar foo foo').not_to include('foo').at_least(:twice) }.to fail_with(/expected "foo bar foo foo" not to include "foo" at least twice but it is included 3 times/) end it 'passes if the search term is included too few times' do expect('foo bar foo').not_to include('foo').at_least(:thrice) end end context "with at_most count" do it 'fails if the search term is included at most the number of times' do expect { expect('foo bar').not_to include('foo').at_most(:twice) }.to fail_with(/expected "foo bar" not to include "foo" at most twice but it is included once/) end it 'passes if the search term is included too many times' do expect('foo bar foo foo').not_to include('foo').at_most(:twice) end end end context "for an array target" do it "passes if target does not include expected" do expect([1, 2, 3]).not_to include(4) end it "fails if target includes expected" do expect { expect([1, 2, 3]).not_to include(3) }.to fail_with("expected [1, 2, 3] not to include 3") end it 'passes when given differing null doubles' do expect([double.as_null_object]).not_to include(double.as_null_object) end it 'fails when given the same null double' do dbl = double.as_null_object expect { expect([dbl]).not_to include(dbl) }.to fail_matching("expected [#{dbl.inspect}] not to include") end end context "for a hash target" do it 'passes if target does not have the expected as a key' do expect({ :other => 'value' }).not_to include(:key) end it "fails if target includes expected key" do expect { expect({ :key => 'value' }).not_to include(:key) }.to fail_matching('expected {:key => "value"} not to include :key') end end end describe "expect(...).not_to include(with, multiple, args)" do context "for a string target" do it "passes if the target does not include any of the expected" do expect("abc").not_to include("d", "e", "f") end it "fails if the target includes all of the expected" do expect { expect("abc").not_to include("c", "a") }.to fail_with('expected "abc" not to include "c" and "a"') end it "fails if the target includes one (but not all) of the expected" do expect { expect("abc").not_to include("d", "a") }.to fail_with('expected "abc" not to include "a"') end it "fails if the target includes two (but not all) of the expected" do expect { expect("abc").not_to include("d", "a", "b") }.to fail_with('expected "abc" not to include "a" and "b"') end it "fails if the target includes many (but not all) of the expected" do expect { expect("abcd").not_to include("b", "d", "a", "f") }.to fail_with('expected "abcd" not to include "b", "d", and "a"') end end context "for a hash target" do it "passes if it does not include any of the expected keys" do expect({ :a => 1, :b => 2 }).not_to include(:c, :d) end it "fails if the target includes all of the expected keys" do expect { expect({ :a => 1, :b => 2 }).not_to include(:a, :b) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} not to include :a and :b|) end it "fails if the target includes one (but not all) of the expected keys" do expect { expect({ :a => 1, :b => 2 }).not_to include(:d, :b) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} not to include :b|) end it "fails if the target includes two (but not all) of the expected keys" do expect { expect({ :a => 1, :b => 2 }).not_to include(:a, :b, :c) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} not to include :a and :b|) end it "fails if the target includes many (but not all) of the expected keys" do expect { expect({ :a => 1, :b => 2, :c => 3 }).not_to include(:b, :a, :c, :f) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2, :c => 3} not to include :b, :a, and :c|) end end context "for an array target" do it "passes if the target does not include any of the expected" do expect([1, 2, 3]).not_to include(4, 5, 6) end it "fails if the target includes all of the expected" do expect { expect([1, 2, 3]).not_to include(3, 1) }.to fail_with('expected [1, 2, 3] not to include 3 and 1') end it "fails if the target includes one (but not all) of the expected" do expect { expect([1, 2, 3]).not_to include(4, 1) }.to fail_with('expected [1, 2, 3] not to include 1') end it "fails if the target includes two (but not all) of the expected" do expect { expect([1, 2, 3]).not_to include(4, 1, 2) }.to fail_with('expected [1, 2, 3] not to include 1 and 2') end it "fails if the target includes many (but not all) of the expected" do expect { expect([1, 2, 3]).not_to include(5, 4, 2, 1, 3) }.to fail_with('expected [1, 2, 3] not to include 2, 1, and 3') end end end describe "expect(...).to include(:key => value)" do context 'for a hash target' do it "passes if target includes the key/value pair" do expect({ :key => 'value' }).to include(:key => 'value') end it "passes if target includes the key/value pair among others" do expect({ :key => 'value', :other => 'different' }).to include(:key => 'value') end it "passes if target includes the key/value pair fuzzily matched among others", :if => (RUBY_VERSION.to_f > 1.8) do hsh = { :key => 'value', :other => 'different' } expect(hsh).to include(match(/KEY/i) => 'value') expect(FakeHashWithIndifferentAccess.from_hash(hsh)).to include(match(/KEY/i) => 'value') expect(CaseInsensitiveHash.from_hash(hsh)).to include(match(/KEY/i) => 'value') end it "fails if target has a different value for key" do expect { expect({ :key => 'different' }).to include(:key => 'value') }.to fail_matching('expected {:key => "different"} to include {:key => "value"}') end it "fails if target has a different key" do expect { expect({ :other => 'value' }).to include(:key => 'value') }.to fail_matching('expected {:other => "value"} to include {:key => "value"}') end end context 'for a non-hash target' do it "fails if the target does not contain the given hash" do expect { expect(['a', 'b']).to include(:key => 'value') }.to fail_matching('expected ["a", "b"] to include {:key => "value"}') end it "passes if the target contains the given hash" do expect(['a', { :key => 'value' }]).to include(:key => 'value') end end end describe "expect(...).not_to include(:key => value)" do context 'for a hash target' do it "fails if target includes the key/value pair" do expect { expect({ :key => 'value' }).not_to include(:key => 'value') }.to fail_matching('expected {:key => "value"} not to include {:key => "value"}') end it "fails if target includes the key/value pair among others" do expect { expect({ :key => 'value', :other => 'different' }).not_to include(:key => 'value') }.to fail_with(%r|expected #{hash_inspect :key => "value", :other => "different"} not to include \{:key => "value"\}|) end it "passes if target has a different value for key" do expect({ :key => 'different' }).not_to include(:key => 'value') end it "passes if target has a different key" do expect({ :other => 'value' }).not_to include(:key => 'value') end end context "for a non-hash target" do it "passes if the target does not contain the given hash" do expect(['a', 'b']).not_to include(:key => 'value') end it "fails if the target contains the given hash" do expect { expect(['a', { :key => 'value' }]).not_to include(:key => 'value') }.to fail_matching('expected ["a", {:key => "value"}] not to include {:key => "value"}') end end end describe "expect(...).to include(:key1 => value1, :key2 => value2)" do context 'for a hash target' do it "passes if target includes the key/value pairs" do expect({ :a => 1, :b => 2 }).to include(:b => 2, :a => 1) end it "passes if target includes the key/value pairs among others" do expect({ :a => 1, :c => 3, :b => 2 }).to include(:b => 2, :a => 1) end it "fails if target has a different value for one of the keys" do expect { expect({ :a => 1, :b => 2 }).to include(:a => 2, :b => 2) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} to include #{hash_inspect :a => 2}|) end it "fails if target has a different value for both of the keys" do expect { expect({ :a => 1, :b => 1 }).to include(:a => 2, :b => 2) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 1} to include #{hash_inspect :a => 2, :b => 2}|) end it "fails if target lacks one of the keys" do expect { expect({ :a => 1, :b => 1 }).to include(:a => 1, :c => 1) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 1} to include #{hash_inspect :c => 1}|) end it "fails if target lacks both of the keys" do expect { expect({ :a => 1, :b => 1 }).to include(:c => 1, :d => 1) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 1} to include #{hash_inspect :c => 1, :d => 1}|) end it "fails if target lacks one of the keys and has a different value for another" do expect { expect({ :a => 1, :b => 2 }).to include(:c => 1, :b => 3) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} to include #{hash_inspect :c => 1, :b => 3}|) end end context 'for a non-hash target' do it "fails if the target does not contain the given hash" do expect { expect(['a', 'b']).to include(:a => 1, :b => 1) }.to fail_with(%r|expected \["a", "b"\] to include #{hash_inspect :a => 1, :b => 1}|) end it "passes if the target contains the given hash" do expect(['a', { :a => 1, :b => 2 }]).to include(:a => 1, :b => 2) end end end describe "expect(...).not_to include(:key1 => value1, :key2 => value2)" do context 'for a hash target' do it "fails if target includes the key/value pairs" do expect { expect({ :a => 1, :b => 2 }).not_to include(:a => 1, :b => 2) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} not to include #{hash_inspect :a => 1, :b => 2}|) end it "fails if target includes the key/value pairs among others" do hash = { :a => 1, :b => 2, :c => 3 } expect { expect(hash).not_to include(:a => 1, :b => 2) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2, :c => 3} not to include #{hash_inspect :a => 1, :b => 2}|) end it "fails if target has a different value for one of the keys" do expect { expect({ :a => 1, :b => 2 }).not_to include(:a => 2, :b => 2) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 2} not to include #{hash_inspect :b => 2}|) end it "passes if target has a different value for both of the keys" do expect({ :a => 1, :b => 1 }).not_to include(:a => 2, :b => 2) end it "fails if target lacks one of the keys" do expect { expect({ :a => 1, :b => 1 }).not_to include(:a => 1, :c => 1) }.to fail_with(%r|expected #{hash_inspect :a => 1, :b => 1} not to include #{hash_inspect :a => 1}|) end it "passes if target lacks both of the keys" do expect({ :a => 1, :b => 1 }).not_to include(:c => 1, :d => 1) end end context 'for a non-hash target' do it "passes if the target does not contain the given hash" do expect(['a', 'b']).not_to include(:a => 1, :b => 1) end it "fails if the target contains the given hash" do expect { expect(['a', { :a => 1, :b => 2 }]).not_to include(:a => 1, :b => 2) }.to fail_with(%r|expected \["a", #{hash_inspect :a => 1, :b => 2}\] not to include #{hash_inspect :a => 1, :b => 2}|) end end end describe "Composing matchers with `include`" do RSpec::Matchers.define :a_string_containing do |expected| match do |actual| actual.include?(expected) end description do "a string containing '#{expected}'" end end describe "expect(array).to include(matcher)" do it "passes when the matcher matches one of the values" do expect([10, 20, 30]).to include( a_value_within(5).of(24) ) end it 'provides a description' do description = include( a_value_within(5).of(24) ).description expect(description).to eq("include (a value within 5 of 24)") end it 'fails with a clear message when the matcher matches none of the values' do expect { expect([10, 30]).to include( a_value_within(5).of(24) ) }.to fail_with("expected [10, 30] to include (a value within 5 of 24)") end it 'works with comparison matchers' do expect { expect([100, 200]).to include(a_value < 90) }.to fail_with("expected [100, 200] to include (a value < 90)") expect([100, 200]).to include(a_value > 150) end it 'does not treat an object that only implements #matches? as a matcher' do not_a_matcher = Struct.new(:value) do def matches?(_) fail "`matches?` should never be called" end end expect([not_a_matcher.new("rspec.info")]).to include(not_a_matcher.new("rspec.info")) expect { expect([not_a_matcher.new("rspec.info")]).to include(not_a_matcher.new("foo.com")) }.to fail_matching("expected [#{not_a_matcher.new("rspec.info").inspect}] to include") end end describe "expect(array).to include(multiple, matcher, arguments)" do it "passes if target includes items satisfying all matchers" do expect(['foo', 'bar', 'baz']).to include(a_string_containing("ar"), a_string_containing('oo')) end it "fails if target does not include an item satisfying any one of the items" do expect { expect(['foo', 'bar', 'baz']).to include(a_string_containing("ar"), a_string_containing("abc")) }.to fail_matching("expected #{['foo', 'bar', 'baz'].inspect} to include (a string containing 'abc')") end end describe "expect(hash).to include(key => matcher)" do it "passes when the matcher matches" do expect(:a => 12).to include(:a => a_value_within(3).of(10)) end it 'provides a description' do description = include(:a => a_value_within(3).of(10)).description expect(description).to eq("include {:a => (a value within 3 of 10)}") end it "fails with a clear message when the matcher does not match" do expect { expect(:a => 15).to include(:a => a_value_within(3).of(10)) }.to fail_matching("expected {:a => 15} to include {:a => (a value within 3 of 10)}") end end describe "expect(hash).to include(key_matcher)" do it "passes when the matcher matches a key", :if => (RUBY_VERSION.to_f > 1.8) do expect(:drink => "water", :food => "bread").to include(match(/foo/)) end it 'provides a description' do description = include(match(/foo/)).description expect(description).to eq("include (match /foo/)") end it 'fails with a clear message when the matcher does not match', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/)) }.to fail_matching('expected {:drink => "water", :food => "bread"} to include (match /bar/)') end end describe "expect(hash).to include(key_matcher => value)" do it "passes when the matcher matches a pair", :if => (RUBY_VERSION.to_f > 1.8) do expect(:drink => "water", :food => "bread").to include(match(/foo/) => "bread") end it "passes when the matcher matches all pairs", :if => (RUBY_VERSION.to_f > 1.8) do expect(:drink => "water", :food => "bread").to include(match(/foo/) => "bread", match(/ink/) => "water") end it "passes with a natural matcher", :if => (RUBY_VERSION.to_f > 1.8) do expect(:drink => "water", :food => "bread").to include(/foo/ => "bread") end it "passes with a natural matcher", :if => (RUBY_VERSION.to_f > 1.8) do expect(:drink => "water", :food => "bread").to include(/foo/ => /read/) end it 'provides a description' do description = include(match(/foo/) => "bread").description expect(description).to eq('include {(match /foo/) => "bread"}') end it 'fails with a clear message when the value does not match', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect(:drink => "water", :food => "bread").to include(match(/foo/) => "meat") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /foo/) => "meat"}') end it 'fails with a clear message when the matcher does not match', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/) => "bread") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /bar/) => "bread"}') end it 'fails with a clear message when several matchers do not match', :if => (RUBY_VERSION.to_f > 1.8) do expect { expect(:drink => "water", :food => "bread").to include(match(/bar/) => "bread", match(/baz/) => "water") }.to fail_matching('expected {:drink => "water", :food => "bread"} to include {(match /bar/) => "bread", (match /baz/) => "water"}') end end describe "expect(array).not_to include(multiple, matcher, arguments)" do it "passes if none of the target values satisfies any of the matchers" do expect(['foo', 'bar', 'baz']).not_to include(a_string_containing("gh"), a_string_containing('de')) end it 'fails if all of the matchers are satisfied by one of the target values' do expect { expect(['foo', 'bar', 'baz']).not_to include(a_string_containing("ar"), a_string_containing('az')) }.to fail_matching("expected #{['foo', 'bar', 'baz'].inspect} not to include (a string containing 'ar') and (a string containing 'az')") end it 'fails if the some (but not all) of the matchers are satisfied' do expect { expect(['foo', 'bar', 'baz']).not_to include(a_string_containing("ar"), a_string_containing('bz')) }.to fail_matching("expected #{['foo', 'bar', 'baz'].inspect} not to include (a string containing 'ar')") end end end # `fail_including` uses the `include` matcher internally, and using a matcher # to test itself is potentially problematic, so just for this spec file we # use `fail_matching` instead, which converts to a regex instead. def fail_matching(message) raise_error(RSpec::Expectations::ExpectationNotMetError, /#{Regexp.escape(message)}/) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/change_spec.rb0000664000000000000000000010702214557700001030651 0ustar rootrootclass SomethingExpected attr_accessor :some_value end value_pattern = /(?:result|`.+?`)/ RSpec.describe "expect { ... }.to change ..." do context "with a numeric value" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when actual is modified by the block" do expect { @instance.some_value = 6.0 }.to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail_with("expected `SomethingExpected#some_value` to have changed, but is still 5") end it "provides a #description" do expect(change(@instance, :some_value).description).to eq "change `SomethingExpected#some_value`" end end it "can specify the change of a variable's class" do val = nil expect { val = "string" }.to change { val.class }.from(NilClass).to(String) expect { expect { val = :symbol }.to change { val.class }.from(String).to(NilClass) }.to fail_with(/but is now Symbol/) end context "with boolean values" do before(:example) do @instance = SomethingExpected.new @instance.some_value = true end it "passes when actual is modified by the block" do expect { @instance.some_value = false }.to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail_with("expected `SomethingExpected#some_value` to have changed, but is still true") end end context "with set values" do it "passes when it should" do in_sub_process_if_possible do require 'set' set = Set.new([1]) expect { set << 2 }.to change { set }.from([1].to_set).to([2, 1].to_set) end end it "fails when it should" do in_sub_process_if_possible do require 'set' expect { set = Set.new([1]) expect { set << 2 }.to change { set }.from([1].to_set).to([2, 1, 3].to_set) }.to fail_with(/expected #{value_pattern} to have changed to #{Regexp.escape([2, 1, 3].to_set.inspect)}, but is now #{Regexp.escape([1, 2].to_set.inspect)}/) end end end context "with an IO stream" do it "fails when the stream does not change" do expect { k = STDOUT expect {}.to change { k } }.to fail_with(/expected #{value_pattern} to have changed/) end end it 'correctly detects a change that both mutates and replaces an object' do obj = Struct.new(:x).new([]) expect { obj.x << 1 # mutate it obj.x = [1] # replace it }.to change { obj.x } end it 'does not detect changes in an object that updates its hash upon comparison' do obj = Class.new do def ==(another) @hash = rand # (^ '=')^ # object_id == another.object_id end def hash @hash ||= super end end.new expect {}.not_to change { obj } end context "with nil value" do before(:example) do @instance = SomethingExpected.new @instance.some_value = nil end it "passes when actual is modified by the block" do expect { @instance.some_value = false }.to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail_with("expected `SomethingExpected#some_value` to have changed, but is still nil") end end context "with a deeply nested object graph" do it "passes when a leaf is changed" do data = [{ :a => [1, 2] }] expect { data[0][:a] << 3 }.to change { data } end it 'fails when no part of it is changed' do data = [{ :a => [1, 2] }] failure_msg = /expected #{value_pattern} to have changed, but is still #{regexp_inspect data}/ expect { expect { data.to_s }.to change { data } }.to fail_with(failure_msg) end it "passes when correctly specifying the exact mutation of a leaf" do data = [{ :a => [1, 2] }] expect { data[0][:a] << 3 }.to change { data }. from([{ :a => [1, 2] }]). to([{ :a => [1, 2, 3] }]) end it "fails when wrongly specifying the `from` value" do data = [{ :a => [1, 2] }] expected_initial = [{ :a => [1] }] failure_msg = /expected #{value_pattern} to have initially been #{regexp_inspect expected_initial}, but was #{regexp_inspect data}/ expect { expect { data[0][:a] << 3 }.to change { data }. from(expected_initial). to([{ :a => [1, 2, 3] }]) }.to fail_with(failure_msg) end it "fails when wrongly specifying the `to` value" do data = [{ :a => [1, 2] }] expected_final = [{ :a => [1] }] failure_msg = /expected #{value_pattern} to have changed to #{regexp_inspect expected_final}, but is now #{regexp_inspect [{ :a => [1, 2, 3] }]}/ expect { expect { data[0][:a] << 3 }.to change { data }. from([{ :a => [1, 2] }]). to(expected_final) }.to fail_with(failure_msg) end def regexp_inspect(object) Regexp.escape(object.inspect) end end context "with an array" do before(:example) do @instance = SomethingExpected.new @instance.some_value = [] end it "passes when actual is modified by the block" do expect { @instance.some_value << 1 }.to change(@instance, :some_value) end it "fails when a predicate on the actual fails" do expect do expect { @instance.some_value << 1 }.to change { @instance.some_value }.to be_empty end.to fail_with(/#{value_pattern} to have changed to/) end it "passes when a predicate on the actual passes" do @instance.some_value = [1] expect { @instance.some_value.pop }.to change { @instance.some_value }.to be_empty end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail_with("expected `SomethingExpected#some_value` to have changed, but is still []") end end context "with a hash" do before(:example) do @instance = SomethingExpected.new @instance.some_value = { :a => 'a' } end it "passes when actual is modified by the block" do expect { @instance.some_value[:a] = 'A' }.to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail end end context "with a string" do it "passes when actual is modified by the block" do string = "ab".dup expect { string << "c" }.to change { string } end it 'fails when actual is not modified by the block' do string = "ab" expect { expect {}.to change { string } }.to fail_with(/to have changed/) end end context "with an arbitrary enumerable" do before(:example) do @instance = SomethingExpected.new # rubocop:disable Layout/EmptyLinesAroundArguments This is a RuboCop bug, and it's fixed in 0.65.0 @instance.some_value = Class.new do include Enumerable attr_reader :elements def initialize(*elements) @elements = elements.dup end def <<(element) elements << element end def dup self.class.new(*elements) end def ==(other) elements == other.elements end def hash elements.hash end end.new # rubocop:enable Layout/EmptyLinesAroundArguments end it "passes when actual is modified by the block" do expect { @instance.some_value << 1 }.to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect {}.to change(@instance, :some_value) end.to fail_with(/^expected `SomethingExpected#some_value` to have changed, but is still/) end end end RSpec.describe "expect { ... }.to change(actual, message)" do it 'provides a #description with `SomeClass#some_message` notation' do expect(change('instance', :some_value).description).to eq 'change `String#some_value`' end context "when the receiver is an instance of anonymous class" do let(:klass) do Class.new(SomethingExpected) end it "can handle it" do expect(change(klass.new, :some_value).description).to match(/change `##some_value`/) end end context 'when the receiver is an object that does not respond to #class such as BasicObject' do let(:basic_object) do basic_object_class.new end let(:basic_object_class) do defined?(BasicObject) ? BasicObject : fake_basic_object_class end let(:fake_basic_object_class) do Class.new do def self.to_s 'BasicObject' end undef class, inspect, respond_to? end end it 'can properly extract the class name' do expect(change(basic_object, :__id__).description).to eq 'change `BasicObject#__id__`' end end context "when the receiver is a Module" do it "provides a #description with `SomeModule.some_message` notation" do expect(change(SomethingExpected, :some_value).description).to match(/change `SomethingExpected.some_value`/) end end context "with a missing message" do it "fails with an ArgumentError" do expect do expect {}.to change(:receiver) end.to raise_error(ArgumentError, /^`change` requires either an object and message/) end end end RSpec.describe "expect { ... }.not_to change(actual, message)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when actual is not modified by the block" do expect {}.not_to change(@instance, :some_value) end it "fails when actual is not modified by the block" do expect do expect { @instance.some_value = 6 }.not_to change(@instance, :some_value) end.to fail_with("expected `SomethingExpected#some_value` not to have changed, but did change from 5 to 6") end end RSpec.describe "expect { ... }.to change { block }" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when actual is modified by the block" do expect { @instance.some_value = 6 }.to change { @instance.some_value } end it "fails when actual is not modified by the block" do expect do expect {}.to change { @instance.some_value } end.to fail_with(/expected #{value_pattern} to have changed, but is still 5/) end it "warns if passed a block using do/end instead of {}" do expect do expect {}.to change do; end end.to raise_error(SyntaxError, /Block not received by the `change` matcher/) end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do context 'when the block body fits into a single line' do it "provides a #description with the block snippet" do expect(change { @instance.some_value }.description).to eq "change `@instance.some_value`" end end context 'when the block body spans multiple lines' do before do def @instance.reload end end let(:matcher) do change { @instance.reload @instance.some_value } end it "provides a #description with the block snippet" do expect(matcher.description).to eq "change result" end end context 'when used with an alias name' do alias_matcher :modify, :change it 'can extract the block snippet' do expect(modify { @instance.some_value }.description).to eq "modify `@instance.some_value`" end end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description without the block snippet" do expect(change { @instance.some_value }.description).to eq "change result" end end end RSpec.describe "expect { ... }.not_to change { block }" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when actual is modified by the block" do expect {}.not_to change { @instance.some_value } end it "fails when actual is not modified by the block" do expect do expect { @instance.some_value = 6 }.not_to change { @instance.some_value } end.to fail_with(/expected #{value_pattern} not to have changed, but did change from 5 to 6/) end it "warns if passed a block using do/end instead of {}" do expect do expect {}.not_to change do; end end.to raise_error(SyntaxError, /Block not received by the `change` matcher/) end context "with an IO stream" do it "passes when the stream does not change" do k = STDOUT expect {}.not_to change { k } end end context "with a deeply nested object graph" do it "passes when the object is changed" do data = [{ :a => [1, 2] }] expect { data.to_s }.not_to change { data } end it 'fails when part of it is changed' do data = [{ :a => [1, 2] }] failure_msg = /expected #{value_pattern} not to have changed, but did change from #{regexp_inspect data} to #{regexp_inspect [{ :a=>[1, 2, 3] }]}/ expect { expect { data[0][:a] << 3 }.not_to change { data } }.to fail_with(failure_msg) end it "passes when correctly specifying the exact mutation of a leaf" do data = [{ :a => [1, 2] }] expect { data[0][:a] << 3 }.to change { data }. from([{ :a => [1, 2] }]). to([{ :a => [1, 2, 3] }]) end def regexp_inspect(object) Regexp.escape(object.inspect) end end end RSpec.describe "expect { ... }.not_to change { }.from" do context 'when the value starts at the from value' do it 'passes when the value does not change' do k = 5 expect {}.not_to change { k }.from(5) end it 'fails when the value does change' do expect { k = 5 expect { k += 1 }.not_to change { k }.from(5) }.to fail_with(/but did change from 5 to 6/) end end context 'when the value starts at a different value' do it 'fails when the value does not change' do expect { k = 6 expect {}.not_to change { k }.from(5) }.to fail_with(/expected #{value_pattern} to have initially been 5/) end it 'fails when the value does change' do expect { k = 6 expect { k += 1 }.not_to change { k }.from(5) }.to fail_with(/expected #{value_pattern} to have initially been 5/) end end end RSpec.describe "expect { ... }.not_to change { }.to" do it 'is not supported' do expect { expect {}.not_to change {}.to(3) }.to raise_error(NotImplementedError) end it 'is not supported when it comes after `from`' do expect { expect {}.not_to change {}.from(nil).to(3) }.to raise_error(NotImplementedError) end end RSpec.describe "expect { ... }.not_to change { }.by" do it 'is not supported' do expect { expect {}.not_to change {}.by(3) }.to raise_error(NotImplementedError) end end RSpec.describe "expect { ... }.not_to change { }.by_at_least" do it 'is not supported' do expect { expect {}.not_to change {}.by_at_least(3) }.to raise_error(NotImplementedError) end end RSpec.describe "expect { ... }.not_to change { }.by_at_most" do it 'is not supported' do expect { expect {}.not_to change {}.by_at_most(3) }.to raise_error(NotImplementedError) end end RSpec.describe "expect { ... }.to change(actual, message).by(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by expected amount" do expect { @instance.some_value += 1 }.to change(@instance, :some_value).by(1) end it "passes when attribute is not changed and expected amount is 0" do expect { @instance.some_value += 0 }.to change(@instance, :some_value).by(0) end it "fails when the attribute is changed by unexpected amount" do expect do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by(1) end.to fail_with("expected `SomethingExpected#some_value` to have changed by 1, but was changed by 2") end it "fails when the attribute is changed by unexpected amount in the opposite direction" do expect do expect { @instance.some_value -= 1 }.to change(@instance, :some_value).by(1) end.to fail_with("expected `SomethingExpected#some_value` to have changed by 1, but was changed by -1") end it "provides a #description" do expect(change(@instance, :some_value).by(3).description).to eq "change `SomethingExpected#some_value` by 3" end end RSpec.describe "expect { ... }.to change { block }.by(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by expected amount" do expect { @instance.some_value += 1 }.to change { @instance.some_value }.by(1) end it "fails when the attribute is changed by unexpected amount" do expect do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by(1) end.to fail_with(/expected #{value_pattern} to have changed by 1, but was changed by 2/) end it "fails when the attribute is changed by unexpected amount in the opposite direction" do expect do expect { @instance.some_value -= 1 }.to change { @instance.some_value }.by(1) end.to fail_with(/expected #{value_pattern} to have changed by 1, but was changed by -1/) end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description with the block snippet" do expect(change { @instance.some_value }.by(3).description).to eq "change `@instance.some_value` by 3" end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description without the block snippet" do expect(change { @instance.some_value }.by(3).description).to eq "change result by 3" end end end RSpec.describe "expect { ... }.to change(actual, message).by_at_least(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by greater than the expected amount" do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_least(1) end it "passes when attribute is changed by the expected amount" do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_least(2) end it "fails when the attribute is changed by less than the expected amount" do expect do expect { @instance.some_value += 1 }.to change(@instance, :some_value).by_at_least(2) end.to fail_with("expected `SomethingExpected#some_value` to have changed by at least 2, but was changed by 1") end it "provides a #description" do expect(change(@instance, :some_value).by_at_least(3).description).to eq "change `SomethingExpected#some_value` by at least 3" end end RSpec.describe "expect { ... }.to change { block }.by_at_least(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by greater than expected amount" do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by_at_least(1) end it "passes when attribute is changed by the expected amount" do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by_at_least(2) end it "fails when the attribute is changed by less than the unexpected amount" do expect do expect { @instance.some_value += 1 }.to change { @instance.some_value }.by_at_least(2) end.to fail_with(/expected #{value_pattern} to have changed by at least 2, but was changed by 1/) end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description with the block snippet" do expect(change { @instance.some_value }.by_at_least(3).description).to eq "change `@instance.some_value` by at least 3" end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description without the block snippet" do expect(change { @instance.some_value }.by_at_least(3).description).to eq "change result by at least 3" end end end RSpec.describe "expect { ... }.to change(actual, message).by_at_most(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by less than the expected amount" do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_most(3) end it "passes when attribute is changed by the expected amount" do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_most(2) end it "fails when the attribute is changed by greater than the expected amount" do expect do expect { @instance.some_value += 2 }.to change(@instance, :some_value).by_at_most(1) end.to fail_with("expected `SomethingExpected#some_value` to have changed by at most 1, but was changed by 2") end it "provides a #description" do expect(change(@instance, :some_value).by_at_most(3).description).to eq "change `SomethingExpected#some_value` by at most 3" end end RSpec.describe "expect { ... }.to change { block }.by_at_most(expected)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 5 end it "passes when attribute is changed by less than expected amount" do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by_at_most(3) end it "passes when attribute is changed by the expected amount" do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by_at_most(2) end it "fails when the attribute is changed by greater than the unexpected amount" do expect do expect { @instance.some_value += 2 }.to change { @instance.some_value }.by_at_most(1) end.to fail_with(/expected #{value_pattern} to have changed by at most 1, but was changed by 2/) end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description with the block snippet" do expect(change { @instance.some_value }.by_at_most(3).description).to eq "change `@instance.some_value` by at most 3" end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description without the block snippet" do expect(change { @instance.some_value }.by_at_most(3).description).to eq "change result by at most 3" end end end RSpec.describe "expect { ... }.to change(actual, message).from(old)" do context "with boolean values" do before(:example) do @instance = SomethingExpected.new @instance.some_value = true end it "passes when attribute is == to expected value before executing block" do expect { @instance.some_value = false }.to change(@instance, :some_value).from(true) end it "fails when attribute is not == to expected value before executing block" do expect do expect { @instance.some_value = 'foo' }.to change(@instance, :some_value).from(false) end.to fail_with("expected `SomethingExpected#some_value` to have initially been false, but was true") end end context "with non-boolean values" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end it "passes when attribute matches expected value before executing block" do expect { @instance.some_value = "astring" }.to change(@instance, :some_value).from("string") end it "fails when attribute does not match expected value before executing block" do expect do expect { @instance.some_value = "knot" }.to change(@instance, :some_value).from("cat") end.to fail_with("expected `SomethingExpected#some_value` to have initially been \"cat\", but was \"string\"") end it "provides a #description" do expect(change(@instance, :some_value).from(3).description).to eq "change `SomethingExpected#some_value` from 3" end end end RSpec.describe "expect { ... }.to change { block }.from(old)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end it "passes when attribute matches expected value before executing block" do expect { @instance.some_value = "astring" }.to change { @instance.some_value }.from("string") end it "fails when attribute does not match expected value before executing block" do expect do expect { @instance.some_value = "knot" }.to change { @instance.some_value }.from("cat") end.to fail_with(/expected #{value_pattern} to have initially been "cat", but was "string"/) end it "fails when attribute does not change" do expect do expect {}.to change { @instance.some_value }.from("string") end.to fail_with(/expected #{value_pattern} to have changed from "string", but did not change/) end context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description with the block snippet" do expect(change { @instance.some_value }.from(3).description).to eq "change `@instance.some_value` from 3" end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "provides a #description without the block snippet" do expect(change { @instance.some_value }.from(3).description).to eq "change result from 3" end end it "provides a #description" do expect(change {}.from(3).description).to eq "change result from 3" end end RSpec.describe "expect { ... }.to change(actual, message).to(new)" do context "with boolean values" do before(:example) do @instance = SomethingExpected.new @instance.some_value = true end it "passes when attribute is == to expected value after executing block" do expect { @instance.some_value = false }.to change(@instance, :some_value).to(false) end it "fails when attribute is not == to expected value after executing block" do expect do expect { @instance.some_value = 1 }.to change(@instance, :some_value).from(true).to(false) end.to fail_with("expected `SomethingExpected#some_value` to have changed to false, but is now 1") end end context "with non-boolean values" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end it "passes when attribute matches expected value after executing block" do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("cat") end it "fails when attribute does not match expected value after executing block" do expect do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog") end.to fail_with("expected `SomethingExpected#some_value` to have changed to \"dog\", but is now \"cat\"") end it "fails with a clear message when it ends with the right value but did not change" do expect { expect {}.to change(@instance, :some_value).to("string") }.to fail_with('expected `SomethingExpected#some_value` to have changed to "string", but did not change') end end end RSpec.describe "expect { ... }.to change { block }.to(new)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end it "passes when attribute matches expected value after executing block" do expect { @instance.some_value = "cat" }.to change { @instance.some_value }.to("cat") end it "fails when attribute does not match expected value after executing block" do expect do expect { @instance.some_value = "cat" }.to change { @instance.some_value }.from("string").to("dog") end.to fail_with(/expected #{value_pattern} to have changed to "dog", but is now "cat"/) end it "provides a #description" do expect(change {}.to(3).description).to eq "change result to 3" end end RSpec.describe "expect { ... }.to change(actual, message).from(old).to(new)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end it "passes when #to comes before #from" do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("cat").from("string") end it "passes when #from comes before #to" do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("cat") end it "shows the correct messaging when #after and #to are different" do expect do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog") end.to fail_with("expected `SomethingExpected#some_value` to have changed to \"dog\", but is now \"cat\"") end it "shows the correct messaging when #before and #from are different" do expect do expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("not_string").to("cat") end.to fail_with("expected `SomethingExpected#some_value` to have initially been \"not_string\", but was \"string\"") end end RSpec.describe "expect { ... }.to change { block }.from(old).to(new)" do before(:example) do @instance = SomethingExpected.new @instance.some_value = 'string' end context "when #to comes before #from" do it "passes" do expect { @instance.some_value = "cat" }.to change { @instance.some_value }.to("cat").from("string") end it "provides a #description" do expect(change {}.to(1).from(3).description).to eq "change result to 1 from 3" end end context "when #from comes before #to" do it "passes" do expect { @instance.some_value = "cat" }.to change { @instance.some_value }.from("string").to("cat") end it "provides a #description" do expect(change {}.from(1).to(3).description).to eq "change result from 1 to 3" end end end RSpec.describe "Composing a matcher with `change`" do describe "expect { ... }.to change { ... }" do context ".from(matcher).to(matcher)" do it 'passes when the matchers match the from and to values' do k = 0.51 expect { k += 1 }.to change { k }. from( a_value_within(0.1).of(0.5) ). to( a_value_within(0.1).of(1.5) ) end it 'fails with a clear message when the `from` does not match' do expect { k = 0.51 expect { k += 1 }.to change { k }. from( a_value_within(0.1).of(0.7) ). to( a_value_within(0.1).of(1.5) ) }.to fail_with(/expected #{value_pattern} to have initially been a value within 0.1 of 0.7, but was 0.51/) end it 'fails with a clear message when the `to` does not match' do expect { k = 0.51 expect { k += 1 }.to change { k }. from( a_value_within(0.1).of(0.5) ). to( a_value_within(0.1).of(2.5) ) }.to fail_with(/expected #{value_pattern} to have changed to a value within 0.1 of 2.5, but is now 1.51/) end it 'provides a description' do expect(change(nil, :foo). from( a_value_within(0.1).of(0.5) ). to( a_value_within(0.1).of(1.5) ).description ).to eq("change `NilClass#foo` from a value within 0.1 of 0.5 to a value within 0.1 of 1.5") end end context ".to(matcher).from(matcher)" do it 'passes when the matchers match the from and to values' do k = 0.51 expect { k += 1 }.to change { k }. to( a_value_within(0.1).of(1.5) ). from( a_value_within(0.1).of(0.5) ) end it 'fails with a clear message when the `from` does not match' do expect { k = 0.51 expect { k += 1 }.to change { k }. to( a_value_within(0.1).of(1.5) ). from( a_value_within(0.1).of(0.7) ) }.to fail_with(/expected #{value_pattern} to have initially been a value within 0.1 of 0.7, but was 0.51/) end it 'fails with a clear message when the `to` does not match' do expect { k = 0.51 expect { k += 1 }.to change { k }. to( a_value_within(0.1).of(2.5) ). from( a_value_within(0.1).of(0.5) ) }.to fail_with(/expected #{value_pattern} to have changed to a value within 0.1 of 2.5, but is now 1.51/) end it 'provides a description' do expect(change(nil, :foo). to( a_value_within(0.1).of(0.5) ). from( a_value_within(0.1).of(1.5) ).description ).to eq("change `NilClass#foo` to a value within 0.1 of 0.5 from a value within 0.1 of 1.5") end end context ".by(matcher)" do it "passes when the matcher matches" do k = 0.5 expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1) ) end it 'fails with a clear message when the `by` does not match' do expect { k = 0.5 expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(0.5) ) }.to fail_with(/expected #{value_pattern} to have changed by a value within 0.1 of 0.5, but was changed by 1.05/) end it 'provides a description' do expect(change(nil, :foo). by( a_value_within(0.1).of(0.5) ).description ).to eq("change `NilClass#foo` by a value within 0.1 of 0.5") end end end describe "expect { ... }.not_to change { ... }.from(matcher).to(matcher)" do it 'passes when the matcher matches the `from` value and it does not change' do k = 0.51 expect {}.not_to change { k }.from( a_value_within(0.1).of(0.5) ) end it 'fails with a clear message when the `from` matcher does not match' do expect { k = 0.51 expect {}.not_to change { k }.from( a_value_within(0.1).of(1.5) ) }.to fail_with(/expected #{value_pattern} to have initially been a value within 0.1 of 1.5, but was 0.51/) end end end RSpec.describe RSpec::Matchers::BuiltIn::Change do it "works when the receiver has implemented #send" do @instance = SomethingExpected.new @instance.some_value = "string" def @instance.send(*_args); raise "DOH! Library developers shouldn't use #send!" end expect { expect { @instance.some_value = "cat" }.to change(@instance, :some_value) }.not_to raise_error end it_behaves_like "an RSpec block-only matcher" do let(:matcher) { change { @k } } before { @k = 1 } def valid_block @k += 1 end def invalid_block end end end RSpec.describe RSpec::Matchers::BuiltIn::ChangeRelatively do it_behaves_like "an RSpec block-only matcher", :disallows_negation => true, :skip_deprecation_check => true do let(:matcher) { change { @k }.by(1) } before { @k = 0 } def valid_block @k += 1 end def invalid_block @k += 2 end end end RSpec.describe RSpec::Matchers::BuiltIn::ChangeFromValue do it_behaves_like "an RSpec block-only matcher" do let(:matcher) { change { @k }.from(0) } before { @k = 0 } def valid_block @k += 1 end def invalid_block end end end RSpec.describe RSpec::Matchers::BuiltIn::ChangeToValue do it_behaves_like "an RSpec block-only matcher", :disallows_negation => true do let(:matcher) { change { @k }.to(2) } before { @k = 0 } def valid_block @k = 2 end def invalid_block @k = 3 end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/satisfy_spec.rb0000664000000000000000000000734114557700001031111 0ustar rootrootRSpec.describe "expect(...).to satisfy { block }" do it_behaves_like "an RSpec value matcher", :valid_value => true, :invalid_value => false do let(:matcher) { satisfy { |v| v } } end it "describes itself" do expect(satisfy.description).to eq("satisfy block") end it "passes if block returns true" do expect(true).to satisfy { |val| val } expect(true).to satisfy do |val| val end end context "when no custom description is provided" do context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "fails with block snippet if block returns false" do expect { expect(false).to satisfy { |val| val } }.to fail_with("expected false to satisfy expression `val`") expect do expect(false).to satisfy do |val| val end end.to fail_with("expected false to satisfy expression `val`") end context 'when used with an alias name' do alias_matcher :fulfill, :satisfy it 'can extract the block snippet' do expect { expect(false).to fulfill { |val| val } }.to fail_with("expected false to fulfill expression `val`") end end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "fails without block snippet if block returns false" do expect { expect(false).to satisfy { |val| val } }.to fail_with("expected false to satisfy block") expect do expect(false).to satisfy do |val| val end end.to fail_with("expected false to satisfy block") end end end context "when a custom description is provided" do it "describes itself" do expect(satisfy("be awesome").description).to eq("be awesome") end it "passes if block returns true" do expect(true).to satisfy("be true") { |val| val } expect(true).to satisfy("be true") do |val| val end end it "fails with the custom description if block returns false" do expect { expect(false).to satisfy("be true") { |val| val } }.to fail_with("expected false to be true") expect do expect(false).to satisfy("be true") do |val| val end end.to fail_with("expected false to be true") end end end RSpec.describe "expect(...).not_to satisfy { block }" do it "passes if block returns false" do expect(false).not_to satisfy { |val| val } expect(false).not_to satisfy do |val| val end end context "when no custom description is provided" do context 'in Ripper supported environment', :if => RSpec::Support::RubyFeatures.ripper_supported? do it "fails with block snippet if block returns true" do expect { expect(true).not_to satisfy { |val| val } }.to fail_with("expected true not to satisfy expression `val`") end end context 'in Ripper unsupported environment', :unless => RSpec::Support::RubyFeatures.ripper_supported? do it "fails without block snippet if block returns true" do expect { expect(true).not_to satisfy { |val| val } }.to fail_with("expected true not to satisfy block") end end end context "when a custom description is provided" do it "passes if block returns false" do expect(false).not_to satisfy("be true") { |val| val } expect(false).not_to satisfy("be true") do |val| val end end it "fails with the custom description if block returns true" do expect { expect(true).not_to satisfy("be true") { |val| val } }.to fail_with("expected true not to be true") end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/exist_spec.rb0000664000000000000000000001062314557700001030560 0ustar rootrootRSpec.describe "exist matcher" do it_behaves_like "an RSpec value matcher", :valid_value => Class.new { def exist?; true; end }.new, :invalid_value => Class.new { def exist?; false; end }.new do let(:matcher) { exist } end context "when the object does not respond to #exist? or #exists?" do subject { double } [:to, :not_to].each do |expect_method| describe "expect(...).#{expect_method} exist" do it "fails" do expect { expect(subject).send(expect_method, exist) }.to fail_including("it does not respond to either `exist?` or `exists?`") end end end end it 'composes gracefully' do expect([ double, double(:exists? => false), double(:exists? => true), ]).to include existing end [:exist?, :exists?].each do |predicate| context "when the object responds to ##{predicate}" do describe "expect(...).to exist" do it "passes if #{predicate}" do expect(double(predicate => true)).to exist end it "fails if not #{predicate}" do expect { expect(double(predicate => false)).to exist }.to fail_with(/expected .* to exist/) end it 'works when the object overrides `send`' do klass = Struct.new(:message) do def send :message_sent end define_method predicate do true end end expect(klass.new("msg")).to exist end end describe "expect(...).not_to exist" do it "passes if not #{predicate}" do expect(double(predicate => false)).not_to exist end it "fails if #{predicate}" do expect { expect(double(predicate => true)).not_to exist }.to fail_with(/expected .* not to exist/) end end end end context "when the object responds to #exist? and #exists?" do context "when they both return falsey values" do subject { double(:exist? => false, :exists? => nil) } describe "expect(...).not_to exist" do it "passes" do expect(subject).not_to exist end end describe "expect(...).to exist" do it "fails" do expect { expect(subject).to exist }.to fail_with(/expected .* to exist/) end end end context "when they both return truthy values" do subject { double(:exist? => true, :exists? => "something true") } describe "expect(...).not_to exist" do it "fails" do expect { expect(subject).not_to exist }.to fail_with(/expected .* not to exist/) end end describe "expect(...).to exist" do it "passes" do expect(subject).to exist end end end context "when they return values with different truthiness" do subject { double(:exist? => true, :exists? => false) } [:to, :not_to].each do |expect_method| describe "expect(...).#{expect_method} exist" do it "fails" do expect { expect(subject).send(expect_method, exist) }.to fail_including("`exist?` and `exists?` returned different values") end end end end context "when one predicate is deprecated" do context 'File has deprecated exists?' do it 'will not call exists? triggering the warning' do expect(File).to exist __FILE__ end end context 'FileTest has deprecated exists?' do it 'will not call exists? triggering the warning' do expect(FileTest).to exist __FILE__ end end if RUBY_VERSION > "1.9" context 'Dir has deprecated exists?' do it 'will not call exists? triggering the warning' do expect(Dir).to exist Dir.pwd end end end end end it 'passes any provided arguments to the call to #exist?' do object = double expect(object).to receive(:exist?).with(:foo, :bar) { true }.at_least(:once) expect(object).to exist(:foo, :bar) end it 'memoizes the call to `exist?` because it can be expensive (such as doing a DB query)' do object = double allow(object).to receive(:exist?) { false } expect { expect(object).to exist }.to fail expect(object).to have_received(:exist?).once end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_spec.rb0000664000000000000000000006731414557700001030023 0ustar rootrootRSpec.describe "expect(...).to be_predicate" do it "passes when actual returns true for :predicate?" do actual = double("actual", :happy? => true) expect(actual).to be_happy end it 'allows composable aliases to be defined' do RSpec::Matchers.alias_matcher :a_user_who_is_happy, :be_happy actual = double("actual", :happy? => true) expect(actual).to a_user_who_is_happy expect(a_user_who_is_happy.description).to eq("a user who is happy") RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin actual = double("actual", :admin? => true) expect(actual).to a_user_who_is_an_admin expect(a_user_who_is_an_admin.description).to eq("a user who is an admin") RSpec::Matchers.alias_matcher :an_animal_that_is_a_canine, :be_a_canine actual = double("actual", :canine? => true) expect(actual).to an_animal_that_is_a_canine expect(an_animal_that_is_a_canine.description).to eq("an animal that is a canine") end it 'composes gracefully' do RSpec::Matchers.alias_matcher :a_happy_object, :be_happy expect([ double, double(:happy? => false), double(:happy? => true), ]).to include a_happy_object end it "passes when actual returns true for :predicates? (present tense)" do actual = double("actual", :exists? => true, :exist? => true) expect(actual).to be_exist end context "when actual returns false for :predicate?" do it "fails when actual returns false for :predicate?" do actual = double("actual", :happy? => false) expect { expect(actual).to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to return true, got false") end it "only calls :predicate? once" do actual = double "actual", :happy? => false expect(actual).to receive(:happy?).once expect { expect(actual).to be_happy }.to fail end end it "fails when actual returns nil for :predicate?" do actual = double("actual", :happy? => nil) expect { expect(actual).to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to return true, got nil") end context "when strict_predicate_matchers is set to true" do it "fails when actual returns 42 for :predicate?" do actual = double("actual", :happy? => 42) expect { expect(actual).to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to return true, got 42") end end context "when strict_predicate_matchers is set to false" do around do |example| RSpec::Expectations.configuration.strict_predicate_matchers = false example.run RSpec::Expectations.configuration.strict_predicate_matchers = true end it "passes when actual returns truthy value for :predicate?" do actual = double("actual", :happy? => 42) expect(actual).to be_happy end it "states actual predicate used when it fails" do actual = double("actual", :happy? => false) expect { expect(actual).to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to be truthy, got false") end end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).to be_happy }.to fail_including("to respond to `happy?`") end it "indicates when a predicate was attempted to be matched against an unexpected `nil`" do expect { expect(nil).to be_happy }.to fail_including("expected nil to respond to `happy?`") end it 'handles arguments to the predicate' do object = Object.new def object.predicate?(return_val); return_val; end expect(object).to be_predicate(true) expect(object).to_not be_predicate(false) expect { expect(object).to be_predicate }.to raise_error(ArgumentError) expect { expect(object).to be_predicate(false) }.to fail expect { expect(object).not_to be_predicate(true) }.to fail end it 'handles arguments to the predicate implementing to_hash' do object = Object.new def object.predicate?(value); value.to_return; end hash_a_like = Class.new do def to_hash {:to_return => true} end def to_return true end end expect(object).to be_predicate(hash_a_like.new) end it 'handles keyword arguments to the predicate', :if => RSpec::Support::RubyFeatures.required_kw_args_supported? do object = Object.new binding.eval(<<-CODE, __FILE__, __LINE__) def object.predicate?(returns:); returns; end expect(object).to be_predicate(returns: true) expect(object).to_not be_predicate(returns: false) expect { expect(object).to be_predicate(returns: false) }.to fail expect { expect(object).to_not be_predicate(returns: true) }.to fail CODE expect { expect(object).to be_predicate }.to raise_error(ArgumentError) expect { expect(object).to be_predicate(true) }.to raise_error(ArgumentError) end it 'falls back to a present-tense form of the predicate when needed' do mouth = Object.new def mouth.frowns?(return_val); return_val; end expect(mouth).to be_frown(true) end it 'fails when :predicate? is private' do privately_happy = Class.new do private def happy? true end end expect { expect(privately_happy.new).to be_happy }.to fail_with(/private/) end it 'does not call :private_methods when the object publicly responds to the message' do publicly_happy = double('happy') expect(publicly_happy).to receive(:happy?) { true } expect(publicly_happy).not_to receive(:private_methods) expect(publicly_happy).to be_happy end it "fails on error other than NameError" do actual = double("actual") expect(actual).to receive(:foo?).and_raise("aaaah") expect { expect(actual).to be_foo }.to raise_error(/aaaah/) end it 'raises an error when :predicate? exists but raises NameError' do actual_class = Class.new do def foo? raise NameError, "aaaah" end end expect { expect(actual_class.new).to be_foo }.to raise_error(NameError, /aaaah/) end it "fails on error other than NameError (with the present tense predicate)" do actual = double expect(actual).to receive(:foos?).and_raise("aaaah") expect { expect(actual).to be_foo }.to raise_error(/aaaah/) end it "does not support operator chaining like a basic `be` matcher does" do matcher = be_happy value = double(:happy? => false) expect(matcher == value).to be false end it "indicates `be true` or `be_truthy` when using `be_true`" do actual = double("actual") expect { expect(actual).to be_true }.to fail_with(/or perhaps you meant `be true` or `be_truthy`/) end it "shows no message if actual responds to `true?` when using `be_true`" do actual = double("actual", :true? => true) expect { expect(actual).to be_true }.not_to raise_error end it "indicates `be false` or `be_falsey` when using `be_false`" do actual = double("actual") expect { expect(actual).to be_false }.to fail_with(/or perhaps you meant `be false` or `be_falsey`/) end it "shows no message if actual responds to `false?` when using `be_false`" do actual = double("actual", :false? => true) expect { expect(actual).to be_false }.not_to raise_error end end RSpec.describe "expect(...).not_to be_predicate" do let(:strict_predicate_matchers) { true } around do |example| default = RSpec::Expectations.configuration.strict_predicate_matchers? RSpec::Expectations.configuration.strict_predicate_matchers = strict_predicate_matchers example.run RSpec::Expectations.configuration.strict_predicate_matchers = default end it "passes when actual returns false for :sym?" do actual = double("actual", :happy? => false) expect(actual).not_to be_happy end context "when strict_predicate_matchers is set to true" do it "fails when actual returns nil for :sym?" do actual = double("actual", :happy? => nil) expect { expect(actual).not_to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to return false, got nil") end end context "when strict_predicate_matchers is set to false" do around do |example| RSpec::Expectations.configuration.strict_predicate_matchers = false example.run RSpec::Expectations.configuration.strict_predicate_matchers = true end it "passes when actual returns nil for :sym?" do actual = double("actual", :happy? => nil) expect(actual).not_to be_happy end it "shows actual comparison made when it fails" do actual = double("actual", :happy? => 42) expect { expect(actual).not_to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to be falsey, got 42") end end it "fails when actual returns true for :sym?" do actual = double("actual", :happy? => true) expect { expect(actual).not_to be_happy }.to fail_with("expected `#{actual.inspect}.happy?` to return false, got true") end it "fails when actual does not respond to :sym?" do expect { expect(Object.new).not_to be_happy }.to fail_including("to respond to `happy?`") end end RSpec.describe "expect(...).to be_predicate(*args)" do it "passes when actual returns true for :predicate?(*args)" do actual = double("actual") expect(actual).to receive(:older_than?).with(3).and_return(true) expect(actual).to be_older_than(3) end it "fails when actual returns false for :predicate?(*args)" do actual = double("actual") expect(actual).to receive(:older_than?).with(3).and_return(false) expect { expect(actual).to be_older_than(3) }.to fail_with("expected `#{actual.inspect}.older_than?(3)` to return true, got false") end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).to be_older_than(3) }.to fail_including("to respond to `older_than?`") end end RSpec.describe "expect(...).not_to be_predicate(*args)" do it "passes when actual returns false for :predicate?(*args)" do actual = double("actual") expect(actual).to receive(:older_than?).with(3).and_return(false) expect(actual).not_to be_older_than(3) end it "fails when actual returns true for :predicate?(*args)" do actual = double("actual") expect(actual).to receive(:older_than?).with(3).and_return(true) expect { expect(actual).not_to be_older_than(3) }.to fail_with("expected `#{actual.inspect}.older_than?(3)` to return false, got true") end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).not_to be_older_than(3) }.to fail_including("to respond to `older_than?`") end end RSpec.describe "expect(...).to be_predicate(&block)" do it "passes when actual returns true for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:happy?).and_yield expect(delegate).to receive(:check_happy).and_return(true) expect(actual).to be_happy { delegate.check_happy } end it "fails when actual returns false for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:happy?).and_yield expect(delegate).to receive(:check_happy).and_return(false) expect { expect(actual).to be_happy { delegate.check_happy } }.to fail_with("expected `#{actual.inspect}.happy?` to return true, got false") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_happy => true) expect { expect(Object.new).to be_happy { delegate.check_happy } }.to fail_including("to respond to `happy?`") end it 'passes the block on to the present-tense predicate form' do mouth = Object.new def mouth.frowns?; yield; end expect(mouth).to be_frown { true } expect(mouth).not_to be_frown { false } end it 'works with a do..end block for either predicate form' do mouth1 = Object.new def mouth1.frown?; yield; end mouth2 = Object.new def mouth2.frowns?; yield; end expect(mouth1).to be_frown do true end expect(mouth1).not_to be_frown do false end expect(mouth2).to be_frown do true end expect(mouth2).not_to be_frown do false end end it 'prefers a { ... } block to a do/end block because it binds more tightly' do mouth1 = Object.new def mouth1.frown?; yield; end mouth2 = Object.new def mouth2.frowns?; yield; end expect(mouth1).to be_frown { true } do false end expect(mouth1).not_to be_frown { false } do true end expect(mouth2).to be_frown { true } do false end expect(mouth2).not_to be_frown { false } do true end end end RSpec.describe "expect(...).not_to be_predicate(&block)" do it "passes when actual returns false for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:happy?).and_yield expect(delegate).to receive(:check_happy).and_return(false) expect(actual).not_to be_happy { delegate.check_happy } end it "fails when actual returns true for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:happy?).and_yield expect(delegate).to receive(:check_happy).and_return(true) expect { expect(actual).not_to be_happy { delegate.check_happy } }.to fail_with("expected `#{actual.inspect}.happy?` to return false, got true") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_happy => true) expect { expect(Object.new).not_to be_happy { delegate.check_happy } }.to fail_including("to respond to `happy?`") end end RSpec.describe "expect(...).to be_predicate(*args, &block)" do it "passes when actual returns true for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:older_than?).with(3).and_yield(3) expect(delegate).to receive(:check_older_than).with(3).and_return(true) expect(actual).to be_older_than(3) { |age| delegate.check_older_than(age) } end it "fails when actual returns false for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:older_than?).with(3).and_yield(3) expect(delegate).to receive(:check_older_than).with(3).and_return(false) expect { expect(actual).to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_with("expected `#{actual.inspect}.older_than?(3)` to return true, got false") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_older_than => true) expect { expect(Object.new).to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_including("to respond to `older_than?`") end end RSpec.describe "expect(...).not_to be_predicate(*args, &block)" do it "passes when actual returns false for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:older_than?).with(3).and_yield(3) expect(delegate).to receive(:check_older_than).with(3).and_return(false) expect(actual).not_to be_older_than(3) { |age| delegate.check_older_than(age) } end it "fails when actual returns true for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") expect(actual).to receive(:older_than?).with(3).and_yield(3) expect(delegate).to receive(:check_older_than).with(3).and_return(true) expect { expect(actual).not_to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_with("expected `#{actual.inspect}.older_than?(3)` to return false, got true") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_older_than => true) expect { expect(Object.new).not_to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_including("to respond to `older_than?`") end end RSpec.describe "expect(...).to be_truthy" do it "passes when actual equal?(true)" do expect(true).to be_truthy end it "passes when actual is 1" do expect(1).to be_truthy end it "fails when actual equal?(false)" do expect { expect(false).to be_truthy }.to fail_with("expected: truthy value\n got: false") end end RSpec.describe "expect(...).to be_falsey" do it "passes when actual equal?(false)" do expect(false).to be_falsey end it "passes when actual equal?(nil)" do expect(nil).to be_falsey end it "fails when actual equal?(true)" do expect { expect(true).to be_falsey }.to fail_with("expected: falsey value\n got: true") end end RSpec.describe "expect(...).to be_falsy" do it "passes when actual equal?(false)" do expect(false).to be_falsy end it "passes when actual equal?(nil)" do expect(nil).to be_falsy end it "fails when actual equal?(true)" do expect { expect(true).to be_falsy }.to fail_with("expected: falsey value\n got: true") end end RSpec.describe "expect(...).to be_nil" do it "passes when actual is nil" do expect(nil).to be_nil end it "fails when actual is not nil" do expect { expect(:not_nil).to be_nil }.to fail_with(/^expected: nil/) end end RSpec.describe "expect(...).not_to be_nil" do it "passes when actual is not nil" do expect(:not_nil).not_to be_nil end it "fails when actual is nil" do expect { expect(nil).not_to be_nil }.to fail_with(/^expected: not nil/) end end RSpec.describe "expect(...).to be <" do it "passes when < operator returns true" do expect(3).to be < 4 expect('a').to be < 'b' end it "fails when < operator returns false" do expect { expect(3).to be < 3 }.to fail_with("expected: < 3\n got: 3") expect { expect('a').to be < 'a' }.to fail_with(%(expected: < "a"\n got: "a")) end it "fails when < operator raises ArgumentError" do expect { expect('a').to be < 1 }.to fail_with(%(expected: < 1\n got: "a")) end it 'fails when < operator is not defined' do expect { expect(nil).to be < 1 }.to fail_with(%(expected: < 1\n got: nil)) end it "describes itself" do expect(be.<(4).description).to eq "be < 4" end it 'does not lie and say that it is equal to a number' do matcher = (be < 3) expect(5 == matcher).to be false end end RSpec.describe "expect(...).to be <=" do it "passes when <= operator returns true" do expect(3).to be <= 4 expect(4).to be <= 4 expect('a').to be <= 'b' expect('a').to be <= 'a' end it "fails when <= operator returns false" do expect { expect(3).to be <= 2 }.to fail_with("expected: <= 2\n got: 3") expect { expect('c').to be <= 'a' }.to fail_with(%(expected: <= "a"\n got: "c")) end it "fails when <= operator raises ArgumentError" do expect { expect('a').to be <= 1 }.to fail_with(%(expected: <= 1\n got: "a")) end it 'fails when <= operator is not defined' do expect { expect(nil).to be <= 1 }.to fail_with(%(expected: <= 1\n got: nil)) end end RSpec.describe "expect(...).to be >=" do it "passes when >= operator returns true" do expect(4).to be >= 4 expect(5).to be >= 4 end it "fails when >= operator returns false" do expect { expect(3).to be >= 4 }.to fail_with("expected: >= 4\n got: 3") expect { expect('a').to be >= 'c' }.to fail_with(%(expected: >= "c"\n got: "a")) end it "fails when >= operator raises ArgumentError" do expect { expect('a').to be >= 1 }.to fail_with(%(expected: >= 1\n got: "a")) end it 'fails when >= operator is not defined' do expect { expect(nil).to be >= 1 }.to fail_with(%(expected: >= 1\n got: nil)) end end RSpec.describe "expect(...).to be >" do it "passes when > operator returns true" do expect(5).to be > 4 end it "fails when > operator returns false" do expect { expect(3).to be > 4 }.to fail_with("expected: > 4\n got: 3") expect { expect('a').to be > 'a' }.to fail_with(%(expected: > "a"\n got: "a")) end it "fails when > operator raises ArgumentError" do expect { expect('a').to be > 1 }.to fail_with(%(expected: > 1\n got: "a")) end it 'fails when > operator is not defined' do expect { expect(nil).to be > 1 }.to fail_with(%(expected: > 1\n got: nil)) end end RSpec.describe "expect(...).to be ==" do it "passes when == operator returns true" do expect(5).to be == 5 end it "fails when == operator returns false" do expect { expect(3).to be == 4 }.to fail_with("expected: == 4\n got: 3") expect { expect('a').to be == 'c' }.to fail_with(%(expected: == "c"\n got: "a")) end it "fails when == operator raises ArgumentError" do failing_equality_klass = Class.new do def inspect "" end def ==(other) raise ArgumentError end end expect { expect(failing_equality_klass.new).to be == 1 }.to fail_with(%(expected: == 1\n got: )) end it 'works when the target overrides `#send`' do klass = Struct.new(:message) do def send :message_sent end end msg_1 = klass.new("hello") msg_2 = klass.new("hello") expect(msg_1).to be == msg_2 end end RSpec.describe "expect(...).to be =~" do it "passes when =~ operator returns true" do expect("a string").to be =~ /str/ end it "fails when =~ operator returns false" do expect { expect("a string").to be =~ /blah/ }.to fail_with(%(expected: =~ /blah/\n got: "a string")) end end RSpec.describe "should be =~", :uses_should do it "passes when =~ operator returns true" do "a string".should be =~ /str/ end it "fails when =~ operator returns false" do expect { "a string".should be =~ /blah/ }.to fail_with(%(expected: =~ /blah/\n got: "a string")) end end RSpec.describe "expect(...).to be ===" do it "passes when === operator returns true" do expect(Hash).to be === {} end it "fails when === operator returns false" do expect { expect(Hash).to be === "not a hash" }.to fail_with(%(expected: === "not a hash"\n got: Hash)) end end RSpec.describe "expect(...).not_to with comparison operators" do it "coaches user to stop using operators with expect().not_to with numerical comparison operators" do expect { expect(5).not_to be < 6 }.to fail_with("`expect(5).not_to be < 6` not only FAILED, it is a bit confusing.") expect { expect(5).not_to be <= 6 }.to fail_with("`expect(5).not_to be <= 6` not only FAILED, it is a bit confusing.") expect { expect(6).not_to be > 5 }.to fail_with("`expect(6).not_to be > 5` not only FAILED, it is a bit confusing.") expect { expect(6).not_to be >= 5 }.to fail_with("`expect(6).not_to be >= 5` not only FAILED, it is a bit confusing.") end it "coaches users to stop using negation with string comparison operators" do expect { expect("foo").not_to be > "bar" }.to fail_with('`expect("foo").not_to be > "bar"` not only FAILED, it is a bit confusing.') end it "handles ArgumentError as a failure" do [:<, :<=, :>=, :>].each do |operator| expect { expect('a').to_not be.send(operator, 1) }.to fail_with(%(`expect("a").not_to be #{operator} 1` not only FAILED, it is a bit confusing.)) end end it "handles NameError as a failure" do [:<, :<=, :>=, :>].each do |operator| expect { expect( Class.new do def inspect '' end define_method(operator) { |arg| self.non_existent_attribute == operator } end.new ).to_not be.send(operator, 1) }.to fail_with(%(`expect().not_to be #{operator} 1` not only FAILED, it is a bit confusing.)) end end end RSpec.describe "expect(...).not_to with equality operators" do it "raises normal error with expect().not_to with equality operators" do expect { expect(6).not_to be == 6 }.to fail_with("`expect(6).not_to be == 6`") expect { expect(String).not_to be === "Hello" }.to fail_with('`expect(String).not_to be === "Hello"`') end it "handles ArgumentError as a failure" do failing_equality_klass = Class.new do def inspect "" end def ==(other) raise ArgumentError end end expect { expect(failing_equality_klass.new).not_to be == 1 }.to fail_with(%(`expect().not_to be == 1`)) expect { expect(failing_equality_klass.new).not_to be === 1 }.to fail_with(%(`expect().not_to be === 1`)) end it "handles NameError as a failure" do failing_equality_klass = Class.new do def inspect "" end undef == end expect { expect(failing_equality_klass.new).not_to be == 1 }.to fail_with(%(`expect().not_to be == 1`)) expect { expect(failing_equality_klass.new).not_to be === 1 }.to fail_with(%(`expect().not_to be === 1`)) end end RSpec.describe "expect(...).to be" do it "passes if actual is truthy" do expect(true).to be expect(1).to be end it "fails if actual is false" do expect { expect(false).to be }.to fail_with("expected false to evaluate to true") end it "fails if actual is nil" do expect { expect(nil).to be }.to fail_with("expected nil to evaluate to true") end it "describes itself" do expect(be.description).to eq "be" end end RSpec.describe "expect(...).not_to be" do it "passes if actual is falsy" do expect(false).not_to be expect(nil).not_to be end it "fails on true" do expect { expect(true).not_to be }.to fail_with("expected true to evaluate to false") end end RSpec.describe "expect(...).to be(value)" do it "delegates to equal" do matcher = equal(5) expect(self).to receive(:equal).with(5).and_return(matcher) expect(5).to be(5) end end RSpec.describe "expect(...).not_to be(value)" do it "delegates to equal" do matcher = equal(4) expect(self).to receive(:equal).with(4).and_return(matcher) expect(5).not_to be(4) end end RSpec.describe "'expect(...).to be' with operator" do it "includes 'be' in the description" do expect((be > 6).description).to match(/be > 6/) expect((be >= 6).description).to match(/be >= 6/) expect((be <= 6).description).to match(/be <= 6/) expect((be < 6).description).to match(/be < 6/) end end RSpec.describe "arbitrary predicate with DelegateClass" do it "accesses methods defined in the delegating class (LH[#48])" do in_sub_process_if_possible do require 'delegate' class ArrayDelegate < DelegateClass(Array) def initialize(array) @internal_array = array super(@internal_array) end def large? @internal_array.size >= 5 end end delegate = ArrayDelegate.new([1, 2, 3, 4, 5, 6]) expect(delegate).to be_large end end end RSpec.describe "be_a, be_an" do it "passes when class matches" do expect("foobar").to be_a(String) expect([1, 2, 3]).to be_an(Array) end it "fails when class does not match" do expect("foobar").not_to be_a(Hash) expect([1, 2, 3]).not_to be_an(Integer) end end RSpec.describe "be_an_instance_of" do it "passes when direct class matches" do expect("string").to be_an_instance_of(String) end it "fails when class is higher up hierarchy" do expect(5).not_to be_an_instance_of(Numeric) end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/base_matcher_spec.rb0000664000000000000000000001134214557700001032040 0ustar rootrootmodule RSpec::Matchers::BuiltIn RSpec.describe BaseMatcher do describe "#match_unless_raises" do let(:matcher) do Class.new(BaseMatcher).new end it "returns true if there are no errors" do expect(matcher.match_unless_raises {}).to be_truthy end it "returns false if there is an error" do expect(matcher.match_unless_raises { raise }).to be_falsey end it "returns false if the only submitted error is raised" do expect(matcher.match_unless_raises(RuntimeError) { raise "foo" }).to be_falsey end it "returns false if any of several errors submitted is raised" do expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise "foo" }).to be_falsey expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise ArgumentError.new('') }).to be_falsey expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise NameError.new('') }).to be_falsey end it "re-raises any error other than one of those specified" do expect do matcher.match_unless_raises(ArgumentError) { raise "foo" } end.to raise_error "foo" end it "stores the rescued exception for use in messages" do matcher.match_unless_raises(RuntimeError) { raise "foo" } expect(matcher.rescued_exception).to be_a(RuntimeError) expect(matcher.rescued_exception.message).to eq("foo") end end describe "#failure_message" do context "when the parameter to .new is omitted" do it "describes what was expected" do matcher_class = Class.new(BaseMatcher) do def match(_expected, _actual) false end end stub_const("Foo::Bar::BeSomething", matcher_class) matcher = matcher_class.new matcher.matches?("foo") expect(matcher.failure_message).to eq('expected "foo" to be something') end end end describe "#===" do it "responds the same way as matches?" do matcher = Class.new(BaseMatcher) do def initialize(expected) @expected = expected end def matches?(actual) (@actual = actual) == @expected end end expect(matcher.new(3).matches?(3)).to be_truthy expect(matcher.new(3)).to be === 3 expect(matcher.new(3).matches?(4)).to be_falsey expect(matcher.new(3)).not_to be === 4 end end describe "default failure message detection" do def has_default_failure_messages?(matcher) BaseMatcher::DefaultFailureMessages.has_default_failure_messages?(matcher) end shared_examples_for "detecting default failure message" do context "that has no failure message overrides" do it "indicates that it has default failure messages" do matcher = build_matcher expect(has_default_failure_messages?(matcher)).to be true end end context "that overrides `failure_message`" do it "indicates that it lacks default failure messages" do matcher = build_matcher { def failure_message; end } expect(has_default_failure_messages?(matcher)).to be false end end context "that overrides `failure_message_when_negated`" do it "indicates that it lacks default failure messages" do matcher = build_matcher { def failure_message_when_negated; end } expect(has_default_failure_messages?(matcher)).to be false end end end context "for a DSL-defined custom matcher" do include_examples "detecting default failure message" do def build_matcher(&block) definition = Proc.new do match {} module_exec(&block) if block end RSpec::Matchers::DSL::Matcher.new(:matcher_name, definition, self) end end end context "for a matcher that subclasses `BaseMatcher`" do include_examples "detecting default failure message" do def build_matcher(&block) Class.new(RSpec::Matchers::BuiltIn::BaseMatcher, &block).new end end end context "for a custom matcher that lacks `failure_message_when_negated` (documented as an optional part of the matcher protocol" do it "indicates that it lacks default failure messages" do matcher = Class.new(RSpec::Matchers::BuiltIn::BaseMatcher) { undef failure_message_when_negated }.new expect(RSpec::Support.is_a_matcher?(matcher)).to be true expect(has_default_failure_messages?(matcher)).to be false end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_within_spec.rb0000664000000000000000000001244114557700001031374 0ustar rootrootmodule RSpec module Matchers RSpec.describe "expect(actual).to be_within(delta).of(expected)" do it_behaves_like "an RSpec value matcher", :valid_value => 5, :invalid_value => -5 do let(:matcher) { be_within(2).of(4.0) } end it "passes when actual == expected" do expect(5.0).to be_within(0.5).of(5.0) end it "passes when actual < (expected + delta)" do expect(5.49).to be_within(0.5).of(5.0) end it "passes when actual > (expected - delta)" do expect(4.51).to be_within(0.5).of(5.0) end it "passes when actual == (expected - delta)" do expect(4.5).to be_within(0.5).of(5.0) end it "passes when actual == (expected + delta)" do expect(5.5).to be_within(0.5).of(5.0) end it "passes with integer arguments that are near each other" do expect(1.0001).to be_within(5).percent_of(1) end it "passes with negative arguments" do expect(-1.0001).to be_within(5).percent_of(-1) end it "fails when actual < (expected - delta)" do expect { expect(4.49).to be_within(0.5).of(5.0) }.to fail_with("expected 4.49 to be within 0.5 of 5.0") end it "fails when actual > (expected + delta)" do expect { expect(5.51).to be_within(0.5).of(5.0) }.to fail_with("expected 5.51 to be within 0.5 of 5.0") end it "works with Time" do expect(Time.now).to be_within(0.1).of(Time.now) end it "provides a description" do matcher = be_within(0.5).of(5.0) matcher.matches?(5.1) expect(matcher.description).to eq "be within 0.5 of 5.0" end it "formats expected within description" do klass = Class.new { def inspect; "5"; end } matcher = be_within(0.5).of(klass.new) expect(matcher.description).to eq "be within 0.5 of 5" end it "raises an error if no expected value is given" do expect { expect(5.1).to be_within(0.5) }.to raise_error(ArgumentError, /must set an expected value using #of/) end it "fails if the actual is not numeric" do expect { expect(nil).to be_within(0.1).of(0) }.to fail_with("expected nil to be within 0.1 of 0, but it could not be treated as a numeric value") end end RSpec.describe "expect(actual).to be_within(delta).percent_of(expected)" do it "passes when actual is within the given percent variance" do expect(9.0).to be_within(10).percent_of(10.0) expect(10.0).to be_within(10).percent_of(10.0) expect(11.0).to be_within(10).percent_of(10.0) end it "fails when actual is outside the given percent variance" do expect { expect(8.9).to be_within(10).percent_of(10.0) }.to fail_with("expected 8.9 to be within 10% of 10.0") expect { expect(11.1).to be_within(10).percent_of(10.0) }.to fail_with("expected 11.1 to be within 10% of 10.0") end it "provides a description" do matcher = be_within(0.5).percent_of(5.0) matcher.matches?(5.1) expect(matcher.description).to eq "be within 0.5% of 5.0" end it "works with custom measure objects" do weight_class = Struct.new(:val) do include Comparable def <=>(other); val <=> other.val; end def -(other); self.class.new(val - other.val); end def abs; self.class.new(val.abs); end def *(numeric); self.class.new(val * numeric); end def /(numeric); self.class.new(val / numeric); end end expect(weight_class.new(99)).to be_within(2).percent_of(weight_class.new(100)) expect { expect(weight_class.new(90)).to be_within(2).percent_of(weight_class.new(100)) }.to fail_with(/expected # to be within 2% of #/) end end RSpec.describe "expect(actual).not_to be_within(delta).of(expected)" do it "passes when actual < (expected - delta)" do expect(4.49).not_to be_within(0.5).of(5.0) end it "passes when actual > (expected + delta)" do expect(5.51).not_to be_within(0.5).of(5.0) end it "fails when actual == expected" do expect { expect(5.0).not_to be_within(0.5).of(5.0) }.to fail_with("expected 5.0 not to be within 0.5 of 5.0") end it "fails when actual < (expected + delta)" do expect { expect(5.49).not_to be_within(0.5).of(5.0) }.to fail_with("expected 5.49 not to be within 0.5 of 5.0") end it "fails when actual > (expected - delta)" do expect { expect(4.51).not_to be_within(0.5).of(5.0) }.to fail_with("expected 4.51 not to be within 0.5 of 5.0") end it "fails when actual == (expected - delta)" do expect { expect(4.5).not_to be_within(0.5).of(5.0) }.to fail_with("expected 4.5 not to be within 0.5 of 5.0") end it "fails when actual == (expected + delta)" do expect { expect(5.5).not_to be_within(0.5).of(5.0) }.to fail_with("expected 5.5 not to be within 0.5 of 5.0") end it "passes if the actual is not numeric" do expect(nil).not_to be_within(0.1).of(0) end end end end ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/start_and_end_with_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/start_and_end_with_sp0000664000000000000000000003233414557700001032355 0ustar rootrootRSpec.describe "expect(...).to start_with" do it_behaves_like "an RSpec value matcher", :valid_value => "ab", :invalid_value => "bc" do let(:matcher) { start_with("a") } end context "with a string" do it "passes if it matches the start of the actual string" do expect("this string").to start_with "this str" end it "fails if it does not match the start of the actual string" do expect { expect("this string").to start_with "that str" }.to fail_with("expected \"this string\" to start with \"that str\"") end end context "with an array" do it "passes if it is the first element of the array" do expect([0, 1, 2]).to start_with 0 end it "passes if the first elements of the array match" do expect([0, 1, 2]).to start_with 0, 1 end it "fails if it does not match the first element of the array" do expect { expect([0, 1, 2]).to start_with 2 }.to fail_with("expected [0, 1, 2] to start with 2") end it "fails if it the first elements of the array do not match" do expect { expect([0, 1, 2]).to start_with 1, 2 }.to fail_with("expected [0, 1, 2] to start with 1 and 2") end end context "with an array of strings" do it "passes if given the first element of the array" do expect(%w[ a b c ]).to start_with 'a' end it "passes if given the first n of the array" do expect(%w[ a b c ]).to start_with('a', 'b') end it 'fails if given the wrong first element of the array' do expect { expect(%w[ a b c ]).to start_with 'z' }.to fail_with('expected ["a", "b", "c"] to start with "z"') end end context "with an array of uncustomized structs" do struct = Struct.new(:foo) it 'passes if the array ends with a struct equal to the provided struct' do s1 = struct.new(5) s2 = struct.new(5) expect(s1).to eq(s2) expect([s1, 10]).to start_with(s2) end it 'fails if the array ends with a struct not equal to the provided struct' do s1 = struct.new(5) s2 = struct.new(6) expect(s1).not_to eq(s2) expect { expect([s1, 10]).to start_with(s2) }.to fail_including("expected [#{s1.inspect}, 10] to start with #{s2.inspect}") end end context "with an array of structs that have a custom `==` definition" do my_struct = Struct.new(:id, :fluff) do def ==(other) other.is_a?(self.class) && other.id == id end end it 'passes if the array ends with a struct equal to the provided struct' do s1 = my_struct.new(1, "foo") s2 = my_struct.new(1, "bar") expect(s1).to eq(s2) expect([s1, 10]).to start_with(s2) end it 'fails if the array ends with a struct not equal to the provided struct' do s1 = my_struct.new(1, "foo") s2 = my_struct.new(2, "bar") expect(s1).not_to eq(s2) expect { expect([s1, 10]).to start_with(s2) }.to fail_including("expected [#{s1.inspect}, 10] to start with #{s2.inspect}") end end context "with an object that does not respond to :[]" do it "fails with a useful message" do actual = Object.new expect { expect(actual).to start_with 0 }.to fail_with("expected #{actual.inspect} to start with 0, but it cannot be indexed using #[]") end end context "with a hash" do it "fails with a useful error if trying to match more than one element" do actual = { :a => 'b', :b => 'b', :c => 'c' } expected = { :a => 'b', :b => 'b' } expect { expect(actual).to start_with(expected) }.to fail_with(/\Aexpected #{hash_inspect(actual).gsub(" => ", "=>")} to start with #{hash_inspect(expected).gsub(" => ", "=>")}, but it does not have ordered elements\z/) end end describe "composing with other matchers" do it 'passes if the start of an array matches two given matchers' do expect([1.01, "food", 3]).to start_with(a_value_within(0.2).of(1), a_string_matching(/foo/)) end it 'passes if the start of an array matches one given matcher' do expect([1.01, "food", 3]).to start_with(a_value_within(0.2).of(1)) end it 'provides a description' do description = start_with(a_value_within(0.1).of(1), a_string_matching(/abc/)).description expect(description).to eq("start with a value within 0.1 of 1 and a string matching /abc/") end it 'fails with a clear error message when the matchers do not match' do expect { expect([2.01, "food", 3]).to start_with(a_value_within(0.2).of(1), a_string_matching(/foo/)) }.to fail_with('expected [2.01, "food", 3] to start with a value within 0.2 of 1 and a string matching /foo/') end end end RSpec.describe "expect(...).not_to start_with" do context "with a string" do it "passes if it does not match the start of the actual string" do expect("this string").not_to start_with "that str" end it "fails if it does match the start of the actual string" do expect { expect("this string").not_to start_with "this str" }.to fail_with("expected \"this string\" not to start with \"this str\"") end end context "with an array" do it "passes if it is not the first element of the array" do expect([0, 1, 2]).not_to start_with 2 end it "passes if the first elements of the array do not match" do expect([0, 1, 2]).not_to start_with 1, 2 end it "fails if it matches the first element of the array" do expect { expect([0, 1, 2]).not_to start_with 0 }.to fail_with("expected [0, 1, 2] not to start with 0") end it "fails if it the first elements of the array match" do expect { expect([0, 1, 2]).not_to start_with 0, 1 }.to fail_with("expected [0, 1, 2] not to start with 0 and 1") end end context "with an array of strings" do it "fails if given the first element of the array" do expect { expect(%w[ a b c ]).not_to start_with 'a' }.to fail_with('expected ["a", "b", "c"] not to start with "a"') end it "fails if given the first n of the array" do expect { expect(%w[ a b c ]).not_to start_with('a', 'b') }.to fail_with('expected ["a", "b", "c"] not to start with "a" and "b"') end it 'passes if given the wrong first element of the array' do expect(%w[ a b c ]).not_to start_with 'z' end end it 'can pass when composed with another matcher' do expect(["a"]).not_to start_with(a_string_matching(/bar/)) end it 'can fail when composed with another matcher' do expect { expect(["a"]).not_to start_with(a_string_matching(/a/)) }.to fail_with('expected ["a"] not to start with a string matching /a/') end end RSpec.describe "expect(...).to end_with" do it_behaves_like "an RSpec value matcher", :valid_value => "ab", :invalid_value => "bc" do let(:matcher) { end_with("b") } end context "with a string" do it "passes if it matches the end of the actual string" do expect("this string").to end_with "is string" end it "fails if it does not match the end of the actual string" do expect { expect("this string").to end_with "is stringy" }.to fail_with("expected \"this string\" to end with \"is stringy\"") end end context "with an array" do it "passes if it is the last element of the array" do expect([0, 1, 2]).to end_with 2 end it "passes if the last elements of the array match" do expect([0, 1, 2]).to end_with [1, 2] end it "fails if it does not match the last element of the array" do expect { expect([0, 1, 2]).to end_with 1 }.to fail_with("expected [0, 1, 2] to end with 1") end it "fails if it the last elements of the array do not match" do expect { expect([0, 1, 2]).to end_with [0, 1] }.to fail_with("expected [0, 1, 2] to end with 0 and 1") end end context "with an array of strings" do it "passes if given the last element of the array" do expect(%w[ a b c ]).to end_with 'c' end it "passes if given the last n of the array" do expect(%w[ a b c ]).to end_with('b', 'c') end it 'fails if given the wrong last element of the array' do expect { expect(%w[ a b c ]).to end_with 'z' }.to fail_with('expected ["a", "b", "c"] to end with "z"') end end context "with an array of uncustomized structs" do struct = Struct.new(:foo) it 'passes if the array ends with a struct equal to the provided struct' do s1 = struct.new(5) s2 = struct.new(5) expect(s1).to eq(s2) expect([10, s1]).to end_with(s2) end it 'fails if the array ends with a struct not equal to the provided struct' do s1 = struct.new(5) s2 = struct.new(6) expect(s1).not_to eq(s2) expect { expect([10, s1]).to end_with(s2) }.to fail_including("expected [10, #{s1.inspect}] to end with #{s2.inspect}") end end context "with an array of structs that have a custom `==` definition" do my_struct = Struct.new(:id, :fluff) do def ==(other) other.is_a?(self.class) && other.id == id end end it 'passes if the array ends with a struct equal to the provided struct' do s1 = my_struct.new(1, "foo") s2 = my_struct.new(1, "bar") expect(s1).to eq(s2) expect([10, s1]).to end_with(s2) end it 'fails if the array ends with a struct not equal to the provided struct' do s1 = my_struct.new(1, "foo") s2 = my_struct.new(2, "bar") expect(s1).not_to eq(s2) expect { expect([10, s1]).to end_with(s2) }.to fail_including("expected [10, #{s1.inspect}] to end with #{s2.inspect}") end end context "with an object that does not respond to :[]" do it "fails with a useful message" do actual = Object.new expect { expect(actual).to end_with 0 }.to fail_with("expected #{actual.inspect} to end with 0, but it cannot be indexed using #[]") end end context "with a hash" do it "raises an ArgumentError if trying to match more than one element" do actual = { :a => 'b', :b => 'b', :c => 'c' } expected = { :a => 'b', :b => 'b' } expect { expect(actual).to end_with(expected) }.to fail_with(/\Aexpected #{hash_inspect(actual).gsub(" => ", "=>")} to end with #{hash_inspect(expected).gsub(" => ", "=>")}, but it does not have ordered elements\z/) end end describe "composing with other matchers" do it 'passes if the end of an array matches two given matchers' do expect([3, "food", 1.1]).to end_with(a_string_matching(/foo/), a_value_within(0.2).of(1)) end it 'passes if the end of an array matches one given matcher' do expect([3, "food", 1.1]).to end_with(a_value_within(0.2).of(1)) end it 'provides a description' do description = end_with(a_value_within(0.1).of(1), a_string_matching(/abc/)).description expect(description).to eq("end with a value within 0.1 of 1 and a string matching /abc/") end it 'fails with a clear error message when the matchers do not match' do expect { expect([2.01, 3, "food"]).to end_with(a_value_within(0.2).of(1), a_string_matching(/foo/)) }.to fail_with('expected [2.01, 3, "food"] to end with a value within 0.2 of 1 and a string matching /foo/') end end end RSpec.describe "expect(...).not_to end_with" do context "with a sting" do it "passes if it does not match the end of the actual string" do expect("this string").not_to end_with "stringy" end it "fails if it matches the end of the actual string" do expect { expect("this string").not_to end_with "string" }.to fail_with("expected \"this string\" not to end with \"string\"") end end context "an array" do it "passes if it is not the last element of the array" do expect([0, 1, 2]).not_to end_with 1 end it "passes if the last elements of the array do not match" do expect([0, 1, 2]).not_to end_with [0, 1] end it "fails if it matches the last element of the array" do expect { expect([0, 1, 2]).not_to end_with 2 }.to fail_with("expected [0, 1, 2] not to end with 2") end it "fails if it the last elements of the array match" do expect { expect([0, 1, 2]).not_to end_with [1, 2] }.to fail_with("expected [0, 1, 2] not to end with 1 and 2") end end context "with an array of strings" do it "fails if given the last element of the array" do expect { expect(%w[ a b c ]).not_to end_with 'c' }.to fail_with('expected ["a", "b", "c"] not to end with "c"') end it "fails if given the last n of the array" do expect { expect(%w[ a b c ]).not_to end_with('b', 'c') }.to fail_with('expected ["a", "b", "c"] not to end with "b" and "c"') end it 'passes if given the wrong last element of the array' do expect(%w[ a b c ]).not_to end_with 'z' end end it 'can pass when composed with another matcher' do expect(["a"]).not_to end_with(a_string_matching(/bar/)) end it 'can fail when composed with another matcher' do expect { expect(["a"]).not_to end_with(a_string_matching(/a/)) }.to fail_with('expected ["a"] not to end with a string matching /a/') end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/has_spec.rb0000664000000000000000000001447414557700001030207 0ustar rootrootRSpec.describe "expect(...).to have_sym(*args)" do it_behaves_like "an RSpec value matcher", :valid_value => { :a => 1 }, :invalid_value => {} do let(:matcher) { have_key(:a) } end it "passes if #has_sym?(*args) returns true" do expect({ :a => "A" }).to have_key(:a) end if RSpec::Support::RubyFeatures.required_kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it 'supports the use of required keyword arguments' do thing = Class.new { def has_keyword?(keyword:); keyword == 'a'; end } expect(thing.new).to have_keyword(keyword: 'a') end CODE end if RSpec::Support::RubyFeatures.kw_args_supported? binding.eval(<<-CODE, __FILE__, __LINE__) it 'supports the use of optional keyword arguments' do thing = Class.new { def has_keyword?(keyword: 'b'); keyword == 'a'; end } expect(thing.new).to have_keyword(keyword: 'a') end CODE end it "fails if #has_sym?(*args) returns false" do expect { expect({ :b => "B" }).to have_key(:a) }.to fail_with('expected `{:b=>"B"}.has_key?(:a)` to return true, got false') end obj_with_block_method = Object.new def obj_with_block_method.has_some_stuff?; yield; end it 'forwards the given `{ }` block on to the `has_xyz?` method' do expect(obj_with_block_method).to have_some_stuff { true } expect(obj_with_block_method).to_not have_some_stuff { false } end it 'forwards the given `do..end` block on to the `has_xyz?` method' do expect(obj_with_block_method).to have_some_stuff do true end expect(obj_with_block_method).to_not have_some_stuff do false end end it 'favors a curly brace block over a do...end one since it binds to the matcher method' do expect(obj_with_block_method).to have_some_stuff { true } do false end expect(obj_with_block_method).not_to have_some_stuff { false } do true end end it 'does not include any args in the failure message if no args were given to the matcher' do o = Object.new def o.has_some_stuff?; false; end expect { expect(o).to have_some_stuff }.to fail_with("expected `#{o.inspect}.has_some_stuff?` to return true, got false") end it 'includes multiple args in the failure message if multiple args were given to the matcher' do o = Object.new def o.has_some_stuff?(*_); false; end expect { expect(o).to have_some_stuff(:a, 7, "foo") }.to fail_with(%Q{expected `#{o.inspect}.has_some_stuff?(:a, 7, "foo")` to return true, got false}) end it "fails if #has_sym?(*args) returns nil" do klass = Class.new do def has_foo? end end expect { expect(klass.new).to have_foo }.to fail_with(/expected `.*\.has_foo\?` to return true, got nil/) end it 'fails if #has_sym?(*args) is private' do klass = Class.new do private def has_foo? true end end expect { expect(klass.new).to have_foo }.to fail_with(/private/) end it "fails if target does not respond to #has_sym?" do expect { expect(Object.new).to have_key(:a) }.to fail_including('to respond to `has_key?`') end it "reraises an exception thrown in #has_sym?(*args)" do o = Object.new def o.has_sym?(*_args) raise "Funky exception" end expect { expect(o).to have_sym(:foo) }.to raise_error("Funky exception") end it 'allows composable aliases to be defined' do RSpec::Matchers.alias_matcher :an_object_having_sym, :have_sym o = Object.new def o.has_sym?(sym); sym == :foo; end expect(o).to an_object_having_sym(:foo) expect(o).not_to an_object_having_sym(:bar) expect(an_object_having_sym(:foo).description).to eq("an object having sym :foo") end it 'composes gracefully' do RSpec::Matchers.alias_matcher :an_object_having_foo, :have_foo expect([ double, double(:has_foo? => false), double(:has_foo? => true), ]).to include an_object_having_foo end end RSpec.describe "expect(...).not_to have_sym(*args)" do it "passes if #has_sym?(*args) returns false" do expect({ :a => "A" }).not_to have_key(:b) end context "when strict_predicate_matchers is set to true" do it "fails when #has_sym? returns nil" do actual = double("actual", :has_foo? => nil) expect { expect(actual).not_to have_foo }.to fail_with("expected `#{actual.inspect}.has_foo?` to return false, got nil") end end context "when strict_predicate_matchers is set to false" do around do |example| RSpec::Expectations.configuration.strict_predicate_matchers = false example.run RSpec::Expectations.configuration.strict_predicate_matchers = true end it "passes if #has_sym?(*args) returns nil" do actual = double("actual", :has_foo? => nil) expect(actual).not_to have_foo end end it "fails if #has_sym?(*args) returns true" do expect { expect({ :a => "A" }).not_to have_key(:a) }.to fail_with('expected `{:a=>"A"}.has_key?(:a)` to return false, got true') end it "fails if target does not respond to #has_sym?" do expect { expect(Object.new).not_to have_key(:a) }.to fail_including('to respond to `has_key?`') end it "reraises an exception thrown in #has_sym?(*args)" do o = Object.new def o.has_sym?(*_args) raise "Funky exception" end expect { expect(o).not_to have_sym(:foo) }.to raise_error("Funky exception") end it 'does not include any args in the failure message if no args were given to the matcher' do o = Object.new def o.has_some_stuff?; true; end expect { expect(o).not_to have_some_stuff }.to fail_with("expected `#{o.inspect}.has_some_stuff?` to return false, got true") end it 'includes multiple args in the failure message if multiple args were given to the matcher' do o = Object.new def o.has_some_stuff?(*_); true; end expect { expect(o).not_to have_some_stuff(:a, 7, "foo") }.to fail_with(%Q{expected `#{o.inspect}.has_some_stuff?(:a, 7, "foo")` to return false, got true}) end end RSpec.describe "has" do it "works when the target implements #send" do o = { :a => "A" } def o.send(*_args); raise "DOH! Library developers shouldn't use #send!" end expect { expect(o).to have_key(:a) }.not_to raise_error end end ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_instance_of_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_instance_of_spec.r0000664000000000000000000000625314557700001032224 0ustar rootrootmodule RSpec module Matchers [:be_an_instance_of, :be_instance_of].each do |method| RSpec.describe "expect(actual).to #{method}(expected)" do it_behaves_like "an RSpec value matcher", :valid_value => "a", :invalid_value => 5 do let(:matcher) { send(method, String) } end it "passes if actual is instance of expected class" do expect("a").to send(method, String) end it "fails if actual is instance of subclass of expected class" do expect { expect(5).to send(method, Numeric) }.to fail_with("expected 5 to be an instance of Numeric") end it "fails with failure message for should unless actual is instance of expected class" do expect { expect("foo").to send(method, Array) }.to fail_with('expected "foo" to be an instance of Array') end it "provides a description" do matcher = be_an_instance_of(Integer) matcher.matches?(Numeric) expect(matcher.description).to eq "be an instance of Integer" end context "when expected provides an expanded inspect, e.g. AR::Base" do let(:user_klass) do Class.new do def self.inspect "User(id: integer, name: string)" end end end before { stub_const("User", user_klass) } it "provides a description including only the class name" do matcher = be_an_instance_of(User) expect(matcher.description).to eq "be an instance of User" end end context "when the actual object does not respond to #instance_of? method" do let(:klass) { Class.new { undef_method :instance_of? } } let(:actual_object) { klass.new } it "raises ArgumentError" do message = "The be_an_instance_of matcher requires that "\ "the actual object responds to #instance_of? method " \ "but a `NoMethodError` was encountered instead." expect { expect(actual_object).to send(method, klass) }.to raise_error ::ArgumentError, message end end end RSpec.describe "expect(actual).not_to #{method}(expected)" do it "fails with failure message for should_not if actual is instance of expected class" do expect { expect("foo").not_to send(method, String) }.to fail_with('expected "foo" not to be an instance of String') end context "when the actual object does not respond to #instance_of? method" do let(:klass) { Class.new { undef_method :instance_of? } } let(:actual_object) { klass.new } it "raises ArgumentError" do message = "The be_an_instance_of matcher requires that "\ "the actual object responds to #instance_of? method " \ "but a `NoMethodError` was encountered instead." expect { expect(actual_object).not_to send(method, klass) }.to raise_error ::ArgumentError, message end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/raise_error_spec.rb0000664000000000000000000004740614557700001031751 0ustar rootrootRSpec.describe "expect { ... }.to raise_error" do it_behaves_like "an RSpec block-only matcher" do def valid_block raise "boom" end def invalid_block end let(:matcher) { raise_error Exception } end it "passes if anything is raised" do expect { raise "error" }.to raise_error "error" end it "issues a warning when used without an error class or message" do expect_warning_with_call_site __FILE__, __LINE__+1, /without providing a specific error/ expect { raise }.to raise_error end it 'issues a warning that includes the current error when used without an error class or message' do expect_warning_with_call_site __FILE__, __LINE__+1, /Actual error raised was #/ expect { raise StandardError.new, 'boom' }.to raise_error end it "issues a warning when `nil` is passed for an error class" do expect_warning_with_call_site __FILE__, __LINE__+1, /with a `nil`/ expect { raise }.to raise_error(nil) end it "issues a warning when `nil` is passed for an error class when negated" do expect_warning_with_call_site __FILE__, __LINE__+1, /raise_error\(nil\)/ expect { '' }.not_to raise_error(nil) end it "issues a warning that does not include current error when it's not present" do expect(::Kernel).to receive(:warn) do |message| ex = /Actual error raised was/ expect(message).not_to match ex end expect { expect { '' }.to(raise_error) }.to fail_with("expected Exception but nothing was raised") end it "raises an exception when configured to do so" do begin RSpec::Expectations.configuration.on_potential_false_positives = :raise expect_no_warnings expect { expect { '' }.to raise_error }.to raise_error ArgumentError ensure RSpec::Expectations.configuration.on_potential_false_positives = :warn end end it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do RSpec::Expectations.configuration.warn_about_potential_false_positives = false expect_no_warnings expect { raise }.to raise_error end it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do RSpec::Expectations.configuration.on_potential_false_positives = :nothing expect_no_warnings expect { raise }.to raise_error end it 'does not issue a warning when an exception class is specified (even if it is just `Exception`)' do expect_no_warnings expect { raise "error" }.to raise_error Exception end it 'does not issue a warning when a message is specified' do expect_no_warnings expect { raise "error" }.to raise_error "error" end it 'does not issue a warning when a block is passed' do expect_no_warnings expect { raise "error" }.to raise_error { |_| } end it "passes if an error instance is expected" do s = StandardError.new expect { raise s }.to raise_error(s) end it 'passes if an error instance with a non string message is raised' do special_error = Class.new(StandardError) do def initialize(message) @message = message end def message self end def to_s @message end end s = special_error.new 'Stringlike' expect { raise s }.to raise_error('Stringlike') end it "fails if a different error instance is thrown from the one that is expected" do s = StandardError.new("Error 1") to_raise = StandardError.new("Error 2") expect do expect { raise to_raise }.to raise_error(s) end.to fail_with(Regexp.new("expected #{s.inspect}, got #{to_raise.inspect} with backtrace")) end it "passes if an error class is expected and an instance of that class is thrown" do s = StandardError.new :bees expect { raise s }.to raise_error(StandardError) end it "fails if nothing is raised" do expect { expect {}.to raise_error Exception }.to fail_with("expected Exception but nothing was raised") end end RSpec.describe "raise_exception aliased to raise_error" do it "passes if anything is raised" do expect { raise "exception" }.to raise_exception "exception" end end RSpec.describe "expect { ... }.to raise_error {|err| ... }" do it "passes if there is an error" do ran = false expect { non_existent_method }.to raise_error { |_e| ran = true } expect(ran).to be_truthy end it "passes the error to the block" do error = nil expect { non_existent_method }.to raise_error { |e| error = e } expect(error).to be_kind_of(NameError) end end RSpec.describe "expect { ... }.to raise_error do |err| ... end" do it "passes the error to the block" do error = nil expect { non_existent_method }.to raise_error do |e| error = e end expect(error).to be_kind_of(NameError) end end RSpec.describe "expect { ... }.to(raise_error { |err| ... }) do |err| ... end" do it "passes the error only to the block taken directly by #raise_error" do error_passed_to_curly = nil error_passed_to_do_end = nil expect { non_existent_method }.to(raise_error { |e| error_passed_to_curly = e }) do |e| error_passed_to_do_end = e end expect(error_passed_to_curly).to be_kind_of(NameError) expect(error_passed_to_do_end).to be_nil end end # rubocop:disable Style/RedundantException RSpec.describe "expect { ... }.not_to raise_error" do context "with a specific error class" do it "issues a warning" do expect_warning_with_call_site __FILE__, __LINE__+1, /risks false positives/ expect { "bees" }.not_to raise_error(RuntimeError) end it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do RSpec::Expectations.configuration.warn_about_potential_false_positives = false expect_no_warnings expect { "bees" }.not_to raise_error(RuntimeError) end end context "with no specific error class" do it "passes if nothing is raised" do expect {}.not_to raise_error end it "fails if anything is raised" do expect { expect { raise RuntimeError, "example message" }.not_to raise_error }.to fail_with(/expected no Exception, got #/) end it 'includes the backtrace of the error that was raised in the error message' do expect { expect { raise "boom" }.not_to raise_error }.to raise_error { |e| backtrace_line = "#{File.basename(__FILE__)}:#{__LINE__ - 2}" expect(e.message).to include("with backtrace", backtrace_line) } end it 'formats the backtrace using the configured backtrace formatter' do allow(RSpec::Matchers.configuration.backtrace_formatter). to receive(:format_backtrace). and_return("formatted-backtrace") expect { expect { raise "boom" }.not_to raise_error }.to raise_error { |e| expect(e.message).to include("with backtrace", "formatted-backtrace") } end end end RSpec.describe "expect { ... }.to raise_error(message)" do it "passes if RuntimeError is raised with the right message" do expect { raise 'blah' }.to raise_error('blah') end it "passes if RuntimeError is raised with a matching message" do expect { raise 'blah' }.to raise_error(/blah/) end it "passes if any other error is raised with the right message" do expect { raise NameError.new('blah') }.to raise_error('blah') end it "fails if RuntimeError error is raised with the wrong message" do expect do expect { raise 'blarg' }.to raise_error('blah') end.to fail_with(/expected Exception with \"blah\", got #/) end it "fails if any other error is raised with the wrong message" do expect do expect { raise NameError.new('blarg') }.to raise_error('blah') end.to fail_with(/expected Exception with \"blah\", got #/) end it "fails if any other error is raised with the wrong message" do expect do expect { raise NameError.new('blarg') }.to raise_error.with_message('blah') end.to fail_with(/expected Exception with \"blah\", got #/) end it "fails if another error is raised (NameError)" do expect { expect { load "non/existent/file" }.to raise_error(NameError) }.to fail_with(/expected NameError, got #/) end it "fails if correct error is raised with incorrect message" do expect { expect { raise RuntimeError.new("not the example message") }.to raise_error(RuntimeError, "example message") }.to fail_with(/expected RuntimeError with \"example message\", got #/) end it "fails if correct error is raised with incorrect message" do expect { expect { raise RuntimeError.new("not the example message") }.to raise_error(RuntimeError, /less than ample mess/) }.to fail_with(/expected RuntimeError with message matching \/less than ample mess\/, got #/) end end # rubocop:enable Style/RedundantException RSpec.describe "expect { ... }.not_to raise_error(NamedError, error_message) with Regexp" do it "issues a warning" do expect_warning_with_call_site __FILE__, __LINE__+1, /risks false positives/ expect {}.not_to raise_error(RuntimeError, /ample mess/) end it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do RSpec::Expectations.configuration.warn_about_potential_false_positives = false expect_no_warnings expect {}.not_to raise_error(RuntimeError, /ample mess/) end end RSpec.describe "expect { ... }.to raise_error(NamedError, error_message) { |err| ... }" do it "yields exception if named error is raised with same message" do ran = false expect { raise "example message" }.to raise_error(RuntimeError, "example message") { |err| ran = true expect(err.class).to eq RuntimeError expect(err.message).to eq "example message" } expect(ran).to be(true) end it "yielded block fails on it's own right" do ran, passed = false, false expect { expect { raise "example message" }.to raise_error(RuntimeError, "example message") { |_err| ran = true expect(5).to eq 4 passed = true } }.to fail_with(/expected: 4/m) expect(ran).to be_truthy expect(passed).to be_falsey end it "does NOT yield exception if no error was thrown" do ran = false expect { expect {}.to raise_error(RuntimeError, "example message") { |_err| ran = true } }.to fail_with(/expected RuntimeError with \"example message\" but nothing was raised/) expect(ran).to eq false end it "does not yield exception if error class is not matched" do ran = false expect { expect { raise "example message" }.to raise_error(SyntaxError, "example message") { |_err| ran = true } }.to fail_with(/expected SyntaxError with \"example message\", got #/) expect(ran).to eq false end it "does NOT yield exception if error message is not matched" do ran = false expect { expect { raise "example message" }.to raise_error(RuntimeError, "different message") { |_err| ran = true } }.to fail_with(/expected RuntimeError with \"different message\", got #/) expect(ran).to eq false end end RSpec.describe "expect { ... }.not_to raise_error(NamedError, error_message) { |err| ... }" do it "issues a warning" do expect_warning_with_call_site __FILE__, __LINE__+1, /risks false positives/ expect {}.not_to raise_error(RuntimeError, "example message") { |err| } end it "can supresses the warning when configured to do so", :warn_about_potential_false_positives do RSpec::Expectations.configuration.warn_about_potential_false_positives = false expect_no_warnings expect {}.not_to raise_error(RuntimeError, "example message") { |err| } end end RSpec.describe "Composing matchers with `raise_error`" do matcher :an_attribute do |attr| chain :equal_to do |value| @expected_value = value end match do |error| return false unless error.respond_to?(attr) error.__send__(attr) == @expected_value end end class FooError < StandardError def foo; :bar; end end describe "expect { }.to raise_error(matcher)" do it 'passes when the matcher matches the raised error' do expect { raise FooError }.to raise_error(an_attribute(:foo).equal_to(:bar)) end it 'passes when the matcher matches the exception message' do expect { raise FooError, "food" }.to raise_error(a_string_including("foo")) end it 'fails with a clear message when the matcher does not match the raised error' do expect { expect { raise FooError }.to raise_error(an_attribute(:foo).equal_to(3)) }.to fail_including("expected Exception with an attribute :foo equal to 3, got #") end it 'fails with a clear message when the matcher does not match the exception message' do expect { expect { raise FooError, "food" }.to raise_error(a_string_including("bar")) }.to fail_including('expected Exception with a string including "bar", got #&2") else system("printf #{msg} 1>&2") end end } end RSpec.describe "output.to_stdout_from_any_process matcher" do include_examples "output_to_stream", :stdout, :to_stdout_from_any_process, Module.new { def print_to_stream(msg) if RSpec::Support::OS.windows? system(" :a, :invalid_value => :b do let(:matcher) { equal(:a) } end def inspect_object(o) "#<#{o.class}:#{o.object_id}> => #{o.inspect}" end it "matches when actual.equal?(expected)" do expect(1).to equal(1) end it "does not match when !actual.equal?(expected)" do expect("1").not_to equal("1".dup) end it "describes itself" do matcher = equal(1) matcher.matches?(1) expect(matcher.description).to eq "equal 1" end context "when the expected object is falsey in conditional semantics" do it "describes itself with the expected object" do matcher = equal(nil) matcher.matches?(nil) expect(matcher.description).to eq "equal nil" end end context "when the expected object's #equal? always returns true" do let(:strange_string) do string = "foo".dup def string.equal?(_other) true end string end it "describes itself with the expected object" do matcher = equal(strange_string) matcher.matches?(strange_string) expect(matcher.description).to eq 'equal "foo"' end end context "the output for expected" do it "doesn't include extra object detail for `true`" do expected, actual = true, "1" expect { expect(actual).to equal(expected) }.to fail_with "\nexpected true\n got #{inspect_object(actual)}\n" end it "doesn't include extra object detail for `false`" do expected, actual = false, "1" expect { expect(actual).to equal(expected) }.to fail_with "\nexpected false\n got #{inspect_object(actual)}\n" end it "doesn't include extra object detail for `nil`" do expected, actual = nil, "1" expect { expect(actual).to equal(expected) }.to fail_with "\nexpected nil\n got #{inspect_object(actual)}\n" end end context "the output for actual" do it "doesn't include extra object detail for `true`" do expected, actual = true, false expect { expect(actual).to equal(expected) }.to fail_with "\nexpected true\n got false\n" end it "doesn't include extra object detail for `false`" do expected, actual = false, nil expect { expect(actual).to equal(expected) }.to fail_with "\nexpected false\n got nil\n" end it "doesn't include extra object detail for `nil`" do expected, actual = nil, false expect { expect(actual).to equal(expected) }.to fail_with "\nexpected nil\n got false\n" end end it "suggests the `eq` matcher on failure" do expected, actual = "1", "1".dup expect { expect(actual).to equal(expected) }.to fail_with <<-MESSAGE expected #{inspect_object(expected)} got #{inspect_object(actual)} Compared using equal?, which compares object identity, but expected and actual are not the same object. Use `expect(actual).to eq(expected)` if you don't care about object identity in this example. MESSAGE end it "provides message on #negative_failure_message" do expected = actual = "1" matcher = equal(expected) matcher.matches?(actual) expect(matcher.failure_message_when_negated).to eq <<-MESSAGE expected not #{inspect_object(expected)} got #{inspect_object(actual)} Compared using equal?, which compares object identity. MESSAGE end end end end ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/have_attributes_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/have_attributes_spec.0000664000000000000000000002061214557700001032270 0ustar rootrootRSpec.describe "#have_attributes matcher" do include RSpec::Support::Spec::DiffHelpers Person = Struct.new(:name, :age) class Person def parent(parent_name) @parent = parent_name end end # This simulates a behaviour of Rails, see #1162. class DynamicAttributes def initialize(attributes) @attributes = attributes end def method_missing(name, *args, &block) @attributes[name] || super end def respond_to?(method_name) @attributes.keys.include?(method_name) || super end end let(:wrong_name) { "Wrong Name" } let(:wrong_age) { 11 } let(:correct_name) { "Correct name" } let(:correct_age) { 33 } let(:person) { Person.new(correct_name, correct_age) } it "is diffable" do expect(have_attributes(:age => correct_age)).to be_diffable end describe "expect(...).to have_attributes(with_one_attribute)" do it_behaves_like "an RSpec value matcher", :valid_value => Person.new("Correct name", 33), :invalid_value => Person.new("Wrong Name", 11) do let(:matcher) { have_attributes(:name => "Correct name") } end it "passes if target has the provided attributes" do expect(person).to have_attributes(:name => correct_name) end it "passes if target responds to :sym but does not implement method" do expect(DynamicAttributes.new(:name => "value")).to have_attributes(:name => "value") end it "fails if target does not have any of the expected attributes" do expect { expect(person).to have_attributes(:name => wrong_name) }.to fail_with(%r|expected #{object_inspect person} to have attributes #{hash_inspect :name => wrong_name} but had attributes #{hash_inspect :name => correct_name }|) end it "fails with correct message if object manipulates its data" do counter = Class.new do def initialize; @count = 1; end def count @count += 1 end end.new expect { expect(counter).to have_attributes(:count => 1) }.to fail_with(%r|to have attributes #{hash_inspect :count => 1} but had attributes #{hash_inspect :count => 2 }|) end it 'diffs the attributes received with those expected' do allow(RSpec::Matchers.configuration).to receive_messages(:color? => false) expected_diff = dedent(<<-EOS) |@@ #{one_line_header} @@ |-:name => "Wrong Name", |+:name => "Correct name", EOS expect { expect(person).to have_attributes(:name => wrong_name) }.to fail_including(expected_diff) end it "fails if target does not responds to any of the attributes" do expect { expect(person).to have_attributes(:color => 'red') }.to fail_including("expected #{object_inspect person} to respond to :color") end it "doesn't produce a diff if the target fails the respond to check" do expect { expect(person).to have_attributes(:color => 'red') }.to fail_with(a_string_excluding "Diff") end it "fails if target responds to the attribute but requires arguments" do expect { expect(person).to have_attributes(:parent => 'Billy') }.to fail_including("expected #{object_inspect person} to respond to :parent with 0 arguments") end describe "expect(...).to have_attributes(key => matcher)" do it "passes when the matchers match" do expect(person).to have_attributes(:age => (a_value > 30)) end it 'provides a description' do description = have_attributes(:age => (a_value > 30)).description expect(description).to eq("have attributes {:age => (a value > 30)}") end it "fails with a clear message when the matcher does not match" do expect { expect(person).to have_attributes(:age => (a_value < 10)) }.to fail_including("expected #{object_inspect person} to have attributes {:age => (a value < 10)}") end end end describe "expect(...).to_not have_attributes(with_one_attribute)" do it "passes if target does not have any of the expected attributes" do expect(person).to_not have_attributes(:age => wrong_age) end it "fails if target has all of the expected attributes" do expect { expect(person).to_not have_attributes(:age => correct_age) }.to fail_with(%r|expected #{object_inspect person} not to have attributes #{hash_inspect :age => correct_age}|) end it "doesn't produce a diff" do expect { expect(person).to_not have_attributes(:age => correct_age) }.to fail_with(a_string_excluding "Diff") end it "fails if target does not responds to any of the attributes" do expect { expect(person).to_not have_attributes(:color => 'red') }.to fail_including("expected #{object_inspect person} to respond to :color") end it "fails if target responds to the attribute but requires arguments" do expect { expect(person).to_not have_attributes(:parent => 'Billy') }.to fail_including("expected #{object_inspect person} to respond to :parent with 0 arguments") end end describe "expect(...).to have_attributes(with_multiple_attributes)" do it_behaves_like "an RSpec value matcher", :valid_value => Person.new("Correct name", 33), :invalid_value => Person.new("Wrong Name", 11) do let(:matcher) { have_attributes(:name => "Correct name", :age => 33) } end it "passes if target has the provided attributes" do expect(person).to have_attributes(:name => correct_name, :age => correct_age) end it "fails if target does not have any of the expected attributes" do expect { expect(person).to have_attributes(:name => correct_name, :age => wrong_age) }.to fail_with(%r|expected #{object_inspect person} to have attributes #{hash_inspect :age => wrong_age, :name => correct_name }|) end it 'diffs the attributes received with those expected' do allow(RSpec::Matchers.configuration).to receive_messages(:color? => false) expected_diff = dedent(<<-EOS) |@@ #{one_line_header(3)} @@ |-:age => 11, |+:age => 33, EOS expected_diff << "\n :name => \"Correct name\",\n" if Diff::LCS::VERSION.to_f < 1.4 expect { expect(person).to have_attributes(:name => correct_name, :age => wrong_age) }.to fail_including(expected_diff) end it "fails if target does not responds to any of the attributes" do expect { expect(person).to have_attributes(:name => correct_name, :color => 'red') }.to fail_including("expected #{object_inspect person} to respond to :color") end it "fails if target responds to the attribute but requires arguments" do expect { expect(person).to have_attributes(:name => correct_name, :parent => 'Billy') }.to fail_including("expected #{object_inspect person} to respond to :parent with 0 arguments") end end describe "expect(...).to_not have_attributes(with_multiple_attributes)" do it "passes if target has none of the expected attributes" do expect(person).to_not have_attributes(:name => wrong_name, :age => wrong_age) end it "fails if target has any of the expected attributes" do expect { expect(person).to_not have_attributes(:name => wrong_name, :age => correct_age) }.to fail_with(%r|expected #{object_inspect person} not to have attributes #{hash_inspect :age => correct_age, :name => wrong_name }|) end it "fails if target has all of the expected attributes" do expect { expect(person).to_not have_attributes(:name => correct_name, :age => correct_age) }.to fail_with(%r|expected #{object_inspect person} not to have attributes #{hash_inspect :age => correct_age, :name => correct_name }|) end it "fails if target does not responds to any of the attributes" do expect { expect(person).to_not have_attributes(:name => correct_name, :color => 'red') }.to fail_including("expected #{object_inspect person} to respond to :color") end it "fails if target responds to the attribute but requires arguments" do expect { expect(person).to_not have_attributes(:name => correct_name, :parent => 'Billy') }.to fail_including("expected #{object_inspect person} to respond to :parent with 0 arguments") end end include RSpec::Matchers::Composable # a helper for failure message assertion def object_inspect(object) surface_descriptions_in object.inspect end end ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/contain_exactly_spec.rbruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/contain_exactly_spec.0000664000000000000000000004746414557700001032301 0ustar rootrootclass UnsortableObject def initialize(id) @id = id end def inspect @id.to_s end def ==(_other) false end end # AR::Relation is meant to act like a collection, but does # not include `Enumerable`. It does implement `to_ary`. class FakeActiveRecordRelation def initialize(records) @records = records end def to_ary @records end end RSpec.describe "should =~ array", :uses_should do it "passes a valid positive expectation" do [1, 2].should =~ [2, 1] end it "fails an invalid positive expectation" do expect { [1, 2, 3].should =~ [2, 1] }.to fail_with(/expected collection contained/) end context "when the array defines a `=~` method" do it 'delegates to that method rather than using the contain_exactly matcher' do array = [] def array.=~(other) other == :foo end array.should =~ :foo expect { array.should =~ :bar }.to fail_with(/expected: :bar/) end end context 'when the array defines a `send` method' do it 'still works' do array = [1, 2] def array.send; :sent; end array.should =~ array end end context "when the array undefines `=~`" do it 'still works' do array_klass = Class.new(Array) { undef =~ if respond_to?(:=~) } array = array_klass.new([1, 2]) array.should =~ [1, 2] expect { array.should =~ [0, 1, 2] }.to fail_with(/expected collection contained/) end end end RSpec.describe "should_not =~ [:with, :multiple, :args]", :uses_should do it "fails when the arrays match" do expect { [1, 2, 3].should_not =~ [1, 2, 3] }.to fail_with "expected [1, 2, 3] not to contain exactly 1, 2, and 3" end it "fails when the arrays match in a different order" do expect { [1, 3, 2].should_not =~ [1, 2, 3] }.to fail_with "expected [1, 3, 2] not to contain exactly 1, 2, and 3" end it "passes when there are extra elements in the array" do [1, 3].should_not =~ [1, 2, 3] end it "passes when there are elements missing from the array" do [1, 2, 3, 4].should_not =~ [1, 2, 3] end end RSpec.describe "using contain_exactly with expect" do it "passes a valid positive expectation" do expect([1, 2]).to contain_exactly(2, 1) end it "fails an invalid positive expectation" do expect { expect([1, 2, 3]).to contain_exactly(2, 1) }.to fail_with(/expected collection contained/) end it "passes for an out of order valid positive expectation with hashes" do expect([ { :a => 10 }, { :a => -10 } ]).to contain_exactly( { :a => (a_value < 0) }, { :a => (a_value > 0) } ) end it "passes for an in order valid positive expectation with hashes" do expect([ { :a => 10 }, { :a => -10 } ]).to contain_exactly( { :a => (a_value > 0) }, { :a => (a_value < 0) } ) end it 'works with strict test doubles (which have not defined `<=>`)' do dbl_1 = double("1") dbl_2 = double("2") expect([dbl_1, dbl_2]).to contain_exactly(dbl_2, dbl_1) expect { expect([dbl_1, dbl_2]).to contain_exactly(dbl_1) }.to fail end it "does not support strings (which have no standard way to be enumerated: bytes, chars or lines)" do expect { expect("abcd").to contain_exactly("d", "c", "a", "b") }.to fail_with('expected a collection that can be converted to an array with `#to_ary` or `#to_a`, but got "abcd"') end it "supports ranges" do expect(1..3).to contain_exactly(1, 2, 3) end end RSpec.describe "expect(array).to contain_exactly(*other_array)" do it_behaves_like "an RSpec value matcher", :valid_value => [1, 2], :invalid_value => [1] do let(:matcher) { contain_exactly(2, 1) } end it 'is also exposed as `match_array` (with unsplatted args)' do expect([1, 2, 3]).to match_array([3, 2, 1]) end it "passes if target contains all items" do expect([1, 2, 3]).to contain_exactly(1, 2, 3) end it "passes if target contains all items out of order" do expect([1, 3, 2]).to contain_exactly(1, 2, 3) end it 'fails if the expected array is empty and the actual array is non-empty' do expect { expect([1]).to contain_exactly # no arguments passed to the matcher }.to fail_with(<<-MESSAGE) expected collection contained: [] actual collection contained: [1] the extra elements were: [1] MESSAGE end it 'fails if the actual array is empty and the expected array is non-empty' do expect { expect([]).to contain_exactly(1) }.to fail_with(<<-MESSAGE) expected collection contained: [1] actual collection contained: [] the missing elements were: [1] MESSAGE end def timeout_if_not_debugging(time) in_sub_process_if_possible do require 'timeout' return yield if defined?(::Debugger) Timeout.timeout(time) { yield } end end it 'fails a match of 11 items with duplicates in a reasonable amount of time' do timeout_if_not_debugging(0.1) do expected = [0, 1, 1, 3, 3, 3, 4, 4, 8, 8, 9 ] actual = [ 1, 2, 3, 3, 3, 3, 7, 8, 8, 9, 9] expect { expect(actual).to contain_exactly(*expected) }.to fail_including("the missing elements were: [0, 1, 4, 4]") end end it "fails if target includes extra items" do expect { expect([1, 2, 3, 4]).to contain_exactly(1, 2, 3) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 2, 3] actual collection contained: [1, 2, 3, 4] the extra elements were: [4] MESSAGE end it "fails if target is missing items" do expect { expect([1, 2]).to contain_exactly(1, 2, 3) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 2, 3] actual collection contained: [1, 2] the missing elements were: [3] MESSAGE end it "fails if target is missing items and has extra items" do expect { expect([1, 2, 4]).to contain_exactly(1, 2, 3) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 2, 3] actual collection contained: [1, 2, 4] the missing elements were: [3] the extra elements were: [4] MESSAGE end it "sorts items in the error message if they all respond to <=>" do expect { expect([6, 2, 1, 5]).to contain_exactly(4, 1, 2, 3) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 2, 3, 4] actual collection contained: [1, 2, 5, 6] the missing elements were: [3, 4] the extra elements were: [5, 6] MESSAGE end it "does not sort items in the error message if they don't all respond to <=>" do expect { expect([UnsortableObject.new(2), UnsortableObject.new(1)]).to contain_exactly(UnsortableObject.new(4), UnsortableObject.new(3)) }.to fail_with(<<-MESSAGE) expected collection contained: [4, 3] actual collection contained: [2, 1] the missing elements were: [4, 3] the extra elements were: [2, 1] MESSAGE end it "accurately reports extra elements when there are duplicates" do expect { expect([1, 1, 1, 5]).to contain_exactly(1, 5) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 5] actual collection contained: [1, 1, 1, 5] the extra elements were: [1, 1] MESSAGE end it "accurately reports missing elements when there are duplicates" do expect { expect([1, 5]).to contain_exactly(1, 1, 5) }.to fail_with(<<-MESSAGE) expected collection contained: [1, 1, 5] actual collection contained: [1, 5] the missing elements were: [1] MESSAGE end end RSpec.describe "expect(...).not_to contain_exactly(:with, :multiple, :args)" do it "fails when the arrays match" do expect { expect([1, 2, 3]).not_to contain_exactly(1, 2, 3) }.to fail_with "expected [1, 2, 3] not to contain exactly 1, 2, and 3" end it "fails when the arrays match in a different order" do expect { expect([1, 3, 2]).not_to contain_exactly(1, 2, 3) }.to fail_with "expected [1, 3, 2] not to contain exactly 1, 2, and 3" end it "passes when there are extra elements in the array" do expect([1, 3]).not_to contain_exactly(1, 2, 3) end it "passes when there are elements missing from the array" do expect([1, 2, 3, 4]).not_to contain_exactly(1, 2, 3) end end RSpec.describe "matching against things that aren't arrays" do it "fails with nil and the expected error message is given" do expect { expect(nil).to contain_exactly(1, 2, 3) }.to fail_with(/expected a collection/) end it "fails with a float and the expected error message is given" do expect { expect(3.7).to contain_exactly(1, 2, 3) }.to fail_with(/expected a collection/) end it "fails with a string and the expected error message is given" do expect { expect("I like turtles").to contain_exactly(1, 2, 3) }.to fail_with(/expected a collection/) end it 'works with other collection objects' do in_sub_process_if_possible do require 'set' expect(Set.new([3, 2, 1])).to contain_exactly(1, 2, 3) expect { expect(Set.new([3, 2, 1])).to contain_exactly(1, 2) }.to fail_including("expected collection contained: [1, 2]") end end it 'works with non-enumerables that implement `to_ary`' do relation = FakeActiveRecordRelation.new([1, 2, 3]) expect(relation).to contain_exactly(2, 1, 3) expect { expect(relation).to contain_exactly(1, 2) }.to fail_including("expected collection contained: [1, 2]") end end RSpec.describe "Composing `contain_exactly` with other matchers" do context "when it is compared to multiple possible matches" do it 'works properly when passed as an argument in its aliased form' do expect([[1, 3], ["food", "barn"]]).to include( a_collection_containing_exactly(/foo/, /bar/) ) end end describe "expect(...).to contain_exactly(matcher, matcher)" do it 'passes when the array matches the matchers in the same order' do expect(["food", "barn"]).to contain_exactly( a_string_matching(/foo/), a_string_matching(/bar/) ) end it 'passes when the array matches the matchers in a different order' do expect(["food", "barn"]).to contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/) ) end it 'fails with a useful message when there is an extra element' do expect { expect(["food", "barn", "goo"]).to contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/) ) }.to fail_with(dedent <<-EOS) |expected collection contained: [(a string matching /bar/), (a string matching /foo/)] |actual collection contained: ["barn", "food", "goo"] |the extra elements were: ["goo"] | EOS end it 'fails with a useful message when there is a missing element' do expect { expect(["food", "barn"]).to contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/), a_string_matching(/goo/) ) }.to fail_with(dedent <<-EOS) |expected collection contained: [(a string matching /bar/), (a string matching /foo/), (a string matching /goo/)] |actual collection contained: ["barn", "food"] |the missing elements were: [(a string matching /goo/)] | EOS end it 'pairs up the items in order to minimize the number of unpaired items' do expect { expect(["fool", "food", "good"]).to contain_exactly(/foo/, /fool/, /poo/) }.to fail_with(dedent <<-EOS) |expected collection contained: [/foo/, /fool/, /poo/] |actual collection contained: ["food", "fool", "good"] |the missing elements were: [/poo/] |the extra elements were: ["good"] | EOS end it 'provides a description' do description = contain_exactly(a_string_matching(/bar/), a_string_matching(/foo/)).description expect(description).to eq("contain exactly (a string matching /bar/) and (a string matching /foo/)") end context 'when an earlier matcher matches more strictly than a later matcher' do it 'works when the actual items match in the same order' do expect(["food", "fool"]).to contain_exactly(a_string_matching(/foo/), a_string_matching(/fool/)) end it 'works when the actual items match in reverse order' do expect(["fool", "food"]).to contain_exactly(a_string_matching(/foo/), a_string_matching(/fool/)) end it 'can handle multiple sets of overlapping matches' do expect(["fool", "barn", "bare", "food"]).to contain_exactly( a_string_matching(/bar/), a_string_matching(/barn/), a_string_matching(/foo/), a_string_matching(/fool/) ) end end it "can use `a_value_within` and `a_string_starting_with` against multiple types of values" do expect(["barn", 2.45]).to contain_exactly( a_value_within(0.1).of(2.5), a_string_starting_with("bar") ) end context 'when a later matcher matches more strictly than an earlier matcher' do it 'works when the actual items match in the same order' do expect(["fool", "food"]).to contain_exactly(a_string_matching(/fool/), a_string_matching(/foo/)) end it 'works when the actual items match in reverse order' do expect(["food", "fool"]).to contain_exactly(a_string_matching(/fool/), a_string_matching(/foo/)) end end end describe "expect(...).to_not contain_exactly(matcher, matcher)" do it 'fails when the array matches the matchers' do expect { expect(["food", "barn"]).to_not contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/) ) }.to fail_with 'expected ["food", "barn"] not to contain exactly '\ "(a string matching /bar/) and (a string matching /foo/)" end it 'passes when there is an extra element' do expect(["food", "barn", "goo"]).to_not contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/) ) end it 'passes when there is a missing element' do expect(["food", "barn"]).to_not contain_exactly( a_string_matching(/bar/), a_string_matching(/foo/), a_string_matching(/goo/) ) end end end RSpec.describe "Reusing a matcher that memoizes state" do require "rspec/matchers/fail_matchers" it "works properly in spite of the memoization" do matcher = contain_exactly(eq(1)) expect { expect([2]).to matcher }.to fail_including(<<-MESSAGE) expected collection contained: [(eq 1)] actual collection contained: [2] the missing elements were: [(eq 1)] the extra elements were: [2] MESSAGE expect { expect([3]).to matcher }.to fail_including(<<-MESSAGE) expected collection contained: [(eq 1)] actual collection contained: [3] the missing elements were: [(eq 1)] the extra elements were: [3] MESSAGE end end module RSpec module Matchers module BuiltIn class ContainExactly RSpec.describe PairingsMaximizer do it 'finds unmatched expected indexes' do maximizer = PairingsMaximizer.new({ 0 => [], 1 => [0] }, { 0 => [1] }) expect(maximizer.solution.unmatched_expected_indexes).to eq([0]) end it 'finds unmatched actual indexes' do maximizer = PairingsMaximizer.new({ 0 => [0] }, { 0 => [0], 1 => [] }) expect(maximizer.solution.unmatched_actual_indexes).to eq([1]) end describe "finding indeterminate indexes" do it 'does not include unmatched indexes' do maximizer = PairingsMaximizer.new({ 0 => [], 1 => [0] }, { 0 => [1], 1 => [] }) expect(maximizer.solution.indeterminate_expected_indexes).not_to include(0) expect(maximizer.solution.indeterminate_actual_indexes).not_to include(1) end it 'does not include indexes that are reciprocally to exactly one index' do maximizer = PairingsMaximizer.new({ 0 => [], 1 => [0] }, { 0 => [1], 1 => [0] }) expect(maximizer.solution.indeterminate_expected_indexes).not_to include(1) expect(maximizer.solution.indeterminate_actual_indexes).not_to include(0) end it 'includes indexes that have multiple matches' do maximizer = PairingsMaximizer.new({ 0 => [0, 2], 1 => [0, 2], 2 => [] }, { 0 => [0, 1], 1 => [], 2 => [0, 1] }) expect(maximizer.solution.indeterminate_expected_indexes).to include(0, 1) expect(maximizer.solution.indeterminate_actual_indexes).to include(0, 2) end it 'includes indexes that have one match which has multiple matches' do maximizer = PairingsMaximizer.new({ 0 => [0], 1 => [0], 2 => [1, 2] }, { 0 => [0, 1], 1 => [2], 2 => [2] }) expect(maximizer.solution.indeterminate_expected_indexes).to include(0, 1) expect(maximizer.solution.indeterminate_actual_indexes).to include(1, 2) end end describe "#unmatched_item_count" do it 'returns the count of unmatched items' do maximizer = PairingsMaximizer.new({ 0 => [1], 1 => [0] }, { 0 => [1], 1 => [0] }) expect(maximizer.solution.unmatched_item_count).to eq(0) maximizer = PairingsMaximizer.new({ 0 => [1], 1 => [0] }, { 0 => [1], 1 => [0], 2 => [] }) expect(maximizer.solution.unmatched_item_count).to eq(1) end end describe "#find_best_solution" do matcher :produce_result do |unmatched_expected, unmatched_actual| match do |result| result.candidate? && result.unmatched_expected_indexes == unmatched_expected && result.unmatched_actual_indexes == unmatched_actual end failure_message do |result| if result.candidate_result? "expected a complete solution, but still had indeterminate indexes: " \ "expected: #{result.indeterminate_expected_indexes.inspect}; " \ "actual: #{result.indeterminate_actual_indexes.inspect}" elsif result.unmatched_expected_indexes != unmatched_expected "expected unmatched_expected_indexes: #{unmatched_expected.inspect} " \ "but got: #{result.unmatched_expected_indexes.inspect}" elsif result.unmatched_actual_indexes != unmatched_actual "expected unmatched_actual_indexes: #{unmatched_actual.inspect} " \ "but got: #{result.unmatched_actual_indexes.inspect}" end end end it 'returns no unmatched indexes when everything reciprocally matches one item' do maximizer = PairingsMaximizer.new({ 0 => [1], 1 => [0] }, { 0 => [1], 1 => [0] }) expect(maximizer.find_best_solution).to produce_result([], []) end it 'returns unmatched indexes for everything that has no matches' do maximizer = PairingsMaximizer.new({ 0 => [], 1 => [0] }, { 0 => [1], 1 => [] }) expect(maximizer.find_best_solution).to produce_result([0], [1]) end it 'searches the solution space for a perfectly matching solution' do maximizer = PairingsMaximizer.new({ 0 => [0, 1], 1 => [0] }, { 0 => [0, 1], 1 => [0] }) expect(maximizer.find_best_solution).to produce_result([], []) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_kind_of_spec.rb0000664000000000000000000000645514557700001031513 0ustar rootrootmodule RSpec module Matchers [:be_a_kind_of, :be_kind_of].each do |method| RSpec.describe "expect(actual).to #{method}(expected)" do it_behaves_like "an RSpec value matcher", :valid_value => 5, :invalid_value => "a" do let(:matcher) { send(method, Integer) } end it "passes if actual is instance of expected class" do expect("string").to send(method, String) end it "passes if actual is instance of subclass of expected class" do expect(5).to send(method, Numeric) end it "fails with failure message for should unless actual is kind of expected class" do expect { expect("foo").to send(method, Array) }.to fail_with('expected "foo" to be a kind of Array') end it "provides a description" do matcher = be_a_kind_of(String) matcher.matches?("this") expect(matcher.description).to eq "be a kind of String" end context "when the actual object does not respond to #kind_of? method" do let(:actual_object) do Class.new { undef_method :kind_of? }.new end it "raises ArgumentError" do message = "The be_a_kind_of matcher requires that " \ "the actual object responds to #kind_of? method " \ "but a `NoMethodError` was encountered instead." expect { expect(actual_object).to send(method, actual_object.class) }.to raise_error ::ArgumentError, message expect { expect(actual_object).to send(method, Object) }.to raise_error ::ArgumentError, message end end context "when the actual object does not respond to #is_a? method" do let(:actual_object) do Class.new { undef_method :is_a? }.new end it "provides correct result" do expect(actual_object).to send(method, actual_object.class) expect(actual_object).to send(method, Object) end end end RSpec.describe "expect(actual).not_to #{method}(expected)" do it "fails with failure message for should_not if actual is kind of expected class" do expect { expect("foo").not_to send(method, String) }.to fail_with('expected "foo" not to be a kind of String') end context "when the actual object does not respond to #kind_of? method" do let(:actual_object) do Class.new { undef_method :kind_of? }.new end it "raises ArgumentError" do message = "The be_a_kind_of matcher requires that " \ "the actual object responds to #kind_of? method " \ "but a `NoMethodError` was encountered instead." expect { expect(actual_object).not_to send(method, String) }.to raise_error ArgumentError, message end end context "when the actual object does not respond to #is_a? method" do let(:actual_object) do Class.new { undef_method :is_a? }.new end it "provides correct result" do expect(actual_object).not_to send(method, String) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/captures_spec.rb0000664000000000000000000000622514557700001031255 0ustar rootrootRSpec.describe "expect(regex).to match(string).with_captures" do context "with a string target" do it "does match a regex with a missing capture" do expect("a123a").to match(/(a)(b)?/).with_captures("a", nil) end it "does not match a regex with an incorrect match" do expect("a123a").not_to match(/(a)/).with_captures("b") end it "matches a regex without named captures" do expect("a123a").to match(/(a)/).with_captures("a") end it "uses the match description if the regex doesn't match" do expect { expect(/(a)/).to match("123").with_captures }.to fail_with(/expected \/\(a\)\/ to match "123"/) end if RUBY_VERSION != "1.8.7" it "matches a regex with named captures" do expect("a123a").to match(Regexp.new("(?123)")).with_captures(:num => "123") end it "matches a regex with a nested matcher" do expect("a123a").to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) end it "does not match a regex with an incorrect named group match" do expect("a123a").not_to match(Regexp.new("(?a)")).with_captures(:name => "b") end it "has a sensible failure description with a hash including matcher" do expect { expect("a123a").not_to match(Regexp.new("(?123)(asdf)?")).with_captures(a_hash_including(:num => "123")) }.to fail_with(/num => "123"/) end it "matches named captures when not passing a hash" do expect("a123a").to match(Regexp.new("(?123)")).with_captures("123") end end end context "with a regex target" do it "does match a regex with a missing capture" do expect(/(a)(b)?/).to match("a123a").with_captures("a", nil) end it "does not match a regex with an incorrect match" do expect(/(a)/).not_to match("a123a").with_captures("b") end it "matches a regex without named captures" do expect(/(a)/).to match("a123a").with_captures("a") end it "uses the match description if the regex doesn't match" do expect { expect(/(a)/).to match("123").with_captures }.to fail_with(/expected \/\(a\)\/ to match "123"/) end if RUBY_VERSION != "1.8.7" it "matches a regex with named captures" do expect(Regexp.new("(?123)")).to match("a123a").with_captures(:num => "123") end it "matches a regex with a nested matcher" do expect(Regexp.new("(?123)(asdf)?")).to match("a123a").with_captures(a_hash_including(:num => "123")) end it "does not match a regex with an incorrect named group match" do expect(Regexp.new("(?a)")).not_to match("a123a").with_captures(:name => "b") end it "has a sensible failure description with a hash including matcher" do expect { expect(Regexp.new("(?123)(asdf)?")).not_to match("a123a").with_captures(a_hash_including(:num => "123")) }.to fail_with(/num => "123"/) end it "matches named captures when not passing a hash" do expect(Regexp.new("(?123)")).to match("a123a").with_captures("123") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/built_in/be_between_spec.rb0000664000000000000000000001161614557700001031526 0ustar rootrootmodule RSpec::Matchers::BuiltIn RSpec.describe BeBetween do class SizeMatters include Comparable attr_reader :str def <=>(other) str.size <=> other.str.size end def initialize(str) @str = str end def inspect @str end end shared_examples "be_between" do |mode| it "passes if target is between min and max" do expect(5).to matcher(1, 10) end it "fails if target is not between min and max" do expect { # It does not go to 11 expect(11).to matcher(1, 10) }.to fail_with("expected 11 to be between 1 and 10 (#{mode})") end it "works with strings" do expect("baz").to matcher("bar", "foo") expect { expect("foo").to matcher("bar", "baz") }.to fail_with("expected \"foo\" to be between \"bar\" and \"baz\" (#{mode})") end it "works with other Comparable objects" do expect(SizeMatters.new("--")).to matcher(SizeMatters.new("-"), SizeMatters.new("---")) expect { expect(SizeMatters.new("---")).to matcher(SizeMatters.new("-"), SizeMatters.new("--")) }.to fail_with("expected --- to be between - and -- (#{mode})") end end shared_examples "not_to be_between" do |mode| it "passes if target is not between min and max" do expect(11).not_to matcher(1, 10) end it "fails if target is between min and max" do expect { expect(5).not_to matcher(1, 10) }.to fail_with("expected 5 not to be between 1 and 10 (#{mode})") end end shared_examples "composing with other matchers" do |mode| it "passes when the matchers both match" do expect([nil, 3]).to include(matcher(2, 4), a_nil_value) end it "works with mixed types" do expect(["baz", Math::PI]).to include(matcher(3.1, 3.2), matcher("bar", "foo")) expect { expect(["baz", 2.14]).to include(matcher(3.1, 3.2), matcher("bar", "foo") ) }.to fail_with("expected [\"baz\", 2.14] to include (a value between 3.1 and 3.2 (#{mode}))") end it "provides a description" do description = include(matcher(2, 4), an_instance_of(Float)).description expect(description).to eq("include (a value between 2 and 4 (#{mode})) and (an instance of Float)") end it "fails with a clear error message when the matchers do not match" do expect { expect([nil, 1]).to include(matcher(2, 4), a_nil_value) }.to fail_with("expected [nil, 1] to include (a value between 2 and 4 (#{mode}))") end end it_behaves_like "an RSpec value matcher", :valid_value => (10), :invalid_value => (11) do let(:matcher) { be_between(1, 10) } end describe "expect(...).to be_between(min, max) (inclusive)" do it_behaves_like "be_between", :inclusive do def matcher(min, max) be_between(min, max) end end it "is inclusive" do expect(1).to be_between(1, 10) expect(10).to be_between(1, 10) end it "indicates it was not comparable if it does not respond to `<=` and `>=`" do expect { expect(nil).to be_between(0, 10) }.to fail_with("expected nil to be between 0 and 10 (inclusive), but it does not respond to `<=` and `>=`") end end describe "expect(...).to be_between(min, max) (exclusive)" do it_behaves_like "be_between", :exclusive do def matcher(min, max) be_between(min, max).exclusive end end it "indicates it was not comparable if it does not respond to `<` and `>`" do expect { expect(nil).to be_between(0, 10).exclusive }.to fail_with("expected nil to be between 0 and 10 (exclusive), but it does not respond to `<` and `>`") end it "is exclusive" do expect { expect(1).to be_between(1, 10).exclusive }.to fail expect { expect(10).to be_between(1, 10).exclusive }.to fail end end describe "expect(...).not_to be_between(min, max) (inclusive)" do it_behaves_like "not_to be_between", :inclusive do def matcher(min, max) be_between(min, max) end end end describe "expect(...).not_to be_between(min, max) (exclusive)" do it_behaves_like "not_to be_between", :exclusive do def matcher(min, max) be_between(min, max).exclusive end end end describe "composing with other matchers (inclusive)" do it_behaves_like "composing with other matchers", :inclusive do def matcher(min, max) a_value_between(min, max) end end end describe "composing with other matchers (exclusive)" do it_behaves_like "composing with other matchers", :exclusive do def matcher(min, max) a_value_between(min, max).exclusive end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/aliased_matcher_spec.rb0000664000000000000000000001173214557700001030726 0ustar rootrootmodule RSpec module Matchers RSpec.describe AliasedMatcher do RSpec::Matchers.define :my_base_matcher do match { |actual| actual == foo } def foo 13 end def description "my base matcher description" end end RSpec::Matchers.alias_matcher :alias_of_my_base_matcher, :my_base_matcher it_behaves_like "an RSpec value matcher", :valid_value => 13, :invalid_value => nil do let(:matcher) { alias_of_my_base_matcher } end shared_examples "making a copy" do |copy_method| context "when making a copy via `#{copy_method}`" do it "uses a copy of the base matcher" do base_matcher = include(3) aliased = AliasedMatcher.new(base_matcher, Proc.new {}) copy = aliased.__send__(copy_method) expect(copy).not_to equal(aliased) expect(copy.base_matcher).not_to equal(base_matcher) expect(copy.base_matcher).to be_a(RSpec::Matchers::BuiltIn::Include) expect(copy.base_matcher.expected).to eq([3]) end it "copies custom matchers properly so they can work even though they have singleton behavior" do base_matcher = my_base_matcher aliased = AliasedMatcher.new(base_matcher, Proc.new { |a| a }) copy = aliased.__send__(copy_method) expect(copy).not_to equal(aliased) expect(copy.base_matcher).not_to equal(base_matcher) expect(13).to copy expect { expect(15).to copy }.to fail_with(/expected 15/) end end end include_examples "making a copy", :dup include_examples "making a copy", :clone it 'can get a method object for delegated methods', :if => (RUBY_VERSION.to_f > 1.8) do matcher = my_base_matcher decorated = AliasedMatcher.new(matcher, Proc.new {}) expect(decorated.method(:foo).call).to eq(13) end it 'can get a method object for `description`' do matcher = my_base_matcher decorated = AliasedMatcher.new(matcher, Proc.new { "overridden description" }) expect(decorated.method(:description).call).to eq("overridden description") end RSpec::Matchers.alias_matcher :my_overridden_matcher, :my_base_matcher do |desc| desc + " (overridden)" end it 'overrides the description with the provided block' do matcher = my_overridden_matcher expect(matcher.description).to eq("my base matcher description (overridden)") end RSpec::Matchers.alias_matcher :my_blockless_override, :my_base_matcher it 'provides a default description override based on the old and new games' do matcher = my_blockless_override expect(matcher.description).to eq("my blockless override description") end it 'works properly with a chained method off a negated matcher' do expect {}.to avoid_outputting.to_stdout expect { expect { $stdout.puts "a" }.to avoid_outputting.to_stdout }.to fail end if RSpec::Support::RubyFeatures.kw_args_supported? eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 class MyKeywordMatcher def initialize(**kwargs); end def matches?(other); true === other; end end RUBY if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 def my_keyword_matcher(...) = MyKeywordMatcher.new(...) RUBY else eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 def my_keyword_matcher(**kw); MyKeywordMatcher.new(**kw); end RUBY end eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 RSpec::Matchers.alias_matcher :my_keyword_override, :my_keyword_matcher RSpec::Matchers.define_negated_matcher :not_keyword_override, :my_keyword_matcher it 'works properly with a keyword arguments matcher' do expect(true).to my_keyword_override(some: :arg) end it 'works properly with a negated keyword arguments matcher' do expect(false).to not_keyword_override(some: :arg) end RUBY end context "when negating a matcher that does not define `description` (which is an optional part of the matcher protocol)" do def matcher_without_description matcher = Object.new def matcher.matches?(v); v; end def matcher.failure_message; "match failed"; end def matcher.chained; self; end expect(RSpec::Matchers.is_a_matcher?(matcher)).to be true matcher end RSpec::Matchers.define_negated_matcher :negation_of_matcher_without_description, :matcher_without_description it 'works properly' do expect(true).to matcher_without_description.chained expect(false).to negation_of_matcher_without_description.chained end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/composable_spec.rb0000664000000000000000000001002014557700001027732 0ustar rootrootmodule RSpec module Matchers RSpec.describe Composable do RSpec::Matchers.define :matcher_using_surface_descriptions_in do |expected| match { false } failure_message { surface_descriptions_in(expected).to_s } end it "does not blow up when surfacing descriptions from an unreadable IO object" do expect { expect(3).to matcher_using_surface_descriptions_in(STDOUT) }.to fail_with(STDOUT.inspect) end it "does not blow up when surfacing descriptions from an unreadable Range object" do infinity = (1.0/0.0) infinite_range = -infinity..infinity expect { expect(1).to matcher_using_surface_descriptions_in(infinite_range) }.to fail_with(infinite_range.inspect) end it "does not blow up when surfacing descriptions from an Enumerable object whose #each includes the object itself" do array = ['something'] array << array expect { expect(1).to matcher_using_surface_descriptions_in(array) }.to fail_with(array.to_s) end it "does not enumerate normal ranges" do range = 1..3 expect { expect(1).to matcher_using_surface_descriptions_in(range) }.to fail_with(range.inspect) end it "doesn't mangle struct descriptions" do model = Struct.new(:a).new(1) expect { expect(1).to matcher_using_surface_descriptions_in(model) }.to fail_with(model.inspect) end RSpec::Matchers.define :all_but_one do |matcher| match do |actual| match_count = actual.count { |v| values_match?(matcher, v) } actual.size == match_count + 1 end end context "when using a matcher instance that memoizes state multiple times in a composed expression" do it "works properly in spite of the memoization" do expect(["foo", "bar", "a"]).to all_but_one(have_string_length(3)) end context "when passing a compound expression" do it "works properly in spite of the memoization" do expect(["A", "AB", "ABC"]).to all_but_one( have_string_length(1).or have_string_length(2) ) end end end describe "cloning data structures containing matchers" do include Composable it "clones only the contained matchers" do matcher_1 = eq(1) matcher_2 = eq(2) object = Object.new uncloneable = nil data_structure = { "foo" => matcher_1, "bar" => [matcher_2, uncloneable], "bazz" => object } cloned = with_matchers_cloned(data_structure) expect(cloned).not_to equal(data_structure) expect(cloned["foo"]).to be_a_clone_of(matcher_1) expect(cloned["bar"].first).to be_a_clone_of(matcher_2) expect(cloned["bazz"]).to equal(object) end it "copies custom matchers properly so they can work even though they have singleton behavior" do expect("foo").to with_matchers_cloned(have_string_length 3) end it 'does not blow up when passed an array containing an IO object' do stdout = STDOUT expect(with_matchers_cloned([stdout]).first).to equal(stdout) end end describe "when an unexpected call stack jump occurs" do RSpec::Matchers.define :cause_call_stack_jump do supports_block_expectations match do |block| begin block.call false rescue Exception # rubocop:disable Lint/RescueException true end end end it "issue a warning suggesting `expects_call_stack_jump?` has been improperly declared" do expect { x = 0 expect { x += 1; exit }.to change { x }.and cause_call_stack_jump }.to raise_error(/no match results, [\.\w\s]+ declare `expects_call_stack_jump\?`/) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/define_negated_matcher_spec.rb0000664000000000000000000001742214557700001032247 0ustar rootrootmodule RSpec module Matchers RSpec.describe 'RSpec::Matchers.define_negated_matcher' do RSpec::Matchers.define :my_base_non_negated_matcher do match { |actual| actual == foo } def foo 13 end def description "my base matcher description" end end shared_examples "making a copy" do |copy_method| context "when making a copy via `#{copy_method}`" do it "uses a copy of the base matcher" do base_matcher = include(3) aliased = AliasedNegatedMatcher.new(base_matcher, Proc.new {}) copy = aliased.__send__(copy_method) expect(copy).not_to equal(aliased) expect(copy.base_matcher).not_to equal(base_matcher) expect(copy.base_matcher).to be_a(RSpec::Matchers::BuiltIn::Include) expect(copy.base_matcher.expected).to eq([3]) end it "copies custom matchers properly so they can work even though they have singleton behavior" do base_matcher = my_base_non_negated_matcher aliased = AliasedNegatedMatcher.new(base_matcher, Proc.new { |a| a }) copy = aliased.__send__(copy_method) expect(copy).not_to equal(aliased) expect(copy.base_matcher).not_to equal(base_matcher) expect(15).to copy expect { expect(13).to copy }.to fail_with(/expected 13/) end end end include_examples "making a copy", :dup include_examples "making a copy", :clone RSpec::Matchers.define_negated_matcher :an_array_excluding, :include it_behaves_like "an RSpec value matcher", :valid_value => [1, 3], :invalid_value => [1, 2] do let(:matcher) { an_array_excluding(2) } end it 'works properly when composed' do list = 1.upto(10).to_a expect { list.delete(5) }.to change { list }.to(an_array_excluding 5) end describe "the failure message" do context "for a matcher with default failure messages" do RSpec::Matchers.define(:be_awesome) { match(&:awesome?) } RSpec::Matchers.define_negated_matcher :be_lame, :be_awesome context "when failing positively" do it "uses the phrasing from the provided defined matcher alias" do expect { expect(double(:awesome? => true, :inspect => "")).to be_lame }.to fail_with("expected to be lame") end end context "when failing negatively" do it "uses the phrasing from the provided defined matcher alias" do expect { expect(double(:awesome? => false, :inspect => "")).not_to be_lame }.to fail_with("expected not to be lame") end end context "when accessed via an alias that is not included in failure messages" do alias_method :be_fantastic, :be_awesome RSpec::Matchers.define_negated_matcher :be_terrible, :be_fantastic context "when failing positively" do it "uses the wrapped matcher's `failure_message_when_negated`" do expect { expect(double(:awesome? => true, :inspect => "")).to be_terrible }.to fail_with("expected not to be awesome") end end context "when failing negatively" do it "uses the wrapped matcher's `failure_message`" do expect { expect(double(:awesome? => false, :inspect => "")).not_to be_terrible }.to fail_with("expected to be awesome") end end end end context "for a matcher with a customized `failure_message_when_negated`" do RSpec::Matchers.define(:be_tall) do match(&:tall?) failure_message_when_negated do |actual| "expected #{actual.inspect} not to be tall, but was tall" end end RSpec::Matchers.define_negated_matcher :be_short, :be_tall context "when failing positively" do it "uses the wrapped matcher's `failure_message_when_negated` since it may include more detail" do expect { expect(double(:tall? => true, :inspect => "")).to be_short }.to fail_with("expected not to be tall, but was tall") end end context "when failing negatively" do it "uses the wrapped matcher's `failure_message` since it may include more detail" do expect { expect(double(:tall? => false, :inspect => "")).not_to be_short }.to fail_with("expected to be tall") end end end end context 'when no block is passed' do RSpec::Matchers.define :be_an_odd_number do match { |actual| actual.odd? } end RSpec::Matchers.define_negated_matcher :be_an_even_number, :be_an_odd_number it 'uses the default negated description' do expect(be_an_even_number.description).to eq("be an even number") end context "when matched positively" do it 'matches values that fail the original matcher' do expect { expect(22).to be_an_odd_number }.to fail_with("expected 22 to be an odd number") expect(22).to be_an_even_number end it "fails matches against values that pass the original matcher" do expect(21).to be_an_odd_number expect { expect(21).to be_an_even_number }.to fail_with("expected 21 to be an even number") end end context "when matched negatively" do it 'matches values that fail the original matcher' do expect { expect(21).not_to be_an_odd_number }.to fail_with("expected 21 not to be an odd number") expect(21).not_to be_an_even_number end it "fails matches against values that pass the original matcher" do expect(22).not_to be_an_odd_number expect { expect(22).not_to be_an_even_number }.to fail_with("expected 22 not to be an even number") end end end context 'when the negated description is overridden' do RSpec::Matchers.define :be_bigger_than_ten do match { |actual| actual > 10 } end RSpec::Matchers.define_negated_matcher :be_smaller_than_ten, :be_bigger_than_ten do |desc| "#{desc.sub('bigger', 'smaller')} (overridden)" end it 'overrides the description with the provided block' do expect(be_smaller_than_ten.description).to eq("be smaller than ten (overridden)") end it 'overrides the failure message with the provided block' do expect { expect(12).to be_smaller_than_ten }.to fail_with("expected 12 to be smaller than ten (overridden)") end end context "for a matcher that has custom `match_when_negated` logic" do RSpec::Matchers.define :matcher_with_custom_negation do |match_value| match { match_value } match_when_negated { |actual| actual == :does_not_match_true } end RSpec::Matchers.define_negated_matcher :negated_matcher_with_custom_negation, :matcher_with_custom_negation it "uses the `match_when_negated` logic for matching" do expect(:does_not_match_true).to negated_matcher_with_custom_negation(true) expect { expect(:does_not_match_false).to negated_matcher_with_custom_negation(true) }.to fail end it "uses the `match` logic for `expect(..).not_to`" do expect(:foo).not_to negated_matcher_with_custom_negation(true) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/rspec/matchers/aliases_spec.rb0000664000000000000000000002514514557700001027245 0ustar rootrootmodule RSpec RSpec.describe Matchers, "aliases", :order => :defined do matcher :be_aliased_to do |old_matcher| chain :with_description do |desc| @expected_desc = desc end match do |aliased_matcher| @actual_desc = aliased_matcher.description @actual_desc == @expected_desc && aliased_matcher.base_matcher.class == old_matcher.class end failure_message do |aliased_matcher| "expected #{aliased_matcher} to be aliased to #{old_matcher} with " \ "description: #{@expected_desc.inspect}, but got #{@actual_desc.inspect}" end description do |_aliased_matcher| "have an alias for #{old_matcher.description.inspect} with description: #{@expected_desc.inspect}" end end specify do expect(a_truthy_value).to be_aliased_to(be_truthy).with_description("a truthy value") end specify do expect(a_falsey_value).to be_aliased_to(be_falsey).with_description("a falsey value") end specify do expect(be_falsy).to be_aliased_to(be_falsey).with_description("be falsy") end specify do expect(a_falsy_value).to be_aliased_to(be_falsey).with_description("a falsy value") end specify do expect(a_nil_value).to be_aliased_to(be_nil).with_description("a nil value") end specify do expect(a_value > 3).to be_aliased_to(be > 3).with_description("a value > 3") end specify do expect(a_value < 3).to be_aliased_to(be < 3).with_description("a value < 3") end specify do expect(a_value <= 3).to be_aliased_to(be <= 3).with_description("a value <= 3") end specify do expect(a_value == 3).to be_aliased_to(be == 3).with_description("a value == 3") end specify do expect(a_value === 3).to be_aliased_to(be === 3).with_description("a value === 3") end specify do expect( an_instance_of(Integer) ).to be_aliased_to( be_an_instance_of(Integer) ).with_description("an instance of Integer") end specify do expect( a_kind_of(Integer) ).to be_aliased_to( be_a_kind_of(Integer) ).with_description("a kind of Integer") end specify do expect( a_value_between(1, 10) ).to be_aliased_to( be_between(1, 10) ).with_description("a value between 1 and 10 (inclusive)") end specify do expect( a_value_within(0.1).of(3) ).to be_aliased_to( be_within(0.1).of(3) ).with_description("a value within 0.1 of 3") end specify do expect( within(0.1).of(3) ).to be_aliased_to( be_within(0.1).of(3) ).with_description("within 0.1 of 3") end specify do expect(a_block_changing).to be_aliased_to(change).with_description("a block changing result") end specify do expect(changing).to be_aliased_to(change).with_description("changing result") end specify do expect( a_collection_containing_exactly(1, 2) ).to be_aliased_to( contain_exactly(1, 2) ).with_description("a collection containing exactly 1 and 2") end specify do expect( containing_exactly(1, 2) ).to be_aliased_to( contain_exactly(1, 2) ).with_description("containing exactly 1 and 2") end specify do expect( a_range_covering(1, 2) ).to be_aliased_to( cover(1, 2) ).with_description("a range covering 1 and 2") end specify do expect( covering(1, 2) ).to be_aliased_to( cover(1, 2) ).with_description("covering 1 and 2") end specify do expect( ending_with(23) ).to be_aliased_to( end_with(23) ).with_description("ending with 23") end specify do expect( a_collection_ending_with(23) ).to be_aliased_to( end_with(23) ).with_description("a collection ending with 23") end specify do expect( a_string_ending_with("z") ).to be_aliased_to( end_with("z") ).with_description('a string ending with "z"') end specify do expect( an_object_eq_to(3) ).to be_aliased_to(eq 3).with_description("an object eq to 3") end specify do expect( eq_to(3) ).to be_aliased_to(eq 3).with_description("eq to 3") end specify do expect( an_object_eql_to(3) ).to be_aliased_to(eql 3).with_description("an object eql to 3") end specify do expect( eql_to(3) ).to be_aliased_to(eql 3).with_description("eql to 3") end specify do expect( an_object_equal_to(3) ).to be_aliased_to(equal 3).with_description("an object equal to 3") end specify do expect( equal_to(3) ).to be_aliased_to(equal 3).with_description("equal to 3") end specify do expect( an_object_existing ).to be_aliased_to(exist).with_description("an object existing") end specify do expect(existing).to be_aliased_to(exist).with_description("existing") end specify do expect( an_object_having_attributes(:age => 32) ).to be_aliased_to( have_attributes(:age => 32) ).with_description("an object having attributes {:age => 32}") end specify do expect( having_attributes(:age => 32) ).to be_aliased_to( have_attributes(:age => 32) ).with_description("having attributes {:age => 32}") end specify do expect( a_string_including("a") ).to be_aliased_to( include("a") ).with_description('a string including "a"') end specify do expect( a_collection_including("a") ).to be_aliased_to( include("a") ).with_description('a collection including "a"') end specify do expect( a_hash_including(:a => 5) ).to be_aliased_to( include(:a => 5) ).with_description('a hash including {:a => 5}') end specify do expect( including(3) ).to be_aliased_to( include(3) ).with_description('including 3') end specify do expect( a_string_matching(/foo/) ).to be_aliased_to( match(/foo/) ).with_description('a string matching /foo/') end specify do expect( an_object_matching(/foo/) ).to be_aliased_to( match(/foo/) ).with_description('an object matching /foo/') end specify do expect( match_regex(/foo/) ).to be_aliased_to( match(/foo/) ).with_description('match regex /foo/') end specify do expect( matching(/foo/) ).to be_aliased_to( match(/foo/) ).with_description('matching /foo/') end specify do expect( an_array_matching([1, 2]) ).to be_aliased_to( match_array([1, 2]) ).with_description('an array containing exactly 1 and 2') end specify do expect( a_block_outputting('foo').to_stdout ).to be_aliased_to( output('foo').to_stdout ).with_description('a block outputting "foo" to stdout') end specify do expect( a_block_outputting('foo').to_stderr ).to be_aliased_to( output('foo').to_stderr ).with_description('a block outputting "foo" to stderr') end specify do expect( a_block_raising(ArgumentError) ).to be_aliased_to( raise_error(ArgumentError) ).with_description('a block raising ArgumentError') end specify do expect( raising(ArgumentError) ).to be_aliased_to( raise_error(ArgumentError) ).with_description("raising ArgumentError") end specify do expect( an_object_responding_to(:foo) ).to be_aliased_to( respond_to(:foo) ).with_description("an object responding to #foo") end specify do expect( responding_to(:foo) ).to be_aliased_to( respond_to(:foo) ).with_description("responding to #foo") end specify do expect( an_object_satisfying {} ).to be_aliased_to( satisfy {} ).with_description("an object satisfying block") end specify do expect( satisfying {} ).to be_aliased_to( satisfy {} ).with_description("satisfying block") end specify do expect( a_collection_starting_with(23) ).to be_aliased_to( start_with(23) ).with_description("a collection starting with 23") end specify do expect( a_string_starting_with("z") ).to be_aliased_to( start_with("z") ).with_description('a string starting with "z"') end specify do expect( starting_with("d") ).to be_aliased_to( start_with("d") ).with_description('starting with "d"') end specify do expect( a_block_throwing(:foo) ).to be_aliased_to( throw_symbol(:foo) ).with_description("a block throwing :foo") end specify do expect( throwing(:foo) ).to be_aliased_to( throw_symbol(:foo) ).with_description("throwing :foo") end specify do expect( a_block_yielding_control ).to be_aliased_to( yield_control ).with_description("a block yielding control") end specify do expect( yielding_control ).to be_aliased_to( yield_control ).with_description("yielding control") end specify do expect( a_block_yielding_with_no_args ).to be_aliased_to( yield_with_no_args ).with_description("a block yielding with no args") end specify do expect( yielding_with_no_args ).to be_aliased_to( yield_with_no_args ).with_description("yielding with no args") end specify do expect( a_block_yielding_with_args ).to be_aliased_to( yield_with_args ).with_description("a block yielding with args") end specify do expect( yielding_with_args ).to be_aliased_to( yield_with_args ).with_description("yielding with args") end specify do expect( a_block_yielding_successive_args ).to be_aliased_to( yield_successive_args ).with_description("a block yielding successive args()") end specify do expect( yielding_successive_args ).to be_aliased_to( yield_successive_args ).with_description("yielding successive args()") end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/0000775000000000000000000000000014557700001023050 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/matchers.rb0000664000000000000000000000206114557700001025202 0ustar rootrootrequire 'rspec/matchers/fail_matchers' RSpec::Matchers.define :include_method do |expected| match do |actual| actual.map { |m| m.to_s }.include?(expected.to_s) end end RSpec::Matchers.define :custom_include do |*args| match { |actual| expect(actual).to include(*args) } end RSpec::Matchers.define :be_a_clone_of do |expected| match do |actual| !actual.equal?(expected) && actual.class.equal?(expected.class) && state_of(actual) == state_of(expected) end def state_of(object) ivar_names = object.instance_variables Hash[ivar_names.map { |n| [n, object.instance_variable_get(n)] }] end end RSpec::Matchers.define :have_string_length do |expected| match do |actual| @actual = actual string_length == expected end def string_length @string_length ||= @actual.length end end RSpec.configure do |config| config.include RSpec::Matchers::FailMatchers end RSpec::Matchers.define_negated_matcher :a_string_excluding, :a_string_including RSpec::Matchers.define_negated_matcher :a_string_not_matching, :match ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/shared_examples/0000775000000000000000000000000014557700001026214 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/shared_examples/block_matcher.rb0000664000000000000000000000645414557700001031347 0ustar rootrootRSpec.shared_examples "an RSpec block-only matcher" do |*options| # Note: Ruby 1.8 expects you to call a block with arguments if it is # declared that accept arguments. In this case, some of the specs # that include examples from this shared example group do not pass # arguments. A workaround is to use splat and pick the first argument # if it was passed. options = options.first || {} # Note: do not use `matcher` in 2 expectation expressions in a single # example here. In some cases (such as `change { x += 2 }.to(2)`), it # will fail because using it a second time will apply `x += 2` twice, # changing the value to 4. matcher :always_passes do supports_block_expectations match do |actual| actual.call true end end matcher :always_fails do supports_block_expectations match do |actual| actual.call false end end let(:valid_expectation) { expect { valid_block } } let(:invalid_expectation) { expect { invalid_block } } let(:valid_block_lambda) { lambda { valid_block } } let(:invalid_block_lambda) { lambda { invalid_block } } include_examples "an RSpec matcher", options it 'preserves the symmetric property of `==`' do expect(matcher).to eq(matcher) expect(matcher).not_to eq(valid_block_lambda) expect(valid_block_lambda).not_to eq(matcher) end it 'matches a valid block when using #=== so it can be composed' do expect(matcher).to be === valid_block_lambda end it 'does not match an invalid block when using #=== so it can be composed' do expect(matcher).not_to be === invalid_block_lambda end it 'matches a valid block when using #=== so it can be composed' do expect(matcher).to be === valid_block_lambda end it 'does not match an invalid block when using #=== so it can be composed' do expect(matcher).not_to be === invalid_block_lambda end it 'uses the `ObjectFormatter` for `failure_message`' do allow(RSpec::Support::ObjectFormatter).to receive(:format).and_return("detailed inspect") expect { invalid_expectation.to matcher }.to raise_error do |error| # Undo our stub so it doesn't affect the `include` matcher below. allow(RSpec::Support::ObjectFormatter).to receive(:format).and_call_original expect(error.message).to include("detailed inspect") end end unless options[:failure_message_uses_no_inspect] it 'fails gracefully when given a value' do expect { expect(3).to matcher }.to fail_with(/was not( given)? a block/) unless options[:disallows_negation] expect { expect(3).not_to matcher }.to fail_with(/was not( given)? a block/) end end it 'prints a deprecation warning when given a value' do expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { expect(3).to matcher }.to fail end unless options[:skip_deprecation_check] || options[:expects_lambda] it 'prints a deprecation warning when given a value and negated' do expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { expect(3).not_to matcher }.to fail end unless options[:disallows_negation] || options[:expects_lambda] it 'allows lambda expectation target' do allow_deprecation expect(valid_block_lambda).to matcher end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/shared_examples/matcher.rb0000664000000000000000000000254514557700001030172 0ustar rootrootRSpec.shared_examples "an RSpec matcher" do |options| # Note: do not use `matcher` in 2 expectation expressions in a single # example here. In some cases (such as `change { }.to(2)`), it will fail # because using it a second time will apply `x += 2` twice, changing # the value to 4. it 'allows additional matchers to be chained off it using `and`' do valid_expectation.to matcher.and always_passes end it 'can be chained off of an existing matcher using `and`' do valid_expectation.to always_passes.and matcher end it 'allows additional matchers to be chained off it using `or`' do valid_expectation.to matcher.or always_fails end it 'can be chained off of an existing matcher using `or`' do valid_expectation.to always_fails.or matcher end it 'implements the full matcher protocol' do expect(matcher).to respond_to( :matches?, :failure_message, :description, :supports_block_expectations?, :supports_value_expectations?, :expects_call_stack_jump? ) # We do not require failure_message_when_negated and does_not_match? # Because some matchers purposefully do not support negation. end it 'can match negatively properly' do invalid_expectation.not_to matcher expect { valid_expectation.not_to matcher }.to fail end unless options[:disallows_negation] end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/support/shared_examples/value_matcher.rb0000664000000000000000000000356014557700001031364 0ustar rootrootRSpec.shared_examples "an RSpec value matcher" do |options| let(:valid_value) { options.fetch(:valid_value) } let(:invalid_value) { options.fetch(:invalid_value) } matcher :always_passes do match { |_actual| true } end matcher :always_fails do match { |_actual| false } end def valid_expectation expect(valid_value) end def invalid_expectation expect(invalid_value) end include_examples "an RSpec matcher", options it 'preserves the symmetric property of `==`' do expect(matcher).to eq(matcher) expect(matcher).not_to eq(valid_value) expect(valid_value).not_to eq(matcher) end it 'matches a valid value when using #=== so it can be composed' do expect(matcher).to be === valid_value end it 'does not match an invalid value when using #=== so it can be composed' do expect(matcher).not_to be === invalid_value end it 'can be used in a composed matcher expression' do expect([valid_value, invalid_value]).to include(matcher) expect { expect([invalid_value]).to include(matcher) }.to fail_including("include (#{matcher.description})") end it 'uses the `ObjectFormatter` for `failure_message`' do allow(RSpec::Support::ObjectFormatter).to receive(:format).and_return("detailed inspect") matcher.matches?(invalid_value) message = matcher.failure_message # Undo our stub so it doesn't affect the `include` matcher below. allow(RSpec::Support::ObjectFormatter).to receive(:format).and_call_original expect(message).to include("detailed inspect") end it 'fails when given a block' do expect { expect { 2 + 2 }.to matcher }.to fail_with(/must pass an argument rather than a block/) unless options[:disallows_negation] expect { expect { 2 + 2 }.not_to matcher }.to fail_with(/must pass an argument rather than a block/) end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/spec/spec_helper.rb0000664000000000000000000000760114557700001024156 0ustar rootrootrequire 'rspec/support/spec' require 'rspec/support/spec/in_sub_process' RSpec::Support::Spec.setup_simplecov do minimum_coverage 92 end Dir['./spec/support/**/*.rb'].each do |f| require f.sub(%r{\./spec/}, '') end module CommonHelperMethods def with_env_vars(vars) original = ENV.to_hash vars.each { |k, v| ENV[k] = v } begin yield ensure ENV.replace(original) end end def dedent(string) string.gsub(/^\s+\|/, '').chomp end # We have to use Hash#inspect in examples that have multi-entry # hashes because the #inspect output on 1.8.7 is non-deterministic # due to the fact that hashes are not ordered. So we can't simply # put a literal string for what we expect because it varies. if RUBY_VERSION.to_f == 1.8 def hash_inspect(hash) "\\{(#{hash.map { |key, value| "#{key.inspect} => #{value.inspect}.*" }.join "|"}){#{hash.size}}\\}" end else def hash_inspect(hash) RSpec::Matchers::BuiltIn::BaseMatcher::HashFormatting. improve_hash_formatting hash.inspect end end end RSpec.configure do |config| config.color = true config.order = :random config.include CommonHelperMethods config.include RSpec::Support::InSubProcess config.expect_with :rspec do |expectations| $default_expectation_syntax = expectations.syntax # rubocop:disable Style/GlobalVars expectations.syntax = :expect expectations.include_chain_clauses_in_custom_matcher_descriptions = true expectations.strict_predicate_matchers = true end config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end config.disable_monkey_patching! # We don't want rspec-core to look in our `lib` for failure snippets. # When it does that, it inevitably finds this line: # `RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)` # ...which isn't very helpful. Far better for it to find the expectation # call site in the spec. config.project_source_dirs -= ["lib"] end RSpec.shared_context "with #should enabled", :uses_should do orig_syntax = nil before(:all) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.syntax = [:expect, :should] end after(:context) do RSpec::Matchers.configuration.syntax = orig_syntax end end RSpec.shared_context "with the default expectation syntax" do orig_syntax = nil before(:context) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.reset_syntaxes_to_default end after(:context) do RSpec::Matchers.configuration.syntax = orig_syntax end end RSpec.shared_context "with #should exclusively enabled", :uses_only_should do orig_syntax = nil before(:context) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.syntax = :should end after(:context) do RSpec::Matchers.configuration.syntax = orig_syntax end end RSpec.shared_context "isolate include_chain_clauses_in_custom_matcher_descriptions" do around do |ex| orig = RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions? ex.run RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions = orig end end RSpec.shared_context "with warn_about_potential_false_positives set to false", :warn_about_potential_false_positives do original_value = RSpec::Expectations.configuration.warn_about_potential_false_positives? after(:context) { RSpec::Expectations.configuration.warn_about_potential_false_positives = original_value } end module MinitestIntegration include ::RSpec::Support::InSubProcess def with_minitest_loaded in_sub_process do with_isolated_stderr do require 'minitest/autorun' end require 'rspec/expectations/minitest_integration' yield end end end RSpec::Matchers.define_negated_matcher :avoid_outputting, :output ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/rspec-expectations.gemspec0000664000000000000000000000434214557700001025572 0ustar rootroot$LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require "rspec/expectations/version" Gem::Specification.new do |s| s.name = "rspec-expectations" s.version = RSpec::Expectations::Version::STRING s.platform = Gem::Platform::RUBY s.license = "MIT" s.authors = ["Steven Baker", "David Chelimsky", "Myron Marston"] s.email = "rspec@googlegroups.com" s.homepage = "https://github.com/rspec/rspec-expectations" s.summary = "rspec-expectations-#{RSpec::Expectations::Version::STRING}" s.description = "rspec-expectations provides a simple, readable API to express expected outcomes of a code example." s.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-expectations/issues', 'changelog_uri' => "https://github.com/rspec/rspec-expectations/blob/v#{s.version}/Changelog.md", 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-expectations', } s.files = `git ls-files -- lib/*`.split("\n") s.files += %w[README.md LICENSE.md Changelog.md .yardopts .document] s.test_files = [] s.rdoc_options = ["--charset=UTF-8"] s.require_path = "lib" s.required_ruby_version = '>= 1.8.7' # rubocop:disable Gemspec/RequiredRubyVersion private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem') if File.exist?(private_key) s.signing_key = private_key s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')] end if RSpec::Expectations::Version::STRING =~ /[a-zA-Z]+/ # pin to exact version for rc's and betas s.add_runtime_dependency "rspec-support", "= #{RSpec::Expectations::Version::STRING}" else # pin to major/minor ignoring patch s.add_runtime_dependency "rspec-support", "~> #{RSpec::Expectations::Version::STRING.split('.')[0..1].concat(['0']).join('.')}" end s.add_runtime_dependency "diff-lcs", ">= 1.2.0", "< 2.0" s.add_development_dependency "aruba", "~> 0.14.10" s.add_development_dependency 'cucumber', '>= 1.3' s.add_development_dependency 'minitest', '~> 5.2' s.add_development_dependency 'rake', '> 10.0.0' end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/cucumber.yml0000664000000000000000000000071614557700001022736 0ustar rootroot<% USE_TILDE_TAGS = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') NOT_WIP_TAG = USE_TILDE_TAGS ? '~@wip' : '"not @wip"' NOT_RUBY_1_9_TAG = USE_TILDE_TAGS ? '~@ruby-1.9' : '"not @ruby-1.9"' def tags(tag = NOT_WIP_TAG) tags = [tag] tags << NOT_RUBY_1_9_TAG if RUBY_VERSION.to_f < 1.9 tags.join(" --tags ") end %> default: --require features --tags <%= tags %> --format progress wip: --require features --tags @wip:3 --wip features ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.github/0000775000000000000000000000000014557700001021742 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.github/workflows/0000775000000000000000000000000014557700001023777 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.github/workflows/ci.yml0000664000000000000000000001143014557700001025114 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. name: RSpec CI on: push: branches: - 'main' - '*-maintenance' - '*-dev' pull_request: branches: - '*' permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true env: RSPEC_CI: true # This tells rspec-rails what branch to run in ci RSPEC_VERSION: '~> 3.13.0' jobs: rubocop: name: Rubocop runs-on: 'ubuntu-20.04' steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.0' - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_rubocop test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} runs-on: ${{ matrix.os || 'ubuntu-20.04' }} strategy: matrix: ruby: - '3.3' - '3.2' - '3.1' - '3.0' - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 env: - DIFF_LCS_VERSION: "> 1.4.3" include: - ruby: ruby-head env: RUBY_HEAD: true - ruby: jruby-9.2.13.0 env: JRUBY_OPTS: "--dev" - ruby: 2.7 name_extra: "with diff-lcs 1.3" env: DIFF_LCS_VERSION: "~> 1.3.0" - ruby: 2.7 name_extra: "with diff-lcs 1.4.3" env: DIFF_LCS_VERSION: "1.4.3" fail-fast: false continue-on-error: ${{ matrix.allow_failure || endsWith(matrix.ruby, 'head') }} env: ${{ matrix.env }} steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: ${{ matrix.bundler || '2.2.22' }} ruby-version: ${{ matrix.ruby }} - run: script/update_rubygems_and_install_bundler - run: script/clone_all_rspec_repos - run: bundle install --standalone - run: bundle binstubs --all - run: script/run_build legacy: name: Legacy Ruby Builds (${{ matrix.container.version }}) runs-on: ubuntu-20.04 container: image: ${{ matrix.container.tag }} options: ${{ matrix.container.options || '--add-host github-complains-if-this-is-empty.com:127.0.0.1' }} strategy: fail-fast: false matrix: container: - version: "2.1.9" tag: ghcr.io/rspec/docker-ci:2.1.9 post: git config --global --add safe.directory `pwd` - version: "2.0" tag: ghcr.io/rspec/docker-ci:2.0.0 - version: "1.9.3" tag: ghcr.io/rspec/docker-ci:1.9.3 - version: "1.9.2" tag: ghcr.io/rspec/docker-ci:1.9.2 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "1.8.7" tag: ghcr.io/rspec/docker-ci:1.8.7 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "REE" tag: ghcr.io/rspec/docker-ci:ree options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 1.7" tag: ghcr.io/rspec/docker-ci:jruby-1.7 - version: "JRuby 1.7 1.8 mode" tag: ghcr.io/rspec/docker-ci:jruby-1.7 jruby_opts: '--dev --1.8' pre: gem uninstall jruby-openssl options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" - version: "JRuby 9.1.17.0" tag: ghcr.io/rspec/docker-ci:jruby-9.1.17.0 options: "--add-host rubygems.org:151.101.129.227 --add-host api.rubygems.org:151.101.129.227" env: LEGACY_CI: true JRUBY_OPTS: ${{ matrix.container.jruby_opts || '--dev' }} steps: - uses: actions/checkout@v3 - run: ${{ matrix.container.pre }} - run: script/legacy_setup.sh - run: ${{ matrix.container.post }} - run: bundle exec bin/rspec - run: bundle exec script/cucumber.sh windows: name: Ruby ${{ matrix.ruby }} (Windows) runs-on: windows-latest strategy: matrix: ruby: - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 - 2.2 fail-fast: false steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: bundler: '2.2.22' ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: choco install ansicon - run: bundle exec rspec --backtrace ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.github/dependabot.yml0000664000000000000000000000043714557700001024576 0ustar rootroot# This file was generated on 2023-12-25T16:07:49+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. version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.github/FUNDING.yml0000664000000000000000000000033514557700001023560 0ustar rootroot# This file was generated on 2023-04-16T20:53:22+01: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, benoittgt] open_collective: rspec ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/DEV-README.md0000664000000000000000000000127414557700001022301 0ustar rootroot## Set up the dev environment git clone https://github.com/rspec/rspec-expectations.git cd rspec-expectations gem install bundler bundle install Now you should be able to run any of: rake rake spec rake cucumber Or, if you prefer to use the rspec and cucumber commands directly, you can either: bundle exec rspec Or ... bundle install --binstubs bin/rspec ## Customize the dev environment The Gemfile includes the gems you'll need to be able to run specs. If you want to customize your dev environment with additional tools like guard or ruby-debug, add any additional gem declarations to Gemfile-custom (see Gemfile-custom.sample for some examples). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/CONTRIBUTING.md0000664000000000000000000001036714557700001022642 0ustar rootroot # Contributing RSpec is a community-driven project that has benefited from improvements from over *500* contributors. We welcome contributions from *everyone*. While contributing, please follow the project [code of conduct](CODE_OF_CONDUCT.md), so that everyone can be included. If you'd like to help make RSpec better, here are some ways you can contribute: - by running RSpec HEAD to help us catch bugs before new releases - by [reporting bugs you encounter](https://github.com/rspec/rspec-expectations/issues/new) with [report template](#report-template) - by [suggesting new features](https://github.com/rspec/rspec-expectations/issues/new) - by improving RSpec's Feature or API [documentation](https://rspec.info/documentation/) - by improving [RSpec's website](https://rspec.info/) ([source](https://github.com/rspec/rspec.github.io)) - by taking part in [feature and issue discussions](https://github.com/rspec/rspec-expectations/issues) - by adding a failing test for reproducible [reported bugs](https://github.com/rspec/rspec-expectations/issues) - by reviewing [pull requests](https://github.com/rspec/rspec-expectations/pulls) and suggesting improvements - by [writing code](DEVELOPMENT.md) (no patch is too small! fix typos or bad whitespace) If you need help getting started, check out the [DEVELOPMENT](DEVELOPMENT.md) file for steps that will get you up and running. Thanks for helping us make RSpec better! ## `Small` issues These issue are ones that we be believe are best suited for new contributors to get started with. They represent a meaningful contribution to the project that should not be too hard to pull off. ## Report template Having a way to reproduce your issue will be very helpful for others to help confirm, investigate and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared one basic [bug report templates](REPORT_TEMPLATE.md) for you to use as a starting point. ## Maintenance branches Maintenance branches are how we manage the different supported point releases of RSpec. As such, while they might look like good candidates to merge into main, please do not open pull requests to merge them. ## Working on multiple RSpec gems at the same time RSpec is composed of multiple gems (`rspec-core`, `rspec-mocks`, etc). Sometimes you have to work on a combination of them at the same time. When submitting your code for review, we ask that you get a passing build (green CI). If you are working across the repositories, please add a commit that temporarily pins your PR to the right branch of the other repository you depend on. For example, if we wanted a change in `rspec-expectations` that relied on a change for on `rspec-mocks`. We add a commit with the title: >[WIP] Use rspec-mocks with "custom-failure-message" branch And content: ```diff diff --git a/Gemfile b/Gemfile -%w[rspec rspec-core rspec-mocks rspec-support].each do |lib| +%w[rspec rspec-core rspec-support].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path @@ -11,6 +11,7 @@ branch = File.read(File.expand_path("../maintenance-branch", __FILE__)).chomp gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => branch end end +gem 'rspec-mocks', :git => "https://github.com/rspec/rspec-mocks.git", :branch => "custom-failure-message" ``` In general the process is: 1. Create PRs explaining what you are trying to achieve. 2. Pin the repositories to each other. 3. Check they pass (go green). 4. Await review if appropriate. 5. Remove the commit from step 2. We will merge ignoring the failure. 6. Remove the commit from the other, check it passes with the other commit now on `main`. 7. Merge the other. 8. We will trigger builds for the `main` branch of affected repositories to check if everything is in order. Steps 5-8 should happen continuously (e.g. one after another but within a short timespan) so that we don't leave a broken main around. It is important to triage that build process and revert if necessary. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/BUILD_DETAIL.md0000664000000000000000000001245014557700001022607 0ustar rootroot # The CI build, in detail The [Travis CI build](https://travis-ci.org/rspec/rspec-expectations) runs many verification steps to prevent regressions and ensure high-quality code. To run the Travis build locally, run: ``` $ script/run_build ``` It can be useful to run the build steps individually to repro a failing part of a Travis build. Let's break the build down into the individual steps. ## Specs RSpec dogfoods itself. Its primary defense against regressions is its spec suite. Run with: ``` $ bundle exec rspec # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rspec ``` The spec suite performs a couple extra checks that are worth noting: * *That all the code is warning-free.* Any individual example that produces output to `stderr` will fail. We also have a spec that loads all the `lib` and `spec` files in a newly spawned process to detect load-time warnings and fail if there are any. RSpec must be warning-free so that users who enable Ruby warnings will not get warnings from our code. * *That only a minimal set of stdlibs are loaded.* Since Ruby makes loaded libraries available for use in any context, we want to minimize how many bits of the standard library we load and use. Otherwise, RSpec's use of part of the standard library could mask a problem where a gem author forgets to load a part of the standard library they rely on. The spec suite contains a spec that defines a list of allowed loaded stdlibs. In addition, we use [SimpleCov](https://github.com/colszowka/simplecov) to measure and enforce test coverage. If the coverage falls below a project-specific threshold, the build will fail. ## Cukes RSpec uses [cucumber](https://cucumber.io/) for both acceptance testing and [documentation](https://rspec.info/documentation). Since we publish our cukes as documentation, please limit new cucumber scenarios to user-facing examples that help demonstrate usage. Any tests that exist purely to prevent regressions should be written as specs, even if they are written in an acceptance style. Duplication between our YARD API docs and the cucumber documentation is fine. Run with: ``` $ bundle exec cucumber # or, if you installed your bundle with `--standalone --binstubs`: $ bin/cucumber ``` ## YARD documentation RSpec uses [YARD](https://yardoc.org/) for API documentation on the [rspec.info site](https://rspec.info/). Our commitment to [SemVer](https://semver.org) requires that we explicitly declare our public API, and our build uses YARD to ensure that every class, module and method has either been labeled `@private` or has at least some level of documentation. For new APIs, this forces us to make an intentional decision about whether or not it should be part of RSpec's public API or not. To run the YARD documentation coverage check, run: ``` $ bundle exec yard stats --list-undoc # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard stats --list-undoc ``` We also want to prevent YARD errors or warnings when actually generating the docs. To check for those, run: ``` $ bundle exec yard doc --no-cache # or, if you installed your bundle with `--standalone --binstubs`: $ bin/yard doc --no-cache ``` ## RuboCop We use [RuboCop](https://github.com/rubocop-hq/rubocop) to enforce style conventions on the project so that the code has stylistic consistency throughout. Run with: ``` $ bundle exec rubocop lib # or, if you installed your bundle with `--standalone --binstubs`: $ bin/rubocop lib ``` Our RuboCop configuration is a work-in-progress, so if you get a failure due to a RuboCop default, feel free to ask about changing the configuration. Otherwise, you'll need to address the RuboCop failure, or, as a measure of last resort, by wrapping the offending code in comments like `# rubocop:disable SomeCheck` and `# rubocop:enable SomeCheck`. ## Run spec files one-by-one A fast TDD cycle depends upon being able to run a single spec file, without the rest of the test suite. While rare, it's fairly easy to create a situation where a spec passes when the entire suite runs but fails when its individual file is run. To guard against this, our CI build runs each spec file individually, using a bit of bash like: ``` for file in `find spec -iname '*_spec.rb'`; do echo "Running $file" bin/rspec $file -b --format progress done ``` Since this step boots RSpec so many times, it runs much, much faster when we can avoid the overhead of bundler. This is a main reason our CI build installs the bundle with `--standalone --binstubs` and runs RSpec via `bin/rspec` rather than `bundle exec rspec`. ## Running the spec suite for each of the other repos While each of the RSpec repos is an independent gem (generally designed to be usable on its own), there are interdependencies between the gems, and the specs for each tend to use features from the other gems. We don't want to merge a pull request for one repo that might break the build for another repo, so our CI build includes a spec that runs the spec suite of each of the _other_ project repos. Note that we only run the spec suite, not the full build, of the other projects, as the spec suite runs very quickly compared to the full build. ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/Guardfile0000664000000000000000000000035014557700001022225 0ustar rootrootguard 'rspec', :version => 2 do watch(/^spec\/(.*)_spec.rb/) watch(/^lib\/(.*)\.rb/) { |m| "spec/#{m[1]}_spec.rb" } watch(/^spec\/spec_helper.rb/) { "spec" } watch(/^lib\/rspec\/matchers\/built_in/) { "spec" } end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/0000775000000000000000000000000014557700001022220 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/0000775000000000000000000000000014557700001025420 5ustar rootroot././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_matcher_outside_rspec.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_matcher_outside_rs0000664000000000000000000000171414557700001032543 0ustar rootrootFeature: Defining a matcher outside rspec You can define custom matchers when using rspec-expectations outside of rspec-core. Scenario: Define a matcher with default messages Given a file named "test_multiples.rb" with: """ruby require "minitest/autorun" require "rspec/expectations/minitest_integration" RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end end class TestMultiples < Minitest::Test def test_9_should_be_a_multiple_of_3 expect(9).to be_a_multiple_of(3) end def test_9_should_be_a_multiple_of_4 expect(9).to be_a_multiple_of(4) end end """ When I run `ruby test_multiples.rb` Then the exit status should not be 0 And the output should contain "expected 9 to be a multiple of 4" And the output should contain "2 runs, 2 assertions, 1 failures, 0 errors" ././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_matcher_with_fluent_interface.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_matcher_with_fluen0000664000000000000000000000441514557700001032530 0ustar rootrootFeature: Defining a matcher with fluent interface Use the `chain` method to define matchers with a fluent interface. Scenario: Chained method with argument Given a file named "between_spec.rb" with: """ruby RSpec::Matchers.define :be_bigger_than do |first| match do |actual| (actual > first) && (actual < @second) end chain :and_smaller_than do |second| @second = second end end RSpec.describe 5 do it { is_expected.to be_bigger_than(4).and_smaller_than(6) } end """ When I run `rspec between_spec.rb --format documentation` Then the output should contain "1 example, 0 failures" And the output should contain "is expected to be bigger than 4" Scenario: Chained setter Given a file named "between_spec.rb" with: """ruby RSpec::Matchers.define :be_bigger_than do |first| match do |actual| (actual > first) && (actual < second) end chain :and_smaller_than, :second end RSpec.describe 5 do it { is_expected.to be_bigger_than(4).and_smaller_than(6) } end """ When I run `rspec between_spec.rb --format documentation` Then the output should contain "1 example, 0 failures" And the output should contain "is expected to be bigger than 4" Scenario: With `include_chain_clauses_in_custom_matcher_descriptions` configured to true, and chained method with argument Given a file named "between_spec.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec do |c| c.include_chain_clauses_in_custom_matcher_descriptions = true end end RSpec::Matchers.define :be_bigger_than do |first| match do |actual| (actual > first) && (actual < @second) end chain :and_smaller_than do |second| @second = second end end RSpec.describe 5 do it { is_expected.to be_bigger_than(4).and_smaller_than(6) } end """ When I run `rspec between_spec.rb --format documentation` Then the output should contain "1 example, 0 failures" And the output should contain "is expected to be bigger than 4 and smaller than 6" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_matcher.feature0000664000000000000000000003776714557700001031756 0ustar rootrootFeature: Defining a custom matcher rspec-expectations provides a DSL for defining custom matchers. These are often useful for expressing expectations in the domain of your application. Behind the scenes `RSpec::Matchers.define` evaluates the `define` block in the context of a singleton class. If you need to write a more complex matcher and would like to use the `Class`-approach yourself, please head over to our `API`-documentation and read [the docs](http://rspec.info/documentation/latest/rspec-expectations/RSpec/Matchers/MatcherProtocol.html) about the `MatcherProtocol`. Scenario: Define a matcher with default messages Given a file named "matcher_with_default_message_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end end RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } end RSpec.describe 9 do it { is_expected.not_to be_a_multiple_of(4) } end # fail intentionally to generate expected output RSpec.describe 9 do it { is_expected.to be_a_multiple_of(4) } end # fail intentionally to generate expected output RSpec.describe 9 do it { is_expected.not_to be_a_multiple_of(3) } end """ When I run `rspec ./matcher_with_default_message_spec.rb --format documentation` Then the exit status should not be 0 And the output should contain "is expected to be a multiple of 3" And the output should contain "is expected not to be a multiple of 4" And the output should contain "Failure/Error: it { is_expected.to be_a_multiple_of(4) }" And the output should contain "Failure/Error: it { is_expected.not_to be_a_multiple_of(3) }" And the output should contain "4 examples, 2 failures" And the output should contain "expected 9 to be a multiple of 4" And the output should contain "expected 9 not to be a multiple of 3" Scenario: Overriding the failure_message Given a file named "matcher_with_failure_message_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end failure_message do |actual| "expected that #{actual} would be a multiple of #{expected}" end end # fail intentionally to generate expected output RSpec.describe 9 do it { is_expected.to be_a_multiple_of(4) } end """ When I run `rspec ./matcher_with_failure_message_spec.rb` Then the exit status should not be 0 And the stdout should contain "1 example, 1 failure" And the stdout should contain "expected that 9 would be a multiple of 4" Scenario: Overriding the failure_message_when_negated Given a file named "matcher_with_failure_for_message_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end failure_message_when_negated do |actual| "expected that #{actual} would not be a multiple of #{expected}" end end # fail intentionally to generate expected output RSpec.describe 9 do it { is_expected.not_to be_a_multiple_of(3) } end """ When I run `rspec ./matcher_with_failure_for_message_spec.rb` Then the exit status should not be 0 And the stdout should contain "1 example, 1 failure" And the stdout should contain "expected that 9 would not be a multiple of 3" Scenario: Overriding the description Given a file named "matcher_overriding_description_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end description do "be multiple of #{expected}" end end RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } end RSpec.describe 9 do it { is_expected.not_to be_a_multiple_of(4) } end """ When I run `rspec ./matcher_overriding_description_spec.rb --format documentation` Then the exit status should be 0 And the stdout should contain "2 examples, 0 failures" And the stdout should contain "is expected to be multiple of 3" And the stdout should contain "is expected not to be multiple of 4" Scenario: With no args Given a file named "matcher_with_no_args_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :have_7_fingers do match do |thing| thing.fingers.length == 7 end end class Thing def fingers; (1..7).collect {"finger"}; end end RSpec.describe Thing do it { is_expected.to have_7_fingers } end """ When I run `rspec ./matcher_with_no_args_spec.rb --format documentation` Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "is expected to have 7 fingers" Scenario: With multiple args Given a file named "matcher_with_multiple_args_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_the_sum_of do |a,b,c,d| match do |sum| a + b + c + d == sum end end RSpec.describe 10 do it { is_expected.to be_the_sum_of(1,2,3,4) } end """ When I run `rspec ./matcher_with_multiple_args_spec.rb --format documentation` Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "is expected to be the sum of 1, 2, 3, and 4" Scenario: With a block arg Given a file named "matcher_with_block_arg_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :be_lazily_equal_to do match do |obj| obj == block_arg.call end description { "be lazily equal to #{block_arg.call}" } end RSpec.describe 10 do it { is_expected.to be_lazily_equal_to { 10 } } end """ When I run `rspec ./matcher_with_block_arg_spec.rb --format documentation` Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "is expected to be lazily equal to 10" Scenario: With helper methods Given a file named "matcher_with_internal_helper_spec.rb" with: """ruby require 'rspec/expectations' RSpec::Matchers.define :have_same_elements_as do |sample| match do |actual| similar?(sample, actual) end def similar?(a, b) a.sort == b.sort end end RSpec.describe "these two arrays" do specify "should be similar" do expect([1,2,3]).to have_same_elements_as([2,3,1]) end end """ When I run `rspec ./matcher_with_internal_helper_spec.rb` Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" Scenario: Scoped in a module Given a file named "scoped_matcher_spec.rb" with: """ruby require 'rspec/expectations' module MyHelpers extend RSpec::Matchers::DSL matcher :be_just_like do |expected| match {|actual| actual == expected} end end RSpec.describe "group with MyHelpers" do include MyHelpers it "has access to the defined matcher" do expect(5).to be_just_like(5) end end RSpec.describe "group without MyHelpers" do it "does not have access to the defined matcher" do expect do expect(5).to be_just_like(5) end.to raise_exception end end """ When I run `rspec ./scoped_matcher_spec.rb` Then the stdout should contain "2 examples, 0 failures" Scenario: Scoped in an example group Given a file named "scoped_matcher_spec.rb" with: """ruby require 'rspec/expectations' RSpec.describe "group with matcher" do matcher :be_just_like do |expected| match {|actual| actual == expected} end it "has access to the defined matcher" do expect(5).to be_just_like(5) end describe "nested group" do it "has access to the defined matcher" do expect(5).to be_just_like(5) end end end RSpec.describe "group without matcher" do it "does not have access to the defined matcher" do expect do expect(5).to be_just_like(5) end.to raise_exception end end """ When I run `rspec scoped_matcher_spec.rb` Then the output should contain "3 examples, 0 failures" Scenario: Matcher with separate logic for expect().to and expect().not_to Given a file named "matcher_with_separate_should_not_logic_spec.rb" with: """ruby RSpec::Matchers.define :contain do |*expected| match do |actual| expected.all? { |e| actual.include?(e) } end match_when_negated do |actual| expected.none? { |e| actual.include?(e) } end end RSpec.describe [1, 2, 3] do it { is_expected.to contain(1, 2) } it { is_expected.not_to contain(4, 5, 6) } # deliberate failures it { is_expected.to contain(1, 4) } it { is_expected.not_to contain(1, 4) } end """ When I run `rspec matcher_with_separate_should_not_logic_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected [1, 2, 3] to contain 1 and 4 | | expected [1, 2, 3] not to contain 1 and 4 | Scenario: Use define_method to create a helper method with access to matcher params Given a file named "define_method_spec.rb" with: """ruby RSpec::Matchers.define :be_a_multiple_of do |expected| define_method :is_multiple? do |actual| actual % expected == 0 end match { |actual| is_multiple?(actual) } end RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } it { is_expected.not_to be_a_multiple_of(4) } # deliberate failures it { is_expected.to be_a_multiple_of(2) } it { is_expected.not_to be_a_multiple_of(3) } end """ When I run `rspec define_method_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected 9 to be a multiple of 2 | | expected 9 not to be a multiple of 3 | Scenario: Include a module with helper methods in the matcher Given a file named "include_module_spec.rb" with: """ruby module MatcherHelpers def is_multiple?(actual, expected) actual % expected == 0 end end RSpec::Matchers.define :be_a_multiple_of do |expected| include MatcherHelpers match { |actual| is_multiple?(actual, expected) } end RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } it { is_expected.not_to be_a_multiple_of(4) } # deliberate failures it { is_expected.to be_a_multiple_of(2) } it { is_expected.not_to be_a_multiple_of(3) } end """ When I run `rspec include_module_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected 9 to be a multiple of 2 | | expected 9 not to be a multiple of 3 | Scenario: Using values_match? to compare values and/or compound matchers. Given a file named "compare_values_spec.rb" with: """ruby RSpec::Matchers.define :have_content do |expected| match do |actual| # The order of arguments is important for `values_match?`, e.g. # especially if your matcher should handle `Regexp`-objects # (`/regex/`): First comes the `expected` value, second the `actual` # one. values_match? expected, actual end end RSpec.describe 'a' do it { is_expected.to have_content 'a' } end RSpec.describe 'a' do it { is_expected.to have_content /a/ } end RSpec.describe 'a' do it { is_expected.to have_content a_string_starting_with('a') } end """ When I run `rspec ./compare_values_spec.rb --format documentation` Then the exit status should be 0 Scenario: Error handling Make sure your matcher returns either `true` or `false`. Take care to handle exceptions appropriately in your matcher, e.g. most cases you might want your matcher to return `false` if an exception - e.g. ArgumentError - occurs, but there might be edge cases where you want to pass the exception to the user. You should handle each `StandardError` with care! Do not handle them all in one. ```ruby match do |actual| begin '[...] Some code' rescue ArgumentError false end end ``` Given a file named "error_handling_spec.rb" with: """ruby class CustomClass; end RSpec::Matchers.define :is_lower_than do |expected| match do |actual| begin actual < expected rescue ArgumentError false end end end RSpec.describe 1 do it { is_expected.to is_lower_than 2 } end RSpec.describe 1 do it { is_expected.not_to is_lower_than 'a' } end RSpec.describe CustomClass do it { expect { is_expected.not_to is_lower_than 2 }.to raise_error NoMethodError } end """ When I run `rspec ./error_handling_spec.rb --format documentation` Then the exit status should be 0 Scenario: Define aliases for your matcher If you want your matcher to be readable in different contexts, you can use the `.alias_matcher`-method to provide an alias for your matcher. Given a file named "alias_spec.rb" with: """ruby RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end end RSpec::Matchers.alias_matcher :be_n_of , :be_a_multiple_of RSpec.describe 9 do it { is_expected.to be_n_of(3) } end """ When I run `rspec ./alias_spec.rb --format documentation` Then the exit status should be 0 Scenario: With expectation errors that bubble up By default the match block will swallow expectation errors (e.g. caused by using an expectation such as `expect(1).to eq 2`), if you wish to allow these to bubble up, pass in the option `:notify_expectation_failures => true`. Given a file named "bubbling_expectation_errors_spec.rb" with: """ruby RSpec::Matchers.define :be_a_palindrome do match(:notify_expectation_failures => true) do |actual| expect(actual).to be_a(String) expect(actual.reverse).to eq(actual) end end RSpec.describe "a custom matcher that bubbles up expectation errors" do it "bubbles expectation errors" do expect("carriage").to be_a_palindrome end end """ When I run `rspec bubbling_expectation_errors_spec.rb` Then the output should contain all of these: | Failures: | | 1) a custom matcher that bubbles up expectation errors bubbles expectation errors | | Failure/Error: expect(actual.reverse).to eq(actual) | | expected: "carriage" | | got: "egairrac" | | (compared using ==) | | # ./bubbling_expectation_errors_spec.rb:4 | | # ./bubbling_expectation_errors_spec.rb:10 | ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_diffable_matcher.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_diffable_matcher.f0000664000000000000000000000725014557700001032344 0ustar rootrootFeature: Defining a diffable matcher When a matcher is defined as diffable, the output will include a diff of the submitted objects when the objects are more than simple primitives. @skip-when-diff-lcs-1.3 Scenario: Define a diffable matcher (with diff-lcs 1.4) Given a file named "diffable_matcher_spec.rb" with: """ruby RSpec::Matchers.define :be_just_like do |expected| match do |actual| actual == expected end diffable end RSpec.describe "two\nlines" do it { is_expected.to be_just_like("three\nlines") } end """ When I run `rspec ./diffable_matcher_spec.rb` Then it should fail with: """ Diff: @@ -1 +1 @@ -three +two """ @skip-when-diff-lcs-1.4 Scenario: Define a diffable matcher (with diff-lcs 1.3) Given a file named "diffable_matcher_spec.rb" with: """ruby RSpec::Matchers.define :be_just_like do |expected| match do |actual| actual == expected end diffable end RSpec.describe "two\nlines" do it { is_expected.to be_just_like("three\nlines") } end """ When I run `rspec ./diffable_matcher_spec.rb` Then it should fail with: """ Diff: @@ -1,3 +1,3 @@ -three +two lines """ @skip-when-diff-lcs-1.3 @skip-when-diff-lcs-1.4.3 Scenario: Redefine actual (with diff-lcs 1.4.4) Sometimes is necessary to overwrite actual to make diffing work, e.g. if `actual` is a name of a file you want to read from. For this to work you need to overwrite `@actual` in your matcher. Given a file named "redefine_actual_matcher_spec.rb" with: """ruby RSpec::Matchers.define :have_content do |expected| match do |actual| @actual = File.read(actual).chomp values_match? expected, @actual end diffable end RSpec.describe 'Compare files' do context 'when content is equal' do it { expect('data.txt').to have_content 'Data' } end context 'when files are different' do it { expect('data.txt').to have_content "No\nData\nhere" } end end """ And a file named "data.txt" with: """ Data """ When I run `rspec ./redefine_actual_matcher_spec.rb --format documentation` Then the exit status should not be 0 And the output should contain: """ 2 examples, 1 failure """ And the output should contain: """ @@ -1,4 +1,2 @@ -No Data -here """ @skip-when-diff-lcs-1.4 Scenario: Redefine actual (with diff-lcs 1.3) Given a file named "redefine_actual_matcher_spec.rb" with: """ruby RSpec::Matchers.define :have_content do |expected| match do |actual| @actual = File.read(actual).chomp values_match? expected, @actual end diffable end RSpec.describe 'Compare files' do context 'when content is equal' do it { expect('data.txt').to have_content 'Data' } end context 'when files are different' do it { expect('data.txt').to have_content "No\nData\nhere" } end end """ And a file named "data.txt" with: """ Data """ When I run `rspec ./redefine_actual_matcher_spec.rb --format documentation` Then the exit status should not be 0 And the output should contain: """ 2 examples, 1 failure """ And the output should contain: """ @@ -1,4 +1,2 @@ -No Data -here """ ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_block_matcher.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/define_block_matcher.feat0000664000000000000000000000430714557700001032374 0ustar rootrootFeature: Defining a matcher supporting block expectations When you wish to support block expectations (e.g. `expect { ... }.to matcher`) with your custom matchers you must specify this. You can do this manually (or determinately based on some logic) by defining a `supports_block_expectation?` method or by using the DSL's `supports_block_expectations` shortcut method. Scenario: Define a block matcher manually Given a file named "block_matcher_spec.rb" with: """ruby RSpec::Matchers.define :support_blocks do match do |actual| actual.is_a? Proc end def supports_block_expectations? true # or some logic end end RSpec.describe "a custom block matcher" do specify { expect { }.to support_blocks } end """ When I run `rspec ./block_matcher_spec.rb` Then the example should pass Scenario: Define a block matcher using shortcut Given a file named "block_matcher_spec.rb" with: """ruby RSpec::Matchers.define :support_blocks do match do |actual| actual.is_a? Proc end supports_block_expectations end RSpec.describe "a custom block matcher" do specify { expect { }.to support_blocks } end """ When I run `rspec ./block_matcher_spec.rb` Then the example should pass Scenario: Define a block matcher using shortcut Given a file named "block_matcher_spec.rb" with: """ruby RSpec::Matchers.define :support_blocks_with_errors do match(:notify_expectation_failures => true) do |actual| actual.call true end supports_block_expectations end RSpec.describe "a custom block matcher" do specify do expect { expect(true).to eq false }.to support_blocks_with_errors end end """ When I run `rspec ./block_matcher_spec.rb` Then it should fail with: """ Failures: 1) a custom block matcher is expected to support blocks with errors Failure/Error: expect(true).to eq false expected: false got: true (compared using ==) """ ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/access_running_example.featureruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/custom_matchers/access_running_example.fe0000664000000000000000000000264314557700001032455 0ustar rootrootFeature: Access the running example In the context of a custom matcher, you can call helper methods that are available from the current example's example group. This is used, for example, by rspec-rails in order to wrap rails' built-in assertions (which depend on helper methods available in the test context). Scenario: Call method defined on example from matcher Given a file named "example_spec.rb" with: """ruby RSpec::Matchers.define :bar do match do |_| foo == "foo" end end RSpec.describe "something" do def foo "foo" end it "does something" do expect("foo").to bar end end """ When I run `rspec ./example_spec.rb` Then the output should contain "1 example, 0 failures" Scenario: Call method _not_ defined on example from matcher Given a file named "example_spec.rb" with: """ruby RSpec::Matchers.define :bar do match do |_| foo == "foo" end end RSpec.describe "something" do it "does something" do expect("foo").to bar end end """ When I run `rspec ./example_spec.rb` Then the output should contain "1 example, 1 failure" And the output should match /undefined.*method/ And the output should contain "RSpec::Matchers::DSL::Matcher" And the output should not contain "ExampleGroup" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/aggregating_failures.feature0000664000000000000000000000503214557700001027746 0ustar rootrootFeature: Aggregating Failures Normally, an expectation failure causes the example to immediately abort. When you have multiple independent expectations, it's nice to be able to see all of the failures rather than just the first. One solution is to split off a separate example for each expectation, but if the setup for the examples is slow, that's going to take extra time and slow things down. `aggregate_failures` provides an alternate solution. It wraps a set of expectations with a block. Within the block, expectation failures will not immediatly abort like normal; instead, the failures will be aggregated into a single exception that is raised at the end of the block, allowing you to see all expectations that failed. `aggregate_failures` takes an optional string argument that will be used in the aggregated failure message as a label. RSpec::Core expands this feature a bit; see [the rspec-core docs](../rspec-core/expectation-framework-integration/aggregating-failures) for more detail. Note: The implementation of `aggregate_failures` uses a thread-local variable, which means that if you have an expectation failure in another thread, it'll abort like normal. Scenario: Multiple expectation failures within `aggregate_failures` are all reported Given a file named "spec/aggregated_failure_spec.rb" with: """ruby require 'rspec/expectations' include RSpec::Matchers Response = Struct.new(:status, :headers, :body) response = Response.new(404, { "Content-Type" => "text/plain" }, "Not Found") begin aggregate_failures "testing response" do expect(response.status).to eq(200) expect(response.headers["Content-Type"]).to eq("application/json") expect(response.body).to eq('{"message":"Success"}') end rescue RSpec::Expectations::MultipleExpectationsNotMetError => e puts e.message.gsub(/(:in).+/, '') exit(1) end """ When I run `ruby spec/aggregated_failure_spec.rb` Then it should fail with: """ Got 3 failures from failure aggregation block "testing response": 1) expected: 200 got: 404 (compared using ==) spec/aggregated_failure_spec.rb:9 2) expected: "application/json" got: "text/plain" (compared using ==) spec/aggregated_failure_spec.rb:10 3) expected: "{"message":"Success"}" got: "Not Found" (compared using ==) spec/aggregated_failure_spec.rb:11 """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/customized_message.feature0000664000000000000000000000257514557700001027500 0ustar rootrootFeature: Customized message RSpec tries to provide useful failure messages, but for cases in which you want more specific information, you can define your own message right in the example.This works for any matcher _other than the operator matchers_. Scenario: Customize failure message Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do context "when created with `new`" do it "is empty" do array = Array.new array << 1 # trigger a failure to demonstrate the message expect(array).to be_empty, "expected empty array, got #{array.inspect}" end end end """ When I run `rspec example_spec.rb --format documentation` Then the output should contain "expected empty array, got [1]" Scenario: Customize failure message with a proc Given a file named "example_spec.rb" with: """ruby RSpec.describe Array do context "when created with `new`" do it "is empty" do array = Array.new array << 1 # trigger a failure to demonstrate the message expect(array).to be_empty, lambda { "expected empty array, got #{array.inspect}" } end end end """ When I run `rspec example_spec.rb --format documentation` Then the output should contain "expected empty array, got [1]" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/test_frameworks/0000775000000000000000000000000014557700001025437 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/test_frameworks/minitest.feature0000664000000000000000000000727014557700001030656 0ustar rootrootFeature: Minitest integration rspec-expectations is a stand-alone gem that can be used without the rest of RSpec. If you like minitest as your test runner, but prefer RSpec's approach to expressing expectations, you can have both. To integrate rspec-expectations with minitest, require `rspec/expectations/minitest_integration`. Scenario: Use rspec/expectations with minitest Given a file named "rspec_expectations_test.rb" with: """ruby require 'minitest/autorun' require 'rspec/expectations/minitest_integration' class RSpecExpectationsTest < Minitest::Test RSpec::Matchers.define :be_an_integer do match { |actual| Integer === actual } end def be_an_int # This is actually an internal rspec-expectations API, but is used # here to demonstrate that deprecation warnings from within # rspec-expectations work correctly without depending on rspec-core RSpec.deprecate(:be_an_int, :replacement => :be_an_integer) be_an_integer end def test_passing_expectation expect(1 + 3).to eq 4 end def test_failing_expectation expect([1, 2]).to be_empty end def test_custom_matcher_with_deprecation_warning expect(1).to be_an_int end def test_using_aggregate_failures aggregate_failures do expect(1).to be_even expect(2).to be_odd end end end """ When I run `ruby rspec_expectations_test.rb` Then the output should contain "4 runs, 5 assertions, 2 failures, 0 errors" And the output should contain "expected `[1, 2].empty?` to be truthy, got false" And the output should contain "be_an_int is deprecated" And the output should contain "Got 2 failures from failure aggregation block" Scenario: Use rspec/expectations with minitest/spec Given a file named "rspec_expectations_spec.rb" with: """ruby require 'minitest/autorun' require 'minitest/spec' require 'rspec/expectations/minitest_integration' describe "Using RSpec::Expectations with Minitest::Spec" do RSpec::Matchers.define :be_an_integer do match { |actual| Integer === actual } end it 'passes an expectation' do expect(1 + 3).to eq 4 end it 'fails an expectation' do expect([1, 2]).to be_empty end it 'passes a block expectation' do expect { 1 / 0 }.to raise_error(ZeroDivisionError) end it 'fails a block expectation' do expect { 1 / 1 }.to raise_error(ZeroDivisionError) end it 'passes a negative expectation (using `not_to`)' do expect(1).not_to eq 2 end it 'fails a negative expectation (using `to_not`)' do expect(1).to_not eq 1 end it 'fails multiple expectations' do aggregate_failures do expect(1).to be_even expect(2).to be_odd end end it 'passes a minitest expectation' do expect(1 + 3).must_equal 4 end it 'fails a minitest expectation' do expect([1, 2]).must_be :empty? end end """ When I run `ruby rspec_expectations_spec.rb` Then the output should contain "9 runs, 10 assertions, 5 failures, 0 errors" And the output should contain "expected `[1, 2].empty?` to be truthy, got false" And the output should contain "expected ZeroDivisionError but nothing was raised" And the output should contain "Got 2 failures from failure aggregation block" And the output should contain "Expected [1, 2] to be empty?" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/.nav0000664000000000000000000000177014557700001023012 0ustar rootroot- built_in_matchers: - equality.feature - comparisons.feature - predicates.feature - types.feature - all.feature - be.feature - be_within.feature - exist.feature - change.feature - contain_exactly.feature - cover.feature - end_with.feature - exist.feature - have.feature - have_attributes.feature - include.feature - match.feature - operators.feature - raise_error.feature - respond_to.feature - satisfy.feature - start_with.feature - throw_symbol.feature - yield.feature - custom_matchers: - define_matcher.feature - define_diffable_matcher.feature - define_matcher_with_fluent_interface.feature - access_running_example.feature - define_matcher_outside_rspec.feature - aggregating_failures.feature - composing_matchers.feature - compound_expectations.feature - define_negated_matcher.feature - customized_message.feature - diffing.feature - implicit_docstrings.feature - syntax_configuration.feature - test_frameworks: - test_unit.feature - Changelog.md ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/diffing.feature0000664000000000000000000000551114557700001025205 0ustar rootrootFeature: Diffing When appropriate, failure messages will automatically include a diff. Scenario: Diff for a multiline string Given a file named "example_spec.rb" with: """ruby RSpec.describe "a multiline string" do it "is like another string" do expected = <<-EXPECTED this is the expected string EXPECTED actual = <<-ACTUAL this is the actual string ACTUAL expect(actual).to eq(expected) end end """ When I run `rspec example_spec.rb` Then the output should contain: """ Diff: @@ -1,4 +1,4 @@ this is the - expected + actual string """ @skip-when-diff-lcs-1.3 Scenario: Diff for a multiline string and a regexp on diff-lcs 1.4 Given a file named "example_spec.rb" with: """ruby RSpec.describe "a multiline string" do it "is like another string" do expected = /expected/m actual = <<-ACTUAL this is the actual string ACTUAL expect(actual).to match expected end end """ When I run `rspec example_spec.rb` Then the output should contain: """ Diff: @@ -1,3 +1,5 @@ -/expected/m +this is the + actual + string """ @skip-when-diff-lcs-1.4 Scenario: Diff for a multiline string and a regexp on diff-lcs 1.3 Given a file named "example_spec.rb" with: """ruby RSpec.describe "a multiline string" do it "is like another string" do expected = /expected/m actual = <<-ACTUAL this is the actual string ACTUAL expect(actual).to match expected end end """ When I run `rspec example_spec.rb` Then the output should contain: """ Diff: @@ -1,2 +1,4 @@ -/expected/m +this is the + actual + string """ Scenario: No diff for a single line strings Given a file named "example_spec.rb" with: """ruby RSpec.describe "a single line string" do it "is like another string" do expected = "this string" actual = "that string" expect(actual).to eq(expected) end end """ When I run `rspec example_spec.rb` Then the output should not contain "Diff:" Scenario: No diff for numbers Given a file named "example_spec.rb" with: """ruby RSpec.describe "a number" do it "is like another number" do expect(1).to eq(2) end end """ When I run `rspec example_spec.rb` Then the output should not contain "Diff:" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/0000775000000000000000000000000014557700001025713 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/exist.feature0000664000000000000000000000241014557700001030421 0ustar rootrootFeature: `exist` matcher The `exist` matcher is used to specify that something exists (as indicated by `#exist?` or `#exists?`): ```ruby expect(obj).to exist # passes if obj.exist? or obj.exists? ``` Scenario: Basic usage Given a file named "exist_matcher_spec.rb" with: """ruby class Planet attr_reader :name def initialize(name) @name = name end def inspect "" end def exist? # also works with exists? %w[Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune].include?(name) end end RSpec.describe "Earth" do let(:earth) { Planet.new("Earth") } specify { expect(earth).to exist } specify { expect(earth).not_to exist } # deliberate failure end RSpec.describe "Tatooine" do let(:tatooine) { Planet.new("Tatooine") } specify { expect(tatooine).to exist } # deliberate failure specify { expect(tatooine).not_to exist } end """ When I run `rspec exist_matcher_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected not to exist | | expected to exist | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/respond_to.feature0000664000000000000000000002743414557700001031456 0ustar rootrootFeature: `respond_to` matcher Use the `respond_to` matcher to specify details of an object's interface. In its most basic form: ```ruby expect(obj).to respond_to(:foo) # pass if obj.respond_to?(:foo) ``` You can specify that an object responds to multiple messages in a single statement with multiple arguments passed to the matcher: ```ruby expect(obj).to respond_to(:foo, :bar) # passes if obj.respond_to?(:foo) && obj.respond_to?(:bar) ``` If the number of arguments accepted by the method is important to you, you can specify that as well: ```ruby expect(obj).to respond_to(:foo).with(1).argument expect(obj).to respond_to(:bar).with(2).arguments expect(obj).to respond_to(:baz).with(1..2).arguments expect(obj).to respond_to(:xyz).with_unlimited_arguments ``` If your Ruby version supports keyword arguments, you can specify a list of keywords accepted by the method. ```ruby expect(obj).to respond_to(:foo).with_keywords(:ichi, :ni) expect(obj).to respond_to(:bar).with(2).arguments.and_keywords(:san, :yon) expect(obj).to respond_to(:baz).with_arbitrary_keywords ``` Note that this matcher relies entirely upon `#respond_to?`. If an object dynamically responds to a message via `#method_missing`, but does not indicate this via `#respond_to?`, then this matcher will give you false results. Scenario: Basic usage Given a file named "respond_to_matcher_spec.rb" with: """ruby RSpec.describe "a string" do it { is_expected.to respond_to(:length) } it { is_expected.to respond_to(:hash, :class, :to_s) } it { is_expected.not_to respond_to(:to_model) } it { is_expected.not_to respond_to(:compact, :flatten) } # deliberate failures it { is_expected.to respond_to(:to_model) } it { is_expected.to respond_to(:compact, :flatten) } it { is_expected.not_to respond_to(:length) } it { is_expected.not_to respond_to(:hash, :class, :to_s) } # mixed examples--String responds to :length but not :flatten # both specs should fail it { is_expected.to respond_to(:length, :flatten) } it { is_expected.not_to respond_to(:length, :flatten) } end """ When I run `rspec respond_to_matcher_spec.rb` Then the output should contain all of these: | 10 examples, 6 failures | | expected "a string" to respond to :to_model | | expected "a string" to respond to :compact, :flatten | | expected "a string" not to respond to :length | | expected "a string" not to respond to :hash, :class, :to_s | | expected "a string" to respond to :flatten | | expected "a string" not to respond to :length | Scenario: Specify arguments Given a file named "respond_to_matcher_argument_checking_spec.rb" with: """ruby RSpec.describe 7 do it { is_expected.to respond_to(:zero?).with(0).arguments } it { is_expected.not_to respond_to(:zero?).with(1).argument } it { is_expected.to respond_to(:between?).with(2).arguments } it { is_expected.not_to respond_to(:between?).with(7).arguments } # deliberate failures it { is_expected.to respond_to(:zero?).with(1).argument } it { is_expected.not_to respond_to(:zero?).with(0).arguments } it { is_expected.to respond_to(:between?).with(7).arguments } it { is_expected.not_to respond_to(:between?).with(2).arguments } end """ When I run `rspec respond_to_matcher_argument_checking_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected 7 to respond to :zero? with 1 argument | | expected 7 not to respond to :zero? with 0 arguments | | expected 7 to respond to :between? with 7 arguments | | expected 7 not to respond to :between? with 2 arguments | @skip-when-splat-args-unsupported Scenario: Specify arguments range Given a file named "respond_to_matcher_argument_range_checking_spec.rb" with: """ruby class MyClass def build(name, options = {}) end def inspect 'my_object' end end RSpec.describe MyClass do it { is_expected.to respond_to(:build).with(1..2).arguments } it { is_expected.not_to respond_to(:build).with(0..1).arguments } it { is_expected.not_to respond_to(:build).with(2..3).arguments } it { is_expected.not_to respond_to(:build).with(0..3).arguments } # deliberate failures it { is_expected.not_to respond_to(:build).with(1..2).arguments } it { is_expected.to respond_to(:build).with(0..1).arguments } it { is_expected.to respond_to(:build).with(2..3).arguments } it { is_expected.to respond_to(:build).with(0..3).arguments } end """ When I run `rspec respond_to_matcher_argument_range_checking_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected my_object not to respond to :build with 1..2 arguments | | expected my_object to respond to :build with 0..1 arguments | | expected my_object to respond to :build with 2..3 arguments | | expected my_object to respond to :build with 0..3 arguments | @skip-when-splat-args-unsupported Scenario: Specify unlimited arguments Given a file named "respond_to_matcher_unlimited_argument_checking_spec.rb" with: """ruby class MyClass def greet(message = 'Hello', *people) end def hail(person) end def inspect 'my_object' end end RSpec.describe MyClass do it { is_expected.to respond_to(:greet).with_unlimited_arguments } it { is_expected.to respond_to(:greet).with(1).argument.and_unlimited_arguments } it { is_expected.not_to respond_to(:hail).with_unlimited_arguments } it { is_expected.not_to respond_to(:hail).with(1).argument.and_unlimited_arguments } # deliberate failures it { is_expected.not_to respond_to(:greet).with_unlimited_arguments } it { is_expected.not_to respond_to(:greet).with(1).argument.and_unlimited_arguments } it { is_expected.to respond_to(:hail).with_unlimited_arguments } it { is_expected.to respond_to(:hail).with(1).argument.and_unlimited_arguments } end """ When I run `rspec respond_to_matcher_unlimited_argument_checking_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected my_object not to respond to :greet with unlimited arguments | | expected my_object not to respond to :greet with 1 argument and unlimited arguments | | expected my_object to respond to :hail with unlimited arguments | | expected my_object to respond to :hail with 1 argument and unlimited arguments | @skip-when-keyword-args-unsupported Scenario: Specify keywords Given a file named "respond_to_matcher_keyword_checking_spec.rb" with: """ruby class MyClass def find(name = 'id', limit: 1_000, offset: 0) [] end def inspect 'my_object' end end RSpec.describe MyClass do it { is_expected.to respond_to(:find).with_keywords(:limit, :offset) } it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) } it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset, :page) } it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) } # deliberate failures it { is_expected.to respond_to(:find).with_keywords(:limit, :offset, :page) } it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) } it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset) } it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) } end """ When I run `rspec respond_to_matcher_keyword_checking_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected my_object to respond to :find with keywords :limit, :offset, and :page | | expected my_object to respond to :find with 1 argument and keywords :limit, :offset, and :page | | expected my_object not to respond to :find with keywords :limit and :offset | | expected my_object not to respond to :find with 1 argument and keywords :limit and :offset | @skip-when-keyword-args-unsupported Scenario: Specify any keywords Given a file named "respond_to_matcher_any_keywords_checking_spec.rb" with: """ruby class MyClass def build(name: 'object', **opts) end def create(name: 'object', type: String) end def inspect 'my_object' end end RSpec.describe MyClass do it { is_expected.to respond_to(:build).with_any_keywords } it { is_expected.to respond_to(:build).with_keywords(:name).and_any_keywords } it { is_expected.not_to respond_to(:create).with_any_keywords } it { is_expected.not_to respond_to(:create).with_keywords(:name).and_any_keywords } # deliberate failures it { is_expected.not_to respond_to(:build).with_any_keywords } it { is_expected.not_to respond_to(:build).with_keywords(:name).and_any_keywords } it { is_expected.to respond_to(:create).with_any_keywords } it { is_expected.to respond_to(:create).with_keywords(:name).and_any_keywords } end """ When I run `rspec respond_to_matcher_any_keywords_checking_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected my_object not to respond to :build with any keywords | | expected my_object not to respond to :build with keyword :name and any keywords | | expected my_object to respond to :create with any keywords | | expected my_object to respond to :create with keyword :name and any keywords | @skip-when-required-keyword-args-unsupported Scenario: Specify required keywords Given a file named "respond_to_matcher_required_keyword_checking_spec.rb" with: """ruby class MyClass def plant(seed:, fertilizer: nil, water: 'daily') [] end def inspect 'my_object' end end RSpec.describe MyClass do it { is_expected.to respond_to(:plant).with_keywords(:seed) } it { is_expected.to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) } it { is_expected.not_to respond_to(:plant).with_keywords(:fertilizer, :water) } # deliberate failures it { is_expected.not_to respond_to(:plant).with_keywords(:seed) } it { is_expected.not_to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) } it { is_expected.to respond_to(:plant).with_keywords(:fertilizer, :water) } end """ When I run `rspec respond_to_matcher_required_keyword_checking_spec.rb` Then the output should contain all of these: | 6 examples, 3 failures | | expected my_object not to respond to :plant with keyword :seed | | expected my_object not to respond to :plant with keywords :seed, :fertilizer, and :water | | expected my_object to respond to :plant with keywords :fertilizer and :water | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/yield.feature0000664000000000000000000002024014557700001030374 0ustar rootrootFeature: `yield` matchers There are four related matchers that allow you to specify whether or not a method yields, how many times it yields, whether or not it yields with arguments, and what those arguments are. * `yield_control` matches if the method-under-test yields, regardless of whether or not arguments are yielded. * `yield_with_args` matches if the method-under-test yields with arguments. If arguments are provided to this matcher, it will only pass if the actual yielded arguments match the expected ones using `===` or `==`. * `yield_with_no_args` matches if the method-under-test yields with no arguments. * `yield_successive_args` is designed for iterators, and will match if the method-under-test yields the same number of times as arguments passed to this matcher, and all actual yielded arguments match the expected ones using `===` or `==`. Note: your expect block _must_ accept an argument that is then passed on to the method-under-test as a block. This acts as a "probe" that allows the matcher to detect whether or not your method yields, and, if so, how many times and what the yielded arguments are. Background: Given a file named "my_class.rb" with: """ruby class MyClass def self.yield_once_with(*args) yield *args end def self.yield_twice_with(*args) 2.times { yield *args } end def self.raw_yield yield end def self.dont_yield end end """ Scenario: The `yield_control` matcher Given a file named "yield_control_spec.rb" with: """ruby require './my_class' RSpec.describe "yield_control matcher" do specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control } specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_control } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.twice } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.exactly(2).times } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_least(1) } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_most(3).times } # deliberate failures specify { expect { |b| MyClass.yield_once_with(1, &b) }.not_to yield_control } specify { expect { |b| MyClass.dont_yield(&b) }.to yield_control } specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control.at_least(2).times } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.twice } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(2).times } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(1) } specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_most(3).times } end """ When I run `rspec yield_control_spec.rb` Then the output should contain all of these: | 13 examples, 7 failures | | expected given block to yield control | | expected given block not to yield control | | expected given block not to yield control at least twice | | expected given block not to yield control at most 3 times | Scenario: The `yield_with_args` matcher Given a file named "yield_with_args_spec.rb" with: """ruby require './my_class' RSpec.describe "yield_with_args matcher" do specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args("foo") } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(String) } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(/oo/) } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args("foo", "bar") } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(String, String) } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(/fo/, /ar/) } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args(17, "baz") } # deliberate failures specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args("foo") } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(String) } specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(/oo/) } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args("foo", "bar") } specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(17, "baz") } end """ When I run `rspec yield_with_args_spec.rb` Then the output should contain all of these: | 14 examples, 6 failures | | expected given block not to yield with arguments, but did | | expected given block not to yield with arguments, but yielded with expected arguments | | expected given block to yield with arguments, but yielded with unexpected arguments | Scenario: The `yield_with_no_args` matcher Given a file named "yield_with_no_args_spec.rb" with: """ruby require './my_class' RSpec.describe "yield_with_no_args matcher" do specify { expect { |b| MyClass.raw_yield(&b) }.to yield_with_no_args } specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_with_no_args } specify { expect { |b| MyClass.yield_once_with("a", &b) }.not_to yield_with_no_args } # deliberate failures specify { expect { |b| MyClass.raw_yield(&b) }.not_to yield_with_no_args } specify { expect { |b| MyClass.dont_yield(&b) }.to yield_with_no_args } specify { expect { |b| MyClass.yield_once_with("a", &b) }.to yield_with_no_args } end """ When I run `rspec yield_with_no_args_spec.rb` Then the output should contain all of these: | 6 examples, 3 failures | | expected given block not to yield with no arguments, but did | | expected given block to yield with no arguments, but did not yield | | expected given block to yield with no arguments, but yielded with arguments: ["a"] | Scenario: The `yield_successive_args` matcher Given a file named "yield_successive_args_spec.rb" with: """ruby def array [1, 2, 3] end def array_of_tuples [[:a, :b], [:c, :d]] end RSpec.describe "yield_successive_args matcher" do specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2, 3) } specify { expect { |b| array_of_tuples.each(&b) }.to yield_successive_args([:a, :b], [:c, :d]) } specify { expect { |b| array.each(&b) }.to yield_successive_args(Integer, Integer, Integer) } specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2) } # deliberate failures specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2, 3) } specify { expect { |b| array_of_tuples.each(&b) }.not_to yield_successive_args([:a, :b], [:c, :d]) } specify { expect { |b| array.each(&b) }.not_to yield_successive_args(Integer, Integer, Integer) } specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2) } end """ When I run `rspec yield_successive_args_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected given block not to yield successively with arguments, but yielded with expected arguments | | expected given block to yield successively with arguments, but yielded with unexpected arguments | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/be_within.feature0000664000000000000000000000330314557700001031237 0ustar rootrootFeature: `be_within` matcher Normal equality expectations do not work well for floating point values. Consider this irb session: > radius = 3 => 3 > area_of_circle = radius * radius * Math::PI => 28.2743338823081 > area_of_circle == 28.2743338823081 => false Instead, you should use the `be_within` matcher to check that the value is within a delta of your expected value: ```ruby expect(area_of_circle).to be_within(0.1).of(28.3) ``` Note that the difference between the actual and expected values must be smaller than your delta; if it is equal, the matcher will fail. Scenario: Basic usage Given a file named "be_within_matcher_spec.rb" with: """ruby RSpec.describe 27.5 do it { is_expected.to be_within(0.5).of(27.9) } it { is_expected.to be_within(0.5).of(28.0) } it { is_expected.to be_within(0.5).of(27.1) } it { is_expected.to be_within(0.5).of(27.0) } it { is_expected.not_to be_within(0.5).of(28.1) } it { is_expected.not_to be_within(0.5).of(26.9) } # deliberate failures it { is_expected.not_to be_within(0.5).of(28) } it { is_expected.not_to be_within(0.5).of(27) } it { is_expected.to be_within(0.5).of(28.1) } it { is_expected.to be_within(0.5).of(26.9) } end """ When I run `rspec be_within_matcher_spec.rb` Then the output should contain all of these: | 10 examples, 4 failures | | expected 27.5 not to be within 0.5 of 28 | | expected 27.5 not to be within 0.5 of 27 | | expected 27.5 to be within 0.5 of 28.1 | | expected 27.5 to be within 0.5 of 26.9 | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/equality.feature0000664000000000000000000001013014557700001031120 0ustar rootrootFeature: Equality matchers Ruby exposes several different methods for handling equality: a.equal?(b) # object identity - a and b refer to the same object a.eql?(b) # object equivalence - a and b have the same value a == b # object equivalence - a and b have the same value with type conversions Note that these descriptions are guidelines but are not forced by the language. Any object can implement any of these methods with its own semantics. rspec-expectations ships with matchers that align with each of these methods: ```ruby expect(a).to equal(b) # passes if a.equal?(b) expect(a).to eql(b) # passes if a.eql?(b) expect(a).to be == b # passes if a == b ``` It also ships with two matchers that have more of a DSL feel to them: ```ruby expect(a).to be(b) # passes if a.equal?(b) expect(a).to eq(b) # passes if a == b ``` Scenario: Compare using eq (==) Given a file named "compare_using_eq.rb" with: """ruby RSpec.describe "a string" do it "is equal to another string of the same value" do expect("this string").to eq("this string") end it "is not equal to another string of a different value" do expect("this string").not_to eq("a different string") end end RSpec.describe "an integer" do it "is equal to a float of the same value" do expect(5).to eq(5.0) end end """ When I run `rspec compare_using_eq.rb` Then the output should contain "3 examples, 0 failures" Scenario: Compare using == Given a file named "compare_using_==.rb" with: """ruby RSpec.describe "a string" do it "is equal to another string of the same value" do expect("this string").to be == "this string" end it "is not equal to another string of a different value" do expect("this string").not_to be == "a different string" end end RSpec.describe "an integer" do it "is equal to a float of the same value" do expect(5).to be == 5.0 end end """ When I run `rspec compare_using_==.rb` Then the output should contain "3 examples, 0 failures" Scenario: Compare using eql (eql?) Given a file named "compare_using_eql.rb" with: """ruby RSpec.describe "an integer" do it "is equal to another integer of the same value" do expect(5).to eql(5) end it "is not equal to another integer of a different value" do expect(5).not_to eql(6) end it "is not equal to a float of the same value" do expect(5).not_to eql(5.0) end end """ When I run `rspec compare_using_eql.rb` Then the output should contain "3 examples, 0 failures" Scenario: Compare using equal (equal?) Given a file named "compare_using_equal.rb" with: """ruby RSpec.describe "a string" do it "is equal to itself" do string = "this string" expect(string).to equal(string) end it "is not equal to another string of the same value" do expect("this string").not_to equal("this string") end it "is not equal to another string of a different value" do expect("this string").not_to equal("a different string") end end """ When I run `rspec compare_using_equal.rb` Then the output should contain "3 examples, 0 failures" Scenario: Compare using be (equal?) Given a file named "compare_using_be.rb" with: """ruby RSpec.describe "a string" do it "is equal to itself" do string = "this string" expect(string).to be(string) end it "is not equal to another string of the same value" do expect("this string").not_to be("this string") end it "is not equal to another string of a different value" do expect("this string").not_to be("a different string") end end """ When I run `rspec compare_using_be.rb` Then the output should contain "3 examples, 0 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/all.feature0000664000000000000000000000501414557700001030040 0ustar rootrootFeature: `all` matcher Use the `all` matcher to specify that a collection's objects all pass an expected matcher. This works on any enumerable object. ```ruby expect([1, 3, 5]).to all( be_odd ) expect([1, 3, 5]).to all( be_an(Integer) ) expect([1, 3, 5]).to all( be < 10 ) expect([1, 3, 4]).to all( be_odd ) # fails ``` The matcher also supports compound matchers: ```ruby expect([1, 3, 5]).to all( be_odd.and be < 10 ) expect([1, 4, 21]).to all( be_odd.or be < 10 ) ``` If you are looking for "any" member of a collection that passes an expectation, look at the `include`-matcher. Scenario: Array usage Given a file named "array_all_matcher_spec.rb" with: """ruby RSpec.describe [1, 3, 5] do it { is_expected.to all( be_odd ) } it { is_expected.to all( be_an(Integer) ) } it { is_expected.to all( be < 10 ) } # deliberate failures it { is_expected.to all( be_even ) } it { is_expected.to all( be_a(String) ) } it { is_expected.to all( be > 2 ) } end """ When I run `rspec array_all_matcher_spec.rb` Then the output should contain all of these: | 6 examples, 3 failures | | expected [1, 3, 5] to all be even | | expected [1, 3, 5] to all be a kind of String | | expected [1, 3, 5] to all be > 2 | Scenario: Compound matcher usage Given a file named "compound_all_matcher_spec.rb" with: """ruby RSpec.describe ['anything', 'everything', 'something'] do it { is_expected.to all( be_a(String).and include("thing") ) } it { is_expected.to all( be_a(String).and end_with("g") ) } it { is_expected.to all( start_with("s").or include("y") ) } # deliberate failures it { is_expected.to all( include("foo").and include("bar") ) } it { is_expected.to all( be_a(String).and start_with("a") ) } it { is_expected.to all( start_with("a").or include("z") ) } end """ When I run `rspec compound_all_matcher_spec.rb` Then the output should contain all of these: | 6 examples, 3 failures | | expected ["anything", "everything", "something"] to all include "foo" and include "bar" | | expected ["anything", "everything", "something"] to all be a kind of String and start with "a" | | expected ["anything", "everything", "something"] to all start with "a" or include "z" | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/contain_exactly.feature0000664000000000000000000000465114557700001032462 0ustar rootrootFeature: `contain_exactly` matcher The `contain_exactly` matcher provides a way to test arrays against each other in a way that disregards differences in the ordering between the actual and expected array. For example: ```ruby expect([1, 2, 3]).to contain_exactly(2, 3, 1) # pass expect([:a, :c, :b]).to contain_exactly(:a, :c ) # fail ``` This matcher is also available as `match_array`, which expects the expected array to be given as a single array argument rather than as individual splatted elements. The above could also be written as: ```ruby expect([1, 2, 3]).to match_array [2, 3, 1] # pass expect([:a, :c, :b]).to match_array [:a, :c] # fail ``` Scenario: Array is expected to contain every value Given a file named "contain_exactly_matcher_spec.rb" with: """ruby RSpec.describe [1, 2, 3] do it { is_expected.to contain_exactly(1, 2, 3) } it { is_expected.to contain_exactly(1, 3, 2) } it { is_expected.to contain_exactly(2, 1, 3) } it { is_expected.to contain_exactly(2, 3, 1) } it { is_expected.to contain_exactly(3, 1, 2) } it { is_expected.to contain_exactly(3, 2, 1) } # deliberate failures it { is_expected.to contain_exactly(1, 2, 1) } end """ When I run `rspec contain_exactly_matcher_spec.rb` Then the output should contain "7 examples, 1 failure" And the output should contain: """ Failure/Error: it { is_expected.to contain_exactly(1, 2, 1) } expected collection contained: [1, 1, 2] actual collection contained: [1, 2, 3] the missing elements were: [1] the extra elements were: [3] """ Scenario: Array is not expected to contain every value Given a file named "contain_exactly_matcher_spec.rb" with: """ruby RSpec.describe [1, 2, 3] do it { is_expected.to_not contain_exactly(1, 2, 3, 4) } it { is_expected.to_not contain_exactly(1, 2) } # deliberate failures it { is_expected.to_not contain_exactly(1, 3, 2) } end """ When I run `rspec contain_exactly_matcher_spec.rb` Then the output should contain "3 examples, 1 failure" And the output should contain: """ Failure/Error: it { is_expected.to_not contain_exactly(1, 3, 2) } expected [1, 2, 3] not to contain exactly 1, 3, and 2 """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/be.feature0000664000000000000000000001227714557700001027667 0ustar rootrootFeature: `be` matchers There are several related "be" matchers: ```ruby expect(obj).to be_truthy # passes if obj is truthy (not nil or false) expect(obj).to be_falsey # passes if obj is falsy (nil or false) expect(obj).to be_nil # passes if obj is nil expect(obj).to be # passes if obj is truthy (not nil or false) ``` Scenario: The `be_truthy` matcher Given a file named "be_truthy_spec.rb" with: """ruby RSpec.describe "be_truthy matcher" do specify { expect(true).to be_truthy } specify { expect(7).to be_truthy } specify { expect("foo").to be_truthy } specify { expect(nil).not_to be_truthy } specify { expect(false).not_to be_truthy } # deliberate failures specify { expect(true).not_to be_truthy } specify { expect(7).not_to be_truthy } specify { expect("foo").not_to be_truthy } specify { expect(nil).to be_truthy } specify { expect(false).to be_truthy } end """ When I run `rspec be_truthy_spec.rb` Then the output should contain "10 examples, 5 failures" And the output should contain: """ expected: falsey value got: true """ And the output should contain: """ expected: falsey value got: 7 """ And the output should contain: """ expected: falsey value got: "foo" """ And the output should contain: """ expected: truthy value got: nil """ And the output should contain: """ expected: truthy value got: false """ Scenario: The `be_falsey` matcher Given a file named "be_falsey_spec.rb" with: """ruby RSpec.describe "be_falsey matcher" do specify { expect(nil).to be_falsey } specify { expect(false).to be_falsey } specify { expect(true).not_to be_falsey } specify { expect(7).not_to be_falsey } specify { expect("foo").not_to be_falsey } # deliberate failures specify { expect(nil).not_to be_falsey } specify { expect(false).not_to be_falsey } specify { expect(true).to be_falsey } specify { expect(7).to be_falsey } specify { expect("foo").to be_falsey } end """ When I run `rspec be_falsey_spec.rb` Then the output should contain "10 examples, 5 failures" And the output should contain: """ expected: truthy value got: nil """ And the output should contain: """ expected: truthy value got: false """ And the output should contain: """ expected: falsey value got: true """ And the output should contain: """ expected: falsey value got: 7 """ And the output should contain: """ expected: falsey value got: "foo" """ Scenario: The `be_nil` matcher Given a file named "be_nil_spec.rb" with: """ruby RSpec.describe "be_nil matcher" do specify { expect(nil).to be_nil } specify { expect(false).not_to be_nil } specify { expect(true).not_to be_nil } specify { expect(7).not_to be_nil } specify { expect("foo").not_to be_nil } # deliberate failures specify { expect(nil).not_to be_nil } specify { expect(false).to be_nil } specify { expect(true).to be_nil } specify { expect(7).to be_nil } specify { expect("foo").to be_nil } end """ When I run `rspec be_nil_spec.rb` Then the output should contain "10 examples, 5 failures" And the output should contain: """ expected: not nil got: nil """ And the output should contain: """ expected: nil got: false """ And the output should contain: """ expected: nil got: true """ And the output should contain: """ expected: nil got: 7 """ And the output should contain: """ expected: nil got: "foo" """ Scenario: The `be` matcher Given a file named "be_spec.rb" with: """ruby RSpec.describe "be_matcher" do specify { expect(true).to be } specify { expect(7).to be } specify { expect("foo").to be } specify { expect(nil).not_to be } specify { expect(false).not_to be } # deliberate failures specify { expect(true).not_to be } specify { expect(7).not_to be } specify { expect("foo").not_to be } specify { expect(nil).to be } specify { expect(false).to be } end """ When I run `rspec be_spec.rb` Then the output should contain all of these: | 10 examples, 5 failures | | expected true to evaluate to false | | expected 7 to evaluate to false | | expected "foo" to evaluate to false | | expected nil to evaluate to true | | expected false to evaluate to true | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/have_attributes.feature0000664000000000000000000000371414557700001032466 0ustar rootrootFeature: `have_attributes` matcher Use the have_attributes matcher to specify that an object's attributes match the expected attributes: ```ruby Person = Struct.new(:name, :age) person = Person.new("Jim", 32) expect(person).to have_attributes(:name => "Jim", :age => 32) expect(person).to have_attributes(:name => a_string_starting_with("J"), :age => (a_value > 30) ) ``` The matcher will fail if actual doesn't respond to any of the expected attributes: ```ruby expect(person).to have_attributes(:name => "Jim", :color => 'red') ``` Scenario: Basic usage Given a file named "basic_have_attributes_matcher_spec.rb" with: """ruby Person = Struct.new(:name, :age) RSpec.describe Person.new("Jim", 32) do it { is_expected.to have_attributes(:name => "Jim") } it { is_expected.to have_attributes(:name => a_string_starting_with("J") ) } it { is_expected.to have_attributes(:age => 32) } it { is_expected.to have_attributes(:age => (a_value > 30) ) } it { is_expected.to have_attributes(:name => "Jim", :age => 32) } it { is_expected.to have_attributes(:name => a_string_starting_with("J"), :age => (a_value > 30) ) } it { is_expected.not_to have_attributes(:name => "Bob") } it { is_expected.not_to have_attributes(:age => 10) } it { is_expected.not_to have_attributes(:age => (a_value < 30) ) } # deliberate failures it { is_expected.to have_attributes(:name => "Bob") } it { is_expected.to have_attributes(:age => 10) } # fails if any of the attributes don't match it { is_expected.to have_attributes(:name => "Bob", :age => 32) } it { is_expected.to have_attributes(:name => "Jim", :age => 10) } it { is_expected.to have_attributes(:name => "Bob", :age => 10) } end """ When I run `rspec basic_have_attributes_matcher_spec.rb` Then the output should contain "14 examples, 5 failures" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/satisfy.feature0000664000000000000000000000275514557700001030763 0ustar rootrootFeature: `satisfy` matcher The `satisfy` matcher is extremely flexible and can handle almost anything you want to specify. It passes if the block you provide returns true: ```ruby expect(10).to satisfy { |v| v % 5 == 0 } expect(7).not_to satisfy { |v| v % 5 == 0 } ``` The default failure message ("expected [actual] to satisfy block") is not very descriptive or helpful. To add clarification, you can provide your own description as an argument: ```ruby expect(10).to satisfy("be a multiple of 5") do |v| v % 5 == 0 end ``` @skip-when-ripper-unsupported Scenario: Basic usage Given a file named "satisfy_matcher_spec.rb" with: """ruby RSpec.describe 10 do it { is_expected.to satisfy { |v| v > 5 } } it { is_expected.not_to satisfy { |v| v > 15 } } # deliberate failures it { is_expected.not_to satisfy { |v| v > 5 } } it { is_expected.to satisfy { |v| v > 15 } } it { is_expected.to_not satisfy("be greater than 5") { |v| v > 5 } } it { is_expected.to satisfy("be greater than 15") { |v| v > 15 } } end """ When I run `rspec satisfy_matcher_spec.rb` Then the output should contain all of these: | 6 examples, 4 failures | | expected 10 not to satisfy expression `v > 5` | | expected 10 to satisfy expression `v > 15` | | expected 10 not to be greater than 5 | | expected 10 to be greater than 15 | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/output.feature0000664000000000000000000001676514557700001030647 0ustar rootrootFeature: `output` matcher The `output` matcher provides a way to assert that the block has emitted content to either `$stdout` or `$stderr`. With no arg, passes if the block outputs `to_stdout` or `to_stderr`. With a string, passes if the blocks outputs that specific string `to_stdout` or `to_stderr`. With a regexp or matcher, passes if the blocks outputs a string `to_stdout` or `to_stderr` that matches. Note: `to_stdout` and `to_stderr` work by temporarily replacing `$stdout` or `$stderr`, so they're not able to intercept stream output that explicitly uses `STDOUT`/`STDERR` or that uses a reference to `$stdout`/`$stderr` that was stored before the matcher is used. To capture output from any spawned subprocess as well, use `to_stdout_from_any_process` or `to_stderr_from_any_process`. Output from any process that inherits the main process's corresponding standard stream will be captured. Note: `to_stdout_from_any_process` and `to_stderr_from_any_process` use tempfiles to capture output, and are thus significantly (~30x) slower than `to_stdout` and `to_stderr`. Scenario: Using the `output_to_stdout` matcher Given a file named "output_to_stdout_spec.rb" with: """ruby RSpec.describe "output.to_stdout matcher" do specify { expect { print('foo') }.to output.to_stdout } specify { expect { print('foo') }.to output('foo').to_stdout } specify { expect { print('foo') }.to output(/foo/).to_stdout } specify { expect { }.to_not output.to_stdout } specify { expect { print('foo') }.to_not output('bar').to_stdout } specify { expect { print('foo') }.to_not output(/bar/).to_stdout } # deliberate failures specify { expect { }.to output.to_stdout } specify { expect { }.to output('foo').to_stdout } specify { expect { print('foo') }.to_not output.to_stdout } specify { expect { print('foo') }.to output('bar').to_stdout } specify { expect { print('foo') }.to output(/bar/).to_stdout } end """ When I run `rspec output_to_stdout_spec.rb` Then the output should contain all of these: | 11 examples, 5 failures | | expected block to output to stdout, but did not | | expected block to not output to stdout, but output "foo" | | expected block to output "bar" to stdout, but output "foo" | | expected block to output "foo" to stdout, but output nothing | | expected block to output /bar/ to stdout, but output "foo" | Scenario: Using the `output_to_stderr` matcher Given a file named "output_to_stderr.rb" with: """ruby RSpec.describe "output_to_stderr matcher" do specify { expect { warn('foo') }.to output.to_stderr } specify { expect { warn('foo') }.to output("foo\n").to_stderr } specify { expect { warn('foo') }.to output(/foo/).to_stderr } specify { expect { }.to_not output.to_stderr } specify { expect { warn('foo') }.to_not output('bar').to_stderr } specify { expect { warn('foo') }.to_not output(/bar/).to_stderr } # deliberate failures specify { expect { }.to output.to_stderr } specify { expect { }.to output('foo').to_stderr } specify { expect { warn('foo') }.to_not output.to_stderr } specify { expect { warn('foo') }.to output('bar').to_stderr } specify { expect { warn('foo') }.to output(/bar/).to_stderr } end """ When I run `rspec output_to_stderr.rb` Then the output should contain all of these: | 11 examples, 5 failures | | expected block to output to stderr, but did not | | expected block to not output to stderr, but output "foo | | expected block to output "bar" to stderr, but output "foo\n" | | expected block to output "foo" to stderr, but output nothing | | expected block to output /bar/ to stderr, but output "foo\n" | Scenario: Using the `output_to_stdout_from_any_process` matcher Given a file named "output_to_stdout_from_any_process_spec.rb" with: """ruby RSpec.describe "output.to_stdout_from_any_process matcher" do specify { expect { system('printf foo') }.to output.to_stdout_from_any_process } specify { expect { system('printf foo') }.to output("foo").to_stdout_from_any_process } specify { expect { system('printf foo') }.to output(/foo/).to_stdout_from_any_process } specify { expect { }.to_not output.to_stdout_from_any_process } specify { expect { system('printf foo') }.to_not output("bar").to_stdout_from_any_process } specify { expect { system('printf foo') }.to_not output(/bar/).to_stdout_from_any_process } # deliberate failures specify { expect { }.to output.to_stdout_from_any_process } specify { expect { }.to output('foo').to_stdout_from_any_process } specify { expect { system('printf foo') }.to_not output.to_stdout_from_any_process } specify { expect { system('printf foo') }.to output('bar').to_stdout_from_any_process } specify { expect { system('printf foo') }.to output(/bar/).to_stdout_from_any_process } end """ When I run `rspec output_to_stdout_from_any_process_spec.rb` Then the output should contain all of these: | 11 examples, 5 failures | | expected block to output to stdout, but did not | | expected block to not output to stdout, but output "foo" | | expected block to output "bar" to stdout, but output "foo" | | expected block to output "foo" to stdout, but output nothing | | expected block to output /bar/ to stdout, but output "foo" | Scenario: Using the `output_to_stderr_from_any_process` matcher Given a file named "output_to_stderr_from_any_process_spec.rb" with: """ruby RSpec.describe "output.to_stderr_from_any_process matcher" do specify { expect { system('printf foo 1>&2') }.to output.to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to output("foo").to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to output(/foo/).to_stderr_from_any_process } specify { expect { }.to_not output.to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to_not output("bar").to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to_not output(/bar/).to_stderr_from_any_process } # deliberate failures specify { expect { }.to output.to_stderr_from_any_process } specify { expect { }.to output('foo').to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to_not output.to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to output('bar').to_stderr_from_any_process } specify { expect { system('printf foo 1>&2') }.to output(/bar/).to_stderr_from_any_process } end """ When I run `rspec output_to_stderr_from_any_process_spec.rb` Then the output should contain all of these: | 11 examples, 5 failures | | expected block to output to stderr, but did not | | expected block to not output to stderr, but output "foo" | | expected block to output "bar" to stderr, but output "foo" | | expected block to output "foo" to stderr, but output nothing | | expected block to output /bar/ to stderr, but output "foo" | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/match.feature0000664000000000000000000000324114557700001030364 0ustar rootrootFeature: `match` matcher The `match` matcher calls `#match` on the object, passing if `#match` returns a truthy (not `false` or `nil`) value. `Regexp` and `String` both provide a `#match` method. ```ruby expect("a string").to match(/str/) # passes expect("a string").to match(/foo/) # fails expect(/foo/).to match("food") # passes expect(/foo/).to match("drinks") # fails ``` You can also use this matcher to match nested data structures when composing matchers. Scenario: String usage Given a file named "string_match_spec.rb" with: """ruby RSpec.describe "a string" do it { is_expected.to match(/str/) } it { is_expected.not_to match(/foo/) } # deliberate failures it { is_expected.not_to match(/str/) } it { is_expected.to match(/foo/) } end """ When I run `rspec string_match_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected "a string" not to match /str/ | | expected "a string" to match /foo/ | Scenario: Regular expression usage Given a file named "regexp_match_spec.rb" with: """ruby RSpec.describe /foo/ do it { is_expected.to match("food") } it { is_expected.not_to match("drinks") } # deliberate failures it { is_expected.not_to match("food") } it { is_expected.to match("drinks") } end """ When I run `rspec regexp_match_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected /foo/ not to match "food" | | expected /foo/ to match "drinks" | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/throw_symbol.feature0000664000000000000000000000743314557700001032027 0ustar rootrootFeature: `throw_symbol` matcher The `throw_symbol` matcher is used to specify that a block of code throws a symbol. The most basic form passes if any symbol is thrown: ```ruby expect { throw :foo }.to throw_symbol ``` You'll often want to specify that a particular symbol is thrown: ```ruby expect { throw :foo }.to throw_symbol(:foo) ``` If you care about the additional argument given to throw, you can specify that as well: ```ruby expect { throw :foo, 7 }.to throw_symbol(:foo, 7) ``` Scenario: Basic usage Given a file named "throw_symbol_matcher_spec.rb" with: """ruby RSpec.describe "throw" do specify { expect { throw :foo }.to throw_symbol } specify { expect { throw :bar, 7 }.to throw_symbol } specify { expect { 5 + 5 }.not_to throw_symbol } # deliberate failures specify { expect { throw :foo }.not_to throw_symbol } specify { expect { throw :bar, 7 }.not_to throw_symbol } specify { expect { 5 + 5 }.to throw_symbol } end """ When I run `rspec throw_symbol_matcher_spec.rb` Then the output should contain all of these: | 6 examples, 3 failures | | expected no Symbol to be thrown, got :foo | | expected no Symbol to be thrown, got :bar | | expected a Symbol to be thrown, got nothing | Scenario: Specify thrown symbol Given a file named "throw_symbol_matcher_spec.rb" with: """ruby RSpec.describe "throw symbol" do specify { expect { throw :foo }.to throw_symbol(:foo) } specify { expect { throw :foo, 7 }.to throw_symbol(:foo) } specify { expect { 5 + 5 }.not_to throw_symbol(:foo) } specify { expect { throw :bar }.not_to throw_symbol(:foo) } # deliberate failures specify { expect { throw :foo }.not_to throw_symbol(:foo) } specify { expect { throw :foo, 7 }.not_to throw_symbol(:foo) } specify { expect { 5 + 5 }.to throw_symbol(:foo) } specify { expect { throw :bar }.to throw_symbol(:foo) } end """ When I run `rspec throw_symbol_matcher_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected :foo not to be thrown, got :foo | | expected :foo not to be thrown, got :foo with 7 | | expected :foo to be thrown, got nothing | | expected :foo to be thrown, got :bar | Scenario: Specify thrown symbol and argument Given a file named "throw_symbol_argument_matcher_spec.rb" with: """ruby RSpec.describe "throw symbol with argument" do specify { expect { throw :foo, 7 }.to throw_symbol(:foo, 7) } specify { expect { throw :foo, 8 }.not_to throw_symbol(:foo, 7) } specify { expect { throw :bar, 7 }.not_to throw_symbol(:foo, 7) } specify { expect { throw :foo }.not_to throw_symbol(:foo, 7) } # deliberate failures specify { expect { throw :foo, 7 }.not_to throw_symbol(:foo, 7) } specify { expect { throw :foo, 8 }.to throw_symbol(:foo, 7) } specify { expect { throw :bar, 7 }.to throw_symbol(:foo, 7) } specify { expect { throw :foo }.to throw_symbol(:foo, 7) } end """ When I run `rspec throw_symbol_argument_matcher_spec.rb` Then the output should contain all of these: | 8 examples, 4 failures | | expected :foo with 7 not to be thrown, got :foo with 7 | | expected :foo with 7 to be thrown, got :foo with 8 | | expected :foo with 7 to be thrown, got :bar | | expected :foo with 7 to be thrown, got :foo with no argument | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/start_with.feature0000664000000000000000000000320114557700001031454 0ustar rootrootFeature: `start_with` matcher Use the `start_with` matcher to specify that a string or array starts with the expected characters or elements. ```ruby expect("this string").to start_with("this") expect("this string").not_to start_with("that") expect([0,1,2]).to start_with(0, 1) ``` Scenario: With a string Given a file named "example_spec.rb" with: """ruby RSpec.describe "this string" do it { is_expected.to start_with "this" } it { is_expected.not_to start_with "that" } # deliberate failures it { is_expected.not_to start_with "this" } it { is_expected.to start_with "that" } end """ When I run `rspec example_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected "this string" not to start with "this" | | expected "this string" to start with "that" | Scenario: With an array Given a file named "example_spec.rb" with: """ruby RSpec.describe [0, 1, 2, 3, 4] do it { is_expected.to start_with 0 } it { is_expected.to start_with(0, 1)} it { is_expected.not_to start_with(2) } it { is_expected.not_to start_with(0, 1, 2, 3, 4, 5) } # deliberate failures it { is_expected.not_to start_with 0 } it { is_expected.to start_with 3 } end """ When I run `rspec example_spec.rb` Then the output should contain all of these: | 6 examples, 2 failures | | expected [0, 1, 2, 3, 4] not to start with 0 | | expected [0, 1, 2, 3, 4] to start with 3 | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/README.md0000664000000000000000000001206314557700001027174 0ustar rootroot# Built in matchers `rspec-expectations` ships with a number of built-in matchers. Each matcher can be used with `expect(..).to` or `expect(..).not_to` to define positive and negative expectations respectively on an object. Most matchers can also be accessed using the `(...).should` and `(...).should_not` syntax; see [using should syntax](https://github.com/rspec/rspec-expectations/blob/main/Should.md) for why we recommend using `expect`. e.g. ```ruby expect(result).to eq(3) expect(list).not_to be_empty pi.should be > 3 ``` ## Object identity ```ruby expect(actual).to be(expected) # passes if actual.equal?(expected) ``` ## Object equivalence ```ruby expect(actual).to eq(expected) # passes if actual == expected ``` ## Optional APIs for identity/equivalence ```ruby expect(actual).to eql(expected) # passes if actual.eql?(expected) expect(actual).to equal(expected) # passes if actual.equal?(expected) # NOTE: `expect` does not support `==` matcher. ``` ## Comparisons ```ruby expect(actual).to be > expected expect(actual).to be >= expected expect(actual).to be <= expected expect(actual).to be < expected expect(actual).to be_between(minimum, maximum).inclusive expect(actual).to be_between(minimum, maximum).exclusive expect(actual).to match(/expression/) expect(actual).to be_within(delta).of(expected) expect(actual).to start_with expected expect(actual).to end_with expected # NOTE: `expect` does not support `=~` matcher. ``` ## Types/classes/response ```ruby expect(actual).to be_instance_of(expected) expect(actual).to be_kind_of(expected) expect(actual).to respond_to(expected) ``` ## Truthiness and existentialism ```ruby expect(actual).to be_truthy # passes if actual is truthy (not nil or false) expect(actual).to be true # passes if actual == true expect(actual).to be_falsey # passes if actual is falsy (nil or false) expect(actual).to be false # passes if actual == false expect(actual).to be_nil # passes if actual is nil expect(actual).to exist # passes if actual.exist? and/or actual.exists? are truthy expect(actual).to exist(*args) # passes if actual.exist?(*args) and/or actual.exists?(*args) are truthy ``` ## Expecting errors ```ruby expect { ... }.to raise_error expect { ... }.to raise_error(ErrorClass) expect { ... }.to raise_error("message") expect { ... }.to raise_error(ErrorClass, "message") ``` ## Expecting throws ```ruby expect { ... }.to throw_symbol expect { ... }.to throw_symbol(:symbol) expect { ... }.to throw_symbol(:symbol, 'value') ``` ## Predicate matchers ```ruby expect(actual).to be_xxx # passes if actual.xxx? expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg) ``` ### Examples ```ruby expect([]).to be_empty expect(:a => 1).to have_key(:a) ``` ## Collection membership ```ruby expect(actual).to include(expected) expect(array).to match_array(expected_array) # ...which is the same as: expect(array).to contain_exactly(individual, elements) ``` ### Examples ```ruby expect([1, 2, 3]).to include(1) expect([1, 2, 3]).to include(1, 2) expect(:a => 'b').to include(:a => 'b') expect("this string").to include("is str") expect([1, 2, 3]).to contain_exactly(2, 1, 3) expect([1, 2, 3]).to match_array([3, 2, 1]) ``` ## Ranges (1.9+ only) ```ruby expect(1..10).to cover(3) ``` ## Change observation ```ruby expect { object.action }.to change(object, :value).from(old).to(new) expect { object.action }.to change(object, :value).by(delta) expect { object.action }.to change(object, :value).by_at_least(minimum_delta) expect { object.action }.to change(object, :value).by_at_most(maximum_delta) ``` ### Examples ```ruby expect { a += 1 }.to change { a }.by(1) expect { a += 3 }.to change { a }.from(2) expect { a += 3 }.to change { a }.by_at_least(2) ``` ## Satisfy ```ruby expect(actual).to satisfy { |value| value == expected } ``` ## Output capture ```ruby expect { actual }.to output("some output").to_stdout expect { actual }.to output("some error").to_stderr ``` ## Block expectation ```ruby expect { |b| object.action(&b) }.to yield_control expect { |b| object.action(&b) }.to yield_with_no_args # only matches no args expect { |b| object.action(&b) }.to yield_with_args # matches any args expect { |b| object.action(&b) }.to yield_successive_args(*args) # matches args against multiple yields ``` ### Examples ```ruby expect { |b| User.transaction(&b) }.to yield_control expect { |b| User.transaction(&b) }.to yield_with_no_args expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5` expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5 expect { |b| 5.tap(&b) }.to yield_with_args(Integer) # because Integer === 5 expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) ``` ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/cover.feature0000664000000000000000000000320214557700001030403 0ustar rootroot@ruby-1.9 Feature: `cover` matcher Use the `cover` matcher to specify that a range covers one or more expected objects. This works on any object that responds to `#cover?` (such as a `Range`): ```ruby expect(1..10).to cover(5) expect(1..10).to cover(4, 6) expect(1..10).not_to cover(11) ``` Scenario: Range usage Given a file named "range_cover_matcher_spec.rb" with: """ruby RSpec.describe (1..10) do it { is_expected.to cover(4) } it { is_expected.to cover(6) } it { is_expected.to cover(8) } it { is_expected.to cover(4, 6) } it { is_expected.to cover(4, 6, 8) } it { is_expected.not_to cover(11) } it { is_expected.not_to cover(11, 12) } # deliberate failures it { is_expected.to cover(11) } it { is_expected.not_to cover(4) } it { is_expected.not_to cover(6) } it { is_expected.not_to cover(8) } it { is_expected.not_to cover(4, 6, 8) } # both of these should fail since it covers 5 but not 11 it { is_expected.to cover(5, 11) } it { is_expected.not_to cover(5, 11) } end """ When I run `rspec range_cover_matcher_spec.rb` Then the output should contain all of these: | 14 examples, 7 failures | | expected 1..10 to cover 11 | | expected 1..10 not to cover 4 | | expected 1..10 not to cover 6 | | expected 1..10 not to cover 8 | | expected 1..10 not to cover 4, 6, and 8 | | expected 1..10 to cover 5 and 11 | | expected 1..10 not to cover 5 and 11 | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/comparisons.feature0000664000000000000000000000701514557700001031630 0ustar rootrootFeature: Comparison matchers RSpec provides a number of matchers that are based on Ruby's built-in operators. These can be used for generalized comparison of values. E.g. ```ruby expect(9).to be > 6 expect(3).to be <= 3 expect(1).to be < 6 expect('a').to be < 'b' ``` Scenario: Numeric operator matchers Given a file named "numeric_operator_matchers_spec.rb" with: """ruby RSpec.describe 18 do it { is_expected.to be < 20 } it { is_expected.to be > 15 } it { is_expected.to be <= 19 } it { is_expected.to be >= 17 } # deliberate failures it { is_expected.to be < 15 } it { is_expected.to be > 20 } it { is_expected.to be <= 17 } it { is_expected.to be >= 19 } it { is_expected.to be < 'a' } end RSpec.describe 'a' do it { is_expected.to be < 'b' } # deliberate failures it { is_expected.to be < 18 } end """ When I run `rspec numeric_operator_matchers_spec.rb` Then the output should contain "11 examples, 6 failures" And the output should contain: """ Failure/Error: it { is_expected.to be < 15 } expected: < 15 got: 18 """ And the output should contain: """ Failure/Error: it { is_expected.to be > 20 } expected: > 20 got: 18 """ And the output should contain: """ Failure/Error: it { is_expected.to be <= 17 } expected: <= 17 got: 18 """ And the output should contain: """ Failure/Error: it { is_expected.to be >= 19 } expected: >= 19 got: 18 """ And the output should contain: """ Failure/Error: it { is_expected.to be < 'a' } expected: < "a" got: 18 """ And the output should contain: """ Failure/Error: it { is_expected.to be < 18 } expected: < 18 got: "a" """ Scenario: String operator matchers Given a file named "string_operator_matchers_spec.rb" with: """ruby RSpec.describe "Strawberry" do it { is_expected.to be < "Tomato" } it { is_expected.to be > "Apple" } it { is_expected.to be <= "Turnip" } it { is_expected.to be >= "Banana" } # deliberate failures it { is_expected.to be < "Cranberry" } it { is_expected.to be > "Zuchini" } it { is_expected.to be <= "Potato" } it { is_expected.to be >= "Tomato" } end """ When I run `rspec string_operator_matchers_spec.rb` Then the output should contain "8 examples, 4 failures" And the output should contain: """ Failure/Error: it { is_expected.to be < "Cranberry" } expected: < "Cranberry" got: "Strawberry" """ And the output should contain: """ Failure/Error: it { is_expected.to be > "Zuchini" } expected: > "Zuchini" got: "Strawberry" """ And the output should contain: """ Failure/Error: it { is_expected.to be <= "Potato" } expected: <= "Potato" got: "Strawberry" """ And the output should contain: """ Failure/Error: it { is_expected.to be >= "Tomato" } expected: >= "Tomato" got: "Strawberry" """ ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/raise_error.feature0000664000000000000000000001170414557700001031607 0ustar rootrootFeature: `raise_error` matcher Use the `raise_error` matcher to specify that a block of code raises an error. The most basic form passes if any error is thrown: ```ruby expect { raise StandardError }.to raise_error ``` You can use `raise_exception` instead if you prefer that wording: ```ruby expect { 3 / 0 }.to raise_exception ``` `raise_error` and `raise_exception` are functionally interchangeable, so use the one that makes the most sense to you in any given context. In addition to the basic form, above, there are a number of ways to specify details of an error/exception: ```ruby expect { raise "oops" }.to raise_error expect { raise "oops" }.to raise_error(RuntimeError) expect { raise "oops" }.to raise_error("oops") expect { raise "oops" }.to raise_error(/op/) expect { raise "oops" }.to raise_error(RuntimeError, "oops") expect { raise "oops" }.to raise_error(RuntimeError, /op/) expect { raise "oops" }.to raise_error(an_instance_of(RuntimeError).and having_attributes(message: "oops")) ``` Scenario: Expecting any error Given a file named "example_spec" with: """ RSpec.describe "calling a missing method" do it "raises" do expect { Object.new.foo }.to raise_error end end """ When I run `rspec example_spec` Then the example should pass Scenario: Expecting a specific error Given a file named "example_spec" with: """ RSpec.describe "calling a missing method" do it "raises" do expect { Object.new.foo }.to raise_error(NameError) end end """ When I run `rspec example_spec` Then the example should pass Scenario: Matching a message with a string Given a file named "example_spec.rb" with: """ruby RSpec.describe "matching error message with string" do it "matches the error message" do expect { raise StandardError, 'this message exactly'}. to raise_error('this message exactly') end end """ When I run `rspec example_spec.rb` Then the example should pass Scenario: Matching a message with a regexp Given a file named "example_spec.rb" with: """ruby RSpec.describe "matching error message with regex" do it "matches the error message" do expect { raise StandardError, "my message" }. to raise_error(/my mess/) end end """ When I run `rspec example_spec.rb` Then the example should pass Scenario: Matching a message with `with_message` Given a file named "example_spec.rb" with: """ruby RSpec.describe "matching error message with regex" do it "matches the error message" do expect { raise StandardError, "my message" }. to raise_error.with_message(/my mess/) end end """ When I run `rspec example_spec.rb` Then the example should pass Scenario: Matching a class + message with string Given a file named "example_spec.rb" with: """ruby RSpec.describe "matching error message with string" do it "matches the error message" do expect { raise StandardError, 'this message exactly'}. to raise_error(StandardError, 'this message exactly') end end """ When I run `rspec example_spec.rb` Then the example should pass Scenario: Matching a class + message with regexp Given a file named "example_spec.rb" with: """ruby RSpec.describe "matching error message with regex" do it "matches the error message" do expect { raise StandardError, "my message" }. to raise_error(StandardError, /my mess/) end end """ When I run `rspec example_spec.rb` Then the example should pass Scenario: Setting expectations on error object passed to block Given a file named "example_spec" with: """ RSpec.describe "#foo" do it "raises NameError" do expect { Object.new.foo }.to raise_error { |error| expect(error).to be_a(NameError) } end end """ When I run `rspec example_spec` Then the example should pass Scenario: Setting expectations on an error object with chained matchers Given a file named "example_spec" with: """ RSpec.describe "composing matchers" do it "raises StandardError" do expect { raise StandardError, "my message" }. to raise_error(an_instance_of(StandardError).and having_attributes({"message" => "my message"})) end end """ When I run `rspec example_spec` Then the example should pass Scenario: Expecting no error at all Given a file named "example_spec" with: """ RSpec.describe "#to_s" do it "does not raise" do expect { Object.new.to_s }.not_to raise_error end end """ When I run `rspec example_spec` Then the example should pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/types.feature0000664000000000000000000001067614557700001030446 0ustar rootrootFeature: Type matchers rspec-expectations includes two matchers to specify types of objects: * `expect(obj).to be_kind_of(type)`: calls `obj.kind_of?(type)`, which returns true if type is in obj's class hierarchy or is a module and is included in a class in obj's class hierarchy. * `expect(obj).to be_instance_of(type)`: calls `obj.instance_of?(type)`, which returns true if and only if type if obj's class. Both of these matchers have aliases: ```ruby expect(obj).to be_a_kind_of(type) # same as expect(obj).to be_kind_of(type) expect(obj).to be_a(type) # same as expect(obj).to be_kind_of(type) expect(obj).to be_an(type) # same as expect(obj).to be_kind_of(type) expect(obj).to be_an_instance_of(type) # same as expect(obj).to be_instance_of(type) ``` Scenario: With `be_(a_)kind_of` matcher Given a file named "be_kind_of_matcher_spec.rb" with: """ruby module MyModule; end class Float include MyModule end RSpec.describe 17.0 do # the actual class it { is_expected.to be_kind_of(Float) } it { is_expected.to be_a_kind_of(Float) } it { is_expected.to be_a(Float) } # the superclass it { is_expected.to be_kind_of(Numeric) } it { is_expected.to be_a_kind_of(Numeric) } it { is_expected.to be_an(Numeric) } # an included module it { is_expected.to be_kind_of(MyModule) } it { is_expected.to be_a_kind_of(MyModule) } it { is_expected.to be_a(MyModule) } # negative passing case it { is_expected.not_to be_kind_of(String) } it { is_expected.not_to be_a_kind_of(String) } it { is_expected.not_to be_a(String) } # deliberate failures it { is_expected.not_to be_kind_of(Float) } it { is_expected.not_to be_a_kind_of(Float) } it { is_expected.not_to be_a(Float) } it { is_expected.not_to be_kind_of(Numeric) } it { is_expected.not_to be_a_kind_of(Numeric) } it { is_expected.not_to be_an(Numeric) } it { is_expected.not_to be_kind_of(MyModule) } it { is_expected.not_to be_a_kind_of(MyModule) } it { is_expected.not_to be_a(MyModule) } it { is_expected.to be_kind_of(String) } it { is_expected.to be_a_kind_of(String) } it { is_expected.to be_a(String) } end """ When I run `rspec be_kind_of_matcher_spec.rb` Then the output should contain all of these: | 24 examples, 12 failures | | expected 17.0 not to be a kind of Float | | expected 17.0 not to be a kind of Numeric | | expected 17.0 not to be a kind of MyModule | | expected 17.0 to be a kind of String | Scenario: With `be_(an_)instance_of` matcher Given a file named "be_instance_of_matcher_spec.rb" with: """ruby module MyModule; end class Float include MyModule end RSpec.describe 17.0 do # the actual class it { is_expected.to be_instance_of(Float) } it { is_expected.to be_an_instance_of(Float) } # the superclass it { is_expected.not_to be_instance_of(Numeric) } it { is_expected.not_to be_an_instance_of(Numeric) } # an included module it { is_expected.not_to be_instance_of(MyModule) } it { is_expected.not_to be_an_instance_of(MyModule) } # another class with no relation to the subject's hierarchy it { is_expected.not_to be_instance_of(String) } it { is_expected.not_to be_an_instance_of(String) } # deliberate failures it { is_expected.not_to be_instance_of(Float) } it { is_expected.not_to be_an_instance_of(Float) } it { is_expected.to be_instance_of(Numeric) } it { is_expected.to be_an_instance_of(Numeric) } it { is_expected.to be_instance_of(MyModule) } it { is_expected.to be_an_instance_of(MyModule) } it { is_expected.to be_instance_of(String) } it { is_expected.to be_an_instance_of(String) } end """ When I run `rspec be_instance_of_matcher_spec.rb` Then the output should contain all of these: | 16 examples, 8 failures | | expected 17.0 not to be an instance of Float | | expected 17.0 to be an instance of Numeric | | expected 17.0 to be an instance of MyModule | | expected 17.0 to be an instance of String | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/include.feature0000664000000000000000000002201114557700001030707 0ustar rootrootFeature: `include` matcher Use the `include` matcher to specify that a collection includes one or more expected objects. It succeeds if any object of the given collection passes the specified matcher. This works on any object that responds to `#include?` (such as a string or array): ```ruby expect("a string").to include("a") expect("a string").to include(/a|str/).twice expect("a string").to include("str", "g") expect("a string").not_to include("foo") expect([1, 2]).to include(1) expect([1, 2]).to include(1, 2) expect([1, 2]).to include(a_kind_of(Integer)) expect([1, 2]).to include(be_odd.and be < 10 ) expect([1, 2]).to include(be_odd) expect([1, 2]).to include(be < 10).at_least(2).times expect([1, 2]).not_to include(17) ``` The matcher also provides flexible handling for hashes: ```ruby expect(:a => 1, :b => 2).to include(:a) expect(:a => 1, :b => 2).to include(:a, :b) expect(:a => 1, :b => 2).to include(:a => 1) expect(:a => 1, :b => 2).to include(:b => 2, :a => 1) expect(:a => 1, :b => 2).to include(match(/b/) => 2) expect(:a => 1, :b => 2).to include(match(/b/) => be_even) expect(:a => 1, :b => 2).not_to include(:c) expect(:a => 1, :b => 2).not_to include(:a => 2) expect(:a => 1, :b => 2).not_to include(:c => 3) ``` Scenario: Array usage Given a file named "array_include_matcher_spec.rb" with: """ruby RSpec.describe [1, 3, 7] do it { is_expected.to include(1) } it { is_expected.to include(3) } it { is_expected.to include(7) } it { is_expected.to include(1, 7) } it { is_expected.to include(1, 3, 7) } it { is_expected.to include(a_kind_of(Integer)) } it { is_expected.to include(be_odd.and be < 10) } it { is_expected.to include(be_odd).at_least(:twice) } it { is_expected.not_to include(be_even) } it { is_expected.not_to include(17) } it { is_expected.not_to include(43, 100) } # deliberate failures it { is_expected.to include(4) } it { is_expected.to include(be_even) } it { is_expected.to include(be_odd).at_most(2).times } it { is_expected.not_to include(1) } it { is_expected.not_to include(3) } it { is_expected.not_to include(7) } it { is_expected.not_to include(1, 3, 7) } # both of these should fail since it includes 1 but not 9 it { is_expected.to include(1, 9) } it { is_expected.not_to include(1, 9) } end """ When I run `rspec array_include_matcher_spec.rb` Then the output should contain all of these: | 20 examples, 9 failures | | expected [1, 3, 7] to include 4 | | expected [1, 3, 7] to include (be even) | | expected [1, 3, 7] to include (be odd) at most twice but it is included 3 times | | expected [1, 3, 7] not to include 1 | | expected [1, 3, 7] not to include 3 | | expected [1, 3, 7] not to include 7 | | expected [1, 3, 7] not to include 1, 3, and 7 | | expected [1, 3, 7] to include 9 | | expected [1, 3, 7] not to include 1 | Scenario: String usage Given a file named "string_include_matcher_spec.rb" with: """ruby RSpec.describe "a string" do it { is_expected.to include("str") } it { is_expected.to include("a", "str", "ng") } it { is_expected.to include(/a|str/).twice } it { is_expected.not_to include("foo") } it { is_expected.not_to include("foo", "bar") } # deliberate failures it { is_expected.to include("foo") } it { is_expected.not_to include("str") } it { is_expected.to include("str").at_least(:twice) } it { is_expected.to include("str", "foo") } it { is_expected.not_to include("str", "foo") } end """ When I run `rspec string_include_matcher_spec.rb` Then the output should contain all of these: | 10 examples, 5 failures | | expected "a string" to include "foo" | | expected "a string" not to include "str" | | expected "a string" to include "str" at least twice but it is included once | | expected "a string" to include "foo" | | expected "a string" not to include "str" | Scenario: Hash usage Given a file named "hash_include_matcher_spec.rb" with: """ruby RSpec.describe :a => 7, :b => 5 do it { is_expected.to include(:a) } it { is_expected.to include(:b, :a) } it { is_expected.to include(:a => 7) } it { is_expected.to include(:b => 5, :a => 7) } it { is_expected.not_to include(:c) } it { is_expected.not_to include(:c, :d) } it { is_expected.not_to include(:d => 2) } it { is_expected.not_to include(:a => 5) } it { is_expected.not_to include(:b => 7, :a => 5) } # deliberate failures it { is_expected.not_to include(:a) } it { is_expected.not_to include(:b, :a) } it { is_expected.not_to include(:a => 7) } it { is_expected.not_to include(:a => 7, :b => 5) } it { is_expected.to include(:c) } it { is_expected.to include(:c, :d) } it { is_expected.to include(:d => 2) } it { is_expected.to include(:a => 5) } it { is_expected.to include(:a => 5, :b => 7) } # Mixed cases--the hash includes one but not the other. # All 4 of these cases should fail. it { is_expected.to include(:a, :d) } it { is_expected.not_to include(:a, :d) } it { is_expected.to include(:a => 7, :d => 3) } it { is_expected.not_to include(:a => 7, :d => 3) } end """ When I run `rspec hash_include_matcher_spec.rb` Then the output should contain all of these: | 22 examples, 13 failures | | expected {:a => 7, :b => 5} not to include :a | | expected {:a => 7, :b => 5} not to include :b and :a | | expected {:a => 7, :b => 5} not to include {:a => 7} | | expected {:a => 7, :b => 5} not to include {:a => 7, :b => 5} | | expected {:a => 7, :b => 5} to include :c | | expected {:a => 7, :b => 5} to include :c and :d | | expected {:a => 7, :b => 5} to include {:d => 2} | | expected {:a => 7, :b => 5} to include {:a => 5} | | expected {:a => 7, :b => 5} to include {:a => 5, :b => 7} | | expected {:a => 7, :b => 5} to include :d | | expected {:a => 7, :b => 5} not to include :a | | expected {:a => 7, :b => 5} to include {:d => 3} | | expected {:a => 7, :b => 5} not to include {:a => 7} | Scenario: Counts usage Given a file named "include_matcher_with_counts_spec.rb" with: """ruby RSpec.describe [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] do it { is_expected.to include(:b => 2).exactly(1).times } it { is_expected.to include(:b => 2).once } it { is_expected.to include(have_key(:a)).twice } it { is_expected.to include(have_key(:c)).at_least(2).times } it { is_expected.to include(have_key(:a)).at_least(:once) } it { is_expected.to include(have_key(:c)).at_least(:twice) } it { is_expected.to include(have_key(:d)).at_most(:once) } it { is_expected.to include(have_key(:b)).at_most(:twice) } # deliberate failures it { is_expected.not_to include(have_key(:b)).once } it { is_expected.not_to include(have_key(:a)).twice } it { is_expected.not_to include(have_key(:c)).at_least(2).times } it { is_expected.not_to include(have_key(:d)).at_most(:once) } end """ When I run `rspec include_matcher_with_counts_spec.rb` Then the output should contain all of these: | 12 examples, 4 failures | | expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :b) once | | expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :a) twice | | expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :c) at least twice | | expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :d) at most once | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/predicates.feature0000664000000000000000000001620114557700001031413 0ustar rootrootFeature: Predicate matchers Ruby objects commonly provide predicate methods: ```ruby 7.zero? # => false 0.zero? # => true [1].empty? # => false [].empty? # => true { :a => 5 }.has_key?(:b) # => false { :b => 5 }.has_key?(:b) # => true ``` You could use a basic equality matcher to set expectations on these: ```ruby expect(7.zero?).to eq true # fails with "expected true, got false (using ==)" ``` ...but RSpec provides dynamic predicate matchers that are more readable and provide better failure output. For any predicate method, RSpec gives you a corresponding matcher. Simply prefix the method with `be_` and remove the question mark. Examples: ```ruby expect(7).not_to be_zero # calls 7.zero? expect([]).to be_empty # calls [].empty? expect(x).to be_multiple_of(3) # calls x.multiple_of?(3) ``` Alternately, for a predicate method that begins with `has_` like `Hash#has_key?`, RSpec allows you to use an alternate form since `be_has_key` makes no sense. ```ruby expect(hash).to have_key(:foo) # calls hash.has_key?(:foo) expect(array).not_to have_odd_values # calls array.has_odd_values? ``` In either case, RSpec provides nice, clear error messages, such as: `expected zero? to be truthy, got false` Calling private methods will also fail: `expected private_method? to return true but it's a private method` Any arguments passed to the matcher will be passed on to the predicate method. Scenario: Expecting `subject` to `be_zero` (based on Integer#zero?) Given a file named "should_be_zero_spec.rb" with: """ruby RSpec.describe 0 do it { is_expected.to be_zero } end RSpec.describe 7 do it { is_expected.to be_zero } # deliberate failure end """ When I run `rspec should_be_zero_spec.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "expected `7.zero?` to be truthy, got false" Scenario: Expecting `subject` to not `be_empty` (based on Array#empty?) Given a file named "should_not_be_empty_spec.rb" with: """ruby RSpec.describe [1, 2, 3] do it { is_expected.not_to be_empty } end RSpec.describe [] do it { is_expected.not_to be_empty } # deliberate failure end """ When I run `rspec should_not_be_empty_spec.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "expected `[].empty?` to be falsey, got true" Scenario: Expecting `subject` to `have_key` (based on Hash#has_key?) Given a file named "should_have_key_spec.rb" with: """ruby RSpec.describe Hash do subject { { :foo => 7 } } it { is_expected.to have_key(:foo) } it { is_expected.to have_key(:bar) } # deliberate failure end """ When I run `rspec should_have_key_spec.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "expected `{:foo=>7}.has_key?(:bar)` to be truthy, got false" Scenario: Expecting `subject` to have all decimals (based on custom `has_decimals?` method) Given a file named "should_not_have_all_string_keys_spec.rb" with: """ruby class Float def has_decimals? round != self end end RSpec.describe Float do context 'with decimals' do subject { 4.2 } it { is_expected.to have_decimals } end context 'with no decimals' do subject { 42.0 } it { is_expected.to have_decimals } # deliberate failure end end """ When I run `rspec should_not_have_all_string_keys_spec.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "expected `42.0.has_decimals?` to be truthy, got false" Scenario: Matcher arguments are passed on to the predicate method Given a file named "predicate_matcher_argument_spec.rb" with: """ruby class Integer def multiple_of?(x) (self % x).zero? end end RSpec.describe 12 do it { is_expected.to be_multiple_of(3) } it { is_expected.not_to be_multiple_of(7) } # deliberate failures it { is_expected.not_to be_multiple_of(4) } it { is_expected.to be_multiple_of(5) } end """ When I run `rspec predicate_matcher_argument_spec.rb` Then the output should contain "4 examples, 2 failures" And the output should contain "expected `12.multiple_of?(4)` to be falsey, got true" And the output should contain "expected `12.multiple_of?(5)` to be truthy, got false" Scenario: The config `strict_predicate_matchers` impacts matching of results other than `true` and `false` Given a file named "strict_or_not.rb" with: """ruby class StrangeResult def has_strange_result? 42 end end RSpec.describe StrangeResult do subject { StrangeResult.new } before do RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.strict_predicate_matchers = strict end end end context 'with non-strict matchers (default)' do let(:strict) { false } it { is_expected.to have_strange_result } end context 'with strict matchers' do let(:strict) { true } # deliberate failure it { is_expected.to have_strange_result } end end """ When I run `rspec strict_or_not.rb` Then the output should contain "2 examples, 1 failure" And the output should contain "has_strange_result?` to return true, got 42" Scenario: Calling private method with be_predicate causes error Given a file named "attempting_to_match_private_method_spec.rb" with: """ruby class WithPrivateMethods def secret? true end private :secret? end RSpec.describe 'private methods' do subject { WithPrivateMethods.new } # deliberate failure it { is_expected.to be_secret } end """ When I run `rspec attempting_to_match_private_method_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "`secret?` is a private method" Scenario: Calling private method with have_predicate causes error Given a file named "attempting_to_match_private_method_spec.rb" with: """ruby class WithPrivateMethods def has_secret? true end private :has_secret? end RSpec.describe 'private methods' do subject { WithPrivateMethods.new } # deliberate failure it { is_expected.to have_secret } end """ When I run `rspec attempting_to_match_private_method_spec.rb` Then the output should contain "1 example, 1 failure" And the output should contain "`has_secret?` is a private method" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/change.feature0000664000000000000000000000414314557700001030517 0ustar rootrootFeature: `change` matcher The `change` matcher is used to specify that a block of code changes some mutable state. You can specify what will change using either of two forms: * `expect { do_something }.to change(object, :attribute)` * `expect { do_something }.to change { object.attribute }` You can further qualify the change by chaining `from` and/or `to` or one of `by`, `by_at_most`, `by_at_least`. Background: Given a file named "lib/counter.rb" with: """ruby class Counter class << self def increment @count ||= 0 @count += 1 end def count @count ||= 0 end end end """ @skip-when-ripper-unsupported Scenario: Expect change Given a file named "spec/example_spec.rb" with: """ruby require "counter" RSpec.describe Counter, "#increment" do it "should increment the count" do expect { Counter.increment }.to change { Counter.count }.from(0).to(1) end # deliberate failure it "should increment the count by 2" do expect { Counter.increment }.to change { Counter.count }.by(2) end end """ When I run `rspec spec/example_spec.rb` Then the output should contain "1 failure" Then the output should contain "expected `Counter.count` to have changed by 2, but was changed by 1" @skip-when-ripper-unsupported Scenario: Expect no change Given a file named "spec/example_spec.rb" with: """ruby require "counter" RSpec.describe Counter, "#increment" do it "should not increment the count by 1 (using not_to)" do expect { Counter.increment }.not_to change { Counter.count } end it "should not increment the count by 1 (using to_not)" do expect { Counter.increment }.to_not change { Counter.count } end end """ When I run `rspec spec/example_spec.rb` Then the output should contain "2 failures" Then the output should contain "expected `Counter.count` not to have changed, but did change from 1 to 2" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/built_in_matchers/end_with.feature0000664000000000000000000000314414557700001031073 0ustar rootrootFeature: `end_with` matcher Use the `end_with` matcher to specify that a string or array ends with the expected characters or elements. ```ruby expect("this string").to end_with "string" expect("this string").not_to end_with "stringy" expect([0, 1, 2]).to end_with 1, 2 ``` Scenario: String usage Given a file named "example_spec.rb" with: """ruby RSpec.describe "this string" do it { is_expected.to end_with "string" } it { is_expected.not_to end_with "stringy" } # deliberate failures it { is_expected.not_to end_with "string" } it { is_expected.to end_with "stringy" } end """ When I run `rspec example_spec.rb` Then the output should contain all of these: | 4 examples, 2 failures | | expected "this string" not to end with "string" | | expected "this string" to end with "stringy" | Scenario: Array usage Given a file named "example_spec.rb" with: """ruby RSpec.describe [0, 1, 2, 3, 4] do it { is_expected.to end_with 4 } it { is_expected.to end_with 3, 4 } it { is_expected.not_to end_with 3 } it { is_expected.not_to end_with 0, 1, 2, 3, 4, 5 } # deliberate failures it { is_expected.not_to end_with 4 } it { is_expected.to end_with 3 } end """ When I run `rspec example_spec.rb` Then the output should contain all of these: | 6 examples, 2 failures | | expected [0, 1, 2, 3, 4] not to end with 4 | | expected [0, 1, 2, 3, 4] to end with 3 | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/implicit_docstrings.feature0000664000000000000000000000425614557700001027655 0ustar rootrootFeature: Implicit docstrings When you use rspec-expectations with rspec-core, RSpec is able to auto-generate the docstrings for examples for you based on the last expectation in the example. This can be handy when the matcher expresses exactly what you would write in your example docstring, but it can also be easily abused. We find that the freeform nature of the docstring provides a lot of value when used well (e.g. to document the "why" of a particular behavior), and you lose that kind of flexibility when you rely on the matcher to generate the docstring for you. In general, we recommend only using this feature when the matcher aligns _exactly_ with the docstring you would write. Even then, many users prefer the explicitness of the full docstring, so use this feature with care (if at all). Scenario: Run passing examples Given a file named "implicit_docstrings_spec.rb" with: """ruby RSpec.describe "Examples with no docstrings generate their own:" do specify { expect(3).to be < 5 } specify { expect([1,2,3]).to include(2) } specify { expect([1,2,3]).to respond_to(:size) } end """ When I run `rspec ./implicit_docstrings_spec.rb -fdoc` Then the output should contain "is expected to be < 5" And the output should contain "is expected to include 2" And the output should contain "is expected to respond to #size" Scenario: Run failing examples Given a file named "failing_implicit_docstrings_spec.rb" with: """ruby RSpec.describe "Failing examples with no descriptions" do # description is auto-generated per the last executed expectation specify do expect(3).to equal(2) expect(5).to equal(5) end specify { expect(3).to be > 5 } specify { expect([1,2,3]).to include(4) } specify { expect([1,2,3]).not_to respond_to(:size) } end """ When I run `rspec ./failing_implicit_docstrings_spec.rb -fdoc` Then the output should contain "is expected to equal 2" And the output should contain "is expected to be > 5" And the output should contain "is expected to include 4" And the output should contain "is expected not to respond to #size" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/step_definitions/0000775000000000000000000000000014557700001025566 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/step_definitions/additional_cli_steps.rb0000664000000000000000000000162114557700001032270 0ustar rootroot# Useful for when the output is slightly different on different versions of ruby Then /^the output should contain "([^"]*)" or "([^"]*)"$/ do |string1, string2| unless [string1, string2].any? { |s| all_output.include?(s) } fail %(Neither "#{string1}" or "#{string2}" were found in:\n#{all_output}) end end Then /^the output should contain all of these:$/ do |table| table.raw.flatten.each do |string| if RUBY_VERSION == '1.8.7' && string =~ /\{.+=>.+\}/ warn "Skipping checking #{string} on 1.8.7 because hash ordering is not consistent" else expect(all_output).to include_output_string string end end end Then /^the example(?:s)? should(?: all)? pass$/ do step 'the output should contain "0 failures"' 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 ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/README.md0000664000000000000000000000301414557700001023475 0ustar rootroot# RSpec Expectations rspec-expectations is used to define expected outcomes. ```ruby RSpec.describe Account do it "has a balance of zero when first created" do expect(Account.new.balance).to eq(Money.new(0)) end end ``` ## Basic structure The basic structure of an rspec expectation is: ```ruby expect(actual).to matcher(expected) expect(actual).not_to matcher(expected) ``` Note: You can also use `expect(..).to_not` instead of `expect(..).not_to`. One is an alias to the other, so you can use whichever reads better to you. #### Examples ```ruby expect(5).to eq(5) expect(5).not_to eq(4) ``` ## What is a matcher? A matcher is any object that responds to the following methods: ```ruby matches?(actual) failure_message ``` These methods are also part of the matcher protocol, but are optional: ```ruby does_not_match?(actual) failure_message_when_negated description supports_block_expectations? ``` RSpec ships with a number of built-in matchers and a DSL for writing custom matchers. ## Issues The documentation for rspec-expectations is a work in progress. We'll be adding Cucumber features over time, and clarifying existing ones. If you have specific features you'd like to see added, find the existing documentation incomplete or confusing, or, better yet, wish to write a missing Cucumber feature yourself, please [submit an issue](http://github.com/rspec/rspec-expectations/issues) or a [pull request](http://github.com/rspec/rspec-expectations). ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/syntax_configuration.feature0000664000000000000000000000647614557700001030067 0ustar rootroot@allow-disallowed-api Feature: Syntax Configuration The primary syntax provided by rspec-expectations is based on the `expect` method, which explicitly wraps an object or block of code in order to set an expectation on it. There's also an older `should`-based syntax, which relies upon `should` being monkey-patched onto every object in the system. However, this syntax can at times lead to some surprising failures, since RSpec does not own every object in the system and cannot guarantee that it will always work consistently. We recommend you use the `expect` syntax unless you have a specific reason you prefer the `should` syntax. We have no plans to ever completely remove the `should` syntax but starting in RSpec 3, a deprecation warning will be issued if you do not explicitly enable it, with the plan to disable it by default in RSpec 4 (and potentially move it into an external gem). If you have an old `should`-based project that you would like to upgrade to the `expect`, check out [transpec](http://yujinakayama.me/transpec/), which can perform the conversion automatically for you. Background: Given a file named "spec/syntaxes_spec.rb" with: """ruby require 'spec_helper' RSpec.describe "using the should syntax" do specify { 3.should eq(3) } specify { 3.should_not eq(4) } specify { lambda { raise "boom" }.should raise_error("boom") } specify { lambda { }.should_not raise_error } end RSpec.describe "using the expect syntax" do specify { expect(3).to eq(3) } specify { expect(3).not_to eq(4) } specify { expect { raise "boom" }.to raise_error("boom") } specify { expect { }.not_to raise_error } end """ Scenario: Both syntaxes are available by default Given a file named "spec/spec_helper.rb" with: """ruby """ When I run `rspec` Then the examples should all pass And the output should contain "Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated" Scenario: Disable should syntax Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.syntax = :expect end end """ When I run `rspec` Then the output should contain all of these: | 8 examples, 4 failures | | undefined method `should' | Scenario: Disable expect syntax Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.syntax = :should end config.mock_with :rspec do |mocks| mocks.syntax = :should end end """ When I run `rspec` Then the output should contain all of these: | 8 examples, 4 failures | | undefined method `expect' | Scenario: Explicitly enable both syntaxes Given a file named "spec/spec_helper.rb" with: """ruby RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.syntax = [:should, :expect] end end """ When I run `rspec` Then the examples should all pass And the output should not contain "deprecated" ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/define_negated_matcher.feature0000664000000000000000000000265014557700001030224 0ustar rootrootFeature: Define negated matcher You can use `RSpec::Matchers.define_negated_matcher` to define a negated version of an existing matcher. This is particularly useful in composed matcher expressions. @skip-when-ripper-unsupported Scenario: Composed negated matcher expression Given a file named "composed_negated_expression_spec.rb" with: """ruby RSpec::Matchers.define_negated_matcher :an_array_excluding, :include RSpec.describe "A negated matcher" do let(:list) { 1.upto(10).to_a } it "can be used in a composed matcher expression" do expect { list.delete(5) }.to change { list }.to(an_array_excluding 5) end it "provides a good failure message based on the name" do # deliberate failure expect { list.delete(1) }.to change { list }.to(an_array_excluding 5) end end """ When I run `rspec composed_negated_expression_spec.rb` Then the output should contain all of these: | 2 examples, 1 failure | | 1) A negated matcher provides a good failure message based on the name | | Failure/Error: expect { list.delete(1) }.to change { list }.to(an_array_excluding 5) | | expected `list` to have changed to an array excluding 5, but is now [2, 3, 4, 5, 6, 7, 8, 9, 10] | ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/composing_matchers.feature0000664000000000000000000002114514557700001027464 0ustar rootrootFeature: Composing Matchers RSpec's matchers are designed to be composable so that you can combine them to express the exact details of what you expect but nothing more. This can help you avoid writing over-specified brittle specs, by using a matcher in place of an exact value to specify only the essential aspects of what you expect. The following matchers accept matchers as arguments: * `change { }.by(matcher)` * `change { }.from(matcher).to(matcher)` * `contain_exactly(matcher, matcher, matcher)` * `end_with(matcher, matcher)` * `include(matcher, matcher)` * `include(:key => matcher, :other => matcher)` * `match(arbitrary_nested_structure_with_matchers)` * `output(matcher).to_stdout` * `output(matcher).to_stderr` * `raise_error(ErrorClass, matcher)` * `start_with(matcher, matcher)` * `throw_symbol(:sym, matcher)` * `yield_with_args(matcher, matcher)` * `yield_successive_args(matcher, matcher)` Note that many built-in matchers do not accept matcher arguments because they have precise semantics that do not allow for a matcher argument. For example, `equal(some_object)` is designed to pass only if the actual and expected arguments are references to the same object. It would not make sense to support a matcher argument here. All of RSpec's built-in matchers have one or more aliases that allow you to use a noun-phrase rather than verb form since they read better as composed arguments. They also provide customized failure output so that the failure message reads better as well. A full list of these aliases is out of scope here, but here are some of the aliases used below: * `be < 2` => `a_value < 2` * `be > 2` => `a_value > 2` * `be_an_instance_of` => `an_instance_of` * `be_within` => `a_value_within` * `contain_exactly` => `a_collection_containing_exactly` * `end_with` => `a_string_ending_with`, `ending_with` * `match` => `a_string_matching` * `start_with` => `a_string_starting_with` For a full list, see the API docs for the `RSpec::Matchers` module. Scenario: Composing matchers with `change` Given a file named "change_spec.rb" with: """ruby RSpec.describe "Passing matchers to `change`" do specify "you can pass a matcher to `by`" do k = 0 expect { k += 1.05 }.to change { k }. by( a_value_within(0.1).of(1.0) ) end specify "you can pass matchers to `from` and `to`" do s = "food" expect { s = "barn" }.to change { s }. from( a_string_matching(/foo/) ). to( a_string_matching(/bar/) ) end end """ When I run `rspec change_spec.rb` Then the examples should all pass Scenario: Composing matchers with `contain_exactly` Given a file named "contain_exactly_spec.rb" with: """ruby RSpec.describe "Passing matchers to `contain_exactly`" do specify "you can pass matchers in place of exact values" do expect(["barn", 2.45]).to contain_exactly( a_value_within(0.1).of(2.5), a_string_starting_with("bar") ) end end """ When I run `rspec contain_exactly_spec.rb` Then the examples should all pass Scenario: Composing matchers with `end_with` Given a file named "end_with_spec.rb" with: """ruby RSpec.describe "Passing matchers to `end_with`" do specify "you can pass matchers in place of exact values" do expect(["barn", "food", 2.45]).to end_with( a_string_matching("foo"), a_value > 2 ) end end """ When I run `rspec end_with_spec.rb` Then the examples should all pass Scenario: Composing matchers with `include` Given a file named "include_spec.rb" with: """ruby RSpec.describe "Passing matchers to `include`" do specify "you can use matchers in place of array values" do expect(["barn", 2.45]).to include( a_string_starting_with("bar") ) end specify "you can use matchers in place of hash values" do expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/)) end specify "you can use matchers in place of hash keys" do expect("food" => "is good").to include( a_string_matching(/foo/) ) end end """ When I run `rspec include_spec.rb` Then the examples should all pass Scenario: Composing matchers with `match`: Given a file named "match_spec.rb" with: """ruby RSpec.describe "Passing matchers to `match`" do specify "you can match nested data structures against matchers" do hash = { :a => { :b => ["foo", 5.0], :c => { :d => 2.05 } } } expect(hash).to match( :a => { :b => a_collection_containing_exactly( a_string_starting_with("f"), an_instance_of(Float) ), :c => { :d => (a_value < 3) } } ) end end """ When I run `rspec match_spec.rb` Then the examples should all pass Scenario: Composing matchers with `output` Given a file named "output_spec.rb" with: """ruby RSpec.describe "Passing matchers to `output`" do specify "you can pass a matcher in place of the output (to_stdout)" do expect { print 'foo' }.to output(a_string_starting_with('f')).to_stdout end specify "you can pass a matcher in place of the output (to_stderr)" do expect { warn 'foo' }.to output(a_string_starting_with('f')).to_stderr end end """ When I run `rspec output_spec.rb` Then the examples should all pass Scenario: Composing matchers with `raise_error` Given a file named "raise_error_spec.rb" with: """ruby RSpec.describe "Passing matchers to `raise_error`" do specify "you can pass a matcher in place of the message" do expect { raise RuntimeError, "this goes boom" }.to raise_error(RuntimeError, a_string_ending_with("boom")) end end """ When I run `rspec raise_error_spec.rb` Then the examples should all pass Scenario: Composing matchers with `start_with` Given a file named "start_with_spec.rb" with: """ruby RSpec.describe "Passing matchers to `start_with`" do specify "you can pass matchers in place of exact values" do expect(["barn", "food", 2.45]).to start_with( a_string_matching("bar"), a_string_matching("foo") ) end end """ When I run `rspec start_with_spec.rb` Then the examples should all pass Scenario: Composing matchers with `throw_symbol` Given a file named "throw_symbol_spec.rb" with: """ruby RSpec.describe "Passing matchers to `throw_symbol`" do specify "you can pass a matcher in place of a throw arg" do expect { throw :pi, Math::PI }.to throw_symbol(:pi, a_value_within(0.01).of(3.14)) end end """ When I run `rspec throw_symbol_spec.rb` Then the examples should all pass Scenario: Composing matchers with `yield_with_args` Given a file named "yield_with_args_spec.rb" with: """ruby RSpec.describe "Passing matchers to `yield_with_args`" do specify "you can pass matchers in place of the args" do expect { |probe| "food".tap(&probe) }.to yield_with_args(a_string_matching(/foo/)) end end """ When I run `rspec yield_with_args_spec.rb` Then the examples should all pass Scenario: Composing matchers with `yield_successive_args` Given a file named "yield_successive_args_spec.rb" with: """ruby RSpec.describe "Passing matchers to `yield_successive_args`" do specify "you can pass matchers in place of the args" do expect { |probe| [1, 2, 3].each(&probe) }.to yield_successive_args(a_value < 2, 2, a_value > 2) end end """ When I run `rspec yield_successive_args_spec.rb` Then the examples should all pass Scenario: Composing matchers using a compound `and` expression Given a file named "include_spec.rb" with: """ruby RSpec.describe "Passing a compound matcher expression to `include`" do example do expect(["food", "drink"]).to include( a_string_starting_with("f").and ending_with("d")) end end """ When I run `rspec include_spec.rb` Then the examples should all pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/0000775000000000000000000000000014557700001023734 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/env.rb0000664000000000000000000000101114557700001025042 0ustar rootrootrequire 'aruba/cucumber' Aruba.configure do |config| if RUBY_PLATFORM =~ /java/ || defined?(Rubinius) config.exit_timeout = 60 else config.exit_timeout = 10 end end Before do if RUBY_PLATFORM == 'java' # disable JIT since these processes are so short lived set_environment_variable('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") end if defined?(Rubinius) # disable JIT since these processes are so short lived set_environment_variable('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/rubinius.rb0000664000000000000000000000034214557700001026120 0ustar rootroot# Required until https://github.com/rubinius/rubinius/issues/2430 is resolved ENV['RBXOPT'] = "#{ENV["RBXOPT"]} -Xcompiler.no_rbc" Around "@unsupported-on-rbx" do |_scenario, block| block.call unless defined?(Rubinius) end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/disallow_certain_apis.rb0000664000000000000000000000161014557700001030616 0ustar rootroot# This file is designed to prevent the use of certain APIs that # we don't want used from our cukes, since they function as documentation. if defined?(Cucumber) require 'shellwords' tag = !defined?(::RUBY_ENGINE_VERSION) || (::RUBY_ENGINE_VERSION < '2.0.0') ? '~@allow-disallowed-api': 'not @allow-disallowed-api' Before(tag) do set_environment_variable('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}") end else module DisallowOneLinerShould def should(*) raise "one-liner should is not allowed" end def should_not(*) raise "one-liner should_not is not allowed" end end RSpec.configure do |rspec| rspec.expose_dsl_globally = false rspec.mock_with :rspec do |mocks| mocks.syntax = :expect end rspec.expect_with :rspec do |expectations| expectations.syntax = :expect end rspec.include DisallowOneLinerShould end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/ruby_features.rb0000664000000000000000000000227714557700001027150 0ustar rootrootAround "@skip-when-splat-args-unsupported" do |scenario, block| require 'rspec/support/ruby_features' if ::RSpec::Support::RubyFeatures.optional_and_splat_args_supported? block.call else skip_this_scenario "Skipping scenario #{scenario.name} because splat arguments are not supported" end end Around "@skip-when-keyword-args-unsupported" do |scenario, block| require 'rspec/support/ruby_features' if ::RSpec::Support::RubyFeatures.kw_args_supported? block.call else skip_this_scenario "Skipping scenario #{scenario.name} because keyword arguments are not supported" end end Around "@skip-when-required-keyword-args-unsupported" do |scenario, block| require 'rspec/support/ruby_features' if ::RSpec::Support::RubyFeatures.required_kw_args_supported? block.call else skip_this_scenario "Skipping scenario #{scenario.name} because required keyword arguments are not supported" end end Around "@skip-when-ripper-unsupported" do |scenario, block| require 'rspec/support/ruby_features' if ::RSpec::Support::RubyFeatures.ripper_supported? block.call else skip_this_scenario "Skipping scenario #{scenario.name} because Ripper is not supported" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/support/diff_lcs_versions.rb0000664000000000000000000000124314557700001027762 0ustar rootrootrequire 'diff-lcs' Around "@skip-when-diff-lcs-1.4" do |scenario, block| if Diff::LCS::VERSION >= '1.4' skip_this_scenario "Skipping scenario #{scenario.name} on `diff-lcs` v#{Diff::LCS::VERSION}" else block.call end end Around "@skip-when-diff-lcs-1.4.3" do |scenario, block| if Diff::LCS::VERSION =~ /1\.4\.3/ skip_this_scenario "Skipping scenario #{scenario.name} on `diff-lcs` v#{Diff::LCS::VERSION}" else block.call end end Around "@skip-when-diff-lcs-1.3" do |scenario, block| if Diff::LCS::VERSION < '1.4' skip_this_scenario "Skipping scenario #{scenario.name} on `diff-lcs` v#{Diff::LCS::VERSION}" else block.call end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/features/compound_expectations.feature0000664000000000000000000000313514557700001030211 0ustar rootrootFeature: Compound Expectations Matchers can be composed using `and` or `or` to make compound expectations. Scenario: Use `and` to chain expectations Given a file named "compound_and_matcher_spec.rb" with: """ruby RSpec.describe "A compound `and` matcher" do let(:string) { "foo bar bazz" } it "passes when both are true" do expect(string).to start_with("foo").and end_with("bazz") end it "passes when using boolean AND `&` alias" do expect(string).to start_with("foo") & end_with("bazz") end it "fails when the first matcher fails" do expect(string).to start_with("bar").and end_with("bazz") end it "fails when the second matcher fails" do expect(string).to start_with("foo").and end_with("bar") end end """ When I run `rspec compound_and_matcher_spec.rb` Then the output should contain "4 examples, 2 failures" Scenario: Use `or` to chain expectations Given a file named "stoplight_spec.rb" with: """ruby class StopLight def color %w[ green yellow red ].shuffle.first end end RSpec.describe StopLight, "#color" do let(:light) { StopLight.new } it "is green, yellow or red" do expect(light.color).to eq("green").or eq("yellow").or eq("red") end it "passes when using boolean OR `|` alias" do expect(light.color).to eq("green") | eq("yellow") | eq("red") end end """ When I run `rspec stoplight_spec.rb` Then the example should pass ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/.gitignore0000664000000000000000000000024014557700001022366 0ustar rootroot*.sw? .DS_Store coverage* rdoc pkg doc tmp rerun.txt Gemfile.lock .bundle *.rbc .yardoc bin .rbx Gemfile-custom bundle .rspec-local spec/examples.txt specs.out ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/0000775000000000000000000000000014557700001021150 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/0000775000000000000000000000000014557700001022264 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers.rb0000664000000000000000000011631314557700001024424 0ustar rootrootrequire 'rspec/support' RSpec::Support.require_rspec_support 'matcher_definition' RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) } %w[ english_phrasing composable built_in generated_descriptions dsl matcher_delegator aliased_matcher multi_matcher_diff ].each { |file| RSpec::Support.require_rspec_matchers(file) } # RSpec's top level namespace. All of rspec-expectations is contained # in the `RSpec::Expectations` and `RSpec::Matchers` namespaces. module RSpec # RSpec::Matchers provides a number of useful matchers we use to define # expectations. Any object that implements the [matcher protocol](Matchers/MatcherProtocol) # can be used as a matcher. # # ## Predicates # # In addition to matchers that are defined explicitly, RSpec will create # custom matchers on the fly for any arbitrary predicate, giving your specs a # much more natural language feel. # # A Ruby predicate is a method that ends with a "?" and returns true or false. # Common examples are `empty?`, `nil?`, and `instance_of?`. # # All you need to do is write `expect(..).to be_` followed by the predicate # without the question mark, and RSpec will figure it out from there. # For example: # # expect([]).to be_empty # => [].empty?() | passes # expect([]).not_to be_empty # => [].empty?() | fails # # In addition to prefixing the predicate matchers with "be_", you can also use "be_a_" # and "be_an_", making your specs read much more naturally: # # expect("a string").to be_an_instance_of(String) # =>"a string".instance_of?(String) # passes # # expect(3).to be_a_kind_of(Integer) # => 3.kind_of?(Numeric) | passes # expect(3).to be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes # expect(3).to be_an_instance_of(Integer) # => 3.instance_of?(Integer) | passes # expect(3).not_to be_an_instance_of(Numeric) # => 3.instance_of?(Numeric) | fails # # RSpec will also create custom matchers for predicates like `has_key?`. To # use this feature, just state that the object should have_key(:key) and RSpec will # call has_key?(:key) on the target. For example: # # expect(:a => "A").to have_key(:a) # expect(:a => "A").to have_key(:b) # fails # # You can use this feature to invoke any predicate that begins with "has_", whether it is # part of the Ruby libraries (like `Hash#has_key?`) or a method you wrote on your own class. # # Note that RSpec does not provide composable aliases for these dynamic predicate # matchers. You can easily define your own aliases, though: # # RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin # expect(user_list).to include(a_user_who_is_an_admin) # # ## Alias Matchers # # With {RSpec::Matchers.alias_matcher}, you can easily create an # alternate name for a given matcher. # # The description will also change according to the new name: # # RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to # sum_to(3).description # => "sum to 3" # a_list_that_sums_to(3).description # => "a list that sums to 3" # # or you can specify a custom description like this: # # RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description| # description.sub("be sorted by", "a list sorted by") # end # # be_sorted_by(:age).description # => "be sorted by age" # a_list_sorted_by(:age).description # => "a list sorted by age" # # ## Custom Matchers # # When you find that none of the stock matchers provide a natural feeling # expectation, you can very easily write your own using RSpec's matcher DSL # or writing one from scratch. # # ### Matcher DSL # # Imagine that you are writing a game in which players can be in various # zones on a virtual board. To specify that bob should be in zone 4, you # could say: # # expect(bob.current_zone).to eql(Zone.new("4")) # # But you might find it more expressive to say: # # expect(bob).to be_in_zone("4") # # and/or # # expect(bob).not_to be_in_zone("3") # # You can create such a matcher like so: # # RSpec::Matchers.define :be_in_zone do |zone| # match do |player| # player.in_zone?(zone) # end # end # # This will generate a be_in_zone method that returns a matcher # with logical default messages for failures. You can override the failure # messages and the generated description as follows: # # RSpec::Matchers.define :be_in_zone do |zone| # match do |player| # player.in_zone?(zone) # end # # failure_message do |player| # # generate and return the appropriate string. # end # # failure_message_when_negated do |player| # # generate and return the appropriate string. # end # # description do # # generate and return the appropriate string. # end # end # # Each of the message-generation methods has access to the block arguments # passed to the create method (in this case, zone). The # failure message methods (failure_message and # failure_message_when_negated) are passed the actual value (the # receiver of expect(..) or expect(..).not_to). # # ### Custom Matcher from scratch # # You could also write a custom matcher from scratch, as follows: # # class BeInZone # def initialize(expected) # @expected = expected # end # # def matches?(target) # @target = target # @target.current_zone.eql?(Zone.new(@expected)) # end # # def failure_message # "expected #{@target.inspect} to be in Zone #{@expected}" # end # # def failure_message_when_negated # "expected #{@target.inspect} not to be in Zone #{@expected}" # end # end # # ... and a method like this: # # def be_in_zone(expected) # BeInZone.new(expected) # end # # And then expose the method to your specs. This is normally done # by including the method and the class in a module, which is then # included in your spec: # # module CustomGameMatchers # class BeInZone # # ... # end # # def be_in_zone(expected) # # ... # end # end # # describe "Player behaviour" do # include CustomGameMatchers # # ... # end # # or you can include in globally in a spec_helper.rb file required # from your spec file(s): # # RSpec::configure do |config| # config.include(CustomGameMatchers) # end # # ### Making custom matchers composable # # RSpec's built-in matchers are designed to be composed, in expressions like: # # expect(["barn", 2.45]).to contain_exactly( # a_value_within(0.1).of(2.5), # a_string_starting_with("bar") # ) # # Custom matchers can easily participate in composed matcher expressions like these. # Include {RSpec::Matchers::Composable} in your custom matcher to make it support # being composed (matchers defined using the DSL have this included automatically). # Within your matcher's `matches?` method (or the `match` block, if using the DSL), # use `values_match?(expected, actual)` rather than `expected == actual`. # Under the covers, `values_match?` is able to match arbitrary # nested data structures containing a mix of both matchers and non-matcher objects. # It uses `===` and `==` to perform the matching, considering the values to # match if either returns `true`. The `Composable` mixin also provides some helper # methods for surfacing the matcher descriptions within your matcher's description # or failure messages. # # RSpec's built-in matchers each have a number of aliases that rephrase the matcher # from a verb phrase (such as `be_within`) to a noun phrase (such as `a_value_within`), # which reads better when the matcher is passed as an argument in a composed matcher # expressions, and also uses the noun-phrase wording in the matcher's `description`, # for readable failure messages. You can alias your custom matchers in similar fashion # using {RSpec::Matchers.alias_matcher}. # # ## Negated Matchers # # Sometimes if you want to test for the opposite using a more descriptive name # instead of using `not_to`, you can use {RSpec::Matchers.define_negated_matcher}: # # RSpec::Matchers.define_negated_matcher :exclude, :include # include(1, 2).description # => "include 1 and 2" # exclude(1, 2).description # => "exclude 1 and 2" # # While the most obvious negated form may be to add a `not_` prefix, # the failure messages you get with that form can be confusing (e.g. # "expected [actual] to not [verb], but did not"). We've found it works # best to find a more positive name for the negated form, such as # `avoid_changing` rather than `not_change`. # module Matchers # rubocop:disable Metrics/ModuleLength extend ::RSpec::Matchers::DSL # @!macro [attach] alias_matcher # @!parse # alias $1 $2 # @!visibility private # We define this override here so we can attach a YARD macro to it. # It ensures that our docs list all the matcher aliases. def self.alias_matcher(*args, &block) super(*args, &block) end # @!method self.alias_matcher(new_name, old_name, options={}, &description_override) # Extended from {RSpec::Matchers::DSL#alias_matcher}. # @!method self.define(name, &declarations) # Extended from {RSpec::Matchers::DSL#define}. # @!method self.define_negated_matcher(negated_name, base_name, &description_override) # Extended from {RSpec::Matchers::DSL#define_negated_matcher}. # @method expect # Supports `expect(actual).to matcher` syntax by wrapping `actual` in an # `ExpectationTarget`. # @example # expect(actual).to eq(expected) # expect(actual).not_to eq(expected) # @return [Expectations::ExpectationTarget] # @see Expectations::ExpectationTarget#to # @see Expectations::ExpectationTarget#not_to # Allows multiple expectations in the provided block to fail, and then # aggregates them into a single exception, rather than aborting on the # first expectation failure like normal. This allows you to see all # failures from an entire set of expectations without splitting each # off into its own example (which may slow things down if the example # setup is expensive). # # @param label [String] label for this aggregation block, which will be # included in the aggregated exception message. # @param metadata [Hash] additional metadata about this failure aggregation # block. If multiple expectations fail, it will be exposed from the # {Expectations::MultipleExpectationsNotMetError} exception. Mostly # intended for internal RSpec use but you can use it as well. # @yield Block containing as many expectation as you want. The block is # simply yielded to, so you can trust that anything that works outside # the block should work within it. # @raise [Expectations::MultipleExpectationsNotMetError] raised when # multiple expectations fail. # @raise [Expectations::ExpectationNotMetError] raised when a single # expectation fails. # @raise [Exception] other sorts of exceptions will be raised as normal. # # @example # aggregate_failures("verifying response") do # expect(response.status).to eq(200) # expect(response.headers).to include("Content-Type" => "text/plain") # expect(response.body).to include("Success") # end # # @note The implementation of this feature uses a thread-local variable, # which means that if you have an expectation failure in another thread, # it'll abort like normal. def aggregate_failures(label=nil, metadata={}, &block) Expectations::FailureAggregator.new(label, metadata).aggregate(&block) end # Passes if actual is truthy (anything but false or nil) def be_truthy BuiltIn::BeTruthy.new end alias_matcher :a_truthy_value, :be_truthy # Passes if actual is falsey (false or nil) def be_falsey BuiltIn::BeFalsey.new end alias_matcher :be_falsy, :be_falsey alias_matcher :a_falsey_value, :be_falsey alias_matcher :a_falsy_value, :be_falsey # Passes if actual is nil def be_nil BuiltIn::BeNil.new end alias_matcher :a_nil_value, :be_nil # @example # expect(actual).to be_truthy # expect(actual).to be_falsey # expect(actual).to be_nil # expect(actual).to be_[arbitrary_predicate](*args) # expect(actual).not_to be_nil # expect(actual).not_to be_[arbitrary_predicate](*args) # # Given true, false, or nil, will pass if actual value is true, false or # nil (respectively). Given no args means the caller should satisfy an if # condition (to be or not to be). # # Predicates are any Ruby method that ends in a "?" and returns true or # false. Given be_ followed by arbitrary_predicate (without the "?"), # RSpec will match convert that into a query against the target object. # # The arbitrary_predicate feature will handle any predicate prefixed with # "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of) or "be_" # (e.g. be_empty), letting you choose the prefix that best suits the # predicate. def be(*args) args.empty? ? Matchers::BuiltIn::Be.new : equal(*args) end alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport # passes if target.kind_of?(klass) def be_a(klass) be_a_kind_of(klass) end alias_method :be_an, :be_a # Passes if actual.instance_of?(expected) # # @example # expect(5).to be_an_instance_of(Integer) # expect(5).not_to be_an_instance_of(Numeric) # expect(5).not_to be_an_instance_of(Float) def be_an_instance_of(expected) BuiltIn::BeAnInstanceOf.new(expected) end alias_method :be_instance_of, :be_an_instance_of alias_matcher :an_instance_of, :be_an_instance_of # Passes if actual.kind_of?(expected) # # @example # expect(5).to be_a_kind_of(Integer) # expect(5).to be_a_kind_of(Numeric) # expect(5).not_to be_a_kind_of(Float) def be_a_kind_of(expected) BuiltIn::BeAKindOf.new(expected) end alias_method :be_kind_of, :be_a_kind_of alias_matcher :a_kind_of, :be_a_kind_of # Passes if actual.between?(min, max). Works with any Comparable object, # including String, Symbol, Time, or Numeric (Fixnum, Bignum, Integer, # Float, Complex, and Rational). # # By default, `be_between` is inclusive (i.e. passes when given either the max or min value), # but you can make it `exclusive` by chaining that off the matcher. # # @example # expect(5).to be_between(1, 10) # expect(11).not_to be_between(1, 10) # expect(10).not_to be_between(1, 10).exclusive def be_between(min, max) BuiltIn::BeBetween.new(min, max) end alias_matcher :a_value_between, :be_between # Passes if actual == expected +/- delta # # @example # expect(result).to be_within(0.5).of(3.0) # expect(result).not_to be_within(0.5).of(3.0) def be_within(delta) BuiltIn::BeWithin.new(delta) end alias_matcher :a_value_within, :be_within alias_matcher :within, :be_within # Applied to a proc, specifies that its execution will cause some value to # change. # # @param [Object] receiver # @param [Symbol] message the message to send the receiver # # You can either pass receiver and message, or a block, # but not both. # # When passing a block, it must use the `{ ... }` format, not # do/end, as `{ ... }` binds to the `change` method, whereas do/end # would errantly bind to the `expect(..).to` or `expect(...).not_to` method. # # You can chain any of the following off of the end to specify details # about the change: # # * `from` # * `to` # # or any one of: # # * `by` # * `by_at_least` # * `by_at_most` # # @example # expect { # team.add_player(player) # }.to change(roster, :count) # # expect { # team.add_player(player) # }.to change(roster, :count).by(1) # # expect { # team.add_player(player) # }.to change(roster, :count).by_at_least(1) # # expect { # team.add_player(player) # }.to change(roster, :count).by_at_most(1) # # string = "string" # expect { # string.reverse! # }.to change { string }.from("string").to("gnirts") # # string = "string" # expect { # string # }.not_to change { string }.from("string") # # expect { # person.happy_birthday # }.to change(person, :birthday).from(32).to(33) # # expect { # employee.develop_great_new_social_networking_app # }.to change(employee, :title).from("Mail Clerk").to("CEO") # # expect { # doctor.leave_office # }.to change(doctor, :sign).from(/is in/).to(/is out/) # # user = User.new(:type => "admin") # expect { # user.symbolize_type # }.to change(user, :type).from(String).to(Symbol) # # == Notes # # Evaluates `receiver.message` or `block` before and after it # evaluates the block passed to `expect`. If the value is the same # object, its before/after `hash` value is used to see if it has changed. # Therefore, your object needs to properly implement `hash` to work correctly # with this matcher. # # `expect( ... ).not_to change` supports the form that specifies `from` # (which specifies what you expect the starting, unchanged value to be) # but does not support forms with subsequent calls to `by`, `by_at_least`, # `by_at_most` or `to`. def change(receiver=nil, message=nil, &block) BuiltIn::Change.new(receiver, message, &block) end alias_matcher :a_block_changing, :change alias_matcher :changing, :change # Passes if actual contains all of the expected regardless of order. # This works for collections. Pass in multiple args and it will only # pass if all args are found in collection. # # @note This is also available using the `=~` operator with `should`, # but `=~` is not supported with `expect`. # # @example # expect([1, 2, 3]).to contain_exactly(1, 2, 3) # expect([1, 2, 3]).to contain_exactly(1, 3, 2) # # @see #match_array def contain_exactly(*items) BuiltIn::ContainExactly.new(items) end alias_matcher :a_collection_containing_exactly, :contain_exactly alias_matcher :containing_exactly, :contain_exactly # Passes if actual covers expected. This works for # Ranges. You can also pass in multiple args # and it will only pass if all args are found in Range. # # @example # expect(1..10).to cover(5) # expect(1..10).to cover(4, 6) # expect(1..10).to cover(4, 6, 11) # fails # expect(1..10).not_to cover(11) # expect(1..10).not_to cover(5) # fails # # ### Warning:: Ruby >= 1.9 only def cover(*values) BuiltIn::Cover.new(*values) end alias_matcher :a_range_covering, :cover alias_matcher :covering, :cover # Matches if the actual value ends with the expected value(s). In the case # of a string, matches against the last `expected.length` characters of the # actual string. In the case of an array, matches against the last # `expected.length` elements of the actual array. # # @example # expect("this string").to end_with "string" # expect([0, 1, 2, 3, 4]).to end_with 4 # expect([0, 2, 3, 4, 4]).to end_with 3, 4 def end_with(*expected) BuiltIn::EndWith.new(*expected) end alias_matcher :a_collection_ending_with, :end_with alias_matcher :a_string_ending_with, :end_with alias_matcher :ending_with, :end_with # Passes if actual == expected. # # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more # information about equality in Ruby. # # @example # expect(5).to eq(5) # expect(5).not_to eq(3) def eq(expected) BuiltIn::Eq.new(expected) end alias_matcher :an_object_eq_to, :eq alias_matcher :eq_to, :eq # Passes if `actual.eql?(expected)` # # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more # information about equality in Ruby. # # @example # expect(5).to eql(5) # expect(5).not_to eql(3) def eql(expected) BuiltIn::Eql.new(expected) end alias_matcher :an_object_eql_to, :eql alias_matcher :eql_to, :eql # Passes if actual.equal?(expected) (object identity). # # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more # information about equality in Ruby. # # @example # expect(5).to equal(5) # Integers are equal # expect("5").not_to equal("5") # Strings that look the same are not the same object def equal(expected) BuiltIn::Equal.new(expected) end alias_matcher :an_object_equal_to, :equal alias_matcher :equal_to, :equal # Passes if `actual.exist?` or `actual.exists?` # # @example # expect(File).to exist("path/to/file") def exist(*args) BuiltIn::Exist.new(*args) end alias_matcher :an_object_existing, :exist alias_matcher :existing, :exist # Passes if actual's attribute values match the expected attributes hash. # This works no matter how you define your attribute readers. # # @example # Person = Struct.new(:name, :age) # person = Person.new("Bob", 32) # # expect(person).to have_attributes(:name => "Bob", :age => 32) # expect(person).to have_attributes(:name => a_string_starting_with("B"), :age => (a_value > 30) ) # # @note It will fail if actual doesn't respond to any of the expected attributes. # # @example # expect(person).to have_attributes(:color => "red") def have_attributes(expected) BuiltIn::HaveAttributes.new(expected) end alias_matcher :an_object_having_attributes, :have_attributes alias_matcher :having_attributes, :have_attributes # Passes if actual includes expected. This works for # collections and Strings. You can also pass in multiple args # and it will only pass if all args are found in collection. # # @example # expect([1,2,3]).to include(3) # expect([1,2,3]).to include(2,3) # expect([1,2,3]).to include(2,3,4) # fails # expect([1,2,3]).not_to include(4) # expect("spread").to include("read") # expect("spread").not_to include("red") # expect(:a => 1, :b => 2).to include(:a) # expect(:a => 1, :b => 2).to include(:a, :b) # expect(:a => 1, :b => 2).to include(:a => 1) # expect(:a => 1, :b => 2).to include(:b => 2, :a => 1) # expect(:a => 1, :b => 2).to include(:c) # fails # expect(:a => 1, :b => 2).not_to include(:a => 2) def include(*expected) BuiltIn::Include.new(*expected) end alias_matcher :a_collection_including, :include alias_matcher :a_string_including, :include alias_matcher :a_hash_including, :include alias_matcher :including, :include # Passes if the provided matcher passes when checked against all # elements of the collection. # # @example # expect([1, 3, 5]).to all be_odd # expect([1, 3, 6]).to all be_odd # fails # # @note The negative form `not_to all` is not supported. Instead # use `not_to include` or pass a negative form of a matcher # as the argument (e.g. `all exclude(:foo)`). # # @note You can also use this with compound matchers as well. # # @example # expect([1, 3, 5]).to all( be_odd.and be_an(Integer) ) def all(expected) BuiltIn::All.new(expected) end # Given a `Regexp` or `String`, passes if `actual.match(pattern)` # Given an arbitrary nested data structure (e.g. arrays and hashes), # matches if `expected === actual` || `actual == expected` for each # pair of elements. # # @example # expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) # expect(email).to match("@example.com") # # @example # hash = { # :a => { # :b => ["foo", 5], # :c => { :d => 2.05 } # } # } # # expect(hash).to match( # :a => { # :b => a_collection_containing_exactly( # a_string_starting_with("f"), # an_instance_of(Integer) # ), # :c => { :d => (a_value < 3) } # } # ) # # @note The `match_regex` alias is deprecated and is not recommended for use. # It was added in 2.12.1 to facilitate its use from within custom # matchers (due to how the custom matcher DSL was evaluated in 2.x, # `match` could not be used there), but is no longer needed in 3.x. def match(expected) BuiltIn::Match.new(expected) end alias_matcher :match_regex, :match alias_matcher :an_object_matching, :match alias_matcher :a_string_matching, :match alias_matcher :matching, :match # An alternate form of `contain_exactly` that accepts # the expected contents as a single array arg rather # than splatted out as individual items. # # @example # expect(results).to contain_exactly(1, 2) # # is identical to: # expect(results).to match_array([1, 2]) # # @see #contain_exactly def match_array(items) contain_exactly(*items) end alias_matcher :an_array_matching, :match_array do |desc| desc.sub("contain exactly", "an array containing exactly") end # With no arg, passes if the block outputs `to_stdout` or `to_stderr`. # With a string, passes if the block outputs that specific string `to_stdout` or `to_stderr`. # With a regexp or matcher, passes if the block outputs a string `to_stdout` or `to_stderr` that matches. # # To capture output from any spawned subprocess as well, use `to_stdout_from_any_process` or # `to_stderr_from_any_process`. Output from any process that inherits the main process's corresponding # standard stream will be captured. # # @example # expect { print 'foo' }.to output.to_stdout # expect { print 'foo' }.to output('foo').to_stdout # expect { print 'foo' }.to output(/foo/).to_stdout # # expect { do_something }.to_not output.to_stdout # # expect { warn('foo') }.to output.to_stderr # expect { warn('foo') }.to output('foo').to_stderr # expect { warn('foo') }.to output(/foo/).to_stderr # # expect { do_something }.to_not output.to_stderr # # expect { system('echo foo') }.to output("foo\n").to_stdout_from_any_process # expect { system('echo foo', out: :err) }.to output("foo\n").to_stderr_from_any_process # # @note `to_stdout` and `to_stderr` work by temporarily replacing `$stdout` or `$stderr`, # so they're not able to intercept stream output that explicitly uses `STDOUT`/`STDERR` # or that uses a reference to `$stdout`/`$stderr` that was stored before the # matcher was used. # @note `to_stdout_from_any_process` and `to_stderr_from_any_process` use Tempfiles, and # are thus significantly (~30x) slower than `to_stdout` and `to_stderr`. def output(expected=nil) BuiltIn::Output.new(expected) end alias_matcher :a_block_outputting, :output # With no args, matches if any error is raised. # With a named error, matches only if that specific error is raised. # With a named error and message specified as a String, matches only if both match. # With a named error and message specified as a Regexp, matches only if both match. # Pass an optional block to perform extra verifications on the exception matched # # @example # expect { do_something_risky }.to raise_error # expect { do_something_risky }.to raise_error(PoorRiskDecisionError) # expect { do_something_risky }.to raise_error(PoorRiskDecisionError) { |error| expect(error.data).to eq 42 } # expect { do_something_risky }.to raise_error { |error| expect(error.data).to eq 42 } # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, "that was too risky") # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/) # expect { do_something_risky }.to raise_error("that was too risky") # # expect { do_something_risky }.not_to raise_error def raise_error(error=BuiltIn::RaiseError::UndefinedValue, message=nil, &block) BuiltIn::RaiseError.new(error, message, &block) end alias_method :raise_exception, :raise_error alias_matcher :a_block_raising, :raise_error do |desc| desc.sub("raise", "a block raising") end alias_matcher :raising, :raise_error do |desc| desc.sub("raise", "raising") end # Matches if the target object responds to all of the names # provided. Names can be Strings or Symbols. # # @example # expect("string").to respond_to(:length) # def respond_to(*names) BuiltIn::RespondTo.new(*names) end alias_matcher :an_object_responding_to, :respond_to alias_matcher :responding_to, :respond_to # Passes if the submitted block returns true. Yields target to the # block. # # Generally speaking, this should be thought of as a last resort when # you can't find any other way to specify the behaviour you wish to # specify. # # If you do find yourself in such a situation, you could always write # a custom matcher, which would likely make your specs more expressive. # # @param description [String] optional description to be used for this matcher. # # @example # expect(5).to satisfy { |n| n > 3 } # expect(5).to satisfy("be greater than 3") { |n| n > 3 } def satisfy(description=nil, &block) BuiltIn::Satisfy.new(description, &block) end alias_matcher :an_object_satisfying, :satisfy alias_matcher :satisfying, :satisfy # Matches if the actual value starts with the expected value(s). In the # case of a string, matches against the first `expected.length` characters # of the actual string. In the case of an array, matches against the first # `expected.length` elements of the actual array. # # @example # expect("this string").to start_with "this s" # expect([0, 1, 2, 3, 4]).to start_with 0 # expect([0, 2, 3, 4, 4]).to start_with 0, 1 def start_with(*expected) BuiltIn::StartWith.new(*expected) end alias_matcher :a_collection_starting_with, :start_with alias_matcher :a_string_starting_with, :start_with alias_matcher :starting_with, :start_with # Given no argument, matches if a proc throws any Symbol. # # Given a Symbol, matches if the given proc throws the specified Symbol. # # Given a Symbol and an arg, matches if the given proc throws the # specified Symbol with the specified arg. # # @example # expect { do_something_risky }.to throw_symbol # expect { do_something_risky }.to throw_symbol(:that_was_risky) # expect { do_something_risky }.to throw_symbol(:that_was_risky, 'culprit') # # expect { do_something_risky }.not_to throw_symbol # expect { do_something_risky }.not_to throw_symbol(:that_was_risky) # expect { do_something_risky }.not_to throw_symbol(:that_was_risky, 'culprit') def throw_symbol(expected_symbol=nil, expected_arg=nil) BuiltIn::ThrowSymbol.new(expected_symbol, expected_arg) end alias_matcher :a_block_throwing, :throw_symbol do |desc| desc.sub("throw", "a block throwing") end alias_matcher :throwing, :throw_symbol do |desc| desc.sub("throw", "throwing") end # Passes if the method called in the expect block yields, regardless # of whether or not arguments are yielded. # # @example # expect { |b| 5.tap(&b) }.to yield_control # expect { |b| "a".to_sym(&b) }.not_to yield_control # # @note Your expect block must accept a parameter and pass it on to # the method-under-test as a block. def yield_control BuiltIn::YieldControl.new end alias_matcher :a_block_yielding_control, :yield_control alias_matcher :yielding_control, :yield_control # Passes if the method called in the expect block yields with # no arguments. Fails if it does not yield, or yields with arguments. # # @example # expect { |b| User.transaction(&b) }.to yield_with_no_args # expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5` # expect { |b| "a".to_sym(&b) }.not_to yield_with_no_args # because it does not yield # # @note Your expect block must accept a parameter and pass it on to # the method-under-test as a block. # @note This matcher is not designed for use with methods that yield # multiple times. def yield_with_no_args BuiltIn::YieldWithNoArgs.new end alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args alias_matcher :yielding_with_no_args, :yield_with_no_args # Given no arguments, matches if the method called in the expect # block yields with arguments (regardless of what they are or how # many there are). # # Given arguments, matches if the method called in the expect block # yields with arguments that match the given arguments. # # Argument matching is done using `===` (the case match operator) # and `==`. If the expected and actual arguments match with either # operator, the matcher will pass. # # @example # expect { |b| 5.tap(&b) }.to yield_with_args # because #tap yields an arg # expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5 # expect { |b| 5.tap(&b) }.to yield_with_args(Integer) # because Integer === 5 # expect { |b| File.open("f.txt", &b) }.to yield_with_args(/txt/) # because /txt/ === "f.txt" # # expect { |b| User.transaction(&b) }.not_to yield_with_args # because it yields no args # expect { |b| 5.tap(&b) }.not_to yield_with_args(1, 2, 3) # # @note Your expect block must accept a parameter and pass it on to # the method-under-test as a block. # @note This matcher is not designed for use with methods that yield # multiple times. def yield_with_args(*args) BuiltIn::YieldWithArgs.new(*args) end alias_matcher :a_block_yielding_with_args, :yield_with_args alias_matcher :yielding_with_args, :yield_with_args # Designed for use with methods that repeatedly yield (such as # iterators). Passes if the method called in the expect block yields # multiple times with arguments matching those given. # # Argument matching is done using `===` (the case match operator) # and `==`. If the expected and actual arguments match with either # operator, the matcher will pass. # # @example # expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) # expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2]) # expect { |b| [1, 2, 3].each(&b) }.not_to yield_successive_args(1, 2) # # @note Your expect block must accept a parameter and pass it on to # the method-under-test as a block. def yield_successive_args(*args) BuiltIn::YieldSuccessiveArgs.new(*args) end alias_matcher :a_block_yielding_successive_args, :yield_successive_args alias_matcher :yielding_successive_args, :yield_successive_args # Delegates to {RSpec::Expectations.configuration}. # This is here because rspec-core's `expect_with` option # looks for a `configuration` method on the mixin # (`RSpec::Matchers`) to yield to a block. # @return [RSpec::Expectations::Configuration] the configuration object def self.configuration Expectations.configuration end private BE_PREDICATE_REGEX = /^(?:be_(?:an?_)?)(.*)/ HAS_REGEX = /^(?:have_)(.*)/ DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX) def method_missing(method, *args, &block) case method.to_s when BE_PREDICATE_REGEX BuiltIn::BePredicate.new(method, *args, &block) when HAS_REGEX BuiltIn::Has.new(method, *args, &block) else super end end ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) if RUBY_VERSION.to_f >= 1.9 def respond_to_missing?(method, *) method =~ DYNAMIC_MATCHER_REGEX || super end else # for 1.8.7 # :nocov: def respond_to?(method, *) method = method.to_s method =~ DYNAMIC_MATCHER_REGEX || super end public :respond_to? # :nocov: end # @api private def self.is_a_matcher?(obj) return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj begin return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher) rescue NoMethodError # Some objects, like BasicObject, don't implemented standard # reflection methods. return false end return false unless obj.respond_to?(:matches?) obj.respond_to?(:failure_message) || obj.respond_to?(:failure_message_for_should) # support legacy matchers end ::RSpec::Support.register_matcher_definition do |obj| is_a_matcher?(obj) end # @api private def self.is_a_describable_matcher?(obj) is_a_matcher?(obj) && obj.respond_to?(:description) end class << self private if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9' # Note that `included` doesn't work for this because it is triggered # _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather # than _before_, like `append_features`. It's important we check this before # in order to find the cases where it was already previously included. # @api private def append_features(mod) return super if mod < self # `mod < self` indicates a re-inclusion. subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self } return super unless subclasses.any? subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor. subclasses = subclasses.map { |s| "`#{s}`" }.join(", ") RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \ "after previously being included in subclasses (#{subclasses}), " \ "which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \ "(https://redmine.ruby-lang.org/issues/3351). To work around this, " \ "either upgrade to MRI 2.0+, include a dup of the module (e.g. " \ "`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \ "before it is included in subclasses (#{subclasses}). See " \ "https://github.com/rspec/rspec-expectations/issues/814 for more info" super end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations.rb0000664000000000000000000000630114557700001025317 0ustar rootrootrequire 'rspec/support' RSpec::Support.require_rspec_support "caller_filter" RSpec::Support.require_rspec_support "warnings" RSpec::Support.require_rspec_support "object_formatter" require 'rspec/matchers' RSpec::Support.define_optimized_require_for_rspec(:expectations) { |f| require_relative(f) } %w[ expectation_target configuration fail_with handler version ].each { |file| RSpec::Support.require_rspec_expectations(file) } module RSpec # RSpec::Expectations provides a simple, readable API to express # the expected outcomes in a code example. To express an expected # outcome, wrap an object or block in `expect`, call `to` or `to_not` # (aliased as `not_to`) and pass it a matcher object: # # expect(order.total).to eq(Money.new(5.55, :USD)) # expect(list).to include(user) # expect(message).not_to match(/foo/) # expect { do_something }.to raise_error # # The last form (the block form) is needed to match against ruby constructs # that are not objects, but can only be observed when executing a block # of code. This includes raising errors, throwing symbols, yielding, # and changing values. # # When `expect(...).to` is invoked with a matcher, it turns around # and calls `matcher.matches?()`. For example, # in the expression: # # expect(order.total).to eq(Money.new(5.55, :USD)) # # ...`eq(Money.new(5.55, :USD))` returns a matcher object, and it results # in the equivalent of `eq.matches?(order.total)`. If `matches?` returns # `true`, the expectation is met and execution continues. If `false`, then # the spec fails with the message returned by `eq.failure_message`. # # Given the expression: # # expect(order.entries).not_to include(entry) # # ...the `not_to` method (also available as `to_not`) invokes the equivalent of # `include.matches?(order.entries)`, but it interprets `false` as success, and # `true` as a failure, using the message generated by # `include.failure_message_when_negated`. # # rspec-expectations ships with a standard set of useful matchers, and writing # your own matchers is quite simple. # # See [RSpec::Matchers](../RSpec/Matchers) for more information about the # built-in matchers that ship with rspec-expectations, and how to write your # own custom matchers. module Expectations # Exception raised when an expectation fails. # # @note We subclass Exception so that in a stub implementation if # the user sets an expectation, it can't be caught in their # code by a bare `rescue`. # @api public class ExpectationNotMetError < Exception end # Exception raised from `aggregate_failures` when multiple expectations fail. # # @note The constant is defined here but the extensive logic of this class # is lazily defined when `FailureAggregator` is autoloaded, since we do # not need to waste time defining that functionality unless # `aggregate_failures` is used. class MultipleExpectationsNotMetError < ExpectationNotMetError end autoload :BlockSnippetExtractor, "rspec/expectations/block_snippet_extractor" autoload :FailureAggregator, "rspec/expectations/failure_aggregator" end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/0000775000000000000000000000000014557700001024772 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/fail_with.rb0000664000000000000000000000233614557700001027271 0ustar rootrootmodule RSpec module Expectations class << self # @private class Differ # @private OBJECT_PREPARER = lambda do |object| RSpec::Matchers::Composable.surface_descriptions_in(object) end end # @private def differ RSpec::Support::Differ.new( :object_preparer => Differ::OBJECT_PREPARER, :color => RSpec::Matchers.configuration.color? ) end # Raises an RSpec::Expectations::ExpectationNotMetError with message. # @param [String] message # @param [Object] expected # @param [Object] actual # # Adds a diff to the failure message when `expected` and `actual` are # both present. def fail_with(message, expected=nil, actual=nil) unless message raise ArgumentError, "Failure message is nil. Does your matcher define the " \ "appropriate failure_message[_when_negated] method to return a string?" end message = ::RSpec::Matchers::MultiMatcherDiff.from(expected, actual).message_with_diff(message, differ) RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/minitest_integration.rb0000664000000000000000000000324314557700001031560 0ustar rootrootrequire 'rspec/expectations' Minitest::Test.class_eval do include ::RSpec::Matchers # This `expect` will only be called if the user is using Minitest < 5.6 # or if they are _not_ using Minitest::Spec on 5.6+. Minitest::Spec on 5.6+ # defines its own `expect` and will have the assertions incremented via our # definitions of `to`/`not_to`/`to_not` below. def expect(*a, &b) self.assertions += 1 super end # Convert a `MultipleExpectationsNotMetError` to a `Minitest::Assertion` error so # it gets counted in minitest's summary stats as a failure rather than an error. # It would be nice to make `MultipleExpectationsNotMetError` subclass # `Minitest::Assertion`, but Minitest's implementation does not treat subclasses # the same, so this is the best we can do. def aggregate_failures(*args, &block) super rescue RSpec::Expectations::MultipleExpectationsNotMetError => e assertion_failed = Minitest::Assertion.new(e.message) assertion_failed.set_backtrace e.backtrace raise assertion_failed end end # Older versions of Minitest (e.g. before 5.6) do not define # `Minitest::Expectation`. if defined?(::Minitest::Expectation) Minitest::Expectation.class_eval do include RSpec::Expectations::ExpectationTarget::InstanceMethods def to(*args) ctx.assertions += 1 super end def not_to(*args) ctx.assertions += 1 super end def to_not(*args) ctx.assertions += 1 super end end end module RSpec module Expectations remove_const :ExpectationNotMetError # Exception raised when an expectation fails. const_set :ExpectationNotMetError, ::Minitest::Assertion end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/expectation_target.rb0000664000000000000000000001360614557700001031216 0ustar rootrootmodule RSpec module Expectations # Wraps the target of an expectation. # # @example # expect(something) # => ExpectationTarget wrapping something # expect { do_something } # => ExpectationTarget wrapping the block # # # used with `to` # expect(actual).to eq(3) # # # with `not_to` # expect(actual).not_to eq(3) # # @note `ExpectationTarget` is not intended to be instantiated # directly by users. Use `expect` instead. class ExpectationTarget # @private # Used as a sentinel value to be able to tell when the user # did not pass an argument. We can't use `nil` for that because # `nil` is a valid value to pass. UndefinedValue = Module.new # @note this name aligns with `Minitest::Expectation` so that our # {InstanceMethods} module can be included in that class when # used in a Minitest context. # @return [Object] the target of the expectation attr_reader :target # @api private def initialize(value) @target = value end # @private def self.for(value, block) if UndefinedValue.equal?(value) unless block raise ArgumentError, "You must pass either an argument or a block to `expect`." end BlockExpectationTarget.new(block) elsif block raise ArgumentError, "You cannot pass both an argument and a block to `expect`." else ValueExpectationTarget.new(value) end end # Defines instance {ExpectationTarget} instance methods. These are defined # in a module so we can include it in `Minitest::Expectation` when # `rspec/expectations/minitest_integration` is loaded in order to # support usage with Minitest. module InstanceMethods # Runs the given expectation, passing if `matcher` returns true. # @example # expect(value).to eq(5) # expect { perform }.to raise_error # @param [Matcher] # matcher # @param [String, Proc] message optional message to display when the expectation fails # @return [Boolean] true if the expectation succeeds (else raises) # @see RSpec::Matchers def to(matcher=nil, message=nil, &block) prevent_operator_matchers(:to) unless matcher RSpec::Expectations::PositiveExpectationHandler.handle_matcher(target, matcher, message, &block) end # Runs the given expectation, passing if `matcher` returns false. # @example # expect(value).not_to eq(5) # @param [Matcher] # matcher # @param [String, Proc] message optional message to display when the expectation fails # @return [Boolean] false if the negative expectation succeeds (else raises) # @see RSpec::Matchers def not_to(matcher=nil, message=nil, &block) prevent_operator_matchers(:not_to) unless matcher RSpec::Expectations::NegativeExpectationHandler.handle_matcher(target, matcher, message, &block) end alias to_not not_to private def prevent_operator_matchers(verb) raise ArgumentError, "The expect syntax does not support operator matchers, " \ "so you must pass a matcher to `##{verb}`." end end include InstanceMethods end # @private # Validates the provided matcher to ensure it supports block # expectations, in order to avoid user confusion when they # use a block thinking the expectation will be on the return # value of the block rather than the block itself. class ValueExpectationTarget < ExpectationTarget def to(matcher=nil, message=nil, &block) enforce_value_expectation(matcher) super end def not_to(matcher=nil, message=nil, &block) enforce_value_expectation(matcher) super end private def enforce_value_expectation(matcher) return if supports_value_expectations?(matcher) RSpec.deprecate( "expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}", :message => "The implicit block expectation syntax is deprecated, you should pass " \ "a block rather than an argument to `expect` to use the provided " \ "block expectation matcher or the matcher must implement " \ "`supports_value_expectations?`. e.g `expect { value }.to " \ "#{RSpec::Support::ObjectFormatter.format(matcher)}` not " \ "`expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}`" ) end def supports_value_expectations?(matcher) !matcher.respond_to?(:supports_value_expectations?) || matcher.supports_value_expectations? end end # @private # Validates the provided matcher to ensure it supports block # expectations, in order to avoid user confusion when they # use a block thinking the expectation will be on the return # value of the block rather than the block itself. class BlockExpectationTarget < ExpectationTarget def to(matcher, message=nil, &block) enforce_block_expectation(matcher) super end def not_to(matcher, message=nil, &block) enforce_block_expectation(matcher) super end alias to_not not_to private def enforce_block_expectation(matcher) return if supports_block_expectations?(matcher) raise ExpectationNotMetError, "You must pass an argument rather than a block to `expect` to use the provided " \ "matcher (#{RSpec::Support::ObjectFormatter.format(matcher)}), or the matcher must implement " \ "`supports_block_expectations?`." end def supports_block_expectations?(matcher) matcher.respond_to?(:supports_block_expectations?) && matcher.supports_block_expectations? end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/block_snippet_extractor.rb0000664000000000000000000001624714557700001032260 0ustar rootrootmodule RSpec module Expectations # @private class BlockSnippetExtractor # rubocop:disable Metrics/ClassLength # rubocop should properly handle `Struct.new {}` as an inner class definition. attr_reader :proc, :method_name def self.try_extracting_single_line_body_of(proc, method_name) lines = new(proc, method_name).body_content_lines return nil unless lines.count == 1 lines.first rescue Error nil end def initialize(proc, method_name) @proc = proc @method_name = method_name.to_s.freeze end # Ideally we should properly handle indentations of multiline snippet, # but it's not implemented yet since because we use result of this method only when it's a # single line and implementing the logic introduces additional complexity. def body_content_lines raw_body_lines.map(&:strip).reject(&:empty?) end private def raw_body_lines raw_body_snippet.split("\n") end def raw_body_snippet block_token_extractor.body_tokens.map(&:string).join end def block_token_extractor @block_token_extractor ||= BlockTokenExtractor.new(method_name, source, beginning_line_number) end if RSpec.respond_to?(:world) def source raise TargetNotFoundError unless File.exist?(file_path) RSpec.world.source_from_file(file_path) end else RSpec::Support.require_rspec_support 'source' def source raise TargetNotFoundError unless File.exist?(file_path) @source ||= RSpec::Support::Source.from_file(file_path) end end def file_path source_location.first end def beginning_line_number source_location.last end def source_location proc.source_location || raise(TargetNotFoundError) end Error = Class.new(StandardError) TargetNotFoundError = Class.new(Error) AmbiguousTargetError = Class.new(Error) # @private # Performs extraction of block body snippet using tokens, # which cannot be done with node information. BlockTokenExtractor = Struct.new(:method_name, :source, :beginning_line_number) do attr_reader :state, :body_tokens def initialize(*) super parse! end private def parse! @state = :initial catch(:finish) do source.tokens.each do |token| invoke_state_handler(token) end end end def finish! throw :finish end def invoke_state_handler(token) __send__("#{state}_state", token) end def initial_state(token) @state = :after_method_call if token.location == block_locator.method_call_location end def after_method_call_state(token) @state = :after_opener if handle_opener_token(token) end def after_opener_state(token) if handle_closer_token(token) finish_or_find_next_block_if_incorrect! elsif pipe_token?(token) finalize_pending_tokens! @state = :after_beginning_of_args else pending_tokens << token handle_opener_token(token) @state = :after_beginning_of_body unless token.type == :on_sp end end def after_beginning_of_args_state(token) @state = :after_beginning_of_body if pipe_token?(token) end def after_beginning_of_body_state(token) if handle_closer_token(token) finish_or_find_next_block_if_incorrect! else pending_tokens << token handle_opener_token(token) end end def pending_tokens @pending_tokens ||= [] end def finalize_pending_tokens! pending_tokens.freeze.tap do @pending_tokens = nil end end def finish_or_find_next_block_if_incorrect! body_tokens = finalize_pending_tokens! if correct_block?(body_tokens) @body_tokens = body_tokens finish! else @state = :after_method_call end end def handle_opener_token(token) opener_token?(token).tap do |boolean| opener_token_stack.push(token) if boolean end end def opener_token?(token) token.type == :on_lbrace || (token.type == :on_kw && token.string == 'do') end def handle_closer_token(token) if opener_token_stack.last.closed_by?(token) opener_token_stack.pop opener_token_stack.empty? else false end end def opener_token_stack @opener_token_stack ||= [] end def pipe_token?(token) token.type == :on_op && token.string == '|' end def correct_block?(body_tokens) return true if block_locator.body_content_locations.empty? content_location = block_locator.body_content_locations.first content_location.between?(body_tokens.first.location, body_tokens.last.location) end def block_locator @block_locator ||= BlockLocator.new(method_name, source, beginning_line_number) end end # @private # Locates target block with node information (semantics), which tokens don't have. BlockLocator = Struct.new(:method_name, :source, :beginning_line_number) do def method_call_location @method_call_location ||= method_ident_node.location end def body_content_locations @body_content_locations ||= block_body_node.map(&:location).compact end private def method_ident_node method_call_node = block_wrapper_node.children.first method_call_node.find do |node| method_ident_node?(node) end end def block_body_node block_node = block_wrapper_node.children[1] block_node.children.last end def block_wrapper_node case candidate_block_wrapper_nodes.size when 1 candidate_block_wrapper_nodes.first when 0 raise TargetNotFoundError else raise AmbiguousTargetError end end def candidate_block_wrapper_nodes @candidate_block_wrapper_nodes ||= candidate_method_ident_nodes.map do |method_ident_node| block_wrapper_node = method_ident_node.each_ancestor.find { |node| node.type == :method_add_block } next nil unless block_wrapper_node method_call_node = block_wrapper_node.children.first method_call_node.include?(method_ident_node) ? block_wrapper_node : nil end.compact end def candidate_method_ident_nodes source.nodes_by_line_number[beginning_line_number].select do |node| method_ident_node?(node) end end def method_ident_node?(node) node.type == :@ident && node.args.first == method_name end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/syntax.rb0000664000000000000000000001121114557700001026641 0ustar rootrootmodule RSpec module Expectations # @api private # Provides methods for enabling and disabling the available # syntaxes provided by rspec-expectations. module Syntax module_function # @api private # Determines where we add `should` and `should_not`. def default_should_host @default_should_host ||= ::Object.ancestors.last end # @api private # Instructs rspec-expectations to warn on first usage of `should` or `should_not`. # Enabled by default. This is largely here to facilitate testing. def warn_about_should! @warn_about_should = true end # @api private # Generates a deprecation warning for the given method if no warning # has already been issued. def warn_about_should_unless_configured(method_name) return unless @warn_about_should RSpec.deprecate( "Using `#{method_name}` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax", :replacement => "the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }`" ) @warn_about_should = false end # @api private # Enables the `should` syntax. def enable_should(syntax_host=default_should_host) @warn_about_should = false if syntax_host == default_should_host return if should_enabled?(syntax_host) syntax_host.module_exec do def should(matcher=nil, message=nil, &block) ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(::Kernel.__method__) ::RSpec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, message, &block) end def should_not(matcher=nil, message=nil, &block) ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(::Kernel.__method__) ::RSpec::Expectations::NegativeExpectationHandler.handle_matcher(self, matcher, message, &block) end end end # @api private # Disables the `should` syntax. def disable_should(syntax_host=default_should_host) return unless should_enabled?(syntax_host) syntax_host.module_exec do undef should undef should_not end end # @api private # Enables the `expect` syntax. def enable_expect(syntax_host=::RSpec::Matchers) return if expect_enabled?(syntax_host) syntax_host.module_exec do def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block) ::RSpec::Expectations::ExpectationTarget.for(value, block) end end end # @api private # Disables the `expect` syntax. def disable_expect(syntax_host=::RSpec::Matchers) return unless expect_enabled?(syntax_host) syntax_host.module_exec do undef expect end end # @api private # Indicates whether or not the `should` syntax is enabled. def should_enabled?(syntax_host=default_should_host) syntax_host.method_defined?(:should) end # @api private # Indicates whether or not the `expect` syntax is enabled. def expect_enabled?(syntax_host=::RSpec::Matchers) syntax_host.method_defined?(:expect) end end end end if defined?(BasicObject) # The legacy `:should` syntax adds the following methods directly to # `BasicObject` so that they are available off of any object. Note, however, # that this syntax does not always play nice with delegate/proxy objects. # We recommend you use the non-monkeypatching `:expect` syntax instead. class BasicObject # @method should(matcher, message) # Passes if `matcher` returns true. Available on every `Object`. # @example # actual.should eq expected # actual.should match /expression/ # @param [Matcher] # matcher # @param [String] message optional message to display when the expectation fails # @return [Boolean] true if the expectation succeeds (else raises) # @note This is only available when you have enabled the `:should` syntax. # @see RSpec::Matchers # @method should_not(matcher, message) # Passes if `matcher` returns false. Available on every `Object`. # @example # actual.should_not eq expected # @param [Matcher] # matcher # @param [String] message optional message to display when the expectation fails # @return [Boolean] false if the negative expectation succeeds (else raises) # @note This is only available when you have enabled the `:should` syntax. # @see RSpec::Matchers end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/version.rb0000664000000000000000000000015714557700001027007 0ustar rootrootmodule RSpec module Expectations # @private module Version STRING = '3.13.0' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/handler.rb0000664000000000000000000001357114557700001026743 0ustar rootrootmodule RSpec module Expectations # @private module ExpectationHelper def self.check_message(msg) unless msg.nil? || msg.respond_to?(:to_str) || msg.respond_to?(:call) ::Kernel.warn [ "WARNING: ignoring the provided expectation message argument (", msg.inspect, ") since it is not a string or a proc." ].join end end # Returns an RSpec-3+ compatible matcher, wrapping a legacy one # in an adapter if necessary. # # @private def self.modern_matcher_from(matcher) LegacyMatcherAdapter::RSpec2.wrap(matcher) || LegacyMatcherAdapter::RSpec1.wrap(matcher) || matcher end def self.with_matcher(handler, matcher, message) check_message(message) matcher = modern_matcher_from(matcher) yield matcher ensure ::RSpec::Matchers.last_expectation_handler = handler ::RSpec::Matchers.last_matcher = matcher end def self.handle_failure(matcher, message, failure_message_method) message = message.call if message.respond_to?(:call) message ||= matcher.__send__(failure_message_method) if matcher.respond_to?(:diffable?) && matcher.diffable? ::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual else ::RSpec::Expectations.fail_with message end end end # @private class PositiveExpectationHandler def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block) ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher| return ::RSpec::Matchers::BuiltIn::PositiveOperatorMatcher.new(actual) unless initial_matcher match_result = matcher.matches?(actual, &block) if custom_message && match_result.respond_to?(:error_generator) match_result.error_generator.opts[:message] = custom_message end match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message) end end def self.verb 'is expected to' end def self.should_method :should end def self.opposite_should_method :should_not end end # @private class NegativeExpectationHandler def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block) ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher| return ::RSpec::Matchers::BuiltIn::NegativeOperatorMatcher.new(actual) unless initial_matcher negated_match_result = does_not_match?(matcher, actual, &block) if custom_message && negated_match_result.respond_to?(:error_generator) negated_match_result.error_generator.opts[:message] = custom_message end negated_match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message_when_negated) end end def self.does_not_match?(matcher, actual, &block) if matcher.respond_to?(:does_not_match?) matcher.does_not_match?(actual, &block) else !matcher.matches?(actual, &block) end end def self.verb 'is expected not to' end def self.should_method :should_not end def self.opposite_should_method :should end end # Wraps a matcher written against one of the legacy protocols in # order to present the current protocol. # # @private class LegacyMatcherAdapter < Matchers::MatcherDelegator def initialize(matcher) super ::RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''), :type => "legacy_matcher") |#{matcher.class.name || matcher.inspect} implements a legacy RSpec matcher |protocol. For the current protocol you should expose the failure messages |via the `failure_message` and `failure_message_when_negated` methods. |(Used from #{CallerFilter.first_non_rspec_line}) EOS end def self.wrap(matcher) new(matcher) if interface_matches?(matcher) end # Starting in RSpec 1.2 (and continuing through all 2.x releases), # the failure message protocol was: # * `failure_message_for_should` # * `failure_message_for_should_not` # @private class RSpec2 < self def failure_message base_matcher.failure_message_for_should end def failure_message_when_negated base_matcher.failure_message_for_should_not end def self.interface_matches?(matcher) ( !matcher.respond_to?(:failure_message) && matcher.respond_to?(:failure_message_for_should) ) || ( !matcher.respond_to?(:failure_message_when_negated) && matcher.respond_to?(:failure_message_for_should_not) ) end end # Before RSpec 1.2, the failure message protocol was: # * `failure_message` # * `negative_failure_message` # @private class RSpec1 < self def failure_message base_matcher.failure_message end def failure_message_when_negated base_matcher.negative_failure_message end # Note: `failure_message` is part of the RSpec 3 protocol # (paired with `failure_message_when_negated`), so we don't check # for `failure_message` here. def self.interface_matches?(matcher) !matcher.respond_to?(:failure_message_when_negated) && matcher.respond_to?(:negative_failure_message) end end end # RSpec 3.0 was released with the class name misspelled. For SemVer compatibility, # we will provide this misspelled alias until 4.0. # @deprecated Use LegacyMatcherAdapter instead. # @private LegacyMacherAdapter = LegacyMatcherAdapter end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/configuration.rb0000664000000000000000000002006214557700001030166 0ustar rootrootRSpec::Support.require_rspec_expectations "syntax" module RSpec module Expectations # Provides configuration options for rspec-expectations. # If you are using rspec-core, you can access this via a # block passed to `RSpec::Core::Configuration#expect_with`. # Otherwise, you can access it via RSpec::Expectations.configuration. # # @example # RSpec.configure do |rspec| # rspec.expect_with :rspec do |c| # # c is the config object # end # end # # # or # # RSpec::Expectations.configuration class Configuration # @private FALSE_POSITIVE_BEHAVIOURS = { :warn => lambda { |message| RSpec.warning message }, :raise => lambda { |message| raise ArgumentError, message }, :nothing => lambda { |_| true }, } def initialize @on_potential_false_positives = :warn @strict_predicate_matchers = false end # Configures the supported syntax. # @param [Array, Symbol] values the syntaxes to enable # @example # RSpec.configure do |rspec| # rspec.expect_with :rspec do |c| # c.syntax = :should # # or # c.syntax = :expect # # or # c.syntax = [:should, :expect] # end # end def syntax=(values) if Array(values).include?(:expect) Expectations::Syntax.enable_expect else Expectations::Syntax.disable_expect end if Array(values).include?(:should) Expectations::Syntax.enable_should else Expectations::Syntax.disable_should end end # Configures the maximum character length that RSpec will print while # formatting an object. You can set length to nil to prevent RSpec from # doing truncation. # @param [Fixnum] length the number of characters to limit the formatted output to. # @example # RSpec.configure do |rspec| # rspec.expect_with :rspec do |c| # c.max_formatted_output_length = 200 # end # end def max_formatted_output_length=(length) RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = length end # The list of configured syntaxes. # @return [Array] the list of configured syntaxes. # @example # unless RSpec::Matchers.configuration.syntax.include?(:expect) # raise "this RSpec extension gem requires the rspec-expectations `:expect` syntax" # end def syntax syntaxes = [] syntaxes << :should if Expectations::Syntax.should_enabled? syntaxes << :expect if Expectations::Syntax.expect_enabled? syntaxes end if ::RSpec.respond_to?(:configuration) def color? ::RSpec.configuration.color_enabled? end else # Indicates whether or not diffs should be colored. # Delegates to rspec-core's color option if rspec-core # is loaded; otherwise you can set it here. attr_writer :color # Indicates whether or not diffs should be colored. # Delegates to rspec-core's color option if rspec-core # is loaded; otherwise you can set it here. def color? defined?(@color) && @color end end # Adds `should` and `should_not` to the given classes # or modules. This can be used to ensure `should` works # properly on things like proxy objects (particular # `Delegator`-subclassed objects on 1.8). # # @param [Array] modules the list of classes or modules # to add `should` and `should_not` to. def add_should_and_should_not_to(*modules) modules.each do |mod| Expectations::Syntax.enable_should(mod) end end # Sets or gets the backtrace formatter. The backtrace formatter should # implement `#format_backtrace(Array)`. This is used # to format backtraces of errors handled by the `raise_error` # matcher. # # If you are using rspec-core, rspec-core's backtrace formatting # will be used (including respecting the presence or absence of # the `--backtrace` option). # # @!attribute [rw] backtrace_formatter attr_writer :backtrace_formatter def backtrace_formatter @backtrace_formatter ||= if defined?(::RSpec.configuration.backtrace_formatter) ::RSpec.configuration.backtrace_formatter else NullBacktraceFormatter end end # Sets if custom matcher descriptions and failure messages # should include clauses from methods defined using `chain`. # @param value [Boolean] attr_writer :include_chain_clauses_in_custom_matcher_descriptions # Indicates whether or not custom matcher descriptions and failure messages # should include clauses from methods defined using `chain`. It is # false by default for backwards compatibility. def include_chain_clauses_in_custom_matcher_descriptions? @include_chain_clauses_in_custom_matcher_descriptions ||= false end # @private def reset_syntaxes_to_default self.syntax = [:should, :expect] RSpec::Expectations::Syntax.warn_about_should! end # @api private # Null implementation of a backtrace formatter used by default # when rspec-core is not loaded. Does no filtering. NullBacktraceFormatter = Module.new do def self.format_backtrace(backtrace) backtrace end end # Configures whether RSpec will warn about matcher use which will # potentially cause false positives in tests. # # @param [Boolean] boolean def warn_about_potential_false_positives=(boolean) if boolean self.on_potential_false_positives = :warn elsif warn_about_potential_false_positives? self.on_potential_false_positives = :nothing else # no-op, handler is something else end end # # Configures what RSpec will do about matcher use which will # potentially cause false positives in tests. # # @param [Symbol] behavior can be set to :warn, :raise or :nothing def on_potential_false_positives=(behavior) unless FALSE_POSITIVE_BEHAVIOURS.key?(behavior) raise ArgumentError, "Supported values are: #{FALSE_POSITIVE_BEHAVIOURS.keys}" end @on_potential_false_positives = behavior end # Configures RSpec to check predicate matchers to `be(true)` / `be(false)` (strict), # or `be_truthy` / `be_falsey` (not strict). # Historically, the default was `false`, but `true` is recommended. def strict_predicate_matchers=(flag) raise ArgumentError, "Pass `true` or `false`" unless flag == true || flag == false @strict_predicate_matchers = flag end attr_reader :strict_predicate_matchers def strict_predicate_matchers? @strict_predicate_matchers end # Indicates what RSpec will do about matcher use which will # potentially cause false positives in tests, generally you want to # avoid such scenarios so this defaults to `true`. attr_reader :on_potential_false_positives # Indicates whether RSpec will warn about matcher use which will # potentially cause false positives in tests, generally you want to # avoid such scenarios so this defaults to `true`. def warn_about_potential_false_positives? on_potential_false_positives == :warn end # @private def false_positives_handler FALSE_POSITIVE_BEHAVIOURS.fetch(@on_potential_false_positives) end end # The configuration object. # @return [RSpec::Expectations::Configuration] the configuration object def self.configuration @configuration ||= Configuration.new end # set default syntax configuration.reset_syntaxes_to_default end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/expectations/failure_aggregator.rb0000664000000000000000000001776214557700001031165 0ustar rootrootmodule RSpec module Expectations # @private class FailureAggregator attr_reader :block_label, :metadata # @private class AggregatedFailure # @private MESSAGE = 'AggregatedFailure: This method caused a failure which has been ' \ 'suppressed to be aggregated into our failure report by returning ' \ 'this value, further errors can be ignored.' def inspect MESSAGE end end AGGREGATED_FAILURE = AggregatedFailure.new def aggregate RSpec::Support.with_failure_notifier(self) do begin yield rescue ExpectationNotMetError => e # Normally, expectation failures will be notified via the `call` method, below, # but since the failure notifier uses a thread local variable, failing expectations # in another thread will still raise. We handle that here and categorize it as part # of `failures` rather than letting it fall through and be categorized as part of # `other_errors`. failures << e rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e # While it is normally a bad practice to rescue `Exception`, it's important we do # so here. It's low risk (`notify_aggregated_failures` below will re-raise the exception, # or raise a `MultipleExpectationsNotMetError` that includes the exception), and it's # essential that the user is notified of expectation failures that may have already # occurred in the `aggregate_failures` block. Those expectation failures may provide # important diagnostics for understanding why this exception occurred, and if we simply # allowed this exception to be raised as-is, it would (wrongly) suggest to the user # that the expectation passed when it did not, which would be quite confusing. other_errors << e end end notify_aggregated_failures end def failures @failures ||= [] end def other_errors @other_errors ||= [] end # This method is defined to satisfy the callable interface # expected by `RSpec::Support.with_failure_notifier`. def call(failure, options) source_id = options[:source_id] return if source_id && @seen_source_ids.key?(source_id) @seen_source_ids[source_id] = true assign_backtrace(failure) unless failure.backtrace failures << failure AGGREGATED_FAILURE end private if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version < '9.2.0.0' # On JRuby 9.1.x.x and before, `caller` and `raise` produce different backtraces with # regards to `.java` stack frames. It's important that we use `raise` for JRuby to produce # a backtrace that has a continuous common section with the raised `MultipleExpectationsNotMetError`, # so that rspec-core's truncation logic can work properly on it to list the backtrace # relative to the `aggregate_failures` block. def assign_backtrace(failure) raise failure rescue failure.class => e failure.set_backtrace(e.backtrace) end else # Using `caller` performs better (and is simpler) than `raise` on most Rubies. def assign_backtrace(failure) failure.set_backtrace(caller) end end def initialize(block_label, metadata) @block_label = block_label @metadata = metadata @seen_source_ids = {} # don't want to load stdlib set end def notify_aggregated_failures all_errors = failures + other_errors case all_errors.size when 0 then return true when 1 then RSpec::Support.notify_failure all_errors.first else RSpec::Support.notify_failure MultipleExpectationsNotMetError.new(self) end end end # Exception raised from `aggregate_failures` when multiple expectations fail. class MultipleExpectationsNotMetError # @return [String] The fully formatted exception message. def message @message ||= (["#{summary}:"] + enumerated_failures + enumerated_errors).join("\n\n") end # @return [Array] The list of expectation failures. def failures @failure_aggregator.failures end # @return [Array] The list of other exceptions. def other_errors @failure_aggregator.other_errors end # @return [Array] The list of expectation failures and other exceptions, combined. attr_reader :all_exceptions # @return [String] The user-assigned label for the aggregation block. def aggregation_block_label @failure_aggregator.block_label end # @return [Hash] The metadata hash passed to `aggregate_failures`. def aggregation_metadata @failure_aggregator.metadata end # @return [String] A summary of the failure, including the block label and a count of failures. def summary "Got #{exception_count_description} from failure aggregation " \ "block#{block_description}" end # return [String] A description of the failure/error counts. def exception_count_description failure_count = pluralize("failure", failures.size) return failure_count if other_errors.empty? error_count = pluralize("other error", other_errors.size) "#{failure_count} and #{error_count}" end private def initialize(failure_aggregator) @failure_aggregator = failure_aggregator @all_exceptions = failures + other_errors end def block_description return "" unless aggregation_block_label " #{aggregation_block_label.inspect}" end def pluralize(noun, count) "#{count} #{noun}#{'s' unless count == 1}" end def enumerated(exceptions, index_offset) exceptions.each_with_index.map do |exception, index| index += index_offset formatted_message = "#{yield exception}\n#{format_backtrace(exception.backtrace).first}" "#{index_label index}#{indented formatted_message, index}" end end def exclusion_patterns patterns = %w[/lib\d*/ruby/ bin/ exe/rspec /lib/bundler/ /exe/bundle:] patterns << "org/jruby/" if RSpec::Support::Ruby.jruby? patterns.map! { |s| Regexp.new(s.gsub('/', File::SEPARATOR)) } end def format_backtrace(backtrace) backtrace.map { |l| backtrace_line(l) }.compact.tap { |filtered| filtered.concat backtrace if filtered.empty? } end def backtrace_line(line) return if [Regexp.union(RSpec::CallerFilter::IGNORE_REGEX, *exclusion_patterns)].any? { |p| line =~ p } # It changes the current path that is relative to # system root to be relative to the project root. line.sub(/(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/, '\\1.\\2'.freeze).sub(/\A([^:]+:\d+)$/, '\\1'.freeze) end def enumerated_failures enumerated(failures, 0, &:message) end def enumerated_errors enumerated(other_errors, failures.size) do |error| "#{error.class}: #{error.message}" end end def indented(failure_message, index) line_1, *rest = failure_message.strip.lines.to_a first_line_indentation = ' ' * (longest_index_label_width - width_of_label(index)) first_line_indentation + line_1 + rest.map do |line| line =~ /\S/ ? indentation + line : line end.join end def indentation @indentation ||= ' ' * longest_index_label_width end def longest_index_label_width @longest_index_label_width ||= width_of_label(failures.size) end def width_of_label(index) index_label(index).chars.count end def index_label(index) " #{index + 1}) " end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/0000775000000000000000000000000014557700001024072 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/english_phrasing.rb0000664000000000000000000000350514557700001027746 0ustar rootrootmodule RSpec module Matchers # Facilitates converting ruby objects to English phrases. module EnglishPhrasing # Converts a symbol into an English expression. # # split_words(:banana_creme_pie) #=> "banana creme pie" # def self.split_words(sym) sym.to_s.tr('_', ' ') end # @note The returned string has a leading space except # when given an empty list. # # Converts an object (often a collection of objects) # into an English list. # # list(['banana', 'kiwi', 'mango']) # #=> " \"banana\", \"kiwi\", and \"mango\"" # # Given an empty collection, returns the empty string. # # list([]) #=> "" # def self.list(obj) return " #{RSpec::Support::ObjectFormatter.format(obj)}" if !obj || Struct === obj || Hash === obj items = Array(obj).map { |w| RSpec::Support::ObjectFormatter.format(w) } case items.length when 0 "" when 1 " #{items[0]}" when 2 " #{items[0]} and #{items[1]}" else " #{items[0...-1].join(', ')}, and #{items[-1]}" end end if RUBY_VERSION == '1.8.7' # Not sure why, but on travis on 1.8.7 we have gotten these warnings: # lib/rspec/matchers/english_phrasing.rb:28: warning: default `to_a' will be obsolete # So it appears that `Array` can trigger that (e.g. by calling `to_a` on the passed object?) # So here we replace `Kernel#Array` with our own warning-free implementation for 1.8.7. # @private # rubocop:disable Naming/MethodName def self.Array(obj) case obj when Array then obj else [obj] end end # rubocop:enable Naming/MethodName end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/matcher_protocol.rb0000664000000000000000000001172614557700001027772 0ustar rootrootmodule RSpec module Matchers # rspec-expectations can work with any matcher object that implements this protocol. # # @note This class is not loaded at runtime by rspec-expectations. It exists # purely to provide documentation for the matcher protocol. class MatcherProtocol # @!group Required Methods # @!method matches?(actual) # @param actual [Object] The object being matched against. # @yield For an expression like `expect(x).to matcher do...end`, the `do/end` # block binds to `to`. It passes that block, if there is one, on to this method. # @return [Boolean] true if this matcher matches the provided object. # @!method failure_message # This will only be called if {#matches?} returns false. # @return [String] Explanation for the failure. # @!endgroup # @!group Optional Methods # @!method does_not_match?(actual) # In a negative expectation such as `expect(x).not_to foo`, RSpec will # call `foo.does_not_match?(x)` if this method is defined. If it's not # defined it will fall back to using `!foo.matches?(x)`. This allows you # to provide custom logic for the negative case. # # @param actual [Object] The object being matched against. # @yield For an expression like `expect(x).not_to matcher do...end`, the `do/end` # block binds to `not_to`. It passes that block, if there is one, on to this method. # @return [Boolean] true if this matcher does not match the provided object. # @!method failure_message_when_negated # This will only be called when a negative match fails. # @return [String] Explanation for the failure. # @note This method is listed as optional because matchers do not have to # support negation. But if your matcher does support negation, this is a # required method -- otherwise, you'll get a `NoMethodError`. # @!method description # The description is used for two things: # # * When using RSpec's one-liner syntax # (e.g. `it { is_expected.to matcher }`), the description # is used to generate the example's doc string since you # have not provided one. # * In a composed matcher expression, the description is used # as part of the failure message (and description) of the outer # matcher. # # @return [String] Description of the matcher. # @!method supports_block_expectations? # Indicates that this matcher can be used in a block expectation expression, # such as `expect { foo }.to raise_error`. Generally speaking, this is # only needed for matchers which operate on a side effect of a block, rather # than on a particular object. # @return [Boolean] true if this matcher can be used in block expressions. # @note If not defined, RSpec assumes a value of `false` for this method. # @!method supports_value_expectations? # Indicates that this matcher can be used in a value expectation expression, # such as `expect(foo).to eq(bar)`. # @return [Boolean] true if this matcher can be used in value expressions. # @note If not defined, RSpec assumes a value of `true` for this method. # @!method expects_call_stack_jump? # Indicates that when this matcher is used in a block expectation # expression, it expects the block to use a ruby construct that causes # a call stack jump (such as raising an error or throwing a symbol). # # This is used internally for compound block expressions, as matchers # which expect call stack jumps must be treated with care to work properly. # # @return [Boolean] true if the matcher expects a call stack jump # # @note This method is very rarely used or needed. # @note If not defined, RSpec assumes a value of `false` for this method. # @!method diffable? # @return [Boolean] true if `actual` and `expected` can be diffed. # Indicates that this matcher provides `actual` and `expected` attributes, # and that the values returned by these can be usefully diffed, which can # be included in the output. # @!method actual # @return [String, Object] If an object (rather than a string) is provided, # RSpec will use the `pp` library to convert it to multi-line output in # order to diff. # The actual value for the purposes of a diff. # @note This method is required if `diffable?` returns true. # @!method expected # @return [String, Object] If an object (rather than a string) is provided, # RSpec will use the `pp` library to convert it to multi-line output in # order to diff. # The expected value for the purposes of a diff. # @note This method is required if `diffable?` returns true. # @!endgroup end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/fail_matchers.rb0000664000000000000000000000236314557700001027224 0ustar rootrootrequire 'rspec/expectations' module RSpec module Matchers # Matchers for testing RSpec matchers. Include them with: # # require 'rspec/matchers/fail_matchers' # RSpec.configure do |config| # config.include RSpec::Matchers::FailMatchers # end # module FailMatchers # Matches if an expectation fails # # @example # expect { some_expectation }.to fail def fail(&block) raise_error(RSpec::Expectations::ExpectationNotMetError, &block) end # Matches if an expectation fails with the provided message # # @example # expect { some_expectation }.to fail_with("some failure message") # expect { some_expectation }.to fail_with(/some failure message/) def fail_with(message) raise_error(RSpec::Expectations::ExpectationNotMetError, message) end # Matches if an expectation fails including the provided message # # @example # expect { some_expectation }.to fail_including("portion of some failure message") def fail_including(*snippets) raise_error( RSpec::Expectations::ExpectationNotMetError, a_string_including(*snippets) ) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/generated_descriptions.rb0000664000000000000000000000225414557700001031146 0ustar rootrootmodule RSpec module Matchers class << self # @private attr_accessor :last_matcher, :last_expectation_handler end # @api private # Used by rspec-core to clear the state used to generate # descriptions after an example. def self.clear_generated_description self.last_matcher = nil self.last_expectation_handler = nil end # @api private # Generates an an example description based on the last expectation. # Used by rspec-core's one-liner syntax. def self.generated_description return nil if last_expectation_handler.nil? "#{last_expectation_handler.verb} #{last_description}" end # @private def self.last_description last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE When you call a matcher in an example without a String, like this: specify { expect(object).to matcher } or this: it { is_expected.to matcher } RSpec expects the matcher to have a #description method. You should either add a String to the example this matcher is being used in, or give it a description method. Then you won't have to suffer this lengthy warning again. MESSAGE end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/aliased_matcher.rb0000664000000000000000000001025714557700001027531 0ustar rootrootmodule RSpec module Matchers # Decorator that wraps a matcher and overrides `description` # using the provided block in order to support an alias # of a matcher. This is intended for use when composing # matchers, so that you can use an expression like # `include( a_value_within(0.1).of(3) )` rather than # `include( be_within(0.1).of(3) )`, and have the corresponding # description read naturally. # # @api private class AliasedMatcher < MatcherDelegator def initialize(base_matcher, description_block) @description_block = description_block super(base_matcher) end # Forward messages on to the wrapped matcher. # Since many matchers provide a fluent interface # (e.g. `a_value_within(0.1).of(3)`), we need to wrap # the returned value if it responds to `description`, # so that our override can be applied when it is eventually # used. def method_missing(*) return_val = super return return_val unless RSpec::Matchers.is_a_matcher?(return_val) self.class.new(return_val, @description_block) end # Provides the description of the aliased matcher. Aliased matchers # are designed to behave identically to the original matcher except # for the description and failure messages. The description is different # to reflect the aliased name. # # @api private def description @description_block.call(super) end # Provides the failure_message of the aliased matcher. Aliased matchers # are designed to behave identically to the original matcher except # for the description and failure messages. The failure_message is different # to reflect the aliased name. # # @api private def failure_message @description_block.call(super) end # Provides the failure_message_when_negated of the aliased matcher. Aliased matchers # are designed to behave identically to the original matcher except # for the description and failure messages. The failure_message_when_negated is different # to reflect the aliased name. # # @api private def failure_message_when_negated @description_block.call(super) end end # Decorator used for matchers that have special implementations of # operators like `==` and `===`. # @private class AliasedMatcherWithOperatorSupport < AliasedMatcher # We undef these so that they get delegated via `method_missing`. undef == undef === end # @private class AliasedNegatedMatcher < AliasedMatcher def matches?(*args, &block) if @base_matcher.respond_to?(:does_not_match?) @base_matcher.does_not_match?(*args, &block) else !super end end def does_not_match?(*args, &block) @base_matcher.matches?(*args, &block) end def failure_message optimal_failure_message(__method__, :failure_message_when_negated) end def failure_message_when_negated optimal_failure_message(__method__, :failure_message) end private DefaultFailureMessages = BuiltIn::BaseMatcher::DefaultFailureMessages # For a matcher that uses the default failure messages, we prefer to # use the override provided by the `description_block`, because it # includes the phrasing that the user has expressed a preference for # by going through the effort of defining a negated matcher. # # However, if the override didn't actually change anything, then we # should return the opposite failure message instead -- the overridden # message is going to be confusing if we return it as-is, as it represents # the non-negated failure message for a negated match (or vice versa). def optimal_failure_message(same, inverted) if DefaultFailureMessages.has_default_failure_messages?(@base_matcher) base_message = @base_matcher.__send__(same) overridden = @description_block.call(base_message) return overridden if overridden != base_message end @base_matcher.__send__(inverted) end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in.rb0000664000000000000000000000651514557700001026233 0ustar rootrootRSpec::Support.require_rspec_matchers "built_in/base_matcher" module RSpec module Matchers # Container module for all built-in matchers. The matcher classes are here # (rather than directly under `RSpec::Matchers`) in order to prevent name # collisions, since `RSpec::Matchers` gets included into the user's namespace. # # Autoloading is used to delay when the matcher classes get loaded, allowing # rspec-matchers to boot faster, and avoiding loading matchers the user is # not using. module BuiltIn autoload :BeAKindOf, 'rspec/matchers/built_in/be_kind_of' autoload :BeAnInstanceOf, 'rspec/matchers/built_in/be_instance_of' autoload :BeBetween, 'rspec/matchers/built_in/be_between' autoload :Be, 'rspec/matchers/built_in/be' autoload :BeComparedTo, 'rspec/matchers/built_in/be' autoload :BeFalsey, 'rspec/matchers/built_in/be' autoload :BeHelpers, 'rspec/matchers/built_in/be' autoload :BeNil, 'rspec/matchers/built_in/be' autoload :BePredicate, 'rspec/matchers/built_in/has' autoload :BeTruthy, 'rspec/matchers/built_in/be' autoload :BeWithin, 'rspec/matchers/built_in/be_within' autoload :Change, 'rspec/matchers/built_in/change' autoload :Compound, 'rspec/matchers/built_in/compound' autoload :ContainExactly, 'rspec/matchers/built_in/contain_exactly' autoload :Cover, 'rspec/matchers/built_in/cover' autoload :EndWith, 'rspec/matchers/built_in/start_or_end_with' autoload :Eq, 'rspec/matchers/built_in/eq' autoload :Eql, 'rspec/matchers/built_in/eql' autoload :Equal, 'rspec/matchers/built_in/equal' autoload :Exist, 'rspec/matchers/built_in/exist' autoload :Has, 'rspec/matchers/built_in/has' autoload :HaveAttributes, 'rspec/matchers/built_in/have_attributes' autoload :Include, 'rspec/matchers/built_in/include' autoload :All, 'rspec/matchers/built_in/all' autoload :Match, 'rspec/matchers/built_in/match' autoload :NegativeOperatorMatcher, 'rspec/matchers/built_in/operators' autoload :OperatorMatcher, 'rspec/matchers/built_in/operators' autoload :Output, 'rspec/matchers/built_in/output' autoload :PositiveOperatorMatcher, 'rspec/matchers/built_in/operators' autoload :RaiseError, 'rspec/matchers/built_in/raise_error' autoload :RespondTo, 'rspec/matchers/built_in/respond_to' autoload :Satisfy, 'rspec/matchers/built_in/satisfy' autoload :StartWith, 'rspec/matchers/built_in/start_or_end_with' autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol' autoload :YieldControl, 'rspec/matchers/built_in/yield' autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield' autoload :YieldWithArgs, 'rspec/matchers/built_in/yield' autoload :YieldWithNoArgs, 'rspec/matchers/built_in/yield' end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/composable.rb0000664000000000000000000001430614557700001026547 0ustar rootrootRSpec::Support.require_rspec_support "fuzzy_matcher" module RSpec module Matchers # Mixin designed to support the composable matcher features # of RSpec 3+. Mix it into your custom matcher classes to # allow them to be used in a composable fashion. # # @api public module Composable # Creates a compound `and` expectation. The matcher will # only pass if both sub-matchers pass. # This can be chained together to form an arbitrarily long # chain of matchers. # # @example # expect(alphabet).to start_with("a").and end_with("z") # expect(alphabet).to start_with("a") & end_with("z") # # @note The negative form (`expect(...).not_to matcher.and other`) # is not supported at this time. def and(matcher) BuiltIn::Compound::And.new self, matcher end alias & and # Creates a compound `or` expectation. The matcher will # pass if either sub-matcher passes. # This can be chained together to form an arbitrarily long # chain of matchers. # # @example # expect(stoplight.color).to eq("red").or eq("green").or eq("yellow") # expect(stoplight.color).to eq("red") | eq("green") | eq("yellow") # # @note The negative form (`expect(...).not_to matcher.or other`) # is not supported at this time. def or(matcher) BuiltIn::Compound::Or.new self, matcher end alias | or # Delegates to `#matches?`. Allows matchers to be used in composable # fashion and also supports using matchers in case statements. def ===(value) matches?(value) end private # This provides a generic way to fuzzy-match an expected value against # an actual value. It understands nested data structures (e.g. hashes # and arrays) and is able to match against a matcher being used as # the expected value or within the expected value at any level of # nesting. # # Within a custom matcher you are encouraged to use this whenever your # matcher needs to match two values, unless it needs more precise semantics. # For example, the `eq` matcher _does not_ use this as it is meant to # use `==` (and only `==`) for matching. # # @param expected [Object] what is expected # @param actual [Object] the actual value # # @!visibility public def values_match?(expected, actual) expected = with_matchers_cloned(expected) Support::FuzzyMatcher.values_match?(expected, actual) end # Returns the description of the given object in a way that is # aware of composed matchers. If the object is a matcher with # a `description` method, returns the description; otherwise # returns `object.inspect`. # # You are encouraged to use this in your custom matcher's # `description`, `failure_message` or # `failure_message_when_negated` implementation if you are # supporting matcher arguments. # # @!visibility public def description_of(object) RSpec::Support::ObjectFormatter.format(object) end # Transforms the given data structure (typically a hash or array) # into a new data structure that, when `#inspect` is called on it, # will provide descriptions of any contained matchers rather than # the normal `#inspect` output. # # You are encouraged to use this in your custom matcher's # `description`, `failure_message` or # `failure_message_when_negated` implementation if you are # supporting any arguments which may be a data structure # containing matchers. # # @!visibility public def surface_descriptions_in(item) if Matchers.is_a_describable_matcher?(item) DescribableItem.new(item) elsif Hash === item Hash[surface_descriptions_in(item.to_a)] elsif Struct === item || unreadable_io?(item) RSpec::Support::ObjectFormatter.format(item) elsif should_enumerate?(item) item.map { |subitem| surface_descriptions_in(subitem) } else item end end # @private # Historically, a single matcher instance was only checked # against a single value. Given that the matcher was only # used once, it's been common to memoize some intermediate # calculation that is derived from the `actual` value in # order to reuse that intermediate result in the failure # message. # # This can cause a problem when using such a matcher as an # argument to another matcher in a composed matcher expression, # since the matcher instance may be checked against multiple # values and produce invalid results due to the memoization. # # To deal with this, we clone any matchers in `expected` via # this method when using `values_match?`, so that any memoization # does not "leak" between checks. def with_matchers_cloned(object) if Matchers.is_a_matcher?(object) object.clone elsif Hash === object Hash[with_matchers_cloned(object.to_a)] elsif should_enumerate?(object) object.map { |subobject| with_matchers_cloned(subobject) } else object end end # @api private # We should enumerate arrays as long as they are not recursive. def should_enumerate?(item) Array === item && item.none? { |subitem| subitem.equal?(item) } end # @api private def unreadable_io?(object) return false unless IO === object object.each {} # STDOUT is enumerable but raises an error false rescue IOError true end module_function :surface_descriptions_in, :should_enumerate?, :unreadable_io? # Wraps an item in order to surface its `description` via `inspect`. # @api private DescribableItem = Struct.new(:item) do # Inspectable version of the item description def inspect "(#{item.description})" end # A pretty printed version of the item description. def pretty_print(pp) pp.text "(#{item.description})" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/matcher_delegator.rb0000664000000000000000000000333114557700001030070 0ustar rootrootmodule RSpec module Matchers # Provides a base class with as little methods as possible, so that # most methods can be delegated via `method_missing`. # # On Ruby 2.0+ BasicObject could be used for this purpose, but it # introduce some extra complexity with constant resolution, so the # BlankSlate pattern was prefered. # @private class BaseDelegator kept_methods = [ # Methods that raise warnings if removed. :__id__, :__send__, :object_id, # Methods that are explicitly undefined in some subclasses. :==, :===, # Methods we keep on purpose. :class, :respond_to?, :__method__, :method, :dup, :clone, :initialize_dup, :initialize_copy, :initialize_clone, ] instance_methods.each do |method| unless kept_methods.include?(method.to_sym) undef_method(method) end end end # Provides the necessary plumbing to wrap a matcher with a decorator. # @private class MatcherDelegator < BaseDelegator include Composable attr_reader :base_matcher def initialize(base_matcher) @base_matcher = base_matcher end def method_missing(*args, &block) base_matcher.__send__(*args, &block) end if ::RUBY_VERSION.to_f > 1.8 def respond_to_missing?(name, include_all=false) super || base_matcher.respond_to?(name, include_all) end else # :nocov: def respond_to?(name, include_all=false) super || base_matcher.respond_to?(name, include_all) end # :nocov: end def initialize_copy(other) @base_matcher = @base_matcher.clone super end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/0000775000000000000000000000000014557700001025677 5ustar rootrootruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/be.rb0000664000000000000000000001103414557700001026611 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `be_truthy`. # Not intended to be instantiated directly. class BeTruthy < BaseMatcher # @api private # @return [String] def failure_message "expected: truthy value\n got: #{actual_formatted}" end # @api private # @return [String] def failure_message_when_negated "expected: falsey value\n got: #{actual_formatted}" end private def match(_, actual) !!actual end end # @api private # Provides the implementation for `be_falsey`. # Not intended to be instantiated directly. class BeFalsey < BaseMatcher # @api private # @return [String] def failure_message "expected: falsey value\n got: #{actual_formatted}" end # @api private # @return [String] def failure_message_when_negated "expected: truthy value\n got: #{actual_formatted}" end private def match(_, actual) !actual end end # @api private # Provides the implementation for `be_nil`. # Not intended to be instantiated directly. class BeNil < BaseMatcher # @api private # @return [String] def failure_message "expected: nil\n got: #{actual_formatted}" end # @api private # @return [String] def failure_message_when_negated "expected: not nil\n got: nil" end private def match(_, actual) actual.nil? end end # @private module BeHelpers private def args_to_s @args.empty? ? "" : parenthesize(inspected_args.join(', ')) end def parenthesize(string) "(#{string})" end def inspected_args @args.map { |a| RSpec::Support::ObjectFormatter.format(a) } end def expected_to_sentence EnglishPhrasing.split_words(@expected) end def args_to_sentence EnglishPhrasing.list(@args) end end # @api private # Provides the implementation for `be`. # Not intended to be instantiated directly. class Be < BaseMatcher include BeHelpers def initialize(*args) @args = args end # @api private # @return [String] def failure_message "expected #{actual_formatted} to evaluate to true" end # @api private # @return [String] def failure_message_when_negated "expected #{actual_formatted} to evaluate to false" end [:==, :<, :<=, :>=, :>, :===, :=~].each do |operator| define_method operator do |operand| BeComparedTo.new(operand, operator) end end private def match(_, actual) !!actual end end # @api private # Provides the implementation of `be value`. # Not intended to be instantiated directly. class BeComparedTo < BaseMatcher include BeHelpers def initialize(operand, operator) @expected = operand @operator = operator @args = [] end def matches?(actual) perform_match(actual) rescue ArgumentError, NoMethodError false end def does_not_match?(actual) !perform_match(actual) rescue ArgumentError, NoMethodError false end # @api private # @return [String] def failure_message "expected: #{@operator} #{expected_formatted}\n" \ " got: #{@operator.to_s.gsub(/./, ' ')} #{actual_formatted}" end # @api private # @return [String] def failure_message_when_negated message = "`expect(#{actual_formatted}).not_to " \ "be #{@operator} #{expected_formatted}`" if [:<, :>, :<=, :>=].include?(@operator) message + " not only FAILED, it is a bit confusing." else message end end # @api private # @return [String] def description "be #{@operator} #{expected_to_sentence}#{args_to_sentence}" end private def perform_match(actual) @actual = actual @actual.__send__ @operator, @expected end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/include.rb0000664000000000000000000001467614557700001027665 0ustar rootrootrequire 'rspec/matchers/built_in/count_expectation' module RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `include`. # Not intended to be instantiated directly. class Include < BaseMatcher # rubocop:disable Metrics/ClassLength include CountExpectation # @private attr_reader :expecteds # @api private def initialize(*expecteds) @expecteds = expecteds end # @api private # @return [Boolean] def matches?(actual) check_actual?(actual) && if check_expected_count? expected_count_matches?(count_inclusions) else perform_match { |v| v } end end # @api private # @return [Boolean] def does_not_match?(actual) check_actual?(actual) && if check_expected_count? !expected_count_matches?(count_inclusions) else perform_match { |v| !v } end end # @api private # @return [String] def description improve_hash_formatting("include#{readable_list_of(expecteds)}#{count_expectation_description}") end # @api private # @return [String] def failure_message format_failure_message("to") { super } end # @api private # @return [String] def failure_message_when_negated format_failure_message("not to") { super } end # @api private # @return [Boolean] def diffable? !diff_would_wrongly_highlight_matched_item? end # @api private # @return [Array, Hash] def expected if expecteds.one? && Hash === expecteds.first expecteds.first else expecteds end end private def check_actual?(actual) actual = actual.to_hash if convert_to_hash?(actual) @actual = actual @actual.respond_to?(:include?) end def check_expected_count? case when !has_expected_count? return false when expecteds.size != 1 raise NotImplementedError, 'Count constraint supported only when testing for a single value being included' when actual.is_a?(Hash) raise NotImplementedError, 'Count constraint on hash keys not implemented' end true end def format_failure_message(preposition) msg = if actual.respond_to?(:include?) "expected #{description_of @actual} #{preposition}" \ " include#{readable_list_of @divergent_items}" \ "#{count_failure_reason('it is included') if has_expected_count?}" else "#{yield}, but it does not respond to `include?`" end improve_hash_formatting(msg) end def readable_list_of(items) described_items = surface_descriptions_in(items) if described_items.all? { |item| item.is_a?(Hash) } " #{described_items.inject(:merge).inspect}" else EnglishPhrasing.list(described_items) end end def perform_match(&block) @divergent_items = excluded_from_actual(&block) @divergent_items.empty? end def excluded_from_actual return [] unless @actual.respond_to?(:include?) expecteds.inject([]) do |memo, expected_item| if comparing_hash_to_a_subset?(expected_item) expected_item.each do |(key, value)| memo << { key => value } unless yield actual_hash_includes?(key, value) end elsif comparing_hash_keys?(expected_item) memo << expected_item unless yield actual_hash_has_key?(expected_item) else memo << expected_item unless yield actual_collection_includes?(expected_item) end memo end end def comparing_hash_to_a_subset?(expected_item) actual.is_a?(Hash) && expected_item.is_a?(Hash) end def actual_hash_includes?(expected_key, expected_value) actual_value = actual.fetch(expected_key) do actual.find(Proc.new { return false }) { |actual_key, _| values_match?(expected_key, actual_key) }[1] end values_match?(expected_value, actual_value) end def comparing_hash_keys?(expected_item) actual.is_a?(Hash) && !expected_item.is_a?(Hash) end def actual_hash_has_key?(expected_key) # We check `key?` first for perf: # `key?` is O(1), but `any?` is O(N). has_exact_key = begin actual.key?(expected_key) rescue false end has_exact_key || actual.keys.any? { |key| values_match?(expected_key, key) } end def actual_collection_includes?(expected_item) return true if actual.include?(expected_item) # String lacks an `any?` method... return false unless actual.respond_to?(:any?) actual.any? { |value| values_match?(expected_item, value) } end if RUBY_VERSION < '1.9' def count_enumerable(expected_item) actual.select { |value| values_match?(expected_item, value) }.size end else def count_enumerable(expected_item) actual.count { |value| values_match?(expected_item, value) } end end def count_inclusions @divergent_items = expected case actual when String actual.scan(expected.first).length when Enumerable count_enumerable(Hash === expected ? expected : expected.first) else raise NotImplementedError, 'Count constraints are implemented for Enumerable and String values only' end end def diff_would_wrongly_highlight_matched_item? return false unless actual.is_a?(String) && expected.is_a?(Array) lines = actual.split("\n") expected.any? do |str| actual.include?(str) && lines.none? { |line| line == str } end end def convert_to_hash?(obj) !obj.respond_to?(:include?) && obj.respond_to?(:to_hash) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/start_or_end_with.rb0000664000000000000000000000533414557700001031747 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Base class for the `end_with` and `start_with` matchers. # Not intended to be instantiated directly. class StartOrEndWith < BaseMatcher def initialize(*expected) @actual_does_not_have_ordered_elements = false @expected = expected.length == 1 ? expected.first : expected end # @api private # @return [String] def failure_message super.tap do |msg| if @actual_does_not_have_ordered_elements msg << ", but it does not have ordered elements" elsif !actual.respond_to?(:[]) msg << ", but it cannot be indexed using #[]" end end end # @api private # @return [String] def description return super unless Hash === expected english_name = EnglishPhrasing.split_words(self.class.matcher_name) description_of_expected = surface_descriptions_in(expected).inspect "#{english_name} #{description_of_expected}" end private def match(_expected, actual) return false unless actual.respond_to?(:[]) begin return true if subsets_comparable? && subset_matches? element_matches? rescue ArgumentError @actual_does_not_have_ordered_elements = true return false end end def subsets_comparable? # Structs support the Enumerable interface but don't really have # the semantics of a subset of a larger set... return false if Struct === expected expected.respond_to?(:length) end end # For RSpec 3.1, the base class was named `StartAndEndWith`. For SemVer reasons, # we still provide this constant until 4.0. # @deprecated Use StartOrEndWith instead. # @private StartAndEndWith = StartOrEndWith # @api private # Provides the implementation for `start_with`. # Not intended to be instantiated directly. class StartWith < StartOrEndWith private def subset_matches? values_match?(expected, actual[0, expected.length]) end def element_matches? values_match?(expected, actual[0]) end end # @api private # Provides the implementation for `end_with`. # Not intended to be instantiated directly. class EndWith < StartOrEndWith private def subset_matches? values_match?(expected, actual[-expected.length, expected.length]) end def element_matches? values_match?(expected, actual[-1]) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/be_kind_of.rb0000664000000000000000000000115014557700001030300 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `be_a_kind_of`. # Not intended to be instantiated directly. class BeAKindOf < BaseMatcher private def match(expected, actual) actual.kind_of?(expected) rescue NoMethodError raise ::ArgumentError, "The #{matcher_name} matcher requires that " \ "the actual object responds to #kind_of? method " \ "but a `NoMethodError` was encountered instead." end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/throw_symbol.rb0000664000000000000000000000772214557700001030764 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `throw_symbol`. # Not intended to be instantiated directly. class ThrowSymbol include Composable def initialize(expected_symbol=nil, expected_arg=nil) @expected_symbol = expected_symbol @expected_arg = expected_arg @caught_symbol = @caught_arg = nil end # rubocop:disable Metrics/MethodLength # @private def matches?(given_proc) @block = given_proc return false unless Proc === given_proc begin if @expected_symbol.nil? given_proc.call else @caught_arg = catch :proc_did_not_throw_anything do catch @expected_symbol do given_proc.call throw :proc_did_not_throw_anything, :nothing_thrown end end if @caught_arg == :nothing_thrown @caught_arg = nil else @caught_symbol = @expected_symbol end end # Ruby 1.8 uses NameError with `symbol' # Ruby 1.9 uses ArgumentError with :symbol rescue NameError, ArgumentError => e unless (match_data = e.message.match(/uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/)) other_exception = e raise end @caught_symbol = match_data.captures[1].to_sym rescue => other_exception raise ensure # rubocop:disable Lint/EnsureReturn unless other_exception if @expected_symbol.nil? return !!@caught_symbol else if @expected_arg.nil? return @caught_symbol == @expected_symbol else return (@caught_symbol == @expected_symbol) && values_match?(@expected_arg, @caught_arg) end end end # rubocop:enable Lint/EnsureReturn end end # rubocop:enable Metrics/MethodLength def does_not_match?(given_proc) !matches?(given_proc) && Proc === given_proc end # @api private # @return [String] def failure_message "expected #{expected} to be thrown, #{actual_result}" end # @api private # @return [String] def failure_message_when_negated "expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, #{actual_result}" end # @api private # @return [String] def description "throw #{expected}" end # @api private # Indicates this matcher matches against a block. # @return [True] def supports_block_expectations? true end # @api private def supports_value_expectations? false end # @api private def expects_call_stack_jump? true end private def actual_result return "but was not a block" unless Proc === @block "got #{caught}" end def expected(symbol_desc='a Symbol') throw_description(@expected_symbol || symbol_desc, @expected_arg) end def caught throw_description(@caught_symbol || 'nothing', @caught_arg) end def throw_description(symbol, arg) symbol_description = symbol.is_a?(String) ? symbol : description_of(symbol) arg_description = if arg " with #{description_of arg}" elsif @expected_arg && @caught_symbol == @expected_symbol " with no argument" else "" end symbol_description + arg_description end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/all.rb0000664000000000000000000000465314557700001027004 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `all`. # Not intended to be instantiated directly. class All < BaseMatcher # @private attr_reader :matcher, :failed_objects def initialize(matcher) @matcher = matcher @failed_objects = {} end # @private def does_not_match?(_actual) raise NotImplementedError, '`expect().not_to all( matcher )` is not supported.' end # @api private # @return [String] def failure_message unless iterable? return "#{improve_hash_formatting(super)}, but was not iterable" end all_messages = [improve_hash_formatting(super)] failed_objects.each do |index, matcher_failure_message| all_messages << failure_message_for_item(index, matcher_failure_message) end all_messages.join("\n\n") end # @api private # @return [String] def description improve_hash_formatting "all #{description_of matcher}" end private def match(_expected, _actual) return false unless iterable? index_failed_objects failed_objects.empty? end def index_failed_objects actual.each_with_index do |actual_item, index| cloned_matcher = matcher.clone matches = cloned_matcher.matches?(actual_item) failed_objects[index] = cloned_matcher.failure_message unless matches end end def failure_message_for_item(index, failure_message) failure_message = indent_multiline_message(add_new_line_if_needed(failure_message)) indent_multiline_message("object at index #{index} failed to match:#{failure_message}") end def add_new_line_if_needed(message) message.start_with?("\n") ? message : "\n#{message}" end def indent_multiline_message(message) message = message.sub(/\n+\z/, '') message.lines.map do |line| line =~ /\S/ ? ' ' + line : line end.join end def initialize_copy(other) @matcher = @matcher.clone @failed_objects = @failed_objects.clone super end def iterable? @actual.respond_to?(:each_with_index) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/contain_exactly.rb0000664000000000000000000002621014557700001031411 0ustar rootrootmodule RSpec module Matchers module BuiltIn # rubocop:disable Metrics/ClassLength # @api private # Provides the implementation for `contain_exactly` and `match_array`. # Not intended to be instantiated directly. class ContainExactly < BaseMatcher # @api private # @return [String] def failure_message if Array === actual generate_failure_message else "expected a collection that can be converted to an array with " \ "`#to_ary` or `#to_a`, but got #{actual_formatted}" end end # @api private # @return [String] def failure_message_when_negated list = EnglishPhrasing.list(surface_descriptions_in(expected)) "expected #{actual_formatted} not to contain exactly#{list}" end # @api private # @return [String] def description list = EnglishPhrasing.list(surface_descriptions_in(expected)) "contain exactly#{list}" end def matches?(actual) @pairings_maximizer = nil @best_solution = nil @extra_items = nil @missing_items = nil super(actual) end private def generate_failure_message message = expected_collection_line message += actual_collection_line message += missing_elements_line unless missing_items.empty? message += extra_elements_line unless extra_items.empty? message end def expected_collection_line message_line('expected collection contained', expected, true) end def actual_collection_line message_line('actual collection contained', actual) end def missing_elements_line message_line('the missing elements were', missing_items, true) end def extra_elements_line message_line('the extra elements were', extra_items) end def describe_collection(collection, surface_descriptions=false) if surface_descriptions "#{description_of(safe_sort(surface_descriptions_in collection))}\n" else "#{description_of(safe_sort(collection))}\n" end end def message_line(prefix, collection, surface_descriptions=false) "%-32s%s" % [prefix + ':', describe_collection(collection, surface_descriptions)] end def match(_expected, _actual) return false unless convert_actual_to_an_array match_when_sorted? || (extra_items.empty? && missing_items.empty?) end # This cannot always work (e.g. when dealing with unsortable items, # or matchers as expected items), but it's practically free compared to # the slowness of the full matching algorithm, and in common cases this # works, so it's worth a try. def match_when_sorted? values_match?(safe_sort(expected), safe_sort(actual)) end def convert_actual_to_an_array if actual.respond_to?(:to_ary) @actual = actual.to_ary elsif actual.respond_to?(:to_a) && !to_a_disallowed?(actual) @actual = actual.to_a else false end end def safe_sort(array) array.sort rescue Support::AllExceptionsExceptOnesWeMustNotRescue array end if RUBY_VERSION == "1.8.7" def to_a_disallowed?(object) case object when NilClass, String then true else Kernel == RSpec::Support.method_handle_for(object, :to_a).owner end end else def to_a_disallowed?(object) NilClass === object end end def missing_items @missing_items ||= best_solution.unmatched_expected_indexes.map do |index| expected[index] end end def extra_items @extra_items ||= best_solution.unmatched_actual_indexes.map do |index| actual[index] end end def best_solution @best_solution ||= pairings_maximizer.find_best_solution end def pairings_maximizer @pairings_maximizer ||= begin expected_matches = Hash[Array.new(expected.size) { |i| [i, []] }] actual_matches = Hash[Array.new(actual.size) { |i| [i, []] }] expected.each_with_index do |e, ei| actual.each_with_index do |a, ai| next unless values_match?(e, a) expected_matches[ei] << ai actual_matches[ai] << ei end end PairingsMaximizer.new(expected_matches, actual_matches) end end # Once we started supporting composing matchers, the algorithm for this matcher got # much more complicated. Consider this expression: # # expect(["fool", "food"]).to contain_exactly(/foo/, /fool/) # # This should pass (because we can pair /fool/ with "fool" and /foo/ with "food"), but # the original algorithm used by this matcher would pair the first elements it could # (/foo/ with "fool"), which would leave /fool/ and "food" unmatched. When we have # an expected element which is a matcher that matches a superset of actual items # compared to another expected element matcher, we need to consider every possible pairing. # # This class is designed to maximize the number of actual/expected pairings -- or, # conversely, to minimize the number of unpaired items. It's essentially a brute # force solution, but with a few heuristics applied to reduce the size of the # problem space: # # * Any items which match none of the items in the other list are immediately # placed into the `unmatched_expected_indexes` or `unmatched_actual_indexes` array. # The extra items and missing items in the matcher failure message are derived # from these arrays. # * Any items which reciprocally match only each other are paired up and not # considered further. # # What's left is only the items which match multiple items from the other list # (or vice versa). From here, it performs a brute-force depth-first search, # looking for a solution which pairs all elements in both lists, or, barring that, # that produces the fewest unmatched items. # # @private class PairingsMaximizer # @private Solution = Struct.new(:unmatched_expected_indexes, :unmatched_actual_indexes, :indeterminate_expected_indexes, :indeterminate_actual_indexes) do def worse_than?(other) unmatched_item_count > other.unmatched_item_count end def candidate? indeterminate_expected_indexes.empty? && indeterminate_actual_indexes.empty? end def ideal? candidate? && ( unmatched_expected_indexes.empty? || unmatched_actual_indexes.empty? ) end def unmatched_item_count unmatched_expected_indexes.count + unmatched_actual_indexes.count end def +(derived_candidate_solution) self.class.new( unmatched_expected_indexes + derived_candidate_solution.unmatched_expected_indexes, unmatched_actual_indexes + derived_candidate_solution.unmatched_actual_indexes, # Ignore the indeterminate indexes: by the time we get here, # we've dealt with all indeterminates. [], [] ) end end attr_reader :expected_to_actual_matched_indexes, :actual_to_expected_matched_indexes, :solution def initialize(expected_to_actual_matched_indexes, actual_to_expected_matched_indexes) @expected_to_actual_matched_indexes = expected_to_actual_matched_indexes @actual_to_expected_matched_indexes = actual_to_expected_matched_indexes unmatched_expected_indexes, indeterminate_expected_indexes = categorize_indexes(expected_to_actual_matched_indexes, actual_to_expected_matched_indexes) unmatched_actual_indexes, indeterminate_actual_indexes = categorize_indexes(actual_to_expected_matched_indexes, expected_to_actual_matched_indexes) @solution = Solution.new(unmatched_expected_indexes, unmatched_actual_indexes, indeterminate_expected_indexes, indeterminate_actual_indexes) end def find_best_solution return solution if solution.candidate? best_solution_so_far = NullSolution expected_index = solution.indeterminate_expected_indexes.first actuals = expected_to_actual_matched_indexes[expected_index] actuals.each do |actual_index| solution = best_solution_for_pairing(expected_index, actual_index) return solution if solution.ideal? best_solution_so_far = solution if best_solution_so_far.worse_than?(solution) end best_solution_so_far end private # @private # Starting solution that is worse than any other real solution. NullSolution = Class.new do def self.worse_than?(_other) true end end def categorize_indexes(indexes_to_categorize, other_indexes) unmatched = [] indeterminate = [] indexes_to_categorize.each_pair do |index, matches| if matches.empty? unmatched << index elsif !reciprocal_single_match?(matches, index, other_indexes) indeterminate << index end end return unmatched, indeterminate end def reciprocal_single_match?(matches, index, other_list) return false unless matches.one? other_list[matches.first] == [index] end def best_solution_for_pairing(expected_index, actual_index) modified_expecteds = apply_pairing_to( solution.indeterminate_expected_indexes, expected_to_actual_matched_indexes, actual_index) modified_expecteds.delete(expected_index) modified_actuals = apply_pairing_to( solution.indeterminate_actual_indexes, actual_to_expected_matched_indexes, expected_index) modified_actuals.delete(actual_index) solution + self.class.new(modified_expecteds, modified_actuals).find_best_solution end def apply_pairing_to(indeterminates, original_matches, other_list_index) indeterminates.inject({}) do |accum, index| accum[index] = original_matches[index] - [other_list_index] accum end end end end # rubocop:enable Metrics/ClassLength end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/base_matcher.rb0000664000000000000000000001674514557700001030656 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # # Used _internally_ as a base class for matchers that ship with # rspec-expectations and rspec-rails. # # ### Warning: # # This class is for internal use, and subject to change without notice. # We strongly recommend that you do not base your custom matchers on this # class. If/when this changes, we will announce it and remove this warning. class BaseMatcher include RSpec::Matchers::Composable # @api private # Used to detect when no arg is passed to `initialize`. # `nil` cannot be used because it's a valid value to pass. UNDEFINED = Object.new.freeze # @private attr_reader :actual, :expected, :rescued_exception # @private attr_writer :matcher_name def initialize(expected=UNDEFINED) @expected = expected unless UNDEFINED.equal?(expected) end # @api private # Indicates if the match is successful. Delegates to `match`, which # should be defined on a subclass. Takes care of consistently # initializing the `actual` attribute. def matches?(actual) @actual = actual match(expected, actual) end # @api private # Used to wrap a block of code that will indicate failure by # raising one of the named exceptions. # # This is used by rspec-rails for some of its matchers that # wrap rails' assertions. def match_unless_raises(*exceptions) exceptions.unshift Exception if exceptions.empty? begin yield true rescue *exceptions => @rescued_exception false end end # @api private # Generates a description using {EnglishPhrasing}. # @return [String] def description desc = EnglishPhrasing.split_words(self.class.matcher_name) desc << EnglishPhrasing.list(@expected) if defined?(@expected) desc end # @api private # Matchers are not diffable by default. Override this to make your # subclass diffable. def diffable? false end # @api private # Most matchers are value matchers (i.e. meant to work with `expect(value)`) # rather than block matchers (i.e. meant to work with `expect { }`), so # this defaults to false. Block matchers must override this to return true. def supports_block_expectations? false end # @private def supports_value_expectations? true end # @api private def expects_call_stack_jump? false end # @private def expected_formatted RSpec::Support::ObjectFormatter.format(@expected) end # @private def actual_formatted RSpec::Support::ObjectFormatter.format(@actual) end # @private def self.matcher_name @matcher_name ||= underscore(name.split('::').last) end # @private def matcher_name if defined?(@matcher_name) @matcher_name else self.class.matcher_name end end # @private # Borrowed from ActiveSupport. def self.underscore(camel_cased_word) word = camel_cased_word.to_s.dup word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.tr!('-', '_') word.downcase! word end private_class_method :underscore private def assert_ivars(*expected_ivars) return unless (expected_ivars - present_ivars).any? ivar_list = EnglishPhrasing.list(expected_ivars) raise "#{self.class.name} needs to supply#{ivar_list}" end if RUBY_VERSION.to_f < 1.9 # :nocov: def present_ivars instance_variables.map(&:to_sym) end # :nocov: else alias present_ivars instance_variables end # @private module HashFormatting # `{ :a => 5, :b => 2 }.inspect` produces: # # {:a=>5, :b=>2} # # ...but it looks much better as: # # {:a => 5, :b => 2} # # This is idempotent and safe to run on a string multiple times. def improve_hash_formatting(inspect_string) inspect_string.gsub(/(\S)=>(\S)/, '\1 => \2') end module_function :improve_hash_formatting end include HashFormatting # @private module StringEncodingFormatting # @api private # @return [Boolean] True if the actual and expected string encoding are different. # i.e. the failure may be related to encoding differences and the encoding # should be shown to the user. false otherwise. if String.method_defined?(:encoding) def string_encoding_differs? actual.is_a?(String) && expected.is_a?(String) && actual.encoding != expected.encoding end else # @api private # @return [Boolean] False always as the curent Ruby version does not support String encoding def string_encoding_differs? false end end module_function :string_encoding_differs? if String.method_defined?(:encoding) # @api private # Formats a String's encoding as a human readable string # @param value [String] # @return [String] def format_encoding(value) "#" end else # @api private # Formats a String's encoding as a human readable string # @param _value [String] # @return [nil] nil as the curent Ruby version does not support String encoding def format_encoding(_value) nil end end module_function :format_encoding end include StringEncodingFormatting # @api private # Provides default implementations of failure messages, based on the `description`. module DefaultFailureMessages # @api private # Provides a good generic failure message. Based on `description`. # When subclassing, if you are not satisfied with this failure message # you often only need to override `description`. # @return [String] def failure_message "expected #{description_of @actual} to #{description}".dup end # @api private # Provides a good generic negative failure message. Based on `description`. # When subclassing, if you are not satisfied with this failure message # you often only need to override `description`. # @return [String] def failure_message_when_negated "expected #{description_of @actual} not to #{description}".dup end # @private def self.has_default_failure_messages?(matcher) matcher.method(:failure_message).owner == self && matcher.method(:failure_message_when_negated).owner == self rescue NameError false end end include DefaultFailureMessages end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/output.rb0000664000000000000000000001270414557700001027570 0ustar rootrootrequire 'stringio' module RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `output`. # Not intended to be instantiated directly. class Output < BaseMatcher def initialize(expected) @expected = expected @actual = "" @block = nil @stream_capturer = NullCapture end def matches?(block) @block = block return false unless Proc === block @actual = @stream_capturer.capture(block) @expected ? values_match?(@expected, @actual) : captured? end def does_not_match?(block) !matches?(block) && Proc === block end # @api public # Tells the matcher to match against stdout. # Works only when the main Ruby process prints to stdout def to_stdout @stream_capturer = CaptureStdout self end # @api public # Tells the matcher to match against stderr. # Works only when the main Ruby process prints to stderr def to_stderr @stream_capturer = CaptureStderr self end # @api public # Tells the matcher to match against stdout. # Works when subprocesses print to stdout as well. # This is significantly (~30x) slower than `to_stdout` def to_stdout_from_any_process @stream_capturer = CaptureStreamToTempfile.new("stdout", $stdout) self end # @api public # Tells the matcher to match against stderr. # Works when subprocesses print to stderr as well. # This is significantly (~30x) slower than `to_stderr` def to_stderr_from_any_process @stream_capturer = CaptureStreamToTempfile.new("stderr", $stderr) self end # @api private # @return [String] def failure_message "expected block to #{description}, but #{positive_failure_reason}" end # @api private # @return [String] def failure_message_when_negated "expected block to not #{description}, but #{negative_failure_reason}" end # @api private # @return [String] def description if @expected "output #{description_of @expected} to #{@stream_capturer.name}" else "output to #{@stream_capturer.name}" end end # @api private # @return [Boolean] def diffable? true end # @api private # Indicates this matcher matches against a block. # @return [True] def supports_block_expectations? true end # @api private # Indicates this matcher matches against a block only. # @return [False] def supports_value_expectations? false end private def captured? @actual.length > 0 end def positive_failure_reason return "was not a block" unless Proc === @block return "output #{actual_output_description}" if @expected "did not" end def negative_failure_reason return "was not a block" unless Proc === @block "output #{actual_output_description}" end def actual_output_description return "nothing" unless captured? actual_formatted end end # @private module NullCapture def self.name "some stream" end def self.capture(_block) raise "You must chain `to_stdout` or `to_stderr` off of the `output(...)` matcher." end end # @private module CaptureStdout def self.name 'stdout' end def self.capture(block) captured_stream = StringIO.new original_stream = $stdout $stdout = captured_stream block.call captured_stream.string ensure $stdout = original_stream end end # @private module CaptureStderr def self.name 'stderr' end def self.capture(block) captured_stream = StringIO.new original_stream = $stderr $stderr = captured_stream block.call captured_stream.string ensure $stderr = original_stream end end # @private class CaptureStreamToTempfile < Struct.new(:name, :stream) def capture(block) # We delay loading tempfile until it is actually needed because # we want to minimize stdlibs loaded so that users who use a # portion of the stdlib can't have passing specs while forgetting # to load it themselves. `CaptureStreamToTempfile` is rarely used # and `tempfile` pulls in a bunch of things (delegate, tmpdir, # thread, fileutils, etc), so it's worth delaying it until this point. require 'tempfile' original_stream = stream.clone captured_stream = Tempfile.new(name) begin captured_stream.sync = true stream.reopen(captured_stream) block.call captured_stream.rewind captured_stream.read ensure stream.reopen(original_stream) captured_stream.close captured_stream.unlink end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/be_within.rb0000664000000000000000000000346314557700001030202 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `be_within`. # Not intended to be instantiated directly. class BeWithin < BaseMatcher def initialize(delta) @delta = delta end # @api public # Sets the expected value. def of(expected) @expected = expected @tolerance = @delta @unit = '' self end # @api public # Sets the expected value, and makes the matcher do # a percent comparison. def percent_of(expected) @expected = expected @tolerance = @expected.abs * @delta / 100.0 @unit = '%' self end # @private def matches?(actual) @actual = actual raise needs_expected unless defined? @expected numeric? && (@actual - @expected).abs <= @tolerance end # @api private # @return [String] def failure_message "expected #{actual_formatted} to #{description}#{not_numeric_clause}" end # @api private # @return [String] def failure_message_when_negated "expected #{actual_formatted} not to #{description}" end # @api private # @return [String] def description "be within #{@delta}#{@unit} of #{expected_formatted}" end private def numeric? @actual.respond_to?(:-) end def needs_expected ArgumentError.new "You must set an expected value using #of: be_within(#{@delta}).of(expected_value)" end def not_numeric_clause ", but it could not be treated as a numeric value" unless numeric? end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/be_between.rb0000664000000000000000000000377014557700001030332 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `be_between`. # Not intended to be instantiated directly. class BeBetween < BaseMatcher def initialize(min, max) @min, @max = min, max inclusive end # @api public # Makes the between comparison inclusive. # # @example # expect(3).to be_between(2, 3).inclusive # # @note The matcher is inclusive by default; this simply provides # a way to be more explicit about it. def inclusive @less_than_operator = :<= @greater_than_operator = :>= @mode = :inclusive self end # @api public # Makes the between comparison exclusive. # # @example # expect(3).to be_between(2, 4).exclusive def exclusive @less_than_operator = :< @greater_than_operator = :> @mode = :exclusive self end # @api private # @return [Boolean] def matches?(actual) @actual = actual comparable? && compare rescue ArgumentError false end # @api private # @return [String] def failure_message "#{super}#{not_comparable_clause}" end # @api private # @return [String] def description "be between #{description_of @min} and #{description_of @max} (#{@mode})" end private def comparable? @actual.respond_to?(@less_than_operator) && @actual.respond_to?(@greater_than_operator) end def not_comparable_clause ", but it does not respond to `#{@less_than_operator}` and `#{@greater_than_operator}`" unless comparable? end def compare @actual.__send__(@greater_than_operator, @min) && @actual.__send__(@less_than_operator, @max) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/compound.rb0000664000000000000000000002211514557700001030051 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Base class for `and` and `or` compound matchers. class Compound < BaseMatcher # @private attr_reader :matcher_1, :matcher_2, :evaluator def initialize(matcher_1, matcher_2) @matcher_1 = matcher_1 @matcher_2 = matcher_2 end # @private def does_not_match?(_actual) raise NotImplementedError, "`expect(...).not_to matcher.#{conjunction} matcher` " \ "is not supported, since it creates a bit of an ambiguity. Instead, define negated versions " \ "of whatever matchers you wish to negate with `RSpec::Matchers.define_negated_matcher` and " \ "use `expect(...).to matcher.#{conjunction} matcher`." end # @api private # @return [String] def description "#{matcher_1.description} #{conjunction} #{matcher_2.description}" end # @api private def supports_block_expectations? matcher_supports_block_expectations?(matcher_1) && matcher_supports_block_expectations?(matcher_2) end # @api private def supports_value_expectations? matcher_supports_value_expectations?(matcher_1) && matcher_supports_value_expectations?(matcher_2) end # @api private def expects_call_stack_jump? NestedEvaluator.matcher_expects_call_stack_jump?(matcher_1) || NestedEvaluator.matcher_expects_call_stack_jump?(matcher_2) end # @api private # @return [Boolean] def diffable? matcher_is_diffable?(matcher_1) || matcher_is_diffable?(matcher_2) end # @api private # @return [RSpec::Matchers::MultiMatcherDiff] def expected return nil unless evaluator ::RSpec::Matchers::MultiMatcherDiff.for_many_matchers(diffable_matcher_list) end protected def diffable_matcher_list list = [] list.concat(diffable_matcher_list_for(matcher_1)) unless matcher_1_matches? list.concat(diffable_matcher_list_for(matcher_2)) unless matcher_2_matches? list end private def initialize_copy(other) @matcher_1 = @matcher_1.clone @matcher_2 = @matcher_2.clone super end def match(_expected, actual) evaluator_klass = if supports_block_expectations? && Proc === actual NestedEvaluator else SequentialEvaluator end @evaluator = evaluator_klass.new(actual, matcher_1, matcher_2) end def indent_multiline_message(message) message.lines.map do |line| line =~ /\S/ ? ' ' + line : line end.join end def compound_failure_message "#{indent_multiline_message(matcher_1.failure_message.sub(/\n+\z/, ''))}" \ "\n\n...#{conjunction}:" \ "\n\n#{indent_multiline_message(matcher_2.failure_message.sub(/\A\n+/, ''))}" end def matcher_1_matches? evaluator.matcher_matches?(matcher_1) end def matcher_2_matches? evaluator.matcher_matches?(matcher_2) end def matcher_supports_block_expectations?(matcher) matcher.supports_block_expectations? rescue NoMethodError false end def matcher_supports_value_expectations?(matcher) matcher.supports_value_expectations? rescue NoMethodError true end def matcher_is_diffable?(matcher) matcher.diffable? rescue NoMethodError false end def diffable_matcher_list_for(matcher) return [] unless matcher_is_diffable?(matcher) return matcher.diffable_matcher_list if Compound === matcher [matcher] end # For value expectations, we can evaluate the matchers sequentially. class SequentialEvaluator def initialize(actual, *) @actual = actual end def matcher_matches?(matcher) matcher.matches?(@actual) end end # Normally, we evaluate the matching sequentially. For an expression like # `expect(x).to foo.and bar`, this becomes: # # expect(x).to foo # expect(x).to bar # # For block expectations, we need to nest them instead, so that # `expect { x }.to foo.and bar` becomes: # # expect { # expect { x }.to foo # }.to bar # # This is necessary so that the `expect` block is only executed once. class NestedEvaluator def initialize(actual, matcher_1, matcher_2) @actual = actual @matcher_1 = matcher_1 @matcher_2 = matcher_2 @match_results = {} inner, outer = order_block_matchers @match_results[outer] = outer.matches?(Proc.new do |*args| @match_results[inner] = inner.matches?(inner_matcher_block(args)) end) end def matcher_matches?(matcher) @match_results.fetch(matcher) do raise ArgumentError, "Your #{matcher.description} has no match " \ "results, this can occur when an unexpected call stack or " \ "local jump occurs. Perhaps one of your matchers needs to " \ "declare `expects_call_stack_jump?` as `true`?" end end private # Some block matchers (such as `yield_xyz`) pass args to the `expect` block. # When such a matcher is used as the outer matcher, we need to forward the # the args on to the `expect` block. def inner_matcher_block(outer_args) return @actual if outer_args.empty? Proc.new do |*inner_args| unless inner_args.empty? raise ArgumentError, "(#{@matcher_1.description}) and " \ "(#{@matcher_2.description}) cannot be combined in a compound expectation " \ "since both matchers pass arguments to the block." end @actual.call(*outer_args) end end # For a matcher like `raise_error` or `throw_symbol`, where the block will jump # up the call stack, we need to order things so that it is the inner matcher. # For example, we need it to be this: # # expect { # expect { # x += 1 # raise "boom" # }.to raise_error("boom") # }.to change { x }.by(1) # # ...rather than: # # expect { # expect { # x += 1 # raise "boom" # }.to change { x }.by(1) # }.to raise_error("boom") # # In the latter case, the after-block logic in the `change` matcher would never # get executed because the `raise "boom"` line would jump to the `rescue` in the # `raise_error` logic, so only the former case will work properly. # # This method figures out which matcher should be the inner matcher and which # should be the outer matcher. def order_block_matchers return @matcher_1, @matcher_2 unless self.class.matcher_expects_call_stack_jump?(@matcher_2) return @matcher_2, @matcher_1 unless self.class.matcher_expects_call_stack_jump?(@matcher_1) raise ArgumentError, "(#{@matcher_1.description}) and " \ "(#{@matcher_2.description}) cannot be combined in a compound expectation " \ "because they both expect a call stack jump." end def self.matcher_expects_call_stack_jump?(matcher) matcher.expects_call_stack_jump? rescue NoMethodError false end end # @api public # Matcher used to represent a compound `and` expectation. class And < self # @api private # @return [String] def failure_message if matcher_1_matches? matcher_2.failure_message elsif matcher_2_matches? matcher_1.failure_message else compound_failure_message end end private def match(*) super matcher_1_matches? && matcher_2_matches? end def conjunction "and" end end # @api public # Matcher used to represent a compound `or` expectation. class Or < self # @api private # @return [String] def failure_message compound_failure_message end private def match(*) super matcher_1_matches? || matcher_2_matches? end def conjunction "or" end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/count_expectation.rb0000664000000000000000000001176714557700001031773 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Abstract class to implement `once`, `at_least` and other # count constraints. module CountExpectation # @api public # Specifies that the method is expected to match once. def once exactly(1) end # @api public # Specifies that the method is expected to match twice. def twice exactly(2) end # @api public # Specifies that the method is expected to match thrice. def thrice exactly(3) end # @api public # Specifies that the method is expected to match the given number of times. def exactly(number) set_expected_count(:==, number) self end # @api public # Specifies the maximum number of times the method is expected to match def at_most(number) set_expected_count(:<=, number) self end # @api public # Specifies the minimum number of times the method is expected to match def at_least(number) set_expected_count(:>=, number) self end # @api public # No-op. Provides syntactic sugar. def times self end protected # @api private attr_reader :count_expectation_type, :expected_count private if RUBY_VERSION.to_f > 1.8 def cover?(count, number) count.cover?(number) end else def cover?(count, number) number >= count.first && number <= count.last end end def expected_count_matches?(actual_count) @actual_count = actual_count return @actual_count > 0 unless count_expectation_type return cover?(expected_count, actual_count) if count_expectation_type == :<=> @actual_count.__send__(count_expectation_type, expected_count) end def has_expected_count? !!count_expectation_type end def set_expected_count(relativity, n) raise_unsupported_count_expectation if unsupported_count_expectation?(relativity) count = count_constraint_to_number(n) if count_expectation_type == :<= && relativity == :>= raise_impossible_count_expectation(count) if count > expected_count @count_expectation_type = :<=> @expected_count = count..expected_count elsif count_expectation_type == :>= && relativity == :<= raise_impossible_count_expectation(count) if count < expected_count @count_expectation_type = :<=> @expected_count = expected_count..count else @count_expectation_type = relativity @expected_count = count end end def raise_impossible_count_expectation(count) text = case count_expectation_type when :<= then "at_least(#{count}).at_most(#{expected_count})" when :>= then "at_least(#{expected_count}).at_most(#{count})" end raise ArgumentError, "The constraint #{text} is not possible" end def raise_unsupported_count_expectation text = case count_expectation_type when :<= then "at_least" when :>= then "at_most" when :<=> then "at_least/at_most combination" else "count" end raise ArgumentError, "Multiple #{text} constraints are not supported" end def count_constraint_to_number(n) case n when Numeric then n when :once then 1 when :twice then 2 when :thrice then 3 else raise ArgumentError, "Expected a number, :once, :twice or :thrice," \ " but got #{n}" end end def unsupported_count_expectation?(relativity) return true if count_expectation_type == :== return true if count_expectation_type == :<=> (count_expectation_type == :<= && relativity == :<=) || (count_expectation_type == :>= && relativity == :>=) end def count_expectation_description "#{human_readable_expectation_type}#{human_readable_count(expected_count)}" end def count_failure_reason(action) "#{count_expectation_description}" \ " but #{action}#{human_readable_count(@actual_count)}" end def human_readable_expectation_type case count_expectation_type when :<= then ' at most' when :>= then ' at least' when :<=> then ' between' else '' end end def human_readable_count(count) case count when Range then " #{count.first} and #{count.last} times" when nil then '' when 1 then ' once' when 2 then ' twice' else " #{count} times" end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/has.rb0000664000000000000000000001124614557700001027003 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for dynamic predicate matchers. # Not intended to be inherited directly. class DynamicPredicate < BaseMatcher include BeHelpers def initialize(method_name, *args, &block) @method_name, @args, @block = method_name, args, block end ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true) # @private def matches?(actual, &block) @actual = actual @block ||= block predicate_accessible? && predicate_matches? end # @private def does_not_match?(actual, &block) @actual = actual @block ||= block predicate_accessible? && predicate_matches?(false) end # @api private # @return [String] def failure_message failure_message_expecting(true) end # @api private # @return [String] def failure_message_when_negated failure_message_expecting(false) end # @api private # @return [String] def description "#{method_description}#{args_to_sentence}" end private def predicate_accessible? @actual.respond_to? predicate end # support 1.8.7, evaluate once at load time for performance if String === methods.first # :nocov: def private_predicate? @actual.private_methods.include? predicate.to_s end # :nocov: else def private_predicate? @actual.private_methods.include? predicate end end def predicate_result @predicate_result = actual.__send__(predicate_method_name, *@args, &@block) end def predicate_method_name predicate end def predicate_matches?(value=true) if RSpec::Expectations.configuration.strict_predicate_matchers? value == predicate_result else value == !!predicate_result end end def root # On 1.9, there appears to be a bug where String#match can return `false` # rather than the match data object. Changing to Regex#match appears to # work around this bug. For an example of this bug, see: # https://travis-ci.org/rspec/rspec-expectations/jobs/27549635 self.class::REGEX.match(@method_name.to_s).captures.first end def method_description EnglishPhrasing.split_words(@method_name) end def failure_message_expecting(value) validity_message || "expected `#{actual_formatted}.#{predicate}#{args_to_s}` to #{expectation_of value}, got #{description_of @predicate_result}" end def expectation_of(value) if RSpec::Expectations.configuration.strict_predicate_matchers? "return #{value}" elsif value "be truthy" else "be falsey" end end def validity_message return nil if predicate_accessible? "expected #{actual_formatted} to respond to `#{predicate}`#{failure_to_respond_explanation}" end def failure_to_respond_explanation if private_predicate? " but `#{predicate}` is a private method" end end end # @api private # Provides the implementation for `has_`. # Not intended to be instantiated directly. class Has < DynamicPredicate # :nodoc: REGEX = Matchers::HAS_REGEX private def predicate @predicate ||= :"has_#{root}?" end end # @api private # Provides the implementation of `be_`. # Not intended to be instantiated directly. class BePredicate < DynamicPredicate # :nodoc: REGEX = Matchers::BE_PREDICATE_REGEX private def predicate @predicate ||= :"#{root}?" end def predicate_method_name actual.respond_to?(predicate) ? predicate : present_tense_predicate end def failure_to_respond_explanation super || if predicate == :true? " or perhaps you meant `be true` or `be_truthy`" elsif predicate == :false? " or perhaps you meant `be false` or `be_falsey`" end end def predicate_accessible? super || actual.respond_to?(present_tense_predicate) end def present_tense_predicate :"#{root}s?" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/be_instance_of.rb0000664000000000000000000000137314557700001031166 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `be_an_instance_of`. # Not intended to be instantiated directly. class BeAnInstanceOf < BaseMatcher # @api private # @return [String] def description "be an instance of #{expected}" end private def match(expected, actual) actual.instance_of?(expected) rescue NoMethodError raise ::ArgumentError, "The #{matcher_name} matcher requires that " \ "the actual object responds to #instance_of? method " \ "but a `NoMethodError` was encountered instead." end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/equal.rb0000664000000000000000000000357114557700001027341 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `equal`. # Not intended to be instantiated directly. class Equal < BaseMatcher # @api private # @return [String] def failure_message if expected_is_a_literal_singleton? simple_failure_message else detailed_failure_message end end # @api private # @return [String] def failure_message_when_negated <<-MESSAGE expected not #{inspect_object(actual)} got #{inspect_object(expected)} Compared using equal?, which compares object identity. MESSAGE end # @api private # @return [Boolean] def diffable? !expected_is_a_literal_singleton? end private def match(expected, actual) actual.equal? expected end LITERAL_SINGLETONS = [true, false, nil] def expected_is_a_literal_singleton? LITERAL_SINGLETONS.include?(expected) end def actual_inspected if LITERAL_SINGLETONS.include?(actual) actual_formatted else inspect_object(actual) end end def simple_failure_message "\nexpected #{expected_formatted}\n got #{actual_inspected}\n" end def detailed_failure_message <<-MESSAGE expected #{inspect_object(expected)} got #{inspect_object(actual)} Compared using equal?, which compares object identity, but expected and actual are not the same object. Use `expect(actual).to eq(expected)` if you don't care about object identity in this example. MESSAGE end def inspect_object(o) "#<#{o.class}:#{o.object_id}> => #{RSpec::Support::ObjectFormatter.format(o)}" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/change.rb0000664000000000000000000003511514557700001027456 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `change`. # Not intended to be instantiated directly. class Change < BaseMatcher # @api public # Specifies the delta of the expected change. def by(expected_delta) ChangeRelatively.new(change_details, expected_delta, :by) do |actual_delta| values_match?(expected_delta, actual_delta) end end # @api public # Specifies a minimum delta of the expected change. def by_at_least(minimum) ChangeRelatively.new(change_details, minimum, :by_at_least) do |actual_delta| actual_delta >= minimum end end # @api public # Specifies a maximum delta of the expected change. def by_at_most(maximum) ChangeRelatively.new(change_details, maximum, :by_at_most) do |actual_delta| actual_delta <= maximum end end # @api public # Specifies the new value you expect. def to(value) ChangeToValue.new(change_details, value) end # @api public # Specifies the original value. def from(value) ChangeFromValue.new(change_details, value) end # @private def matches?(event_proc) raise_block_syntax_error if block_given? perform_change(event_proc) && change_details.changed? end def does_not_match?(event_proc) raise_block_syntax_error if block_given? perform_change(event_proc) && !change_details.changed? end # @api private # @return [String] def failure_message "expected #{change_details.value_representation} to have changed, " \ "but #{positive_failure_reason}" end # @api private # @return [String] def failure_message_when_negated "expected #{change_details.value_representation} not to have changed, " \ "but #{negative_failure_reason}" end # @api private # @return [String] def description "change #{change_details.value_representation}" end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def initialize(receiver=nil, message=nil, &block) @receiver = receiver @message = message @block = block end def change_details @change_details ||= ChangeDetails.new(matcher_name, @receiver, @message, &@block) end def perform_change(event_proc) @event_proc = event_proc change_details.perform_change(event_proc) do |actual_before| # pre-compute values derived from the `before` value before the # mutation is applied, in case the specified mutation is mutation # of a single object (rather than a changing what object a method # returns). We need to cache these values before the `before` value # they are based on potentially gets mutated. @actual_before_description = description_of(actual_before) end end def raise_block_syntax_error raise SyntaxError, "Block not received by the `change` matcher. " \ "Perhaps you want to use `{ ... }` instead of do/end?" end def positive_failure_reason return "was not given a block" unless Proc === @event_proc "is still #{@actual_before_description}" end def negative_failure_reason return "was not given a block" unless Proc === @event_proc "did change from #{@actual_before_description} " \ "to #{description_of change_details.actual_after}" end end # Used to specify a relative change. # @api private class ChangeRelatively < BaseMatcher def initialize(change_details, expected_delta, relativity, &comparer) @change_details = change_details @expected_delta = expected_delta @relativity = relativity @comparer = comparer end # @private def failure_message "expected #{@change_details.value_representation} to have changed " \ "#{@relativity.to_s.tr('_', ' ')} " \ "#{description_of @expected_delta}, but #{failure_reason}" end # @private def matches?(event_proc) @event_proc = event_proc @change_details.perform_change(event_proc) && @comparer.call(@change_details.actual_delta) end # @private def does_not_match?(_event_proc) raise NotImplementedError, "`expect { }.not_to change " \ "{ }.#{@relativity}()` is not supported" end # @private def description "change #{@change_details.value_representation} " \ "#{@relativity.to_s.tr('_', ' ')} #{description_of @expected_delta}" end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def failure_reason return "was not given a block" unless Proc === @event_proc "was changed by #{description_of @change_details.actual_delta}" end end # @api private # Base class for specifying a change from and/or to specific values. class SpecificValuesChange < BaseMatcher # @private MATCH_ANYTHING = ::Object.ancestors.last def initialize(change_details, from, to) @change_details = change_details @expected_before = from @expected_after = to end # @private def matches?(event_proc) perform_change(event_proc) && @change_details.changed? && @matches_before && matches_after? end # @private def description "change #{@change_details.value_representation} #{change_description}" end # @private def failure_message return not_given_a_block_failure unless Proc === @event_proc return before_value_failure unless @matches_before return did_not_change_failure unless @change_details.changed? after_value_failure end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def perform_change(event_proc) @event_proc = event_proc @change_details.perform_change(event_proc) do |actual_before| # pre-compute values derived from the `before` value before the # mutation is applied, in case the specified mutation is mutation # of a single object (rather than a changing what object a method # returns). We need to cache these values before the `before` value # they are based on potentially gets mutated. @matches_before = values_match?(@expected_before, actual_before) @actual_before_description = description_of(actual_before) end end def matches_after? values_match?(@expected_after, @change_details.actual_after) end def before_value_failure "expected #{@change_details.value_representation} " \ "to have initially been #{description_of @expected_before}, " \ "but was #{@actual_before_description}" end def after_value_failure "expected #{@change_details.value_representation} " \ "to have changed to #{description_of @expected_after}, " \ "but is now #{description_of @change_details.actual_after}" end def did_not_change_failure "expected #{@change_details.value_representation} " \ "to have changed #{change_description}, but did not change" end def did_change_failure "expected #{@change_details.value_representation} not to have changed, but " \ "did change from #{@actual_before_description} " \ "to #{description_of @change_details.actual_after}" end def not_given_a_block_failure "expected #{@change_details.value_representation} to have changed " \ "#{change_description}, but was not given a block" end end # @api private # Used to specify a change from a specific value # (and, optionally, to a specific value). class ChangeFromValue < SpecificValuesChange def initialize(change_details, expected_before) @description_suffix = nil super(change_details, expected_before, MATCH_ANYTHING) end # @api public # Specifies the new value you expect. def to(value) @expected_after = value @description_suffix = " to #{description_of value}" self end # @private def does_not_match?(event_proc) if @description_suffix raise NotImplementedError, "`expect { }.not_to change { }.to()` " \ "is not supported" end perform_change(event_proc) && !@change_details.changed? && @matches_before end # @private def failure_message_when_negated return not_given_a_block_failure unless Proc === @event_proc return before_value_failure unless @matches_before did_change_failure end private def change_description "from #{description_of @expected_before}#{@description_suffix}" end end # @api private # Used to specify a change to a specific value # (and, optionally, from a specific value). class ChangeToValue < SpecificValuesChange def initialize(change_details, expected_after) @description_suffix = nil super(change_details, MATCH_ANYTHING, expected_after) end # @api public # Specifies the original value. def from(value) @expected_before = value @description_suffix = " from #{description_of value}" self end # @private def does_not_match?(_event_proc) raise NotImplementedError, "`expect { }.not_to change { }.to()` " \ "is not supported" end private def change_description "to #{description_of @expected_after}#{@description_suffix}" end end # @private # Encapsulates the details of the before/after values. # # Note that this class exposes the `actual_after` value, to allow the # matchers above to derive failure messages, etc from the value on demand # as needed, but it intentionally does _not_ expose the `actual_before` # value. Some usages of the `change` matcher mutate a specific object # returned by the value proc, which means that failure message snippets, # etc, which are derived from the `before` value may not be accurate if # they are lazily computed as needed. We must pre-compute them before # applying the change in the `expect` block. To ensure that all `change` # matchers do that properly, we do not expose the `actual_before` value. # Instead, matchers must pass a block to `perform_change`, which yields # the `actual_before` value before applying the change. class ChangeDetails attr_reader :actual_after UNDEFINED = Module.new.freeze def initialize(matcher_name, receiver=nil, message=nil, &block) if receiver && !message raise( ArgumentError, "`change` requires either an object and message " \ "(`change(obj, :msg)`) or a block (`change { }`). " \ "You passed an object but no message." ) end @matcher_name = matcher_name @receiver = receiver @message = message @value_proc = block # TODO: temporary measure to mute warning of access to an initialized # instance variable when a deprecated implicit block expectation # syntax is used. This may be removed once `fail` is used, and the # matcher never issues this warning. @actual_after = UNDEFINED end def value_representation @value_representation ||= if @message "`#{message_notation(@receiver, @message)}`" elsif (value_block_snippet = extract_value_block_snippet) "`#{value_block_snippet}`" else 'result' end end def perform_change(event_proc) @actual_before = evaluate_value_proc @before_hash = @actual_before.hash yield @actual_before if block_given? return false unless Proc === event_proc event_proc.call @actual_after = evaluate_value_proc @actual_hash = @actual_after.hash true end def changed? # Consider it changed if either: # # - The before/after values are unequal # - The before/after values have different hash values # # The latter case specifically handles the case when the value proc # returns the exact same object, but it has been mutated. # # Note that it is not sufficient to only check the hashes; it is # possible for two values to be unequal (and of different classes) # but to return the same hash value. Also, some objects may change # their hash after being compared with `==`/`!=`. @actual_before != @actual_after || @before_hash != @actual_hash end def actual_delta @actual_after - @actual_before end private def evaluate_value_proc @value_proc ? @value_proc.call : @receiver.__send__(@message) end def message_notation(receiver, message) case receiver when Module "#{receiver}.#{message}" else "#{Support.class_of(receiver)}##{message}" end end if RSpec::Support::RubyFeatures.ripper_supported? def extract_value_block_snippet return nil unless @value_proc Expectations::BlockSnippetExtractor.try_extracting_single_line_body_of(@value_proc, @matcher_name) end else def extract_value_block_snippet nil end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/raise_error.rb0000664000000000000000000002320614557700001030543 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `raise_error`. # Not intended to be instantiated directly. # rubocop:disable Metrics/ClassLength # rubocop:disable Lint/RescueException class RaiseError include Composable # Used as a sentinel value to be able to tell when the user did not pass an # argument. We can't use `nil` for that because we need to warn when `nil` is # passed in a different way. It's an Object, not a Module, since Module's `===` # does not evaluate to true when compared to itself. UndefinedValue = Object.new.freeze def initialize(expected_error_or_message, expected_message, &block) @block = block @actual_error = nil @warn_about_bare_error = UndefinedValue === expected_error_or_message @warn_about_nil_error = expected_error_or_message.nil? case expected_error_or_message when nil, UndefinedValue @expected_error = Exception @expected_message = expected_message when String @expected_error = Exception @expected_message = expected_error_or_message else @expected_error = expected_error_or_message @expected_message = expected_message end end # @api public # Specifies the expected error message. def with_message(expected_message) raise_message_already_set if @expected_message @warn_about_bare_error = false @expected_message = expected_message self end # rubocop:disable Metrics/MethodLength # @private def matches?(given_proc, negative_expectation=false, &block) @given_proc = given_proc @block ||= block @raised_expected_error = false @with_expected_message = false @eval_block = false @eval_block_passed = false return false unless Proc === given_proc begin given_proc.call rescue Exception => @actual_error if values_match?(@expected_error, @actual_error) || values_match?(@expected_error, actual_error_message) @raised_expected_error = true @with_expected_message = verify_message end end unless negative_expectation warn_about_bare_error! if warn_about_bare_error? warn_about_nil_error! if warn_about_nil_error? eval_block if ready_to_eval_block? end expectation_matched? end # rubocop:enable Metrics/MethodLength # @private def does_not_match?(given_proc) warn_for_negative_false_positives! !matches?(given_proc, :negative_expectation) && Proc === given_proc end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end # @private def expects_call_stack_jump? true end # @api private # @return [String] def failure_message @eval_block ? actual_error_message : "expected #{expected_error}#{given_error}" end # @api private # @return [String] def failure_message_when_negated "expected no #{expected_error}#{given_error}" end # @api private # @return [String] def description "raise #{expected_error}" end private def actual_error_message return nil unless @actual_error @actual_error.respond_to?(:original_message) ? @actual_error.original_message : @actual_error.message end def expectation_matched? error_and_message_match? && block_matches? end def error_and_message_match? @raised_expected_error && @with_expected_message end def block_matches? @eval_block ? @eval_block_passed : true end def ready_to_eval_block? @raised_expected_error && @with_expected_message && @block end def eval_block @eval_block = true begin @block[@actual_error] @eval_block_passed = true rescue Exception => err @actual_error = err end end def verify_message return true if @expected_message.nil? values_match?(@expected_message, actual_error_message.to_s) end def warn_for_negative_false_positives! expression = if expecting_specific_exception? && @expected_message "`expect { }.not_to raise_error(SpecificErrorClass, message)`" elsif expecting_specific_exception? "`expect { }.not_to raise_error(SpecificErrorClass)`" elsif @expected_message "`expect { }.not_to raise_error(message)`" elsif @warn_about_nil_error "`expect { }.not_to raise_error(nil)`" end return unless expression warn_about_negative_false_positive! expression end def handle_warning(message) RSpec::Expectations.configuration.false_positives_handler.call(message) end def warn_about_bare_error? @warn_about_bare_error && @block.nil? end def warn_about_nil_error? @warn_about_nil_error end def warn_about_bare_error! handle_warning("Using the `raise_error` matcher without providing a specific " \ "error or message risks false positives, since `raise_error` " \ "will match when Ruby raises a `NoMethodError`, `NameError` or " \ "`ArgumentError`, potentially allowing the expectation to pass " \ "without even executing the method you are intending to call. " \ "#{warning}"\ "Instead consider providing a specific error class or message. " \ "This message can be suppressed by setting: " \ "`RSpec::Expectations.configuration.on_potential_false" \ "_positives = :nothing`") end def warn_about_nil_error! handle_warning("Using the `raise_error` matcher with a `nil` error is probably " \ "unintentional, it risks false positives, since `raise_error` " \ "will match when Ruby raises a `NoMethodError`, `NameError` or " \ "`ArgumentError`, potentially allowing the expectation to pass " \ "without even executing the method you are intending to call. " \ "#{warning}"\ "Instead consider providing a specific error class or message. " \ "This message can be suppressed by setting: " \ "`RSpec::Expectations.configuration.on_potential_false" \ "_positives = :nothing`") end def warn_about_negative_false_positive!(expression) handle_warning("Using #{expression} risks false positives, since literally " \ "any other error would cause the expectation to pass, " \ "including those raised by Ruby (e.g. `NoMethodError`, `NameError` " \ "and `ArgumentError`), meaning the code you are intending to test " \ "may not even get reached. Instead consider using " \ "`expect { }.not_to raise_error` or `expect { }.to raise_error" \ "(DifferentSpecificErrorClass)`. This message can be suppressed by " \ "setting: `RSpec::Expectations.configuration.on_potential_false" \ "_positives = :nothing`") end def expected_error case @expected_message when nil if RSpec::Support.is_a_matcher?(@expected_error) "Exception with #{description_of(@expected_error)}" else description_of(@expected_error) end when Regexp "#{@expected_error} with message matching #{description_of(@expected_message)}" else "#{@expected_error} with #{description_of(@expected_message)}" end end def format_backtrace(backtrace) formatter = Matchers.configuration.backtrace_formatter formatter.format_backtrace(backtrace) end def given_error return " but was not given a block" unless Proc === @given_proc return " but nothing was raised" unless @actual_error backtrace = format_backtrace(@actual_error.backtrace) [ ", got #{description_of(@actual_error)} with backtrace:", *backtrace ].join("\n # ") end def expecting_specific_exception? @expected_error != Exception end def raise_message_already_set raise "`expect { }.to raise_error(message).with_message(message)` is not valid. " \ 'The matcher only allows the expected message to be specified once' end def warning warning = "Actual error raised was #{description_of(@actual_error)}. " warning if @actual_error end end # rubocop:enable Lint/RescueException # rubocop:enable Metrics/ClassLength end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/cover.rb0000664000000000000000000000104214557700001027337 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `cover`. # Not intended to be instantiated directly. class Cover < BaseMatcher def initialize(*expected) @expected = expected end def matches?(range) @actual = range @expected.all? { |e| range.cover?(e) } end def does_not_match?(range) @actual = range expected.none? { |e| range.cover?(e) } end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/have_attributes.rb0000664000000000000000000000616514557700001031425 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `have_attributes`. # Not intended to be instantiated directly. class HaveAttributes < BaseMatcher # @private attr_reader :respond_to_failed def initialize(expected) @expected = expected @values = {} @respond_to_failed = false @negated = false end # @private def actual @values end # @api private # @return [Boolean] def matches?(actual) @actual = actual @negated = false return false unless respond_to_attributes? perform_match(:all?) end # @api private # @return [Boolean] def does_not_match?(actual) @actual = actual @negated = true return false unless respond_to_attributes? perform_match(:none?) end # @api private # @return [String] def description described_items = surface_descriptions_in(expected) improve_hash_formatting "have attributes #{RSpec::Support::ObjectFormatter.format(described_items)}" end # @api private # @return [Boolean] def diffable? !@respond_to_failed && !@negated end # @api private # @return [String] def failure_message respond_to_failure_message_or do "expected #{actual_formatted} to #{description} but had attributes #{ formatted_values }" end end # @api private # @return [String] def failure_message_when_negated respond_to_failure_message_or { "expected #{actual_formatted} not to #{description}" } end private def cache_all_values @values = {} expected.each do |attribute_key, _attribute_value| actual_value = @actual.__send__(attribute_key) @values[attribute_key] = actual_value end end def perform_match(predicate) cache_all_values expected.__send__(predicate) do |attribute_key, attribute_value| actual_has_attribute?(attribute_key, attribute_value) end end def actual_has_attribute?(attribute_key, attribute_value) values_match?(attribute_value, @values.fetch(attribute_key)) end def respond_to_attributes? matches = respond_to_matcher.matches?(@actual) @respond_to_failed = !matches matches end def respond_to_matcher @respond_to_matcher ||= RespondTo.new(*expected.keys).with(0).arguments.tap { |m| m.ignoring_method_signature_failure! } end def respond_to_failure_message_or if respond_to_failed respond_to_matcher.failure_message else improve_hash_formatting(yield) end end def formatted_values values = RSpec::Support::ObjectFormatter.format(@values) improve_hash_formatting(values) end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/eq.rb0000664000000000000000000000223214557700001026630 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `eq`. # Not intended to be instantiated directly. class Eq < BaseMatcher # @api private # @return [String] def failure_message if string_encoding_differs? "\nexpected: #{format_encoding(expected)} #{expected_formatted}\n got: #{format_encoding(actual)} #{actual_formatted}\n\n(compared using ==)\n" else "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n" end end # @api private # @return [String] def failure_message_when_negated "\nexpected: value != #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n" end # @api private # @return [String] def description "eq #{expected_formatted}" end # @api private # @return [Boolean] def diffable? true end private def match(expected, actual) actual == expected end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/satisfy.rb0000664000000000000000000000275414557700001027716 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `satisfy`. # Not intended to be instantiated directly. class Satisfy < BaseMatcher def initialize(description=nil, &block) @description = description @block = block end # @private def matches?(actual, &block) @block = block if block @actual = actual @block.call(actual) end # @private def description @description ||= "satisfy #{block_representation}" end # @api private # @return [String] def failure_message "expected #{actual_formatted} to #{description}" end # @api private # @return [String] def failure_message_when_negated "expected #{actual_formatted} not to #{description}" end private if RSpec::Support::RubyFeatures.ripper_supported? def block_representation if (block_snippet = extract_block_snippet) "expression `#{block_snippet}`" else 'block' end end def extract_block_snippet return nil unless @block Expectations::BlockSnippetExtractor.try_extracting_single_line_body_of(@block, matcher_name) end else def block_representation 'block' end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/respond_to.rb0000664000000000000000000001541614557700001030407 0ustar rootrootRSpec::Support.require_rspec_support "method_signature_verifier" module RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `respond_to`. # Not intended to be instantiated directly. class RespondTo < BaseMatcher def initialize(*names) @names = names @expected_arity = nil @expected_keywords = [] @ignoring_method_signature_failure = false @unlimited_arguments = nil @arbitrary_keywords = nil end # @api public # Specifies the number of expected arguments. # # @example # expect(obj).to respond_to(:message).with(3).arguments def with(n) @expected_arity = n self end # @api public # Specifies keyword arguments, if any. # # @example # expect(obj).to respond_to(:message).with_keywords(:color, :shape) # @example with an expected number of arguments # expect(obj).to respond_to(:message).with(3).arguments.and_keywords(:color, :shape) def with_keywords(*keywords) @expected_keywords = keywords self end alias :and_keywords :with_keywords # @api public # Specifies that the method accepts any keyword, i.e. the method has # a splatted keyword parameter of the form **kw_args. # # @example # expect(obj).to respond_to(:message).with_any_keywords def with_any_keywords @arbitrary_keywords = true self end alias :and_any_keywords :with_any_keywords # @api public # Specifies that the number of arguments has no upper limit, i.e. the # method has a splatted parameter of the form *args. # # @example # expect(obj).to respond_to(:message).with_unlimited_arguments def with_unlimited_arguments @unlimited_arguments = true self end alias :and_unlimited_arguments :with_unlimited_arguments # @api public # No-op. Intended to be used as syntactic sugar when using `with`. # # @example # expect(obj).to respond_to(:message).with(3).arguments def argument self end alias :arguments :argument # @private def matches?(actual) find_failing_method_names(actual, :reject).empty? end # @private def does_not_match?(actual) find_failing_method_names(actual, :select).empty? end # @api private # @return [String] def failure_message "expected #{actual_formatted} to respond to #{@failing_method_names.map { |name| description_of(name) }.join(', ')}#{with_arity}" end # @api private # @return [String] def failure_message_when_negated failure_message.sub(/to respond to/, 'not to respond to') end # @api private # @return [String] def description "respond to #{pp_names}#{with_arity}" end # @api private # Used by other matchers to suppress a check def ignoring_method_signature_failure! @ignoring_method_signature_failure = true end private def find_failing_method_names(actual, filter_method) @actual = actual @failing_method_names = @names.__send__(filter_method) do |name| @actual.respond_to?(name) && matches_arity?(actual, name) end end def matches_arity?(actual, name) ArityCheck.new(@expected_arity, @expected_keywords, @arbitrary_keywords, @unlimited_arguments).matches?(actual, name) rescue NameError return true if @ignoring_method_signature_failure raise ArgumentError, "The #{matcher_name} matcher requires that " \ "the actual object define the method(s) in " \ "order to check arity, but the method " \ "`#{name}` is not defined. Remove the arity " \ "check or define the method to continue." end def with_arity str = ''.dup str << " with #{with_arity_string}" if @expected_arity str << " #{str.length == 0 ? 'with' : 'and'} #{with_keywords_string}" if @expected_keywords && @expected_keywords.count > 0 str << " #{str.length == 0 ? 'with' : 'and'} unlimited arguments" if @unlimited_arguments str << " #{str.length == 0 ? 'with' : 'and'} any keywords" if @arbitrary_keywords str end def with_arity_string "#{@expected_arity} argument#{@expected_arity == 1 ? '' : 's'}" end def with_keywords_string kw_str = case @expected_keywords.count when 1 @expected_keywords.first.inspect when 2 @expected_keywords.map(&:inspect).join(' and ') else "#{@expected_keywords[0...-1].map(&:inspect).join(', ')}, and #{@expected_keywords.last.inspect}" end "keyword#{@expected_keywords.count == 1 ? '' : 's'} #{kw_str}" end def pp_names @names.length == 1 ? "##{@names.first}" : description_of(@names) end # @private class ArityCheck def initialize(expected_arity, expected_keywords, arbitrary_keywords, unlimited_arguments) expectation = Support::MethodSignatureExpectation.new if expected_arity.is_a?(Range) expectation.min_count = expected_arity.min expectation.max_count = expected_arity.max else expectation.min_count = expected_arity end expectation.keywords = expected_keywords expectation.expect_unlimited_arguments = unlimited_arguments expectation.expect_arbitrary_keywords = arbitrary_keywords @expectation = expectation end def matches?(actual, name) return true if @expectation.empty? verifier_for(actual, name).with_expectation(@expectation).valid? end def verifier_for(actual, name) Support::StrictSignatureVerifier.new(method_signature_for(actual, name)) end def method_signature_for(actual, name) method_handle = Support.method_handle_for(actual, name) if name == :new && method_handle.owner === ::Class && ::Class === actual Support::MethodSignature.new(actual.instance_method(:initialize)) else Support::MethodSignature.new(method_handle) end end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/operators.rb0000664000000000000000000001041114557700001030237 0ustar rootrootrequire 'rspec/support' module RSpec module Matchers module BuiltIn # @api private # Provides the implementation for operator matchers. # Not intended to be instantiated directly. # Only available for use with `should`. class OperatorMatcher class << self # @private def registry @registry ||= {} end # @private def register(klass, operator, matcher) registry[klass] ||= {} registry[klass][operator] = matcher end # @private def unregister(klass, operator) registry[klass] && registry[klass].delete(operator) end # @private def get(klass, operator) klass.ancestors.each do |ancestor| matcher = registry[ancestor] && registry[ancestor][operator] return matcher if matcher end nil end end register Enumerable, '=~', BuiltIn::ContainExactly def initialize(actual) @actual = actual end # @private def self.use_custom_matcher_or_delegate(operator) define_method(operator) do |expected| if !has_non_generic_implementation_of?(operator) && (matcher = OperatorMatcher.get(@actual.class, operator)) @actual.__send__(::RSpec::Matchers.last_expectation_handler.should_method, matcher.new(expected)) else eval_match(@actual, operator, expected) end end negative_operator = operator.sub(/^=/, '!') if negative_operator != operator && respond_to?(negative_operator) define_method(negative_operator) do |_expected| opposite_should = ::RSpec::Matchers.last_expectation_handler.opposite_should_method raise "RSpec does not support `#{::RSpec::Matchers.last_expectation_handler.should_method} #{negative_operator} expected`. " \ "Use `#{opposite_should} #{operator} expected` instead." end end end ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator| use_custom_matcher_or_delegate operator end # @private def fail_with_message(message) RSpec::Expectations.fail_with(message, @expected, @actual) end # @api private # @return [String] def description "#{@operator} #{RSpec::Support::ObjectFormatter.format(@expected)}" end private def has_non_generic_implementation_of?(op) Support.method_handle_for(@actual, op).owner != ::Kernel rescue NameError false end def eval_match(actual, operator, expected) ::RSpec::Matchers.last_matcher = self @operator, @expected = operator, expected __delegate_operator(actual, operator, expected) end end # @private # Handles operator matcher for `should`. class PositiveOperatorMatcher < OperatorMatcher def __delegate_operator(actual, operator, expected) if actual.__send__(operator, expected) true else expected_formatted = RSpec::Support::ObjectFormatter.format(expected) actual_formatted = RSpec::Support::ObjectFormatter.format(actual) if ['==', '===', '=~'].include?(operator) fail_with_message("expected: #{expected_formatted}\n got: #{actual_formatted} (using #{operator})") else fail_with_message("expected: #{operator} #{expected_formatted}\n got: #{operator.gsub(/./, ' ')} #{actual_formatted}") end end end end # @private # Handles operator matcher for `should_not`. class NegativeOperatorMatcher < OperatorMatcher def __delegate_operator(actual, operator, expected) return false unless actual.__send__(operator, expected) expected_formatted = RSpec::Support::ObjectFormatter.format(expected) actual_formatted = RSpec::Support::ObjectFormatter.format(actual) fail_with_message("expected not: #{operator} #{expected_formatted}\n got: #{operator.gsub(/./, ' ')} #{actual_formatted}") end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/exist.rb0000664000000000000000000000506414557700001027365 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `exist`. # Not intended to be instantiated directly. class Exist < BaseMatcher def initialize(*expected) @expected = expected end # @api private # @return [Boolean] def matches?(actual) @actual = actual @test = ExistenceTest.new @actual, @expected @test.valid_test? && @test.actual_exists? end # @api private # @return [Boolean] def does_not_match?(actual) @actual = actual @test = ExistenceTest.new @actual, @expected @test.valid_test? && !@test.actual_exists? end # @api private # @return [String] def failure_message "expected #{actual_formatted} to exist#{@test.validity_message}" end # @api private # @return [String] def failure_message_when_negated "expected #{actual_formatted} not to exist#{@test.validity_message}" end # @api private # Simple class for memoizing actual/expected for this matcher # and examining the match class ExistenceTest < Struct.new(:actual, :expected) # @api private # @return [Boolean] def valid_test? uniq_truthy_values.size == 1 end # @api private # @return [Boolean] def actual_exists? existence_values.first end # @api private # @return [String] def validity_message case uniq_truthy_values.size when 0 " but it does not respond to either `exist?` or `exists?`" when 2 " but `exist?` and `exists?` returned different values:\n\n"\ " exist?: #{existence_values.first}\n"\ "exists?: #{existence_values.last}" end end private def uniq_truthy_values @uniq_truthy_values ||= existence_values.map { |v| !!v }.uniq end def existence_values @existence_values ||= predicates.map { |p| actual.__send__(p, *expected) } end def predicates @predicates ||= [:exist?, :exists?].select { |p| actual.respond_to?(p) && !deprecated(p, actual) } end def deprecated(predicate, actual) predicate == :exists? && (File == actual || FileTest == actual || Dir == actual) end end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/match.rb0000664000000000000000000000567114557700001027331 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `match`. # Not intended to be instantiated directly. class Match < BaseMatcher def initialize(expected) super(expected) @expected_captures = nil end # @api private # @return [String] def description if @expected_captures && @expected.match(actual) "match #{surface_descriptions_in(expected).inspect} with captures #{surface_descriptions_in(@expected_captures).inspect}" else "match #{surface_descriptions_in(expected).inspect}" end end # @api private # @return [Boolean] def diffable? true end # Used to specify the captures we match against # @return [self] def with_captures(*captures) @expected_captures = captures self end private def match(expected, actual) return match_captures(expected, actual) if @expected_captures return true if values_match?(expected, actual) return false unless can_safely_call_match?(expected, actual) actual.match(expected) end def can_safely_call_match?(expected, actual) return false unless actual.respond_to?(:match) !(RSpec::Matchers.is_a_matcher?(expected) && (String === actual || Regexp === actual)) end def match_captures(expected, actual) match = actual.match(expected) if match match = ReliableMatchData.new(match) if match.names.empty? values_match?(@expected_captures, match.captures) else expected_matcher = @expected_captures.last values_match?(expected_matcher, Hash[match.names.zip(match.captures)]) || values_match?(expected_matcher, Hash[match.names.map(&:to_sym).zip(match.captures)]) || values_match?(@expected_captures, match.captures) end else false end end end # @api private # Used to wrap match data and make it reliable for 1.8.7 class ReliableMatchData def initialize(match_data) @match_data = match_data end if RUBY_VERSION == "1.8.7" # @api private # Returns match data names for named captures # @return Array def names [] end else # @api private # Returns match data names for named captures # @return Array def names match_data.names end end # @api private # returns an array of captures from the match data # @return Array def captures match_data.captures end protected attr_reader :match_data end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/eql.rb0000664000000000000000000000205014557700001027002 0ustar rootrootmodule RSpec module Matchers module BuiltIn # @api private # Provides the implementation for `eql`. # Not intended to be instantiated directly. class Eql < BaseMatcher # @api private # @return [String] def failure_message if string_encoding_differs? "\nexpected: #{format_encoding(expected)} #{expected_formatted}\n got: #{format_encoding(actual)} #{actual_formatted}\n\n(compared using eql?)\n" else "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n" end end # @api private # @return [String] def failure_message_when_negated "\nexpected: value != #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n" end # @api private # @return [Boolean] def diffable? true end private def match(expected, actual) actual.eql? expected end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/built_in/yield.rb0000664000000000000000000002574314557700001027345 0ustar rootrootrequire 'rspec/matchers/built_in/count_expectation' RSpec::Support.require_rspec_support 'method_signature_verifier' module RSpec module Matchers module BuiltIn # @private # Object that is yielded to `expect` when one of the # yield matchers is used. Provides information about # the yield behavior of the object-under-test. class YieldProbe def self.probe(block, &callback) probe = new(block, &callback) return probe unless probe.has_block? probe.probe end attr_accessor :num_yields, :yielded_args def initialize(block, &callback) @block = block @callback = callback || Proc.new {} @used = false self.num_yields = 0 self.yielded_args = [] end def has_block? Proc === @block end def probe assert_valid_expect_block! @block.call(self) assert_used! self end def to_proc @used = true probe = self callback = @callback Proc.new do |*args| probe.num_yields += 1 probe.yielded_args << args callback.call(*args) nil # to indicate the block does not return a meaningful value end end def single_yield_args yielded_args.first end def yielded_once?(matcher_name) case num_yields when 1 then true when 0 then false else raise "The #{matcher_name} matcher is not designed to be used with a " \ 'method that yields multiple times. Use the yield_successive_args ' \ 'matcher for that case.' end end def assert_used! return if @used raise 'You must pass the argument yielded to your expect block on ' \ 'to the method-under-test as a block. It acts as a probe that ' \ 'allows the matcher to detect whether or not the method-under-test ' \ 'yields, and, if so, how many times, and what the yielded arguments ' \ 'are.' end if RUBY_VERSION.to_f > 1.8 def assert_valid_expect_block! block_signature = RSpec::Support::BlockSignature.new(@block) return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid? raise 'Your expect block must accept an argument to be used with this ' \ 'matcher. Pass the argument as a block on to the method you are testing.' end else # :nocov: # On 1.8.7, `lambda { }.arity` and `lambda { |*a| }.arity` both return -1, # so we can't distinguish between accepting no args and an arg splat. # It's OK to skip, this, though; it just provides a nice error message # when the user forgets to accept an arg in their block. They'll still get # the `assert_used!` error message from above, which is sufficient. def assert_valid_expect_block! # nothing to do end # :nocov: end end # @api private # Provides the implementation for `yield_control`. # Not intended to be instantiated directly. class YieldControl < BaseMatcher include CountExpectation # @private def matches?(block) @probe = YieldProbe.probe(block) return false unless @probe.has_block? expected_count_matches?(@probe.num_yields) end # @private def does_not_match?(block) !matches?(block) && @probe.has_block? end # @api private # @return [String] def failure_message 'expected given block to yield control' + failure_reason end # @api private # @return [String] def failure_message_when_negated 'expected given block not to yield control' + failure_reason end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def failure_reason return ' but was not a block' unless @probe.has_block? return "#{count_expectation_description} but did not yield" if @probe.num_yields == 0 count_failure_reason('yielded') end end # @api private # Provides the implementation for `yield_with_no_args`. # Not intended to be instantiated directly. class YieldWithNoArgs < BaseMatcher # @private def matches?(block) @probe = YieldProbe.probe(block) return false unless @probe.has_block? @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty? end # @private def does_not_match?(block) !matches?(block) && @probe.has_block? end # @private def failure_message "expected given block to yield with no arguments, but #{positive_failure_reason}" end # @private def failure_message_when_negated "expected given block not to yield with no arguments, but #{negative_failure_reason}" end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def positive_failure_reason return 'was not a block' unless @probe.has_block? return 'did not yield' if @probe.num_yields.zero? "yielded with arguments: #{description_of @probe.single_yield_args}" end def negative_failure_reason return 'was not a block' unless @probe.has_block? 'did' end end # @api private # Provides the implementation for `yield_with_args`. # Not intended to be instantiated directly. class YieldWithArgs < BaseMatcher def initialize(*args) @expected = args end # @private def matches?(block) @args_matched_when_yielded = true @probe = YieldProbe.new(block) do @actual = @probe.single_yield_args @actual_formatted = actual_formatted @args_matched_when_yielded &&= args_currently_match? end return false unless @probe.has_block? @probe.probe @probe.yielded_once?(:yield_with_args) && @args_matched_when_yielded end # @private def does_not_match?(block) !matches?(block) && @probe.has_block? end # @private def failure_message "expected given block to yield with arguments, but #{positive_failure_reason}" end # @private def failure_message_when_negated "expected given block not to yield with arguments, but #{negative_failure_reason}" end # @private def description desc = 'yield with args' desc = "#{desc}(#{expected_arg_description})" unless @expected.empty? desc end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def positive_failure_reason return 'was not a block' unless @probe.has_block? return 'did not yield' if @probe.num_yields.zero? @positive_args_failure end def expected_arg_description @expected.map { |e| description_of e }.join(', ') end def negative_failure_reason if !@probe.has_block? 'was not a block' elsif @args_matched_when_yielded && !@expected.empty? 'yielded with expected arguments' \ "\nexpected not: #{surface_descriptions_in(@expected).inspect}" \ "\n got: #{@actual_formatted}" else 'did' end end def args_currently_match? if @expected.empty? # expect {...}.to yield_with_args @positive_args_failure = 'yielded with no arguments' if @actual.empty? return !@actual.empty? end unless (match = all_args_match?) @positive_args_failure = 'yielded with unexpected arguments' \ "\nexpected: #{surface_descriptions_in(@expected).inspect}" \ "\n got: #{@actual_formatted}" end match end def all_args_match? values_match?(@expected, @actual) end end # @api private # Provides the implementation for `yield_successive_args`. # Not intended to be instantiated directly. class YieldSuccessiveArgs < BaseMatcher def initialize(*args) @expected = args end # @private def matches?(block) @actual_formatted = [] @actual = [] args_matched_when_yielded = true yield_count = 0 @probe = YieldProbe.probe(block) do |*arg_array| arg_or_args = arg_array.size == 1 ? arg_array.first : arg_array @actual_formatted << RSpec::Support::ObjectFormatter.format(arg_or_args) @actual << arg_or_args args_matched_when_yielded &&= values_match?(@expected[yield_count], arg_or_args) yield_count += 1 end return false unless @probe.has_block? args_matched_when_yielded && yield_count == @expected.length end def does_not_match?(block) !matches?(block) && @probe.has_block? end # @private def failure_message 'expected given block to yield successively with arguments, ' \ "but #{positive_failure_reason}" end # @private def failure_message_when_negated 'expected given block not to yield successively with arguments, ' \ "but #{negative_failure_reason}" end # @private def description "yield successive args(#{expected_arg_description})" end # @private def supports_block_expectations? true end # @private def supports_value_expectations? false end private def expected_arg_description @expected.map { |e| description_of e }.join(', ') end def positive_failure_reason return 'was not a block' unless @probe.has_block? 'yielded with unexpected arguments' \ "\nexpected: #{surface_descriptions_in(@expected).inspect}" \ "\n got: [#{@actual_formatted.join(", ")}]" end def negative_failure_reason return 'was not a block' unless @probe.has_block? 'yielded with expected arguments' \ "\nexpected not: #{surface_descriptions_in(@expected).inspect}" \ "\n got: [#{@actual_formatted.join(", ")}]" end end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/multi_matcher_diff.rb0000664000000000000000000000504414557700001030247 0ustar rootrootmodule RSpec module Matchers # @api private # Handles list of expected and actual value pairs when there is a need # to render multiple diffs. Also can handle one pair. class MultiMatcherDiff # @private # Default diff label when there is only one matcher in diff # output DEFAULT_DIFF_LABEL = "Diff:".freeze # @private # Maximum readable matcher description length DESCRIPTION_MAX_LENGTH = 65 def initialize(expected_list) @expected_list = expected_list end # @api private # Wraps provided expected value in instance of # MultiMatcherDiff. If provided value is already an # MultiMatcherDiff then it just returns it. # @param [Any] expected value to be wrapped # @param [Any] actual value # @return [RSpec::Matchers::MultiMatcherDiff] def self.from(expected, actual) return expected if self === expected new([[expected, DEFAULT_DIFF_LABEL, actual]]) end # @api private # Wraps provided matcher list in instance of # MultiMatcherDiff. # @param [Array] matchers list of matchers to wrap # @return [RSpec::Matchers::MultiMatcherDiff] def self.for_many_matchers(matchers) new(matchers.map { |m| [m.expected, diff_label_for(m), m.actual] }) end # @api private # Returns message with diff(s) appended for provided differ # factory and actual value if there are any # @param [String] message original failure message # @param [Proc] differ # @return [String] def message_with_diff(message, differ) diff = diffs(differ) message = "#{message}\n#{diff}" unless diff.empty? message end private class << self private def diff_label_for(matcher) "Diff for (#{truncated(RSpec::Support::ObjectFormatter.format(matcher))}):" end def truncated(description) return description if description.length <= DESCRIPTION_MAX_LENGTH description[0...DESCRIPTION_MAX_LENGTH - 3] << "..." end end def diffs(differ) @expected_list.map do |(expected, diff_label, actual)| diff = differ.diff(actual, expected) next if diff.strip.empty? if diff == "\e[0m\n\e[0m" "#{diff_label}\n" \ " " else "#{diff_label}#{diff}" end end.compact.join("\n") end end end end ruby-rspec_3.13.0c0e0m0s1.orig/rspec-expectations/lib/rspec/matchers/dsl.rb0000664000000000000000000005371014557700001025207 0ustar rootrootRSpec::Support.require_rspec_support "with_keywords_when_needed" module RSpec module Matchers # Defines the custom matcher DSL. module DSL # Defines a matcher alias. The returned matcher's `description` will be overridden # to reflect the phrasing of the new name, which will be used in failure messages # when passed as an argument to another matcher in a composed matcher expression. # # @example # RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to # sum_to(3).description # => "sum to 3" # a_list_that_sums_to(3).description # => "a list that sums to 3" # # @example # RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description| # description.sub("be sorted by", "a list sorted by") # end # # be_sorted_by(:age).description # => "be sorted by age" # a_list_sorted_by(:age).description # => "a list sorted by age" # # @param new_name [Symbol] the new name for the matcher # @param old_name [Symbol] the original name for the matcher # @param options [Hash] options for the aliased matcher # @option options [Class] :klass the ruby class to use as the decorator. (Not normally used). # @yield [String] optional block that, when given, is used to define the overridden # logic. The yielded arg is the original description or failure message. If no # block is provided, a default override is used based on the old and new names. # @see RSpec::Matchers def alias_matcher(new_name, old_name, options={}, &description_override) description_override ||= lambda do |old_desc| old_desc.gsub(EnglishPhrasing.split_words(old_name), EnglishPhrasing.split_words(new_name)) end klass = options.fetch(:klass) { AliasedMatcher } define_method(new_name) do |*args, &block| matcher = __send__(old_name, *args, &block) matcher.matcher_name = new_name if matcher.respond_to?(:matcher_name=) klass.new(matcher, description_override) end ruby2_keywords new_name if respond_to?(:ruby2_keywords, true) end # Defines a negated matcher. The returned matcher's `description` and `failure_message` # will be overridden to reflect the phrasing of the new name, and the match logic will # be based on the original matcher but negated. # # @example # RSpec::Matchers.define_negated_matcher :exclude, :include # include(1, 2).description # => "include 1 and 2" # exclude(1, 2).description # => "exclude 1 and 2" # # @param negated_name [Symbol] the name for the negated matcher # @param base_name [Symbol] the name of the original matcher that will be negated # @yield [String] optional block that, when given, is used to define the overridden # logic. The yielded arg is the original description or failure message. If no # block is provided, a default override is used based on the old and new names. # @see RSpec::Matchers def define_negated_matcher(negated_name, base_name, &description_override) alias_matcher(negated_name, base_name, :klass => AliasedNegatedMatcher, &description_override) end # Defines a custom matcher. # # @param name [Symbol] the name for the matcher # @yield [Object] block that is used to define the matcher. # The block is evaluated in the context of your custom matcher class. # When args are passed to your matcher, they will be yielded here, # usually representing the expected value(s). # @see RSpec::Matchers def define(name, &declarations) warn_about_block_args(name, declarations) define_method name do |*expected, &block_arg| RSpec::Matchers::DSL::Matcher.new(name, declarations, self, *expected, &block_arg) end end alias_method :matcher, :define private if Proc.method_defined?(:parameters) def warn_about_block_args(name, declarations) declarations.parameters.each do |type, arg_name| next unless type == :block RSpec.warning("Your `#{name}` custom matcher receives a block argument (`#{arg_name}`), " \ "but due to limitations in ruby, RSpec cannot provide the block. Instead, " \ "use the `block_arg` method to access the block") end end else # :nocov: def warn_about_block_args(*) # There's no way to detect block params on 1.8 since the method reflection APIs don't expose it end # :nocov: end RSpec.configure { |c| c.extend self } if RSpec.respond_to?(:configure) # Contains the methods that are available from within the # `RSpec::Matchers.define` DSL for creating custom matchers. module Macros # Stores the block that is used to determine whether this matcher passes # or fails. The block should return a boolean value. When the matcher is # passed to `expect(...).to` and the block returns `true`, then the expectation # passes. Similarly, when the matcher is passed to `expect(...).not_to` and the # block returns `false`, then the expectation passes. # # @example # # RSpec::Matchers.define :be_even do # match do |actual| # actual.even? # end # end # # expect(4).to be_even # passes # expect(3).not_to be_even # passes # expect(3).to be_even # fails # expect(4).not_to be_even # fails # # By default the match block will swallow expectation errors (e.g. # caused by using an expectation such as `expect(1).to eq 2`), if you # wish to allow these to bubble up, pass in the option # `:notify_expectation_failures => true`. # # @param [Hash] options for defining the behavior of the match block. # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`) def match(options={}, &match_block) define_user_override(:matches?, match_block) do |actual| @actual = actual RSpec::Support.with_failure_notifier(RAISE_NOTIFIER) do begin super(*actual_arg_for(match_block)) rescue RSpec::Expectations::ExpectationNotMetError raise if options[:notify_expectation_failures] false end end end end # @private RAISE_NOTIFIER = Proc.new { |err, _opts| raise err } # Use this to define the block for a negative expectation (`expect(...).not_to`) # when the positive and negative forms require different handling. This # is rarely necessary, but can be helpful, for example, when specifying # asynchronous processes that require different timeouts. # # By default the match block will swallow expectation errors (e.g. # caused by using an expectation such as `expect(1).to eq 2`), if you # wish to allow these to bubble up, pass in the option # `:notify_expectation_failures => true`. # # @param [Hash] options for defining the behavior of the match block. # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`) def match_when_negated(options={}, &match_block) define_user_override(:does_not_match?, match_block) do |actual| begin @actual = actual RSpec::Support.with_failure_notifier(RAISE_NOTIFIER) do super(*actual_arg_for(match_block)) end rescue RSpec::Expectations::ExpectationNotMetError raise if options[:notify_expectation_failures] false end end end # Use this instead of `match` when the block will raise an exception # rather than returning false to indicate a failure. # # @example # # RSpec::Matchers.define :accept_as_valid do |candidate_address| # match_unless_raises ValidationException do |validator| # validator.validate(candidate_address) # end # end # # expect(email_validator).to accept_as_valid("person@company.com") # # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) def match_unless_raises(expected_exception=Exception, &match_block) define_user_override(:matches?, match_block) do |actual| @actual = actual begin super(*actual_arg_for(match_block)) rescue expected_exception => @rescued_exception false else true end end end # Customizes the failure message to use when this matcher is # asked to positively match. Only use this when the message # generated by default doesn't suit your needs. # # @example # # RSpec::Matchers.define :have_strength do |expected| # match { your_match_logic } # # failure_message do |actual| # "Expected strength of #{expected}, but had #{actual.strength}" # end # end # # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) def failure_message(&definition) define_user_override(__method__, definition) end # Customize the failure message to use when this matcher is asked # to negatively match. Only use this when the message generated by # default doesn't suit your needs. # # @example # # RSpec::Matchers.define :have_strength do |expected| # match { your_match_logic } # # failure_message_when_negated do |actual| # "Expected not to have strength of #{expected}, but did" # end # end # # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) def failure_message_when_negated(&definition) define_user_override(__method__, definition) end # Customize the description to use for one-liners. Only use this when # the description generated by default doesn't suit your needs. # # @example # # RSpec::Matchers.define :qualify_for do |expected| # match { your_match_logic } # # description do # "qualify for #{expected}" # end # end # # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`) def description(&definition) define_user_override(__method__, definition) end # Tells the matcher to diff the actual and expected values in the failure # message. def diffable define_method(:diffable?) { true } end # Declares that the matcher can be used in a block expectation. # Users will not be able to use your matcher in a block # expectation without declaring this. # (e.g. `expect { do_something }.to matcher`). def supports_block_expectations define_method(:supports_block_expectations?) { true } end # Convenience for defining methods on this matcher to create a fluent # interface. The trick about fluent interfaces is that each method must # return self in order to chain methods together. `chain` handles that # for you. If the method is invoked and the # `include_chain_clauses_in_custom_matcher_descriptions` config option # hash been enabled, the chained method name and args will be added to the # default description and failure message. # # In the common case where you just want the chained method to store some # value(s) for later use (e.g. in `match`), you can provide one or more # attribute names instead of a block; the chained method will store its # arguments in instance variables with those names, and the values will # be exposed via getters. # # @example # # RSpec::Matchers.define :have_errors_on do |key| # chain :with do |message| # @message = message # end # # match do |actual| # actual.errors[key] == @message # end # end # # expect(minor).to have_errors_on(:age).with("Not old enough to participate") def chain(method_name, *attr_names, &definition) unless block_given? ^ attr_names.any? raise ArgumentError, "You must pass either a block or some attribute names (but not both) to `chain`." end definition = assign_attributes(attr_names) if attr_names.any? define_user_override(method_name, definition) do |*args, &block| super(*args, &block) @chained_method_clauses.push([method_name, args]) self end end def assign_attributes(attr_names) attr_reader(*attr_names) private(*attr_names) lambda do |*attr_values| attr_names.zip(attr_values) do |attr_name, attr_value| instance_variable_set(:"@#{attr_name}", attr_value) end end end # assign_attributes isn't defined in the private section below because # that makes MRI 1.9.2 emit a warning about private attributes. private :assign_attributes private # Does the following: # # - Defines the named method using a user-provided block # in @user_method_defs, which is included as an ancestor # in the singleton class in which we eval the `define` block. # - Defines an overridden definition for the same method # usign the provided `our_def` block. # - Provides a default `our_def` block for the common case # of needing to call the user's definition with `@actual` # as an arg, but only if their block's arity can handle it. # # This compiles the user block into an actual method, allowing # them to use normal method constructs like `return` # (e.g. for an early guard statement), while allowing us to define # an override that can provide the wrapped handling # (e.g. assigning `@actual`, rescueing errors, etc) and # can `super` to the user's definition. def define_user_override(method_name, user_def, &our_def) @user_method_defs.__send__(:define_method, method_name, &user_def) our_def ||= lambda { super(*actual_arg_for(user_def)) } define_method(method_name, &our_def) end # Defines deprecated macro methods from RSpec 2 for backwards compatibility. # @deprecated Use the methods from {Macros} instead. module Deprecated # @deprecated Use {Macros#match} instead. def match_for_should(&definition) RSpec.deprecate("`match_for_should`", :replacement => "`match`") match(&definition) end # @deprecated Use {Macros#match_when_negated} instead. def match_for_should_not(&definition) RSpec.deprecate("`match_for_should_not`", :replacement => "`match_when_negated`") match_when_negated(&definition) end # @deprecated Use {Macros#failure_message} instead. def failure_message_for_should(&definition) RSpec.deprecate("`failure_message_for_should`", :replacement => "`failure_message`") failure_message(&definition) end # @deprecated Use {Macros#failure_message_when_negated} instead. def failure_message_for_should_not(&definition) RSpec.deprecate("`failure_message_for_should_not`", :replacement => "`failure_message_when_negated`") failure_message_when_negated(&definition) end end end # Defines default implementations of the matcher # protocol methods for custom matchers. You can # override any of these using the {RSpec::Matchers::DSL::Macros Macros} methods # from within an `RSpec::Matchers.define` block. module DefaultImplementations include BuiltIn::BaseMatcher::DefaultFailureMessages # @api private # Used internally by objects returns by `should` and `should_not`. def diffable? false end # The default description. def description english_name = EnglishPhrasing.split_words(name) expected_list = EnglishPhrasing.list(expected) "#{english_name}#{expected_list}#{chained_method_clause_sentences}" end # Matchers do not support block expectations by default. You # must opt-in. def supports_block_expectations? false end def supports_value_expectations? true end # Most matchers do not expect call stack jumps. def expects_call_stack_jump? false end private def chained_method_clause_sentences return '' unless Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions? @chained_method_clauses.map do |(method_name, method_args)| english_name = EnglishPhrasing.split_words(method_name) arg_list = EnglishPhrasing.list(method_args) " #{english_name}#{arg_list}" end.join end end # The class used for custom matchers. The block passed to # `RSpec::Matchers.define` will be evaluated in the context # of the singleton class of an instance, and will have the # {RSpec::Matchers::DSL::Macros Macros} methods available. class Matcher # Provides default implementations for the matcher protocol methods. include DefaultImplementations # Allows expectation expressions to be used in the match block. include RSpec::Matchers # Supports the matcher composability features of RSpec 3+. include Composable # Makes the macro methods available to an `RSpec::Matchers.define` block. extend Macros extend Macros::Deprecated # Exposes the value being matched against -- generally the object # object wrapped by `expect`. attr_reader :actual # Exposes the exception raised during the matching by `match_unless_raises`. # Could be useful to extract details for a failure message. attr_reader :rescued_exception # The block parameter used in the expectation attr_reader :block_arg # The name of the matcher. attr_reader :name # @api private def initialize(name, declarations, matcher_execution_context, *expected, &block_arg) @name = name @actual = nil @expected_as_array = expected @matcher_execution_context = matcher_execution_context @chained_method_clauses = [] @block_arg = block_arg klass = class << self # See `Macros#define_user_override` above, for an explanation. include(@user_method_defs = Module.new) self end RSpec::Support::WithKeywordsWhenNeeded.class_exec(klass, *expected, &declarations) end # Provides the expected value. This will return an array if # multiple arguments were passed to the matcher; otherwise it # will return a single value. # @see #expected_as_array def expected if expected_as_array.size == 1 expected_as_array[0] else expected_as_array end end # Returns the expected value as an an array. This exists primarily # to aid in upgrading from RSpec 2.x, since in RSpec 2, `expected` # always returned an array. # @see #expected attr_reader :expected_as_array # Adds the name (rather than a cryptic hex number) # so we can identify an instance of # the matcher in error messages (e.g. for `NoMethodError`) def inspect "#<#{self.class.name} #{name}>" end if RUBY_VERSION.to_f >= 1.9 # Indicates that this matcher responds to messages # from the `@matcher_execution_context` as well. # Also, supports getting a method object for such methods. def respond_to_missing?(method, include_private=false) super || @matcher_execution_context.respond_to?(method, include_private) end else # for 1.8.7 # :nocov: # Indicates that this matcher responds to messages # from the `@matcher_execution_context` as well. def respond_to?(method, include_private=false) super || @matcher_execution_context.respond_to?(method, include_private) end # :nocov: end private def actual_arg_for(block) block.arity.zero? ? [] : [@actual] end # Takes care of forwarding unhandled messages to the # `@matcher_execution_context` (typically the current # running `RSpec::Core::Example`). This is needed by # rspec-rails so that it can define matchers that wrap # Rails' test helper methods, but it's also a useful # feature in its own right. def method_missing(method, *args, &block) if @matcher_execution_context.respond_to?(method) @matcher_execution_context.__send__ method, *args, &block else super(method, *args, &block) end end # The method_missing method should be refactored to pass kw args in RSpec 4 # then this can be removed ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) end end end end