diff options
Diffstat (limited to 'qa/spec/factory')
-rw-r--r-- | qa/spec/factory/api_fabricator_spec.rb | 61 | ||||
-rw-r--r-- | qa/spec/factory/base_spec.rb | 205 | ||||
-rw-r--r-- | qa/spec/factory/product_spec.rb | 60 |
3 files changed, 113 insertions, 213 deletions
diff --git a/qa/spec/factory/api_fabricator_spec.rb b/qa/spec/factory/api_fabricator_spec.rb index 3fda5407549..8f8c29dd92d 100644 --- a/qa/spec/factory/api_fabricator_spec.rb +++ b/qa/spec/factory/api_fabricator_spec.rb @@ -27,26 +27,12 @@ describe QA::Factory::ApiFabricator do end end - subject { factory.tap { |f| f.include(described_class) }.new } - - describe '#api_support?' do - context 'when factory does not respond to api_get_path, api_post_path, and api_post_body' do - let(:factory) { factory_without_api_support } - - it 'returns false' do - expect(subject).not_to be_api_support - end - end - - context 'when factory responds to api_get_path, api_post_path, and api_post_body' do - let(:factory) { factory_with_api_support } - - it 'returns true' do - expect(subject).to be_api_support - end - end + before do + allow(subject).to receive(:current_url).and_return('') end + subject { factory.tap { |f| f.include(described_class) }.new } + describe '#fabricate_via_api!' do context 'when factory does not support fabrication via the API' do let(:factory) { factory_without_api_support } @@ -63,7 +49,7 @@ describe QA::Factory::ApiFabricator do let(:api_request) { spy('Runtime::API::Request') } let(:resource_web_url) { 'http://example.org/api/v4/foo' } let(:resource) { { id: 1, name: 'John Doe', web_url: resource_web_url } } - let(:raw_get) { double('Raw GET response', code: 200, body: resource.to_json) } + let(:raw_post) { double('Raw POST response', code: 201, body: resource.to_json) } before do stub_const('QA::Runtime::API::Client', api_client) @@ -71,44 +57,15 @@ describe QA::Factory::ApiFabricator do allow(api_client).to receive(:new).and_return(api_client_instance) allow(api_request).to receive(:new).and_return(double(url: resource_web_url)) - allow(subject).to receive(:get).with(resource_web_url).and_return(raw_get) - end - - context 'when resource already exists' do - it 'returns the resource URL' do - expect(api_request).to receive(:new).with(api_client_instance, subject.api_get_path).and_return(double(url: resource_web_url)) - expect(subject).to receive(:get).with(resource_web_url).and_return(raw_get) - - expect(subject.fabricate_via_api!).to eq(resource_web_url) - end - - it 'populates api_resource with the resource' do - subject.fabricate_via_api! - - expect(subject.api_resource).to eq(resource) - end - - context 'when the resource does not expose a `web_url` property' do - let(:resource) { { id: 1, name: 'John Doe' } } - - it 'raises a ResourceFabricationFailedError exception' do - expect { subject.fabricate_via_api! }.to raise_error(described_class::ResourceURLMissingError, "API resource for FooBarFactory does not expose a `web_url` property: `#{resource}`.") - expect(subject.api_resource).to eq(resource) - end - end end context 'when the resource does not exist' do - let(:raw_get) { double('Raw GET response', code: 404, body: { error: "404 not found." }.to_json) } - let(:raw_post) { double('Raw POST response', code: 201, body: resource.to_json) } - before do allow(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post) end it 'returns the resource URL' do - expect(api_request).to receive(:new).with(api_client_instance, subject.api_get_path).and_return(double(url: resource_web_url)) - expect(subject).to receive(:get).with(resource_web_url).and_return(raw_get) + expect(api_request).to receive(:new).with(api_client_instance, subject.api_post_path).and_return(double(url: resource_web_url)) expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post) expect(subject.fabricate_via_api!).to eq(resource_web_url) @@ -125,11 +82,10 @@ describe QA::Factory::ApiFabricator do let(:raw_post) { double('Raw POST response', code: 400, body: post_response.to_json) } it 'raises a ResourceFabricationFailedError exception' do - expect(api_request).to receive(:new).with(api_client_instance, subject.api_get_path).and_return(double(url: resource_web_url)) - expect(subject).to receive(:get).with(resource_web_url).and_return(raw_get) + expect(api_request).to receive(:new).with(api_client_instance, subject.api_post_path).and_return(double(url: resource_web_url)) expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post) - expect { subject.fabricate_via_api! }.to raise_error(described_class::ResourceFabricationFailedError, "Fabrication of FooBarFactory using the API failed (400) with `#{post_response}`.") + expect { subject.fabricate_via_api! }.to raise_error(described_class::ResourceFabricationFailedError, "Fabrication of FooBarFactory using the API failed (400) with `#{raw_post}`.") expect(subject.api_resource).to be_nil end end @@ -165,6 +121,7 @@ describe QA::Factory::ApiFabricator do let(:transformed_resource) { { existing: 'foo', new: 'foobar', web_url: resource_web_url } } it 'transforms the resource' do + expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post) expect(subject).to receive(:transform_api_resource).with(resource).and_return(transformed_resource) subject.fabricate_via_api! diff --git a/qa/spec/factory/base_spec.rb b/qa/spec/factory/base_spec.rb index 0457d878270..b9cf60e4cc0 100644 --- a/qa/spec/factory/base_spec.rb +++ b/qa/spec/factory/base_spec.rb @@ -11,124 +11,107 @@ describe QA::Factory::Base do subject { Class.new(described_class) } before do - allow(QA::Factory::Product).to receive(:new).with(product_location).and_return(product) - allow(QA::Factory::Product).to receive(:populate!).and_return(product) allow(subject).to receive(:current_url).and_return(product_location) allow(subject).to receive(:new).and_return(factory) + allow(QA::Factory::Product).to receive(:populate!).with(factory, product_location).and_return(product) end end - shared_examples 'API fabrication method' do |fabrication_method_called, actual_fabrication_method = nil| + shared_examples 'fabrication method' do |fabrication_method_called, actual_fabrication_method = nil| let(:fabrication_method_used) { actual_fabrication_method || fabrication_method_called } - include_context 'fabrication context' + it 'yields factory before calling factory method' do + allow(subject).to receive(:new).and_return(factory) - it_behaves_like 'fabrication method', fabrication_method_called, actual_fabrication_method + expect(factory).to receive(:something!).ordered + expect(factory).to receive(fabrication_method_used).ordered.and_return(product_location) - it 'instantiates the factory and calls factory method' do - expect(subject).to receive(:new).and_return(factory) + subject.public_send(fabrication_method_called) do |factory| + factory.something! + end + end - subject.public_send(fabrication_method_called) + it 'does not log the factory and build method when VERBOSE=false' do + stub_env('VERBOSE', 'false') + expect(factory).to receive(fabrication_method_used).and_return(product_location) - expect(factory).to have_received(fabrication_method_used) + expect { subject.public_send(fabrication_method_called, 'something') } + .not_to output(/Resource #{factory.class.name} built via/) + .to_stdout end + end - it 'returns fabrication product' do - result = subject.public_send(fabrication_method_called) + describe '.fabricate!' do + context 'when factory 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!) - expect(result).to eq product + described_class.fabricate! + end end - it 'logs the factory and build method when VERBOSE=true' do - stub_env('VERBOSE', 'true') + context 'when factory supports fabrication via the API' do + it 'calls .fabricate_via_browser_ui!' do + expect(described_class).to receive(:fabricate_via_api!) - expect { subject.public_send(fabrication_method_called) } - .to output(/Resource #{factory.class.name} built via do_fabricate_via_api/) - .to_stdout + described_class.fabricate! + end end end - shared_examples 'Browser UI fabrication method' do |fabrication_method_called, actual_fabrication_method = nil| - let(:fabrication_method_used) { actual_fabrication_method || fabrication_method_called } - + describe '.fabricate_via_api!' do include_context 'fabrication context' - it_behaves_like 'fabrication method', fabrication_method_called, actual_fabrication_method - - it 'instantiates the factory and calls factory method' do - expect(subject).to receive(:new).and_return(factory) - - subject.public_send(fabrication_method_called, 'something') + it_behaves_like 'fabrication method', :fabricate_via_api! - expect(factory).to have_received(fabrication_method_used).with('something') - end + it 'instantiates the factory, calls factory method returns fabrication product' do + expect(factory).to receive(:fabricate_via_api!).and_return(product_location) - it 'returns fabrication product' do - result = subject.public_send(fabrication_method_called, 'something') + result = subject.fabricate_via_api! - expect(result).to eq product + expect(result).to eq(product) end it 'logs the factory and build method when VERBOSE=true' do stub_env('VERBOSE', 'true') + expect(factory).to receive(:fabricate_via_api!).and_return(product_location) - expect { subject.public_send(fabrication_method_called, 'something') } - .to output(/Resource #{factory.class.name} built via do_fabricate_via_browser_ui/) + expect { subject.fabricate_via_api! } + .to output(/Resource #{factory.class.name} built via api/) .to_stdout end end - shared_examples 'fabrication method' do |fabrication_method_called, actual_fabrication_method = nil| - let(:fabrication_method_used) { actual_fabrication_method || fabrication_method_called } - + describe '.fabricate_via_browser_ui!' do include_context 'fabrication context' - it 'yields factory before calling factory method' do - allow(subject).to receive(:new).and_return(factory) - - subject.public_send(fabrication_method_called) do |factory| - factory.something! - end + it_behaves_like 'fabrication method', :fabricate_via_browser_ui!, :fabricate! - expect(factory).to have_received(:something!).ordered - expect(factory).to have_received(fabrication_method_used).ordered - end - - it 'does not log the factory and build method when VERBOSE=false' do - stub_env('VERBOSE', 'false') + it 'instantiates the factory and calls factory method' do + subject.fabricate_via_browser_ui!('something') - expect { subject.public_send(fabrication_method_called, 'something') } - .not_to output(/Resource #{factory.class.name} built via/) - .to_stdout + expect(factory).to have_received(:fabricate!).with('something') end - end - describe '.fabricate!' do - context 'when factory does not support fabrication via the API' do - before do - allow(factory).to receive(:api_support?).and_return(false) - end + it 'returns fabrication product' do + result = subject.fabricate_via_browser_ui!('something') - it_behaves_like 'Browser UI fabrication method', :fabricate! + expect(result).to eq(product) end - context 'when factory supports fabrication via the API' do - before do - allow(factory).to receive(:api_support?).and_return(true) - end + it 'logs the factory and build method when VERBOSE=true' do + stub_env('VERBOSE', 'true') - it_behaves_like 'API fabrication method', :fabricate!, :fabricate_via_api! + expect { subject.fabricate_via_browser_ui!('something') } + .to output(/Resource #{factory.class.name} built via browser_ui/) + .to_stdout end end - describe '.fabricate_via_api!' do - it_behaves_like 'API fabrication method', :fabricate_via_api! - end - - describe '.fabricate_via_browser_ui!' do - it_behaves_like 'Browser UI fabrication method', :fabricate_via_browser_ui!, :fabricate! - end - describe '.dependency' do let(:dependency) { spy('dependency') } @@ -168,8 +151,7 @@ describe QA::Factory::Base do allow(subject).to receive(:new).and_return(instance) allow(subject).to receive(:current_url).and_return(product_location) allow(instance).to receive(:mydep).and_return(nil) - allow(QA::Factory::Product).to receive(:new) - allow(QA::Factory::Product).to receive(:populate!) + expect(QA::Factory::Product).to receive(:populate!) end it 'builds all dependencies first' do @@ -181,79 +163,22 @@ describe QA::Factory::Base do end describe '.product' do - context 'when the product is produced via the browser' do - subject do - Class.new(described_class) do - def fabricate! - "any" - end - - # Defined only to be stubbed - def self.find_page - end - - product :token do - find_page.do_something_on_page! - 'resulting value' - end - end - end - - it 'appends new product attribute' do - expect(subject.attributes).to be_one - expect(subject.attributes).to have_key(:token) - end - - describe 'populating fabrication product with data' do - let(:page) { spy('page') } + include_context 'fabrication context' - before do - allow(QA::Factory::Product).to receive(:new).and_return(product) - allow(product).to receive(:page).and_return(page) - allow(subject).to receive(:current_url).and_return(product_location) - allow(subject).to receive(:find_page).and_return(page) + subject do + Class.new(described_class) do + def fabricate! + "any" end - it 'populates product after fabrication' do - subject.fabricate! - - expect(product.token).to eq 'resulting value' - expect(page).to have_received(:do_something_on_page!) - end + product :token end end - context 'when the product is producted via the API' do - subject do - Class.new(described_class) do - def fabricate! - "any" - end - - product :token - end - end - - it 'appends new product attribute' do - expect(subject.attributes).to be_one - expect(subject.attributes).to have_key(:token) - end - - describe 'populating fabrication product with data' do - before do - allow(subject).to receive(:new).and_return(factory) - allow(factory).to receive(:class).and_return(subject) - allow(factory).to receive(:api_support?).and_return(true) - allow(factory).to receive(:api_resource).and_return({ token: 'resulting value' }) - allow(QA::Factory::Product).to receive(:new).and_return(product) - end - - it 'populates product after fabrication' do - subject.fabricate! - - expect(product.token).to eq 'resulting value' - end - end + it 'appends new product attribute' do + expect(subject.attributes).to be_one + expect(subject.attributes[0]).to be_a(QA::Factory::Product::Attribute) + expect(subject.attributes[0].name).to eq(:token) end end end diff --git a/qa/spec/factory/product_spec.rb b/qa/spec/factory/product_spec.rb index 2f2d5568af7..43b1d93d769 100644 --- a/qa/spec/factory/product_spec.rb +++ b/qa/spec/factory/product_spec.rb @@ -1,51 +1,71 @@ describe QA::Factory::Product do let(:factory) do - QA::Factory::Base.new + Class.new(QA::Factory::Base) do + def foo + 'bar' + end + end.new end let(:product) { spy('product') } let(:product_location) { 'http://product_location' } - subject { described_class.new(product_location) } + subject { described_class.new(factory, product_location) } describe '.populate!' do before do - allow(QA::Factory::Base).to receive(:attributes).and_return(attributes) + expect(factory.class).to receive(:attributes).and_return(attributes) end - context 'when the product is produced via the browser' do + context 'when the product attribute is populated via a block' do let(:attributes) do - { test: QA::Factory::Product::Attribute.new(:test, proc { 'returned' }) } + [QA::Factory::Product::Attribute.new(:test, proc { 'returned' })] end it 'returns a fabrication product and defines factory attributes as its methods' do - expect(described_class).to receive(:new).with(product_location).and_return(product) + result = described_class.populate!(factory, product_location) + + expect(result).to be_a(described_class) + expect(result.test).to eq('returned') + end + end - result = described_class.populate!(factory, product_location) do |instance| - instance.something = 'string' - end + context 'when the product attribute is populated via the api' do + let(:attributes) do + [QA::Factory::Product::Attribute.new(:test)] + end + + it 'returns a fabrication product and defines factory attributes as its methods' do + expect(factory).to receive(:api_resource).and_return({ test: 'returned' }) - expect(result).to be product + result = described_class.populate!(factory, product_location) + + expect(result).to be_a(described_class) expect(result.test).to eq('returned') end end - context 'when the product is produced via the api' do + context 'when the product attribute is populated via a factory attribute' do let(:attributes) do - { test: QA::Factory::Product::Attribute.new(:test) } + [QA::Factory::Product::Attribute.new(:foo)] end it 'returns a fabrication product and defines factory attributes as its methods' do - allow(factory).to receive(:api_resource).and_return({ test: 'returned' }) + result = described_class.populate!(factory, product_location) - expect(described_class).to receive(:new).with(product_location).and_return(product) + expect(result).to be_a(described_class) + expect(result.foo).to eq('bar') + end + end - result = described_class.populate!(factory, product_location) do |instance| - instance.something = 'string' - end + context 'when the product attribute has no value' do + let(:attributes) do + [QA::Factory::Product::Attribute.new(:bar)] + end - expect(result).to be product - expect(result.test).to eq('returned') + it 'returns a fabrication product and defines factory attributes as its methods' do + expect { described_class.populate!(factory, product_location) } + .to raise_error(described_class::NoValueError, "No value was computed for product bar of factory #{factory.class.name}.") end end end @@ -53,8 +73,6 @@ describe QA::Factory::Product do describe '.visit!' do it 'makes it possible to visit fabrication product' do allow_any_instance_of(described_class) - .to receive(:current_url).and_return('some url') - allow_any_instance_of(described_class) .to receive(:visit).and_return('visited some url') expect(subject.visit!).to eq 'visited some url' |