diff options
Diffstat (limited to 'qa/spec')
-rw-r--r-- | qa/spec/factory/base_spec.rb | 66 | ||||
-rw-r--r-- | qa/spec/factory/product_spec.rb | 21 | ||||
-rw-r--r-- | qa/spec/page/base_spec.rb | 63 | ||||
-rw-r--r-- | qa/spec/page/element_spec.rb | 51 | ||||
-rw-r--r-- | qa/spec/page/validator_spec.rb | 79 | ||||
-rw-r--r-- | qa/spec/page/view_spec.rb | 70 | ||||
-rw-r--r-- | qa/spec/scenario/test/sanity/selectors_spec.rb | 40 |
7 files changed, 355 insertions, 35 deletions
diff --git a/qa/spec/factory/base_spec.rb b/qa/spec/factory/base_spec.rb index a3ba0176819..90dd58e20fd 100644 --- a/qa/spec/factory/base_spec.rb +++ b/qa/spec/factory/base_spec.rb @@ -1,8 +1,9 @@ describe QA::Factory::Base do + let(:factory) { spy('factory') } + let(:product) { spy('product') } + describe '.fabricate!' do subject { Class.new(described_class) } - let(:factory) { spy('factory') } - let(:product) { spy('product') } before do allow(QA::Factory::Product).to receive(:new).and_return(product) @@ -59,30 +60,63 @@ describe QA::Factory::Base do it 'defines dependency accessors' do expect(subject.new).to respond_to :mydep, :mydep= end - end - describe 'building dependencies' do - let(:dependency) { double('dependency') } - let(:instance) { spy('instance') } + describe 'dependencies fabrication' do + let(:dependency) { double('dependency') } + let(:instance) { spy('instance') } + + subject do + Class.new(described_class) do + dependency Some::MyDependency, as: :mydep + end + end + + before do + stub_const('Some::MyDependency', dependency) + allow(subject).to receive(:new).and_return(instance) + allow(instance).to receive(:mydep).and_return(nil) + allow(QA::Factory::Product).to receive(:new) + end + + it 'builds all dependencies first' do + expect(dependency).to receive(:fabricate!).once + + subject.fabricate! + end + end + end + + describe '.product' do subject do Class.new(described_class) do - dependency Some::MyDependency, as: :mydep + product :token do + page.do_something_on_page! + 'resulting value' + end end end - before do - stub_const('Some::MyDependency', dependency) - - allow(subject).to receive(:new).and_return(instance) - allow(instance).to receive(:mydep).and_return(nil) - allow(QA::Factory::Product).to receive(:new) + it 'appends new product attribute' do + expect(subject.attributes).to be_one + expect(subject.attributes).to have_key(:token) end - it 'builds all dependencies first' do - expect(dependency).to receive(:fabricate!).once + describe 'populating fabrication product with data' do + let(:page) { spy('page') } + + before do + allow(subject).to receive(:new).and_return(factory) + allow(QA::Factory::Product).to receive(:new).and_return(product) + allow(product).to receive(:page).and_return(page) + end - subject.fabricate! + it 'populates product after fabrication' do + subject.fabricate! + + expect(page).to have_received(:do_something_on_page!) + expect(product.token).to eq 'resulting value' + end end end end diff --git a/qa/spec/factory/product_spec.rb b/qa/spec/factory/product_spec.rb index 3d9e86a641b..fdfb1ec90cc 100644 --- a/qa/spec/factory/product_spec.rb +++ b/qa/spec/factory/product_spec.rb @@ -3,19 +3,8 @@ describe QA::Factory::Product do let(:product) { spy('product') } describe '.populate!' do - it 'instantiates and yields factory' do - expect(described_class).to receive(:new).with(factory) - - described_class.populate!(factory) do |instance| - instance.something = 'string' - end - - expect(factory).to have_received(:something=).with('string') - end - it 'returns a fabrication product' do - expect(described_class).to receive(:new) - .with(factory).and_return(product) + expect(described_class).to receive(:new).and_return(product) result = described_class.populate!(factory) do |instance| instance.something = 'string' @@ -23,11 +12,6 @@ describe QA::Factory::Product do expect(result).to be product end - - it 'raises unless block given' do - expect { described_class.populate!(factory) } - .to raise_error ArgumentError - end end describe '.visit!' do @@ -37,8 +21,7 @@ describe QA::Factory::Product do allow_any_instance_of(described_class) .to receive(:visit).and_return('visited some url') - expect(described_class.new(factory).visit!) - .to eq 'visited some url' + expect(subject.visit!).to eq 'visited some url' end end end diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb new file mode 100644 index 00000000000..287adf35c46 --- /dev/null +++ b/qa/spec/page/base_spec.rb @@ -0,0 +1,63 @@ +describe QA::Page::Base do + describe 'page helpers' do + it 'exposes helpful page helpers' do + expect(subject).to respond_to :refresh, :wait, :scroll_to + end + end + + describe '.view', 'DSL for defining view partials' do + subject do + Class.new(described_class) do + view 'path/to/some/view.html.haml' do + element :something, 'string pattern' + element :something_else, /regexp pattern/ + end + + view 'path/to/some/_partial.html.haml' do + element :something, 'string pattern' + end + end + end + + it 'makes it possible to define page views' do + expect(subject.views.size).to eq 2 + expect(subject.views).to all(be_an_instance_of QA::Page::View) + end + + it 'populates views objects with data about elements' do + subject.views.first.elements.tap do |elements| + expect(elements.size).to eq 2 + expect(elements).to all(be_an_instance_of QA::Page::Element) + expect(elements.map(&:name)).to eq [:something, :something_else] + end + end + end + + describe '.errors' do + let(:view) { double('view') } + + context 'when page has views and elements defined' do + before do + allow(described_class).to receive(:views) + .and_return([view]) + + allow(view).to receive(:errors).and_return(['some error']) + end + + it 'iterates views composite and returns errors' do + expect(described_class.errors).to eq ['some error'] + end + end + + context 'when page has no views and elements defined' do + before do + allow(described_class).to receive(:views).and_return([]) + end + + it 'appends an error about missing views / elements block' do + expect(described_class.errors) + .to include 'Page class does not have views / elements defined!' + end + end + end +end diff --git a/qa/spec/page/element_spec.rb b/qa/spec/page/element_spec.rb new file mode 100644 index 00000000000..8598c57ad34 --- /dev/null +++ b/qa/spec/page/element_spec.rb @@ -0,0 +1,51 @@ +describe QA::Page::Element do + describe '#selector' do + it 'transforms element name into QA-specific selector' do + expect(described_class.new(:sign_in_button).selector) + .to eq 'qa-sign-in-button' + end + end + + describe '#selector_css' do + it 'transforms element name into QA-specific clickable css selector' do + expect(described_class.new(:sign_in_button).selector_css) + .to eq '.qa-sign-in-button' + end + end + + context 'when pattern is an expression' do + subject { described_class.new(:something, /button 'Sign in'/) } + + it 'matches when there is a match' do + expect(subject.matches?("button 'Sign in'")).to be true + end + + it 'does not match if pattern is not present' do + expect(subject.matches?("button 'Sign out'")).to be false + end + end + + context 'when pattern is a string' do + subject { described_class.new(:something, 'button') } + + it 'matches when there is match' do + expect(subject.matches?('some button in the view')).to be true + end + + it 'does not match if pattern is not present' do + expect(subject.matches?('text_field :name')).to be false + end + end + + context 'when pattern is not provided' do + subject { described_class.new(:some_name) } + + it 'matches when QA specific selector is present' do + expect(subject.matches?('some qa-some-name selector')).to be true + end + + it 'does not match if QA selector is not there' do + expect(subject.matches?('some_name selector')).to be false + end + end +end diff --git a/qa/spec/page/validator_spec.rb b/qa/spec/page/validator_spec.rb new file mode 100644 index 00000000000..02822d7d18f --- /dev/null +++ b/qa/spec/page/validator_spec.rb @@ -0,0 +1,79 @@ +describe QA::Page::Validator do + describe '#constants' do + subject do + described_class.new(QA::Page::Project) + end + + it 'returns all constants that are module children' do + expect(subject.constants) + .to include QA::Page::Project::New, QA::Page::Project::Settings + end + end + + describe '#descendants' do + subject do + described_class.new(QA::Page::Project) + end + + it 'recursively returns all descendants that are page objects' do + expect(subject.descendants) + .to include QA::Page::Project::New, QA::Page::Project::Settings::Repository + end + + it 'does not return modules that aggregate page objects' do + expect(subject.descendants) + .not_to include QA::Page::Project::Settings + end + end + + context 'when checking validation errors' do + let(:view) { spy('view') } + + before do + allow(QA::Page::Admin::Settings) + .to receive(:views).and_return([view]) + end + + subject do + described_class.new(QA::Page::Admin) + end + + context 'when there are no validation errors' do + before do + allow(view).to receive(:errors).and_return([]) + end + + describe '#errors' do + it 'does not return errors' do + expect(subject.errors).to be_empty + end + end + + describe '#validate!' do + it 'does not raise error' do + expect { subject.validate! }.not_to raise_error + end + end + end + + context 'when there are validation errors' do + before do + allow(view).to receive(:errors) + .and_return(['some error', 'another error']) + end + + describe '#errors' do + it 'returns errors' do + expect(subject.errors.count).to eq 2 + end + end + + describe '#validate!' do + it 'raises validation error' do + expect { subject.validate! } + .to raise_error described_class::ValidationError + end + end + end + end +end diff --git a/qa/spec/page/view_spec.rb b/qa/spec/page/view_spec.rb new file mode 100644 index 00000000000..aedbc3863a7 --- /dev/null +++ b/qa/spec/page/view_spec.rb @@ -0,0 +1,70 @@ +describe QA::Page::View do + let(:element) do + double('element', name: :something, pattern: /some element/) + end + + subject { described_class.new('some/file.html', [element]) } + + describe '.evaluate' do + it 'evaluates a block and returns a DSL object' do + results = described_class.evaluate do + element :something, 'my pattern' + element :something_else, /another pattern/ + end + + expect(results.elements.size).to eq 2 + end + end + + describe '#pathname' do + it 'returns an absolute and clean path to the view' do + expect(subject.pathname.to_s).not_to include 'qa/page/' + expect(subject.pathname.to_s).to include 'some/file.html' + end + end + + describe '#errors' do + context 'when view partial is present' do + before do + allow(subject.pathname).to receive(:readable?) + .and_return(true) + end + + context 'when pattern is found' do + before do + allow(File).to receive(:foreach) + .and_yield('some element').once + allow(element).to receive(:matches?) + .with('some element').and_return(true) + end + + it 'walks through the view and asserts on elements existence' do + expect(subject.errors).to be_empty + end + end + + context 'when pattern has not been found' do + before do + allow(File).to receive(:foreach) + .and_yield('some element').once + allow(element).to receive(:matches?) + .with('some element').and_return(false) + end + + it 'returns an array of errors related to missing elements' do + expect(subject.errors).not_to be_empty + expect(subject.errors.first) + .to match %r(Missing element `.*` in `.*/some/file.html` view) + end + end + end + + context 'when view partial has not been found' do + it 'returns an error when it is not able to find the partial' do + expect(subject.errors).to be_one + expect(subject.errors.first) + .to match %r(Missing view partial `.*/some/file.html`!) + end + end + end +end diff --git a/qa/spec/scenario/test/sanity/selectors_spec.rb b/qa/spec/scenario/test/sanity/selectors_spec.rb new file mode 100644 index 00000000000..45d21d54955 --- /dev/null +++ b/qa/spec/scenario/test/sanity/selectors_spec.rb @@ -0,0 +1,40 @@ +describe QA::Scenario::Test::Sanity::Selectors do + let(:validator) { spy('validator') } + + before do + stub_const('QA::Page::Validator', validator) + end + + context 'when there are errors detected' do + before do + allow(validator).to receive(:errors).and_return(['some error']) + end + + it 'outputs information about errors' do + expect { described_class.perform } + .to output(/some error/).to_stderr + + expect { described_class.perform } + .to output(/electors validation test detected problems/) + .to_stderr + end + end + + context 'when there are no errors detected' do + before do + allow(validator).to receive(:errors).and_return([]) + end + + it 'processes pages module' do + described_class.perform + + expect(validator).to have_received(:new).with(QA::Page) + end + + it 'triggers validation' do + described_class.perform + + expect(validator).to have_received(:validate!).at_least(:once) + end + end +end |