chefspec 7.3.3 → 7.3.4

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +23 -0
  3. data/Rakefile +77 -0
  4. data/chefspec.gemspec +29 -0
  5. data/lib/chefspec/version.rb +1 -1
  6. data/spec/spec_helper.rb +13 -0
  7. data/spec/support/hash.rb +35 -0
  8. data/spec/unit/cacher_spec.rb +70 -0
  9. data/spec/unit/coverage/filters_spec.rb +60 -0
  10. data/spec/unit/deprecations_spec.rb +53 -0
  11. data/spec/unit/errors_spec.rb +57 -0
  12. data/spec/unit/expect_exception_spec.rb +32 -0
  13. data/spec/unit/macros_spec.rb +119 -0
  14. data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
  15. data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
  16. data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
  17. data/spec/unit/matchers/notifications_matcher_spec.rb +40 -0
  18. data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
  19. data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
  20. data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
  21. data/spec/unit/matchers/subscribes_matcher_spec.rb +65 -0
  22. data/spec/unit/renderer_spec.rb +69 -0
  23. data/spec/unit/server_runner_spec.rb +28 -0
  24. data/spec/unit/solo_runner_spec.rb +171 -0
  25. data/spec/unit/stubs/command_registry_spec.rb +27 -0
  26. data/spec/unit/stubs/command_stub_spec.rb +61 -0
  27. data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
  28. data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
  29. data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
  30. data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
  31. data/spec/unit/stubs/registry_spec.rb +29 -0
  32. data/spec/unit/stubs/search_registry_spec.rb +39 -0
  33. data/spec/unit/stubs/search_stub_spec.rb +36 -0
  34. data/spec/unit/stubs/stub_spec.rb +64 -0
  35. metadata +34 -2
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::ExpectException do
4
+ context 'when there have been no `raise_error` matchers' do
5
+ subject { described_class.new(Exception) }
6
+
7
+ it 'does not match' do
8
+ allow(RSpec::Matchers::BuiltIn::RaiseError).to receive(:last_run).and_return(nil)
9
+ expect(subject.expected?).to be_falsy
10
+ end
11
+ end
12
+
13
+ context 'when the last error does not match the expected type' do
14
+ subject { described_class.new(RuntimeError) }
15
+
16
+ it 'does not match' do
17
+ last_error = double('last error', last_error_for_chefspec: ArgumentError)
18
+ allow(RSpec::Matchers::BuiltIn::RaiseError).to receive(:last_run).and_return(last_error)
19
+ expect(subject.expected?).to be_falsy
20
+ end
21
+ end
22
+
23
+ context 'when the last error matches the expected type' do
24
+ subject { described_class.new(RuntimeError) }
25
+
26
+ it 'does not match' do
27
+ last_error = double('last error', last_error_for_chefspec: RuntimeError)
28
+ allow(RSpec::Matchers::BuiltIn::RaiseError).to receive(:last_run).and_return(last_error)
29
+ expect(subject.expected?).to be_truthy
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::API::Stubs do
4
+ describe '#stub_command' do
5
+ let(:command_stub) { double('command') }
6
+
7
+ it 'adds the command to the command registry' do
8
+ allow(ChefSpec::Stubs::CommandStub).to receive(:new).and_return(command_stub)
9
+ stub_command('echo "hello"')
10
+
11
+ expect(ChefSpec::Stubs::CommandRegistry.stubs).to include(command_stub)
12
+ end
13
+ end
14
+
15
+ describe '#stub_search' do
16
+ let(:search_stub) { double('search') }
17
+
18
+ it 'adds the query to the search registry' do
19
+ allow(ChefSpec::Stubs::SearchStub).to receive(:new).and_return(search_stub)
20
+ stub_search(:node, '*:*')
21
+
22
+ expect(ChefSpec::Stubs::SearchRegistry.stubs).to include(search_stub)
23
+ end
24
+ end
25
+
26
+ describe '#stub_data_bag' do
27
+ let(:data_bag_stub) { double('data_bag') }
28
+
29
+ it 'adds the query to the data_bag registry' do
30
+ allow(ChefSpec::Stubs::DataBagStub).to receive(:new).and_return(data_bag_stub)
31
+ stub_data_bag(:users)
32
+
33
+ expect(ChefSpec::Stubs::DataBagRegistry.stubs).to include(data_bag_stub)
34
+ end
35
+ end
36
+
37
+ describe '#stub_data_bag_item' do
38
+ let(:data_bag_item_stub) { double('data_bag_item') }
39
+
40
+ it 'adds the query to the data_bag_item registry' do
41
+ allow(ChefSpec::Stubs::DataBagItemStub).to receive(:new).and_return(data_bag_item_stub)
42
+ stub_data_bag_item(:users, 'id')
43
+
44
+ expect(ChefSpec::Stubs::DataBagItemRegistry.stubs).to include(data_bag_item_stub)
45
+ end
46
+ end
47
+
48
+ describe '#stub_node' do
49
+ it 'returns a Chef::Node' do
50
+ expect(stub_node).to be_a(Chef::Node)
51
+ end
52
+
53
+ it 'defaults the node name to `node.example`' do
54
+ node = stub_node
55
+ expect(node.name).to eq('node.example')
56
+ end
57
+
58
+ it 'sets the node name when given' do
59
+ node = stub_node('example.com')
60
+ expect(node.name).to eq('example.com')
61
+ end
62
+
63
+ it 'sets the automatic attributes' do
64
+ node = stub_node
65
+ expect(node.automatic).to eq(Fauxhai.mock.data)
66
+ end
67
+
68
+ it 'sets the automatic attributes with ohai overrides' do
69
+ node = stub_node('node.example', ohai: { ipaddress: '1.2.3.4' })
70
+ expect(node['ipaddress']).to eq('1.2.3.4')
71
+ end
72
+
73
+ it 'sets the automatic attributes for a specific platform and version' do
74
+ node = stub_node('node.example', platform: 'ubuntu', version: '18.04')
75
+ expect(node.automatic).to eq(Fauxhai.mock(platform: 'ubuntu', version: '18.04').data)
76
+ end
77
+
78
+ it 'sets the automatic attributes from a JSON data path' do
79
+ allow(File).to receive(:exist?).with('/path/to/json').and_return(true)
80
+ allow(File).to receive(:read).with('/path/to/json').and_return('{ "ipaddress": "1.2.3.4" }')
81
+ node = stub_node('node.example', path: '/path/to/json')
82
+ expect(node['ipaddress']).to eq('1.2.3.4')
83
+ end
84
+
85
+ it 'yields a block' do
86
+ expect { |block| stub_node(&block) }.to yield_with_args(Chef::Node)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe 'nginx::source' do
92
+ describe '#described_cookbook' do
93
+ describe 'nginx::source' do
94
+ it 'returns the name of the cookbook' do
95
+ expect(described_cookbook).to eq('nginx')
96
+ end
97
+
98
+ context 'in a nested context' do
99
+ it 'still returns the name of the cookbook' do
100
+ expect(described_cookbook).to eq('nginx')
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ describe '#described_recipe' do
107
+ describe 'nginx::source' do
108
+ it 'returns the cookbook::recipe' do
109
+ expect(described_recipe).to eq('nginx::source')
110
+ end
111
+
112
+ context 'in a nested context' do
113
+ it 'still retrns the cookbook::recipe' do
114
+ expect(described_recipe).to eq('nginx::source')
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::DoNothingMatcher do
4
+ pending
5
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::IncludeRecipeMatcher do
4
+ let(:chef_run) { double('chef run', run_context: { loaded_recipes: %w(one two three) }) }
5
+ subject { described_class.new('one::default') }
6
+
7
+ describe '#failure_message' do
8
+ it 'has the right value' do
9
+ subject.matches?(chef_run)
10
+ expect(subject.failure_message)
11
+ .to eq(%q(expected ["one::default", "two::default", "three::default"] to include "one::default"))
12
+ end
13
+ end
14
+
15
+ describe '#failure_message_when_negated' do
16
+ it 'has the right value' do
17
+ subject.matches?(chef_run)
18
+ expect(subject.failure_message_when_negated)
19
+ .to eq(%q(expected "one::default" to not be included))
20
+ end
21
+ end
22
+
23
+ describe '#description' do
24
+ it 'has the right value' do
25
+ subject.matches?(chef_run)
26
+ expect(subject.description).to eq(%q(include recipe "one::default"))
27
+ end
28
+ end
29
+
30
+ it 'matches when the recipe is included' do
31
+ expect(subject.matches?(chef_run)).to be_truthy
32
+ end
33
+
34
+ it 'does not match when the recipe is not included' do
35
+ failure = described_class.new('nope')
36
+ expect(failure.matches?(chef_run)).to be_falsy
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::LinkToMatcher do
4
+ let(:from) { '/var/www' }
5
+ let(:to) { '/var/html' }
6
+ let(:link) do
7
+ Chef::Resource::Link.new(from).tap do |link|
8
+ link.to(to)
9
+ link.perform_action(:create)
10
+ end
11
+ end
12
+ subject { described_class.new(to) }
13
+
14
+ describe '#failure_message' do
15
+ it 'has the right value' do
16
+ subject.matches?(link)
17
+ expect(subject.failure_message)
18
+ .to eq(%Q(expected "link[#{from}]" to link to "#{to}" but was "#{to}"))
19
+ end
20
+ end
21
+
22
+ describe '#failure_message_when_negated' do
23
+ it 'has the right value' do
24
+ subject.matches?(link)
25
+ expect(subject.failure_message_when_negated)
26
+ .to eq(%Q(expected "link[#{from}]" to not link to "#{to}"))
27
+ end
28
+ end
29
+
30
+ describe '#description' do
31
+ it 'has the right value' do
32
+ subject.matches?(link)
33
+ expect(subject.description).to eq(%Q(link to "#{to}"))
34
+ end
35
+ end
36
+
37
+ context 'when the link is correct' do
38
+ it 'matches' do
39
+ expect(subject.matches?(link)).to be_truthy
40
+ end
41
+
42
+ it 'adds the link to the coverage report' do
43
+ expect(ChefSpec::Coverage).to receive(:cover!).with(link)
44
+ subject.matches?(link)
45
+ end
46
+ end
47
+
48
+ context 'when the link is not correct' do
49
+ subject { described_class.new('/nope/bad/path/bro') }
50
+
51
+ it 'does not match' do
52
+ expect(subject.matches?(link)).to be_falsy
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::NotificationsMatcher do
4
+ subject { described_class.new('execute[install]') }
5
+ let(:package) do
6
+ double('package',
7
+ name: 'package',
8
+ to_s: 'package[foo]',
9
+ is_a?: true,
10
+ performed_action?: true,
11
+ immediate_notifications: [],
12
+ delayed_notifications: [],
13
+ before_notifications: []
14
+ )
15
+ end
16
+
17
+ describe '#failure_message' do
18
+ it 'has the right value' do
19
+ subject.matches?(package)
20
+ expect(subject.failure_message)
21
+ .to include %|expected "package[foo]" to notify "execute[install]", but did not.|
22
+ end
23
+ end
24
+
25
+ describe '#failure_message_when_negated' do
26
+ it 'has the right value' do
27
+ subject.matches?(package)
28
+ expect(subject.failure_message_when_negated)
29
+ .to eq %|expected "package[foo]" to not notify "execute[install]", but it did.|
30
+ end
31
+ end
32
+
33
+ describe '#description' do
34
+ it 'has the right value' do
35
+ subject.matches?(package)
36
+ expect(subject.description)
37
+ .to eq %|notify "execute[install]"|
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::RenderFileMatcher do
4
+ let(:path) { '/tmp/thing' }
5
+ let(:file) { double('file', to: path, to_s: "file[#{path}]", performed_action?: true) }
6
+ let(:chef_run) { double('chef run', find_resource: file) }
7
+ subject { described_class.new(path) }
8
+
9
+ describe '#with_content' do
10
+ it 'accepts do/end syntax' do
11
+ subject.matches?(chef_run)
12
+ expect(
13
+ subject.with_content do |content|
14
+ 'Does not raise ArgumentError'
15
+ end.expected_content.first.call
16
+ ).to eq('Does not raise ArgumentError')
17
+ end
18
+ end
19
+
20
+ describe '#failure_message' do
21
+ it 'has the right value' do
22
+ subject.matches?(chef_run)
23
+ expect(subject.failure_message)
24
+ .to eq(%Q(expected Chef run to render "#{path}"))
25
+ end
26
+ end
27
+
28
+ describe '#failure_message_when_negated' do
29
+ it 'has the right value' do
30
+ subject.matches?(chef_run)
31
+ expect(subject.failure_message_when_negated)
32
+ .to eq(%Q(expected file "#{path}" to not be in Chef run))
33
+ end
34
+ end
35
+
36
+ describe '#description' do
37
+ it 'has the right value' do
38
+ subject.matches?(chef_run)
39
+ expect(subject.description).to eq(%Q(render file "#{path}"))
40
+ end
41
+
42
+ it 'has the right value when with_content is chained' do
43
+ subject.matches?(chef_run)
44
+ expect(
45
+ subject.with_content('foo').with_content('bar').description
46
+ ).to eq(%Q(render file "#{path}" with content "foo" with content "bar"))
47
+ end
48
+ end
49
+
50
+ context 'when the file is correct' do
51
+ it 'matches' do
52
+ expect(subject.matches?(chef_run)).to be_truthy
53
+ end
54
+
55
+ it 'adds the resource to the coverage report' do
56
+ expect(ChefSpec::Coverage).to receive(:cover!).with(file)
57
+ subject.matches?(chef_run)
58
+ end
59
+ end
60
+
61
+ context 'when the file is not correct' do
62
+ it 'does not match' do
63
+ allow(chef_run).to receive(:find_resource).and_return(nil)
64
+ failure = described_class.new('nope')
65
+ expect(failure.matches?(chef_run)).to be_falsy
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::ResourceMatcher do
4
+ pending
5
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::StateAttrsMatcher do
4
+ subject { described_class.new([:a, :b]) }
5
+
6
+ context 'when the resource does not exist' do
7
+ let(:resource) { nil }
8
+ before { subject.matches?(resource) }
9
+
10
+ it 'does not match' do
11
+ expect(subject).to_not be_matches(resource)
12
+ end
13
+
14
+ it 'has the correct description' do
15
+ expect(subject.description).to eq('have state attributes [:a, :b]')
16
+ end
17
+
18
+ it 'has the correct failure message for should' do
19
+ expect(subject.failure_message).to include <<-EOH.gsub(/^ {8}/, '')
20
+ expected _something_ to have state attributes, but the _something_ you gave me was nil!
21
+ Ensure the resource exists before making assertions:
22
+
23
+ expect(resource).to be
24
+ EOH
25
+ end
26
+
27
+ it 'has the correct failure message for should not' do
28
+ expect(subject.failure_message_when_negated).to include <<-EOH.gsub(/^ {8}/, '')
29
+ expected _something_ to not have state attributes, but the _something_ you gave me was nil!
30
+ Ensure the resource exists before making assertions:
31
+
32
+ expect(resource).to be
33
+ EOH
34
+ end
35
+ end
36
+
37
+ context 'when the resource exists' do
38
+ let(:klass) { double('class', state_attrs: [:a, :b]) }
39
+ let(:resource) { double('resource', class: klass) }
40
+ before { subject.matches?(resource) }
41
+
42
+ it 'has the correct description' do
43
+ expect(subject.description).to eq('have state attributes [:a, :b]')
44
+ end
45
+
46
+ it 'has the correct failure message for should' do
47
+ expect(subject.failure_message).to eq('expected [:a, :b] to equal [:a, :b]')
48
+ end
49
+
50
+ it 'has the correct failure message for should not' do
51
+ expect(subject.failure_message_when_negated).to eq('expected [:a, :b] to not equal [:a, :b]')
52
+ end
53
+
54
+ it 'matches when the state attributes are correct' do
55
+ expect(subject).to be_matches(resource)
56
+ end
57
+
58
+ it 'does not match when the state attributes are incorrect' do
59
+ allow(klass).to receive(:state_attrs).and_return([:c, :d])
60
+ expect(subject).to_not be_matches(resource)
61
+ end
62
+
63
+ it 'does not match when partial state attribute are incorrect' do
64
+ allow(klass).to receive(:state_attrs).and_return([:b, :c])
65
+ expect(subject).to_not be_matches(resource)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe ChefSpec::Matchers::SubscribesMatcher do
4
+ subject { described_class.new('execute[install]') }
5
+ let(:runner) { double('runner', find_resource: nil) }
6
+ let(:run_context) { double('run_context', node: node) }
7
+ let(:node) { double('node', runner: runner) }
8
+ let(:package) do
9
+ double('package',
10
+ name: 'package',
11
+ to_s: 'package[foo]',
12
+ run_context: run_context,
13
+ )
14
+ end
15
+
16
+ context 'when no resource is found' do
17
+ describe '#failure_message' do
18
+ it 'has the right value' do
19
+ subject.matches?(package)
20
+ expect(subject.failure_message)
21
+ .to include %|expected _something_ to notify "package[foo]", but the _something_ you gave me was nil! If you are running a test like:|
22
+ end
23
+ end
24
+ end
25
+
26
+ context 'when the resource exists' do
27
+ let(:execute) do
28
+ double('execute',
29
+ name: 'execute',
30
+ to_s: 'execute[install]',
31
+ immediate_notifications: [],
32
+ delayed_notifications: [],
33
+ before_notifications: []
34
+ )
35
+ end
36
+
37
+ before do
38
+ allow(runner).to receive(:find_resource).and_return(execute)
39
+ end
40
+
41
+ describe '#failure_message' do
42
+ it 'has the right value' do
43
+ subject.matches?(package)
44
+ expect(subject.failure_message)
45
+ .to include %|expected "execute[install]" to notify "package[foo]", but did not.|
46
+ end
47
+ end
48
+
49
+ describe '#failure_message_when_negated' do
50
+ it 'has the right value' do
51
+ subject.matches?(package)
52
+ expect(subject.failure_message_when_negated)
53
+ .to eq %|expected "execute[install]" to not notify "package[foo]", but it did.|
54
+ end
55
+ end
56
+ end
57
+
58
+ describe '#description' do
59
+ it 'has the right value' do
60
+ subject.matches?(package)
61
+ expect(subject.description)
62
+ .to eq %|notify "package[foo]"|
63
+ end
64
+ end
65
+ end