berkshelf 3.1.5 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/berkshelf.gemspec +6 -5
  4. data/features/commands/search.feature +2 -2
  5. data/features/commands/vendor.feature +6 -2
  6. data/features/commands/verify.feature +29 -0
  7. data/features/config.feature +13 -48
  8. data/features/step_definitions/filesystem_steps.rb +2 -2
  9. data/features/step_definitions/gem_steps.rb +3 -1
  10. data/features/step_definitions/utility_steps.rb +2 -2
  11. data/generator_files/Vagrantfile.erb +30 -30
  12. data/generator_files/metadata.rb.erb +0 -1
  13. data/lib/berkshelf.rb +5 -2
  14. data/lib/berkshelf/berksfile.rb +41 -41
  15. data/lib/berkshelf/cli.rb +11 -1
  16. data/lib/berkshelf/community_rest.rb +1 -0
  17. data/lib/berkshelf/config.rb +18 -4
  18. data/lib/berkshelf/cookbook_store.rb +1 -1
  19. data/lib/berkshelf/downloader.rb +4 -0
  20. data/lib/berkshelf/errors.rb +0 -1
  21. data/lib/berkshelf/file_syncer.rb +134 -0
  22. data/lib/berkshelf/locations/base.rb +6 -1
  23. data/lib/berkshelf/locations/git.rb +2 -2
  24. data/lib/berkshelf/lockfile.rb +14 -2
  25. data/lib/berkshelf/uploader.rb +10 -17
  26. data/lib/berkshelf/validator.rb +37 -0
  27. data/lib/berkshelf/version.rb +1 -1
  28. data/lib/berkshelf/visualizer.rb +13 -6
  29. data/spec/spec_helper.rb +1 -1
  30. data/spec/support/kitchen.rb +3 -1
  31. data/spec/support/matchers/file_system_matchers.rb +1 -1
  32. data/spec/support/matchers/filepath_matchers.rb +38 -2
  33. data/spec/support/shared_examples/formatter.rb +7 -7
  34. data/spec/unit/berkshelf/berksfile_spec.rb +51 -21
  35. data/spec/unit/berkshelf/cached_cookbook_spec.rb +5 -5
  36. data/spec/unit/berkshelf/cli_spec.rb +1 -1
  37. data/spec/unit/berkshelf/community_rest_spec.rb +12 -12
  38. data/spec/unit/berkshelf/config_spec.rb +4 -4
  39. data/spec/unit/berkshelf/cookbook_generator_spec.rb +2 -2
  40. data/spec/unit/berkshelf/cookbook_store_spec.rb +6 -6
  41. data/spec/unit/berkshelf/core_ext/file_utils_spec.rb +3 -3
  42. data/spec/unit/berkshelf/core_ext/pathname_spec.rb +23 -6
  43. data/spec/unit/berkshelf/dependency_spec.rb +4 -4
  44. data/spec/unit/berkshelf/downloader_spec.rb +5 -1
  45. data/spec/unit/berkshelf/errors_spec.rb +1 -1
  46. data/spec/unit/berkshelf/file_syncer_spec.rb +206 -0
  47. data/spec/unit/berkshelf/init_generator_spec.rb +19 -22
  48. data/spec/unit/berkshelf/installer_spec.rb +6 -6
  49. data/spec/unit/berkshelf/locations/base_spec.rb +17 -8
  50. data/spec/unit/berkshelf/locations/git_spec.rb +34 -34
  51. data/spec/unit/berkshelf/locations/path_spec.rb +3 -3
  52. data/spec/unit/berkshelf/lockfile_parser_spec.rb +1 -1
  53. data/spec/unit/berkshelf/lockfile_spec.rb +50 -36
  54. data/spec/unit/berkshelf/packager_spec.rb +6 -4
  55. data/spec/unit/berkshelf/resolver/graph_spec.rb +3 -3
  56. data/spec/unit/berkshelf/resolver_spec.rb +3 -3
  57. data/spec/unit/berkshelf/shell_spec.rb +30 -24
  58. data/spec/unit/berkshelf/uploader_spec.rb +10 -36
  59. data/spec/unit/berkshelf/validator_spec.rb +30 -0
  60. data/spec/unit/berkshelf/visualizer_spec.rb +17 -2
  61. metadata +34 -15
  62. data/lib/berkshelf/mixin/dsl_eval.rb +0 -58
  63. data/spec/unit/berkshelf/mixin/dsl_eval_spec.rb +0 -55
@@ -7,9 +7,9 @@ describe FileUtils do
7
7
  let(:options) { double('options') }
8
8
 
9
9
  it 'replaces mv with cp_r and rm_rf' do
10
- subject.stub(:windows?) { true }
11
- FileUtils.should_receive(:cp_r).with(src, dest, options)
12
- FileUtils.should_receive(:rm_rf).with(src)
10
+ allow(subject).to receive(:windows?) { true }
11
+ expect(FileUtils).to receive(:cp_r).with(src, dest, options)
12
+ expect(FileUtils).to receive(:rm_rf).with(src)
13
13
 
14
14
  FileUtils.mv(src, dest, options)
15
15
  end
@@ -10,17 +10,26 @@ describe Pathname do
10
10
 
11
11
  context "when the path contains a metadata.json file" do
12
12
  before { FileUtils.touch(metadata_json) }
13
- its(:cookbook?) { should be_true }
13
+
14
+ it "is a cookbook" do
15
+ expect(subject.cookbook?).to be(true)
16
+ end
14
17
  end
15
18
 
16
19
  context "when the path contains a metadata.rb file" do
17
20
  before { FileUtils.touch(metadata_rb) }
18
- its(:cookbook?) { should be_true }
21
+
22
+ it "is a cookbook" do
23
+ expect(subject.cookbook?).to be(true)
24
+ end
19
25
  end
20
26
 
21
27
  context "when the path does not contain a metadata.json or metadata.rb file" do
22
28
  before { FileUtils.rm_f(metadata_rb) && FileUtils.rm_f(metadata_json) }
23
- its(:cookbook?) { should be_false }
29
+
30
+ it "is not a cookbook" do
31
+ expect(subject.cookbook?).to be(false)
32
+ end
24
33
  end
25
34
  end
26
35
 
@@ -30,17 +39,25 @@ describe Pathname do
30
39
  subject { Pathname.new(cookbook_path) }
31
40
 
32
41
  context "when in the root of a cookbook" do
33
- its(:cookbook_root) { should eql(root_path) }
42
+ it "has the correct root" do
43
+ expect(subject.cookbook_root).to eq(root_path)
44
+ end
34
45
  end
35
46
 
36
47
  context "when in the structure of a cookbook" do
37
48
  let(:cookbook_path) { root_path.join("recipes") }
38
- its(:cookbook_root) { should eql(root_path) }
49
+
50
+ it "has the correct root" do
51
+ expect(subject.cookbook_root).to eq(root_path)
52
+ end
39
53
  end
40
54
 
41
55
  context "when not within the structure of a cookbook" do
42
56
  let(:cookbook_path) { "/" }
43
- its(:cookbook_root) { should be_nil }
57
+
58
+ it "has the correct root" do
59
+ expect(subject.cookbook_root).to be(nil)
60
+ end
44
61
  end
45
62
  end
46
63
  end
@@ -121,13 +121,13 @@ describe Berkshelf::Dependency do
121
121
 
122
122
  describe '#installed?' do
123
123
  it 'returns true if self.cached_cookbook is not nil' do
124
- subject.stub(:cached_cookbook) { double('cb') }
125
- expect(subject.installed?).to be_true
124
+ allow(subject).to receive(:cached_cookbook) { double('cb') }
125
+ expect(subject.installed?).to be(true)
126
126
  end
127
127
 
128
128
  it 'returns false if self.cached_cookbook is nil' do
129
- subject.stub(:cached_cookbook) { nil }
130
- expect(subject.installed?).to be_false
129
+ allow(subject).to receive(:cached_cookbook) { nil }
130
+ expect(subject.installed?).to be(false)
131
131
  end
132
132
  end
133
133
  end
@@ -5,7 +5,7 @@ describe Berkshelf::Downloader do
5
5
  subject { described_class.new(berksfile) }
6
6
 
7
7
  describe "#download" do
8
- pending
8
+ skip
9
9
  end
10
10
 
11
11
  describe "#try_download" do
@@ -35,5 +35,9 @@ describe Berkshelf::Downloader do
35
35
  expect(rest).to receive(:download).with(name, version)
36
36
  subject.try_download(source, name, version)
37
37
  end
38
+
39
+ it "supports the 'file_store' location type" do
40
+ skip
41
+ end
38
42
  end
39
43
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::BerkshelfError do
4
- pending
4
+ skip
5
5
  end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ module Berkshelf
4
+ describe FileSyncer do
5
+ describe '#glob' do
6
+ before do
7
+ FileUtils.mkdir_p(File.join(tmp_path, 'folder'))
8
+ FileUtils.mkdir_p(File.join(tmp_path, '.hidden_folder'))
9
+
10
+ FileUtils.touch(File.join(tmp_path, 'folder', 'file'))
11
+ FileUtils.touch(File.join(tmp_path, '.hidden_file'))
12
+ end
13
+
14
+ let(:list) do
15
+ described_class
16
+ .glob("#{tmp_path}/**/*")
17
+ .map { |item| item.sub("#{tmp_path}/", '') }
18
+ end
19
+
20
+ it 'includes regular files' do
21
+ expect(list).to include('folder')
22
+ expect(list).to include('folder/file')
23
+ end
24
+
25
+ it 'ignores .' do
26
+ expect(list).to_not include('.')
27
+ end
28
+
29
+ it 'ignores ..' do
30
+ expect(list).to_not include('..')
31
+ end
32
+
33
+ it 'includes hidden files' do
34
+ expect(list).to include('.hidden_file')
35
+ end
36
+
37
+ it 'includes hidden folders' do
38
+ expect(list).to include('.hidden_folder')
39
+ end
40
+ end
41
+
42
+ describe '#sync' do
43
+ let(:source) do
44
+ source = File.join(tmp_path, 'source')
45
+ FileUtils.mkdir_p(source)
46
+
47
+ FileUtils.touch(File.join(source, 'file_a'))
48
+ FileUtils.touch(File.join(source, 'file_b'))
49
+ FileUtils.touch(File.join(source, 'file_c'))
50
+
51
+ FileUtils.mkdir_p(File.join(source, 'folder'))
52
+ FileUtils.touch(File.join(source, 'folder', 'file_d'))
53
+ FileUtils.touch(File.join(source, 'folder', 'file_e'))
54
+
55
+ FileUtils.mkdir_p(File.join(source, '.dot_folder'))
56
+ FileUtils.touch(File.join(source, '.dot_folder', 'file_f'))
57
+
58
+ FileUtils.touch(File.join(source, '.file_g'))
59
+ source
60
+ end
61
+
62
+ let(:destination) { File.join(tmp_path, 'destination') }
63
+
64
+ context 'when the destination is empty' do
65
+ it 'syncs the directories' do
66
+ described_class.sync(source, destination)
67
+
68
+ expect("#{destination}/file_a").to be_a_file
69
+ expect("#{destination}/file_b").to be_a_file
70
+ expect("#{destination}/file_c").to be_a_file
71
+ expect("#{destination}/folder/file_d").to be_a_file
72
+ expect("#{destination}/folder/file_e").to be_a_file
73
+ expect("#{destination}/.dot_folder/file_f").to be_a_file
74
+ expect("#{destination}/.file_g").to be_a_file
75
+ end
76
+ end
77
+
78
+ context 'when the directory exists' do
79
+ before { FileUtils.mkdir_p(destination) }
80
+
81
+ it 'deletes existing files and folders' do
82
+ FileUtils.mkdir_p("#{destination}/existing_folder")
83
+ FileUtils.mkdir_p("#{destination}/.existing_folder")
84
+ FileUtils.touch("#{destination}/existing_file")
85
+ FileUtils.touch("#{destination}/.existing_file")
86
+
87
+ described_class.sync(source, destination)
88
+
89
+ expect("#{destination}/file_a").to be_a_file
90
+ expect("#{destination}/file_b").to be_a_file
91
+ expect("#{destination}/file_c").to be_a_file
92
+ expect("#{destination}/folder/file_d").to be_a_file
93
+ expect("#{destination}/folder/file_e").to be_a_file
94
+ expect("#{destination}/.dot_folder/file_f").to be_a_file
95
+ expect("#{destination}/.file_g").to be_a_file
96
+
97
+ expect("#{destination}/existing_folder").to_not be_a_directory
98
+ expect("#{destination}/.existing_folder").to_not be_a_directory
99
+ expect("#{destination}/existing_file").to_not be_a_file
100
+ expect("#{destination}/.existing_file").to_not be_a_file
101
+ end
102
+ end
103
+
104
+ context 'with deeply nested paths and symlinks' do
105
+ let(:source) do
106
+ source = File.join(tmp_path, 'source')
107
+ FileUtils.mkdir_p(source)
108
+
109
+ FileUtils.mkdir_p(File.join(source, 'bin'))
110
+ FileUtils.touch(File.join(source, 'bin', 'apt'))
111
+ FileUtils.touch(File.join(source, 'bin', 'yum'))
112
+
113
+ FileUtils.touch(File.join(source, 'LICENSE'))
114
+
115
+ FileUtils.mkdir_p(File.join(source, 'include'))
116
+ FileUtils.mkdir_p(File.join(source, 'include', 'linux'))
117
+ FileUtils.touch(File.join(source, 'include', 'linux', 'init.ini'))
118
+
119
+ FileUtils.mkdir_p(File.join(source, 'source'))
120
+ FileUtils.mkdir_p(File.join(source, 'source', 'bin'))
121
+ FileUtils.touch(File.join(source, 'source', 'bin', 'apt'))
122
+ FileUtils.touch(File.join(source, 'source', 'bin', 'yum'))
123
+ FileUtils.touch(File.join(source, 'source', 'LICENSE'))
124
+
125
+ FileUtils.mkdir_p(File.join(source, 'empty_directory'))
126
+
127
+ FileUtils.mkdir_p(File.join(source, 'links'))
128
+ FileUtils.touch(File.join(source, 'links', 'home.html'))
129
+ FileUtils.ln_s("./home.html", "#{source}/links/index.html")
130
+ FileUtils.ln_s("./home.html", "#{source}/links/default.html")
131
+ FileUtils.ln_s("../source/bin/apt", "#{source}/links/apt")
132
+
133
+ FileUtils.ln_s('/foo/bar', "#{source}/root")
134
+
135
+ source
136
+ end
137
+
138
+ it 'copies relative and absolute symlinks' do
139
+ described_class.sync(source, destination)
140
+
141
+ expect("#{destination}/bin").to be_a_directory
142
+ expect("#{destination}/bin/apt").to be_a_file
143
+ expect("#{destination}/bin/yum").to be_a_file
144
+
145
+ expect("#{destination}/LICENSE").to be_a_file
146
+
147
+ expect("#{destination}/include").to be_a_directory
148
+ expect("#{destination}/include/linux").to be_a_directory
149
+ expect("#{destination}/include/linux/init.ini").to be_a_file
150
+
151
+ expect("#{destination}/source").to be_a_directory
152
+ expect("#{destination}/source/bin").to be_a_directory
153
+ expect("#{destination}/source/bin/apt").to be_a_file
154
+ expect("#{destination}/source/bin/yum").to be_a_file
155
+ expect("#{destination}/source/LICENSE").to be_a_file
156
+
157
+ expect("#{destination}/empty_directory").to be_a_directory
158
+
159
+ expect("#{destination}/links").to be_a_directory
160
+ expect("#{destination}/links/home.html").to be_a_file
161
+ expect("#{destination}/links/index.html").to be_a_symlink_to("./home.html")
162
+ expect("#{destination}/links/default.html").to be_a_symlink_to("./home.html")
163
+ expect("#{destination}/links/apt").to be_a_symlink_to("../source/bin/apt")
164
+
165
+ expect("#{destination}/root").to be_a_symlink_to('/foo/bar')
166
+ end
167
+ end
168
+
169
+ context 'when :exclude is given' do
170
+ it 'does not copy files and folders that match the pattern' do
171
+ described_class.sync(source, destination, exclude: '.dot_folder')
172
+
173
+ expect("#{destination}/file_a").to be_a_file
174
+ expect("#{destination}/file_b").to be_a_file
175
+ expect("#{destination}/file_c").to be_a_file
176
+ expect("#{destination}/folder/file_d").to be_a_file
177
+ expect("#{destination}/folder/file_e").to be_a_file
178
+ expect("#{destination}/.dot_folder").to_not be_a_directory
179
+ expect("#{destination}/.dot_folder/file_f").to_not be_a_file
180
+ expect("#{destination}/.file_g").to be_a_file
181
+ end
182
+
183
+ it 'removes existing files and folders in destination' do
184
+ FileUtils.mkdir_p("#{destination}/existing_folder")
185
+ FileUtils.touch("#{destination}/existing_file")
186
+ FileUtils.mkdir_p("#{destination}/.dot_folder")
187
+ FileUtils.touch("#{destination}/.dot_folder/file_f")
188
+
189
+ described_class.sync(source, destination, exclude: '.dot_folder')
190
+
191
+ expect("#{destination}/file_a").to be_a_file
192
+ expect("#{destination}/file_b").to be_a_file
193
+ expect("#{destination}/file_c").to be_a_file
194
+ expect("#{destination}/folder/file_d").to be_a_file
195
+ expect("#{destination}/folder/file_e").to be_a_file
196
+ expect("#{destination}/.dot_folder").to_not be_a_directory
197
+ expect("#{destination}/.dot_folder/file_f").to_not be_a_file
198
+ expect("#{destination}/.file_g").to be_a_file
199
+
200
+ expect("#{destination}/existing_folder").to_not be_a_directory
201
+ expect("#{destination}/existing_file").to_not be_a_file
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -6,7 +6,7 @@ describe Berkshelf::InitGenerator do
6
6
  let(:kitchen_generator) { double('kitchen-generator', invoke_all: nil) }
7
7
 
8
8
  before do
9
- Kitchen::Generator::Init.stub(:new).with(any_args()).and_return(kitchen_generator)
9
+ allow(Kitchen::Generator::Init).to receive(:new).with(any_args()).and_return(kitchen_generator)
10
10
  FileUtils.mkdir_p(target)
11
11
  File.open(File.join(target, 'metadata.rb'), 'w') do |f|
12
12
  f.write("name 'some_cookbook'")
@@ -25,13 +25,12 @@ describe Berkshelf::InitGenerator do
25
25
  file '.gitignore'
26
26
  file 'Berksfile'
27
27
  file 'Gemfile' do
28
- contains "gem 'berkshelf'"
28
+ contains %(gem 'berkshelf')
29
29
  end
30
30
  file 'Vagrantfile' do
31
- contains 'recipe[some_cookbook::default]'
32
- contains ' config.omnibus.chef_version = :latest'
33
- contains 'config.vm.box = "chef/ubuntu-14.04"'
34
- contains 'config.vm.box_url = "https://vagrantcloud.com/chef/ubuntu-14.04/version/1/provider/virtualbox.box"'
31
+ contains %(recipe[some_cookbook::default])
32
+ contains %(config.omnibus.chef_version = 'latest')
33
+ contains %(config.vm.box = 'chef/ubuntu-14.04')
35
34
  end
36
35
  file 'chefignore'
37
36
  }
@@ -175,54 +174,52 @@ describe Berkshelf::InitGenerator do
175
174
  end
176
175
  end
177
176
 
178
- context "given the 'vagrant.omnibus.enabled' option set to false" do
177
+ context "given the 'vagrant.omnibus.version' option set" do
179
178
  before do
180
- Berkshelf::Config.instance.vagrant.omnibus.enabled = false
179
+ Berkshelf::Config.instance.vagrant.omnibus.version = "11.4.4"
181
180
  capture(:stdout) {
182
181
  Berkshelf::InitGenerator.new([target]).invoke_all
183
182
  }
184
183
  end
185
184
 
186
- it "generates a Vagrantfile without the 'config.omnibus.chef_version' value set" do
185
+ it "generates a Vagrantfile with the 'config.omnibus.chef_version' value set" do
187
186
  expect(target).to have_structure {
188
187
  file 'Vagrantfile' do
189
- contains "#config.omnibus.chef_version"
188
+ contains "config.omnibus.chef_version = '11.4.4'"
190
189
  end
191
190
  }
192
191
  end
193
192
  end
194
193
 
195
- context "given the 'vagrant.omnibus.version' option set" do
194
+ context "given the 'vagrant.omnibus.version' option set to 'latest'" do
196
195
  before do
197
- Berkshelf::Config.instance.vagrant.omnibus.enabled = true
198
- Berkshelf::Config.instance.vagrant.omnibus.version = "11.4.4"
196
+ Berkshelf::Config.instance.vagrant.omnibus.version = "latest"
199
197
  capture(:stdout) {
200
198
  Berkshelf::InitGenerator.new([target]).invoke_all
201
199
  }
202
200
  end
203
201
 
204
- it "generates a Vagrantfile with the 'config.omnibus.chef_version' value set" do
202
+ it "generates a Vagrantfile with the 'config.omnibus.chef_version' value set to :latest" do
205
203
  expect(target).to have_structure {
206
204
  file 'Vagrantfile' do
207
- contains " config.omnibus.chef_version = \"11.4.4\""
205
+ contains " config.omnibus.chef_version = 'latest'"
208
206
  end
209
207
  }
210
208
  end
211
209
  end
212
210
 
213
- context "given the 'vagrant.omnibus.version' option set to 'latest'" do
211
+ context "given the 'vagrant.vm.box_url' option set" do
214
212
  before do
215
- Berkshelf::Config.instance.vagrant.omnibus.enabled = true
216
- Berkshelf::Config.instance.vagrant.omnibus.version = "latest"
213
+ Berkshelf::Config.instance.vagrant.vm.box_url = "https://vagrantcloud.com/chef/ubuntu-14.04/version/1/provider/virtualbox.box"
217
214
  capture(:stdout) {
218
215
  Berkshelf::InitGenerator.new([target]).invoke_all
219
216
  }
220
217
  end
221
218
 
222
- it "generates a Vagrantfile with the 'config.omnibus.chef_version' value set to :latest" do
219
+ it "generates a Vagrantfile with the 'config.vm.box_url' value set" do
223
220
  expect(target).to have_structure {
224
221
  file 'Vagrantfile' do
225
- contains " config.omnibus.chef_version = :latest"
222
+ contains "config.vm.box_url = 'https://vagrantcloud.com/chef/ubuntu-14.04/version/1/provider/virtualbox.box'"
226
223
  end
227
224
  }
228
225
  end
@@ -230,8 +227,8 @@ describe Berkshelf::InitGenerator do
230
227
 
231
228
  context 'with the chef_minitest option true' do
232
229
  before(:each) do
233
- Berkshelf::Resolver.stub(:resolve) { resolver }
234
- pending 'Runs fine with no mock for the HTTP call on the first pass, subsequent passes throw errors'
230
+ allow(Berkshelf::Resolver).to receive(:resolve) { resolver }
231
+ skip 'Runs fine with no mock for the HTTP call on the first pass, subsequent passes throw errors'
235
232
  capture(:stdout) {
236
233
  Berkshelf::InitGenerator.new([target], chef_minitest: true).invoke_all
237
234
  }
@@ -10,11 +10,11 @@ describe Berkshelf::Installer do
10
10
  let(:source_two) { double('two', uri: 'https://api.chef.org') }
11
11
  let(:sources) { [ source_one, source_two ] }
12
12
 
13
- before { berksfile.stub(sources: sources) }
13
+ before { allow(berksfile).to receive_messages(sources: sources) }
14
14
 
15
15
  it "sends the message #universe on each source" do
16
- source_one.should_receive(:build_universe)
17
- source_two.should_receive(:build_universe)
16
+ expect(source_one).to receive(:build_universe)
17
+ expect(source_two).to receive(:build_universe)
18
18
 
19
19
  subject.build_universe
20
20
  end
@@ -22,15 +22,15 @@ describe Berkshelf::Installer do
22
22
 
23
23
  describe "#run" do
24
24
  context 'when a lockfile is not present' do
25
- pending
25
+ skip
26
26
  end
27
27
 
28
28
  context 'when a value for :except is given' do
29
- pending
29
+ skip
30
30
  end
31
31
 
32
32
  context 'when a value for :only is given' do
33
- pending
33
+ skip
34
34
  end
35
35
  end
36
36
  end