Commit c79d5189 authored by Dan Davison's avatar Dan Davison

Merge branch 'e2e-ci-cd-pipeline-dashboard' into 'master'

E2E test operations dashboard

See merge request gitlab-org/gitlab!35051
parents 216f8214 69439a02
...@@ -88,6 +88,7 @@ export default { ...@@ -88,6 +88,7 @@ export default {
type="search" type="search"
class="mb-3" class="mb-3"
autofocus autofocus
data-qa-selector="project_search_field"
@input="onInput" @input="onInput"
/> />
<div class="d-flex flex-column"> <div class="d-flex flex-column">
...@@ -107,6 +108,7 @@ export default { ...@@ -107,6 +108,7 @@ export default {
:project="project" :project="project"
:matcher="searchQuery" :matcher="searchQuery"
class="js-project-list-item" class="js-project-list-item"
data-qa-selector="project_list_item"
@click="projectClicked(project)" @click="projectClicked(project)"
/> />
</div> </div>
......
...@@ -26,16 +26,16 @@ ...@@ -26,16 +26,16 @@
%ul %ul
- if dashboard_nav_link?(:groups) - if dashboard_nav_link?(:groups)
%li.d-md-none %li.d-md-none
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups' do = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', data: { qa_selector: 'groups_link' } do
= _('Groups') = _('Groups')
- if dashboard_nav_link?(:activity) - if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity') do = nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity' do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', data: { qa_selector: 'activity_link' } do
= _('Activity') = _('Activity')
- if dashboard_nav_link?(:milestones) - if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones') do = nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones' do = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', data: { qa_selector: 'milestones_link' } do
= _('Milestones') = _('Milestones')
- if dashboard_nav_link?(:snippets) - if dashboard_nav_link?(:snippets)
......
...@@ -118,6 +118,7 @@ export default { ...@@ -118,6 +118,7 @@ export default {
:ok-title="s__('OperationsDashboard|Add projects')" :ok-title="s__('OperationsDashboard|Add projects')"
:ok-disabled="okDisabled" :ok-disabled="okDisabled"
ok-variant="success" ok-variant="success"
data-qa-selector="add_projects_modal"
@cancel="onCancel" @cancel="onCancel"
@ok="onOk" @ok="onOk"
> >
...@@ -146,6 +147,7 @@ export default { ...@@ -146,6 +147,7 @@ export default {
variant="success" variant="success"
category="primary" category="primary"
data-testid="add-projects-button" data-testid="add-projects-button"
data-qa-selector="add_projects_button"
> >
{{ s__('OperationsDashboard|Add projects') }} {{ s__('OperationsDashboard|Add projects') }}
</gl-button> </gl-button>
...@@ -185,6 +187,7 @@ export default { ...@@ -185,6 +187,7 @@ export default {
v-gl-modal="$options.modalId" v-gl-modal="$options.modalId"
variant="success" variant="success"
data-testid="add-projects-button" data-testid="add-projects-button"
data-qa-selector="add_projects_button"
> >
{{ s__('OperationsDashboard|Add projects') }} {{ s__('OperationsDashboard|Add projects') }}
</gl-button> </gl-button>
......
...@@ -113,7 +113,10 @@ export default { ...@@ -113,7 +113,10 @@ export default {
}; };
</script> </script>
<template> <template>
<div class="js-dashboard-project dashboard-card card border-0"> <div
class="js-dashboard-project dashboard-card card border-0"
data-qa-selector="dashboard_project_card"
>
<project-header <project-header
:project="project" :project="project"
:has-pipeline-failed="hasPipelineFailed" :has-pipeline-failed="hasPipelineFailed"
......
- if dashboard_nav_link?(:environments) - if dashboard_nav_link?(:environments)
= link_to operations_environments_path, class: 'dropdown-item' do = link_to operations_environments_path, class: 'dropdown-item', data: { qa_selector: 'environment_link' } do
= _('Environments') = _('Environments')
- if dashboard_nav_link?(:operations) - if dashboard_nav_link?(:operations)
= link_to operations_path, class: 'dropdown-item' do = link_to operations_path, class: 'dropdown-item', data: { qa_selector: 'operations_link' } do
= _('Operations') = _('Operations')
- if dashboard_nav_link?(:security) - if dashboard_nav_link?(:security)
= link_to security_root_path, class: 'dropdown-item' do = link_to security_root_path, class: 'dropdown-item', data: { qa_selector: 'security_link' } do
= _('Security') = _('Security')
...@@ -448,6 +448,7 @@ module QA ...@@ -448,6 +448,7 @@ module QA
autoload :ConfirmModal, 'qa/page/component/confirm_modal' autoload :ConfirmModal, 'qa/page/component/confirm_modal'
autoload :CustomMetric, 'qa/page/component/custom_metric' autoload :CustomMetric, 'qa/page/component/custom_metric'
autoload :DesignManagement, 'qa/page/component/design_management' autoload :DesignManagement, 'qa/page/component/design_management'
autoload :ProjectSelector, 'qa/page/component/project_selector'
module Issuable module Issuable
autoload :Common, 'qa/page/component/issuable/common' autoload :Common, 'qa/page/component/issuable/common'
......
...@@ -12,6 +12,8 @@ module QA ...@@ -12,6 +12,8 @@ module QA
end end
module Page module Page
autoload :OperationsDashboard, 'qa/ee/page/operations_dashboard'
module Component module Component
autoload :LicenseManagement, 'qa/ee/page/component/license_management' autoload :LicenseManagement, 'qa/ee/page/component/license_management'
autoload :SecureReport, 'qa/ee/page/component/secure_report' autoload :SecureReport, 'qa/ee/page/component/secure_report'
...@@ -49,6 +51,7 @@ module QA ...@@ -49,6 +51,7 @@ module QA
module Main module Main
autoload :Banner, 'qa/ee/page/main/banner' autoload :Banner, 'qa/ee/page/main/banner'
autoload :Menu, 'qa/ee/page/main/menu'
end end
module Admin module Admin
......
# frozen_string_literal: true
module QA
module EE
module Page
module Main
module Menu
extend QA::Page::PageConcern
def self.included(base)
super
base.view 'ee/app/views/dashboard/_nav_link_list.html.haml' do
element :environment_link
element :operations_link
element :security_link
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module EE
module Page
class OperationsDashboard < QA::Page::Base
include QA::Page::Component::ProjectSelector
include QA::Page::Component::CiBadgeLink
view 'ee/app/assets/javascripts/operations/components/dashboard/dashboard.vue' do
element :add_projects_button
element :add_projects_modal
end
view 'ee/app/assets/javascripts/operations/components/dashboard/project.vue' do
element :dashboard_project_card
end
def add_project(project_name)
open_add_project_modal
within_add_projects_modal do
fill_project_search_input(project_name)
select_project
find('button.btn.btn-success').click
end
end
def remove_all_projects
project_cards.each do |card|
card.find('button.btn.js-remove-button').click
end
end
def has_project_card?
has_element? :dashboard_project_card
end
def find_project_card_by_name(name)
project_cards.each do |card|
title = card.find('div.card-header').find('a.gl-link')[:title]
return card if title.include? name
end
end
def pipeline_status(project_card)
project_card.find(element_selector_css(:status_badge)).text
end
private
def project_cards
all_elements(:dashboard_project_card, minimum: 1)
end
def within_add_projects_modal
within_element(:add_projects_modal) do
yield
end
end
def open_add_project_modal
click_element :add_projects_button
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Component
module ProjectSelector
extend QA::Page::PageConcern
def self.included(base)
super
base.view 'app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue' do
element :project_search_field
element :project_list_item
end
end
def fill_project_search_input(project_name)
fill_element :project_search_field, project_name
end
def select_project
click_element :project_list_item
end
end
end
end
end
...@@ -22,6 +22,9 @@ module QA ...@@ -22,6 +22,9 @@ module QA
element :groups_dropdown, required: true element :groups_dropdown, required: true
element :more_dropdown element :more_dropdown
element :snippets_link element :snippets_link
element :groups_link
element :activity_link
element :milestones_link
end end
view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do
...@@ -53,10 +56,10 @@ module QA ...@@ -53,10 +56,10 @@ module QA
end end
end end
def go_to_snippets def go_to_more_dropdown_option(option_name)
within_top_menu do within_top_menu do
click_element :more_dropdown click_element :more_dropdown
click_element :snippets_link click_element option_name
end end
end end
...@@ -148,3 +151,5 @@ module QA ...@@ -148,3 +151,5 @@ module QA
end end
end end
end end
QA::Page::Main::Menu.prepend_if_ee('QA::EE::Page::Main::Menu')
...@@ -6,7 +6,9 @@ module QA ...@@ -6,7 +6,9 @@ module QA
it 'User creates a personal snippet' do it 'User creates a personal snippet' do
Flow::Login.sign_in Flow::Login.sign_in
Page::Main::Menu.perform(&:go_to_snippets) Page::Main::Menu.perform do |menu|
menu.go_to_more_dropdown_option(:snippets_link)
end
Resource::Snippet.fabricate_via_browser_ui! do |snippet| Resource::Snippet.fabricate_via_browser_ui! do |snippet|
snippet.title = 'Snippet title' snippet.title = 'Snippet title'
......
# frozen_string_literal: true
module QA
context 'Verify', :docker do
describe 'Operations Dashboard' do
let(:group) { Resource::Group.fabricate_via_api! }
let!(:runner) do
Resource::Runner.fabricate_via_api! do |runner|
runner.token = group.reload!.runners_token
runner.name = group.name
runner.tags = [group.name]
end
end
let(:project_with_tag) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-with-tag'
project.group = group
end
end
let(:project_without_tag) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-without-tag'
project.group = group
end
end
let(:project_without_ci) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-without-ci'
project.group = group
end
end
let(:project_with_failed_run) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-with-failed-run'
project.group = group
end
end
before do
Flow::Login.sign_in
setup_projects
Page::Main::Menu.perform do |menu|
menu.go_to_more_dropdown_option(:operations_link)
end
end
after do
runner.remove_via_api!
end
it 'has many pipelines with appropriate statuses' do
add_projects_to_board
EE::Page::OperationsDashboard.perform do |operation|
{
'project-with-tag' => 'passed',
'project-with-failed-run' => 'failed',
'project-without-tag' => 'pending',
'project-without-ci' => nil
}.each do |project_name, status|
project = operation.find_project_card_by_name(project_name)
if project_name == 'project-without-ci'
expect(project).to have_content('The branch for this project has no active pipeline configuration.')
next
end
expect(operation.pipeline_status(project)).to eq(status)
end
end
remove_projects
end
private
def commit_ci_file(project, file)
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([file])
end
end
def setup_projects
commit_ci_file(project_with_tag, ci_file_with_tag)
commit_ci_file(project_without_tag, ci_file_without_tag)
commit_ci_file(project_with_failed_run, ci_file_failed_run)
end
def add_projects_to_board
[project_with_tag, project_without_tag, project_without_ci, project_with_failed_run].each do |project|
EE::Page::OperationsDashboard.perform do |operation|
operation.add_project(project.name)
expect(operation).to have_project_card
end
end
end
def remove_projects
EE::Page::OperationsDashboard.perform do |operation|
operation.remove_all_projects
expect(operation).not_to have_project_card
end
end
def ci_file_with_tag
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
test-success:
tags: ["#{group.name}"]
script: echo 'OK'
YAML
}
end
def ci_file_without_tag
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
test-pending:
script: echo 'OK'
YAML
}
end
def ci_file_failed_run
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
test-fail:
tags: ["#{group.name}"]
script: exit 1
YAML
}
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment