gem_metadata 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.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'rspec/collection_matchers'
21
+ require 'temporary_directory'
22
+
23
+ World(GodObject::TemporaryDirectory::Helper.new(name_prefix: 'gem_metadata_cucumber'))
24
+
25
+ After do
26
+ ensure_absence_of_temporary_directory
27
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GemDependencies
21
+ def gem_dependencies
22
+ @gem_dependencies ||= []
23
+ end
24
+
25
+ def create_gem_dependency(name:, gemspec_content: gemspec_for(gem_name: name))
26
+ gem_directory = temporary_directory / name
27
+ gem_directory.mkdir
28
+
29
+ gemspec_file = gem_directory / "#{name}.gemspec"
30
+ gemspec_file.write(gemspec_content)
31
+
32
+ gem_dependencies << name
33
+
34
+ gem_directory
35
+ end
36
+
37
+ def gemspec_for(gem_name:, additional_content: nil)
38
+ <<-GEMSPEC
39
+ Gem::Specification.new do |gem|
40
+ gem.name = '#{gem_name}'
41
+ gem.version = '1.0.0'
42
+
43
+ gem.summary = 'This serves as an example for a gem.'
44
+ gem.description = 'This serves as an example for a gem.'
45
+
46
+ gem.authors = %w{somebody}
47
+ gem.email = %w{somebody@example.org}
48
+ gem.homepage = 'http://example.org'
49
+
50
+ #{additional_content}
51
+ end
52
+ GEMSPEC
53
+ end
54
+ end
55
+
56
+ World(GemDependencies)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module Project
21
+ def project_root_directory
22
+ @project_root_directory ||= Pathname.new(__dir__) / '..' / '..'
23
+ end
24
+ end
25
+
26
+ World(Project)
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module SeparateEnvironmentEvaluation
21
+ class ExecutionResult
22
+ attr_reader :return_value, :console_output
23
+
24
+ def initialize(process_status: $CHILD_STATUS, console_output:)
25
+ @process_status = process_status
26
+ @console_output = console_output
27
+ end
28
+
29
+ def success?
30
+ @process_status.success?
31
+ end
32
+ end
33
+
34
+ class ObjectExecutionResult < ExecutionResult
35
+ def object_output
36
+ fail "Execution failed" unless success?
37
+
38
+ Marshal.load(@console_output)
39
+ end
40
+ end
41
+
42
+ def evaluation_result
43
+ @evaluation_result ||= @execution_result.object_output
44
+ end
45
+
46
+ def write_code_as_function_into_file(code)
47
+ code_file = temporary_directory / 'code.rb'
48
+ code_file.write(<<~CODE)
49
+ def code_to_execute
50
+ #{code}
51
+ end
52
+ CODE
53
+
54
+ code_file
55
+ end
56
+
57
+ def evaluate_in_separate_environment(command)
58
+ output = execute_in_separate_environment(command)
59
+
60
+ @execution_result = ObjectExecutionResult.new(console_output: output)
61
+ end
62
+ end
63
+
64
+ World(SeparateEnvironmentEvaluation)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'English'
21
+
22
+ module SeparateEnvironmentExecution
23
+ def execute_in_separate_environment(command)
24
+ Bundler.with_clean_env do
25
+ Dir.chdir(temporary_directory) do
26
+ @output = `#{command}`
27
+ end
28
+ end
29
+ end
30
+
31
+ def create_gemfile(include_gems: [])
32
+ gemfile = temporary_directory / 'Gemfile'
33
+
34
+ gemfile.open('w') do |io|
35
+ io.puts(%(gem 'gem_metadata', path: '#{project_root_directory}'))
36
+
37
+ include_gems.each do |gem_name|
38
+ io.puts(%(gem '#{gem_name}', path: '#{gem_name}'))
39
+ end
40
+ end
41
+
42
+ gemfile
43
+ end
44
+ end
45
+
46
+ World(SeparateEnvironmentExecution)
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'English'
21
+ require_relative 'lib/god_object/gem_metadata/version'
22
+
23
+ Gem::Specification.new do |gem|
24
+ gem.name = 'gem_metadata'
25
+ gem.version = GodObject::GemMetadata::VERSION.dup
26
+ gem.authors = ['Alexander E. Fischer']
27
+ gem.email = ['aef@godobject.net']
28
+ gem.description = <<-DESCRIPTION
29
+ GemMetadata is a Ruby library that allows to filter and access gems by custom
30
+ metadata keys that their specifications contain.
31
+ DESCRIPTION
32
+ gem.summary = 'Filter and access gems depending on metadata they contain'
33
+ gem.homepage = 'https://www.godobject.net/'
34
+ gem.license = 'ISC'
35
+ gem.has_rdoc = 'yard'
36
+ gem.extra_rdoc_files = %w(HISTORY.md LICENSE.md)
37
+ gem.rubyforge_project = nil
38
+
39
+ `git ls-files 2> /dev/null`
40
+
41
+ if $CHILD_STATUS.success?
42
+ gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
43
+ else
44
+ gem.files = `ls -1`.split($OUTPUT_RECORD_SEPARATOR)
45
+ end
46
+
47
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
48
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
49
+ gem.require_paths = %w(lib)
50
+
51
+ gem.required_ruby_version = '>= 2.3.0'
52
+
53
+ gem.add_development_dependency('rake')
54
+ gem.add_development_dependency('bundler')
55
+ gem.add_development_dependency('rspec', '~> 3.5')
56
+ gem.add_development_dependency('rspec-collection_matchers', '~> 1.1')
57
+ gem.add_development_dependency('cucumber', '~> 2.4')
58
+ gem.add_development_dependency('temporary_directory', '= 0.1.0')
59
+ gem.add_development_dependency('simplecov')
60
+ gem.add_development_dependency('pry')
61
+ gem.add_development_dependency('yard')
62
+ gem.add_development_dependency('kramdown')
63
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require_relative 'god_object/gem_metadata'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject
21
+ module GemMetadata
22
+ end
23
+ end
24
+
25
+ require_relative 'gem_metadata/version'
26
+ require_relative 'gem_metadata/service'
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject::GemMetadata
21
+ class Service
22
+ def initialize(gems: ::Gem.loaded_specs.values)
23
+ @gems = gems
24
+ end
25
+
26
+ def find_gems_providing(metadata_key)
27
+ @gems.select { |gem| gem.metadata.key?(metadata_key) }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject
21
+ module GemMetadata
22
+
23
+ # The currently loaded version.
24
+ #
25
+ # Using Semantic Versioning (2.0.0) rules
26
+ # @see http://semver.org/spec/v2.0.0.html
27
+ VERSION = '0.1.0'
28
+
29
+ end
30
+ end
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@godobject.net>, 2016
4
+
5
+ This file is part of GemMetadata.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject::GemMetadata
21
+
22
+ describe Service do
23
+ shared_context 'only one gem was provided at construction' do
24
+ let(:constructor_arguments) { [gems: gems] }
25
+ let(:gems) { [gem_specification] }
26
+ let(:gem_specification) { instance_spy(::Gem::Specification, :specification, name: gem_name).as_null_object }
27
+ let(:gem_name) { 'some_gem' }
28
+ end
29
+
30
+ shared_context 'two gems were provided at construction' do
31
+ let(:constructor_arguments) { [gems: gems] }
32
+ let(:gems) { [first_gem_specification, second_gem_specification] }
33
+ let(:first_gem_specification) { instance_spy(::Gem::Specification, :first_specification, name: first_gem_name).as_null_object }
34
+ let(:first_gem_name) { 'some_gem' }
35
+
36
+ let(:second_gem_specification) { instance_spy(::Gem::Specification, :second_specification, name: second_gem_name).as_null_object }
37
+ let(:second_gem_name) { 'other_gem' }
38
+ end
39
+
40
+ let(:service) { described_class.new(*constructor_arguments) }
41
+
42
+ describe '.new' do
43
+ subject(:method_call) { described_class.new(*arguments) }
44
+
45
+ context 'when called without any arguments' do
46
+ let(:arguments) { [] }
47
+
48
+ before(:example) { allow(::Gem).to receive(:loaded_specs).and_return({}) }
49
+
50
+ it 'acquires the currently loaded gems from Rubygems' do
51
+ expect(::Gem).to receive(:loaded_specs)
52
+
53
+ method_call
54
+ end
55
+
56
+ it { is_expected.to be_an described_class }
57
+ end
58
+
59
+ context 'when called with gems' do
60
+ include_context 'two gems were provided at construction'
61
+
62
+ let(:arguments) { [gems: gems] }
63
+
64
+ it { is_expected.to be_an described_class }
65
+ end
66
+ end
67
+
68
+ describe '#find_gems_providing' do
69
+ subject(:method_call) { service.find_gems_providing(*arguments) }
70
+
71
+ context 'when called without any arguments' do
72
+ include_context 'only one gem was provided at construction'
73
+
74
+ let(:arguments) { [] }
75
+
76
+ specify { expect { method_call }.to raise_error ArgumentError, /wrong number of arguments/ }
77
+ end
78
+
79
+ context 'when called with a metadata key' do
80
+ let(:arguments) { [metadata_key] }
81
+ let(:metadata_key) { 'some key' }
82
+
83
+ context 'in case only one gem that does not contain metadata was provided at construction' do
84
+ include_context 'only one gem was provided at construction'
85
+
86
+ let(:metadata) { {} }
87
+
88
+ before(:example) do
89
+ allow(gem_specification).to receive(:metadata).and_return(metadata)
90
+ end
91
+
92
+ it 'requests the metadata from the gem specification' do
93
+ method_call
94
+
95
+ expect(gem_specification).to have_received(:metadata).with(no_args)
96
+ end
97
+
98
+ it { is_expected.to eq [] }
99
+ end
100
+
101
+ context 'in case only one gem that does contain non-matching metadata was provided at construction' do
102
+ include_context 'only one gem was provided at construction'
103
+
104
+ let(:metadata) do
105
+ { 'other key' => '' }
106
+ end
107
+
108
+ before(:example) do
109
+ allow(gem_specification).to receive(:metadata).and_return(metadata)
110
+ end
111
+
112
+ it 'requests the metadata from the gem specification' do
113
+ method_call
114
+
115
+ expect(gem_specification).to have_received(:metadata).with(no_args)
116
+ end
117
+
118
+ it { is_expected.to eq [] }
119
+ end
120
+
121
+ context 'in case only one gem that does contain matching metadata was provided at construction' do
122
+ include_context 'only one gem was provided at construction'
123
+
124
+ let(:metadata) do
125
+ { metadata_key => '' }
126
+ end
127
+
128
+ before(:example) do
129
+ allow(gem_specification).to receive(:metadata).and_return(metadata)
130
+ end
131
+
132
+ it 'requests the metadata from the gem specification' do
133
+ method_call
134
+
135
+ expect(gem_specification).to have_received(:metadata).with(no_args)
136
+ end
137
+
138
+ it { is_expected.to be_an Array }
139
+ it { is_expected.to have(1).item }
140
+
141
+ describe 'first item' do
142
+ subject(:item) { method_call[0] }
143
+
144
+ it 'is the gem specification' do
145
+ expect(item).to be gem_specification
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'in case one gem containg metadata and one without were provided at construction' do
151
+ include_context 'two gems were provided at construction'
152
+
153
+ let(:first_metadata) { {} }
154
+ let(:second_metadata) do
155
+ { metadata_key => '' }
156
+ end
157
+
158
+ before(:example) do
159
+ allow(first_gem_specification).to receive(:metadata).and_return(first_metadata)
160
+ allow(second_gem_specification).to receive(:metadata).and_return(second_metadata)
161
+ end
162
+
163
+ it 'requests the metadata from the first gem specification' do
164
+ method_call
165
+
166
+ expect(first_gem_specification).to have_received(:metadata).with(no_args)
167
+ end
168
+
169
+ it 'requests the metadata from the second gem specification' do
170
+ method_call
171
+
172
+ expect(second_gem_specification).to have_received(:metadata).with(no_args)
173
+ end
174
+
175
+ it { is_expected.to be_an Array }
176
+ it { is_expected.to have(1).item }
177
+
178
+ describe 'first item' do
179
+ subject(:item) { method_call[0] }
180
+
181
+ it 'is the second gem specification' do
182
+ expect(item).to be second_gem_specification
183
+ end
184
+ end
185
+ end
186
+
187
+ context 'in case two gems containg matching metadata were provided at construction' do
188
+ include_context 'two gems were provided at construction'
189
+
190
+ let(:first_metadata) do
191
+ { metadata_key => '' }
192
+ end
193
+
194
+ let(:second_metadata) do
195
+ { metadata_key => '' }
196
+ end
197
+
198
+ before(:example) do
199
+ allow(first_gem_specification).to receive(:metadata).and_return(first_metadata)
200
+ allow(second_gem_specification).to receive(:metadata).and_return(second_metadata)
201
+ end
202
+
203
+ it 'requests the metadata from the first gem specification' do
204
+ method_call
205
+
206
+ expect(first_gem_specification).to have_received(:metadata).with(no_args)
207
+ end
208
+
209
+ it 'requests the metadata from the second gem specification' do
210
+ method_call
211
+
212
+ expect(second_gem_specification).to have_received(:metadata).with(no_args)
213
+ end
214
+
215
+ it { is_expected.to be_an Array }
216
+ it { is_expected.to have(2).item }
217
+
218
+ describe 'first item' do
219
+ subject(:item) { method_call[0] }
220
+
221
+ it 'is the first gem specification' do
222
+ expect(item).to be first_gem_specification
223
+ end
224
+ end
225
+
226
+ describe 'second item' do
227
+ subject(:item) { method_call[1] }
228
+
229
+ it 'is the second gem specification' do
230
+ expect(item).to be second_gem_specification
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ end