Commit 5d4f377b authored by Stan Hu's avatar Stan Hu

Merge branch 'sh-headless-chrome-support' into 'master'

Replace PhantomJS with Headless Chrome for GitLab Integration Tests

Closes #30876

See merge request gitlab-org/gitlab-ce!12244
parents ae470ae2 cc00b289
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.5-golang-1.8-git-2.13-phantomjs-2.1-node-8.x-yarn-1.0-postgresql-9.6"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.5-golang-1.8-git-2.13-chrome-62.0-node-8.x-yarn-1.2-postgresql-9.6"
.default-cache: &default-cache
key: "ruby-235-with-yarn"
......@@ -23,7 +23,6 @@ variables:
SIMPLECOV: "true"
GIT_DEPTH: "20"
GIT_SUBMODULE_STRATEGY: "none"
PHANTOMJS_VERSION: "2.1.1"
GET_SOURCES_ATTEMPTS: "3"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json
KNAPSACK_SPINACH_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/spinach_report-master.json
......@@ -551,7 +550,6 @@ karma:
<<: *dedicated-runner
<<: *except-docs
<<: *pull-cache
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.5-golang-1.8-git-2.13-chrome-61.0-node-8.x-yarn-1.0-postgresql-9.6"
stage: test
variables:
BABEL_ENV: "coverage"
......
......@@ -324,9 +324,9 @@ group :development, :test do
# Generate Fake data
gem 'ffaker', '~> 2.4'
gem 'capybara', '~> 2.15.0'
gem 'capybara', '~> 2.15'
gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.9.0'
gem 'selenium-webdriver', '~> 3.5'
gem 'spring', '~> 2.0.0'
gem 'spring-commands-rspec', '~> 1.0.4'
......
......@@ -113,12 +113,13 @@ GEM
mime-types (>= 1.16)
cause (0.1)
charlock_holmes (0.7.5)
childprocess (0.7.0)
ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2)
chronic_duration (0.10.6)
numerizer (~> 0.1.1)
chunky_png (1.3.5)
citrus (3.0.2)
cliver (0.3.2)
coderay (1.1.1)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
......@@ -604,11 +605,6 @@ GEM
pg (0.18.4)
po_to_json (1.0.1)
json (>= 1.6.0)
poltergeist (1.9.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
posix-spawn (0.3.13)
powerpack (0.1.1)
premailer (1.10.4)
......@@ -818,6 +814,9 @@ GEM
activesupport (>= 3.1)
select2-rails (3.5.9.3)
thor (~> 0.14)
selenium-webdriver (3.5.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
sentry-raven (2.5.3)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
......@@ -949,9 +948,6 @@ GEM
hashdiff
webpack-rails (0.9.10)
railties (>= 3.2.0)
websocket-driver (0.6.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
wikicloth (0.8.1)
builder
expression_parser
......@@ -988,7 +984,7 @@ DEPENDENCIES
browser (~> 2.2)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
capybara (~> 2.15.0)
capybara (~> 2.15)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 1.2)
charlock_holmes (~> 0.7.5)
......@@ -1104,7 +1100,6 @@ DEPENDENCIES
peek-redis (~> 1.2.0)
peek-sidekiq (~> 1.0.3)
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.7.0.beta18)
pry-byebug (~> 3.4.1)
......@@ -1150,6 +1145,7 @@ DEPENDENCIES
scss_lint (~> 0.54.0)
seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9)
selenium-webdriver (~> 3.5)
sentry-raven (~> 2.5.3)
settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6)
......
......@@ -79,8 +79,6 @@ const Filter = {
this.hook.trigger.addEventListener('keydown.dl', this.eventWrapper.debounceKeydown);
this.hook.trigger.addEventListener('mousedown.dl', this.eventWrapper.debounceKeydown);
this.debounceKeydown({ detail: { hook: this.hook } });
},
destroy: function destroy() {
......
import 'core-js/es6/map';
import 'core-js/es6/set';
import simulateDrag from './simulate_drag';
import simulateInput from './simulate_input';
// Export to global space for rspec to use
window.simulateDrag = simulateDrag;
window.simulateInput = simulateInput;
function triggerEvents(input) {
input.dispatchEvent(new Event('keydown'));
input.dispatchEvent(new Event('keypress'));
input.dispatchEvent(new Event('input'));
input.dispatchEvent(new Event('keyup'));
}
export default function simulateInput(target, text) {
const input = document.querySelector(target);
if (!input || !input.matches('textarea, input')) {
return false;
}
if (text.length > 0) {
Array.prototype.forEach.call(text, (char) => {
input.value += char;
triggerEvents(input);
});
} else {
triggerEvents(input);
}
return true;
}
......@@ -484,10 +484,7 @@
height: calc(100vh - #{$header-height});
@media (min-width: $screen-sm-min) {
height: 475px; // Needed for PhantomJS
// scss-lint:disable DuplicateProperty
height: calc(100vh - 180px);
// scss-lint:enable DuplicateProperty
}
}
......
......@@ -268,12 +268,6 @@
.filtered-search-box-input-container {
flex: 1;
position: relative;
// Fix PhantomJS not supporting `flex: 1;` properly.
// This is important because it can change the expected `e.target` when clicking things in tests.
// See https://gitlab.com/gitlab-org/gitlab-ce/blob/b54acba8b732688c59fe2f38510c469dc86ee499/spec/features/issues/filtered_search/visual_tokens_spec.rb#L61
// - With `width: 100%`: `e.target` = `.tokens-container`, https://i.imgur.com/jGq7wbx.png
// - Without `width: 100%`: `e.target` = `.filtered-search`, https://i.imgur.com/cNI2CyT.png
width: 100%;
min-width: 0;
}
......
......@@ -86,10 +86,7 @@
}
@media (min-width: $screen-md-min) {
height: 475px; // Needed for PhantomJS
// scss-lint:disable DuplicateProperty
height: calc(100vh - 160px);
// scss-lint:enable DuplicateProperty
min-height: 475px;
}
}
......
......@@ -485,8 +485,6 @@ ul.notes {
flex-shrink: 0;
display: inline-flex;
align-items: center;
// For PhantomJS that does not support flex
float: right;
margin-left: 10px;
color: $gray-darkest;
......@@ -497,7 +495,6 @@ ul.notes {
}
.more-actions {
float: right; // phantomjs fallback
display: flex;
align-items: flex-end;
......
......@@ -4,11 +4,6 @@
-ms-transition: none !important;
-webkit-transition: none !important;
transition: none !important;
-o-transform: none !important;
-moz-transform: none !important;
-ms-transform: none !important;
-webkit-transform: none !important;
transform: none !important;
-webkit-animation: none !important;
-moz-animation: none !important;
-o-animation: none !important;
......
Rails.application.configure do
# Make sure the middleware is inserted first in middleware chain
config.middleware.insert_before('ActionDispatch::Static', 'Gitlab::Testing::RequestBlockerMiddleware')
config.middleware.insert_before('ActionDispatch::Static', 'Gitlab::Testing::RequestInspectorMiddleware')
# Settings specified here will take precedence over those in config/application.rb
......
......@@ -11,7 +11,7 @@ class Spinach::Features::ProfileNotifications < Spinach::FeatureSteps
end
step 'I select Mention setting from dropdown' do
first(:link, "On mention").trigger('click')
first(:link, "On mention").click
end
step 'I should see Notification saved message' do
......
......@@ -40,6 +40,7 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps
step 'I submit new branch form with invalid name' do
fill_in 'branch_name', with: '1.0 stable'
page.find("body").click # defocus the branch_name input
select_branch('master')
click_button 'Create branch'
end
......@@ -70,17 +71,16 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps
step "I click branch 'improve/awesome' delete link" do
page.within '.js-branch-improve\/awesome' do
find('.btn-remove').click
sleep 0.05
accept_alert { find('.btn-remove').click }
end
end
step "I should not see branch 'improve/awesome'" do
expect(page.all(visible: true)).not_to have_content 'improve/awesome'
expect(page).to have_css('.js-branch-improve\\/awesome', visible: :hidden)
end
def select_branch(branch_name)
click_button 'master'
find('.git-revision-dropdown-toggle').click
page.within '#new-branch-form .dropdown-menu' do
click_link branch_name
......
......@@ -16,7 +16,7 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps
step 'I delete all labels' do
page.within '.labels' do
page.all('.remove-row').each do
first('.remove-row').click
accept_confirm { first('.remove-row').click }
end
end
end
......
......@@ -3,6 +3,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps
include SharedProject
include SharedPaths
include SharedMarkdown
include CapybaraHelpers
step 'I should see milestone "v2.2"' do
milestone = @project.milestones.find_by(title: "v2.2")
......@@ -65,7 +66,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps
end
step 'I click link to remove milestone' do
click_link 'Delete'
confirm_modal_if_present { click_link 'Delete' }
end
step 'I should see no milestones' do
......
......@@ -215,7 +215,7 @@ module SharedDiffNote
end
step 'I click side-by-side diff button' do
find('#parallel-diff-btn').trigger('click')
find('#parallel-diff-btn').click
end
step 'I see side-by-side diff button' do
......@@ -227,12 +227,11 @@ module SharedDiffNote
end
def click_diff_line(code)
find(".line_holder[id='#{code}'] td:nth-of-type(1)").trigger 'mouseover'
find(".line_holder[id='#{code}'] button").trigger 'click'
find(".line_holder[id='#{code}'] button").click
end
def click_parallel_diff_line(code, line_type)
find(".line_holder.parallel td[id='#{code}']").find(:xpath, 'preceding-sibling::*[1][self::td]').trigger 'mouseover'
find(".line_holder.parallel button[data-line-code='#{code}']").trigger 'click'
find(".line_holder.parallel td[id='#{code}']").find(:xpath, 'preceding-sibling::*[1][self::td]').hover
find(".line_holder.parallel button[data-line-code='#{code}']").click
end
end
......@@ -14,7 +14,7 @@ module SharedNote
find('.more-actions').click
find('.more-actions .dropdown-menu li', match: :first)
find(".js-note-delete").click
accept_confirm { find(".js-note-delete").click }
end
end
......
require 'capybara/poltergeist'
require 'capybara-screenshot/spinach'
# Give CI some extra time
timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 60 : 30
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(
app,
js_errors: true,
timeout: timeout,
window_size: [1366, 768],
url_whitelist: %w[localhost 127.0.0.1],
url_blacklist: %w[.mp4 .png .gif .avi .bmp .jpg .jpeg],
phantomjs_options: [
'--load-images=yes'
]
Capybara.javascript_driver = :chrome
Capybara.register_driver :chrome do |app|
extra_args = []
extra_args << 'headless' unless ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: {
'args' => %w[no-sandbox disable-gpu --window-size=1240,1400] + extra_args
}
)
Capybara::Selenium::Driver
.new(app, browser: :chrome, desired_capabilities: capabilities)
end
Capybara.default_max_wait_time = timeout
......@@ -24,6 +23,10 @@ Capybara.ignore_hidden_elements = false
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
# From https://github.com/mattheworiordan/capybara-screenshot/issues/84#issuecomment-41219326
Capybara::Screenshot.register_driver(:chrome) do |driver, path|
driver.browser.save_screenshot(path)
end
Spinach.hooks.before_run do
TestEnv.eager_load_driver_server
......
module CapybaraHelpers
def confirm_modal_if_present
if Capybara.current_driver == Capybara.javascript_driver
accept_confirm { yield }
return
end
yield
end
end
......@@ -7,6 +7,7 @@ module Gitlab
class RequestBlockerMiddleware
@@num_active_requests = Concurrent::AtomicFixnum.new(0)
@@block_requests = Concurrent::AtomicBoolean.new(false)
@@slow_requests = Concurrent::AtomicBoolean.new(false)
# Returns the number of requests the server is currently processing.
def self.num_active_requests
......@@ -19,9 +20,15 @@ module Gitlab
@@block_requests.value = true
end
# Slows down incoming requests (useful for race conditions).
def self.slow_requests!
@@slow_requests.value = true
end
# Allows the server to accept requests again.
def self.allow_requests!
@@block_requests.value = false
@@slow_requests.value = false
end
def initialize(app)
......@@ -33,6 +40,7 @@ module Gitlab
if block_requests?
block_request(env)
else
sleep 0.2 if slow_requests?
@app.call(env)
end
ensure
......@@ -45,6 +53,10 @@ module Gitlab
@@block_requests.true?
end
def slow_requests?
@@slow_requests.true?
end
def block_request(env)
[503, {}, []]
end
......
# rubocop:disable Style/ClassVars
module Gitlab
module Testing
class RequestInspectorMiddleware
@@log_requests = Concurrent::AtomicBoolean.new(false)
@@logged_requests = Concurrent::Array.new
@@inject_headers = Concurrent::Hash.new
# Resets the current request log and starts logging requests
def self.log_requests!(headers = {})
@@inject_headers.replace(headers)
@@logged_requests.replace([])
@@log_requests.value = true
end
# Stops logging requests
def self.stop_logging!
@@log_requests.value = false
end
def self.requests
@@logged_requests
end
def initialize(app)
@app = app
end
def call(env)
return @app.call(env) unless @@log_requests.true?
url = env['REQUEST_URI']
env.merge! http_headers_env(@@inject_headers) if @@inject_headers.any?
request_headers = env_http_headers(env)
status, headers, body = @app.call(env)
request = OpenStruct.new(
url: url,
status_code: status,
request_headers: request_headers,
response_headers: headers
)
log_request request
[status, headers, body]
end
private
def env_http_headers(env)
Hash[*env.select { |k, v| k.start_with? 'HTTP_' }
.collect { |k, v| [k.sub(/^HTTP_/, ''), v] }
.collect { |k, v| [k.split('_').collect(&:capitalize).join('-'), v] }
.sort
.flatten]
end
def http_headers_env(headers)
Hash[*headers
.collect { |k, v| [k.split('-').collect(&:upcase).join('_'), v] }
.collect { |k, v| [k.prepend('HTTP_'), v] }
.flatten]
end
def log_request(response)
@@logged_requests.push(response)
end
end
end
end
......@@ -7,7 +7,7 @@ feature 'Admin disables 2FA for a user' do
edit_user(user)
page.within('.two-factor-status') do
click_link 'Disable'
accept_confirm { click_link 'Disable' }
end
page.within('.two-factor-status') do
......
......@@ -152,7 +152,7 @@ feature 'Admin Groups' do
expect(page).to have_content('Developer')
end
find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click
accept_confirm { find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click }
visit group_group_members_path(group)
......
......@@ -62,14 +62,14 @@ describe 'Admin::Hooks', :js do
it 'from hooks list page' do
visit admin_hooks_path
expect { click_link 'Remove' }.to change(SystemHook, :count).by(-1)
expect { accept_confirm { find(:link, 'Remove').send_keys(:return) } }.to change(SystemHook, :count).by(-1)
end
it 'from hook edit page' do
visit admin_hooks_path
click_link 'Edit'
expect { click_link 'Remove' }.to change(SystemHook, :count).by(-1)
expect { accept_confirm { find(:link, 'Remove').send_keys(:return) } }.to change(SystemHook, :count).by(-1)
end
end
end
......
......@@ -33,7 +33,7 @@ RSpec.describe 'admin issues labels' do
it 'deletes all labels', :js do
page.within '.labels' do
page.all('.btn-remove').each do |remove|
remove.click
accept_confirm { remove.click }
wait_for_requests
end
end
......
......@@ -73,7 +73,7 @@ feature 'Admin updates settings' do
context 'sign-in restrictions', :js do
it 'de-activates oauth sign-in source' do
find('.btn', text: 'GitLab.com').click
find('input#application_setting_enabled_oauth_sign_in_sources_[value=gitlab]').send_keys(:return)
expect(find('.btn', text: 'GitLab.com')).not_to have_css('.active')
end
......
......@@ -24,7 +24,7 @@ describe 'Admin > Users > Impersonation Tokens', :js do
fill_in "Name", with: name
# Set date to 1st of next month
find_field("Expires at").trigger('focus')
find_field("Expires at").click
find(".pika-next").click
click_on "1"
......@@ -60,7 +60,7 @@ describe 'Admin > Users > Impersonation Tokens', :js do
it "allows revocation of an active impersonation token" do
visit admin_user_impersonation_tokens_path(user_id: user.username)
click_on "Revoke"
accept_confirm { click_on "Revoke" }
expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.")
......
......@@ -290,7 +290,7 @@ describe "Admin::Users" do
it 'allows group membership to be revoked', :js do
page.within(first('.group_member')) do
find('.btn-remove').click
accept_confirm { find('.btn-remove').click }
end
wait_for_requests
......@@ -319,7 +319,7 @@ describe "Admin::Users" do
expect(page).to have_content("Secondary email: #{secondary_email.email}")
find("#remove_email_#{secondary_email.id}").click
accept_confirm { find("#remove_email_#{secondary_email.id}").click }
expect(page).not_to have_content(secondary_email.email)
end
......
......@@ -37,7 +37,7 @@ feature 'Admin uses repository checks' do
expect(RepositoryCheck::ClearWorker).to receive(:perform_async)
click_link 'Clear all repository checks'
accept_confirm { find(:link, 'Clear all repository checks').send_keys(:return) }
expect(page).to have_content('Started asynchronous removal of all repository check states.')
end
......
......@@ -101,7 +101,7 @@ describe 'Issue Boards add issue modal', :js do
click_button 'Cancel'
end
first('.board-delete').click
accept_confirm { first('.board-delete').click }
click_button('Add issues')
......
......@@ -2,6 +2,7 @@ require 'rails_helper'
describe 'Issue Boards', :js do
include DragTo
include MobileHelpers
let(:group) { create(:group, :nested) }
let(:project) { create(:project, :public, namespace: group) }
......@@ -13,7 +14,7 @@ describe 'Issue Boards', :js do
project.team << [user, :master]
project.team << [user2, :master]
page.driver.set_cookie('sidebar_collapsed', 'true')
set_cookie('sidebar_collapsed', 'true')
sign_in(user)
end
......@@ -135,7 +136,7 @@ describe 'Issue Boards', :js do
it 'allows user to delete board' do
page.within(find('.board:nth-child(2)')) do
find('.board-delete').click
accept_confirm { find('.board-delete').click }
end
wait_for_requests
......@@ -150,7 +151,7 @@ describe 'Issue Boards', :js do
find('.dropdown-menu-close').click
page.within(find('.board:nth-child(2)')) do
find('.board-delete').click
accept_confirm { find('.board-delete').click }
end
wait_for_requests
......@@ -379,7 +380,7 @@ describe 'Issue Boards', :js do
end
it 'filters by milestone' do
set_filter("milestone", "\"#{milestone.title}\"")
set_filter("milestone", "\"#{milestone.title}")
click_filter_link(milestone.title)
submit_filter
......@@ -400,7 +401,7 @@ describe 'Issue Boards', :js do
end
it 'filters by label with space after reload' do
set_filter("label", "\"#{accepting.title}\"")
set_filter("label", "\"#{accepting.title}")
click_filter_link(accepting.title)
submit_filter
......@@ -521,7 +522,7 @@ describe 'Issue Boards', :js do
end
it 'allows user to use keyboard shortcuts' do
find('.boards-list').native.send_keys('i')
find('body').native.send_keys('i')
expect(page).to have_content('New Issue')
end
end
......@@ -563,6 +564,9 @@ describe 'Issue Boards', :js do
end
def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0)
# ensure there is enough horizontal space for four boards
resize_window(2000, 800)
drag_to(selector: selector,
scrollable: '#board-app',
list_from_index: list_from_index,
......
......@@ -51,7 +51,7 @@ describe 'Issue Boards', :js do
expect(page).to have_selector('.issue-boards-sidebar')
find('.gutter-toggle').trigger('click')
find('.gutter-toggle').click
expect(page).not_to have_selector('.issue-boards-sidebar')
end
......@@ -171,7 +171,7 @@ describe 'Issue Boards', :js do
end
page.within(find('.board:nth-child(2)')) do
find('.card:nth-child(2)').trigger('click')
find('.card:nth-child(2)').click
end
page.within('.assignee') do
......
......@@ -63,8 +63,8 @@ feature 'Contributions Calendar', :js do
Event.create(note_comment_params)
end
def selected_day_activities
find('.user-calendar-activities').text
def selected_day_activities(visible: true)
find('.user-calendar-activities', visible: visible).text
end
before do
......@@ -112,7 +112,7 @@ feature 'Contributions Calendar', :js do
end
it 'hides calendar day activities' do
expect(selected_day_activities).to be_empty
expect(selected_day_activities(visible: false)).to be_empty
end
end
end
......
......@@ -47,7 +47,7 @@ describe "Container Registry", :js do
scenario 'user removes a specific tag from container repository' do
visit_container_registry
find('.js-toggle-repo').trigger('click')
find('.js-toggle-repo').click
wait_for_requests
expect_any_instance_of(ContainerRegistry::Tag)
......
......@@ -13,7 +13,7 @@ RSpec.describe 'Dashboard Group' do
it 'creates new group', :js do
visit dashboard_groups_path
find('.btn-new').trigger('click')
find('.btn-new').click
new_path = 'Samurai'
new_description = 'Tokugawa Shogunate'
......
......@@ -138,7 +138,7 @@ feature 'Dashboard Groups page', :js do
expect(page).not_to have_selector("#group-#{group.id}")
# Go to next page
find(".gl-pagination .page:not(.active) a").trigger('click')
find(".gl-pagination .page:not(.active) a").click
wait_for_requests
......
......@@ -33,7 +33,7 @@ RSpec.describe 'Dashboard Issues' do
end
it 'shows issues when current user is author', :js do
find('#assignee_id', visible: false).set('')
execute_script("document.querySelector('#assignee_id').value=''")
find('.js-author-search', match: :first).click
expect(find('li[data-user-id="null"] a.is-active')).to be_visible
......@@ -71,7 +71,7 @@ RSpec.describe 'Dashboard Issues' do
describe 'new issue dropdown' do
it 'shows projects only with issues feature enabled', :js do
find('.new-project-item-select-button').trigger('click')
find('.new-project-item-select-button').click
page.within('.select2-results') do
expect(page).to have_content(project.name_with_namespace)
......@@ -80,7 +80,7 @@ RSpec.describe 'Dashboard Issues' do
end
it 'shows the new issue page', :js do
find('.new-project-item-select-button').trigger('click')
find('.new-project-item-select-button').click
wait_for_requests
......@@ -93,7 +93,7 @@ RSpec.describe 'Dashboard Issues' do
find('#select2-drop-mask', visible: false)
execute_script("$('#select2-drop-mask').remove();")
find('.new-project-item-link').trigger('click')
find('.new-project-item-link').click
expect(page).to have_current_path("#{project_path}/issues/new")
......
......@@ -25,7 +25,7 @@ feature 'Dashboard Merge Requests' do
end
it 'shows projects only with merge requests feature enabled', :js do
find('.new-project-item-select-button').trigger('click')
find('.new-project-item-select-button').click
page.within('.select2-results') do
expect(page).to have_content(project.name_with_namespace)
......
......@@ -252,7 +252,7 @@ feature 'Dashboard Todos' do
describe 'mark all as done', :js do
before do
visit dashboard_todos_path
find('.js-todos-mark-all').trigger('click')
find('.js-todos-mark-all').click
end
it 'shows "All done" message!' do
......@@ -309,9 +309,9 @@ feature 'Dashboard Todos' do
end
def mark_all_and_undo
find('.js-todos-mark-all').trigger('click')
find('.js-todos-mark-all').click
wait_for_requests
find('.js-todos-undo-all').trigger('click')
find('.js-todos-undo-all').click
wait_for_requests
end
end
......
require 'spec_helper'
describe 'Discussion Comments Merge Request', :js do
describe 'Discussion Comments Commit', :js do
include RepoHelpers
let(:user) { create(:user) }
......
require 'spec_helper'
describe 'Discussion Comments Issue', :js do
describe 'Discussion Comments Snippet', :js do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:snippet) { create(:project_snippet, :private, project: project, author: user) }
......
......@@ -65,9 +65,9 @@ feature 'Top Plus Menu', :js do
visit project_path(project)
page.within '.header-content' do
find('.header-new-dropdown-toggle').trigger('click')
find('.header-new-dropdown-toggle').click
expect(page).to have_selector('.header-new.dropdown.open', count: 1)
find('.header-new-project-snippet a').trigger('click')
find('.header-new-project-snippet a').click
end
expect(page).to have_content('New Snippet')
......@@ -87,9 +87,9 @@ feature 'Top Plus Menu', :js do
visit group_path(group)
page.within '.header-content' do
find('.header-new-dropdown-toggle').trigger('click')
find('.header-new-dropdown-toggle').click
expect(page).to have_selector('.header-new.dropdown.open', count: 1)
find('.header-new-group-project a').trigger('click')
find('.header-new-group-project a').click
end
expect(page).to have_content('Project path')
......@@ -155,7 +155,7 @@ feature 'Top Plus Menu', :js do
def click_topmenuitem(item_name)
page.within '.header-content' do
find('.header-new-dropdown-toggle').trigger('click')
find('.header-new-dropdown-toggle').click
expect(page).to have_selector('.header-new.dropdown.open', count: 1)
click_link item_name
end
......
......@@ -65,7 +65,7 @@ feature 'Group' do
end
it 'updates the team URL on graph path update', :js do
out_span = find('span[data-bind-out="create_chat_team"]')
out_span = find('span[data-bind-out="create_chat_team"]', visible: false)
expect(out_span.text).to be_empty
......
......@@ -405,7 +405,7 @@ feature 'Issues > Labels bulk assignment' do
end
def update_issues
find('.update-selected-issues').trigger('click')
find('.update-selected-issues').click
wait_for_requests
end
......
......@@ -43,15 +43,16 @@ describe 'Dropdown assignee', :js do
end
it 'should show loading indicator when opened' do
slow_requests do
filtered_search.set('assignee:')
expect(page).to have_css('#js-dropdown-assignee .filter-dropdown-loading', visible: true)
end
end
it 'should hide loading indicator when loaded' do
filtered_search.set('assignee:')
expect(find(js_dropdown_assignee)).to have_css('.filter-dropdown-loading')
expect(find(js_dropdown_assignee)).not_to have_css('.filter-dropdown-loading')
end
......
......@@ -51,10 +51,12 @@ describe 'Dropdown author', :js do
end
it 'should show loading indicator when opened' do
slow_requests do
filtered_search.set('author:')
expect(page).to have_css('#js-dropdown-author .filter-dropdown-loading', visible: true)
end
end
it 'should hide loading indicator when loaded' do
send_keys_to_filtered_search('author:')
......
......@@ -70,10 +70,12 @@ describe 'Dropdown emoji', :js do
end
it 'should show loading indicator when opened' do
slow_requests do
filtered_search.set('my-reaction:')
expect(page).to have_css('#js-dropdown-my-reaction .filter-dropdown-loading', visible: true)
end
end
it 'should hide loading indicator when loaded' do
send_keys_to_filtered_search('my-reaction:')
......
......@@ -66,9 +66,11 @@ describe 'Dropdown label', :js do
end
it 'shows loading indicator when opened and hides it when loaded' do
slow_requests do
filtered_search.set('label:')
expect(find(js_dropdown_label)).to have_css('.filter-dropdown-loading')
expect(page).to have_css("#{js_dropdown_label} .filter-dropdown-loading", visible: true)
end
expect(find(js_dropdown_label)).not_to have_css('.filter-dropdown-loading')
end
......
......@@ -50,15 +50,16 @@ describe 'Dropdown milestone', :js do
end
it 'should show loading indicator when opened' do
slow_requests do
filtered_search.set('milestone:')
expect(page).to have_css('#js-dropdown-milestone .filter-dropdown-loading', visible: true)
end
end
it 'should hide loading indicator when loaded' do
filtered_search.set('milestone:')
expect(find(js_dropdown_milestone)).to have_css('.filter-dropdown-loading')
expect(find(js_dropdown_milestone)).not_to have_css('.filter-dropdown-loading')
end
......
......@@ -139,7 +139,7 @@ describe 'Filter issues', :js do
input_filtered_search('label:none')
expect_tokens([label_token('none', false)])
expect_issues_list_count(8)
expect_issues_list_count(4)
expect_filtered_search_input_empty
end
......
......@@ -76,7 +76,8 @@ describe 'Recent searches', :js do
set_recent_searches(project_1_local_storage_key, '["foo", "bar"]')
visit project_issues_path(project_1)
all('.filtered-search-history-dropdown-item', visible: false, count: 2)[0].trigger('click')
find('.filtered-search-history-dropdown-toggle-button').click
all('.filtered-search-history-dropdown-item', count: 2)[0].click
wait_for_filtered_search('foo')
expect(find('.filtered-search').value.strip).to eq('foo')
......@@ -86,10 +87,11 @@ describe 'Recent searches', :js do
set_recent_searches(project_1_local_storage_key, '["foo"]')
visit project_issues_path(project_1)
all('.filtered-search-history-dropdown-item', visible: false, count: 1)
find('.filtered-search-history-dropdown-toggle-button').click
all('.filtered-search-history-dropdown-item', count: 1)
find('.filtered-search-history-clear-button', visible: false).trigger('click')
items_after = all('.filtered-search-history-dropdown-item', visible: false, count: 0)
find('.filtered-search-history-clear-button').click
items_after = all('.filtered-search-history-dropdown-item', count: 0)
expect(items_after.count).to eq(0)
end
......
......@@ -2,7 +2,6 @@ require 'rails_helper'
describe 'Visual tokens', :js do
include FilteredSearchHelpers
include WaitForRequests
let!(:project) { create(:project) }
let!(:user) { create(:user, name: 'administrator', username: 'root') }
......@@ -28,7 +27,7 @@ describe 'Visual tokens', :js do
sign_in(user)
create(:issue, project: project)
page.driver.set_cookie('sidebar_collapsed', 'true')
set_cookie('sidebar_collapsed', 'true')
visit project_issues_path(project)
end
......
......@@ -17,9 +17,9 @@ feature 'GFM autocomplete', :js do
it 'updates issue descripton with GFM reference' do
find('.issuable-edit').click
find('#issue-description').native.send_keys("@#{user.name[0...3]}")
simulate_input('#issue-description', "@#{user.name[0...3]}")
find('.atwho-view .cur').trigger('click')
find('.atwho-view .cur').click
click_button 'Save changes'
......@@ -28,7 +28,6 @@ feature 'GFM autocomplete', :js do
it 'opens autocomplete menu when field starts with text' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('')
find('#note-body').native.send_keys('@')
end
......@@ -46,7 +45,6 @@ feature 'GFM autocomplete', :js do
it 'doesnt select the first item for non-assignee dropdowns' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('')
find('#note-body').native.send_keys(':')
end
......@@ -86,7 +84,6 @@ feature 'GFM autocomplete', :js do
it 'selects the first item for assignee dropdowns' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('')
find('#note-body').native.send_keys('@')
end
......@@ -100,7 +97,7 @@ feature 'GFM autocomplete', :js do
it 'includes items for assignee dropdowns with non-ASCII characters in name' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('')
find('#note-body').native.send_keys("@#{user.name[0...8]}")
simulate_input('#note-body', "@#{user.name[0...8]}")
end
expect(page).to have_selector('.atwho-container')
......@@ -112,7 +109,6 @@ feature 'GFM autocomplete', :js do
it 'selects the first item for non-assignee dropdowns if a query is entered' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('')
find('#note-body').native.send_keys(':1')
end
......@@ -127,9 +123,8 @@ feature 'GFM autocomplete', :js do
it 'wraps the result in double quotes' do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys("~#{label.title[0]}")
note.click
find('#note-body').native.send_keys('')
simulate_input('#note-body', "~#{label.title[0]}")
end
label_item = find('.atwho-view li', text: label.title)
......@@ -152,16 +147,13 @@ feature 'GFM autocomplete', :js do
it "does not show dropdown when preceded with a special character" do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys("@")
note.click
end
expect(page).to have_selector('.atwho-container')
page.within '.timeline-content-form' do
note.native.send_keys("@")
note.click
end
expect(page).to have_selector('.atwho-container', visible: false)
......@@ -170,9 +162,7 @@ feature 'GFM autocomplete', :js do
it "does not throw an error if no labels exist" do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys('~')
note.click
end
expect(page).to have_selector('.atwho-container', visible: false)
......@@ -181,9 +171,7 @@ feature 'GFM autocomplete', :js do
it 'doesn\'t wrap for assignee values' do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys("@#{user.username[0]}")
note.click
end
user_item = find('.atwho-view li', text: user.username)
......@@ -194,9 +182,7 @@ feature 'GFM autocomplete', :js do
it 'doesn\'t wrap for emoji values' do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys(":cartwheel")
note.click
note.native.send_keys(":cartwheel_")
end
emoji_item = find('.atwho-view li', text: 'cartwheel_tone1')
......@@ -223,12 +209,11 @@ feature 'GFM autocomplete', :js do
it 'triggers autocomplete after selecting a quick action' do
note = find('#note-body')
page.within '.timeline-content-form' do
note.native.send_keys('')
note.native.send_keys('/as')
note.click
end
find('.atwho-view li', text: '/assign').native.send_keys(:tab)
find('.atwho-view li', text: '/assign')
note.native.send_keys(:tab)
user_item = find('.atwho-view li', text: user.username)
expect(user_item).to have_content(user.username)
......
......@@ -130,8 +130,8 @@ feature 'Issue Sidebar' do
it 'adds new label' do
page.within('.block.labels') do
fill_in 'new_label_name', with: 'wontfix'
page.find('.suggest-colors a', match: :first).trigger('click')
page.find('button', text: 'Create').trigger('click')
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
page.within('.dropdown-page-one') do
expect(page).to have_content 'wontfix'
......@@ -142,8 +142,8 @@ feature 'Issue Sidebar' do
it 'shows error message if label title is taken' do
page.within('.block.labels') do
fill_in 'new_label_name', with: label.title
page.find('.suggest-colors a', match: :first).trigger('click')
page.find('button', text: 'Create').trigger('click')
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
page.within('.dropdown-page-two') do
expect(page).to have_content 'Title has already been taken'
......@@ -170,7 +170,7 @@ feature 'Issue Sidebar' do
end
def open_issue_sidebar
find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').trigger('click')
find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').click
find('aside.right-sidebar.right-sidebar-expanded')
end
end
......@@ -38,7 +38,7 @@ feature 'issue move to another project' do
end
scenario 'moving issue to another project', :js do
find('.js-move-issue').trigger('click')
find('.js-move-issue').click
wait_for_requests
all('.js-move-issue-dropdown-item')[0].click
find('.js-move-issue-confirmation-button').click
......@@ -52,7 +52,7 @@ feature 'issue move to another project' do
scenario 'searching project dropdown', :js do
new_project_search.team << [user, :reporter]
find('.js-move-issue').trigger('click')
find('.js-move-issue').click
wait_for_requests
page.within '.js-sidebar-move-issue-block' do
......@@ -69,7 +69,7 @@ feature 'issue move to another project' do
background { another_project.team << [user, :guest] }
scenario 'browsing projects in projects select' do
find('.js-move-issue').trigger('click')
find('.js-move-issue').click
wait_for_requests
page.within '.js-sidebar-move-issue-block' do
......
......@@ -118,7 +118,7 @@ feature 'Multiple issue updating from issues#index', :js do
end
def click_update_issues_button
find('.update-selected-issues').trigger('click')
find('.update-selected-issues').click
wait_for_requests
end
end
......@@ -226,7 +226,7 @@ feature 'Issues > User uses quick actions', :js do
end
it 'applies the commands to both issues and moves the issue' do
write_note("/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"\n/move #{target_project.full_path}")
write_note("/label ~#{bug.title} ~#{wontfix.title}\n\n/milestone %\"#{milestone.title}\"\n\n/move #{target_project.full_path}")
expect(page).to have_content 'Commands applied'
expect(issue.reload).to be_closed
......@@ -245,7 +245,7 @@ feature 'Issues > User uses quick actions', :js do
end
it 'moves the issue and applies the commands to both issues' do
write_note("/move #{target_project.full_path}\n/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"")
write_note("/move #{target_project.full_path}\n\n/label ~#{bug.title} ~#{wontfix.title}\n\n/milestone %\"#{milestone.title}\"")
expect(page).to have_content 'Commands applied'
expect(issue.reload).to be_closed
......
......@@ -367,7 +367,7 @@ describe 'Issues' do
it 'changes incoming email address token', :js do
find('.issue-email-modal-btn').click
previous_token = find('input#issue_email').value
find('.incoming-email-token-reset').trigger('click')
find('.incoming-email-token-reset').click
wait_for_requests
......@@ -585,9 +585,11 @@ describe 'Issues' do
end
it "cancels a file upload correctly" do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
click_button 'Cancel'
end
expect(page).to have_button('Attach a file')
expect(page).not_to have_button('Cancel')
......
......@@ -23,11 +23,11 @@ feature 'Merge request conflict resolution', :js do
within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do
all('button', text: 'Use ours').each do |button|
button.trigger('click')
button.send_keys(:return)
end
end
click_button 'Commit conflict resolution'
find_button('Commit conflict resolution').send_keys(:return)
expect(page).to have_content('All merge conflicts were resolved')
merge_request.reload_diff
......@@ -71,7 +71,7 @@ feature 'Merge request conflict resolution', :js do
execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");')
end
click_button 'Commit conflict resolution'
find_button('Commit conflict resolution').send_keys(:return)
expect(page).to have_content('All merge conflicts were resolved')
merge_request.reload_diff
......
......@@ -22,7 +22,7 @@ feature 'Diff note avatars', :js do
project.team << [user, :master]
sign_in user
page.driver.set_cookie('sidebar_collapsed', 'true')
set_cookie('sidebar_collapsed', 'true')
end
context 'discussion tab' do
......@@ -56,7 +56,7 @@ feature 'Diff note avatars', :js do
end
it 'does not render avatar after commenting' do
first('.diff-line-num').trigger('mouseover')
first('.diff-line-num').click
find('.js-add-diff-note-button').click
page.within('.js-discussion-note-form') do
......@@ -85,7 +85,7 @@ feature 'Diff note avatars', :js do
it 'shows note avatar' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').click
find('.diff-notes-collapse').send_keys(:return)
expect(page).to have_selector('img.js-diff-comment-avatar', count: 1)
end
......@@ -93,7 +93,7 @@ feature 'Diff note avatars', :js do
it 'shows comment on note avatar' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').click
find('.diff-notes-collapse').send_keys(:return)
expect(first('img.js-diff-comment-avatar')["data-original-title"]).to eq("#{note.author.name}: #{note.note.truncate(17)}")
end
......@@ -101,7 +101,7 @@ feature 'Diff note avatars', :js do
it 'toggles comments when clicking avatar' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').click
find('.diff-notes-collapse').send_keys(:return)
end
expect(page).to have_selector('.notes_holder', visible: false)
......@@ -117,7 +117,7 @@ feature 'Diff note avatars', :js do
open_more_actions_dropdown(note)
page.within find(".note-row-#{note.id}") do
find('.js-note-delete').click
accept_confirm { find('.js-note-delete').click }
end
wait_for_requests
......@@ -139,7 +139,7 @@ feature 'Diff note avatars', :js do
end
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').trigger('click')
find('.diff-notes-collapse').send_keys(:return)
expect(page).to have_selector('img.js-diff-comment-avatar', count: 2)
end
......@@ -152,14 +152,14 @@ feature 'Diff note avatars', :js do
page.within '.js-discussion-note-form' do
find('.js-note-text').native.send_keys('Test')
find('.js-comment-button').trigger('click')
find('.js-comment-button').click
wait_for_requests
end
end
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').trigger('click')
find('.diff-notes-collapse').send_keys(:return)
expect(page).to have_selector('img.js-diff-comment-avatar', count: 3)
expect(find('.diff-comments-more-count')).to have_content '+1'
......@@ -177,7 +177,7 @@ feature 'Diff note avatars', :js do
it 'shows extra comment count' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').click
find('.diff-notes-collapse').send_keys(:return)
expect(find('.diff-comments-more-count')).to have_content '+1'
end
......
......@@ -192,7 +192,7 @@ feature 'Diff notes resolve', :js do
page.find('.discussion-next-btn').click
end
expect(page.evaluate_script("$('body').scrollTop()")).to be > 0
expect(page.evaluate_script("window.pageYOffset")).to be > 0
end
it 'hides jump to next button when all resolved' do
......@@ -241,11 +241,9 @@ feature 'Diff notes resolve', :js do
end
it 'resolves discussion' do
page.all('.note').each do |note|
note.all('.line-resolve-btn').each do |button|
page.all('.note .line-resolve-btn').each do |button|
button.click
end
end
expect(page).to have_content('Resolved by')
......@@ -305,10 +303,10 @@ feature 'Diff notes resolve', :js do
end
page.within '.line-resolve-all-container' do
page.find('.discussion-next-btn').trigger('click')
page.find('.discussion-next-btn').click
end
expect(page.evaluate_script("$('body').scrollTop()")).to be > 0
expect(page.evaluate_script("window.pageYOffset")).to be > 0
end
it 'updates updated text after resolving note' do
......
......@@ -7,14 +7,12 @@ feature 'Diffs URL', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
context 'when visit with */* as accept header' do
before do
page.driver.add_header('Accept', '*/*')
end
it 'renders the notes' do
create :note_on_merge_request, project: project, noteable: merge_request, note: 'Rebasing with master'
inspect_requests(inject_headers: { 'Accept' => '*/*' }) do
visit diffs_project_merge_request_path(project, merge_request)
end
# Load notes and diff through AJAX
expect(page).to have_css('.note-text', visible: false, text: 'Rebasing with master')
......@@ -90,7 +88,7 @@ feature 'Diffs URL', :js do
visit diffs_project_merge_request_path(project, merge_request)
# Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax
find("[id=\"#{changelog_id}\"] .js-edit-blob").trigger('click')
find("[id=\"#{changelog_id}\"] .js-edit-blob").click
expect(page).to have_selector('.js-fork-suggestion-button', count: 1)
expect(page).to have_selector('.js-cancel-fork-suggestion-button', count: 1)
......
......@@ -43,7 +43,7 @@ describe 'New/edit merge request', :js do
expect(page).to have_content user2.name
end
find('a', text: 'Assign to me').trigger('click')
find('a', text: 'Assign to me').click
expect(find('input[name="merge_request[assignee_id]"]', visible: false).value).to match(user.id.to_s)
page.within '.js-assignee-search' do
expect(page).to have_content user.name
......
......@@ -83,7 +83,7 @@ feature 'Mini Pipeline Graph', :js do
end
before do
toggle.trigger('click')
toggle.click
wait_for_requests
end
......@@ -92,7 +92,7 @@ feature 'Mini Pipeline Graph', :js do
end
it 'should close when toggle is clicked again' do
toggle.trigger('click')
toggle.click
expect(toggle.find(:xpath, '..')).not_to have_selector('.mini-pipeline-graph-dropdown-menu')
end
......
......@@ -127,7 +127,7 @@ feature 'Multiple merge requests updating from merge_requests#index' do
end
def click_update_merge_requests_button
find('.update-selected-issues').trigger('click')
find('.update-selected-issues').click
wait_for_requests
end
end
......@@ -8,7 +8,7 @@ feature 'Merge requests > User posts diff notes', :js do
let(:project) { merge_request.source_project }
before do
page.driver.set_cookie('sidebar_collapsed', 'true')
set_cookie('sidebar_collapsed', 'true')
project.add_developer(user)
sign_in(user)
......@@ -103,7 +103,10 @@ feature 'Merge requests > User posts diff notes', :js do
it 'allows commenting' do
should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
first('.js-note-delete', visible: false).trigger('click')
accept_confirm do
first('button.more-actions-toggle').click
first('.js-note-delete').click
end
should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
end
......@@ -236,7 +239,7 @@ feature 'Merge requests > User posts diff notes', :js do
def should_allow_dismissing_a_comment(line_holder, diff_side = nil)
write_comment_on_line(line_holder, diff_side)
find('.js-close-discussion-note-form').trigger('click')
find('.js-close-discussion-note-form').click
assert_comment_dismissal(line_holder)
end
......
......@@ -141,7 +141,7 @@ describe 'Merge requests > User posts notes', :js do
end
it 'removes the attachment div and resets the edit form' do
find('.js-note-attachment-delete').click
accept_confirm { find('.js-note-attachment-delete').click }
is_expected.not_to have_css('.note-attachment')
is_expected.not_to have_css('.current-note-edit-form')
wait_for_requests
......
......@@ -67,8 +67,8 @@ feature 'Merge Request versions', :js do
line_code = '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44_2_2'
page.within(diff_file_selector) do
find(".line_holder[id='#{line_code}'] td:nth-of-type(1)").trigger 'mouseover'
find(".line_holder[id='#{line_code}'] button").trigger 'click'
find(".line_holder[id='#{line_code}'] td:nth-of-type(1)").hover
find(".line_holder[id='#{line_code}'] button").click
page.within("form[data-line-code='#{line_code}']") do
fill_in "note[note]", with: "Typo, please fix"
......@@ -137,8 +137,8 @@ feature 'Merge Request versions', :js do
line_code = '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44_4_4'
page.within(diff_file_selector) do
find(".line_holder[id='#{line_code}'] td:nth-of-type(1)").trigger 'mouseover'
find(".line_holder[id='#{line_code}'] button").trigger 'click'
find(".line_holder[id='#{line_code}'] td:nth-of-type(1)").hover
find(".line_holder[id='#{line_code}'] button").click
page.within("form[data-line-code='#{line_code}']") do
fill_in "note[note]", with: "Typo, please fix"
......
......@@ -42,7 +42,7 @@ feature 'Widget Deployments Header', :js do
end
scenario 'does start build when stop button clicked' do
click_button('Stop environment')
accept_confirm { click_button('Stop environment') }
expect(page).to have_content('close_app')
end
......
......@@ -65,7 +65,7 @@ describe 'Profile account page', :js do
within('.rss-token-reset') do
previous_token = find("#rss_token").value
click_link('reset it')
accept_confirm { click_link('reset it') }
expect(find('#rss_token').value).not_to eq(previous_token)
end
......@@ -84,7 +84,7 @@ describe 'Profile account page', :js do
within('.incoming-email-token-reset') do
previous_token = find('#incoming_email_token').value
click_link('reset it')
accept_confirm { click_link('reset it') }
expect(find('#incoming_email_token').value).not_to eq(previous_token)
end
......
......@@ -14,7 +14,7 @@ describe 'Profile > Applications' do
page.within('.oauth-applications') do
expect(page).to have_content('Your applications (1)')
click_button 'Destroy'
accept_confirm { click_button 'Destroy' }
end
expect(page).to have_content('The application was deleted successfully')
......@@ -28,7 +28,7 @@ describe 'Profile > Applications' do
page.within('.oauth-authorized-applications') do
expect(page).to have_content('Authorized applications (1)')
click_button 'Revoke'
accept_confirm { click_button 'Revoke' }
end
expect(page).to have_content('The application was revoked access.')
......
......@@ -34,7 +34,7 @@ describe 'Profile > Personal Access Tokens', :js do
fill_in "Name", with: name
# Set date to 1st of next month
find_field("Expires at").trigger('focus')
find_field("Expires at").click
find(".pika-next").click
click_on "1"
......@@ -78,7 +78,7 @@ describe 'Profile > Personal Access Tokens', :js do
it "allows revocation of an active token" do
visit profile_personal_access_tokens_path
click_on "Revoke"
accept_confirm { click_on "Revoke" }
expect(page).to have_selector(".settings-message")
expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.")
......@@ -100,7 +100,7 @@ describe 'Profile > Personal Access Tokens', :js do
errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") }
allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors)
click_on "Revoke"
accept_confirm { click_on "Revoke" }
expect(active_personal_access_tokens).to have_text(personal_access_token.name)
expect(page).to have_content("Could not revoke")
end
......
......@@ -13,7 +13,7 @@ feature 'User visits the notifications tab', :js do
it 'changes the project notifications setting' do
expect(page).to have_content('Notifications')
first('#notifications-button').trigger('click')
first('#notifications-button').click
click_link('On mention')
expect(page).to have_content('On mention')
......
......@@ -53,7 +53,7 @@ describe 'User visits the profile preferences page' do
expect(page).to have_content("You don't have starred projects yet")
expect(page.current_path).to eq starred_dashboard_projects_path
find('.shortcuts-activity').trigger('click')
find('.shortcuts-activity').click
expect(page).not_to have_content("You don't have starred projects yet")
expect(page.current_path).to eq dashboard_projects_path
......
require 'spec_helper'
feature 'Download artifact', :js do
feature 'Download artifact' do
let(:project) { create(:project, :public) }
let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) }
let(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) }
......
......@@ -39,7 +39,6 @@ feature 'Artifact file', :js do
context 'JPG file' do
before do
page.driver.browser.url_blacklist = []
visit_file('rails_sample.jpg')
wait_for_requests
......
......@@ -67,7 +67,7 @@ describe 'Branches' do
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
find('.js-branch-fix .btn-remove').trigger(:click)
accept_confirm { find('.js-branch-fix .btn-remove').click }
expect(page).not_to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 0)
......
......@@ -20,8 +20,8 @@ feature 'Commit diff', :js do
it "adds comment to diff" do
diff_line_num = first('.diff-line-num.new')
diff_line_num.trigger('mouseover')
diff_line_num.find('.js-add-diff-note-button').trigger('click')
diff_line_num.hover
diff_line_num.find('.js-add-diff-note-button').click
page.within(first('.diff-viewer')) do
find('.js-note-text').set 'test comment'
......
......@@ -18,7 +18,7 @@ feature 'Mini Pipeline Graph in Commit View', :js do
expect(page).to have_selector('.mr-widget-pipeline-graph')
first('.mini-pipeline-graph-dropdown-toggle').trigger('click')
first('.mini-pipeline-graph-dropdown-toggle').click
wait_for_requests
......
......@@ -20,7 +20,7 @@ describe 'Project deploy keys', :js do
page.within(find('.deploy-keys')) do
expect(page).to have_selector('.deploy-keys li', count: 1)
click_on 'Remove'
accept_confirm { find(:button, text: 'Remove').send_keys(:return) }
expect(page).not_to have_selector('.fa-spinner', count: 0)
expect(page).to have_selector('.deploy-keys li', count: 0)
......
......@@ -193,12 +193,14 @@ feature 'Environment' do
create(:environment, project: project,
name: 'staging-1.0/review',
state: :available)
end
it 'renders a correct environment folder' do
reqs = inspect_requests do
visit folder_project_environments_path(project, id: 'staging-1.0')
end
it 'renders a correct environment folder' do
expect(page).to have_gitlab_http_status(:ok)
expect(reqs.first.status_code).to eq(200)
expect(page).to have_content('Environments / staging-1.0')
end
end
......
......@@ -151,7 +151,7 @@ feature 'Environments page', :js do
find('.js-dropdown-play-icon-container').click
expect(page).to have_content(action.name.humanize)
expect { find('.js-manual-action-link').trigger('click') }
expect { find('.js-manual-action-link').click }
.not_to change { Ci::Pipeline.count }
end
......
......@@ -22,7 +22,7 @@ describe 'Edit Project Settings' do
# disable by clicking toggle
toggle_feature_off("project[project_feature_attributes][#{tool_name}_access_level]")
page.within('.sharing-permissions') do
click_button 'Save changes'
find('input[value="Save changes"]').click
end
wait_for_requests
expect(page).not_to have_selector(".shortcuts-#{shortcut_name}")
......@@ -30,7 +30,7 @@ describe 'Edit Project Settings' do
# re-enable by clicking toggle again
toggle_feature_on("project[project_feature_attributes][#{tool_name}_access_level]")
page.within('.sharing-permissions') do
click_button 'Save changes'
find('input[value="Save changes"]').click
end
wait_for_requests
expect(page).to have_selector(".shortcuts-#{shortcut_name}")
......
......@@ -7,9 +7,8 @@ feature 'User uses soft wrap whilst editing file', :js do
project.team << [user, :master]
sign_in user
visit project_new_blob_path(project, 'master', file_name: 'test_file-name')
editor = find('.file-editor.code')
editor.click
editor.send_keys 'Touch water with paw then recoil in horror chase dog then
page.within('.file-editor.code') do
find('.ace_text-input', visible: false).send_keys 'Touch water with paw then recoil in horror chase dog then
run away chase the pig around the house eat owner\'s food, and knock
dish off table head butt cant eat out of my own dish. Cat is love, cat
is life rub face on everything poop on grasses so meow. Playing with
......@@ -20,6 +19,7 @@ feature 'User uses soft wrap whilst editing file', :js do
hanging out of own butt jump off balcony, onto stranger\'s head yet
chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish
end
end
let(:toggle_button) { find('.soft-wrap-toggle') }
......@@ -36,6 +36,6 @@ feature 'User uses soft wrap whilst editing file', :js do
end
def get_content_width
find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/)
find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/).to_i
end
end
......@@ -41,7 +41,7 @@ feature 'Import/Export - project export integration test', :js do
expect(page).to have_content('Export project')
click_link 'Export project'
find(:link, 'Export project').send_keys(:return)
visit edit_project_path(project)
......
......@@ -94,6 +94,6 @@ feature 'Import/Export - project import integration test', :js do
end
def click_import_project_tab
find('#import-project-tab').trigger('click')
find('#import-project-tab').click
end
end
......@@ -52,7 +52,7 @@ feature 'Import/Export - Namespace export file cleanup', :js do
expect(page).to have_content('Export project')
click_link 'Export project'
find(:link, 'Export project').send_keys(:return)
visit edit_project_path(project)
......
......@@ -21,12 +21,12 @@ describe 'User browses a job', :js do
expect(page).to have_content("Job ##{build.id}")
expect(page).to have_css('#build-trace')
click_link('Erase')
accept_confirm { click_link('Erase') }
expect(page).to have_no_css('.artifacts')
expect(build).not_to have_trace
expect(build.artifacts_file.exists?).to be_falsy
expect(build.artifacts_metadata.exists?).to be_falsy
expect(page).to have_no_css('.artifacts')
page.within('.erased') do
expect(page).to have_content('Job has been erased')
......
......@@ -380,7 +380,6 @@ feature 'Jobs' do
end
it 'loads the page and shows all needed controls' do
expect(page.status_code).to eq(200)
expect(page).to have_content 'Retry'
end
end
......@@ -392,11 +391,10 @@ feature 'Jobs' do
job.run!
visit project_job_path(project, job)
find('.js-cancel-job').click()
find('.js-retry-button').trigger('click')
find('.js-retry-button').click
end
it 'shows the right status and buttons', :js do
expect(page).to have_gitlab_http_status(200)
page.within('aside.right-sidebar') do
expect(page).to have_content 'Cancel'
end
......@@ -443,28 +441,30 @@ feature 'Jobs' do
context 'access source' do
context 'job from project' do
before do
Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
job.run!
visit project_job_path(project, job)
find('.js-raw-link-controller').click()
end
it 'sends the right headers' do
expect(page.status_code).to eq(200)
expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
expect(page.response_headers['X-Sendfile']).to eq(job.trace.send(:current_path))
requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do
visit raw_project_job_path(project, job)
end
expect(requests.first.status_code).to eq(200)
expect(requests.first.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
expect(requests.first.response_headers['X-Sendfile']).to eq(job.trace.send(:current_path))
end
end
context 'job from other project' do
before do
Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
job2.run!
visit raw_project_job_path(project, job2)
end
it 'sends the right headers' do
expect(page.status_code).to eq(404)
requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do
visit raw_project_job_path(project, job2)
end
expect(requests.first.status_code).to eq(404)
end
end
end
......@@ -473,8 +473,6 @@ feature 'Jobs' do
let(:existing_file) { Tempfile.new('existing-trace-file').path }
before do
Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
job.run!
end
......@@ -483,16 +481,14 @@ feature 'Jobs' do
allow_any_instance_of(Gitlab::Ci::Trace)
.to receive(:paths)
.and_return([existing_file])
visit project_job_path(project, job)
find('.js-raw-link-controller').click
end
it 'sends the right headers' do
expect(page.status_code).to eq(200)
expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
expect(page.response_headers['X-Sendfile']).to eq(existing_file)
requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do
visit raw_project_job_path(project, job)
end
expect(requests.first.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
expect(requests.first.response_headers['X-Sendfile']).to eq(existing_file)
end
end
......
......@@ -31,6 +31,7 @@ feature 'Projects > Members > Groups with access list', :js do
tomorrow = Date.today + 3
fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F")
find('body').click
wait_for_requests
page.within(find('li.group_member')) do
......@@ -40,7 +41,7 @@ feature 'Projects > Members > Groups with access list', :js do
scenario 'deletes group link' do
page.within(first('.group_member')) do
find('.btn-remove').click
accept_confirm { find('.btn-remove').click }
end
wait_for_requests
......
......@@ -20,7 +20,7 @@ feature 'Projects > Members > Master adds member with expiration date', :js do
page.within '.users-project-form' do
select2(new_member.id, from: '#user_ids', multiple: true)
fill_in 'expires_at', with: date.to_s(:medium)
fill_in 'expires_at', with: date.to_s(:medium) + "\n"
click_on 'Add to project'
end
......@@ -37,7 +37,7 @@ feature 'Projects > Members > Master adds member with expiration date', :js do
visit project_project_members_path(project)
page.within "#project_member_#{new_member.project_members.first.id}" do
find('.js-access-expiration-date').set date.to_s(:medium)
find('.js-access-expiration-date').set date.to_s(:medium) + "\n"
wait_for_requests
expect(page).to have_content('Expires in 3 days')
end
......
......@@ -41,7 +41,7 @@ feature 'Project > Members > Share with Group', :js do
select2 group_to_share_with.id, from: '#link_group_id'
page.find('body').click
find('.btn-create').trigger('click')
find('.btn-create').click
page.within('.project-members-groups') do
expect(page).to have_content(group_to_share_with.name)
......@@ -123,7 +123,7 @@ feature 'Project > Members > Share with Group', :js do
fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d')
page.find('body').click
find('.btn-create').trigger('click')
find('.btn-create').click
end
scenario 'the group link shows the expiration time with a warning class' do
......
......@@ -60,7 +60,7 @@ feature 'Projects > Members > User requests access', :js do
expect(project.requesters.exists?(user_id: user)).to be_truthy
click_link 'Withdraw Access Request'
accept_confirm { click_link 'Withdraw Access Request' }
expect(project.requesters.exists?(user_id: user)).to be_falsey
expect(page).to have_content 'Your access request to the project has been withdrawn.'
......
......@@ -31,7 +31,7 @@ describe 'User comments on a diff', :js do
page.within('.files > div:nth-child(3)') do
expect(page).to have_content('Line is wrong')
find('.js-toggle-diff-comments').trigger('click')
find('.js-toggle-diff-comments').click
expect(page).not_to have_content('Line is wrong')
end
......@@ -64,7 +64,7 @@ describe 'User comments on a diff', :js do
# Hide the comment.
page.within('.files > div:nth-child(3)') do
find('.js-toggle-diff-comments').trigger('click')
find('.js-toggle-diff-comments').click
expect(page).not_to have_content('Line is wrong')
end
......@@ -77,7 +77,7 @@ describe 'User comments on a diff', :js do
# Show the comment.
page.within('.files > div:nth-child(3)') do
find('.js-toggle-diff-comments').trigger('click')
find('.js-toggle-diff-comments').click
end
# Now both the comments should be shown.
......@@ -90,6 +90,7 @@ describe 'User comments on a diff', :js do
end
# Check the same comments in the side-by-side view.
execute_script("window.scrollTo(0,0);")
click_link('Side-by-side')
wait_for_requests
......@@ -153,11 +154,11 @@ describe 'User comments on a diff', :js do
find('.more-actions').click
find('.more-actions .dropdown-menu li', match: :first)
find('.js-note-delete').click
accept_confirm { find('.js-note-delete').click }
end
page.within('.merge-request-tabs') do
find('.notes-tab').trigger('click')
find('.notes-tab').click
end
wait_for_requests
......
require 'spec_helper'
describe 'User edits a merge request', :js do
include Select2Helper
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:user) { create(:user) }
......@@ -15,8 +17,7 @@ describe 'User edits a merge request', :js do
it 'changes the target branch' do
expect(page).to have_content('Target branch')
first('.target_branch').click
select('merge-test', from: 'merge_request_target_branch', visible: false)
select2('merge-test', from: '#merge_request_target_branch')
click_button('Save changes')
expect(page).to have_content("Request to merge #{merge_request.source_branch} into merge-test")
......
......@@ -15,7 +15,7 @@ feature 'New project' do
expect(page).to have_content('Project path')
expect(page).to have_content('Project name')
find('#import-project-tab').trigger('click')
find('#import-project-tab').click
expect(page).to have_link('GitHub')
expect(page).to have_link('Bitbucket')
......@@ -137,7 +137,7 @@ feature 'New project' do
context 'Import project options', :js do
before do
visit new_project_path
find('#import-project-tab').trigger('click')
find('#import-project-tab').click
end
context 'from git repository url' do
......
......@@ -54,7 +54,7 @@ feature 'Pipeline Schedules', :js do
end
it 'deletes the pipeline' do
click_link 'Delete'
accept_confirm { click_link 'Delete' }
expect(page).not_to have_css(".pipeline-schedule-table-row")
end
......
......@@ -73,7 +73,7 @@ describe 'Pipeline', :js do
end
it 'should be possible to cancel the running build' do
find('#ci-badge-deploy .ci-action-icon-container').trigger('click')
find('#ci-badge-deploy .ci-action-icon-container').click
expect(page).not_to have_content('Cancel running')
end
......@@ -92,7 +92,7 @@ describe 'Pipeline', :js do
end
it 'should be possible to retry the success job' do
find('#ci-badge-build .ci-action-icon-container').trigger('click')
find('#ci-badge-build .ci-action-icon-container').click
expect(page).not_to have_content('Retry job')
end
......@@ -111,7 +111,7 @@ describe 'Pipeline', :js do
end
it 'should be possible to retry the failed build' do
find('#ci-badge-test .ci-action-icon-container').trigger('click')
find('#ci-badge-test .ci-action-icon-container').click
expect(page).not_to have_content('Retry job')
end
......@@ -130,7 +130,7 @@ describe 'Pipeline', :js do
end
it 'should be possible to play the manual job' do
find('#ci-badge-manual-build .ci-action-icon-container').trigger('click')
find('#ci-badge-manual-build .ci-action-icon-container').click
expect(page).not_to have_content('Play job')
end
......@@ -165,7 +165,7 @@ describe 'Pipeline', :js do
context 'when retrying' do
before do
find('.js-retry-button').trigger('click')
find('.js-retry-button').click
end
it { expect(page).not_to have_content('Retry') }
......@@ -231,7 +231,7 @@ describe 'Pipeline', :js do
context 'when retrying' do
before do
find('.js-retry-button').trigger('click')
find('.js-retry-button').click
end
it { expect(page).not_to have_content('Retry') }
......
......@@ -103,7 +103,7 @@ describe 'Pipelines', :js do
context 'when canceling' do
before do
find('.js-pipelines-cancel-button').click
accept_confirm { find('.js-pipelines-cancel-button').click }
wait_for_requests
end
......@@ -232,7 +232,7 @@ describe 'Pipelines', :js do
context 'when canceling' do
before do
find('.js-pipelines-cancel-button').trigger('click')
accept_alert { find('.js-pipelines-cancel-button').click }
end
it 'indicates that pipeline was canceled' do
......@@ -345,14 +345,14 @@ describe 'Pipelines', :js do
context 'when clicking a stage badge' do
it 'should open a dropdown' do
find('.js-builds-dropdown-button').trigger('click')
find('.js-builds-dropdown-button').click
expect(page).to have_link build.name
end
it 'should be possible to cancel pending build' do
find('.js-builds-dropdown-button').trigger('click')
find('a.js-ci-action-icon').trigger('click')
find('.js-builds-dropdown-button').click
find('a.js-ci-action-icon').click
expect(page).to have_content('canceled')
expect(build.reload).to be_canceled
......@@ -361,11 +361,16 @@ describe 'Pipelines', :js do
context 'dropdown jobs list' do
it 'should keep the dropdown open when the user ctr/cmd + clicks in the job name' do
find('.js-builds-dropdown-button').trigger('click')
find('.js-builds-dropdown-button').click
dropdown_item = find('.mini-pipeline-graph-dropdown-item').native
execute_script('var e = $.Event("keydown", { keyCode: 64 }); $("body").trigger(e);')
find('.mini-pipeline-graph-dropdown-item').trigger('click')
%i(alt control).each do |meta_key|
page.driver.browser.action
.key_down(meta_key)
.click(dropdown_item)
.key_up(meta_key)
.perform
end
expect(page).to have_selector('.js-ci-action-icon')
end
......@@ -525,7 +530,6 @@ describe 'Pipelines', :js do
let(:project) { create(:project, :public, :repository) }
it { expect(page).to have_content 'Build with confidence' }
it { expect(page).to have_gitlab_http_status(:success) }
end
context 'when project is private' do
......
......@@ -6,7 +6,7 @@ feature 'Ref switcher', :js do
before do
project.team << [user, :master]
page.driver.set_cookie('new_repo', 'true')
set_cookie('new_repo', 'true')
sign_in(user)
visit project_tree_path(project, 'master')
end
......
......@@ -65,7 +65,7 @@ describe 'User activates Jira', :js do
expect(find('.flash-container-page')).to have_content 'Test failed. message'
expect(find('.flash-container-page')).to have_content 'Save anyway'
find('.flash-alert .flash-action').trigger('click')
find('.flash-alert .flash-action').click
wait_for_requests
expect(page).to have_content('JIRA activated.')
......
......@@ -76,7 +76,7 @@ feature 'Setup Mattermost slash commands', :js do
select_element = find('#mattermost_team_id')
selected_option = select_element.find('option[selected]')
expect(select_element['disabled']).to be(true)
expect(select_element['disabled']).to eq("true")
expect(selected_option).to have_content(team_name.to_s)
end
......@@ -104,7 +104,7 @@ feature 'Setup Mattermost slash commands', :js do
select_element = find('#mattermost_team_id')
expect(select_element['disabled']).to be(false)
expect(select_element['disabled']).to be_falsey
expect(select_element.all('option').count).to eq(3)
end
......@@ -122,7 +122,7 @@ feature 'Setup Mattermost slash commands', :js do
click_link 'Add to Mattermost'
expect(find('input[type="submit"]')['disabled']).not_to be(true)
expect(find('input[type="submit"]')['disabled']).not_to eq("true")
end
it 'disables the submit button if the required fields are not provided', :js do
......@@ -132,7 +132,7 @@ feature 'Setup Mattermost slash commands', :js do
fill_in('mattermost_trigger', with: '')
expect(find('input[type="submit"]')['disabled']).to be(true)
expect(find('input[type="submit"]')['disabled']).to eq("true")
end
def stub_teams(count: 0)
......
......@@ -21,7 +21,7 @@ feature 'Project settings > Merge Requests', :js do
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
click_on('Save changes')
find('input[value="Save changes"]').send_keys(:return)
end
expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
......@@ -41,7 +41,7 @@ feature 'Project settings > Merge Requests', :js do
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
click_on('Save changes')
find('input[value="Save changes"]').send_keys(:return)
end
expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
......@@ -62,7 +62,7 @@ feature 'Project settings > Merge Requests', :js do
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
click_on('Save changes')
find('input[value="Save changes"]').send_keys(:return)
end
expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
......
......@@ -22,7 +22,7 @@ feature "Pipelines settings" do
context 'for master' do
given(:role) { :master }
scenario 'be allowed to change', :js do
scenario 'be allowed to change' do
fill_in('Test coverage parsing', with: 'coverage_regex')
click_on 'Save changes'
......
......@@ -34,7 +34,6 @@ feature 'Repository settings' do
visit project_settings_repository_path(project)
expect(page.status_code).to eq(200)
expect(page).to have_content('private_deploy_key')
expect(page).to have_content('public_deploy_key')
end
......@@ -86,7 +85,7 @@ feature 'Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
find('li', text: private_deploy_key.title).click_button('Remove')
accept_confirm { find('li', text: private_deploy_key.title).click_button('Remove') }
expect(page).not_to have_content(private_deploy_key.title)
end
......
......@@ -10,7 +10,7 @@ feature 'Create Snippet', :js do
fill_in 'project_snippet_title', with: 'My Snippet Title'
fill_in 'project_snippet_description', with: 'My Snippet **Description**'
page.within('.file-editor') do
find('.ace_editor').native.send_keys('Hello World!')
find('.ace_text-input', visible: false).send_keys('Hello World!')
end
end
......@@ -59,7 +59,7 @@ feature 'Create Snippet', :js do
fill_form
dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
click_button('Create snippet')
find("input[value='Create snippet']").send_keys(:return)
wait_for_requests
expect(page).to have_content('My Snippet Title')
......
require 'spec_helper'
feature 'Multi-file editor new directory', :js do
include WaitForRequests
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
......@@ -10,7 +8,7 @@ feature 'Multi-file editor new directory', :js do
project.add_master(user)
sign_in(user)
page.driver.set_cookie('new_repo', 'true')
set_cookie('new_repo', 'true')
visit project_tree_path(project, :master)
......@@ -32,7 +30,6 @@ feature 'Multi-file editor new directory', :js do
click_button('Commit 1 file')
expect(page).to have_content('Your changes have been committed')
expect(page).to have_selector('td', text: 'commit message')
click_link('foldername')
......
require 'spec_helper'
feature 'Multi-file editor new file', :js do
include WaitForRequests
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
......@@ -10,7 +8,7 @@ feature 'Multi-file editor new file', :js do
project.add_master(user)
sign_in(user)
page.driver.set_cookie('new_repo', 'true')
set_cookie('new_repo', 'true')
visit project_tree_path(project, :master)
......@@ -32,7 +30,6 @@ feature 'Multi-file editor new file', :js do
click_button('Commit 1 file')
expect(page).to have_content('Your changes have been committed')
expect(page).to have_selector('td', text: 'commit message')
end
end
require 'spec_helper'
feature 'Multi-file editor upload file', :js do
include WaitForRequests
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:txt_file) { File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt') }
......@@ -12,7 +10,7 @@ feature 'Multi-file editor upload file', :js do
project.add_master(user)
sign_in(user)
page.driver.set_cookie('new_repo', 'true')
set_cookie('new_repo', 'true')
visit project_tree_path(project, :master)
......@@ -29,7 +27,7 @@ feature 'Multi-file editor upload file', :js do
find('.add-to-tree').click
expect(page).to have_selector('.repo-tab', text: 'doc_sample.txt')
expect(page).to have_content(File.open(txt_file, &:readline))
expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
end
it 'uploads image file' do
......
......@@ -175,10 +175,11 @@ describe 'User browses files' do
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
end
fill_in(:branch_name, with: 'new_branch_name', visible: true)
click_button('Upload file')
end
wait_for_all_requests
visit(project_blob_path(project, 'new_branch_name/logo_sample.svg'))
......
......@@ -18,13 +18,13 @@ feature 'Projects > Wiki > User previews markdown changes', :js do
sign_in(user)
visit project_path(project)
find('.shortcuts-wiki').trigger('click')
find('.shortcuts-wiki').click
end
context "while creating a new wiki page" do
context "when there are no spaces or hyphens in the page name" do
it "rewrites relative links as expected" do
find('.add-new-wiki').trigger('click')
find('.add-new-wiki').click
page.within '#modal-new-wiki' do
fill_in :new_wiki_path, with: 'a/b/c/d'
click_button 'Create page'
......@@ -91,7 +91,7 @@ feature 'Projects > Wiki > User previews markdown changes', :js do
context "while editing a wiki page" do
def create_wiki_page(path)
find('.add-new-wiki').trigger('click')
find('.add-new-wiki').click
page.within '#modal-new-wiki' do
fill_in :new_wiki_path, with: path
......
......@@ -77,14 +77,14 @@ describe 'User creates wiki page' do
[stem]
++++
\sqrt{4} = 2
\\sqrt{4} = 2
++++
another part
[latexmath]
++++
\beta_x \gamma
\\beta_x \\gamma
++++
stem:[2+2] is 4
......
......@@ -138,7 +138,7 @@ describe 'User views a wiki page' do
it 'opens a default wiki page', :js do
visit(project_path(project))
find('.shortcuts-wiki').trigger('click')
find('.shortcuts-wiki').click
expect(page).to have_content('Home · Create Page')
end
......
......@@ -13,8 +13,8 @@ feature 'Project' do
end
it "allows creation from templates", :js do
find('#create-from-template-tab').trigger('click')
find("##{template.name}").trigger('click')
find('#create-from-template-tab').click
find("label[for=#{template.name}]").click
fill_in("project_path", with: template.name)
page.within '#content-body' do
......
......@@ -48,7 +48,7 @@ feature 'Protected Branches', :js do
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
page.find('[data-target="#modal-delete-branch"]').trigger(:click)
page.find('[data-target="#modal-delete-branch"]').click
expect(page).to have_css('.js-delete-branch[disabled]')
fill_in 'delete_branch_input', with: 'fix'
......@@ -67,9 +67,9 @@ feature 'Protected Branches', :js do
form = '.js-new-protected-branch'
within form do
find(".js-allowed-to-merge").trigger('click')
find(".js-allowed-to-merge").click
click_link 'No one'
find(".js-allowed-to-push").trigger('click')
find(".js-allowed-to-push").click
click_link 'Developers + Masters'
end
......@@ -171,7 +171,7 @@ feature 'Protected Branches', :js do
end
def set_protected_branch_name(branch_name)
find(".js-protected-branch-select").trigger('click')
find(".js-protected-branch-select").click
find(".dropdown-input-field").set(branch_name)
click_on("Create wildcard #{branch_name}")
end
......
require 'spec_helper'
feature 'RavenJS', :js do
feature 'RavenJS' do
let(:raven_path) { '/raven.bundle.js' }
it 'should not load raven if sentry is disabled' do
......@@ -18,6 +18,8 @@ feature 'RavenJS', :js do
end
def has_requested_raven
page.driver.network_traffic.one? {|request| request.url.end_with?(raven_path)}
page.all('script', visible: false).one? do |elm|
elm[:src] =~ /#{raven_path}$/
end
end
end
......@@ -32,14 +32,14 @@ describe 'User searches for code' do
include_examples 'top right search form'
it 'finds code' do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
page.within('.project-filter') do
click_link(project.name_with_namespace)
end
fill_in('dashboard_search', with: 'rspec')
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.results') do
expect(find(:css, '.search-results')).to have_content('Update capybara, rspec-rails, poltergeist to recent versions')
......
......@@ -18,7 +18,7 @@ describe 'User searches for issues', :js do
it 'finds an issue' do
fill_in('dashboard_search', with: issue1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Issues')
......@@ -31,14 +31,14 @@ describe 'User searches for issues', :js do
context 'when on a project page' do
it 'finds an issue' do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
page.within('.project-filter') do
click_link(project.name_with_namespace)
end
fill_in('dashboard_search', with: issue1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Issues')
......@@ -62,7 +62,7 @@ describe 'User searches for issues', :js do
it 'finds an issue' do
fill_in('dashboard_search', with: issue1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Issues')
......
......@@ -17,7 +17,7 @@ describe 'User searches for merge requests', :js do
it 'finds a merge request' do
fill_in('dashboard_search', with: merge_request1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Merge requests')
......@@ -30,14 +30,14 @@ describe 'User searches for merge requests', :js do
context 'when on a project page' do
it 'finds a merge request' do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
page.within('.project-filter') do
click_link(project.name_with_namespace)
end
fill_in('dashboard_search', with: merge_request1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Merge requests')
......
......@@ -17,7 +17,7 @@ describe 'User searches for milestones', :js do
it 'finds a milestone' do
fill_in('dashboard_search', with: milestone1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Milestones')
......@@ -30,14 +30,14 @@ describe 'User searches for milestones', :js do
context 'when on a project page' do
it 'finds a milestone' do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
page.within('.project-filter') do
click_link(project.name_with_namespace)
end
fill_in('dashboard_search', with: milestone1.title)
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Milestones')
......
......@@ -15,14 +15,14 @@ describe 'User searches for wiki pages', :js do
include_examples 'top right search form'
it 'finds a page' do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
page.within('.project-filter') do
click_link(project.name_with_namespace)
end
fill_in('dashboard_search', with: 'content')
find('.btn-search').trigger('click')
find('.btn-search').click
page.within('.search-filter') do
click_link('Wiki')
......
......@@ -16,7 +16,7 @@ describe 'User uses search filters', :js do
context' when filtering by group' do
it 'shows group projects' do
find('.js-search-group-dropdown').trigger('click')
find('.js-search-group-dropdown').click
wait_for_requests
......@@ -27,7 +27,7 @@ describe 'User uses search filters', :js do
expect(find('.js-search-group-dropdown')).to have_content(group.name)
page.within('.project-filter') do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
wait_for_requests
......@@ -39,7 +39,7 @@ describe 'User uses search filters', :js do
context' when filtering by project' do
it 'shows a project' do
page.within('.project-filter') do
find('.js-search-project-dropdown').trigger('click')
find('.js-search-project-dropdown').click
wait_for_requests
......
......@@ -74,24 +74,21 @@ describe 'Comments on personal snippets', :js do
it 'should not have autocomplete' do
wait_for_requests
request_count_before = page.driver.network_traffic.count
find('#note_note').native.send_keys('')
fill_in 'note[note]', with: '@'
wait_for_requests
request_count_after = page.driver.network_traffic.count
# This selector probably won't be in place even if autocomplete was enabled
# but we want to make sure
expect(page).not_to have_selector('.atwho-view')
expect(request_count_before).to eq(request_count_after)
end
end
context 'when editing a note' do
it 'changes the text' do
find('.js-note-edit').trigger('click')
find('.js-note-edit').click
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'new content'
......@@ -113,7 +110,7 @@ describe 'Comments on personal snippets', :js do
open_more_actions_dropdown(snippet_notes[0])
page.within("#notes-list li#note_#{snippet_notes[0].id}") do
click_on 'Delete comment'
accept_confirm { click_on 'Delete comment' }
end
wait_for_requests
......
......@@ -14,7 +14,7 @@ feature 'User creates snippet', :js do
fill_in 'personal_snippet_title', with: 'My Snippet Title'
fill_in 'personal_snippet_description', with: 'My Snippet **Description**'
page.within('.file-editor') do
find('.ace_editor').native.send_keys 'Hello World!'
find('.ace_text-input', visible: false).send_keys 'Hello World!'
end
end
......@@ -43,8 +43,8 @@ feature 'User creates snippet', :js do
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/temp/\h{32}/banana_sample\.gif\z})
visit(link)
expect(page.status_code).to eq(200)
reqs = inspect_requests { visit(link) }
expect(reqs.first.status_code).to eq(200)
end
end
......@@ -61,8 +61,8 @@ feature 'User creates snippet', :js do
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
visit(link)
expect(page.status_code).to eq(200)
reqs = inspect_requests { visit(link) }
expect(reqs.first.status_code).to eq(200)
end
scenario 'validation fails for the first time' do
......@@ -86,15 +86,15 @@ feature 'User creates snippet', :js do
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
visit(link)
expect(page.status_code).to eq(200)
reqs = inspect_requests { visit(link) }
expect(reqs.first.status_code).to eq(200)
end
scenario 'Authenticated user creates a snippet with + in filename' do
fill_in 'personal_snippet_title', with: 'My Snippet Title'
page.within('.file-editor') do
find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name'
find('.ace_editor').native.send_keys 'Hello World!'
find('.ace_text-input', visible: false).send_keys 'Hello World!'
end
click_button 'Create snippet'
......
......@@ -63,7 +63,7 @@ feature 'Master creates tag' do
expect(ref_input.value).to eq 'master'
expect(find('.dropdown-toggle-text')).to have_content 'master'
find('.js-branch-select').trigger('click')
find('.js-branch-select').click
expect(find('.dropdown-menu')).to have_content 'empty-branch'
end
......
......@@ -64,7 +64,7 @@ feature 'Master deletes tag' do
def delete_first_tag
page.within('.content') do
first('.btn-remove').click
accept_confirm { first('.btn-remove').click }
end
end
end
......@@ -45,7 +45,7 @@ feature 'Triggers', :js do
visit project_settings_ci_cd_path(@project)
# See if edit page has correct descrption
find('a[title="Edit"]').click
find('a[title="Edit"]').send_keys(:return)
expect(page.find('#trigger_description').value).to have_content 'trigger desc'
end
......@@ -54,7 +54,7 @@ feature 'Triggers', :js do
visit project_settings_ci_cd_path(@project)
# See if edit page opens, then fill in new description and save
find('a[title="Edit"]').click
find('a[title="Edit"]').send_keys(:return)
fill_in 'trigger_description', with: new_trigger_title
click_button 'Save trigger'
......@@ -70,7 +70,7 @@ feature 'Triggers', :js do
visit project_settings_ci_cd_path(@project)
# See if the trigger can be edited and description is blank
find('a[title="Edit"]').click
find('a[title="Edit"]').send_keys(:return)
expect(page.find('#trigger_description').value).to have_content ''
# See if trigger can be updated with description and saved successfully
......@@ -94,14 +94,15 @@ feature 'Triggers', :js do
scenario 'take trigger ownership' do
# See if "Take ownership" on trigger works post trigger creation
find('a.btn-trigger-take-ownership').click
page.accept_confirm do
first(:link, "Take ownership").send_keys(:return)
end
expect(page.find('.flash-notice')).to have_content 'Trigger was re-assigned.'
expect(page.find('.triggers-list')).to have_content trigger_title
expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
end
end
end
describe 'trigger "Revoke" workflow' do
before do
......@@ -116,13 +117,14 @@ feature 'Triggers', :js do
scenario 'revoke trigger' do
# See if "Revoke" on trigger works post trigger creation
find('a.btn-trigger-revoke').click
page.accept_confirm do
find('a.btn-trigger-revoke').send_keys(:return)
end
expect(page.find('.flash-notice')).to have_content 'Trigger removed'
expect(page).to have_selector('p.settings-message.text-center.append-bottom-default')
end
end
end
describe 'show triggers workflow' do
scenario 'contains trigger description placeholder' do
......
......@@ -79,7 +79,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
first_u2f_device = register_u2f_device
second_u2f_device = register_u2f_device(name: 'My other device')
click_on "Delete", match: :first
accept_confirm { click_on "Delete", match: :first }
expect(page).to have_content('Successfully deleted')
expect(page.body).not_to match(first_u2f_device.name)
......@@ -162,7 +162,6 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
@u2f_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_css('.sign-out-link', visible: false)
end
end
......@@ -174,23 +173,10 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
@u2f_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_css('.sign-out-link', visible: false)
end
end
it 'persists remember_me value via hidden field' do
gitlab_sign_in(user, remember: true)
@u2f_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
within 'div#js-authenticate-u2f' do
field = first('input#user_remember_me', visible: false)
expect(field.value).to eq '1'
end
end
describe "when a given U2F device has already been registered by another user" do
describe "but not the current user" do
it "does not allow logging in with that particular device" do
......@@ -205,7 +191,6 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
# Try authenticating user with the old U2F device
gitlab_sign_in(current_user)
@u2f_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_content('Authentication via U2F device failed')
end
end
......@@ -223,7 +208,6 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
# Try authenticating user with the same U2F device
gitlab_sign_in(current_user)
@u2f_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_css('.sign-out-link', visible: false)
end
......@@ -235,7 +219,6 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
unregistered_device = FakeU2fDevice.new(page, 'My device')
gitlab_sign_in(user)
unregistered_device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_content('Authentication via U2F device failed')
end
......@@ -260,7 +243,6 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
[first_device, second_device].each do |device|
gitlab_sign_in(user)
device.respond_to_u2f_authentication
expect(page).to have_content('We heard back from your U2F device')
expect(page).to have_css('.sign-out-link', visible: false)
......@@ -283,7 +265,9 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
it "deletes u2f registrations" do
visit profile_account_path
expect { click_on "Disable" }.to change { U2fRegistration.count }.by(-1)
expect do
accept_confirm { click_on "Disable" }
end.to change { U2fRegistration.count }.by(-1)
end
end
end
......
......@@ -21,16 +21,12 @@ feature 'User uploads file to note' do
end
context 'uploading is in progress' do
it 'shows "Cancel" button on uploading', :js do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
expect(page).to have_button('Cancel')
end
it 'cancels uploading on clicking to "Cancel" button', :js do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
click_button 'Cancel'
end
expect(page).to have_button('Attach a file')
expect(page).not_to have_button('Cancel')
......@@ -38,17 +34,21 @@ feature 'User uploads file to note' do
end
it 'shows "Attaching a file" message on uploading 1 file', :js do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching a file -')
end
end
it 'shows "Attaching 2 files" message on uploading 2 file', :js do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'video_sample.mp4'),
Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching 2 files -')
end
end
it 'shows error message, "retry" and "attach a new file" link a if file is too big', :js do
dropzone_file([Rails.root.join('spec', 'fixtures', 'video_sample.mp4')], 0.01)
......
......@@ -24,6 +24,7 @@ feature 'Users', :js do
user.reload
expect(user.reset_password_token).not_to be_nil
find('a[href="#login-pane"]').click
gitlab_sign_in(user)
expect(current_path).to eq root_path
......
......@@ -82,7 +82,7 @@ describe 'Project variables', :js do
it 'deletes variable' do
page.within('.variables-table') do
click_on 'Remove'
accept_confirm { click_on 'Remove' }
end
expect(page).not_to have_selector('variables-table')
......
......@@ -48,6 +48,9 @@ RSpec.configure do |config|
config.include Warden::Test::Helpers, type: :request
config.include LoginHelpers, type: :feature
config.include SearchHelpers, type: :feature
config.include CookieHelper, :js
config.include InputHelper, :js
config.include InspectRequests, :js
config.include WaitForRequests, :js
config.include LiveDebugger, :js
config.include StubConfiguration
......
# rubocop:disable Style/GlobalVars
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara/poltergeist'
require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
# Give CI some extra time
timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 60 : 30
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(
app,
js_errors: true,
timeout: timeout,
window_size: [1366, 768],
url_whitelist: %w[localhost 127.0.0.1],
url_blacklist: %w[.mp4 .png .gif .avi .bmp .jpg .jpeg],
phantomjs_options: [
'--load-images=yes'
]
Capybara.javascript_driver = :chrome
Capybara.register_driver :chrome do |app|
extra_args = []
extra_args << 'headless' unless ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: {
'args' => %w[no-sandbox disable-gpu --window-size=1240,1400] + extra_args
}
)
Capybara::Selenium::Driver
.new(app, browser: :chrome, desired_capabilities: capabilities)
end
Capybara.default_max_wait_time = timeout
......@@ -27,6 +27,10 @@ Capybara.ignore_hidden_elements = true
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
# From https://github.com/mattheworiordan/capybara-screenshot/issues/84#issuecomment-41219326
Capybara::Screenshot.register_driver(:chrome) do |driver, path|
driver.browser.save_screenshot(path)
end
RSpec.configure do |config|
config.before(:context, :js) do
......@@ -37,13 +41,23 @@ RSpec.configure do |config|
end
config.before(:example, :js) do
session = Capybara.current_session
allow(Gitlab::Application.routes).to receive(:default_url_options).and_return(
host: Capybara.current_session.server.host,
port: Capybara.current_session.server.port,
host: session.server.host,
port: session.server.port,
protocol: 'http')
# reset window size between tests
unless session.current_window.size == [1240, 1400]
session.current_window.resize_to(1240, 1400) rescue nil
end
end
config.after(:example, :js) do |example|
# prevent localstorage from introducing side effects based on test order
execute_script("localStorage.clear();")
# capybara/rspec already calls Capybara.reset_sessions! in an `after` hook,
# but `block_and_wait_for_requests_complete` is called before it so by
# calling it explicitely here, we prevent any new requests from being fired
......
......@@ -38,7 +38,7 @@ module CapybaraHelpers
# Simulate a browser restart by clearing the session cookie.
def clear_browser_session
page.driver.remove_cookie('_gitlab_session')
page.driver.browser.manage.delete_cookie('_gitlab_session')
end
end
......
# Helper for setting cookies in Selenium/WebDriver
#
module CookieHelper
def set_cookie(name, value, options = {})
# Selenium driver will not set cookies for a given domain when the browser is at `about:blank`.
# It also doesn't appear to allow overriding the cookie path. loading `/` is the most inclusive.
visit options.fetch(:path, '/') unless on_a_page?
page.driver.browser.manage.add_cookie(name: name, value: value, **options)
end
private
def on_a_page?
current_url = Capybara.current_session.driver.browser.current_url
current_url && current_url != '' && current_url != 'about:blank' && current_url != 'data:,'
end
end
......@@ -71,26 +71,28 @@ shared_examples 'discussion comments' do |resource_name|
expect(page).not_to have_selector menu_selector
find(toggle_selector).click
find('body').trigger 'click'
find('body').click
expect(page).not_to have_selector menu_selector
end
it 'clicking the ul padding or divider should not change the text' do
find(menu_selector).trigger 'click'
execute_script("document.querySelector('#{menu_selector}').click()")
# on issues page, the menu closes when clicking anywhere, on other pages it will
# remain open if clicking divider or menu padding, but should not change button action
if resource_name == 'issue'
expect(find(dropdown_selector)).to have_content 'Comment'
find(toggle_selector).click
find("#{menu_selector} .divider").trigger 'click'
execute_script("document.querySelector('#{menu_selector} .divider').click()")
else
find(menu_selector).trigger 'click'
execute_script("document.querySelector('#{menu_selector}').click()")
expect(page).to have_selector menu_selector
expect(find(dropdown_selector)).to have_content 'Comment'
find("#{menu_selector} .divider").trigger 'click'
execute_script("document.querySelector('#{menu_selector} .divider').click()")
expect(page).to have_selector menu_selector
end
......@@ -105,7 +107,12 @@ shared_examples 'discussion comments' do |resource_name|
end
it 'updates the submit button text and closes the dropdown' do
expect(find(dropdown_selector)).to have_content 'Start discussion'
# on issues page, the submit input is a <button>, on other pages it is <input>
if resource_name == 'issue'
expect(find(submit_selector)).to have_content 'Start discussion'
else
expect(find(submit_selector).value).to eq 'Start discussion'
end
expect(page).not_to have_selector menu_selector
end
......@@ -187,7 +194,12 @@ shared_examples 'discussion comments' do |resource_name|
end
it 'updates the submit button text and closes the dropdown' do
expect(find(dropdown_selector)).to have_content 'Comment'
# on issues page, the submit input is a <button>, on other pages it is <input>
if resource_name == 'issue'
expect(find(submit_selector)).to have_content 'Comment'
else
expect(find(submit_selector).value).to eq 'Comment'
end
expect(page).not_to have_selector menu_selector
end
......@@ -226,6 +238,7 @@ shared_examples 'discussion comments' do |resource_name|
describe "on a closed #{resource_name}" do
before do
find("#{form_selector} .js-note-target-close").click
wait_for_requests
find("#{form_selector} .note-textarea").send_keys('a')
end
......
......@@ -61,7 +61,7 @@ shared_examples 'issuable record that supports quick actions in its description
context 'with a note containing commands' do
it 'creates a note without the commands and interpret the commands accordingly' do
assignee = create(:user, username: 'bob')
write_note("Awesome!\n/assign @bob\n/label ~bug\n/milestone %\"ASAP\"")
write_note("Awesome!\n\n/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"")
expect(page).to have_content 'Awesome!'
expect(page).not_to have_content '/assign @bob'
......@@ -82,7 +82,7 @@ shared_examples 'issuable record that supports quick actions in its description
context 'with a note containing only commands' do
it 'does not create a note but interpret the commands accordingly' do
assignee = create(:user, username: 'bob')
write_note("/assign @bob\n/label ~bug\n/milestone %\"ASAP\"")
write_note("/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"")
expect(page).not_to have_content '/assign @bob'
expect(page).not_to have_content '/label ~bug'
......
......@@ -39,7 +39,7 @@ shared_examples 'reportable note' do |type|
end
def open_dropdown(dropdown)
dropdown.find('.more-actions-toggle').trigger('click')
dropdown.find('.more-actions-toggle').click
dropdown.find('.dropdown-menu li', match: :first)
end
end
......@@ -2,7 +2,7 @@ module MergeRequestDiffHelpers
def click_diff_line(line_holder, diff_side = nil)
line = get_line_components(line_holder, diff_side)
line[:content].hover
line[:num].find('.add-diff-note').trigger('click')
line[:num].find('.add-diff-note', visible: false).send_keys(:return)
end
def get_line_components(line_holder, diff_side = nil)
......
......@@ -2,7 +2,7 @@ module NoteInteractionHelpers
def open_more_actions_dropdown(note)
note_element = find("#note_#{note.id}")
note_element.find('.more-actions-toggle').trigger('click')
note_element.find('.more-actions-toggle').click
note_element.find('.more-actions .dropdown-menu li', match: :first)
end
end
# see app/assets/javascripts/test_utils/simulate_input.js
module InputHelper
def simulate_input(selector, input = '')
evaluate_script("window.simulateInput(#{selector.to_json}, #{input.to_json});")
end
end
require_relative './wait_for_requests'
module InspectRequests
extend self
include WaitForRequests
def inspect_requests(inject_headers: {})
Gitlab::Testing::RequestInspectorMiddleware.log_requests!(inject_headers)
yield
wait_for_all_requests
Gitlab::Testing::RequestInspectorMiddleware.requests
ensure
Gitlab::Testing::RequestInspectorMiddleware.stop_logging!
end
end
......@@ -12,6 +12,6 @@ module MobileHelpers
end
def resize_window(width, height)
page.driver.resize_window width, height
Capybara.current_session.current_window.resize_to(width, height)
end
end
......@@ -9,7 +9,7 @@ RSpec.shared_examples "protected tags > access control > CE" do
allowed_to_create_button = find(".js-allowed-to-create")
unless allowed_to_create_button.text == access_type_name
allowed_to_create_button.trigger('click')
allowed_to_create_button.click
find('.create_access_levels-container .dropdown-menu li', match: :first)
within('.create_access_levels-container .dropdown-menu') { click_on access_type_name }
end
......
......@@ -3,7 +3,7 @@ module QuickActionsHelpers
Sidekiq::Testing.fake! do
page.within('.js-main-target-form') do
fill_in 'note[note]', with: text
find('.js-comment-submit-button').trigger('click')
find('.js-comment-submit-button').click
end
end
end
......
......@@ -9,7 +9,7 @@ shared_examples "protected branches > access control > CE" do
allowed_to_push_button = find(".js-allowed-to-push")
unless allowed_to_push_button.text == access_type_name
allowed_to_push_button.trigger('click')
allowed_to_push_button.click
within(".dropdown.open .dropdown-menu") { click_on access_type_name }
end
end
......@@ -34,7 +34,7 @@ shared_examples "protected branches > access control > CE" do
within('.js-allowed-to-push-container') do
expect(first("li")).to have_content("Roles")
click_on access_type_name
find(:link, access_type_name).click
end
end
......@@ -79,7 +79,7 @@ shared_examples "protected branches > access control > CE" do
within('.js-allowed-to-merge-container') do
expect(first("li")).to have_content("Roles")
click_on access_type_name
find(:link, access_type_name).click
end
end
......
......@@ -80,6 +80,6 @@ end
def submit_time(quick_action)
fill_in 'note[note]', with: quick_action
find('.js-comment-submit-button').trigger('click')
find('.js-comment-submit-button').click
wait_for_requests
end
require_relative './wait_for_requests'
module WaitForRequests
extend self
# This is inspired by http://www.salsify.com/blog/engineering/tearing-capybara-ajax-tests
def block_and_wait_for_requests_complete
block_requests { wait_for_all_requests }
end
# Block all requests inside block with 503 response
def block_requests
Gitlab::Testing::RequestBlockerMiddleware.block_requests!
wait_for('pending requests complete') do
Gitlab::Testing::RequestBlockerMiddleware.num_active_requests.zero? && finished_all_requests?
yield
ensure
Gitlab::Testing::RequestBlockerMiddleware.allow_requests!
end
# Slow down requests inside block by injecting `sleep 0.2` before each response
def slow_requests
Gitlab::Testing::RequestBlockerMiddleware.slow_requests!
yield
ensure
Gitlab::Testing::RequestBlockerMiddleware.allow_requests!
end
# Wait for client-side AJAX requests
def wait_for_requests
wait_for('JS requests') { finished_all_requests? }
wait_for('JS requests complete') { finished_all_js_requests? }
end
# Wait for active Rack requests and client-side AJAX requests
def wait_for_all_requests
wait_for('pending requests complete') do
finished_all_rack_reqiests? &&
finished_all_js_requests?
end
end
private
def finished_all_requests?
def finished_all_rack_reqiests?
Gitlab::Testing::RequestBlockerMiddleware.num_active_requests.zero?
end
def finished_all_js_requests?
return true unless javascript_test?
finished_all_ajax_requests? &&
......
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