chefspec-chef 9.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 (120) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +30 -0
  3. data/LICENSE +22 -0
  4. data/Rakefile +85 -0
  5. data/chefspec-chef.gemspec +30 -0
  6. data/lib/chefspec/api/core.rb +217 -0
  7. data/lib/chefspec/api/described.rb +53 -0
  8. data/lib/chefspec/api/do_nothing.rb +26 -0
  9. data/lib/chefspec/api/include_any_recipe.rb +24 -0
  10. data/lib/chefspec/api/include_recipe.rb +28 -0
  11. data/lib/chefspec/api/link.rb +28 -0
  12. data/lib/chefspec/api/notifications.rb +40 -0
  13. data/lib/chefspec/api/reboot.rb +14 -0
  14. data/lib/chefspec/api/render_file.rb +37 -0
  15. data/lib/chefspec/api/state_attrs.rb +30 -0
  16. data/lib/chefspec/api/stubs.rb +183 -0
  17. data/lib/chefspec/api/stubs_for.rb +139 -0
  18. data/lib/chefspec/api/subscriptions.rb +37 -0
  19. data/lib/chefspec/api/user.rb +230 -0
  20. data/lib/chefspec/api.rb +39 -0
  21. data/lib/chefspec/berkshelf.rb +63 -0
  22. data/lib/chefspec/cacher.rb +64 -0
  23. data/lib/chefspec/coverage/filters.rb +82 -0
  24. data/lib/chefspec/coverage.rb +247 -0
  25. data/lib/chefspec/deprecations.rb +46 -0
  26. data/lib/chefspec/errors.rb +48 -0
  27. data/lib/chefspec/expect_exception.rb +51 -0
  28. data/lib/chefspec/extensions/chef/client.rb +21 -0
  29. data/lib/chefspec/extensions/chef/conditional.rb +16 -0
  30. data/lib/chefspec/extensions/chef/cookbook/gem_installer.rb +33 -0
  31. data/lib/chefspec/extensions/chef/cookbook_loader.rb +14 -0
  32. data/lib/chefspec/extensions/chef/cookbook_uploader.rb +12 -0
  33. data/lib/chefspec/extensions/chef/data_query.rb +49 -0
  34. data/lib/chefspec/extensions/chef/lwrp_base.rb +29 -0
  35. data/lib/chefspec/extensions/chef/provider.rb +39 -0
  36. data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +17 -0
  37. data/lib/chefspec/extensions/chef/resource.rb +188 -0
  38. data/lib/chefspec/extensions/chef/run_context/cookbook_compiler.rb +84 -0
  39. data/lib/chefspec/extensions/chef/securable.rb +19 -0
  40. data/lib/chefspec/extensions/ohai/system.rb +11 -0
  41. data/lib/chefspec/extensions.rb +21 -0
  42. data/lib/chefspec/file_cache_path_proxy.rb +15 -0
  43. data/lib/chefspec/formatter.rb +282 -0
  44. data/lib/chefspec/librarian.rb +51 -0
  45. data/lib/chefspec/matchers/do_nothing_matcher.rb +52 -0
  46. data/lib/chefspec/matchers/include_any_recipe_matcher.rb +51 -0
  47. data/lib/chefspec/matchers/include_recipe_matcher.rb +46 -0
  48. data/lib/chefspec/matchers/link_to_matcher.rb +37 -0
  49. data/lib/chefspec/matchers/notifications_matcher.rb +143 -0
  50. data/lib/chefspec/matchers/render_file_matcher.rb +140 -0
  51. data/lib/chefspec/matchers/resource_matcher.rb +175 -0
  52. data/lib/chefspec/matchers/state_attrs_matcher.rb +71 -0
  53. data/lib/chefspec/matchers/subscribes_matcher.rb +72 -0
  54. data/lib/chefspec/matchers.rb +13 -0
  55. data/lib/chefspec/mixins/normalize.rb +22 -0
  56. data/lib/chefspec/policyfile.rb +69 -0
  57. data/lib/chefspec/renderer.rb +145 -0
  58. data/lib/chefspec/rspec.rb +21 -0
  59. data/lib/chefspec/runner.rb +8 -0
  60. data/lib/chefspec/server.rb +4 -0
  61. data/lib/chefspec/server_methods.rb +173 -0
  62. data/lib/chefspec/server_runner.rb +76 -0
  63. data/lib/chefspec/solo_runner.rb +516 -0
  64. data/lib/chefspec/stubs/command_registry.rb +11 -0
  65. data/lib/chefspec/stubs/command_stub.rb +37 -0
  66. data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
  67. data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
  68. data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
  69. data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
  70. data/lib/chefspec/stubs/registry.rb +32 -0
  71. data/lib/chefspec/stubs/search_registry.rb +13 -0
  72. data/lib/chefspec/stubs/search_stub.rb +25 -0
  73. data/lib/chefspec/stubs/stub.rb +38 -0
  74. data/lib/chefspec/util.rb +58 -0
  75. data/lib/chefspec/version.rb +3 -0
  76. data/lib/chefspec/zero_server.rb +142 -0
  77. data/lib/chefspec.rb +75 -0
  78. data/spec/spec_helper.rb +12 -0
  79. data/spec/support/hash.rb +35 -0
  80. data/spec/unit/cacher_spec.rb +70 -0
  81. data/spec/unit/coverage/filters_spec.rb +60 -0
  82. data/spec/unit/deprecations_spec.rb +52 -0
  83. data/spec/unit/errors_spec.rb +57 -0
  84. data/spec/unit/expect_exception_spec.rb +32 -0
  85. data/spec/unit/macros_spec.rb +119 -0
  86. data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
  87. data/spec/unit/matchers/include_any_recipe_matcher_spec.rb +52 -0
  88. data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
  89. data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
  90. data/spec/unit/matchers/notifications_matcher_spec.rb +39 -0
  91. data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
  92. data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
  93. data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
  94. data/spec/unit/matchers/subscribes_matcher_spec.rb +63 -0
  95. data/spec/unit/renderer_spec.rb +69 -0
  96. data/spec/unit/server_runner_spec.rb +28 -0
  97. data/spec/unit/solo_runner_spec.rb +171 -0
  98. data/spec/unit/stubs/command_registry_spec.rb +27 -0
  99. data/spec/unit/stubs/command_stub_spec.rb +61 -0
  100. data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
  101. data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
  102. data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
  103. data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
  104. data/spec/unit/stubs/registry_spec.rb +29 -0
  105. data/spec/unit/stubs/search_registry_spec.rb +39 -0
  106. data/spec/unit/stubs/search_stub_spec.rb +36 -0
  107. data/spec/unit/stubs/stub_spec.rb +64 -0
  108. data/templates/coverage/human.erb +22 -0
  109. data/templates/coverage/json.erb +8 -0
  110. data/templates/coverage/table.erb +14 -0
  111. data/templates/errors/cookbook_path_not_found.erb +3 -0
  112. data/templates/errors/erb_template_parse_error.erb +5 -0
  113. data/templates/errors/gem_load_error.erb +7 -0
  114. data/templates/errors/invalid_berkshelf_options.erb +4 -0
  115. data/templates/errors/may_need_to_specify_platform.erb +25 -0
  116. data/templates/errors/no_conversion_error.erb +1 -0
  117. data/templates/errors/not_stubbed.erb +7 -0
  118. data/templates/errors/shell_out_not_stubbed.erb +10 -0
  119. data/templates/errors/template_not_found.erb +9 -0
  120. metadata +221 -0
@@ -0,0 +1,25 @@
1
+ require_relative "stub"
2
+
3
+ module ChefSpec
4
+ module Stubs
5
+ class SearchStub < Stub
6
+ attr_reader :block
7
+ attr_reader :query
8
+ attr_reader :type
9
+
10
+ def initialize(type, query = "*:*", &block)
11
+ @type = type.to_s
12
+ @query = query
13
+ @block = block
14
+ end
15
+
16
+ def signature
17
+ if @block
18
+ "stub_search(#{@type.inspect}, #{@query.inspect}) { # Ruby code }"
19
+ else
20
+ "stub_search(#{@type.inspect}, #{@query.inspect}).and_return(#{@value})"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ module ChefSpec
2
+ module Stubs
3
+ class Stub
4
+ attr_reader :value
5
+
6
+ def and_return(value)
7
+ @value = value
8
+ self
9
+ end
10
+
11
+ def and_raise(exception)
12
+ @block = Proc.new { raise exception }
13
+ self
14
+ end
15
+
16
+ def result
17
+ if @block
18
+ recursively_mashify(@block.call)
19
+ else
20
+ recursively_mashify(@value)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def recursively_mashify(thing)
27
+ case thing
28
+ when Array
29
+ thing.collect { |item| recursively_mashify(item) }
30
+ when Hash
31
+ Mash.from_hash(thing)
32
+ else
33
+ thing
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ module ChefSpec
2
+ module Util
3
+ extend self
4
+
5
+ #
6
+ # Covert the given CaMelCaSeD string to under_score. Graciously borrowed
7
+ # from http://stackoverflow.com/questions/1509915.
8
+ #
9
+ # @param [String] string
10
+ # the string to use for transformation
11
+ #
12
+ # @return [String]
13
+ #
14
+ def underscore(string)
15
+ string
16
+ .to_s
17
+ .gsub(/::/, "/")
18
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
19
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
20
+ .tr("-", "_")
21
+ .downcase
22
+ end
23
+
24
+ #
25
+ # Convert an underscored string to it's camelcase equivalent constant.
26
+ #
27
+ # @param [String] string
28
+ # the string to convert
29
+ #
30
+ # @return [String]
31
+ #
32
+ def camelize(string)
33
+ string
34
+ .to_s
35
+ .split("_")
36
+ .map(&:capitalize)
37
+ .join
38
+ end
39
+
40
+ #
41
+ # Truncate the given string to a certain number of characters.
42
+ #
43
+ # @param [String] string
44
+ # the string to truncate
45
+ # @param [Hash] options
46
+ # the list of options (such as +length+)
47
+ #
48
+ def truncate(string, options = {})
49
+ length = options[:length] || 30
50
+
51
+ if string.length > length
52
+ string[0..length - 3] + "..."
53
+ else
54
+ string
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module ChefSpec
2
+ VERSION = "9.3.4".freeze
3
+ end
@@ -0,0 +1,142 @@
1
+ require "chef_zero/server"
2
+
3
+ module ChefSpec
4
+ # Rather than create a ChefZero instance per test case, simply create one
5
+ # ChefZero instance and reset it for every test case.
6
+ class ZeroServer
7
+ class << self
8
+ extend Forwardable
9
+ def_delegators :instance, :setup!, :teardown!, :reset!, :upload_cookbooks!, :server, :load_data, :nuke!
10
+ end
11
+
12
+ include Singleton
13
+
14
+ attr_reader :server
15
+
16
+ # Create the ChefZero Server
17
+ def initialize
18
+ nuke!
19
+ end
20
+
21
+ #
22
+ # Start the ChefZero Server
23
+ #
24
+ def setup!
25
+ @server.start_background unless @server.running?
26
+ end
27
+
28
+ #
29
+ # Remove all the data we just loaded from the ChefZero server
30
+ #
31
+ def reset!
32
+ if RSpec.configuration.server_runner_clear_cookbooks
33
+ @server.clear_data
34
+ @cookbooks_uploaded = false
35
+ else
36
+ # If we don't want to do a full clear, iterate through each value that we
37
+ # set and manually remove it.
38
+ @data_loaded.each do |key, names|
39
+ if key == "data"
40
+ names.each { |n| @server.data_store.delete_dir(["organizations", "chef", key, n]) }
41
+ else
42
+ names.each { |n| @server.data_store.delete(["organizations", "chef", key, n]) }
43
+ end
44
+ end
45
+ end
46
+ @data_loaded = {}
47
+ end
48
+
49
+ #
50
+ # Really reset everything and reload the configuration
51
+ #
52
+ def nuke!
53
+ @server = ChefZero::Server.new(
54
+ # Set the log level from RSpec, defaulting to warn
55
+ log_level: RSpec.configuration.log_level || :warn,
56
+ port: RSpec.configuration.server_runner_port,
57
+
58
+ # Set the data store
59
+ data_store: data_store(RSpec.configuration.server_runner_data_store)
60
+ )
61
+ @cookbooks_uploaded = false
62
+ @data_loaded = {}
63
+ end
64
+
65
+ #
66
+ # Teardown the ChefZero Server
67
+ #
68
+ def teardown!
69
+ @server.stop if @server.running?
70
+ end
71
+
72
+ #
73
+ # Upload the cookbooks to the Chef Server.
74
+ #
75
+ def upload_cookbooks!
76
+ return if @cookbooks_uploaded
77
+
78
+ loader = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
79
+ loader.load_cookbooks
80
+ cookbook_uploader_for(loader).upload_cookbooks
81
+ @cookbooks_uploaded = true
82
+ end
83
+
84
+ #
85
+ # Load (and track) data sent to the server
86
+ #
87
+ # @param [String] name
88
+ # the name or id of the item to load
89
+ # @param [String, Symbol] key
90
+ # the key to load
91
+ # @param [Hash] data
92
+ # the data for the object, which will be converted to JSON and uploaded
93
+ # to the server
94
+ #
95
+ def load_data(name, key, data)
96
+ @data_loaded[key] ||= []
97
+ @data_loaded[key] << name
98
+ @server.load_data({ key => { name => data } })
99
+ end
100
+
101
+ private
102
+
103
+ #
104
+ # The uploader for the cookbooks.
105
+ #
106
+ # @param [Chef::CookbookLoader] loader
107
+ # the Chef cookbook loader
108
+ #
109
+ # @return [Chef::CookbookUploader]
110
+ #
111
+ def cookbook_uploader_for(loader)
112
+ Chef::CookbookUploader.new(loader.cookbooks)
113
+ end
114
+
115
+ #
116
+ # Generate the DataStore object to be passed in to the ChefZero::Server object
117
+ #
118
+ def data_store(option)
119
+ require "chef_zero/data_store/default_facade"
120
+
121
+ store = case option
122
+ when :in_memory
123
+ require "chef_zero/data_store/memory_store_v2"
124
+ ChefZero::DataStore::MemoryStoreV2.new
125
+ when :on_disk
126
+ require "tmpdir" unless defined?(Dir.mktmpdir)
127
+ require "chef_zero/data_store/raw_file_store"
128
+ ChefZero::DataStore::RawFileStore.new(Dir.mktmpdir)
129
+ else
130
+ raise ArgumentError, ":#{option} is not a valid server_runner_data_store option. Please use either :in_memory or :on_disk."
131
+ end
132
+
133
+ ChefZero::DataStore::DefaultFacade.new(store, "chef", true)
134
+ end
135
+ end
136
+ end
137
+
138
+ RSpec.configure do |config|
139
+ config.before(:suite) { ChefSpec::ZeroServer.setup! }
140
+ config.after(:each) { ChefSpec::ZeroServer.reset! }
141
+ config.after(:suite) { ChefSpec::ZeroServer.teardown! }
142
+ end
data/lib/chefspec.rb ADDED
@@ -0,0 +1,75 @@
1
+ require "rspec"
2
+
3
+ module ChefSpec
4
+ #
5
+ # Defines a new runner method on the Chef runner.
6
+ #
7
+ # @param [Symbol] resource_name
8
+ # the name of the resource to define a method
9
+ #
10
+ # @return [self]
11
+ #
12
+ def define_matcher(resource_name)
13
+ matchers[resource_name.to_sym] = Proc.new do |identity|
14
+ find_resource(resource_name, identity)
15
+ end
16
+
17
+ self
18
+ end
19
+ module_function :define_matcher
20
+
21
+ #
22
+ # The source root of the ChefSpec gem. This is useful when requiring files
23
+ # that are relative to the root of the project.
24
+ #
25
+ # @return [Pathname]
26
+ #
27
+ def root
28
+ @root ||= Pathname.new(File.expand_path("..", __dir__))
29
+ end
30
+ module_function :root
31
+
32
+ protected
33
+
34
+ #
35
+ # The list of custom defined matchers.
36
+ #
37
+ # @return [Hash<String, Proc>]
38
+ #
39
+ def matchers
40
+ @matchers ||= {}
41
+ end
42
+ module_function :matchers
43
+ end
44
+
45
+ require_relative "chefspec/extensions"
46
+
47
+ require_relative "chefspec/mixins/normalize"
48
+
49
+ require_relative "chefspec/stubs/command_registry"
50
+ require_relative "chefspec/stubs/command_stub"
51
+ require_relative "chefspec/stubs/data_bag_item_registry"
52
+ require_relative "chefspec/stubs/data_bag_item_stub"
53
+ require_relative "chefspec/stubs/data_bag_registry"
54
+ require_relative "chefspec/stubs/data_bag_stub"
55
+ require_relative "chefspec/stubs/registry"
56
+ require_relative "chefspec/stubs/stub"
57
+ require_relative "chefspec/stubs/search_registry"
58
+ require_relative "chefspec/stubs/search_stub"
59
+
60
+ require_relative "chefspec/api"
61
+ require_relative "chefspec/cacher"
62
+ require_relative "chefspec/coverage"
63
+ require_relative "chefspec/errors"
64
+ require_relative "chefspec/expect_exception"
65
+ require_relative "chefspec/formatter"
66
+ require_relative "chefspec/matchers"
67
+ require_relative "chefspec/renderer"
68
+ require_relative "chefspec/rspec"
69
+ require_relative "chefspec/server_runner"
70
+ require_relative "chefspec/solo_runner"
71
+ require_relative "chefspec/runner"
72
+ require_relative "chefspec/util"
73
+ require_relative "chefspec/version"
74
+
75
+ require_relative "chefspec/deprecations"
@@ -0,0 +1,12 @@
1
+ require "chefspec"
2
+ require "support/hash"
3
+
4
+ ChefSpec::Coverage.start! do
5
+ set_template "table.erb"
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
10
+ config.filter_run(focus: true)
11
+ config.run_all_when_everything_filtered = true
12
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # An extension of a Hash that allows mash-style like lookups.
3
+ #
4
+ # @private
5
+ #
6
+ class Hash
7
+ # Like, seriously Windows?
8
+ undef_method(:timeout) if method_defined?(:timeout)
9
+
10
+ #
11
+ # Monkey-patch to allow mash-style look ups for tests
12
+ #
13
+ def method_missing(m, *args, &block)
14
+ if key?(m.to_sym)
15
+ self[m.to_sym]
16
+ elsif key?(m.to_s)
17
+ self[m.to_s]
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ #
24
+ # Monkey-patch to stdlib Hash to correspond to Mash-style lookup
25
+ #
26
+ # @see Hash#respond_to?
27
+ #
28
+ def respond_to?(m, include_private = false)
29
+ if key?(m.to_sym) || key?(m.to_s)
30
+ true
31
+ else
32
+ super
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,70 @@
1
+ require "spec_helper"
2
+ require "chefspec/cacher"
3
+
4
+ describe ChefSpec::Cacher do
5
+ let(:klass) do
6
+ Class.new(RSpec::Core::ExampleGroup) do
7
+ extend ChefSpec::Cacher
8
+
9
+ def self.metadata
10
+ { parent_example_group: { location: "spec" } }
11
+ end
12
+ end
13
+ end
14
+
15
+ let(:cache) { described_class.class_variable_get(:@@cache) }
16
+ let(:preserve_cache) { false }
17
+
18
+ before(:each) { described_class.class_variable_set(:@@cache, {}) unless preserve_cache }
19
+
20
+ describe "cached" do
21
+ it "lazily defines the results for the cache" do
22
+ klass.cached(:chef_run)
23
+ expect(klass).to be_method_defined(:chef_run)
24
+ end
25
+
26
+ it "adds the item to the cache when called" do
27
+ runner = double(:runner)
28
+ klass.cached(:chef_run) { runner }
29
+ klass.new.chef_run
30
+
31
+ expect(cache[Thread.current.object_id]).to have_key("spec.chef_run")
32
+ expect(cache[Thread.current.object_id]["spec.chef_run"]).to eq(runner)
33
+ end
34
+
35
+ context "when multithreaded environment" do
36
+ it "is thread safe" do
37
+ (1..2).each do |n|
38
+ Thread.new do
39
+ klass.cached(:chef_run) { n }
40
+ expect(klass.new.chef_run).to eq(n)
41
+ end.join
42
+ end
43
+ end
44
+ end
45
+
46
+ context "when example groups are defined by looping" do
47
+ let(:preserve_cache) { true }
48
+
49
+ %w{first second third}.each do |iteration|
50
+ context "on the #{iteration} iteration" do
51
+ context "in caching context" do
52
+ cached(:cached_iteration) { iteration }
53
+ it "caches the iteration for this context" do
54
+ expect(cached_iteration).to eq iteration
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "cached!" do
63
+ it "loads the value at runtime" do
64
+ expect(klass).to receive(:cached).with(:chef_run).once
65
+ expect(klass).to receive(:before).once
66
+
67
+ klass.cached!(:chef_run) {}
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+
3
+ # Note: These specs don't use Berkshelf code directly as this project doesn't
4
+ # have a direct dependency on Berkshelf and loading it would impact the
5
+ # perfance of these specs. While not ideal, the test doubles provide enough of
6
+ # a standin for Berkshelf to exercise the `#matches?` behavior.
7
+ describe ChefSpec::Coverage::BerkshelfFilter do
8
+ let(:dependencies) do
9
+ [double("Berkshelf::Dependency", metadata?: true, name: "cookbookery")]
10
+ end
11
+ let(:berksfile) { double("Berkshelf::Berksfile", dependencies: dependencies) }
12
+ let(:resource) { Chef::Resource.new("theone") }
13
+ subject { described_class.new(berksfile) }
14
+
15
+ describe "#matches?" do
16
+ it "returns truthy if resource source_line is nil" do
17
+ expect(subject.matches?(resource)).to be_truthy
18
+ end
19
+
20
+ context "when resource#source_line is under target cookbook" do
21
+ it "normal unix path returns truthy" do
22
+ resource.source_line =
23
+ "/path/to/cookbooks/nope/recipes/default.rb:22"
24
+ expect(subject.matches?(resource)).to be_truthy
25
+ end
26
+
27
+ it "normal windows path returns truthy" do
28
+ resource.source_line =
29
+ 'C:\\path\\to\\cookbooks\\nope\\recipes\\default.rb:22'
30
+ expect(subject.matches?(resource)).to be_truthy
31
+ end
32
+
33
+ it "mixed windows path returns truthy" do
34
+ resource.source_line =
35
+ 'C:\\path\\to\\cookbooks/nope/recipes/default.rb:22'
36
+ expect(subject.matches?(resource)).to be_truthy
37
+ end
38
+ end
39
+
40
+ context "when resource#source_line is not under target cookbook" do
41
+ it "normal unix path returns falsey" do
42
+ resource.source_line =
43
+ "/path/to/cookbooks/cookbookery/recipes/default.rb:22"
44
+ expect(subject.matches?(resource)).to be_falsey
45
+ end
46
+
47
+ it "normal windows path returns falsey" do
48
+ resource.source_line =
49
+ 'C:\\path\\to\\cookbooks\\cookbookery\\recipes\\default.rb:22'
50
+ expect(subject.matches?(resource)).to be_falsey
51
+ end
52
+
53
+ it "mixed windows path returns falsey" do
54
+ resource.source_line =
55
+ 'C:\\path\\to\\cookbooks/cookbookery/recipes/default.rb:22'
56
+ expect(subject.matches?(resource)).to be_falsey
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe ChefSpec::Runner do
4
+ before do
5
+ allow_any_instance_of(ChefSpec::SoloRunner)
6
+ .to receive(:dry_run?)
7
+ .and_return(true)
8
+ allow(ChefSpec::Runner).to receive(:deprecated)
9
+ end
10
+
11
+ describe "#define_runner_method" do
12
+ before do
13
+ allow(ChefSpec).to receive(:define_matcher)
14
+ end
15
+
16
+ it "prints a deprecation" do
17
+ expect(ChefSpec::Runner).to receive(:deprecated)
18
+ .with("`ChefSpec::Runner.define_runner_method' is deprecated."\
19
+ " It is being used in the my_custom_resource resource matcher." \
20
+ " Please use `ChefSpec.define_matcher' instead.")
21
+ ChefSpec::Runner.define_runner_method(:my_custom_resource)
22
+ end
23
+
24
+ it "calls ChefSpec#define_matcher" do
25
+ expect(ChefSpec).to receive(:define_matcher).with(:my_custom_resource).once
26
+ ChefSpec::Runner.define_runner_method(:my_custom_resource)
27
+ end
28
+
29
+ end
30
+ end
31
+
32
+ describe ChefSpec::Server do
33
+ before do
34
+ allow(ChefSpec::Server).to receive(:deprecated)
35
+ end
36
+
37
+ it "prints a deprecation for any method called" do
38
+ expect(ChefSpec::Server).to receive(:deprecated)
39
+ .with("`ChefSpec::Server.any_method' is deprecated. There is no longer" \
40
+ " a global Chef Server instance. Please use a ChefSpec::SoloRunner" \
41
+ " instead. More documentation can be found in the ChefSpec README.")
42
+ expect {
43
+ ChefSpec::Server.any_method
44
+ }.to raise_error(ChefSpec::Error::NoConversionError)
45
+ end
46
+
47
+ it "raises non-conversion error for any method called" do
48
+ expect { ChefSpec::Server.any_method }
49
+ .to raise_error(ChefSpec::Error::NoConversionError)
50
+ end
51
+
52
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ module ChefSpec::Error
4
+ describe CommandNotStubbed do
5
+ let(:instance) { described_class.new(args: ["cat"]) }
6
+
7
+ it "raises an exception with the correct message" do
8
+ instance
9
+ expect { raise instance }.to( raise_error { |error|
10
+ expect(error).to be_a(described_class)
11
+ expect(error.message).to eq <<-EOH.gsub(/^ {10}/, "")
12
+ Executing a real command is disabled. Unregistered command:
13
+
14
+ command("cat")
15
+
16
+ You can stub this command with:
17
+
18
+ stub_command("cat").and_return(...)
19
+ EOH
20
+ })
21
+ end
22
+ end
23
+
24
+ describe CookbookPathNotFound do
25
+ let(:instance) { described_class.new }
26
+
27
+ it "raises an exception with the correct message" do
28
+ expect { raise instance }.to(raise_error { |error|
29
+ expect(error).to be_a(described_class)
30
+ expect(error.message).to eq <<-EOH.gsub(/^ {10}/, "")
31
+ I could not find or infer a cookbook_path from your current working directory.
32
+ Please make sure you put your specs (tests) under a directory named 'spec' or
33
+ manually set the cookbook path in the RSpec configuration.
34
+ EOH
35
+ })
36
+ end
37
+ end
38
+
39
+ describe GemLoadError do
40
+ let(:instance) { described_class.new(gem: "bacon", name: "bacon") }
41
+
42
+ it "raises an exception with the correct message" do
43
+ expect { raise instance }.to( raise_error { |error|
44
+ expect(error).to be_a(described_class)
45
+ expect(error.message).to eq <<-EOH.gsub(/^ {10}/, "")
46
+ I could not load the 'bacon' gem! You must have the gem installed
47
+ on your local system before you can use the bacon plugin.
48
+ You can install bacon by running:
49
+
50
+ gem install bacon
51
+
52
+ or add bacon to your Gemfile and run the `bundle` command to install.
53
+ EOH
54
+ })
55
+ end
56
+ end
57
+ end
@@ -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