chefspec 4.5.0 → 4.6.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: 4abcb8430f01e2e4a0d3a1be5f8266929d2a0dbc
4
- data.tar.gz: 07da81047be5641e57bb1cfd4c331b1b4082ea09
3
+ metadata.gz: 50dd772f6c2d50123373b31b0a8e6a405a247658
4
+ data.tar.gz: 8bc37a0bf75e8125a436bda5c84fe61a618062fc
5
5
  SHA512:
6
- metadata.gz: cf4f698fca28f6ef69b7d7a176733cbfb0b2608c3bfb8fb8c090187391c167a87bd72564809ecd3f31f4b6e7770431aeba816450efa5c638277df31a646a5f2f
7
- data.tar.gz: d7804c8c4f6f77fb783b161907524d203cdc9505bc089b9e2a46857413d1cc6d1265baee2e6a64e946d89b0eadc1a6f7205b07463deae1e1e0691b74423b5c53
6
+ metadata.gz: 5728bd4b70d37f1426237615aebf8a857a4c77a7d69a91ba21d8798269329de0c5b162656ab8a710830a9015fa7a3145b2222f237081e2b7491f124ff421f49c
7
+ data.tar.gz: 71de6b27a4bcbe114daaa379d721ac5c950c896f24c1f95110ce46c3735dfa3ee818fe873b9a5e6ecc61d3d4fe344e5507c8f372c1a78adeaa39f0b73c457e19
@@ -17,6 +17,8 @@ gemfile: gemfiles/chefspec.gemfile
17
17
 
18
18
  env:
19
19
  - CHEF_VERSION=master
20
+ - CHEF_VERSION=12.7.2
21
+ - CHEF_VERSION=12.6.0
20
22
  - CHEF_VERSION=12.5.1
21
23
  - CHEF_VERSION=12.4.3
22
24
  - CHEF_VERSION=12.4.0
@@ -1,6 +1,20 @@
1
1
  CHANGELOG for ChefSpec
2
2
  ======================
3
3
 
4
+ ## 4.6.0 (March 7, 2016)
5
+
6
+ Improvements
7
+
8
+ - Add support for adding `berkshelf_options` to the RSpec config
9
+ - Add `chocolately_package` matches
10
+ - Support `do..end` style syntax in block expectations
11
+ - Output a diff when multi-line resource parameters are unmatched
12
+
13
+ Bugfixes
14
+
15
+ - Update tests to include better descriptions and feature names
16
+ - Add support for Policyfile workflow
17
+
4
18
  ## 4.5.0 (December 4, 2015)
5
19
 
6
20
  Improvements
data/README.md CHANGED
@@ -145,6 +145,16 @@ Requiring this file will:
145
145
  - Download all the dependencies listed in your `Berksfile` into the temporary directory
146
146
  - Set ChefSpec's `cookbook_path` to the temporary directory
147
147
 
148
+ You can customize the list of options passed to the installation command using the `berkshelf_options` RSpec configuration:
149
+
150
+ ```ruby
151
+ RSpec.configuration do |config|
152
+ config.berkshelf_options = { only: "my-group" }
153
+ end
154
+ ```
155
+
156
+ This is a Ruby hash and valid options include `only` and `except`.
157
+
148
158
  ### Librarian
149
159
 
150
160
  If you are using Librarian, simply require `chefspec/librarian` in your `spec_helper` after requiring `chefspec`:
@@ -244,7 +254,7 @@ require 'chefspec'
244
254
  describe 'example::default' do
245
255
  let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
246
256
 
247
- it 'does something' do
257
+ it 'installs apache2' do
248
258
  expect(chef_run).to install_package('apache2')
249
259
  end
250
260
  end
@@ -260,7 +270,7 @@ require 'chefspec'
260
270
  describe 'example::default' do
261
271
  let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
262
272
 
263
- it 'does something' do
273
+ it 'adds the member vagrant to the docker group' do
264
274
  expect(chef_run).to modify_group('docker').with(members: ['vagrant'])
265
275
  end
266
276
  end
@@ -981,9 +991,34 @@ it 'raises an error' do
981
991
  end
982
992
  ```
983
993
 
994
+ Testing Multiple Recipes
995
+ -------------
996
+ Even though ChefSpec is cookbook-centric, you can still converge multiple recipes in a single `ChefSpec::SoloRunner` instance. Given a cookbook "sandwich" with recipes "bacon", "lettuce" and "tomato":
997
+
998
+ ```ruby
999
+ # cookbooks/sandwich/recipes/bacon.rb
1000
+ package 'bacon'
1001
+
1002
+ # cookbooks/sandwich/recipes/lettuce.rb
1003
+ package 'lettuce'
1004
+
1005
+ # cookbooks/sandwich/recipes/tomato.rb
1006
+ package 'tomato'
1007
+ ```
1008
+
1009
+ ```ruby
1010
+ let(:chef_run) { ChefSpec::SoloRunner.converge('sandwich::bacon', 'sandwich::lettuce', 'sandwich::tomato') }
1011
+ ```
1012
+
1013
+ ```ruby
1014
+ expect(chef_run).to install_package('bacon')
1015
+ expect(chef_run).to install_package('lettuce')
1016
+ expect(chef_run).to install_package('tomato')
1017
+ ```
1018
+
984
1019
  Testing Roles
985
1020
  -------------
986
- Even though ChefSpec is cookbook-centric, you can still converge multiple recipes and roles in a single `ChefSpec::SoloRunner` instance. Given a cookbook "bacon" with a default recipe:
1021
+ Roles can also be used in a single `ChefSpec::SoloRunner` instance. Given a cookbook "bacon" with a default recipe:
987
1022
 
988
1023
  ```ruby
989
1024
  # cookbooks/bacon/recipes/default.rb
@@ -0,0 +1,6 @@
1
+ chocolatey_package '7zip'
2
+
3
+ chocolatey_package 'git' do
4
+ version '2.7.1'
5
+ options '--params /GitAndUnixToolsOnPath'
6
+ end
@@ -0,0 +1,8 @@
1
+ chocolatey_package '7zip' do
2
+ action :remove
3
+ end
4
+
5
+ chocolatey_package 'git' do
6
+ version '2.7.1'
7
+ action :remove
8
+ end
@@ -0,0 +1,8 @@
1
+ chocolatey_package '7zip' do
2
+ action :upgrade
3
+ end
4
+
5
+ chocolatey_package 'git' do
6
+ version '2.7.1'
7
+ action :upgrade
8
+ end
@@ -0,0 +1,21 @@
1
+ require 'chefspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.platform = 'windows'
5
+ config.version = '2012R2'
6
+ end
7
+
8
+ describe 'chocolatey_package::install' do
9
+ let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
10
+
11
+ it 'installs a package' do
12
+ expect(chef_run).to install_chocolatey_package('7zip')
13
+ end
14
+
15
+ it 'installs a specific version of a package with options' do
16
+ expect(chef_run).to install_chocolatey_package('git').with(
17
+ version: %w(2.7.1),
18
+ options: '--params /GitAndUnixToolsOnPath'
19
+ )
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'chefspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.platform = 'windows'
5
+ config.version = '2012R2'
6
+ end
7
+
8
+ describe 'chocolatey_package::remove' do
9
+ let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
10
+
11
+ it 'removes a package' do
12
+ expect(chef_run).to remove_chocolatey_package('7zip')
13
+ end
14
+
15
+ it 'removes a specific version of a package with options' do
16
+ expect(chef_run).to remove_chocolatey_package('git').with(
17
+ version: %w(2.7.1)
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'chefspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.platform = 'windows'
5
+ config.version = '2012R2'
6
+ end
7
+
8
+ describe 'chocolatey_package::upgrade' do
9
+ let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
10
+
11
+ it 'upgrades a package' do
12
+ expect(chef_run).to upgrade_chocolatey_package('7zip')
13
+ end
14
+
15
+ it 'upgrades a specific version of a package with options' do
16
+ expect(chef_run).to upgrade_chocolatey_package('git').with(
17
+ version: %w(2.7.1)
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ @not_chef_11_14_2
2
+ @not_chef_11_14_6
3
+ @not_chef_11_16_0
4
+ @not_chef_11_16_2
5
+ @not_chef_11_16_4
6
+ @not_chef_11_18_0
7
+ @not_chef_11_18_6
8
+ @not_chef_12_0_3
9
+ @not_chef_12_1_0
10
+ @not_chef_12_1_1
11
+ @not_chef_12_1_2
12
+ @not_chef_12_2_1
13
+ @not_chef_12_3_0
14
+ @not_chef_12_4_0
15
+ @not_chef_12_4_3
16
+ @not_chef_12_5_1
17
+ @not_chef_12_6_0
18
+ Feature: The chocolatey_package matcher
19
+ Background:
20
+ * I am using the "chocolatey_package" cookbook
21
+
22
+ Scenario Outline: Running specs
23
+ * I successfully run `rspec spec/<Matcher>_spec.rb`
24
+ * the output should contain "0 failures"
25
+ Examples:
26
+ | Matcher |
27
+ | install |
28
+ | remove |
29
+ | upgrade |
@@ -27,6 +27,7 @@ end
27
27
  require_relative 'api/apt_package'
28
28
  require_relative 'api/batch'
29
29
  require_relative 'api/chef_gem'
30
+ require_relative 'api/chocolatey_package'
30
31
  require_relative 'api/cookbook_file'
31
32
  require_relative 'api/cron'
32
33
  require_relative 'api/deploy'
@@ -0,0 +1,107 @@
1
+ module ChefSpec::API
2
+ # @since 4.6.0
3
+ module ChocolateyPackageMatchers
4
+ ChefSpec.define_matcher :chocolatey_package
5
+ #
6
+ # Assert that a +chocolatey_package+ resource exists in the Chef run with the
7
+ # action +:install+. Given a Chef Recipe that installs "7zip" as a
8
+ # +chocolatey_package+:
9
+ #
10
+ # chocolatey_package '7zip' do
11
+ # action :install
12
+ # end
13
+ #
14
+ # The Examples section demonstrates the different ways to test a
15
+ # +chocolatey_package+ resource with ChefSpec.
16
+ #
17
+ # @example Assert that a +chocolatey_package+ was installed
18
+ # expect(chef_run).to install_chocolatey_package('7zip')
19
+ #
20
+ # @example Assert that a +chocolatey_package+ was installed with attributes
21
+ # expect(chef_run).to install_chocolatey_package('git').with(
22
+ # version: %w(2.7.1),
23
+ # options: '--params /GitAndUnixToolsOnPath'
24
+ # )
25
+ #
26
+ # @example Assert that a +chocolatey_package+ was _not_ installed
27
+ # expect(chef_run).to_not install_chocolatey_package('flashplayeractivex')
28
+ #
29
+ # @param [String, Regex] resource_name
30
+ # the name of the resource to match
31
+ #
32
+ # @return [ChefSpec::Matchers::ResourceMatcher]
33
+ #
34
+ def install_chocolatey_package(resource_name)
35
+ ChefSpec::Matchers::ResourceMatcher.new(:chocolatey_package, :install, resource_name)
36
+ end
37
+
38
+ #
39
+ # Assert that a +chocolatey_package+ resource exists in the Chef run with the
40
+ # action +:remove+. Given a Chef Recipe that removes "7zip" as a
41
+ # +chocolatey_package+:
42
+ #
43
+ # chocolatey_package '7zip' do
44
+ # action :remove
45
+ # end
46
+ #
47
+ # To test the content rendered by a +chocolatey_package+, see
48
+ # {ChefSpec::API::RenderFileMatchers}.
49
+ #
50
+ # The Examples section demonstrates the different ways to test a
51
+ # +chocolatey_package+ resource with ChefSpec.
52
+ #
53
+ # @example Assert that a +chocolatey_package+ was removed
54
+ # expect(chef_run).to remove_chocolatey_package('7zip')
55
+ #
56
+ # @example Assert that a specific +chocolatey_package+ version was removed
57
+ # expect(chef_run).to remove_chocolatey_package('7zip').with(
58
+ # version: %w(15.14)
59
+ # )
60
+ #
61
+ # @example Assert that a +chocolatey_package+ was _not_ removed
62
+ # expect(chef_run).to_not remove_chocolatey_package('7zip')
63
+ #
64
+ #
65
+ # @param [String, Regex] resource_name
66
+ # the name of the resource to match
67
+ #
68
+ # @return [ChefSpec::Matchers::ResourceMatcher]
69
+ #
70
+ def remove_chocolatey_package(resource_name)
71
+ ChefSpec::Matchers::ResourceMatcher.new(:chocolatey_package, :remove, resource_name)
72
+ end
73
+
74
+ #
75
+ # Assert that a +chocolatey_package+ resource exists in the Chef run with the
76
+ # action +:upgrade+. Given a Chef Recipe that upgrades "7zip" as a
77
+ # +chocolatey_package+:
78
+ #
79
+ # chocolatey_package '7zip' do
80
+ # action :upgrade
81
+ # end
82
+ #
83
+ # The Examples section demonstrates the different ways to test a
84
+ # +chocolatey_package+ resource with ChefSpec.
85
+ #
86
+ # @example Assert that a +chocolatey_package+ was upgraded
87
+ # expect(chef_run).to upgrade_chocolatey_package('7zip')
88
+ #
89
+ # @example Assert that a +chocolatey_package+ was upgraded with attributes
90
+ # expect(chef_run).to upgrade_chocolatey_package('git').with(
91
+ # version: %w(2.7.1),
92
+ # options: '-params "/GitAndUnixToolsOnPath"'
93
+ # )
94
+ #
95
+ # @example Assert that a +chocolatey_package+ was _not_ upgraded
96
+ # expect(chef_run).to_not upgrade_chocolatey_package('flashplayeractivex')
97
+ #
98
+ # @param [String, Regex] resource_name
99
+ # the name of the resource to match
100
+ #
101
+ # @return [ChefSpec::Matchers::ResourceMatcher]
102
+ #
103
+ def upgrade_chocolatey_package(resource_name)
104
+ ChefSpec::Matchers::ResourceMatcher.new(:chocolatey_package, :upgrade, resource_name)
105
+ end
106
+ end
107
+ end
@@ -21,7 +21,13 @@ module ChefSpec
21
21
  # Setup and install the necessary dependencies in the temporary directory.
22
22
  #
23
23
  def setup!
24
- berksfile = ::Berkshelf::Berksfile.from_file('Berksfile')
24
+ # Get the list of Berkshelf options
25
+ opts = RSpec.configuration.berkshelf_options
26
+ if !opts.is_a?(Hash)
27
+ raise InvalidBerkshelfOptions(value: opts.inspect)
28
+ end
29
+
30
+ berksfile = ::Berkshelf::Berksfile.from_file('Berksfile', opts)
25
31
 
26
32
  # Grab a handle to tmpdir, since Berkshelf 2 modifies it a bit
27
33
  tmpdir = File.join(@tmpdir, 'cookbooks')
@@ -38,5 +38,7 @@ module ChefSpec
38
38
  class GemLoadError < ChefSpecError; end
39
39
 
40
40
  class MayNeedToSpecifyPlatform < ChefSpecError; end
41
+
42
+ class InvalidBerkshelfOptions < ChefSpecError; end
41
43
  end
42
44
  end
@@ -1,5 +1,6 @@
1
1
  module ChefSpec::Matchers
2
2
  class RenderFileMatcher
3
+ attr_reader :expected_content
3
4
  def initialize(path)
4
5
  @path = path
5
6
  end
@@ -20,7 +21,7 @@ module ChefSpec::Matchers
20
21
  raise ArgumentError, "Cannot specify expected content and a block!"
21
22
  elsif expected_content
22
23
  @expected_content = expected_content
23
- elsif block
24
+ elsif block_given?
24
25
  @expected_content = block
25
26
  else
26
27
  raise ArgumentError, "Must specify expected content or a block!"
@@ -1,3 +1,6 @@
1
+ require 'rspec/matchers/expecteds_for_multiple_diffs'
2
+ require 'rspec/expectations/fail_with'
3
+
1
4
  module ChefSpec::Matchers
2
5
  class ResourceMatcher
3
6
  def initialize(resource_name, expected_action, expected_identity)
@@ -60,10 +63,14 @@ module ChefSpec::Matchers
60
63
  %Q{expected "#{resource.to_s}" to be run at converge time}
61
64
  end
62
65
  else
63
- %Q{expected "#{resource.to_s}" to have parameters:} \
66
+ message = %Q{expected "#{resource.to_s}" to have parameters:} \
64
67
  "\n\n" \
65
68
  " " + unmatched_parameters.collect { |parameter, h|
66
- "#{parameter} #{h[:expected].inspect}, was #{h[:actual].inspect}"
69
+ msg = "#{parameter} #{h[:expected].inspect}, was #{h[:actual].inspect}"
70
+ diff = ::RSpec::Matchers::ExpectedsForMultipleDiffs.from(h[:expected]) \
71
+ .message_with_diff(message, ::RSpec::Expectations::differ, h[:actual])
72
+ msg += diff if diff
73
+ msg
67
74
  }.join("\n ")
68
75
  end
69
76
  else
@@ -23,7 +23,6 @@ module ChefSpec
23
23
  #
24
24
  def setup!
25
25
  policyfile_path = File.join(Dir.pwd, 'Policyfile.rb')
26
- cbdir = File.join(@tmpdir, 'cookbooks')
27
26
 
28
27
  installer = ChefDK::PolicyfileServices::Install.new(
29
28
  policyfile: policyfile_path,
@@ -40,7 +39,12 @@ module ChefSpec
40
39
  FileUtils.rm_rf(@tmpdir)
41
40
  exporter.run
42
41
 
43
- ::RSpec.configure { |config| config.cookbook_path = cbdir }
42
+ ::RSpec.configure do |config|
43
+ config.cookbook_path = [
44
+ File.join(@tmpdir, 'cookbooks'),
45
+ File.join(@tmpdir, 'cookbook_artifacts')
46
+ ]
47
+ end
44
48
  end
45
49
 
46
50
  #
@@ -9,6 +9,7 @@ RSpec.configure do |config|
9
9
  ChefSpec::Stubs::SearchRegistry.reset!
10
10
  end
11
11
 
12
+ config.add_setting :berkshelf_options, default: {}
12
13
  config.add_setting :cookbook_path
13
14
  config.add_setting :role_path
14
15
  config.add_setting :environment_path
@@ -1,3 +1,3 @@
1
1
  module ChefSpec
2
- VERSION = '4.5.0'
2
+ VERSION = '4.6.0'
3
3
  end
@@ -6,6 +6,17 @@ describe ChefSpec::Matchers::RenderFileMatcher do
6
6
  let(:chef_run) { double('chef run', find_resource: file) }
7
7
  subject { described_class.new(path) }
8
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.call
16
+ ).to eq('Does not raise ArgumentError')
17
+ end
18
+ end
19
+
9
20
  describe '#failure_message' do
10
21
  it 'has the right value' do
11
22
  subject.matches?(chef_run)
@@ -0,0 +1,4 @@
1
+ The currently configured value for `berkshelf_options` appears to be invalid.
2
+ This attribute must be a Ruby hash with symbol keys. The current value is:
3
+
4
+ <%= @value %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chefspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Crump
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-10 00:00:00.000000000 Z
12
+ date: 2016-03-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef
@@ -162,6 +162,12 @@ files:
162
162
  - examples/chef_gem/spec/reconfig_spec.rb
163
163
  - examples/chef_gem/spec/remove_spec.rb
164
164
  - examples/chef_gem/spec/upgrade_spec.rb
165
+ - examples/chocolatey_package/recipes/install.rb
166
+ - examples/chocolatey_package/recipes/remove.rb
167
+ - examples/chocolatey_package/recipes/upgrade.rb
168
+ - examples/chocolatey_package/spec/install_spec.rb
169
+ - examples/chocolatey_package/spec/remove_spec.rb
170
+ - examples/chocolatey_package/spec/upgrade_spec.rb
165
171
  - examples/compile_time/recipes/default.rb
166
172
  - examples/compile_time/spec/default_spec.rb
167
173
  - examples/cookbook_file/recipes/create.rb
@@ -569,6 +575,7 @@ files:
569
575
  - features/batch.feature
570
576
  - features/cached.feature
571
577
  - features/chef_gem.feature
578
+ - features/chocolatey_package.feature
572
579
  - features/compile_time.feature
573
580
  - features/cookbook_file.feature
574
581
  - features/cron.feature
@@ -645,6 +652,7 @@ files:
645
652
  - lib/chefspec/api/apt_package.rb
646
653
  - lib/chefspec/api/batch.rb
647
654
  - lib/chefspec/api/chef_gem.rb
655
+ - lib/chefspec/api/chocolatey_package.rb
648
656
  - lib/chefspec/api/cookbook_file.rb
649
657
  - lib/chefspec/api/cron.rb
650
658
  - lib/chefspec/api/deploy.rb
@@ -777,6 +785,7 @@ files:
777
785
  - templates/coverage/human.erb
778
786
  - templates/errors/cookbook_path_not_found.erb
779
787
  - templates/errors/gem_load_error.erb
788
+ - templates/errors/invalid_berkshelf_options.erb
780
789
  - templates/errors/may_need_to_specify_platform.erb
781
790
  - templates/errors/no_conversion_error.erb
782
791
  - templates/errors/not_stubbed.erb
@@ -810,6 +819,7 @@ test_files:
810
819
  - features/batch.feature
811
820
  - features/cached.feature
812
821
  - features/chef_gem.feature
822
+ - features/chocolatey_package.feature
813
823
  - features/compile_time.feature
814
824
  - features/cookbook_file.feature
815
825
  - features/cron.feature