rspec-bash 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/.travis.yml +1 -0
  4. data/Gemfile +4 -4
  5. data/README.md +87 -77
  6. data/Rakefile +1 -1
  7. data/bin/function_override_wrapper.sh.erb +6 -3
  8. data/bin/stub.rb.erb +56 -0
  9. data/lib/rspec/bash.rb +1 -0
  10. data/lib/rspec/bash/call_configuration.rb +39 -14
  11. data/lib/rspec/bash/call_log.rb +33 -43
  12. data/lib/rspec/bash/matchers/called_with_arguments.rb +7 -2
  13. data/lib/rspec/bash/stubbed_command.rb +22 -14
  14. data/lib/rspec/bash/stubbed_env.rb +15 -16
  15. data/lib/rspec/bash/util.rb +2 -0
  16. data/lib/rspec/bash/util/call_conf_argument_list_matcher.rb +47 -0
  17. data/lib/rspec/bash/util/call_log_argument_list_matcher.rb +33 -0
  18. data/return_exitstatus_spec.rb +14 -0
  19. data/rspec-bash.gemspec +2 -3
  20. data/spec/classes/call_configuration_spec.rb +296 -8
  21. data/spec/classes/call_log_spec.rb +168 -272
  22. data/spec/classes/stub_spec.rb +510 -0
  23. data/spec/classes/stubbed_command_spec.rb +26 -26
  24. data/spec/classes/stubbed_env_spec.rb +58 -64
  25. data/spec/classes/util/call_conf_argument_list_matcher_spec.rb +579 -0
  26. data/spec/classes/util/call_log_argument_list_matcher_spec.rb +211 -0
  27. data/spec/helper/shared_tmpdir.rb +6 -0
  28. data/spec/helper/string_file_io.rb +9 -0
  29. data/spec/integration/call_log/called_with_args_spec.rb +48 -0
  30. data/spec/integration/call_log/called_with_no_args_spec.rb +21 -0
  31. data/spec/integration/call_log/stdin_spec.rb +53 -0
  32. data/spec/integration/matchers/be_called_with_arguments_spec.rb +60 -0
  33. data/spec/integration/matchers/be_called_with_no_arguments_spec.rb +35 -0
  34. data/spec/integration/stubbed_command/outputs_spec.rb +262 -0
  35. data/spec/integration/stubbed_command/returns_exitstatus_spec.rb +99 -0
  36. data/spec/integration/stubbed_env/execute_with_env_vars_spec.rb +17 -0
  37. data/spec/integration/stubbed_env/execute_with_path_spec.rb +34 -0
  38. data/spec/integration/stubbed_env/execute_with_stub_wrapper_spec.rb +23 -0
  39. data/spec/spec_helper.rb +10 -0
  40. metadata +42 -24
  41. data/bin/stub +0 -62
  42. data/spec/integration/assert_called_spec.rb +0 -48
  43. data/spec/integration/assert_stdin_spec.rb +0 -39
  44. data/spec/integration/chain_args_spec.rb +0 -65
  45. data/spec/integration/change_exitstatus_spec.rb +0 -53
  46. data/spec/integration/provide_env_vars_spec.rb +0 -31
  47. data/spec/integration/replace_shell_commands_spec.rb +0 -48
  48. data/spec/integration/stub_output_spec.rb +0 -110
  49. data/spec/matchers/be_called_with_arguments_spec.rb +0 -55
  50. data/spec/matchers/be_called_with_no_arguments_spec.rb +0 -32
@@ -1,6 +1,5 @@
1
1
  module Rspec
2
2
  module Bash
3
- # Log of calls to a command
4
3
  class CallLog
5
4
  def initialize(call_log_path)
6
5
  @call_log_path = call_log_path
@@ -10,68 +9,59 @@ module Rspec
10
9
  @call_log_path.exist?
11
10
  end
12
11
 
13
- def called_with_args?(*args)
14
- call_count(*args) > 0
12
+ def stdin_for_args(*argument_list)
13
+ call_argument_list_matcher = Util::CallLogArgumentListMatcher.new(*argument_list)
14
+ matching_call_log_list = call_argument_list_matcher.get_call_log_matches(call_log)
15
+ matching_call_log_list.first[:stdin] unless matching_call_log_list.empty?
15
16
  end
16
17
 
17
- def stdin_for_args(*args)
18
- call = find_call(*args)
19
- call['stdin'] unless call.nil?
18
+ def call_count(*argument_list)
19
+ call_argument_list_matcher = Util::CallLogArgumentListMatcher.new(*argument_list)
20
+ call_argument_list_matcher.get_call_count(call_log)
20
21
  end
21
22
 
22
- def call_count(*expected_argument_series)
23
- get_call_log_args.count do |actual_argument_series|
24
- argument_series_contains?(actual_argument_series, expected_argument_series || [])
25
- end
23
+ def called_with_args?(*argument_list)
24
+ call_argument_list_matcher = Util::CallLogArgumentListMatcher.new(*argument_list)
25
+ call_argument_list_matcher.args_match?(call_log)
26
26
  end
27
27
 
28
28
  def called_with_no_args?
29
- call_log_list = load_call_log_list
30
- !call_log_list.empty? && call_log_list.first['args'].nil?
31
- end
29
+ return false if call_log.empty?
32
30
 
33
- private
34
-
35
- def find_call(*args)
36
- load_call_log_list.find do |call|
37
- call_args = call['args'] || []
38
- (args - call_args).empty?
31
+ call_log.all? do |call_log|
32
+ argument_list = call_log[:args] || []
33
+ argument_list.empty?
39
34
  end
40
35
  end
41
36
 
42
- def get_position_range_from_argument_list(argument_list, range_start_position, range_length)
43
- argument_list.map do |argument_series|
44
- range_start_position ? argument_series[range_start_position, range_length] : argument_series
45
- end
37
+ def add_log(stdin, argument_list)
38
+ updated_log = call_log
39
+ updated_log << {
40
+ args: argument_list,
41
+ stdin: stdin
42
+ }
43
+ write updated_log
46
44
  end
47
45
 
48
- def get_call_log_args
49
- load_call_log_list.map { |call_log| call_log["args"] || [] }.compact
46
+ def call_log
47
+ @call_log_path.open('r') do |call_log|
48
+ YAML.load(call_log.read) || []
49
+ end
50
+ rescue NoMethodError, Errno::ENOENT
51
+ return []
50
52
  end
51
53
 
52
- def argument_series_contains?(actual_argument_series, expected_argument_series)
53
- ensure_wildcards_match(actual_argument_series, expected_argument_series)
54
- expected_argument_series.empty? || (actual_argument_series == expected_argument_series)
54
+ def call_log=(new_log)
55
+ write new_log
55
56
  end
56
57
 
57
- def ensure_wildcards_match(actual_argument_series, expected_argument_series)
58
- # yes, i know. i am disappointed in myself
59
- num_of_args = actual_argument_series.size
60
- expected_argument_series.zip((0..num_of_args), actual_argument_series) do |expected_arg, index, _actual_arg|
61
- if expected_arg.is_a? RSpec::Mocks::ArgumentMatchers::AnyArgMatcher
62
- actual_argument_series[index] = expected_arg
63
- end
64
- end
65
- end
58
+ private
66
59
 
67
- def load_call_log_list
68
- begin
69
- YAML.load_file @call_log_path
70
- rescue Errno::ENOENT
71
- return []
60
+ def write(call_log_to_write)
61
+ @call_log_path.open('w') do |call_log|
62
+ call_log.write call_log_to_write.to_yaml
72
63
  end
73
64
  end
74
-
75
65
  end
76
66
  end
77
67
  end
@@ -4,10 +4,15 @@ RSpec::Matchers.define :be_called_with_arguments do |*expected_argument_list|
4
4
  chain :times do |expected_invocations|
5
5
  @expected_invocations = expected_invocations
6
6
  end
7
-
7
+
8
8
  match do |actual_command|
9
9
  called_with_correct_args = actual_command.called_with_args?(*expected_argument_list)
10
- called_correct_number_of_times = @expected_invocations ? actual_command.call_count(*expected_argument_list) == @expected_invocations : true
10
+ if @expected_invocations
11
+ called_correct_number_of_times =
12
+ actual_command.call_count(*expected_argument_list) == @expected_invocations
13
+ else
14
+ called_correct_number_of_times = true
15
+ end
11
16
 
12
17
  called_with_correct_args && called_correct_number_of_times
13
18
  end
@@ -1,11 +1,10 @@
1
1
  module Rspec
2
2
  module Bash
3
3
  class StubbedCommand
4
- attr_reader :call_log, :arguments
4
+ attr_reader :call_log, :arguments, :path
5
5
 
6
6
  def initialize(command, dir)
7
- command_path = File.join(dir, command)
8
- FileUtils.cp(stub_filepath, command_path)
7
+ @path = create_stub_file(command, dir)
9
8
  @arguments = []
10
9
  @call_configuration = CallConfiguration.new(
11
10
  Pathname.new(dir).join("#{command}_stub.yml"),
@@ -37,22 +36,20 @@ module Rspec
37
36
  @call_log.call_count(*arg)
38
37
  end
39
38
 
40
- def returns_exitstatus(statuscode)
41
- @call_configuration.set_exitcode(statuscode, @arguments)
42
- @call_configuration.write
39
+ def returns_exitstatus(exitcode)
40
+ @call_configuration.set_exitcode(exitcode, @arguments)
43
41
  self
44
42
  end
45
43
 
46
- def stdin
47
- @call_log.stdin_for_args(*@arguments) if @call_log.exist?
48
- end
49
-
50
44
  def outputs(contents, to: :stdout)
51
- @call_configuration.set_output(contents, to, @arguments)
52
- @call_configuration.write
45
+ @call_configuration.add_output(contents, to, @arguments)
53
46
  self
54
47
  end
55
48
 
49
+ def stdin
50
+ @call_log.stdin_for_args(*@arguments) if @call_log.exist?
51
+ end
52
+
56
53
  def inspect
57
54
  if @arguments.any?
58
55
  "<Stubbed #{@call_configuration.command.inspect} " \
@@ -64,8 +61,19 @@ module Rspec
64
61
 
65
62
  private
66
63
 
67
- def stub_filepath
68
- project_root.join('bin', 'stub')
64
+ def create_stub_file(command_name, directory)
65
+ command_path = File.join(directory, command_name)
66
+
67
+ stub_template_path = File.expand_path(
68
+ 'stub.rb.erb', "#{File.dirname(__FILE__)}/../../../bin"
69
+ )
70
+ template = ERB.new File.read(stub_template_path), nil, '%'
71
+ rspec_bash_library_path_for_template = project_root.join('lib')
72
+ stub_content = template.result(binding)
73
+ File.open(command_path, 'w') { |file| file.write(stub_content) }
74
+ File.chmod(0755, command_path)
75
+
76
+ command_path
69
77
  end
70
78
 
71
79
  def project_root
@@ -16,13 +16,10 @@ module Rspec
16
16
 
17
17
  def initialize
18
18
  @dir = Dir.mktmpdir
19
- ENV['PATH'] = "#{@dir}:#{ENV['PATH']}"
20
19
  at_exit { cleanup }
21
20
  end
22
21
 
23
22
  def cleanup
24
- paths = (ENV['PATH'].split ':') - [@dir]
25
- ENV['PATH'] = paths.join ':'
26
23
  FileUtils.remove_entry_secure @dir if Pathname.new(@dir).exist?
27
24
  end
28
25
 
@@ -32,19 +29,21 @@ module Rspec
32
29
  end
33
30
 
34
31
  def execute(command, env_vars = {})
35
- full_command = get_wrapped_execution_with_function_overrides(<<-multiline_script
36
- #{env} source #{command}
37
- multiline_script
32
+ full_command = get_wrapped_execution_with_function_overrides(
33
+ <<-multiline_script
34
+ source #{command}
35
+ multiline_script
38
36
  )
39
37
 
40
38
  Open3.capture3(env_vars, full_command)
41
39
  end
42
40
 
43
41
  def execute_function(script, command, env_vars = {})
44
- full_command = get_wrapped_execution_with_function_overrides(<<-multiline_script
45
- source #{script}
46
- #{env} #{command}
47
- multiline_script
42
+ full_command = get_wrapped_execution_with_function_overrides(
43
+ <<-multiline_script
44
+ source #{script}
45
+ #{command}
46
+ multiline_script
48
47
  )
49
48
 
50
49
  Open3.capture3(env_vars, full_command)
@@ -63,7 +62,9 @@ module Rspec
63
62
  function_command_path_binding_for_template = File.join(@dir, command)
64
63
 
65
64
  function_override_file_path = File.join(@dir, "#{command}_overrides.sh")
66
- function_override_file_template = ERB.new File.new(function_override_template_path).read, nil, '%'
65
+ function_override_file_template = ERB.new(
66
+ File.new(function_override_template_path).read, nil, '%'
67
+ )
67
68
  function_override_file_content = function_override_file_template.result(binding)
68
69
 
69
70
  File.write(function_override_file_path, function_override_file_content)
@@ -74,15 +75,13 @@ module Rspec
74
75
  function_override_path_binding_for_template = "#{@dir}/*_overrides.sh"
75
76
  wrapped_error_path_binding_for_template = "#{@dir}/errors"
76
77
 
77
- function_override_wrapper_template = ERB.new File.new(function_override_wrapper_template_path).read, nil, '%'
78
+ function_override_wrapper_template = ERB.new(
79
+ File.new(function_override_wrapper_template_path).read, nil, '%'
80
+ )
78
81
 
79
82
  function_override_wrapper_template.result(binding)
80
83
  end
81
84
 
82
- def env
83
- "PATH=#{@dir}:$PATH"
84
- end
85
-
86
85
  def function_override_template_path
87
86
  project_root.join('bin', 'function_override.sh.erb')
88
87
  end
@@ -0,0 +1,2 @@
1
+ require 'rspec/bash/util/call_log_argument_list_matcher'
2
+ require 'rspec/bash/util/call_conf_argument_list_matcher'
@@ -0,0 +1,47 @@
1
+ require 'rspec/mocks/argument_list_matcher'
2
+ include RSpec::Mocks
3
+ include RSpec::Mocks::ArgumentMatchers
4
+
5
+ module Rspec
6
+ module Bash
7
+ module Util
8
+ class CallConfArgumentListMatcher < ArgumentListMatcher
9
+ alias parent_args_match? args_match?
10
+ alias parent_initialize initialize
11
+
12
+ def initialize(call_conf_list)
13
+ @expected_call_conf_list = call_conf_list
14
+ end
15
+
16
+ def args_match?(*call_arguments)
17
+ !get_call_conf_matches(*call_arguments).empty?
18
+ end
19
+
20
+ def get_best_call_conf(*call_arguments)
21
+ get_call_conf_matches(*call_arguments).sort_by do |call_conf|
22
+ [
23
+ call_conf[:args].length
24
+ ]
25
+ end.last || {}
26
+ end
27
+
28
+ def get_call_conf_matches(*call_arguments)
29
+ @expected_call_conf_list.select do |expected_call_conf|
30
+ @expected_args = remap_argument_matchers(expected_call_conf[:args])
31
+ parent_args_match?(*call_arguments)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def remap_argument_matchers(expected_call_conf_args)
38
+ expected_call_conf_args.map! do |expected_arg|
39
+ next expected_arg unless expected_arg.is_a?(ArgumentMatchers::SingletonMatcher)
40
+ Object.const_get("#{expected_arg.class}::INSTANCE")
41
+ end
42
+ expected_call_conf_args.empty? ? [any_args] : expected_call_conf_args
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ require 'rspec/mocks/argument_list_matcher'
2
+ include RSpec::Mocks
3
+ include RSpec::Mocks::ArgumentMatchers
4
+
5
+ module Rspec
6
+ module Bash
7
+ module Util
8
+ class CallLogArgumentListMatcher < ArgumentListMatcher
9
+ alias parent_args_match? args_match?
10
+ alias parent_initialize initialize
11
+
12
+ def initialize(*expected_args)
13
+ expected_args = expected_args.empty? ? [any_args] : expected_args
14
+ parent_initialize(*expected_args)
15
+ end
16
+
17
+ def args_match?(actual_call_log_list)
18
+ get_call_count(actual_call_log_list) > 0
19
+ end
20
+
21
+ def get_call_count(actual_call_log_list)
22
+ get_call_log_matches(actual_call_log_list).size
23
+ end
24
+
25
+ def get_call_log_matches(actual_call_log_list)
26
+ actual_call_log_list.select do |actual_call_list|
27
+ parent_args_match?(*actual_call_list[:args])
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ require 'English'
2
+ require 'rspec/bash'
3
+
4
+ describe 'very simple script that just exits' do
5
+ include Rspec::Bash
6
+ let(:stubbed_env) { create_stubbed_env }
7
+ it 'returns an exit status of 0' do
8
+ out, err, rv = stubbed_env.execute_inline('exit 0')
9
+
10
+ expect(out).to eql ''
11
+ expect(err).to eql ''
12
+ expect(rv.exitstatus).to eql 0
13
+ end
14
+ end
@@ -4,13 +4,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'rspec-bash'
7
- spec.version = '0.0.3'
7
+ spec.version = '0.1.0'
8
8
  spec.authors = ['Ben Brewer', 'Mike Urban', 'Matthijs Groen']
9
9
  spec.email = ['ben@benbrewer.me', 'mike.david.urban@gmail.com']
10
10
  spec.summary = 'Test Bash with RSpec'
11
11
  spec.description = <<-DESCRIPTION
12
- Stub and mock Bash commands
13
- Verify Bash calls and outputs
12
+ Test Bash scripts through stubbing and mocking Bash commands
14
13
  DESCRIPTION
15
14
  spec.homepage = 'https://github.com/mdurban/rspec-bash'
16
15
  spec.license = 'MIT'
@@ -1,21 +1,309 @@
1
- require 'rspec/bash'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'CallConfiguration' do
4
4
  let(:stubbed_env) { create_stubbed_env }
5
5
  include Rspec::Bash
6
6
 
7
+ let(:mock_conf_file) { StringFileIO.new }
8
+ let(:mock_conf_pathname) { instance_double(Pathname) }
9
+ before(:each) do
10
+ allow(mock_conf_pathname).to receive(:open).with('r').and_yield(mock_conf_file)
11
+ allow(mock_conf_pathname).to receive(:open).with('w').and_yield(mock_conf_file)
12
+ end
13
+
7
14
  context '#set_exitcode' do
8
- it 'returns the status code that is provided' do
9
- @subject = Rspec::Bash::CallConfiguration.new(anything, anything)
15
+ context 'with any setup' do
16
+ subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
17
+
18
+ context 'with no existing configuration' do
19
+ let(:expected_conf) do
20
+ [
21
+ {
22
+ args: %w(first_argument second_argument),
23
+ exitcode: 1,
24
+ outputs: []
25
+ }
26
+ ]
27
+ end
28
+
29
+ it 'updates the status code conf for the arguments passed in' do
30
+ subject.set_exitcode(1, %w(first_argument second_argument))
31
+ expect(subject.call_configuration).to eql expected_conf
32
+ end
33
+
34
+ it 'writes that configuration to its conf file' do
35
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
36
+ subject.set_exitcode(1, %w(first_argument second_argument))
37
+ end
38
+ end
39
+ context 'with an existing, non-matching configuration' do
40
+ let(:expected_conf) do
41
+ [
42
+ {
43
+ args: %w(first_argument),
44
+ exitcode: 1,
45
+ outputs: []
46
+ },
47
+ {
48
+
49
+ args: %w(first_argument second_argument),
50
+ exitcode: 1,
51
+ outputs: []
52
+ }
53
+ ]
54
+ end
55
+ before(:each) do
56
+ subject.call_configuration = [
57
+ {
58
+ args: %w(first_argument),
59
+ exitcode: 1,
60
+ outputs: []
61
+ }
62
+ ]
63
+ end
64
+ it 'updates the status code conf for the arguments passed in' do
65
+ subject.set_exitcode(1, %w(first_argument second_argument))
66
+ expect(subject.call_configuration).to eql expected_conf
67
+ end
68
+
69
+ it 'writes that configuration to its conf file' do
70
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
71
+ subject.set_exitcode(1, %w(first_argument second_argument))
72
+ end
73
+ end
74
+ context 'with an existing, matching configuration' do
75
+ let(:expected_conf) do
76
+ [
77
+ {
78
+ args: %w(first_argument second_argument),
79
+ exitcode: 1,
80
+ outputs: []
81
+ }
82
+ ]
83
+ end
84
+ before(:each) do
85
+ subject.call_configuration = [
86
+ {
87
+ args: %w(first_argument second_argument),
88
+ exitcode: 2,
89
+ outputs: []
90
+ }
91
+ ]
92
+ end
93
+
94
+ it 'updates the status code conf for the arguments passed in' do
95
+ subject.set_exitcode(1, %w(first_argument second_argument))
96
+ expect(subject.call_configuration).to eql expected_conf
97
+ end
98
+
99
+ it 'writes that configuration to its conf file' do
100
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
101
+ subject.set_exitcode(1, %w(first_argument second_argument))
102
+ end
103
+ end
104
+ end
105
+ context 'with no config_path' do
106
+ subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
107
+ it 'raises an error' do
108
+ expect do
109
+ subject.set_exitcode(1, %w(first_argument second_argument))
110
+ end.to raise_exception(NoMethodError)
111
+ end
112
+ end
113
+ end
114
+ context '#add_output' do
115
+ context 'with any setup' do
116
+ subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
117
+
118
+ context 'with no existing configuration' do
119
+ let(:expected_conf) do
120
+ [
121
+ {
122
+ args: %w(first_argument second_argument),
123
+ exitcode: 0,
124
+ outputs: [
125
+ {
126
+ target: :stderr,
127
+ content: 'new_content'
128
+ }
129
+ ]
130
+ }
131
+ ]
132
+ end
133
+ it 'updates the outputs for the arguments passed in' do
134
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
135
+ expect(subject.call_configuration).to eql expected_conf
136
+ end
137
+
138
+ it 'writes that configuration to its conf file' do
139
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
140
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
141
+ end
142
+ end
143
+ context 'with an existing, non-matching configuration' do
144
+ let(:expected_conf) do
145
+ [
146
+ {
147
+ args: %w(first_argument),
148
+ exitcode: 1,
149
+ outputs: [
150
+ {
151
+ target: :stdout,
152
+ content: 'different_content'
153
+ }
154
+ ]
155
+ },
156
+ {
157
+ args: %w(first_argument second_argument),
158
+ exitcode: 0,
159
+ outputs: [
160
+ {
161
+ target: :stderr,
162
+ content: 'new_content'
163
+ }
164
+ ]
165
+ }
166
+ ]
167
+ end
168
+ before(:each) do
169
+ subject.call_configuration = [
170
+ {
171
+ args: %w(first_argument),
172
+ exitcode: 1,
173
+ outputs: [
174
+ {
175
+ target: :stdout,
176
+ content: 'different_content'
177
+ }
178
+ ]
179
+ }
180
+ ]
181
+ end
182
+ it 'updates the outputs conf for the arguments passed in' do
183
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
184
+ expect(subject.call_configuration).to eql expected_conf
185
+ end
186
+
187
+ it 'writes that configuration to its conf file' do
188
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
189
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
190
+ end
191
+ end
192
+ context 'with an existing, matching configuration' do
193
+ let(:expected_conf) do
194
+ [
195
+ {
196
+ args: %w(first_argument second_argument),
197
+ exitcode: 1,
198
+ outputs: [
199
+ {
200
+ target: :stdout,
201
+ content: 'old_content'
202
+ },
203
+ {
204
+ target: :stderr,
205
+ content: 'new_content'
206
+ }
207
+ ]
208
+ }
209
+ ]
210
+ end
211
+ before(:each) do
212
+ subject.call_configuration = [
213
+ {
214
+ args: %w(first_argument second_argument),
215
+ exitcode: 1,
216
+ outputs: [
217
+ {
218
+ target: :stdout,
219
+ content: 'old_content'
220
+ }
221
+ ]
222
+ }
223
+ ]
224
+ end
225
+ it 'adds to the outputs conf for the arguments passed in' do
226
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
227
+ expect(subject.call_configuration).to eql expected_conf
228
+ end
10
229
 
11
- expect(@subject.set_exitcode('status')).to eql 'status'
230
+ it 'writes that configuration to its conf file' do
231
+ expect(mock_conf_file).to receive(:write).with(expected_conf.to_yaml)
232
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
233
+ end
234
+ end
235
+ end
236
+ context 'with no config_path' do
237
+ subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
238
+ it 'raises an error' do
239
+ expect do
240
+ subject.add_output('new_content', :stderr, %w(first_argument second_argument))
241
+ end.to raise_exception(NoMethodError)
242
+ end
12
243
  end
13
244
  end
14
- context '#write' do
15
- it 'raises error when there is no config_path' do
16
- @subject = Rspec::Bash::CallConfiguration.new(nil, anything)
245
+ context '#call_configuration' do
246
+ context 'when there is no config_path' do
247
+ subject { Rspec::Bash::CallConfiguration.new(nil, anything) }
248
+ it 'returns an empty array' do
249
+ expect(subject.call_configuration).to eql []
250
+ end
251
+ end
252
+ context 'when the conf file exists but is empty' do
253
+ subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, anything) }
254
+ before(:each) do
255
+ allow(mock_conf_file).to receive(:read).and_return('')
256
+ end
257
+ it 'returns an empty array' do
258
+ expect(subject.call_configuration).to eql []
259
+ end
260
+ end
261
+ context 'when the call log file open throws a file not found exception' do
262
+ subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, anything) }
263
+ before(:each) do
264
+ allow(mock_conf_pathname).to receive(:open).with('r').and_raise(Errno::ENOENT)
265
+ end
266
+ it 'returns an empty array' do
267
+ expect(subject.call_configuration).to eql []
268
+ end
269
+ end
270
+ context 'when setup is valid' do
271
+ subject { Rspec::Bash::CallConfiguration.new(mock_conf_pathname, 'command_name') }
272
+ let(:conf) do
273
+ [{
274
+ args: %w(first_argument second_argument),
275
+ exitcode: 1,
276
+ outputs: [
277
+ {
278
+ target: :stdout,
279
+ content: 'old_content'
280
+ },
281
+ {
282
+ target: :stderr,
283
+ content: 'new_content'
284
+ }
285
+ ]
286
+ }]
287
+ end
288
+ context 'and no configuration exists' do
289
+ before(:each) do
290
+ allow(mock_conf_file).to receive(:read).and_return(conf.to_yaml)
291
+ allow(mock_conf_pathname).to receive(:open).with('r').and_yield(mock_conf_file)
292
+ end
293
+
294
+ it 'reads out what was in its configuration file' do
295
+ expect(subject.call_configuration).to eql conf
296
+ end
297
+ end
298
+ context 'and a configuration already exists' do
299
+ before(:each) do
300
+ subject.call_configuration = conf
301
+ end
17
302
 
18
- expect { @subject.write }.to raise_exception(NoMethodError)
303
+ it 'reads out what was in its configuration file' do
304
+ expect(subject.call_configuration).to eql conf
305
+ end
306
+ end
19
307
  end
20
308
  end
21
309
  end