summaryrefslogtreecommitdiff
path: root/qa/spec
diff options
context:
space:
mode:
Diffstat (limited to 'qa/spec')
-rw-r--r--qa/spec/factory/base_spec.rb66
-rw-r--r--qa/spec/factory/product_spec.rb21
-rw-r--r--qa/spec/page/base_spec.rb63
-rw-r--r--qa/spec/page/element_spec.rb51
-rw-r--r--qa/spec/page/validator_spec.rb79
-rw-r--r--qa/spec/page/view_spec.rb70
-rw-r--r--qa/spec/scenario/test/sanity/selectors_spec.rb40
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