summaryrefslogtreecommitdiff
path: root/qa/spec/resource/base_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'qa/spec/resource/base_spec.rb')
-rw-r--r--qa/spec/resource/base_spec.rb246
1 files changed, 246 insertions, 0 deletions
diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb
new file mode 100644
index 00000000000..dc9e16792d3
--- /dev/null
+++ b/qa/spec/resource/base_spec.rb
@@ -0,0 +1,246 @@
+# frozen_string_literal: true
+
+describe QA::Resource::Base do
+ include Support::StubENV
+
+ let(:resource) { spy('resource') }
+ let(:location) { 'http://location' }
+
+ shared_context 'fabrication context' do
+ subject do
+ Class.new(described_class) do
+ def self.name
+ 'MyResource'
+ end
+ end
+ end
+
+ before do
+ allow(subject).to receive(:current_url).and_return(location)
+ allow(subject).to receive(:new).and_return(resource)
+ end
+ end
+
+ shared_examples 'fabrication method' do |fabrication_method_called, actual_fabrication_method = nil|
+ let(:fabrication_method_used) { actual_fabrication_method || fabrication_method_called }
+
+ it 'yields resource before calling resource method' do
+ expect(resource).to receive(:something!).ordered
+ expect(resource).to receive(fabrication_method_used).ordered.and_return(location)
+
+ subject.public_send(fabrication_method_called, resource: resource) do |resource|
+ resource.something!
+ end
+ end
+
+ it 'does not log the resource and build method when QA_DEBUG=false' do
+ stub_env('QA_DEBUG', 'false')
+ expect(resource).to receive(fabrication_method_used).and_return(location)
+
+ expect { subject.public_send(fabrication_method_called, 'something', resource: resource) }
+ .not_to output.to_stdout
+ end
+ end
+
+ describe '.fabricate!' do
+ context 'when resource does not support fabrication via the API' do
+ before do
+ expect(described_class).to receive(:fabricate_via_api!).and_raise(NotImplementedError)
+ end
+
+ it 'calls .fabricate_via_browser_ui!' do
+ expect(described_class).to receive(:fabricate_via_browser_ui!)
+
+ described_class.fabricate!
+ end
+ end
+
+ context 'when resource supports fabrication via the API' do
+ it 'calls .fabricate_via_browser_ui!' do
+ expect(described_class).to receive(:fabricate_via_api!)
+
+ described_class.fabricate!
+ end
+ end
+ end
+
+ describe '.fabricate_via_api!' do
+ include_context 'fabrication context'
+
+ it_behaves_like 'fabrication method', :fabricate_via_api!
+
+ it 'instantiates the resource, calls resource method returns the resource' do
+ expect(resource).to receive(:fabricate_via_api!).and_return(location)
+
+ result = subject.fabricate_via_api!(resource: resource, parents: [])
+
+ expect(result).to eq(resource)
+ end
+
+ it 'logs the resource and build method when QA_DEBUG=true' do
+ stub_env('QA_DEBUG', 'true')
+ expect(resource).to receive(:fabricate_via_api!).and_return(location)
+
+ expect { subject.fabricate_via_api!('something', resource: resource, parents: []) }
+ .to output(/==> Built a MyResource via api in [\d\.\-e]+ seconds+/)
+ .to_stdout
+ end
+ end
+
+ describe '.fabricate_via_browser_ui!' do
+ include_context 'fabrication context'
+
+ it_behaves_like 'fabrication method', :fabricate_via_browser_ui!, :fabricate!
+
+ it 'instantiates the resource and calls resource method' do
+ subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+
+ expect(resource).to have_received(:fabricate!).with('something')
+ end
+
+ it 'returns fabrication resource' do
+ result = subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+
+ expect(result).to eq(resource)
+ end
+
+ it 'logs the resource and build method when QA_DEBUG=true' do
+ stub_env('QA_DEBUG', 'true')
+
+ expect { subject.fabricate_via_browser_ui!('something', resource: resource, parents: []) }
+ .to output(/==> Built a MyResource via browser_ui in [\d\.\-e]+ seconds+/)
+ .to_stdout
+ end
+ end
+
+ shared_context 'simple resource' do
+ subject do
+ Class.new(QA::Resource::Base) do
+ attribute :test do
+ 'block'
+ end
+
+ attribute :no_block
+
+ def fabricate!
+ 'any'
+ end
+
+ def self.current_url
+ 'http://stub'
+ end
+ end
+ end
+
+ let(:resource) { subject.new }
+ end
+
+ describe '.attribute' do
+ include_context 'simple resource'
+
+ it 'appends new attribute' do
+ expect(subject.attributes_names).to eq([:no_block, :test, :web_url])
+ end
+
+ context 'when the attribute is populated via a block' do
+ it 'returns value from the block' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('block')
+ end
+ end
+
+ context 'when the attribute is populated via the api' do
+ let(:api_resource) { { no_block: 'api' } }
+
+ before do
+ expect(resource).to receive(:api_resource).and_return(api_resource)
+ end
+
+ it 'returns value from api' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.no_block).to eq('api')
+ end
+
+ context 'when the attribute also has a block' do
+ let(:api_resource) { { test: 'api_with_block' } }
+
+ before do
+ allow(QA::Runtime::Logger).to receive(:info)
+ end
+
+ it 'returns value from api and emits an INFO log entry' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('api_with_block')
+ expect(QA::Runtime::Logger)
+ .to have_received(:info).with(/api_with_block/)
+ end
+ end
+ end
+
+ context 'when the attribute is populated via direct assignment' do
+ before do
+ resource.test = 'value'
+ end
+
+ it 'returns value from the assignment' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('value')
+ end
+
+ context 'when the api also has such response' do
+ before do
+ allow(resource).to receive(:api_resource).and_return({ test: 'api' })
+ end
+
+ it 'returns value from the assignment' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('value')
+ end
+ end
+ end
+
+ context 'when the attribute has no value' do
+ it 'raises an error because no values could be found' do
+ result = subject.fabricate!(resource: resource)
+
+ expect { result.no_block }
+ .to raise_error(described_class::NoValueError, "No value was computed for no_block of #{resource.class.name}.")
+ end
+ end
+ end
+
+ describe '#web_url' do
+ include_context 'simple resource'
+
+ it 'sets #web_url to #current_url after fabrication' do
+ subject.fabricate!(resource: resource)
+
+ expect(resource.web_url).to eq(subject.current_url)
+ end
+ end
+
+ describe '#visit!' do
+ include_context 'simple resource'
+
+ before do
+ allow(resource).to receive(:visit)
+ end
+
+ it 'calls #visit with the underlying #web_url' do
+ resource.web_url = subject.current_url
+ resource.visit!
+
+ expect(resource).to have_received(:visit).with(subject.current_url)
+ end
+ end
+end