Skip to content

Commit

Permalink
Beef up and restructure the RSpec suite to reduce duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
laserlemon committed Apr 25, 2024
1 parent ef6d6b8 commit 764dfa4
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 515 deletions.
11 changes: 6 additions & 5 deletions lib/rspec/wait.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Wait
# From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/syntax.rb#L72-L74
def wait_for(*args, &block)
raise ArgumentError, "The `wait_for` method only accepts a block." if args.any?
raise ArgumentError, "The `wait_for` method requires a block." unless block

Target.new(block)
end
Expand All @@ -28,14 +29,14 @@ def wait(arg = nil, timeout: arg, delay: nil, clone_matcher: nil)
Proxy.new(timeout: timeout, delay: delay, clone_matcher: clone_matcher)
end

def with_wait(options)
def with_wait(timeout: nil, delay: nil, clone_matcher: nil)
original_timeout = RSpec.configuration.wait_timeout
original_delay = RSpec.configuration.wait_delay
original_clone_matcher = RSpec.configuration.clone_wait_matcher

RSpec.configuration.wait_timeout = options[:timeout] if options[:timeout]
RSpec.configuration.wait_delay = options[:delay] if options[:delay]
RSpec.configuration.clone_wait_matcher = options[:clone_matcher] if options.key?(:clone_matcher)
RSpec.configuration.wait_timeout = timeout unless timeout.nil?
RSpec.configuration.wait_delay = delay unless delay.nil?
RSpec.configuration.clone_wait_matcher = clone_matcher unless clone_matcher.nil?

yield
ensure
Expand All @@ -55,6 +56,6 @@ def with_wait(options)

config.around(wait: {}) do |example|
options = example.metadata.fetch(:wait)
with_wait(options) { example.run }
with_wait(**options) { example.run }
end
end
2 changes: 2 additions & 0 deletions lib/rspec/wait/handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def handle_matcher(target, initial_matcher, message, &block)
super(target.call, matcher, message, &block)
end
rescue RSpec::Expectations::ExpectationNotMetError
raise if RSpec.world.wants_to_quit

elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
raise if elapsed_time > RSpec.configuration.wait_timeout

Expand Down
3 changes: 2 additions & 1 deletion lib/rspec/wait/proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ module Wait
# wait(3.seconds).for { this }.to eq(that)
#
class Proxy
def initialize(options = {})
def initialize(**options)
@options = options
end

def for(*args, &block)
raise ArgumentError, "The `wait.for` method only accepts a block." if args.any?
raise ArgumentError, "The `wait.for` method requires a block." unless block

Target.new(block, @options)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/wait/target.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def not_to(matcher = nil, message = nil, &block)
private

def with_wait(&block)
Wait.with_wait(@wait_options, &block)
Wait.with_wait(**@wait_options, &block)
end
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/support/eq_with_bad_memoization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
RSpec::Matchers.define :eq_with_bad_memoization do |expected|
match do |actual|
@memo ||= actual
@actual = @memo
@memo == expected
end
end
23 changes: 23 additions & 0 deletions spec/support/pass_fail_expectations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module PassFailExpectations
def expect_pass(&block)
expect(&block).not_to raise_error
end

def expect_fail(&block)
expect(&block).to raise_error(RSpec::Expectations::ExpectationNotMetError) do |error|
return error
end
end

def expect_error(*args, &block)
expect(&block).to raise_error(*args) do |error|
return error
end
end
end

RSpec.configure do |config|
config.include(PassFailExpectations)
end
22 changes: 22 additions & 0 deletions spec/support/rspec_shutdown.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module RSpecShutdown
def with_rspec_shutting_down_in(seconds)
original_wants_to_quit = :unknown
wants_to_quit_thread =
Thread.new do
sleep seconds
original_wants_to_quit = RSpec.world.wants_to_quit
RSpec.world.wants_to_quit = true
end

yield
ensure
wants_to_quit_thread&.kill
RSpec.world.wants_to_quit = original_wants_to_quit unless original_wants_to_quit == :unknown
end
end

RSpec.configure do |config|
config.include(RSpecShutdown)
end
28 changes: 28 additions & 0 deletions spec/support/ticker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

class Ticker
attr_reader :timeout, :tape

def initialize(timeout:)
@timeout = timeout
@tape = ""
end

def start
@ticking =
Thread.new do
timeout.times do
sleep 1
@tape += "."
end
end
end

def length
tape.length
end

def stop
@ticking&.kill
end
end
Loading

0 comments on commit 764dfa4

Please sign in to comment.