summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorddavison <ddavison@gitlab.com>2018-08-20 11:04:30 -0400
committerddavison <ddavison@gitlab.com>2018-08-20 11:04:30 -0400
commitc1c218252b2df207e564d57ce66d376906dfbe83 (patch)
tree9464a9c0b7de5e95642003dabc784e9e3bf9521f
parent1a7ecf03944050b9f0126bde9767481d7e8d3ec2 (diff)
downloadgitlab-ce-qa-consolidate-selector-pattern.tar.gz
-rw-r--r--app/helpers/qa_helper.rb25
-rw-r--r--app/views/devise/sessions/_new_base.html.haml6
-rw-r--r--app/views/devise/shared/_tabs_normal.html.haml4
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml4
-rw-r--r--app/views/layouts/header/_default.html.haml6
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml6
-rw-r--r--app/views/layouts/nav/groups_dropdown/_show.html.haml4
-rw-r--r--app/views/layouts/nav/projects_dropdown/_show.html.haml4
-rw-r--r--db/schema.rb4
-rw-r--r--qa/qa.rb1
-rw-r--r--qa/qa/page/base.rb4
-rw-r--r--qa/qa/page/element.rb19
-rw-r--r--qa/qa/page/main/login.rb36
-rw-r--r--qa/qa/page/menu/main.rb39
-rw-r--r--qa/qa/page/validatable.rb19
-rw-r--r--qa/qa/page/view.rb4
-rw-r--r--qa/qa/runtime/browser.rb1
17 files changed, 125 insertions, 61 deletions
diff --git a/app/helpers/qa_helper.rb b/app/helpers/qa_helper.rb
new file mode 100644
index 00000000000..57eee9c144c
--- /dev/null
+++ b/app/helpers/qa_helper.rb
@@ -0,0 +1,25 @@
+module QaHelper
+ # Define a data-qa attribute on the webpage
+ #
+ # Examples:
+ # qa('selector', 'username')
+ # qa('index', 1)
+ #
+ # Params:
+ # +attr+:: the data-qa-* attribute where * is the attribute to match
+ # +value+:: the value to set for data-qa-attr="value"
+ def qa(attr, value)
+ { "qa-#{attr}": value }
+ end
+
+ # Shortcut method(s) for QA
+ #
+ # Examples:
+ # data: qa_selector('test')
+ # data: qa_index(1)
+ [:qa_selector].each do |qa_method|
+ define_method qa_method do |pattern|
+ qa("#{qa_method.to_s.split('_')[1]}", pattern)
+ end
+ end
+end
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 0ee563ac066..9ac89013631 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -1,10 +1,10 @@
= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive'}) do |f|
.form-group
= f.label "Username or email", for: "user_login"
- = f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required."
+ = f.text_field :login, class: "form-control top", data: qa_selector('txt_username'), autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required."
.form-group
= f.label :password
- = f.password_field :password, class: "form-control bottom", required: true, title: "This field is required."
+ = f.password_field :password, class: "form-control bottom", data: qa_selector('txt_password'), required: true, title: "This field is required."
- if devise_mapping.rememberable?
.remember-me
%label{ for: "user_remember_me" }
@@ -17,4 +17,4 @@
= recaptcha_tags
.submit-container.move-submit-down
- = f.submit "Sign in", class: "btn btn-save"
+ = f.submit "Sign in", class: "btn btn-save", data: qa_selector('btn_signin')
diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml
index 284d4fa1b89..13382491f81 100644
--- a/app/views/devise/shared/_tabs_normal.html.haml
+++ b/app/views/devise/shared/_tabs_normal.html.haml
@@ -1,6 +1,6 @@
%ul.nav-links.new-session-tabs.nav-tabs.nav{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
- %a.nav-link.active{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in
+ %a.nav-link.active{ href: '#login-pane', data: { toggle: 'tab' }.merge(qa_selector('tab_standard')), role: 'tab' } Sign in
- if allow_signup?
%li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register
+ %a.nav-link{ href: '#register-pane', data: { toggle: 'tab' }.merge(qa_selector('tab_register')), role: 'tab' } Register
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 9ed05d6e3d0..dfa471bf761 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -11,7 +11,7 @@
= link_to s_("CurrentUser|Profile"), current_user, class: 'profile-link', data: { user: current_user.username }
- if current_user_menu?(:settings)
%li
- = link_to s_("CurrentUser|Settings"), profile_path
+ = link_to s_("CurrentUser|Settings"), profile_path, data: qa_selector('btn_settings')
- if current_user_menu?(:help)
%li
= link_to _("Help"), help_path
@@ -20,4 +20,4 @@
= render 'shared/user_dropdown_contributing_link'
- if current_user_menu?(:sign_out)
%li
- = link_to _("Sign out"), destroy_user_session_path, class: "sign-out-link"
+ = link_to _("Sign out"), destroy_user_session_path, class: "sign-out-link", data: qa_selector('btn_signout')
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index e8d31992149..a8880f4bce8 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,4 +1,4 @@
-%header.navbar.navbar-gitlab.qa-navbar.navbar-expand-sm
+%header.navbar.navbar-gitlab.navbar-expand-sm{data: qa_selector('navbar')}
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
@@ -50,9 +50,9 @@
- if header_link?(:user_dropdown)
%li.nav-item.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
- = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
+ = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar", data: qa_selector('user_avatar')
= sprite_icon('angle-down', css_class: 'caret-down')
- .dropdown-menu.dropdown-menu-right
+ .dropdown-menu.dropdown-menu-right{data: qa_selector('drp_user')}
= render 'layouts/header/current_user_dropdown'
- if header_link?(:admin_impersonation)
%li.nav-item.impersonation
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 5e467c862ab..18635f9e910 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -1,6 +1,6 @@
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown" }) do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: qa_selector('drp_projects') }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('angle-down', css_class: 'caret-down')
@@ -8,7 +8,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups qa-groups-dropdown" }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups", data: qa_selector('drp_groups') }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('angle-down', css_class: 'caret-down')
@@ -72,7 +72,7 @@
= sprite_icon('chart', size: 18)
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin area'), aria: { label: _('Admin area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to admin_root_path, class: 'admin-icon', title: _('Admin area'), aria: { label: _('Admin area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'}.merge(qa_selector('lnk_adminarea')) do
= sprite_icon('admin', size: 18)
- if Gitlab::Sherlock.enabled?
%li
diff --git a/app/views/layouts/nav/groups_dropdown/_show.html.haml b/app/views/layouts/nav/groups_dropdown/_show.html.haml
index 3ce1fa6bcca..a34ebdaf6fe 100644
--- a/app/views/layouts/nav/groups_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/groups_dropdown/_show.html.haml
@@ -1,9 +1,9 @@
- group_meta = { id: @group.id, name: @group.name, namespace: @group.full_name, web_url: group_path(@group), avatar_url: @group.avatar_url } if @group&.persisted?
.frequent-items-dropdown-container
- .frequent-items-dropdown-sidebar.qa-groups-dropdown-sidebar
+ .frequent-items-dropdown-sidebar{data: qa_selector('drp_groups_sidebar')}
%ul
= nav_link(path: 'dashboard/groups#index') do
- = link_to dashboard_groups_path, class: 'qa-your-groups-link' do
+ = link_to dashboard_groups_path, data: qa_selector('drp_groups_sidebar_lnk_yourgroups') do
= _('Your groups')
= nav_link(path: 'groups#explore') do
= link_to explore_groups_path do
diff --git a/app/views/layouts/nav/projects_dropdown/_show.html.haml b/app/views/layouts/nav/projects_dropdown/_show.html.haml
index f2170f71532..b9e37a73bb4 100644
--- a/app/views/layouts/nav/projects_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/projects_dropdown/_show.html.haml
@@ -1,9 +1,9 @@
- project_meta = { id: @project.id, name: @project.name, namespace: @project.full_name, web_url: project_path(@project), avatar_url: @project.avatar_url } if @project&.persisted?
.frequent-items-dropdown-container
- .frequent-items-dropdown-sidebar.qa-projects-dropdown-sidebar
+ .frequent-items-dropdown-sidebar{data: qa_selector('drp_projects_sidebar')}
%ul
= nav_link(path: 'dashboard/projects#index') do
- = link_to dashboard_projects_path, class: 'qa-your-projects-link' do
+ = link_to dashboard_projects_path, data: qa_selector('drp_projects_sidebar_lnk_yourprojects') do
= _('Your projects')
= nav_link(path: 'projects#starred') do
= link_to starred_dashboard_projects_path do
diff --git a/db/schema.rb b/db/schema.rb
index 1288a98745c..66d45115f7e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1204,6 +1204,7 @@ ActiveRecord::Schema.define(version: 20180808162000) do
t.integer "commits_count"
end
+ add_index "merge_request_diffs", ["id"], name: "tmp_partial_diff_id_with_files_index", where: "((state)::text <> ALL ((ARRAY['without_files'::character varying, 'empty'::character varying])::text[]))", using: :btree
add_index "merge_request_diffs", ["merge_request_id", "id"], name: "index_merge_request_diffs_on_merge_request_id_and_id", using: :btree
create_table "merge_request_metrics", force: :cascade do |t|
@@ -1764,6 +1765,7 @@ ActiveRecord::Schema.define(version: 20180808162000) do
end
add_index "redirect_routes", ["path"], name: "index_redirect_routes_on_path", unique: true, using: :btree
+ add_index "redirect_routes", ["path"], name: "index_redirect_routes_on_path_text_pattern_ops", using: :btree, opclasses: {"path"=>"varchar_pattern_ops"}
add_index "redirect_routes", ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id", using: :btree
create_table "releases", force: :cascade do |t|
@@ -2395,7 +2397,7 @@ ActiveRecord::Schema.define(version: 20180808162000) do
add_foreign_key "term_agreements", "users", on_delete: :cascade
add_foreign_key "timelogs", "issues", name: "fk_timelogs_issues_issue_id", on_delete: :cascade
add_foreign_key "timelogs", "merge_requests", name: "fk_timelogs_merge_requests_merge_request_id", on_delete: :cascade
- add_foreign_key "todos", "namespaces", column: "group_id", on_delete: :cascade
+ add_foreign_key "todos", "namespaces", column: "group_id", name: "fk_a27c483435", on_delete: :cascade
add_foreign_key "todos", "notes", name: "fk_91d1f47b13", on_delete: :cascade
add_foreign_key "todos", "projects", name: "fk_45054f9c45", on_delete: :cascade
add_foreign_key "todos", "users", column: "author_id", name: "fk_ccf0373936", on_delete: :cascade
diff --git a/qa/qa.rb b/qa/qa.rb
index 0b48cf58766..2a29a31da93 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -109,6 +109,7 @@ module QA
autoload :View, 'qa/page/view'
autoload :Element, 'qa/page/element'
autoload :Validator, 'qa/page/validator'
+ autoload :Validatable, 'qa/page/validatable'
module Main
autoload :Login, 'qa/page/main/login'
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 30e35bf7abb..10e790ff547 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -5,6 +5,7 @@ module QA
class Base
include Capybara::DSL
include Scenario::Actable
+ extend Validatable
extend SingleForwardable
def_delegators :evaluator, :view, :views
@@ -68,8 +69,9 @@ module QA
all(element_selector_css(name))
end
- def click_element(name)
+ def click_element(name, page = self)
find_element(name).click
+ page.validate_elements_present!
end
def fill_element(name, content)
diff --git a/qa/qa/page/element.rb b/qa/qa/page/element.rb
index 9944a39ce07..cc81b8884ca 100644
--- a/qa/qa/page/element.rb
+++ b/qa/qa/page/element.rb
@@ -1,19 +1,28 @@
module QA
module Page
class Element
- attr_reader :name
+ attr_reader :name, :required
- def initialize(name, pattern = nil)
+ def initialize(name, required = true)
@name = name
- @pattern = pattern || selector
+
+ unless !!required == required
+ warn "[QA] DEPRECATED TYPING: element #{name}, #{required} should be a boolean!"
+ end
+
+ @required = required
+ end
+
+ def required?
+ !!required
end
def selector
- "qa-#{@name.to_s.tr('_', '-')}"
+ /['"]data-qa-selector['"]: ['"]#{@name}['"]/
end
def selector_css
- ".#{selector}"
+ %Q([data-qa-selector="#{@name}"])
end
def expression
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 6cdfbd1c125..089bb49f5c9 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -3,31 +3,31 @@ module QA
module Main
class Login < Page::Base
view 'app/views/devise/passwords/edit.html.haml' do
- element :password_field, 'password_field :password'
- element :password_confirmation, 'password_field :password_confirmation'
- element :change_password_button, 'submit "Change your password"'
+ element :txt_password, false
+ element :txt_password, false
+ element :btn_change_password, false
end
view 'app/views/devise/sessions/_new_base.html.haml' do
- element :login_field, 'text_field :login'
- element :password_field, 'password_field :password'
- element :sign_in_button, 'submit "Sign in"'
+ element :txt_username
+ element :txt_password
+ element :btn_signin
end
view 'app/views/devise/sessions/_new_ldap.html.haml' do
- element :username_field, 'text_field_tag :username'
- element :password_field, 'password_field_tag :password'
- element :sign_in_button, 'submit_tag "Sign in"'
+ element :txt_username
+ element :txt_password
+ element :btn_signin
end
view 'app/views/devise/shared/_tabs_ldap.html.haml' do
- element :ldap_tab, "link_to server['label']"
- element :standard_tab, "link_to 'Standard'"
+ element :ldap_tab, false
+ element :standard_tab, false
end
view 'app/views/devise/shared/_tabs_normal.html.haml' do
- element :sign_in_tab, /nav-link.*login-pane.*Sign in/
- element :register_tab, /nav-link.*register-pane.*Register/
+ element :tab_standard
+ element :tab_register
end
def initialize
@@ -62,11 +62,11 @@ module QA
end
def switch_to_sign_in_tab
- click_on 'Sign in'
+ click_element :tab_standard
end
def switch_to_register_tab
- click_on 'Register'
+ click_element :tab_register
end
private
@@ -82,9 +82,9 @@ module QA
def sign_in_using_gitlab_credentials
click_link 'Standard' if page.has_content?('LDAP')
- fill_in :user_login, with: Runtime::User.name
- fill_in :user_password, with: Runtime::User.password
- click_button 'Sign in'
+ fill_element :txt_username, Runtime::User.name
+ fill_element :txt_password, Runtime::User.password
+ click_element :btn_signin, Page::Menu::Main
end
def set_initial_password_if_present
diff --git a/qa/qa/page/menu/main.rb b/qa/qa/page/menu/main.rb
index 36e7285f7b7..00c6508cefa 100644
--- a/qa/qa/page/menu/main.rb
+++ b/qa/qa/page/menu/main.rb
@@ -3,49 +3,54 @@ module QA
module Menu
class Main < Page::Base
view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
- element :user_sign_out_link, 'link_to _("Sign out")'
- element :settings_link, 'link_to s_("CurrentUser|Settings")'
+ element :btn_signout
+ element :btn_settings
end
view 'app/views/layouts/header/_default.html.haml' do
element :navbar
element :user_avatar
- element :user_menu, '.dropdown-menu'
+ element :drp_user
end
view 'app/views/layouts/nav/_dashboard.html.haml' do
- element :admin_area_link
- element :projects_dropdown
- element :groups_dropdown
+ element :lnk_adminarea
+ element :drp_projects
+ element :drp_groups
end
view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do
- element :projects_dropdown_sidebar
- element :your_projects_link
+ element :drp_projects_sidebar
+ element :drp_projects_sidebar_lnk_yourprojects
+ end
+
+ view 'app/views/layouts/nav/groups_dropdown/_show.html.haml' do
+ element :drp_groups_sidebar
+ element :drp_groups_sidebar_lnk_yourgroups
end
def go_to_groups
within_top_menu do
- click_element :groups_dropdown
+ click_element :drp_groups
end
- page.within('.qa-groups-dropdown-sidebar') do
- click_element :your_groups_link
+ page.within_element(:drp_groups_sidebar) do
+ click_element :drp_groups_sidebar_lnk_yourgroups
end
end
def go_to_projects
within_top_menu do
- click_element :projects_dropdown
+ click_element :drp_projects
end
- page.within('.qa-projects-dropdown-sidebar') do
- click_element :your_projects_link
+ page.within_element(:drp_projects_sidebar) do
+ click_element :drp_projects_sidebar_lnk_yourprojects
end
end
def go_to_admin_area
- within_top_menu { click_element :admin_area_link }
+ within_top_menu { click_element :lnk_adminarea }
end
def sign_out
@@ -68,7 +73,7 @@ module QA
private
def within_top_menu
- page.within('.qa-navbar') do
+ page.within_element(:navbar) do
yield
end
end
@@ -77,7 +82,7 @@ module QA
within_top_menu do
click_element :user_avatar
- page.within('.dropdown-menu') do
+ page.within_element(:drp_user) do
yield
end
end
diff --git a/qa/qa/page/validatable.rb b/qa/qa/page/validatable.rb
new file mode 100644
index 00000000000..1d885915f74
--- /dev/null
+++ b/qa/qa/page/validatable.rb
@@ -0,0 +1,19 @@
+module QA
+ module Page
+ module Validatable
+ PageValidationError = Class.new(StandardError)
+
+ def validate_elements_present!
+ # get elements from self
+ elements.each do |element|
+ if element.required?
+ base_page = self.new
+ unless base_page.using_wait_time(10) { base_page.page.has_selector?(element.selector_css) }
+ raise Validatable::PageValidationError, "#{element.name} expected on #{self.name} page"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/view.rb b/qa/qa/page/view.rb
index b2a2da4dbf3..9ee17d54c22 100644
--- a/qa/qa/page/view.rb
+++ b/qa/qa/page/view.rb
@@ -46,8 +46,8 @@ module QA
@elements = []
end
- def element(name, pattern = nil)
- @elements.push(Page::Element.new(name, pattern))
+ def element(name, required = true)
+ @elements.push(Page::Element.new(name, required))
end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 4c64270ce92..a1e19441123 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -29,6 +29,7 @@ module QA
def self.visit(address, page = nil, &block)
new.visit(address, page, &block)
+ page.validate_elements_present!
end
def self.configure!