shell_mock 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0774052a9e5d9c22ec4c25344e620d68cddc8604
4
- data.tar.gz: 76f022bcb48ff0558e5f4e4564a9a0ff63ddc30c
3
+ metadata.gz: b756c372c9477ca0a21a3894fb4d07c35e87c14e
4
+ data.tar.gz: 565cb68f40d84a3f2d97ccaa50cad9aa41f16eb1
5
5
  SHA512:
6
- metadata.gz: 5ce25833d01a646e100d285ce32f9810e15f348d760db2dacd669c8f045c600a16475026429226d6e10b7086c79485bfe73b0c48e2217bc272960c8eea6c479b
7
- data.tar.gz: 1f0547eb74bbfd0296a5ad37e07b66eb15ce5f516ff78ad2c2f1abb4acbe792d4fb51a3d3c5614b294a8d164cf0c7ca8066ce8a128ac10078c6fa1fba494bd46
6
+ metadata.gz: 40cf06dcafcc3e976cedac4a59623a1d47fc4c4f90f437a149d90f26ef62a3b200b6a342273bdd96036070107fa031d234a34a6fc56b457c9b0be99645257383
7
+ data.tar.gz: 9cdd1c5d0e1a1d8630aa03506493b2e847ad142fe47b4a56bfd5623522b1e8268369e045ea55fa9518f596b77a002730d3e50b5dc4e1d7597848b4a5e87baf5c
data/CHANGELOG.md CHANGED
@@ -1,12 +1,20 @@
1
1
  ## ROADMAP 1.0.0
2
2
 
3
- * add `CommandStub#with_side_effect(&blk)` for specifying desired side effects
4
- * add `CommandStub#with_stdout(str)` & `CommandStub#with_stderr(str)`. these will work differently for backtick than it will for system & exec.
3
+ * convert `CommandStub#and_exit` to `CommandStub#will_exit`
4
+ * convert `CommandStub#and_output` to `CommandStub#will_output`
5
+ * convert `CommandStub#and_return` to `CommandStub#will_return`
6
+ * add `CommandStub#will_cause(&blk)` for specifying desired side effects
7
+ * add `CommandStub#will_stdout(str)` & `CommandStub#will_stderr(str)`. these will work differently for backtick than it will for system & exec.
5
8
  * maybe add `CommandStub#with_stdin(str)` for `spawn`?
6
9
 
10
+ ## RELEASE 0.5.0
11
+
12
+ * FEATURE: `CommandStub#and_output` can be used on command stubs to set the output of a command without setting the exit status.
13
+ * ENHANCEMENT: `Kernel#spawn`, `Kernel.spawn`, & `Process.spawn` are now implemented well enough that `Open3.capture3` behaves as though spawn is not being monkey-patched when ShellMock is enabled (and therefore, spawn most definitely is being monkey-patched). This should apply to all of `Open3`'s methods, since they all delegate to `Open3.popen_run` or `Open3.pipeline_run`, both of which internally use `Kernel#spawn`, **however I only have a spec for `Open3.capture3`**.
14
+
7
15
  ## RELEASE 0.4.0
8
16
 
9
- * FEATURE: `Kernel#spawn` and `Kernel.spawn` are now supported, which means all of Open3 is, as all of that library eventually results in a `spawn` call.
17
+ * FEATURE: `Kernel#spawn` and `Kernel.spawn` are now supported
10
18
 
11
19
  ## RELEASE 0.3.3
12
20
 
data/README.md CHANGED
@@ -1,50 +1,80 @@
1
1
  # ShellMock
2
+ [![Gem Version](https://badge.fury.io/rb/shell_mock.png)](http://badge.fury.io/rb/shell_mock)
3
+ [![Build Status](https://secure.travis-ci.org/yarmiganosca/shell_mock.png)](http://travis-ci.org/yarmiganosca/shell_mock)
2
4
 
3
5
  It's [webmock](http://github.com/bblimke/webmock) for shell commands. It's pretty simple. You can do things like this:
4
6
 
5
7
  ```ruby
6
8
  require 'shell_mock/rspec'
7
9
 
8
- describe 'something' do
9
- stub = ShellMock.stub_command('ls')
10
+ RSpec.describe "shelling out to run 'ls'" do
11
+ before { ShellMock.enable }
12
+ after { ShellMock.disable }
10
13
 
11
- expect(system('ls')).to eq true
14
+ let(:stub) { ShellMock.stub_command('ls') }
12
15
 
13
- expect(stub).to have_been_called
16
+ it "works"
17
+ expect(system('ls')).to eq true
18
+
19
+ expect(stub).to have_been_called
20
+ end
14
21
  end
15
22
  ```
16
23
 
17
- Currently, `` ` ``, `exec`, and `system` are supported. Nothing in the `Open3` standard library module is currently supported.
24
+ This:
25
+ 1. enables ShellMock's monkey patches during the test
26
+ 2. creates a command stub that will match the command `"ls"` (by default it will exit `0` and have no output)
27
+ 3. shells out to run `"ls"` (in this case using `Kernel#system`)
28
+ 4. correctly expects that our command stub for `"ls"` will have recorded an invocation
18
29
 
19
- ### More complex expectations are also supported.
30
+ ### You can narrow what invocations are matched to your command stub:
20
31
 
21
- Called exactly once: `expect(stub).to have_been_called.once`
32
+ **Match env vars as well as the command:** `ShellMock.stub_command('ls').with_env({'FOO' => 'bar'})`
22
33
 
23
- Not called: `expect(stub).to_not have_been_called` or `expect(stub).to have_been_called.never`
34
+ **Provide a more complete invocation:** `ShellMock.stub_command('ls $HOME')`
24
35
 
25
- Called exactly `n` times: `expect(stub).to have_been_called.times(n)`
36
+ Shelling out to run `"ls"` won't match this command stub, but shelling out to run `"ls $HOME"` will. ShellMock always matches as strictly as possible, so if you stubbed `"ls"` and `"ls $HOME"`, invocations of `"ls $HOME'` would only ever match against the latter.
26
37
 
27
- Called more than `n` times: `expect(stub).to have_been_called.more_than(n)`
38
+ ### Setting the behavior of the command invocation:
28
39
 
29
- Called fewer than `n` times: `expect(stub).to have_been_called.fewer_than(n)`
40
+ **Have the mock command invocation write to stdout:** `ShellMock.stub_command('ls').and_output("\n")`
30
41
 
31
- `less_than` is also an alias for `fewer_than`.
42
+ **Set the mock command invocation's exit status:** `ShellMock.stub_command('ls').and_exit(2)`
32
43
 
33
- Right now, only exact command string matches are supported.
44
+ If you want to both write to stdout and set the exit code (a common pair), `ShellMock.stub_command('ls').and_return("\n")` will both have the command invocation write the passed string to stdout, and will set the mock command invocation's exit status to `0`.
34
45
 
35
- ### You can also set the output of the command invocation:
46
+ ### Specifying the expected number of command invocations:
36
47
 
37
- ```ruby
38
- require 'shell_mock/rspec'
48
+ **Called exactly once:** `expect(stub).to have_been_called.once`
39
49
 
40
- describe 'something' do
41
- stub = ShellMock.stub_commmand('ls').and_return("\n")
50
+ **Not called:** `expect(stub).to have_been_called.never`
42
51
 
43
- expect(`ls`).to eq "\n"
52
+ **Not called (using RSpec expectation negation):** `expect(stub).to_not have_been_called`
44
53
 
45
- expect(stub).to have_been_called.once
46
- end
47
- ```
54
+ **Called exactly `n` times:** `expect(stub).to have_been_called.times(n)`
55
+
56
+ **Called more than `n` times:** `expect(stub).to have_been_called.more_than(n)`
57
+
58
+ **Called fewer than `n` times:** `expect(stub).to have_been_called.fewer_than(n)`
59
+
60
+ `less_than` can be used as an alias for `fewer_than`
61
+ ## Limitations
62
+
63
+ Currently, only exact string matches of the stubbed command string are supported. Basic regex support or more complex matching for arguments and flags may be added later.
64
+
65
+ ShellMock supports stubbing these ways of shelling out in Ruby:
66
+ * [`` Kernel#` ``](https://ruby-doc.org/core/Kernel.html#method-i-60) (aka "backticks")
67
+ * [`%x` command literal](https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#command) (which delegates to backticks)
68
+ * [`Kernel#system`](https://ruby-doc.org/core/Kernel.html#method-i-system)
69
+ * [`Kernel#exec`](https://ruby-doc.org/core/Kernel.html#method-i-exec)
70
+ * [`Kernel#spawn`](https://ruby-doc.org/core/Kernel.html#method-i-spawn)
71
+ * [`Process.spawn`](https://ruby-doc.org/core/Process.html#method-c-spawn)
72
+ * [the `Open3` module](https://ruby-doc.org/stdlib/libdoc/open3/rdoc/Open3.html) (since all its methods use `spawn`)
73
+
74
+ ShellMock currently DOES NOT support stubbing these ways of shelling out in Ruby (but will):
75
+ * [`IO.popen`](https://ruby-doc.org/core/IO.html#method-c-popen)
76
+ * [`PTY.spawn`](https://ruby-doc.org/stdlib/libdoc/pty/rdoc/PTY.html#method-c-spawn)
77
+ * [passing a string that starts with `"|"`](https://devver.wordpress.com/2009/07/13/a-dozen-or-so-ways-to-start-sub-processes-in-ruby-part-2/) to [`Kernel#open`](https://ruby-doc.org/core/Kernel.html#method-i-open)
48
78
 
49
79
  ## Installation
50
80
 
data/lib/shell_mock.rb CHANGED
@@ -24,32 +24,39 @@ module ShellMock
24
24
  @let_commands_run
25
25
  end
26
26
 
27
+ # smell; this is a mistake of a method that will only confuse people
27
28
  def self.dont_let_commands_run?
28
29
  !let_commands_run?
29
30
  end
30
31
 
31
32
  def self.enable
32
- ShellMock.monkey_patches.each do |patch|
33
- patch.enable_for(Kernel.eigenclass) unless Kernel.respond_to?(patch.alias_for_original, true)
34
- patch.enable_for(Kernel) unless Object.new.respond_to?(patch.alias_for_original, true)
35
- end
33
+ ShellMock.monkey_patches.each(&:enable)
34
+
35
+ @enabled = true
36
+
37
+ true
36
38
  end
37
39
 
38
40
  def self.disable
39
- ShellMock.monkey_patches.each do |patch|
40
- patch.disable_for(Kernel.eigenclass) if Kernel.respond_to?(patch.alias_for_original, true)
41
- patch.disable_for(Kernel) if Object.new.respond_to?(patch.alias_for_original, true)
42
- end
41
+ ShellMock.monkey_patches.each(&:disable)
43
42
 
44
43
  StubRegistry.clear
44
+
45
+ @enabled = false
46
+
47
+ true
48
+ end
49
+
50
+ def self.enabled?
51
+ @enabled
45
52
  end
46
53
 
47
54
  def self.monkey_patches
48
- [
49
- SpawnMonkeyPatch,
50
- SystemMonkeyPatch,
51
- ExecMonkeyPatch,
52
- BacktickMonkeyPatch
55
+ @monkey_patches ||= [
56
+ SpawnMonkeyPatch.new,
57
+ SystemMonkeyPatch.new,
58
+ ExecMonkeyPatch.new,
59
+ BacktickMonkeyPatch.new,
53
60
  ]
54
61
  end
55
62
  end
@@ -0,0 +1,33 @@
1
+ require 'shell_mock/monkey_patch'
2
+ require 'shell_mock/stub_registry'
3
+ require 'shell_mock/no_stub_specified'
4
+
5
+ module ShellMock
6
+ class BacktickMonkeyPatch < MonkeyPatch
7
+ def method_name
8
+ "`"
9
+ end
10
+
11
+ def interpolatable_name
12
+ :backtick
13
+ end
14
+
15
+ def override(command)
16
+ stub = StubRegistry.stub_matching({}, command, {})
17
+
18
+ if stub
19
+ stub.called_with({}, command, {})
20
+
21
+ stub.side_effect.call
22
+
23
+ __un_shell_mocked_backtick(stub.to_oneliner)
24
+ else
25
+ if ShellMock.let_commands_run?
26
+ __un_shell_mocked_backtick(command)
27
+ else
28
+ raise NoStubSpecified.new({}, command, {})
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,21 +1,26 @@
1
1
  module ShellMock
2
2
  class CallVerifier
3
3
  def initialize
4
- match_calls_when { |calls| calls.any? }
4
+ more_than(0)
5
5
  end
6
6
 
7
- def matches?(actual)
8
- @actual = actual
7
+ def times(n)
8
+ match_calls_when { |calls| calls == n }
9
9
 
10
- condition.call(actual.calls)
10
+ self
11
11
  end
12
12
 
13
- def failure_message
14
- "#{actual.command} was expected."
13
+ def fewer_than(n)
14
+ match_calls_when { |calls| calls < n }
15
+
16
+ self
15
17
  end
18
+ alias less_than fewer_than
16
19
 
17
- def failure_message_when_negated
18
- "#{actual.command} was not expected."
20
+ def more_than(n)
21
+ match_calls_when { |calls| calls > n }
22
+
23
+ self
19
24
  end
20
25
 
21
26
  def once
@@ -26,28 +31,23 @@ module ShellMock
26
31
  times(0)
27
32
  end
28
33
 
29
- def times(n)
30
- match_calls_when { |calls| calls.size == n }
34
+ def matches?(command_stub)
35
+ @command_stub = command_stub
31
36
 
32
- self
37
+ condition.call(command_stub.calls)
33
38
  end
34
39
 
35
- def fewer_than(n)
36
- match_calls_when { |calls| calls.size < n }
37
-
38
- self
40
+ def failure_message
41
+ "#{command_stub.command} was expected."
39
42
  end
40
- alias less_than fewer_than
41
-
42
- def more_than(n)
43
- match_calls_when { |calls| calls.size > n }
44
43
 
45
- self
44
+ def failure_message_when_negated
45
+ "#{command_stub.command} was not expected."
46
46
  end
47
47
 
48
48
  private
49
49
 
50
- attr_reader :actual, :condition
50
+ attr_reader :command_stub, :condition
51
51
 
52
52
  def match_calls_when(&blk)
53
53
  @condition = blk
@@ -3,7 +3,7 @@ require 'shell_mock/stub_registry'
3
3
 
4
4
  module ShellMock
5
5
  class CommandStub
6
- attr_reader :command, :expected_output, :exitstatus, :env, :options, :side_effect, :writer
6
+ attr_reader :command, :output, :exitstatus, :env, :options, :side_effect
7
7
 
8
8
  def initialize(command)
9
9
  @command = command
@@ -21,19 +21,24 @@ module ShellMock
21
21
  self
22
22
  end
23
23
 
24
- def with_option(option)
24
+ def with_options(options)
25
25
  @options = options
26
26
 
27
27
  self
28
28
  end
29
29
 
30
- def and_return(expected_output)
31
- @expected_output = expected_output
32
- @exitstatus = 0
30
+ def and_output(output)
31
+ @output = output
33
32
 
34
33
  self
35
34
  end
36
35
 
36
+ def and_return(output)
37
+ self.
38
+ and_output(output).
39
+ and_exit(0)
40
+ end
41
+
37
42
  def and_exit(exitstatus)
38
43
  @exitstatus = exitstatus
39
44
 
@@ -41,24 +46,26 @@ module ShellMock
41
46
  end
42
47
 
43
48
  def calls
44
- @calls ||= []
49
+ @calls ||= 0
45
50
 
46
51
  marshaled_signatures.each do |marshaled_signature|
47
- @calls << Marshal.load(marshaled_signature)
52
+ @calls += 1
48
53
  end
49
54
 
50
55
  @calls
51
56
  end
52
57
 
53
58
  def called_with(env, command, options)
54
- signature = Marshal.dump([env, command, options])
59
+ writer.puts("called\n")
60
+ end
55
61
 
56
- writer.puts(signature)
62
+ def to_oneliner
63
+ "echo '#{output}' && exit #{exitstatus}"
57
64
  end
58
65
 
59
66
  private
60
67
 
61
- attr_reader :reader
68
+ attr_reader :reader, :writer
62
69
 
63
70
  def marshaled_signatures
64
71
  messages = ""
@@ -0,0 +1,33 @@
1
+ require 'shell_mock/monkey_patch'
2
+ require 'shell_mock/stub_registry'
3
+ require 'shell_mock/no_stub_specified'
4
+
5
+ module ShellMock
6
+ class ExecMonkeyPatch < MonkeyPatch
7
+ def method_name
8
+ :exec
9
+ end
10
+
11
+ def override(env, command = nil, **options)
12
+ env, command = {}, env if command.nil?
13
+
14
+ # other arg manipulation can go here if necessary
15
+
16
+ stub = StubRegistry.stub_matching(env, command, options)
17
+
18
+ if stub
19
+ stub.called_with(env, command, options)
20
+
21
+ stub.side_effect.call
22
+
23
+ __un_shell_mocked_exec(stub.to_oneliner)
24
+ else
25
+ if ShellMock.let_commands_run?
26
+ __un_shell_mocked_exec(env, command, **options)
27
+ else
28
+ raise NoStubSpecified.new(env, command, options)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,42 +2,49 @@ require 'shell_mock/no_stub_specified'
2
2
 
3
3
  module ShellMock
4
4
  class MonkeyPatch
5
- attr_reader :original, :alias_for_original
5
+ def enable
6
+ enable_for(Kernel.eigenclass) unless Kernel.respond_to?(method_alias, true)
7
+ enable_for(Kernel) unless Object.new.respond_to?(method_alias, true)
8
+ end
9
+
10
+ def disable
11
+ disable_for(Kernel.eigenclass) if Kernel.respond_to?(method_alias, true)
12
+ disable_for(Kernel) if Object.new.respond_to?(method_alias, true)
13
+ end
14
+
15
+ private
6
16
 
7
- def initialize(original_name, interpolatable_name = original_name, &block)
8
- @original = original_name
9
- @alias_for_original = "__un_shell_mocked_#{interpolatable_name}"
10
- @replacement = "__shell_mocked_#{interpolatable_name}"
11
- @block = block
17
+ def method_alias
18
+ "__un_shell_mocked_#{interpolatable_name}"
12
19
  end
13
20
 
14
- def to_proc
15
- @block.to_proc
21
+ def interpolatable_name
22
+ method_name
16
23
  end
17
24
 
18
25
  def enable_for(class_or_module)
19
- class_or_module.send(:alias_method, alias_for_original, original)
26
+ class_or_module.send(:alias_method, method_alias, method_name)
20
27
 
21
28
  begin
22
29
  # so we don't have to see method redefinition warnings
23
- class_or_module.send(:remove_method, original)
30
+ class_or_module.send(:remove_method, method_name)
24
31
  rescue NameError
25
32
  end
26
33
 
27
- class_or_module.send(:define_method, original, &to_proc)
34
+ class_or_module.send(:define_method, method_name, &method(:override))
28
35
  end
29
36
 
30
37
  def disable_for(class_or_module)
31
38
  begin
32
39
  # so we don't have to see method redefinition warnings
33
- class_or_module.send(:remove_method, original)
40
+ class_or_module.send(:remove_method, method_name)
34
41
  rescue NameError
35
42
  end
36
43
 
37
- class_or_module.send(:alias_method, original, alias_for_original)
44
+ class_or_module.send(:alias_method, method_name, method_alias)
38
45
 
39
46
  begin
40
- class_or_module.send(:remove_method, alias_for_original)
47
+ class_or_module.send(:remove_method, method_alias)
41
48
  rescue NameError
42
49
  end
43
50
  end
@@ -1,91 +1,4 @@
1
- require 'shell_mock/monkey_patch'
2
- require 'shell_mock/stub_registry'
3
- require 'shell_mock/no_stub_specified'
4
-
5
- module ShellMock
6
- SpawnMonkeyPatch = MonkeyPatch.new(:spawn) do |env, command = nil, **options|
7
- env, command = {}, env if command.nil?
8
-
9
- # other arg manipulation can go here if necessary
10
-
11
- stub = StubRegistry.stub_matching(env, command, options)
12
-
13
- if stub
14
- stub.side_effect.call
15
- stub.called_with(env, command, options)
16
-
17
- __un_shell_mocked_spawn("exit #{stub.exitstatus}")
18
- else
19
- if ShellMock.let_commands_run?
20
- __un_shell_mocked_spawn(env, command, **options)
21
- else
22
- raise NoStubSpecified.new(env, command, options)
23
- end
24
- end
25
- end
26
-
27
- SystemMonkeyPatch = MonkeyPatch.new(:system) do |env, command = nil, **options|
28
- env, command = {}, env if command.nil?
29
-
30
- # other arg manipulation can go here if necessary
31
-
32
- stub = StubRegistry.stub_matching(env, command, options)
33
-
34
- if stub
35
- stub.side_effect.call
36
- stub.called_with(env, command, options)
37
- __un_shell_mocked_backtick("exit #{stub.exitstatus}")
38
-
39
- return stub.exitstatus == 0
40
- else
41
- if ShellMock.let_commands_run?
42
- __un_shell_mocked_system(env, command, **options)
43
- else
44
- raise NoStubSpecified.new(env, command, options)
45
- end
46
- end
47
- end
48
-
49
- # This feels very boilerplatey because Kernel::system and Kernel::exec
50
- # have very similar if not identical method signatures. I'm not sure
51
- # whether extracting the commonalities would be worth it or would just
52
- # confuse.
53
- ExecMonkeyPatch = MonkeyPatch.new(:exec) do |env, command = nil, **options|
54
- env, command = {}, env if command.nil?
55
-
56
- # other arg manipulation can go here if necessary
57
-
58
- stub = StubRegistry.stub_matching(env, command, options)
59
-
60
- if stub
61
- stub.side_effect.call
62
- stub.called_with(env, command, options)
63
-
64
- exit stub.exitstatus
65
- else
66
- if ShellMock.let_commands_run?
67
- __un_shell_mocked_exec(env, command, **options)
68
- else
69
- raise NoStubSpecified.new(env, command, options)
70
- end
71
- end
72
- end
73
-
74
- BacktickMonkeyPatch = MonkeyPatch.new('`', :backtick) do |command|
75
- stub = StubRegistry.stub_matching({}, command, {})
76
-
77
- if stub
78
- stub.side_effect.call
79
- stub.called_with({}, command, {})
80
- __un_shell_mocked_backtick("exit #{stub.exitstatus}")
81
-
82
- return stub.expected_output
83
- else
84
- if ShellMock.let_commands_run?
85
- __un_shell_mocked_backtick(command)
86
- else
87
- raise NoStubSpecified.new({}, command, {})
88
- end
89
- end
90
- end
91
- end
1
+ require 'shell_mock/spawn_monkey_patch'
2
+ require 'shell_mock/system_monkey_patch'
3
+ require 'shell_mock/backtick_monkey_patch'
4
+ require 'shell_mock/exec_monkey_patch'
@@ -0,0 +1,45 @@
1
+ require 'shell_mock/monkey_patch'
2
+ require 'shell_mock/stub_registry'
3
+ require 'shell_mock/no_stub_specified'
4
+
5
+ module ShellMock
6
+ class SpawnMonkeyPatch < MonkeyPatch
7
+ def method_name
8
+ :spawn
9
+ end
10
+
11
+ def override(env, command = nil, **options)
12
+ env, command = {}, env if command.nil?
13
+
14
+ # other arg manipulation can go here if necessary
15
+
16
+ stub = StubRegistry.stub_matching(env, command, options)
17
+
18
+ if stub
19
+ stub.called_with(env, command, options)
20
+
21
+ stub.side_effect.call
22
+
23
+ __un_shell_mocked_spawn(stub.to_oneliner, **options)
24
+ else
25
+ if ShellMock.let_commands_run?
26
+ __un_shell_mocked_spawn(env, command, **options)
27
+ else
28
+ raise NoStubSpecified.new(env, command, options)
29
+ end
30
+ end
31
+ end
32
+
33
+ def enable
34
+ enable_for(Process.eigenclass) unless Process.respond_to?(method_alias, true)
35
+
36
+ super
37
+ end
38
+
39
+ def disable
40
+ super
41
+
42
+ disable_for(Process.eigenclass) if Process.respond_to?(method_alias, true)
43
+ end
44
+ end
45
+ end
@@ -9,11 +9,14 @@ module ShellMock
9
9
 
10
10
  def stub_matching(env, command, options)
11
11
  matching_stubs = command_stubs.select do |command_stub|
12
- command_stub.env <= env &&
13
- command_stub.options <= options &&
14
- command_stub.command == command
12
+ command_stub.command == command &&
13
+ command_stub.env <= env &&
14
+ command_stub.options <= options
15
15
  end
16
16
 
17
+ # question: Should we increment all the stubs that match?
18
+ # What should users expect when they register a stub that
19
+ # wholly "covers" another already-registered stub?
17
20
  matching_stubs.max_by do |command_stub|
18
21
  [env.size, options.size]
19
22
  end
@@ -0,0 +1,33 @@
1
+ require 'shell_mock/monkey_patch'
2
+ require 'shell_mock/stub_registry'
3
+ require 'shell_mock/no_stub_specified'
4
+
5
+ module ShellMock
6
+ class SystemMonkeyPatch < MonkeyPatch
7
+ def method_name
8
+ :system
9
+ end
10
+
11
+ def override(env, command = nil, **options)
12
+ env, command = {}, env if command.nil?
13
+
14
+ # other arg manipulation can go here if necessary
15
+
16
+ stub = StubRegistry.stub_matching(env, command, options)
17
+
18
+ if stub
19
+ stub.called_with(env, command, options)
20
+
21
+ stub.side_effect.call
22
+
23
+ __un_shell_mocked_system(stub.to_oneliner)
24
+ else
25
+ if ShellMock.let_commands_run?
26
+ __un_shell_mocked_system(env, command, **options)
27
+ else
28
+ raise NoStubSpecified.new(env, command, options)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module ShellMock
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shell_mock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hoffman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-18 00:00:00.000000000 Z
11
+ date: 2018-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,15 +114,19 @@ files:
114
114
  - bin/console
115
115
  - bin/setup
116
116
  - lib/shell_mock.rb
117
+ - lib/shell_mock/backtick_monkey_patch.rb
117
118
  - lib/shell_mock/call_verifier.rb
118
119
  - lib/shell_mock/command_stub.rb
119
120
  - lib/shell_mock/core_ext/module.rb
121
+ - lib/shell_mock/exec_monkey_patch.rb
120
122
  - lib/shell_mock/monkey_patch.rb
121
123
  - lib/shell_mock/monkey_patches.rb
122
124
  - lib/shell_mock/no_stub_specified.rb
123
125
  - lib/shell_mock/rspec.rb
124
126
  - lib/shell_mock/rspec/matchers.rb
127
+ - lib/shell_mock/spawn_monkey_patch.rb
125
128
  - lib/shell_mock/stub_registry.rb
129
+ - lib/shell_mock/system_monkey_patch.rb
126
130
  - lib/shell_mock/version.rb
127
131
  - shell_mock.gemspec
128
132
  homepage: http://www.github.com/yarmiganosca/shell_mock