Skip to content

Commit

Permalink
Merge pull request #3101 from rspec/fix-ruby-head
Browse files Browse the repository at this point in the history
Fix build for Ruby 3.4
  • Loading branch information
JonRowe committed Jul 17, 2024
2 parents 34052fb + 1acd671 commit 2ba0f10
Show file tree
Hide file tree
Showing 19 changed files with 121 additions and 75 deletions.
3 changes: 1 addition & 2 deletions features/command_line/init.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ Feature: `--init` option

Scenario: Generate `.rspec`
When I run `rspec --init`
Then the following files should exist:
| .rspec |
Then the file `.rspec` should exist
And the output should contain "create .rspec"

Scenario: `.rspec` file already exists
Expand Down
6 changes: 3 additions & 3 deletions features/configuration/backtrace_exclusion_patterns.feature
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Feature: Excluding lines from the backtrace
"""
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 %R{spec/support/custom_helper.rb:2:in ('Object#|`)assert_baz'}
And the output should contain "lib/rspec/expectations"
And the output should contain "lib/rspec/core"
Expand Down Expand Up @@ -150,5 +150,5 @@ Feature: Excluding lines from the backtrace
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!'"
Then the output from `rspec` should contain %R{vendor/my_gem-1.2.3/lib/my_gem.rb:4:in (`|'MyGem\.)do_amazing_things!'}
But the output from `rspec --require spec_helper` should not contain %R{vendor/my_gem-1.2.3/lib/my_gem.rb:4:in (`|'MyGem\.)do_amazing_things!'}
2 changes: 1 addition & 1 deletion features/configuration/enable_global_dsl.feature
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Feature: Global namespace DSL
end
"""
When I run `rspec`
Then the output should contain "undefined method `describe'"
Then the output should contain %R{undefined method (`|')describe'}

Scenario: Regardless of setting
Given a file named "spec/example_spec.rb" with:
Expand Down
7 changes: 3 additions & 4 deletions features/configuration/zero_monkey_patching_mode.feature
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,10 @@ Feature: Zero monkey patching mode
end
"""
When I run `rspec spec/example_should_spec.rb`
Then the output should contain all of these:
| undefined method `should' |
| unexpected message :stub |
Then the output should contain %R{undefined method (`|')should'}
And the output should contain "unexpected message :stub"
When I run `rspec spec/example_describe_spec.rb`
Then the output should contain "undefined method `describe'"
Then the output should contain %R{undefined method (`|')describe'}

Scenario: `allow` and `expect` syntax works with monkey patching
Given a file named "spec/spec_helper.rb" with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Feature: Aggregating Failures
end
"""

@skip-when-diff-lcs-1.3
@skip-when-diff-lcs-1.3 @broken-on-jruby
Scenario: Use `aggregate_failures` block form
Given a file named "spec/use_block_form_spec.rb" with:
"""ruby
Expand Down
23 changes: 23 additions & 0 deletions features/step_definitions/additional_cli_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@
step %Q{the output from "#{cmd}" should not contain "#{expected_output}"}
end

Then /^the output from `([^`]+)` should( not)? contain %R{(.*?)}$/ do |cmd, negated, expected_output|
step %Q{I run `#{cmd}`}

command = aruba.command_monitor.find(Aruba.platform.detect_ruby(cmd))
regexp = Regexp.new(expected_output)

if negated
expect(command.output).to_not match regexp
else
expect(command.output).to match regexp
end
end

Given /^I have a brand new project with no files$/ do
cd('.') do
expect(Dir["**/*"]).to eq([])
Expand Down Expand Up @@ -137,6 +150,10 @@
step %Q{the output from "#{command}" should contain "#{output_snippet}"}
end

Then /^the output should contain %R{(.*)}$/ do |output_regexp|
expect(all_output).to match(Regexp.new(output_regexp))
end

When(/^I fix "(.*?)" by replacing "(.*?)" with "(.*?)"$/) do |file_name, original, replacement|
cd('.') do
contents = File.read(file_name)
Expand Down Expand Up @@ -240,6 +257,12 @@
end
end

Then /^the file `([^`]+)` should exist$/ do |file|
cd('.') do
File.exist?(file)
end
end

module Normalization
def normalize_failure_output(text)
whitespace_normalized = text.lines.map { |line| line.sub(/\s+$/, '').sub(/:in .*$/, '') }.join
Expand Down
9 changes: 9 additions & 0 deletions features/support/jruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,12 @@
block.call
end
end

Around "@broken-on-jruby" do |scenario, block|
require 'rspec/support/ruby_features'
if RSpec::Support::Ruby.jruby?
skip_this_scenario "Skipping scenario #{scenario.name} not supported on JRuby"
else
block.call
end
end
2 changes: 1 addition & 1 deletion lib/rspec/core/pending.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class PendingExampleFixedError < StandardError; end
# 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)
def pending(message=nil, &_block)
current_example = RSpec.current_example

if block_given?
Expand Down
22 changes: 0 additions & 22 deletions script/custom_build_functions.sh

This file was deleted.

2 changes: 1 addition & 1 deletion spec/integration/bisect_runners_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def with_runner(&block)
expect {
runner.original_results
}.to raise_error(Bisect::BisectFailedError, a_string_including(
"undefined method `escribe' for #{rspec_description}",
"undefined method #{quoted('escribe')} for #{rspec_description}",
'stdout in a_spec',
'stderr in a_spec'
))
Expand Down
2 changes: 1 addition & 1 deletion spec/integration/bisect_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def bisect(cli_args, expected_status=nil)
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")
expect(output).to include("Bisect failed!", "undefined method #{quoted('contex')}", "About to call misspelled method")
end
end

Expand Down
12 changes: 9 additions & 3 deletions spec/integration/failed_line_detection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,16 @@ def self.trigger_failure

run_command "./spec/default_config_spec.rb"

expect(last_cmd_stdout).to include("raise 'LibMod failure'").
expect(
last_cmd_stdout
).to include("raise 'LibMod failure'").
and include("raise 'AppMod failure'").
and include("raise 'SpecSupport failure'").
and exclude("AppMod.trigger_failure")
and include("raise 'SpecSupport failure'")

if RUBY_VERSION.to_f > 3.3
# Ruby 3.4 seems to print the calling function and we've not configured it otherwise
expect(last_cmd_stdout).to include("AppMod.trigger_failure")
end

write_file "spec/change_config_spec.rb", "
require './app/app_mod'
Expand Down
18 changes: 10 additions & 8 deletions spec/integration/spec_file_load_errors_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
let(:error_exit_code) { failure_exit_code + 1 } # 3..100

if RSpec::Support::Ruby.jruby_9000?
let(:spec_line_suffix) { ":in `<main>'" }
let(:spec_line_suffix) { ":in #{quoted('<main>')}" }
elsif RSpec::Support::Ruby.jruby?
let(:spec_line_suffix) { ":in `(root)'" }
let(:spec_line_suffix) { ":in #{quoted('(root)')}" }
elsif RUBY_VERSION == "1.8.7"
let(:spec_line_suffix) { "" }
else
let(:spec_line_suffix) { ":in `<top (required)>'" }
let(:spec_line_suffix) { ":in #{quoted('<top (required)>')}" }
end

before do
Expand Down Expand Up @@ -107,7 +107,7 @@
}.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", "")
output = output.sub("# ./helper_with_exit.rb:1:in #{quoted('exit')}\n", "")

if defined?(JRUBY_VERSION) && !JRUBY_VERSION.empty?
expect(output).to eq unindent(<<-EOS)
Expand All @@ -120,15 +120,17 @@
# ./helper_with_exit.rb:1#{spec_line_suffix}
EOS
else
expect(output).to eq unindent(<<-EOS)
string = <<-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
string += "# ./helper_with_exit.rb:1:in 'Kernel#exit'\n" if RUBY_VERSION.to_f > 3.3
string += "# ./helper_with_exit.rb:1#{spec_line_suffix}\n"
expect(output).to eq unindent(string)
end
end

Expand Down Expand Up @@ -178,14 +180,14 @@
Failure/Error: boom
NameError:
undefined local variable or method `boom' for main#{object_suffix}
undefined local variable or method #{quoted('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}
undefined local variable or method #{quoted('boom')} for main#{object_suffix}
# ./3_spec.rb:1#{spec_line_suffix}
Expand Down
10 changes: 5 additions & 5 deletions spec/integration/suite_hooks_errors_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
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 <main>'" }
let(:spec_line_suffix) { ":in #{quoted('block in <main>')}" }
elsif RSpec::Support::Ruby.jruby_9000?
let(:spec_line_suffix) { ":in `block in (root)'" }
let(:spec_line_suffix) { ":in #{quoted('block in (root)')}" }
elsif RSpec::Support::Ruby.jruby?
let(:spec_line_suffix) { ":in `(root)'" }
let(:spec_line_suffix) { ":in #{quoted('(root)')}" }
elsif RUBY_VERSION == "1.8.7"
let(:spec_line_suffix) { "" }
else
let(:spec_line_suffix) { ":in `block (2 levels) in <top (required)>'" }
let(:spec_line_suffix) { ":in #{quoted('block (2 levels) in <top (required)>')}" }
end

before do
Expand Down Expand Up @@ -107,7 +107,7 @@ def run_spec_expecting_non_zero(before_or_after)
# --- Caused by: ---
# RuntimeError:
# before 1
# ./the_spec.rb:3:in `block in <main>'
# ./the_spec.rb:3:in #{quoted('block in <main>')}
EOS
else
""
Expand Down
15 changes: 12 additions & 3 deletions spec/rspec/core/formatters/base_text_formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,18 @@ def run_all_and_dump_failures
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)
expect(formatter_output_without_formatter_module).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") }
group.example("example name") do
this = Object.new
expect(this).to receive(:that)
end
run_all_and_dump_failures
expect(formatter_output.string).not_to match(/RSpec::/m)
expect(formatter_output_without_formatter_module).not_to match(/RSpec::/m)
end
end

Expand Down Expand Up @@ -293,4 +296,10 @@ def run_all_and_dump_failures
expect(formatter_output.string).to include("\e[36m")
end
end

# Ruby 3.4 includes modules names in stack traces but two of our tests are looking for RSpec module names, remove
# this one as it is considered 'safe'
def formatter_output_without_formatter_module
formatter_output.string.tr('RSpec::ExampleGroups::RSpecCoreFormattersBaseTextFormatter::DumpFailures#','')
end
end
12 changes: 11 additions & 1 deletion spec/rspec/core/formatters/html_formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,17 @@ module Formatters
end

let(:expected_html) do
File.read(expected_file)
handle_ruby34_quoting(File.read(expected_file))
end

if RUBY_VERSION.to_f > 3.3
def handle_ruby34_quoting(string)
string.gsub('`block', '&#39;block')
end
else
def handle_ruby34_quoting(string)
string
end
end

# Uncomment this group temporarily in order to overwrite the expected
Expand Down
2 changes: 1 addition & 1 deletion spec/rspec/core/formatters/snippet_extractor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ module RSpec::Core::Formatters
# 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(*)
def do_something_fail(*, &_block)
raise
end

Expand Down
Loading

0 comments on commit 2ba0f10

Please sign in to comment.