Skip to content

Loading…

Issue 126 #579

Closed
wants to merge 4 commits into from

2 participants

@preethiramdev

Reinstating prepend_before

The issue required the restoring prepend_before and append_after. However, on taking a look at the code it seems to me like "append_after" and the current "after" method would function the same way. Hence I've only added prepend_before. Please let me know if there something I'm missing on the append_after and I will get it working

@dchelimsky
RSpec member

After hooks are run in reverse: https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/hooks.rb#L80.

What we should probably do is change it so after hooks are stored in reverse and run in the stored order, and then append_after will make sense. Also - the way it worked in rspec-1 was that we had

def prepend_before; ...; end
def append_before;  ...; end
def prepend_after;  ...; end
def append_after;   ...; end

alias_method :before, :append_before # so they are stored in order
alias_method :after,  :prepend_after # so they are stored in reverse order

That way the ordering is more self-evident.

@preethiramdev

Will do

@preethiramdev

You should be able to see the changes on the latest commit of this pull request. Let me know if this is what you were think of

@dchelimsky dchelimsky added a commit that referenced this pull request
@dchelimsky dchelimsky rdoc tweaks for #579 d46c857
@dchelimsky dchelimsky added a commit that referenced this pull request
@dchelimsky dchelimsky Changelog for #579 f85d405
@dchelimsky
RSpec member

Merged 19e2e2c

@dchelimsky dchelimsky closed this
@dchelimsky
RSpec member

Actually, this doesn't solve the problem from rspec/rspec-rails#391 yet because we need to be able to prepend_before in a group and have it run before the hooks declared in global config :) I'm looking into a solution for this.

@preethiramdev

Agreed..Will look into it too

@dchelimsky
RSpec member

@preethiramdev I've been working on it on and off for the last week or two - basically refactoring the entire hooks functionality. You're welcome to try something, but I'm likely to go with the changes I'm already midstream on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 9, 2012
  1. @preethiramdev

    Adding prepend before

    preethiramdev committed
  2. @preethiramdev

    Comments

    preethiramdev committed
Commits on Mar 15, 2012
  1. @preethiramdev
Commits on Mar 16, 2012
  1. @preethiramdev
This page is out of date. Refresh to see the latest.
Showing with 170 additions and 9 deletions.
  1. +28 −4 lib/rspec/core/hooks.rb
  2. +142 −5 spec/rspec/core/hooks_spec.rb
View
32 lib/rspec/core/hooks.rb
@@ -77,11 +77,11 @@ def run_all!(example_group_instance)
class AfterHooks < HookCollection
def run_all(example_group_instance)
- reverse.each {|h| h.run_in(example_group_instance) }
+ each { |h| h.run_in(example_group_instance) } unless empty?
end
def run_all!(example_group_instance)
- pop.run_in(example_group_instance) until empty?
+ shift.run_in(example_group_instance) until empty?
end
end
@@ -254,11 +254,23 @@ def hooks
# File.delete(file_to_parse)
# end
# end
- def before(*args, &block)
+ def append_before(*args, &block)
scope, options = scope_and_options_from(*args)
hooks[:before][scope] << BeforeHook.new(options, &block)
end
+ alias_method :before, :append_before
+
+ # Registers a block to be executed before all other before blocks of the same scope.
+ # This method prepends +block+ to existing before blocks.
+ #
+ # See #before for scoping semantics.
+ #
+ def prepend_before(*args, &block)
+ scope, options = scope_and_options_from(*args)
+ hooks[:before][scope].unshift(BeforeHook.new(options, &block))
+ end
+
# @api public
# @overload after(&block)
# @overload after(scope, &block)
@@ -307,11 +319,23 @@ def before(*args, &block)
# This is the reverse of the order in which `before` hooks are run.
# Similarly, if more than one `after` is declared within any one scope,
# they are run in reverse order of that in which they are declared.
- def after(*args, &block)
+ def prepend_after(*args, &block)
+ scope, options = scope_and_options_from(*args)
+ hooks[:after][scope].unshift(AfterHook.new(options, &block))
+ end
+
+ alias_method :after, :prepend_after
+
+ # Registers a block to be executed after each example.
+ # This method appends +block+ to existing after blocks.
+ #
+ def append_after(*args, &block)
scope, options = scope_and_options_from(*args)
hooks[:after][scope] << AfterHook.new(options, &block)
end
+
+
# @api public
# @overload around(&block)
# @overload around(scope, &block)
View
147 spec/rspec/core/hooks_spec.rb
@@ -15,7 +15,7 @@ class HooksHost
define_method :metadata_hash do |*args|
instance = HooksHost.new
args.unshift scope if scope
- hooks = instance.send(type, *args) { }
+ hooks = instance.send(type, *args) {}
hooks.first.options
end
end
@@ -33,19 +33,19 @@ class HooksHost
let(:instance) { HooksHost.new }
it "defaults to :each scope if no arguments are given" do
- hooks = instance.send(type) { }
+ hooks = instance.send(type) {}
hook = hooks.first
instance.hooks[type][:each].should include(hook)
end
it "defaults to :each scope if the only argument is a metadata hash" do
- hooks = instance.send(type, :foo => :bar) { }
+ hooks = instance.send(type, :foo => :bar) {}
hook = hooks.first
instance.hooks[type][:each].should include(hook)
end
it "raises an error if only metadata symbols are given as arguments" do
- expect { instance.send(type, :foo, :bar) { } }.to raise_error(ArgumentError)
+ expect { instance.send(type, :foo, :bar) {} }.to raise_error(ArgumentError)
end
end
end
@@ -63,7 +63,7 @@ class HooksHost
describe "##{type}(#{scope.inspect})" do
let(:instance) { HooksHost.new }
let!(:hook) do
- hooks = instance.send(type, scope) { }
+ hooks = instance.send(type, scope) {}
hooks.first
end
@@ -119,6 +119,7 @@ class HooksHost
def yielder
yield
end
+
around do |example|
yielder { example.run }
end
@@ -139,5 +140,141 @@ def yielder
end
end
end
+
+ describe "prepend_before" do
+ it "should prepend before callbacks so they are run prior to other before filters for the specified scope" do
+ fiddle = []
+ example_group = ExampleGroup.describe do
+ around do |example|
+ example.run
+ end
+ it "foo" do
+ examples << self
+ end
+ end
+ example_group.prepend_before(:all) { fiddle << "prepend_before(:all)" }
+ example_group.before(:all) { fiddle << "before(:all)" }
+ example_group.prepend_before(:each) { fiddle << "prepend_before(:each)" }
+ example_group.before(:each) { fiddle << "before(:each)" }
+ RSpec.configure { |config| config.prepend_before(:each) { fiddle << "config.prepend_before(:each)" } }
+ RSpec.configure { |config| config.prepend_before(:all) { fiddle << "config.prepend_before(:all)" } }
+ example_group.run
+ fiddle.should == [
+ 'config.prepend_before(:all)',
+ 'prepend_before(:all)',
+ 'before(:all)',
+ "config.prepend_before(:each)",
+ 'prepend_before(:each)',
+ 'before(:each)'
+ ]
+ end
+ end
+
+ describe "#append_before" do
+
+ it "should order before callbacks from global to local" do
+ order = []
+ example_group = ExampleGroup.describe do
+ around do |example|
+ example.run
+ end
+ it "foo" do
+ examples << self
+ end
+ end
+ example_group.append_before(:each) do
+ order << :example_group_append_before_each
+ end
+ RSpec.configure { |config| config.append_before { order << :append_before_each } } # default is :each
+ RSpec.configure { |config| config.append_before(:all) { order << :append_before_all } }
+ RSpec.configure { |config| config.before(:all) { order << :before_all } }
+
+ example_group.append_before(:all) do
+ order << :example_group_append_before_all
+ end
+
+ example_group.run
+ order.should == [
+ :append_before_all,
+ :before_all,
+ :example_group_append_before_all,
+ :append_before_each,
+ :example_group_append_before_each,
+ ]
+ end
+ end
+
+ describe "#prepend_after" do
+
+ it "should order after callbacks from global to local" do
+ order = []
+ example_group = ExampleGroup.describe do
+ around do |example|
+ example.run
+ end
+ it "foo" do
+ examples << self
+ end
+ end
+
+ RSpec.configure { |config| config.prepend_after(:all) { order << :prepend__after_all } }
+ RSpec.configure { |config| config.prepend_after(:each) { order << :prepend__after_each } }
+ example_group.prepend_after(:all) do
+ order << :example_group_prepend_after_all
+ end
+ example_group.prepend_after(:each) do
+ order << :example_group_prepend_after_each
+ end
+ example_group.run
+ order.should == [
+ :example_group_prepend_after_each,
+ :prepend__after_each,
+ :example_group_prepend_after_all,
+ :prepend__after_all
+ ]
+ end
+ end
+
+ describe "#append_after" do
+
+ it "should append callbacks so they are run after other after filters for the specified scope" do
+ order = []
+ example_group = ExampleGroup.describe do
+ around do |example|
+ example.run
+ end
+ it "foo" do
+ examples << self
+ end
+ end
+
+ RSpec.configure { |config| config.append_after(:all) { order << :append__after_all } }
+ RSpec.configure { |config| config.after(:all) { order << :after_all } }
+ example_group.append_after(:all) do
+ order << :example_group_append__after_all
+ end
+
+ RSpec.configure { |config| config.append_after(:each) { order << :append_after_each } }
+
+ example_group.append_after(:each) do
+ order << :example_group_append__after_each
+ end
+
+ example_group.after(:each) do
+ order << :example_group__after_each
+ end
+
+ example_group.run
+ order.should == [
+ :example_group__after_each,
+ :example_group_append__after_each,
+ :append_after_each,
+ :example_group_append__after_all,
+ :after_all,
+ :append__after_all
+ ]
+ end
+
+ end
end
end
Something went wrong with that request. Please try again.