diff options
Diffstat (limited to 'qa')
24 files changed, 201 insertions, 70 deletions
diff --git a/qa/.gitignore b/qa/.gitignore index 3fec32c8427..19ec17d0005 100644 --- a/qa/.gitignore +++ b/qa/.gitignore @@ -1 +1,2 @@ tmp/ +.ruby-version diff --git a/qa/bin/qa b/qa/bin/qa index cecdeac14db..6a772e93cee 100755 --- a/qa/bin/qa +++ b/qa/bin/qa @@ -4,4 +4,4 @@ require_relative '../qa' QA::Scenario .const_get(ARGV.shift) - .perform(*ARGV) + .launch!(ARGV) @@ -18,6 +18,7 @@ module QA ## # Support files # + autoload :Bootable, 'qa/scenario/bootable' autoload :Actable, 'qa/scenario/actable' autoload :Entrypoint, 'qa/scenario/entrypoint' autoload :Template, 'qa/scenario/template' @@ -61,6 +62,7 @@ module QA module Main autoload :Entry, 'qa/page/main/entry' + autoload :Login, 'qa/page/main/login' autoload :Menu, 'qa/page/main/menu' end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index b9e199000d6..59cd147e055 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -23,7 +23,7 @@ module QA def password=(pass) @password = pass - @uri.password = pass + @uri.password = CGI.escape(pass) end def use_default_credentials diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index d55326c5262..bdddfb877c5 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -5,7 +5,7 @@ module QA include Scenario::Actable def refresh - visit current_path + visit current_url end end end diff --git a/qa/qa/page/main/entry.rb b/qa/qa/page/main/entry.rb index a9810beeb29..ac939732b1d 100644 --- a/qa/qa/page/main/entry.rb +++ b/qa/qa/page/main/entry.rb @@ -2,9 +2,14 @@ module QA module Page module Main class Entry < Page::Base - def initialize - visit('/') + def visit_login_page + visit("#{Runtime::Scenario.gitlab_address}/users/sign_in") + wait_for_instance_to_be_ready + end + + private + def wait_for_instance_to_be_ready # This resolves cold boot / background tasks problems # start = Time.now @@ -14,18 +19,6 @@ module QA refresh end end - - def sign_in_using_credentials - if page.has_content?('Change your password') - fill_in :user_password, with: Runtime::User.password - fill_in :user_password_confirmation, with: Runtime::User.password - click_button 'Change your password' - end - - fill_in :user_login, with: Runtime::User.name - fill_in :user_password, with: Runtime::User.password - click_button 'Sign in' - end end end end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb new file mode 100644 index 00000000000..8b0111a78a2 --- /dev/null +++ b/qa/qa/page/main/login.rb @@ -0,0 +1,19 @@ +module QA + module Page + module Main + class Login < Page::Base + def sign_in_using_credentials + if page.has_content?('Change your password') + fill_in :user_password, with: Runtime::User.password + fill_in :user_password_confirmation, with: Runtime::User.password + click_button 'Change your password' + end + + fill_in :user_login, with: Runtime::User.name + fill_in :user_password, with: Runtime::User.password + click_button 'Sign in' + end + end + end + end +end diff --git a/qa/qa/page/mattermost/login.rb b/qa/qa/page/mattermost/login.rb index 2001dc5b230..42ab9c6f675 100644 --- a/qa/qa/page/mattermost/login.rb +++ b/qa/qa/page/mattermost/login.rb @@ -3,7 +3,7 @@ module QA module Mattermost class Login < Page::Base def initialize - visit(Runtime::Scenario.mattermost + '/login') + visit(Runtime::Scenario.mattermost_address + '/login') end def sign_in_using_oauth diff --git a/qa/qa/page/mattermost/main.rb b/qa/qa/page/mattermost/main.rb index e636d7676f4..4b8fc28e53f 100644 --- a/qa/qa/page/mattermost/main.rb +++ b/qa/qa/page/mattermost/main.rb @@ -3,7 +3,7 @@ module QA module Mattermost class Main < Page::Base def initialize - visit(Runtime::Scenario.mattermost) + visit(Runtime::Scenario.mattermost_address) end end end diff --git a/qa/qa/runtime/scenario.rb b/qa/qa/runtime/scenario.rb index 0c5e9787e17..7ef59046640 100644 --- a/qa/qa/runtime/scenario.rb +++ b/qa/qa/runtime/scenario.rb @@ -1,8 +1,28 @@ module QA module Runtime + ## + # Singleton approach to global test scenario arguments. + # module Scenario extend self - attr_accessor :mattermost + + attr_reader :attributes + + def define(attribute, value) + (@attributes ||= {}).store(attribute.to_sym, value) + + define_singleton_method(attribute) do + @attributes[attribute.to_sym].tap do |value| + if value.to_s.empty? + raise ArgumentError, "Empty `#{attribute}` attribute!" + end + end + end + end + + def method_missing(name, *) + raise ArgumentError, "Scenario attribute `#{name}` not defined!" + end end end end diff --git a/qa/qa/scenario/bootable.rb b/qa/qa/scenario/bootable.rb new file mode 100644 index 00000000000..cf8996cd597 --- /dev/null +++ b/qa/qa/scenario/bootable.rb @@ -0,0 +1,45 @@ +require 'optparse' + +module QA + module Scenario + module Bootable + Option = Struct.new(:name, :arg, :desc) + + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def launch!(argv) + return self.perform(*argv) unless has_attributes? + + arguments = OptionParser.new do |parser| + options.to_a.each do |opt| + parser.on(opt.arg, opt.desc) do |value| + Runtime::Scenario.define(opt.name, value) + end + end + end + + arguments.parse!(argv) + + self.perform(**Runtime::Scenario.attributes) + end + + private + + def attribute(name, arg, desc) + options.push(Option.new(name, arg, desc)) + end + + def options + @options ||= [] + end + + def has_attributes? + options.any? + end + end + end + end +end diff --git a/qa/qa/scenario/entrypoint.rb b/qa/qa/scenario/entrypoint.rb index 33cb2696f8f..ae099fd911e 100644 --- a/qa/qa/scenario/entrypoint.rb +++ b/qa/qa/scenario/entrypoint.rb @@ -5,18 +5,10 @@ module QA # including staging and on-premises installation. # class Entrypoint < Template - def self.tags(*tags) - @tags = tags - end - - def self.get_tags - @tags - end + include Bootable def perform(address, *files) - Specs::Config.perform do |specs| - specs.address = address - end + Runtime::Scenario.define(:gitlab_address, address) ## # Perform before hooks, which are different for CE and EE @@ -24,13 +16,19 @@ module QA Runtime::Release.perform_before_hooks Specs::Runner.perform do |specs| - specs.rspec( - tty: true, - tags: self.class.get_tags, - files: files.any? ? files : 'qa/specs/features' - ) + specs.tty = true + specs.tags = self.class.get_tags + specs.files = files.any? ? files : 'qa/specs/features' end end + + def self.tags(*tags) + @tags = tags + end + + def self.get_tags + @tags + end end end end diff --git a/qa/qa/scenario/test/integration/mattermost.rb b/qa/qa/scenario/test/integration/mattermost.rb index 0220da929ce..7d0702afdb1 100644 --- a/qa/qa/scenario/test/integration/mattermost.rb +++ b/qa/qa/scenario/test/integration/mattermost.rb @@ -10,7 +10,8 @@ module QA tags :core, :mattermost def perform(address, mattermost, *files) - Runtime::Scenario.mattermost = mattermost + Runtime::Scenario.define(:mattermost_address, mattermost) + super(address, *files) end end diff --git a/qa/qa/specs/config.rb b/qa/qa/specs/config.rb index 79c681168cc..591ddde8ab9 100644 --- a/qa/qa/specs/config.rb +++ b/qa/qa/specs/config.rb @@ -9,15 +9,7 @@ require 'selenium-webdriver' module QA module Specs class Config < Scenario::Template - attr_writer :address - - def initialize - @address = ENV['GITLAB_URL'] - end - def perform - raise 'Please configure GitLab address!' unless @address - configure_rspec! configure_capybara! end @@ -56,7 +48,6 @@ module QA end Capybara.configure do |config| - config.app_host = @address config.default_driver = :chrome config.javascript_driver = :chrome config.default_max_wait_time = 4 diff --git a/qa/qa/specs/features/login/standard_spec.rb b/qa/qa/specs/features/login/standard_spec.rb index ba19ce17ee5..b155708c387 100644 --- a/qa/qa/specs/features/login/standard_spec.rb +++ b/qa/qa/specs/features/login/standard_spec.rb @@ -1,7 +1,8 @@ module QA feature 'standard root login', :core do scenario 'user logs in using credentials' do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } # TODO, since `Signed in successfully` message was removed # this is the only way to tell if user is signed in correctly. diff --git a/qa/qa/specs/features/mattermost/group_create_spec.rb b/qa/qa/specs/features/mattermost/group_create_spec.rb index c4afd83c8e4..853a9a6a4f4 100644 --- a/qa/qa/specs/features/mattermost/group_create_spec.rb +++ b/qa/qa/specs/features/mattermost/group_create_spec.rb @@ -1,7 +1,8 @@ module QA feature 'create a new group', :mattermost do scenario 'creating a group with a mattermost team' do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } Page::Main::Menu.act { go_to_groups } Page::Dashboard::Groups.perform do |page| diff --git a/qa/qa/specs/features/mattermost/login_spec.rb b/qa/qa/specs/features/mattermost/login_spec.rb index a89a6a3d1cf..92f91cb2725 100644 --- a/qa/qa/specs/features/mattermost/login_spec.rb +++ b/qa/qa/specs/features/mattermost/login_spec.rb @@ -1,7 +1,8 @@ module QA feature 'logging in to Mattermost', :mattermost do scenario 'can use gitlab oauth' do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } Page::Mattermost::Login.act { sign_in_using_oauth } Page::Mattermost::Main.perform do |page| diff --git a/qa/qa/specs/features/project/create_spec.rb b/qa/qa/specs/features/project/create_spec.rb index 27eb22f15a6..aba0c2b4c14 100644 --- a/qa/qa/specs/features/project/create_spec.rb +++ b/qa/qa/specs/features/project/create_spec.rb @@ -1,7 +1,8 @@ module QA feature 'create a new project', :core do scenario 'user creates a new project' do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } Scenario::Gitlab::Project::Create.perform do |project| project.name = 'awesome-project' diff --git a/qa/qa/specs/features/repository/clone_spec.rb b/qa/qa/specs/features/repository/clone_spec.rb index 3571173783d..5cc3b3b9c1b 100644 --- a/qa/qa/specs/features/repository/clone_spec.rb +++ b/qa/qa/specs/features/repository/clone_spec.rb @@ -9,7 +9,8 @@ module QA end before do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } Scenario::Gitlab::Project::Create.perform do |scenario| scenario.name = 'project-with-code' diff --git a/qa/qa/specs/features/repository/push_spec.rb b/qa/qa/specs/features/repository/push_spec.rb index 0e691fb0d75..30935dc1e13 100644 --- a/qa/qa/specs/features/repository/push_spec.rb +++ b/qa/qa/specs/features/repository/push_spec.rb @@ -2,7 +2,8 @@ module QA feature 'push code to repository', :core do context 'with regular account over http' do scenario 'user pushes code to the repository' do - Page::Main::Entry.act { sign_in_using_credentials } + Page::Main::Entry.act { visit_login_page } + Page::Main::Login.act { sign_in_using_credentials } Scenario::Gitlab::Project::Create.perform do |scenario| scenario.name = 'project_with_code' diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb index 2aa18d5d3a1..f98b8f88e9a 100644 --- a/qa/qa/specs/runner.rb +++ b/qa/qa/specs/runner.rb @@ -2,16 +2,22 @@ require 'rspec/core' module QA module Specs - class Runner - include Scenario::Actable + class Runner < Scenario::Template + attr_accessor :tty, :tags, :files - def rspec(tty: false, tags: [], files: ['qa/specs/features']) + def initialize + @tty = false + @tags = [] + @files = ['qa/specs/features'] + end + + def perform args = [] - args << '--tty' if tty - tags.to_a.each do |tag| - args << ['-t', tag.to_s] - end - args << files + args.push('--tty') if tty + tags.to_a.each { |tag| args.push(['-t', tag.to_s]) } + args.push(files) + + Specs::Config.perform RSpec::Core::Runner.run(args.flatten, $stderr, $stdout).tap do |status| abort if status.nonzero? diff --git a/qa/spec/runtime/scenario_spec.rb b/qa/spec/runtime/scenario_spec.rb new file mode 100644 index 00000000000..7009192bcc0 --- /dev/null +++ b/qa/spec/runtime/scenario_spec.rb @@ -0,0 +1,27 @@ +describe QA::Runtime::Scenario do + subject do + Module.new.extend(described_class) + end + + it 'makes it possible to define global scenario attributes' do + subject.define(:my_attribute, 'some-value') + subject.define(:another_attribute, 'another-value') + + expect(subject.my_attribute).to eq 'some-value' + expect(subject.another_attribute).to eq 'another-value' + expect(subject.attributes) + .to eq(my_attribute: 'some-value', another_attribute: 'another-value') + end + + it 'raises error when attribute is not known' do + expect { subject.invalid_accessor } + .to raise_error ArgumentError, /invalid_accessor/ + end + + it 'raises error when attribute is empty' do + subject.define(:empty_attribute, '') + + expect { subject.empty_attribute } + .to raise_error ArgumentError, /empty_attribute/ + end +end diff --git a/qa/spec/scenario/bootable_spec.rb b/qa/spec/scenario/bootable_spec.rb new file mode 100644 index 00000000000..273aac7677e --- /dev/null +++ b/qa/spec/scenario/bootable_spec.rb @@ -0,0 +1,24 @@ +describe QA::Scenario::Bootable do + subject do + Class.new(QA::Scenario::Template) + .include(described_class) + end + + it 'makes it possible to define the scenario attribute' do + subject.class_eval do + attribute :something, '--something SOMETHING', 'Some attribute' + attribute :another, '--another ANOTHER', 'Some other attribute' + end + + expect(subject).to receive(:perform) + .with(something: 'test', another: 'other') + + subject.launch!(%w[--another other --something test]) + end + + it 'does not require attributes to be defined' do + expect(subject).to receive(:perform).with('some', 'argv') + + subject.launch!(%w[some argv]) + end +end diff --git a/qa/spec/scenario/entrypoint_spec.rb b/qa/spec/scenario/entrypoint_spec.rb index 3fd068b641c..aec79dcea04 100644 --- a/qa/spec/scenario/entrypoint_spec.rb +++ b/qa/spec/scenario/entrypoint_spec.rb @@ -6,31 +6,30 @@ describe QA::Scenario::Entrypoint do end context '#perform' do - let(:config) { spy('Specs::Config') } + let(:arguments) { spy('Runtime::Scenario') } let(:release) { spy('Runtime::Release') } let(:runner) { spy('Specs::Runner') } before do - allow(config).to receive(:perform) { |&block| block.call config } - allow(runner).to receive(:perform) { |&block| block.call runner } - - stub_const('QA::Specs::Config', config) stub_const('QA::Runtime::Release', release) + stub_const('QA::Runtime::Scenario', arguments) stub_const('QA::Specs::Runner', runner) + + allow(runner).to receive(:perform).and_yield(runner) end - it 'should set address' do + it 'sets an address of the subject' do subject.perform("hello") - expect(config).to have_received(:address=).with("hello") + expect(arguments).to have_received(:define) + .with(:gitlab_address, "hello") end context 'no paths' do it 'should call runner with default arguments' do subject.perform("test") - expect(runner).to have_received(:rspec) - .with(hash_including(files: 'qa/specs/features')) + expect(runner).to have_received(:files=).with('qa/specs/features') end end @@ -38,8 +37,7 @@ describe QA::Scenario::Entrypoint do it 'should call runner with paths' do subject.perform('test', 'path1', 'path2') - expect(runner).to have_received(:rspec) - .with(hash_including(files: %w(path1 path2))) + expect(runner).to have_received(:files=).with(%w[path1 path2]) end end end |