Skip to content

Commit

Permalink
Implement #guard and #guard_not to combine guards
Browse files Browse the repository at this point in the history
* Closes #30
  • Loading branch information
eregon committed Jul 27, 2017
1 parent 9c56e03 commit ea7600d
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 2 deletions.
28 changes: 26 additions & 2 deletions lib/mspec/guards/guard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,22 @@ def yield?(invert = false)

def run_if(name, &block)
@name = name
yield if yield?(false)
if block
yield if yield?(false)
else
yield?(false)
end
ensure
unregister
end

def run_unless(name, &block)
@name = name
yield if yield?(true)
if block
yield if yield?(true)
else
yield?(true)
end
ensure
unregister
end
Expand Down Expand Up @@ -115,3 +123,19 @@ def match?
raise "must be implemented by the subclass"
end
end

# Combined guards

def guard(condition, &block)
raise "condition must be a Proc" unless condition.is_a?(Proc)
raise LocalJumpError, "no block given" unless block
return yield if MSpec.mode? :unguarded or MSpec.mode? :verify or MSpec.mode? :report
yield if condition.call
end

def guard_not(condition, &block)
raise "condition must be a Proc" unless condition.is_a?(Proc)
raise LocalJumpError, "no block given" unless block
return yield if MSpec.mode? :unguarded or MSpec.mode? :verify or MSpec.mode? :report
yield unless condition.call
end
210 changes: 210 additions & 0 deletions spec/guards/guard_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,23 @@
@guard.stub(:match?).and_return(false)
@guard.run_if(:name) { fail }
end

it "returns the result of the block if match? is true" do
@guard.stub(:match?).and_return(true)
@guard.run_if(:name) { 42 }.should == 42
end

it "returns nil if given a block and match? is false" do
@guard.stub(:match?).and_return(false)
@guard.run_if(:name) { 42 }.should == nil
end

it "returns what #match? returns when no block is given" do
@guard.stub(:match?).and_return(true)
@guard.run_if(:name).should == true
@guard.stub(:match?).and_return(false)
@guard.run_if(:name).should == false
end
end

describe SpecGuard, ".run_unless" do
Expand All @@ -213,4 +230,197 @@
@guard.stub(:match?).and_return(true)
@guard.run_unless(:name) { fail }
end

it "returns the result of the block if match? is false" do
@guard.stub(:match?).and_return(false)
@guard.run_unless(:name) { 42 }.should == 42
end

it "returns nil if given a block and match? is true" do
@guard.stub(:match?).and_return(true)
@guard.run_unless(:name) { 42 }.should == nil
end

it "returns the opposite of what #match? returns when no block is given" do
@guard.stub(:match?).and_return(true)
@guard.run_unless(:name).should == false
@guard.stub(:match?).and_return(false)
@guard.run_unless(:name).should == true
end
end

describe Object, "#guard" do
before :each do
ScratchPad.clear
end

after :each do
MSpec.clear_modes
end

it "allows to combine guards" do
guard1 = VersionGuard.new 'x.x.x'
VersionGuard.stub(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
PlatformGuard.stub(:new).and_return(guard2)

guard1.stub(:match?).and_return(true)
guard2.stub(:match?).and_return(true)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield
end
ScratchPad.recorded.should == :yield

guard1.stub(:match?).and_return(false)
guard2.stub(:match?).and_return(true)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end

guard1.stub(:match?).and_return(true)
guard2.stub(:match?).and_return(false)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end

guard1.stub(:match?).and_return(false)
guard2.stub(:match?).and_return(false)
guard -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end
end

it "yields when the Proc returns true" do
guard -> { true } do
ScratchPad.record :yield
end
ScratchPad.recorded.should == :yield
end

it "does not yield when the Proc returns false" do
guard -> { false } do
fail
end
end

it "yields if MSpec.mode?(:unguarded) is true" do
MSpec.register_mode :unguarded

guard -> { false } do
ScratchPad.record :yield1
end
ScratchPad.recorded.should == :yield1

guard -> { true } do
ScratchPad.record :yield2
end
ScratchPad.recorded.should == :yield2
end

it "yields if MSpec.mode?(:verify) is true" do
MSpec.register_mode :verify

guard -> { false } do
ScratchPad.record :yield1
end
ScratchPad.recorded.should == :yield1

guard -> { true } do
ScratchPad.record :yield2
end
ScratchPad.recorded.should == :yield2
end

it "yields if MSpec.mode?(:report) is true" do
MSpec.register_mode :report

guard -> { false } do
ScratchPad.record :yield1
end
ScratchPad.recorded.should == :yield1

guard -> { true } do
ScratchPad.record :yield2
end
ScratchPad.recorded.should == :yield2
end

it "raises an error if no Proc is given" do
-> { guard :foo }.should raise_error(RuntimeError)
end

it "requires a block" do
-> {
guard(-> { true })
}.should raise_error(LocalJumpError)
-> {
guard(-> { false })
}.should raise_error(LocalJumpError)
end
end

describe Object, "#guard_not" do
before :each do
ScratchPad.clear
end

it "allows to combine guards" do
guard1 = VersionGuard.new 'x.x.x'
VersionGuard.stub(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
PlatformGuard.stub(:new).and_return(guard2)

guard1.stub(:match?).and_return(true)
guard2.stub(:match?).and_return(true)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
fail
end

guard1.stub(:match?).and_return(false)
guard2.stub(:match?).and_return(true)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield1
end
ScratchPad.recorded.should == :yield1

guard1.stub(:match?).and_return(true)
guard2.stub(:match?).and_return(false)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield2
end
ScratchPad.recorded.should == :yield2

guard1.stub(:match?).and_return(false)
guard2.stub(:match?).and_return(false)
guard_not -> { ruby_version_is "2.4" and platform_is :linux } do
ScratchPad.record :yield3
end
ScratchPad.recorded.should == :yield3
end

it "yields when the Proc returns false" do
guard_not -> { false } do
ScratchPad.record :yield
end
ScratchPad.recorded.should == :yield
end

it "does not yield when the Proc returns true" do
guard_not -> { true } do
fail
end
end

it "raises an error if no Proc is given" do
-> { guard_not :foo }.should raise_error(RuntimeError)
end

it "requires a block" do
-> {
guard_not(-> { true })
}.should raise_error(LocalJumpError)
-> {
guard_not(-> { false })
}.should raise_error(LocalJumpError)
end
end
14 changes: 14 additions & 0 deletions spec/guards/platform_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
ScratchPad.recorded.should == :yield
end

it "returns what #os? returns when no block is given" do
PlatformGuard.stub(:os?).and_return(true)
platform_is(:solarce).should == true
PlatformGuard.stub(:os?).and_return(false)
platform_is(:solarce).should == false
end

it "sets the name of the guard to :platform_is" do
platform_is(:solarce) { }
@guard.name.should == :platform_is
Expand Down Expand Up @@ -53,6 +60,13 @@
ScratchPad.recorded.should == :yield
end

it "returns the opposite of what #os? returns when no block is given" do
PlatformGuard.stub(:os?).and_return(true)
platform_is_not(:solarce).should == false
PlatformGuard.stub(:os?).and_return(false)
platform_is_not(:solarce).should == true
end

it "sets the name of the guard to :platform_is_not" do
platform_is_not(:solarce) { }
@guard.name.should == :platform_is_not
Expand Down
7 changes: 7 additions & 0 deletions spec/guards/version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@
ScratchPad.recorded.should_not == :yield
end

it "returns what #match? returns when no block is given" do
@guard.stub(:match?).and_return(true)
ruby_version_is('x.x.x').should == true
@guard.stub(:match?).and_return(false)
ruby_version_is('x.x.x').should == false
end

it "sets the name of the guard to :ruby_version_is" do
ruby_version_is("") { }
@guard.name.should == :ruby_version_is
Expand Down

0 comments on commit ea7600d

Please sign in to comment.