diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue index 280ad2951a7b83cad557c7016d0c50a4b2067d5c..23f1592cac159c8355b5dd75da6c2dd86325b148 100644 --- a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue +++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue @@ -111,7 +111,10 @@ export default { <span v-else class="gl-display-inline-flex gl-white-space-nowrap gl-max-w-full"> <tooltip-on-truncate :title="message" class="gl-text-truncate"> - <gl-icon :name="icon" /> <span data-testid="validationMsg">{{ message }}</span> + <gl-icon :name="icon" /> + <span data-qa-selector="validation_message_content" data-testid="validationMsg"> + {{ message }} + </span> </tooltip-on-truncate> <span v-if="!isEmpty" class="gl-flex-shrink-0 gl-pl-2"> <gl-link data-testid="learnMoreLink" :href="helpPath"> diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue index a418668933b1c6639b2d0140538d6838845505f6..c75b1d4bb1130dd9af612b024ff8a25f395c4b7d 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -146,6 +146,7 @@ export default { <template> <gl-tabs class="file-editor gl-mb-3" + data-qa-selector="file_editor_container" :query-param-name="$options.query.TAB_QUERY_PARAM" sync-active-tab-with-query-params > diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue index 64210576b2942b76e8b6df55437ee14495962de6..8daf85e2b2e89cf7f9a08e631b4e8e13fc1011d8 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue @@ -132,6 +132,7 @@ export default { :ref="$options.CONTAINER_REF" class="gl-bg-gray-10 gl-overflow-auto" data-testid="graph-container" + data-qa-selector="pipeline_graph_container" > <links-layer :pipeline-data="pipelineStages" @@ -147,7 +148,10 @@ export default { :key="`${stage.name}-${index}`" class="gl-flex-direction-column" > - <div class="gl-display-flex gl-align-items-center gl-w-full gl-px-9 gl-py-4 gl-mb-5"> + <div + class="gl-display-flex gl-align-items-center gl-w-full gl-px-9 gl-py-4 gl-mb-5" + data-qa-selector="stage_container" + > <stage-name :stage-name="stage.name" /> </div> <div :class="$options.jobWrapperClasses"> @@ -158,6 +162,7 @@ export default { :pipeline-id="$options.PIPELINE_ID" :is-hovered="highlightedJob === group.name" :is-faded-out="isFadedOut(group.name)" + data-qa-selector="job_container" @on-mouse-enter="setHoveredJob" @on-mouse-leave="removeHoveredJob" /> diff --git a/qa/qa/page/project/pipeline_editor/show.rb b/qa/qa/page/project/pipeline_editor/show.rb index c620eaac111079920d8e06b25a3d09e622dc1c97..8289039d4c5a4952eae086a600b40f420c1e41d1 100644 --- a/qa/qa/page/project/pipeline_editor/show.rb +++ b/qa/qa/page/project/pipeline_editor/show.rb @@ -32,6 +32,19 @@ class Show < QA::Page::Base element :commit_changes_button end + view 'app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue' do + element :validation_message_content + end + + view 'app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue' do + element :stage_container + element :job_container + end + + view 'app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue' do + element :file_editor_container + end + def initialize super @@ -80,8 +93,48 @@ def pipeline_id find_element(:pipeline_id_content).text.delete!('#').to_i end + def ci_syntax_validate_message + find_element(:validation_message_content).text + end + + def go_to_visualize_tab + go_to_tab('Visualize') + end + + def go_to_lint_tab + go_to_tab('Lint') + end + + def go_to_view_merged_yaml_tab + go_to_tab('View merged YAML') + end + + def has_source_editor? + has_element?(:source_editor_container) + end + + def has_stage?(name) + all_elements(:stage_container, minimum: 1).any? { |item| item.text.match(/#{name}/i) } + end + + def has_job?(name) + all_elements(:job_container, minimum: 1).any? { |item| item.text.match(/#{name}/i) } + end + + def tab_alert_message + within_element(:file_editor_container) do + find('.gl-alert-body').text + end + end + private + def go_to_tab(name) + within_element(:file_editor_container) do + find('.nav-item', text: name).click + end + end + # If the page thinks user has never opened pipeline editor before # It will expand pipeline editor sidebar by default # Collapse the sidebar if it is expanded diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8f3284662d710329ba077a27e6129edced51e620 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Verify' do + describe 'Pipeline editor' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'pipeline-editor-project' + end + end + + let!(:commit) do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files( + [ + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + stages: + - stage1 + - stage2 + + job1: + stage: stage1 + script: echo 'Done.' + + job2: + stage: stage2 + script: echo 'Done.' + YAML + } + ] + ) + end + end + + before do + Flow::Login.sign_in + project.visit! + Page::Project::Menu.perform(&:go_to_pipeline_editor) + end + + after do + project&.remove_via_api! + end + + context 'when CI has valid syntax' do + it 'shows valid validations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349128' do + Page::Project::PipelineEditor::Show.perform do |show| + aggregate_failures do + expect(show.ci_syntax_validate_message).to have_content('CI configuration is valid') + + show.go_to_visualize_tab + { stage1: 'job1', stage2: 'job2' }.each_pair do |stage, job| + expect(show).to have_stage(stage), "Pipeline graph does not have stage #{stage}." + expect(show).to have_job(job), "Pipeline graph does not have job #{job}." + end + + show.go_to_lint_tab + expect(show.tab_alert_message).to have_content('Syntax is correct') + + show.go_to_view_merged_yaml_tab + expect(show).to have_source_editor + end + end + end + end + + context 'when CI has invalid syntax' do + it 'shows invalid validations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349129' do + invalid_msg = 'syntax is invalid' + + Page::Project::PipelineEditor::Show.perform do |show| + show.write_to_editor(SecureRandom.hex(10)) + + aggregate_failures do + show.go_to_visualize_tab + expect(show.tab_alert_message).to have_content(invalid_msg) + + show.go_to_lint_tab + expect(show.tab_alert_message).to have_content('Syntax is incorrect') + + show.go_to_view_merged_yaml_tab + expect(show.tab_alert_message).to have_content(invalid_msg) + + expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid') + end + end + end + end + end + end +end