Commit 7fca5980 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'qa_78' into 'master'

QA specs for merge request rebasing and squashing

Closes gitlab-qa#78

See merge request gitlab-org/gitlab-ee!4288
parents 440fc56b 784ecdee
...@@ -231,7 +231,8 @@ export default { ...@@ -231,7 +231,8 @@ export default {
@click="handleMergeButtonClick()" @click="handleMergeButtonClick()"
:disabled="isMergeButtonDisabled" :disabled="isMergeButtonDisabled"
:class="mergeButtonClass" :class="mergeButtonClass"
type="button"> type="button"
class="qa-merge-button">
<i <i
v-if="isMakingRequest" v-if="isMakingRequest"
class="fa fa-spinner fa-spin" class="fa fa-spinner fa-spin"
......
...@@ -111,7 +111,7 @@ js-toggle-container accept-action media space-children" ...@@ -111,7 +111,7 @@ js-toggle-container accept-action media space-children"
> >
<button <button
type="button" type="button"
class="btn btn-sm btn-reopen btn-success" class="btn btn-sm btn-reopen btn-success qa-mr-rebase-button"
:disabled="isMakingRequest" :disabled="isMakingRequest"
@click="rebase" @click="rebase"
> >
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
.radio .radio
= label_tag :project_merge_method_ff do = label_tag :project_merge_method_ff do
= form.radio_button :merge_method, :ff, class: "js-merge-method-radio" = form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff"
%strong Fast-forward merge %strong Fast-forward merge
%br %br
%span.descr %span.descr
......
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f| = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f|
= render 'projects/ee/merge_request_settings', form: f = render 'projects/ee/merge_request_settings', form: f
= f.submit 'Save changes', class: "btn btn-save" = f.submit 'Save changes', class: "btn btn-save qa-save-merge-request-changes"
= render 'projects/ee/service_desk_settings' = render 'projects/ee/service_desk_settings'
......
...@@ -29,6 +29,7 @@ export default { ...@@ -29,6 +29,7 @@ export default {
<input <input
type="checkbox" type="checkbox"
name="squash" name="squash"
class="qa-squash-checkbox"
:disabled="isMergeButtonDisabled" :disabled="isMergeButtonDisabled"
v-model="squashBeforeMerge" v-model="squashBeforeMerge"
@change="updateSquashModel"/> @change="updateSquashModel"/>
......
...@@ -130,6 +130,7 @@ module QA ...@@ -130,6 +130,7 @@ module QA
autoload :DeployKeys, 'qa/page/project/settings/deploy_keys' autoload :DeployKeys, 'qa/page/project/settings/deploy_keys'
autoload :SecretVariables, 'qa/page/project/settings/secret_variables' autoload :SecretVariables, 'qa/page/project/settings/secret_variables'
autoload :Runners, 'qa/page/project/settings/runners' autoload :Runners, 'qa/page/project/settings/runners'
autoload :MergeRequest, 'qa/page/project/settings/merge_request'
end end
module Issue module Issue
...@@ -145,6 +146,7 @@ module QA ...@@ -145,6 +146,7 @@ module QA
module MergeRequest module MergeRequest
autoload :New, 'qa/page/merge_request/new' autoload :New, 'qa/page/merge_request/new'
autoload :Show, 'qa/page/merge_request/show'
end end
module Admin module Admin
......
...@@ -18,6 +18,10 @@ module QA ...@@ -18,6 +18,10 @@ module QA
end end
end end
end end
module MergeRequest
autoload :Show, 'qa/ee/page/merge_request/show'
end
end end
module Factory module Factory
......
module QA
module EE
module Page
module MergeRequest
module Show
def self.prepended(page)
page.module_eval do
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js' do
element :head_mismatch, "The source branch HEAD has recently changed."
end
view 'ee/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js' do
element :squash_checkbox
end
end
end
def mark_to_squash
wait(reload: true) do
has_css?(element_selector_css(:squash_checkbox))
end
click_element :squash_checkbox
end
end
end
end
end
end
...@@ -22,7 +22,7 @@ module QA ...@@ -22,7 +22,7 @@ module QA
factory.fabricate!(*args) factory.fabricate!(*args)
return Factory::Product.populate!(self) return Factory::Product.populate!(factory)
end end
end end
......
...@@ -17,8 +17,9 @@ module QA ...@@ -17,8 +17,9 @@ module QA
def self.populate!(factory) def self.populate!(factory)
new.tap do |product| new.tap do |product|
factory.attributes.each_value do |attribute| factory.class.attributes.each_value do |attribute|
product.instance_exec(&attribute.block).tap do |value| product.instance_exec(factory, attribute.block) do |factory, block|
value = block.call(factory)
product.define_singleton_method(attribute.name) { value } product.define_singleton_method(attribute.name) { value }
end end
end end
......
...@@ -2,7 +2,7 @@ module QA ...@@ -2,7 +2,7 @@ module QA
module Factory module Factory
module Repository module Repository
class Push < Factory::Base class Push < Factory::Base
attr_writer :file_name, :file_content, :commit_message, :branch_name attr_writer :file_name, :file_content, :commit_message, :branch_name, :new_branch
dependency Factory::Resource::Project, as: :project do |project| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-code' project.name = 'project-with-code'
...@@ -14,6 +14,7 @@ module QA ...@@ -14,6 +14,7 @@ module QA
@file_content = '# This is test project' @file_content = '# This is test project'
@commit_message = "Add #{@file_name}" @commit_message = "Add #{@file_name}"
@branch_name = 'master' @branch_name = 'master'
@new_branch = true
end end
def fabricate! def fabricate!
...@@ -29,6 +30,7 @@ module QA ...@@ -29,6 +30,7 @@ module QA
repository.clone repository.clone
repository.configure_identity('GitLab QA', 'root@gitlab.com') repository.configure_identity('GitLab QA', 'root@gitlab.com')
repository.checkout(@branch_name) unless @new_branch
repository.add_file(@file_name, @file_content) repository.add_file(@file_name, @file_content)
repository.commit(@commit_message) repository.commit(@commit_message)
repository.push_changes(@branch_name) repository.push_changes(@branch_name)
......
...@@ -9,11 +9,20 @@ module QA ...@@ -9,11 +9,20 @@ module QA
:source_branch, :source_branch,
:target_branch :target_branch
product :project do |factory|
factory.project
end
product :source_branch do |factory|
factory.source_branch
end
dependency Factory::Resource::Project, as: :project do |project| dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-merge-request' project.name = 'project-with-merge-request'
end end
dependency Factory::Repository::Push, as: :target do |push, factory| dependency Factory::Repository::Push, as: :target do |push, factory|
factory.project.visit!
push.project = factory.project push.project = factory.project
push.branch_name = "master:#{factory.target_branch}" push.branch_name = "master:#{factory.target_branch}"
end end
......
...@@ -36,6 +36,10 @@ module QA ...@@ -36,6 +36,10 @@ module QA
`git clone #{opts} #{@uri.to_s} ./ #{suppress_output}` `git clone #{opts} #{@uri.to_s} ./ #{suppress_output}`
end end
def checkout(branch_name)
`git checkout "#{branch_name}"`
end
def shallow_clone def shallow_clone
clone('--depth 1') clone('--depth 1')
end end
......
module QA
module Page
module MergeRequest
class Show < Page::Base
prepend QA::EE::Page::MergeRequest::Show
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js' do
element :merge_button
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
element :merged_status, 'The changes were merged into'
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
element :mr_rebase_button
element :fast_forward_nessage, "Fast-forward merge is not possible"
end
def rebase!
wait(reload: false) do
click_element :mr_rebase_button
has_text?("The source branch HEAD has recently changed.")
end
end
def fast_forward_possible?
!has_text?("Fast-forward merge is not possible")
end
def has_merge_button?
refresh
has_selector?('.accept-merge-request')
end
def merge!
wait(reload: false) do
click_element :merge_button
has_text?("The changes were merged into")
end
end
end
end
end
end
module QA
module Page
module Project
module Settings
class MergeRequest < QA::Page::Base
include Common
view 'app/views/projects/_merge_request_fast_forward_settings.html.haml' do
element :radio_button_merge_ff
end
view 'app/views/projects/edit.html.haml' do
element :merge_request_settings, 'Merge request settings'
element :save_merge_request_changes
end
def enable_ff_only
expand_section('Merge request settings') do
click_element :radio_button_merge_ff
click_element :save_merge_request_changes
end
end
end
end
end
end
end
module QA
feature 'merge request squash commits', :core do
scenario 'when squash commits is marked before merge' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project|
project.name = "squash-before-merge"
end
merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project
merge_request.title = 'Squashing commits'
end
Factory::Repository::Push.fabricate! do |push|
push.project = project
push.commit_message = 'to be squashed'
push.branch_name = merge_request.source_branch
push.new_branch = false
push.file_name = 'other.txt'
push.file_content = "Test with unicode characters ❤✓€❄"
end
merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request_page|
merge_request_page.mark_to_squash
merge_request_page.merge!
merge_request.project.visit!
Git::Repository.perform do |repository|
repository.location = Page::Project::Show.act do
choose_repository_clone_http
repository_location
end
repository.use_default_credentials
repository.act { clone }
expect(repository.commits.size).to eq 3
end
end
end
end
end
module QA
feature 'merge request rebase', :core do
scenario 'rebases source branch of merge request' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project|
project.name = "only-fast-forward"
end
Page::Menu::Side.act { go_to_settings }
Page::Project::Settings::MergeRequest.act { enable_ff_only }
merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project
merge_request.title = 'Needs rebasing'
end
Factory::Repository::Push.fabricate! do |push|
push.project = project
push.file_name = "other.txt"
push.file_content = "New file added!"
end
merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_content('Needs rebasing')
expect(merge_request).not_to be_fast_forward_possible
expect(merge_request).not_to have_merge_button
merge_request.rebase!
expect(merge_request).to have_merge_button
expect(merge_request.fast_forward_possible?).to be_truthy
end
end
end
end
...@@ -7,6 +7,7 @@ describe QA::Factory::Base do ...@@ -7,6 +7,7 @@ describe QA::Factory::Base do
before do before do
allow(QA::Factory::Product).to receive(:new).and_return(product) allow(QA::Factory::Product).to receive(:new).and_return(product)
allow(QA::Factory::Product).to receive(:populate!).and_return(product)
end end
it 'instantiates the factory and calls factory method' do it 'instantiates the factory and calls factory method' do
...@@ -76,6 +77,7 @@ describe QA::Factory::Base do ...@@ -76,6 +77,7 @@ describe QA::Factory::Base do
allow(subject).to receive(:new).and_return(instance) allow(subject).to receive(:new).and_return(instance)
allow(instance).to receive(:mydep).and_return(nil) allow(instance).to receive(:mydep).and_return(nil)
allow(QA::Factory::Product).to receive(:new) allow(QA::Factory::Product).to receive(:new)
allow(QA::Factory::Product).to receive(:populate!)
end end
it 'builds all dependencies first' do it 'builds all dependencies first' do
...@@ -89,8 +91,16 @@ describe QA::Factory::Base do ...@@ -89,8 +91,16 @@ describe QA::Factory::Base do
describe '.product' do describe '.product' do
subject do subject do
Class.new(described_class) do Class.new(described_class) do
def fabricate!
"any"
end
# Defined only to be stubbed
def self.find_page
end
product :token do product :token do
page.do_something_on_page! find_page.do_something_on_page!
'resulting value' 'resulting value'
end end
end end
...@@ -105,16 +115,17 @@ describe QA::Factory::Base do ...@@ -105,16 +115,17 @@ describe QA::Factory::Base do
let(:page) { spy('page') } let(:page) { spy('page') }
before do before do
allow(subject).to receive(:new).and_return(factory) allow(factory).to receive(:class).and_return(subject)
allow(QA::Factory::Product).to receive(:new).and_return(product) allow(QA::Factory::Product).to receive(:new).and_return(product)
allow(product).to receive(:page).and_return(page) allow(product).to receive(:page).and_return(page)
allow(subject).to receive(:find_page).and_return(page)
end end
it 'populates product after fabrication' do it 'populates product after fabrication' do
subject.fabricate! subject.fabricate!
expect(page).to have_received(:do_something_on_page!)
expect(product.token).to eq 'resulting value' expect(product.token).to eq 'resulting value'
expect(page).to have_received(:do_something_on_page!)
end end
end end
end end
......
describe QA::Factory::Product do describe QA::Factory::Product do
let(:factory) { spy('factory') } let(:factory) do
QA::Factory::Base.new
end
let(:attributes) do
{ test: QA::Factory::Product::Attribute.new(:test, proc { 'returned' }) }
end
let(:product) { spy('product') } let(:product) { spy('product') }
before do
allow(QA::Factory::Base).to receive(:attributes).and_return(attributes)
end
describe '.populate!' do describe '.populate!' do
it 'returns a fabrication product' do it 'returns a fabrication product and define factory attributes as its methods' do
expect(described_class).to receive(:new).and_return(product) expect(described_class).to receive(:new).and_return(product)
result = described_class.populate!(factory) do |instance| result = described_class.populate!(factory) do |instance|
...@@ -11,6 +22,7 @@ describe QA::Factory::Product do ...@@ -11,6 +22,7 @@ describe QA::Factory::Product do
end end
expect(result).to be product expect(result).to be product
expect(result.test).to eq('returned')
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment