ecomdev-chefspec 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +79 -0
- data/Rakefile +14 -0
- data/ecomdev-chefspec.gemspec +24 -0
- data/lib/ecomdev-chefspec.rb +2 -0
- data/lib/ecomdev/chefspec.rb +9 -0
- data/lib/ecomdev/chefspec/api.rb +3 -0
- data/lib/ecomdev/chefspec/api/include_recipe.rb +13 -0
- data/lib/ecomdev/chefspec/configuration.rb +86 -0
- data/lib/ecomdev/chefspec/resource/matcher.rb +126 -0
- data/lib/ecomdev/chefspec/resource/matcher/dsl.rb +23 -0
- data/lib/ecomdev/chefspec/resource/matcher/helper.rb +17 -0
- data/lib/ecomdev/chefspec/stub/include_recipe.rb +71 -0
- data/lib/ecomdev/chefspec/version.rb +6 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/configuration_spec.rb +138 -0
- data/spec/unit/matcher/dsl_spec.rb +45 -0
- data/spec/unit/matcher/helper_spec.rb +58 -0
- data/spec/unit/matcher_spec.rb +250 -0
- data/spec/unit/stub/include_recipe/test_spec.rb +33 -0
- data/spec/unit/stub/include_recipe_spec.rb +55 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 01543e12806b48f668ac7ad1fd5ed983ad3d0277
|
4
|
+
data.tar.gz: 07d25f11fc0966b44312207590c7aa81c5ec1b4c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca516b00f234b7120a53974fd1d218fe5a82387c1e37b271c88b3cd8cc7f0e4f29012577b8c3136e2e53417e5694b7657c289905ba1889537cd19b0cd3b5a359
|
7
|
+
data.tar.gz: 11059f3e473023a9c6ef027e0d05560426954b8cb3bb69434f920d70c628f4e58f4ad9c09022a31058e3238d8562e81df8e7ea226d75c0934970afd0f1480b77
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ivan Chepurnyi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# EcomDev::ChefSpec
|
2
|
+
|
3
|
+
A set of valuable helper to make writing ChefSpecs even more easier.
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
* You can define matchers for your LWRP and HWRP by using DSL based file in your specs directory.
|
8
|
+
* By default it looks in `spec/matchers.rb`, `spec/matchers/*.rb`, `spec/library/matchers.rb`, `spec/library/matchers/*.rb`
|
9
|
+
* Example of the file DSL
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
matcher :resource_name, :action
|
13
|
+
matcher :resource_name, [:delete, :create]
|
14
|
+
runner :resource_name
|
15
|
+
```
|
16
|
+
|
17
|
+
* It automatically includes matchers from other recipes, that contain such a Ruby file
|
18
|
+
|
19
|
+
* By default it mocks any inclusion of recipes, except described one. You can specify additional one by calling `allow_recipe` in spec DSL.
|
20
|
+
* Allows to supply additional cookbook directory for your specs. Just add in `spec_helper.rb` file the following code
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
EcomDev::ChefSpec::Configuration.cookbook_path('path/to/your/test/cookbooks')
|
24
|
+
EcomDev::ChefSpec::Configuration.cookbook_path('another/path/to/your/test/cookbooks')
|
25
|
+
```
|
26
|
+
|
27
|
+
It will automatically include the following paths for cookbook search:
|
28
|
+
|
29
|
+
* Berkshelf or Librarian path if any of those was included before
|
30
|
+
* `path/to/your/test/cookbooks`
|
31
|
+
* `another/path/to/your/test/cookbooks`
|
32
|
+
|
33
|
+
|
34
|
+
## Build Status
|
35
|
+
|
36
|
+
[](https://travis-ci.org/IvanChepurnyi/ecomdev-chefspec) **Next Release Branch**
|
37
|
+
|
38
|
+
[](https://travis-ci.org/IvanChepurnyi/ecomdev-chefspec) **Current Stable Release**
|
39
|
+
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
Add this line to your application's Gemfile:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
gem 'ecomdev-chefspec'
|
47
|
+
```
|
48
|
+
|
49
|
+
And then execute:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
bundle
|
53
|
+
```
|
54
|
+
|
55
|
+
Or install it yourself as:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
gem install ecomdev-chefspec
|
59
|
+
```
|
60
|
+
|
61
|
+
## Usage
|
62
|
+
|
63
|
+
Inside of your specs helper you should include this library after chefspec
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'ecomdev/chefspec'
|
67
|
+
```
|
68
|
+
|
69
|
+
Please note, that you should include it in the end, after all the chef spec files are included. E.g. if you use bershelf loader for your cookbooks, you should include `ecomdev/chefspec` after you've included `chefspec/berkshelf`
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it ( https://github.com/IvanChepurnyi/ecomdev-chefspec/fork )
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:unit) do |t|
|
5
|
+
t.rspec_opts = [].tap do |a|
|
6
|
+
a.push('--color')
|
7
|
+
a.push('--format progress')
|
8
|
+
end.join(' ')
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Run all tests'
|
12
|
+
task :test => [:unit]
|
13
|
+
|
14
|
+
task :default => [:test]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ecomdev/chefspec/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'ecomdev-chefspec'
|
8
|
+
spec.version = EcomDev::ChefSpec::VERSION
|
9
|
+
spec.authors = ['Ivan Chepurnyi']
|
10
|
+
spec.email = ['ivan.chepurnyi@ecomdev.org']
|
11
|
+
spec.summary = 'A collection of helpers for chef spec, to make easier writing recipe specs'
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = 'https://github.com/IvanChepurnyi/ecomdev-chefspec'
|
14
|
+
spec.license = 'GPLv3'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'chefspec', '~> 4.0'
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'chefspec' unless defined?(ChefSpec) # Require chef spec only if it is not required before
|
2
|
+
|
3
|
+
require_relative 'chefspec/version'
|
4
|
+
require_relative 'chefspec/configuration'
|
5
|
+
require_relative 'chefspec/resource/matcher'
|
6
|
+
require_relative 'chefspec/api'
|
7
|
+
|
8
|
+
# Registers Resource Matchers callbacks for RSpec
|
9
|
+
EcomDev::ChefSpec::Resource::Matcher.register
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../stub/include_recipe'
|
2
|
+
|
3
|
+
module ChefSpec::API
|
4
|
+
module EcomDevIncludeRecipe
|
5
|
+
def allow_recipe(*recipe_name)
|
6
|
+
recipe_name.flatten.each do |recipe|
|
7
|
+
EcomDev::ChefSpec::Stub::IncludeRecipe.allow_recipe(recipe)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
EcomDev::ChefSpec::Configuration.callback(EcomDev::ChefSpec::Stub::IncludeRecipe)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module EcomDev
|
2
|
+
module ChefSpec
|
3
|
+
class Configuration
|
4
|
+
class << self
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :instance, :reset, :setup!, :teardown!, :cookbook_path, :callback
|
7
|
+
end
|
8
|
+
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_accessor :cookbook_paths
|
12
|
+
attr_accessor :callbacks
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@cookbook_paths = []
|
16
|
+
@callbacks = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup!
|
20
|
+
unless cookbook_paths.empty?
|
21
|
+
original_path = RSpec.configuration.cookbook_path
|
22
|
+
if original_path.nil?
|
23
|
+
original_path = []
|
24
|
+
elsif original_path.is_a?(String)
|
25
|
+
original_path = [original_path]
|
26
|
+
end
|
27
|
+
|
28
|
+
cookbook_paths.each do |path|
|
29
|
+
original_path << path unless original_path.include?(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
RSpec.configuration.cookbook_path = original_path
|
33
|
+
end
|
34
|
+
|
35
|
+
invoke_callbacks(__method__)
|
36
|
+
end
|
37
|
+
|
38
|
+
def teardown!
|
39
|
+
invoke_callbacks(__method__)
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset
|
43
|
+
@cookbook_paths = []
|
44
|
+
@callbacks = []
|
45
|
+
end
|
46
|
+
|
47
|
+
def cookbook_path(path)
|
48
|
+
@cookbook_paths << path unless cookbook_paths.include?(path)
|
49
|
+
end
|
50
|
+
|
51
|
+
def callback(callback)
|
52
|
+
@callbacks << callback unless callbacks.include?(callback)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.register
|
56
|
+
if defined?(ChefSpec::Berkshelf)
|
57
|
+
klass = ChefSpec::Berkshelf
|
58
|
+
elsif defined?(ChefSpec::Librarian)
|
59
|
+
klass = ChefSpec::Librarian
|
60
|
+
else
|
61
|
+
klass = false
|
62
|
+
end
|
63
|
+
|
64
|
+
if klass
|
65
|
+
klass.class_exec do
|
66
|
+
alias_method :old_setup!, :setup!
|
67
|
+
|
68
|
+
def setup!
|
69
|
+
old_setup!
|
70
|
+
EcomDev::ChefSpec::Configuration.setup!
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
RSpec.configure do
|
75
|
+
before(:suite) { EcomDev::ChefSpec::Configuration.setup! }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def invoke_callbacks(method)
|
82
|
+
callbacks.select { |c| c.respond_to?(method) }.each { |c| c.send(method) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require_relative 'matcher/dsl'
|
2
|
+
require_relative 'matcher/helper'
|
3
|
+
|
4
|
+
module EcomDev
|
5
|
+
module ChefSpec
|
6
|
+
module Resource
|
7
|
+
class Matcher
|
8
|
+
class << self
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators :instance, :setup!, :teardown!, :register, :matcher, :runner
|
11
|
+
end
|
12
|
+
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
attr_reader :matchers, :runners
|
16
|
+
attr_accessor :possible_directories
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@matchers = {}
|
20
|
+
@runners = []
|
21
|
+
@possible_directories = [
|
22
|
+
File.join('spec', 'matchers.rb'),
|
23
|
+
File.join('spec', 'matchers', '*.rb'),
|
24
|
+
File.join('spec', 'libraries', 'matchers.rb'),
|
25
|
+
File.join('spec', 'libraries', 'matchers/*.rb')
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup!
|
30
|
+
load_matchers
|
31
|
+
extend_api
|
32
|
+
end
|
33
|
+
|
34
|
+
def teardown!
|
35
|
+
@matchers = {}
|
36
|
+
@runners = []
|
37
|
+
Helper.reset
|
38
|
+
end
|
39
|
+
|
40
|
+
def extend_api
|
41
|
+
matchers.each do |method, info|
|
42
|
+
Helper.add(method) do |identity|
|
43
|
+
ChefSpec::Matchers::ResourceMatcher.new(info.resource, info.action, identity)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def matcher(resource_name, action)
|
49
|
+
if resource_name.is_a?(Array)
|
50
|
+
resource_name.each do |r|
|
51
|
+
matcher(r, action)
|
52
|
+
end
|
53
|
+
elsif action.is_a?(Array)
|
54
|
+
action.each do |a|
|
55
|
+
matcher(resource_name, a)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
add_matcher(resource_name, action)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def runner(resource_name)
|
63
|
+
if resource_name.is_a?(Array)
|
64
|
+
resource_name.each do |r|
|
65
|
+
runner(r)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
add_runner(resource_name)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_matchers
|
73
|
+
files = search_patterns.map { |pattern| Dir.glob(pattern) }.flatten
|
74
|
+
files.each {|file| load_matcher_file(file) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_matcher_file(file)
|
78
|
+
DSL.load(file)
|
79
|
+
end
|
80
|
+
|
81
|
+
def search_patterns
|
82
|
+
cookbook_path = RSpec.configuration.cookbook_path
|
83
|
+
if cookbook_path.nil? ||
|
84
|
+
cookbook_path.is_a?(String) && cookbook_path.empty?
|
85
|
+
return []
|
86
|
+
end
|
87
|
+
|
88
|
+
cookbook_path = [cookbook_path] if cookbook_path.is_a?(String)
|
89
|
+
|
90
|
+
search_patterns = []
|
91
|
+
possible_directories.each do |directory|
|
92
|
+
cookbook_path.each do |cookbook_path|
|
93
|
+
search_patterns << File.join(cookbook_path, '*', directory)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
search_patterns
|
97
|
+
end
|
98
|
+
|
99
|
+
def register
|
100
|
+
EcomDev::ChefSpec::Configuration.callback(self.class.instance)
|
101
|
+
|
102
|
+
RSpec.configure do |config|
|
103
|
+
config.include Helper
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def add_matcher(resource, action)
|
109
|
+
resource_name = resource.to_s
|
110
|
+
action_name = action.to_s
|
111
|
+
matcher_name = action_name + '_' + resource_name
|
112
|
+
matcher = matcher_name.to_sym
|
113
|
+
unless @matchers.key?(matcher)
|
114
|
+
@matchers[matcher] = {action: action_name.to_sym, resource: resource_name.to_sym}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_runner(resource_name)
|
119
|
+
resource = resource_name.to_sym
|
120
|
+
@runners << resource unless @runners.include?(resource)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EcomDev
|
2
|
+
module ChefSpec
|
3
|
+
module Resource
|
4
|
+
class Matcher
|
5
|
+
class DSL
|
6
|
+
def matcher(resource, action)
|
7
|
+
EcomDev::ChefSpec::Resource::Matcher.matcher(resource, action)
|
8
|
+
end
|
9
|
+
|
10
|
+
def runner(resource)
|
11
|
+
EcomDev::ChefSpec::Resource::Matcher.runner(resource)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load(filename)
|
15
|
+
dsl = new
|
16
|
+
dsl.instance_eval(File.read(filename), filename)
|
17
|
+
dsl
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module EcomDev
|
2
|
+
module ChefSpec
|
3
|
+
module Resource
|
4
|
+
class Matcher
|
5
|
+
module Helper
|
6
|
+
def self.reset
|
7
|
+
instance_methods.each { |method| remove_method(method) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.add(method, &block)
|
11
|
+
define_method(method, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module EcomDev::ChefSpec::Stub
|
2
|
+
class IncludeRecipe
|
3
|
+
class << self
|
4
|
+
extend Forwardable
|
5
|
+
def_delegators :instance, :teardown!, :setup!, :allow_recipe, :reset
|
6
|
+
end
|
7
|
+
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_accessor :allowed_recipes, :loaded_recipes
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@allowed_recipes = []
|
14
|
+
@loaded_recipes = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow_recipe(recipe)
|
18
|
+
@allowed_recipes << recipe
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
@allowed_recipes = []
|
23
|
+
@loaded_recipes = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def before_example(object)
|
27
|
+
stub_include(object) unless allowed_recipes.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_include(object)
|
31
|
+
# Don't worry about external cookbook dependencies
|
32
|
+
object.allow_any_instance_of(Chef::Cookbook::Metadata).to object.receive(:depends)
|
33
|
+
|
34
|
+
# Test each recipe in isolation, regardless of includes
|
35
|
+
object.allow_any_instance_of(Chef::RunContext).to object.receive(:loaded_recipe?) do |run_context, recipe_name|
|
36
|
+
run_context.loaded_recipes.include?(recipe_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
object.allow_any_instance_of(Chef::RunContext).to object.receive(:include_recipe) do |run_context, *recipe_names|
|
40
|
+
recipe_names.flatten.each do |recipe_name|
|
41
|
+
@loaded_recipes << recipe_name
|
42
|
+
if allowed_recipes.include?(recipe_name)
|
43
|
+
run_context.load_recipe(recipe_name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
loaded_recipes
|
47
|
+
end
|
48
|
+
|
49
|
+
object.allow_any_instance_of(Chef::RunContext).to object.receive(:loaded_recipes) do
|
50
|
+
loaded_recipes
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def after_example(object)
|
55
|
+
reset
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
RSpec.configure do |c|
|
61
|
+
c.before(:each) do
|
62
|
+
if respond_to?(:described_recipe) && described_recipe.match(/^[a-z_0-9]+::[a-z_0-9]+$/)
|
63
|
+
EcomDev::ChefSpec::Stub::IncludeRecipe.allow_recipe described_recipe
|
64
|
+
end
|
65
|
+
EcomDev::ChefSpec::Stub::IncludeRecipe.instance.before_example(self)
|
66
|
+
end
|
67
|
+
|
68
|
+
c.after(:each) do
|
69
|
+
EcomDev::ChefSpec::Stub::IncludeRecipe.instance.after_example(self)
|
70
|
+
end
|
71
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EcomDev::ChefSpec::Configuration do
|
4
|
+
before(:each) do
|
5
|
+
Singleton.__init__(described_class)
|
6
|
+
end
|
7
|
+
|
8
|
+
def callback_klass
|
9
|
+
Class.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#cookbook_path' do
|
13
|
+
it 'it adds a new cookbook path to path stack' do
|
14
|
+
described_class.cookbook_path('test/path')
|
15
|
+
expect(described_class.instance.cookbook_paths).to contain_exactly('test/path')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'it adds cookbook path only once' do
|
19
|
+
described_class.cookbook_path('test/path')
|
20
|
+
described_class.cookbook_path('test/path')
|
21
|
+
expect(described_class.instance.cookbook_paths).to contain_exactly('test/path')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#callback' do
|
26
|
+
it 'it adds a new callback' do
|
27
|
+
callback = callback_klass.new
|
28
|
+
described_class.callback(callback)
|
29
|
+
expect(described_class.instance.callbacks).to contain_exactly(callback)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'it adds a new callback only once' do
|
33
|
+
callback = callback_klass.new
|
34
|
+
described_class.callback(callback)
|
35
|
+
described_class.callback(callback)
|
36
|
+
callback2 = callback_klass.new
|
37
|
+
described_class.callback(callback2)
|
38
|
+
expect(described_class.instance.callbacks).to contain_exactly(callback, callback2)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#reset' do
|
43
|
+
it 'it removes all callbacks and cookbook_paths' do
|
44
|
+
described_class.cookbook_path('test')
|
45
|
+
described_class.cookbook_path('test2')
|
46
|
+
described_class.callback(callback_klass.new)
|
47
|
+
described_class.callback(callback_klass.new)
|
48
|
+
|
49
|
+
expect(described_class.instance.callbacks).not_to be_empty
|
50
|
+
expect(described_class.instance.cookbook_paths).not_to be_empty
|
51
|
+
|
52
|
+
described_class.reset
|
53
|
+
|
54
|
+
expect(described_class.instance.callbacks).to be_empty
|
55
|
+
expect(described_class.instance.cookbook_paths).to be_empty
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#setup!' do
|
60
|
+
it 'modifies cookbook path for RSpec configuration' do
|
61
|
+
described_class.cookbook_path('test')
|
62
|
+
described_class.cookbook_path('test2')
|
63
|
+
|
64
|
+
expect(RSpec.configuration).to receive(:cookbook_path).and_return(nil)
|
65
|
+
expect(RSpec.configuration).to receive(:cookbook_path=).with(%w(test test2))
|
66
|
+
|
67
|
+
described_class.setup!
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'add cookbook_paths after previously defined value' do
|
71
|
+
described_class.cookbook_path('test')
|
72
|
+
described_class.cookbook_path('test2')
|
73
|
+
|
74
|
+
expect(RSpec.configuration).to receive(:cookbook_path).and_return('value')
|
75
|
+
expect(RSpec.configuration).to receive(:cookbook_path=).with(%w(value test test2))
|
76
|
+
|
77
|
+
described_class.setup!
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'merges cookbook_path with previously defined values' do
|
81
|
+
described_class.cookbook_path('test')
|
82
|
+
described_class.cookbook_path('test2')
|
83
|
+
described_class.cookbook_path('value3')
|
84
|
+
|
85
|
+
expect(RSpec.configuration).to receive(:cookbook_path).and_return(%w(value value2 value3))
|
86
|
+
expect(RSpec.configuration).to receive(:cookbook_path=).with(%w(value value2 value3 test test2))
|
87
|
+
|
88
|
+
described_class.setup!
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
it 'does not modify cookbook path if it is empty' do
|
93
|
+
expect(RSpec.configuration).not_to receive(:cookbook_path)
|
94
|
+
|
95
|
+
described_class.setup!
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'calls a callback method setup! if it exists' do
|
99
|
+
callback = double('callback')
|
100
|
+
|
101
|
+
allow(callback).to receive(:respond_to?).with(:setup!).and_return(true)
|
102
|
+
expect(callback).to receive(:setup!)
|
103
|
+
described_class.callback(callback)
|
104
|
+
described_class.setup!
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'does not call a callback method setup! if it is not defined' do
|
108
|
+
callback = double('callback')
|
109
|
+
|
110
|
+
allow(callback).to receive(:respond_to?).with(:setup!).and_return(false)
|
111
|
+
expect(callback).not_to receive(:setup!)
|
112
|
+
|
113
|
+
described_class.callback(callback)
|
114
|
+
described_class.setup!
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#teardown!' do
|
119
|
+
it 'calls a callback method teardown! if it exists' do
|
120
|
+
callback = double('callback')
|
121
|
+
|
122
|
+
allow(callback).to receive(:respond_to?).with(:teardown!).and_return(true)
|
123
|
+
expect(callback).to receive(:teardown!)
|
124
|
+
described_class.callback(callback)
|
125
|
+
described_class.teardown!
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'does not call a callback method teardown! if it is not defined' do
|
129
|
+
callback = double('callback')
|
130
|
+
|
131
|
+
allow(callback).to receive(:respond_to?).with(:teardown!).and_return(false)
|
132
|
+
expect(callback).not_to receive(:teardown!)
|
133
|
+
|
134
|
+
described_class.callback(callback)
|
135
|
+
described_class.teardown!
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EcomDev::ChefSpec::Resource::Matcher::DSL do
|
4
|
+
let(:instance) { described_class.new }
|
5
|
+
let(:matcher) { EcomDev::ChefSpec::Resource::Matcher }
|
6
|
+
|
7
|
+
describe '#matcher' do
|
8
|
+
it 'calls matcher method on resource matcher instance' do
|
9
|
+
expect_any_instance_of(matcher).to receive(:matcher).with(:my_matcher, :create)
|
10
|
+
instance.matcher(:my_matcher, :create)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'calls matcher method on resource matcher instance with array arguments' do
|
14
|
+
expect_any_instance_of(matcher).to receive(:matcher).with([:my_matcher, :my_matcher2], [:create, :delete])
|
15
|
+
instance.matcher([:my_matcher, :my_matcher2], [:create, :delete])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#runner' do
|
20
|
+
it 'calls runner method on resource matcher instance' do
|
21
|
+
expect_any_instance_of(matcher).to receive(:runner).with(:my_matcher)
|
22
|
+
instance.runner(:my_matcher)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'calls runner method on resource matcher instance with array arguments' do
|
26
|
+
expect_any_instance_of(matcher).to receive(:runner).with([:my_matcher, :my_matcher2])
|
27
|
+
instance.runner([:my_matcher, :my_matcher2])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#load' do
|
32
|
+
it 'loads file dsl content' do
|
33
|
+
allow(File).to receive(:read).with('file.rb').and_return('
|
34
|
+
runner :my_custom_runner
|
35
|
+
matcher :my_custom_action, :create
|
36
|
+
matcher :another_action, [:create, :delete]')
|
37
|
+
|
38
|
+
expect_any_instance_of(matcher).to receive(:runner).with(:my_custom_runner)
|
39
|
+
expect_any_instance_of(matcher).to receive(:matcher).with(:my_custom_action, :create)
|
40
|
+
expect_any_instance_of(matcher).to receive(:matcher).with(:another_action, [:create, :delete])
|
41
|
+
|
42
|
+
expect(described_class.load('file.rb')).to be_instance_of(described_class)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EcomDev::ChefSpec::Resource::Matcher::Helper do
|
4
|
+
|
5
|
+
def create_method_body
|
6
|
+
Proc.new do |argument|
|
7
|
+
argument*argument
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#add' do
|
12
|
+
after(:each) { described_class.reset }
|
13
|
+
|
14
|
+
it 'it adds a new method' do
|
15
|
+
body = create_method_body
|
16
|
+
|
17
|
+
described_class.add(:my_custom_method, &body)
|
18
|
+
described_class.add(:another_custom_method, &body)
|
19
|
+
|
20
|
+
expect(described_class.instance_methods).to contain_exactly(:my_custom_method, :another_custom_method)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'it adds a new method only once' do
|
24
|
+
body = create_method_body do |arg|
|
25
|
+
arg
|
26
|
+
end
|
27
|
+
body2 = create_method_body do |arg|
|
28
|
+
arg*2
|
29
|
+
end
|
30
|
+
|
31
|
+
described_class.add(:another_custom_method, &body)
|
32
|
+
described_class.add(:another_custom_method, &body2)
|
33
|
+
|
34
|
+
expect(described_class.instance_methods).to contain_exactly(:another_custom_method)
|
35
|
+
klass = described_class
|
36
|
+
callable = Class.new do
|
37
|
+
include klass
|
38
|
+
end
|
39
|
+
expect(callable.new.another_custom_method(1)).to equal(1)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#reset' do
|
44
|
+
it 'it removes all defined methods for instance' do
|
45
|
+
body = create_method_body
|
46
|
+
|
47
|
+
expect(described_class.instance_methods).to be_empty
|
48
|
+
|
49
|
+
described_class.add(:my_custom_method, &body)
|
50
|
+
described_class.add(:another_custom_method, &body)
|
51
|
+
|
52
|
+
expect(described_class.instance_methods).to contain_exactly(:my_custom_method, :another_custom_method)
|
53
|
+
|
54
|
+
described_class.reset
|
55
|
+
expect(described_class.instance_methods).to be_empty
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EcomDev::ChefSpec::Resource::Matcher do
|
4
|
+
before(:each) do
|
5
|
+
Singleton.__init__(described_class)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'should set matchers to empty hash' do
|
10
|
+
expect(described_class.instance.matchers).to be_kind_of(Hash).and be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should set runners to empty array' do
|
14
|
+
expect(described_class.instance.runners).to be_kind_of(Array).and be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should set possible_directories to expected list' do
|
18
|
+
expect(described_class.instance.possible_directories)
|
19
|
+
.to be_kind_of(Array)
|
20
|
+
.and contain_exactly(
|
21
|
+
File.join('spec', 'matchers.rb'),
|
22
|
+
File.join('spec', 'matchers', '*.rb'),
|
23
|
+
File.join('spec', 'libraries', 'matchers.rb'),
|
24
|
+
File.join('spec', 'libraries', 'matchers', '*.rb')
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#search_patterns' do
|
30
|
+
it 'should include cookbook_path if it is a string' do
|
31
|
+
RSpec.configure do |config|
|
32
|
+
config.cookbook_path = File.join('test', 'directory')
|
33
|
+
end
|
34
|
+
expect(described_class.instance.search_patterns)
|
35
|
+
.to be_kind_of(Array)
|
36
|
+
.and contain_exactly(
|
37
|
+
File.join('test', 'directory', '*', 'spec', 'matchers.rb'),
|
38
|
+
File.join('test', 'directory', '*', 'spec', 'matchers', '*.rb'),
|
39
|
+
File.join('test', 'directory', '*', 'spec', 'libraries', 'matchers.rb'),
|
40
|
+
File.join('test', 'directory', '*', 'spec', 'libraries', 'matchers', '*.rb')
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should include cookbook_path if it is an array' do
|
45
|
+
RSpec.configure do |config|
|
46
|
+
config.cookbook_path = File.join('test', 'directory')
|
47
|
+
end
|
48
|
+
expect(described_class.instance.search_patterns)
|
49
|
+
.to be_kind_of(Array)
|
50
|
+
.and contain_exactly(
|
51
|
+
File.join('test', 'directory', '*', 'spec', 'matchers.rb'),
|
52
|
+
File.join('test', 'directory', '*', 'spec', 'matchers', '*.rb'),
|
53
|
+
File.join('test', 'directory', '*', 'spec', 'libraries', 'matchers.rb'),
|
54
|
+
File.join('test', 'directory', '*', 'spec', 'libraries', 'matchers', '*.rb')
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should not include any cookbook in path if it is nil' do
|
59
|
+
RSpec.configure do |config|
|
60
|
+
config.cookbook_path = nil
|
61
|
+
end
|
62
|
+
expect(described_class.instance.search_patterns)
|
63
|
+
.to be_kind_of(Array)
|
64
|
+
.and be_empty
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should not include any cookbook in path if it is empty string' do
|
68
|
+
RSpec.configure do |config|
|
69
|
+
config.cookbook_path = ''
|
70
|
+
end
|
71
|
+
expect(described_class.instance.search_patterns)
|
72
|
+
.to be_kind_of(Array)
|
73
|
+
.and be_empty
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#load_matchers' do
|
78
|
+
it 'loads matcher files from configured values' do
|
79
|
+
RSpec.configure do |config|
|
80
|
+
config.cookbook_path = 'test'
|
81
|
+
end
|
82
|
+
|
83
|
+
matcher_paths = {
|
84
|
+
File.join('test', '*', 'matchers.rb') => [
|
85
|
+
File.join('test', 'magento', 'matchers.rb'),
|
86
|
+
File.join('test', 'nginx', 'matchers.rb')
|
87
|
+
],
|
88
|
+
File.join('test', '*', 'matchers', '*.rb') => [
|
89
|
+
File.join('test', 'custom', 'matchers', 'matcher1.rb'),
|
90
|
+
File.join('test', 'custom', 'matchers', 'matcher2.rb')
|
91
|
+
]
|
92
|
+
}
|
93
|
+
|
94
|
+
matcher_paths.each_pair do |key, value|
|
95
|
+
allow(Dir).to receive(:glob).with(key).and_return(value)
|
96
|
+
value.each do |file|
|
97
|
+
expect_any_instance_of(described_class).to receive(:load_matcher_file).with(file).and_return(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
described_class.instance.possible_directories = ['matchers.rb', File.join('matchers', '*.rb')]
|
102
|
+
described_class.instance.load_matchers
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#load_matcher_file' do
|
107
|
+
it 'loads file as matcher DSL' do
|
108
|
+
dsl_class = EcomDev::ChefSpec::Resource::Matcher::DSL
|
109
|
+
expect(dsl_class).to receive(:load).with('file.rb').and_return(dsl_class.new)
|
110
|
+
described_class.instance.load_matcher_file('file.rb')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#setup!' do
|
115
|
+
it 'loads matcher files and extends api' do
|
116
|
+
expect(described_class.instance).to receive(:load_matchers).and_return([])
|
117
|
+
expect(described_class.instance).to receive(:extend_api).and_return(described_class.instance)
|
118
|
+
described_class.setup!
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#extend_api' do
|
123
|
+
after(:each) { EcomDev::ChefSpec::Resource::Matcher::Helper.reset }
|
124
|
+
it 'should add new instance methods to helper' do
|
125
|
+
described_class.matcher(:test, :create)
|
126
|
+
described_class.instance.extend_api
|
127
|
+
|
128
|
+
expect(EcomDev::ChefSpec::Resource::Matcher::Helper.instance_methods).to contain_exactly(:create_test)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#teardown!' do
|
133
|
+
it 'clears matchers and runners' do
|
134
|
+
described_class.matcher(:test, :test)
|
135
|
+
described_class.runner(:test)
|
136
|
+
described_class.setup!
|
137
|
+
described_class.teardown!
|
138
|
+
expect(described_class.instance.runners).to be_empty
|
139
|
+
expect(described_class.instance.matchers).to be_empty
|
140
|
+
expect(EcomDev::ChefSpec::Resource::Matcher::Helper.instance_methods).to be_empty
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#matcher' do
|
145
|
+
it 'adds matcher if resource and action are symbols' do
|
146
|
+
described_class.matcher(:my_custom_matcher, :create)
|
147
|
+
expect(described_class.instance.matchers).to eq(create_my_custom_matcher: {action: :create, resource: :my_custom_matcher})
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'adds matcher if resource and action are strings' do
|
151
|
+
described_class.matcher('my_custom_matcher', 'create')
|
152
|
+
expect(described_class.instance.matchers).to eq(create_my_custom_matcher: {action: :create, resource: :my_custom_matcher})
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'adds multiple matchers if actions is an array of symbols' do
|
156
|
+
described_class.matcher(:my_custom_matcher, [:create, :delete])
|
157
|
+
expect(described_class.instance.matchers).to eq(
|
158
|
+
create_my_custom_matcher: {
|
159
|
+
action: :create,
|
160
|
+
resource: :my_custom_matcher
|
161
|
+
},
|
162
|
+
delete_my_custom_matcher: {
|
163
|
+
action: :delete,
|
164
|
+
resource: :my_custom_matcher
|
165
|
+
}
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'adds multiple matchers if actions is an array of strings' do
|
170
|
+
described_class.matcher(:my_custom_matcher, %w(create delete))
|
171
|
+
expect(described_class.instance.matchers).to eq(
|
172
|
+
create_my_custom_matcher: {
|
173
|
+
action: :create,
|
174
|
+
resource: :my_custom_matcher
|
175
|
+
},
|
176
|
+
delete_my_custom_matcher: {
|
177
|
+
action: :delete,
|
178
|
+
resource: :my_custom_matcher
|
179
|
+
}
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'adds multiple matchers if resource is an array' do
|
184
|
+
described_class.matcher([:my_custom_matcher, :another_matcher], %w(create delete))
|
185
|
+
expect(described_class.instance.matchers).to eq(
|
186
|
+
create_my_custom_matcher: {
|
187
|
+
action: :create,
|
188
|
+
resource: :my_custom_matcher
|
189
|
+
},
|
190
|
+
delete_my_custom_matcher: {
|
191
|
+
action: :delete,
|
192
|
+
resource: :my_custom_matcher
|
193
|
+
},
|
194
|
+
create_another_matcher: {
|
195
|
+
action: :create,
|
196
|
+
resource: :another_matcher
|
197
|
+
},
|
198
|
+
delete_another_matcher: {
|
199
|
+
action: :delete,
|
200
|
+
resource: :another_matcher
|
201
|
+
}
|
202
|
+
)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'adds matcher only once' do
|
206
|
+
described_class.matcher('my_custom_matcher', 'create')
|
207
|
+
described_class.matcher('my_custom_matcher', 'create')
|
208
|
+
expect(described_class.instance.matchers).to eq(
|
209
|
+
create_my_custom_matcher: {
|
210
|
+
action: :create,
|
211
|
+
resource: :my_custom_matcher
|
212
|
+
}
|
213
|
+
)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#runner' do
|
218
|
+
it 'adds runner if resource is a symbol' do
|
219
|
+
described_class.runner(:my_custom_matcher)
|
220
|
+
expect(described_class.instance.runners).to contain_exactly(:my_custom_matcher)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'adds matcher if resource is a string' do
|
224
|
+
described_class.runner('my_custom_matcher')
|
225
|
+
expect(described_class.instance.runners).to contain_exactly(:my_custom_matcher)
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'adds multiple runners if resource is an array of symbols' do
|
229
|
+
described_class.runner([:my_custom_matcher, :antoher_matcher])
|
230
|
+
expect(described_class.instance.runners).to contain_exactly(
|
231
|
+
:my_custom_matcher,
|
232
|
+
:antoher_matcher
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'adds multiple runners if resource is an array of strings' do
|
237
|
+
described_class.runner(%w(my_custom_matcher antoher_matcher))
|
238
|
+
expect(described_class.instance.runners).to contain_exactly(
|
239
|
+
:my_custom_matcher,
|
240
|
+
:antoher_matcher
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'adds runner only once' do
|
245
|
+
described_class.runner('my_custom_matcher')
|
246
|
+
described_class.runner('my_custom_matcher')
|
247
|
+
expect(described_class.instance.runners).to contain_exactly(:my_custom_matcher)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
describe 'test::test' do
|
3
|
+
let (:instance) { EcomDev::ChefSpec::Stub::IncludeRecipe.instance }
|
4
|
+
|
5
|
+
it 'should add test::test to allowed recipes' do
|
6
|
+
expect(instance.allowed_recipes).to contain_exactly('test::test')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should have an available allow_recipe method over API' do
|
10
|
+
allow_recipe('my_custom::recipe')
|
11
|
+
expect(instance.allowed_recipes).to contain_exactly('test::test', 'my_custom::recipe')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allow recipe should allow multiple arguments as recipe names' do
|
15
|
+
allow_recipe('my_custom::recipe', 'recipe::another')
|
16
|
+
expect(instance.allowed_recipes).to contain_exactly('test::test', 'my_custom::recipe', 'recipe::another')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'allow recipe should allow multiple arguments as recipe names' do
|
20
|
+
allow_recipe(%w(my_custom::recipe recipe::another), 'recipe::third')
|
21
|
+
expect(instance.allowed_recipes).to contain_exactly('test::test', 'my_custom::recipe', 'recipe::another', 'recipe::third')
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when defined in hook it' do
|
25
|
+
before (:each) { allow_recipe('before::recipe') }
|
26
|
+
|
27
|
+
it 'calls allow_recipe as well' do
|
28
|
+
expect(instance.allowed_recipes).to contain_exactly('test::test', 'before::recipe')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EcomDev::ChefSpec::Stub::IncludeRecipe do
|
4
|
+
describe '#allow_recipe' do
|
5
|
+
it 'should add recipe to the list of allowed' do
|
6
|
+
described_class.allow_recipe('test_my::test')
|
7
|
+
described_class.allow_recipe('test_two::test')
|
8
|
+
expect(described_class.instance.allowed_recipes).to contain_exactly('test_my::test', 'test_two::test')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#each_exameple' do
|
13
|
+
context 'when there is no described recipe it' do
|
14
|
+
it 'does not stub any include of recipe' do
|
15
|
+
expect { Chef::Cookbook::Metadata.new.depends }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when there is a described recipe', :allow_recipe => true do
|
20
|
+
let (:runner) { ChefSpec::Runner.new }
|
21
|
+
let (:described_recipe) { 'test::test' }
|
22
|
+
|
23
|
+
it 'loaded recipes should be empty in the beginning' do
|
24
|
+
expect(described_class.instance.loaded_recipes).to be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should call original load method on allowed recipes' do
|
28
|
+
described_class.allow_recipe('test2::test')
|
29
|
+
expect_any_instance_of(Chef::RunContext).to receive(:load_recipe).with('test::test').exactly(1).times
|
30
|
+
expect_any_instance_of(Chef::RunContext).to receive(:load_recipe).with('test2::test').exactly(1).times
|
31
|
+
expect_any_instance_of(Chef::Client).to receive(:assert_cookbook_path_not_empty)
|
32
|
+
|
33
|
+
runner.converge
|
34
|
+
runner.run_context.include_recipe('test::test')
|
35
|
+
runner.run_context.include_recipe('test2::test')
|
36
|
+
|
37
|
+
expect(runner.run_context.loaded_recipe?('test::test')).to eq(true)
|
38
|
+
expect(runner.run_context.loaded_recipe?('test2::test')).to eq(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should mark as included recipes that are not allowed, but do not load them' do
|
42
|
+
allow_any_instance_of(Chef::RunContext).to receive(:load_recipe).and_call_original
|
43
|
+
expect_any_instance_of(Chef::RunContext).not_to receive(:load_recipe).with('dummy::test')
|
44
|
+
expect_any_instance_of(Chef::Client).to receive(:assert_cookbook_path_not_empty)
|
45
|
+
|
46
|
+
runner.converge
|
47
|
+
runner.run_context.include_recipe('dummy::test')
|
48
|
+
|
49
|
+
expect(runner.run_context.loaded_recipes).to contain_exactly('dummy::test')
|
50
|
+
expect(runner.run_context.loaded_recipe?('dummy::test')).to eq(true)
|
51
|
+
expect(runner.run_context.loaded_recipe?('test::test')).to eq(false)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ecomdev-chefspec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ivan Chepurnyi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chefspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A collection of helpers for chef spec, to make easier writing recipe
|
56
|
+
specs
|
57
|
+
email:
|
58
|
+
- ivan.chepurnyi@ecomdev.org
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- ecomdev-chefspec.gemspec
|
70
|
+
- lib/ecomdev-chefspec.rb
|
71
|
+
- lib/ecomdev/chefspec.rb
|
72
|
+
- lib/ecomdev/chefspec/api.rb
|
73
|
+
- lib/ecomdev/chefspec/api/include_recipe.rb
|
74
|
+
- lib/ecomdev/chefspec/configuration.rb
|
75
|
+
- lib/ecomdev/chefspec/resource/matcher.rb
|
76
|
+
- lib/ecomdev/chefspec/resource/matcher/dsl.rb
|
77
|
+
- lib/ecomdev/chefspec/resource/matcher/helper.rb
|
78
|
+
- lib/ecomdev/chefspec/stub/include_recipe.rb
|
79
|
+
- lib/ecomdev/chefspec/version.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/unit/configuration_spec.rb
|
82
|
+
- spec/unit/matcher/dsl_spec.rb
|
83
|
+
- spec/unit/matcher/helper_spec.rb
|
84
|
+
- spec/unit/matcher_spec.rb
|
85
|
+
- spec/unit/stub/include_recipe/test_spec.rb
|
86
|
+
- spec/unit/stub/include_recipe_spec.rb
|
87
|
+
homepage: https://github.com/IvanChepurnyi/ecomdev-chefspec
|
88
|
+
licenses:
|
89
|
+
- GPLv3
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.4.0
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A collection of helpers for chef spec, to make easier writing recipe specs
|
111
|
+
test_files:
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- spec/unit/configuration_spec.rb
|
114
|
+
- spec/unit/matcher/dsl_spec.rb
|
115
|
+
- spec/unit/matcher/helper_spec.rb
|
116
|
+
- spec/unit/matcher_spec.rb
|
117
|
+
- spec/unit/stub/include_recipe/test_spec.rb
|
118
|
+
- spec/unit/stub/include_recipe_spec.rb
|
119
|
+
has_rdoc:
|