From 6cc8db31c40a2ce90d7329016f22ee5d72a0d531 Mon Sep 17 00:00:00 2001 From: Sascha Eggenberger Date: Mon, 23 Oct 2023 12:21:44 +0200 Subject: [PATCH] Refactor status_helper to match Vue implementation --- app/helpers/ci/status_helper.rb | 91 ++++++++++-------- app/views/ci/status/_badge.html.haml | 13 --- app/views/ci/status/_icon.html.haml | 11 +-- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/ci/builds/_build.html.haml | 2 +- .../_generic_commit_status.html.haml | 2 +- .../issues/_related_branches.html.haml | 4 +- app/views/projects/jobs/_header.html.haml | 2 +- app/views/projects/tags/_tag.html.haml | 2 +- locale/gitlab.pot | 6 -- qa/qa/page/component/ci_icon.rb | 54 +++++++++++ spec/features/commits_spec.rb | 2 +- spec/features/dashboard/projects_spec.rb | 4 +- spec/helpers/ci/status_helper_spec.rb | 86 ++++++++--------- spec/views/ci/status/_badge.html.haml_spec.rb | 92 ------------------- .../commits/_commit.html.haml_spec.rb | 6 +- .../_related_branches.html.haml_spec.rb | 1 - 17 files changed, 159 insertions(+), 221 deletions(-) delete mode 100644 app/views/ci/status/_badge.html.haml create mode 100644 qa/qa/page/component/ci_icon.rb delete mode 100644 spec/views/ci/status/_badge.html.haml_spec.rb diff --git a/app/helpers/ci/status_helper.rb b/app/helpers/ci/status_helper.rb index c1e61e9d67244a..8bce1ccd7782c8 100644 --- a/app/helpers/ci/status_helper.rb +++ b/app/helpers/ci/status_helper.rb @@ -16,41 +16,41 @@ def ci_status_for_statuseable(subject) # rubocop:disable Metrics/CyclomaticComplexity def ci_icon_for_status(status, size: 16) - if detailed_status?(status) - return sprite_icon(status.icon, size: size) - end - icon_name = - case status - when 'success' - 'status_success' - when 'success-with-warnings' - 'status_warning' - when 'failed' - 'status_failed' - when 'pending' - 'status_pending' - when 'waiting_for_resource' - 'status_pending' - when 'preparing' - 'status_preparing' - when 'running' - 'status_running' - when 'play' - 'play' - when 'created' - 'status_created' - when 'skipped' - 'status_skipped' - when 'manual' - 'status_manual' - when 'scheduled' - 'status_scheduled' + if detailed_status?(status) + status.icon else - 'status_canceled' + case status + when 'success' + 'status_success' + when 'success-with-warnings' + 'status_warning' + when 'failed' + 'status_failed' + when 'pending' + 'status_pending' + when 'waiting-for-resource' + 'status_pending' + when 'preparing' + 'status_preparing' + when 'running' + 'status_running' + when 'play' + 'play' + when 'created' + 'status_created' + when 'skipped' + 'status_skipped' + when 'manual' + 'status_manual' + when 'scheduled' + 'status_scheduled' + else + 'status_canceled' + end end - sprite_icon(icon_name, size: size) + sprite_icon(icon_name, size: size, css_class: 'gl-icon') end # rubocop:enable Metrics/CyclomaticComplexity @@ -68,23 +68,34 @@ def render_commit_status(commit, status, ref: nil, tooltip_placement: 'left') project = commit.project path = pipelines_project_commit_path(project, commit, ref: ref) - render_status_with_link( + render_ci_icon( status, path, tooltip_placement: tooltip_placement, - icon_size: 16) + option_css_classes: 'gl-ml-3' + ) end - def render_status_with_link(status, path = nil, type: _('pipeline'), tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16) + def render_ci_icon( + status, + path = nil, + tooltip_placement: 'left', + option_css_classes: '', + container: 'body', + show_status_text: false + ) variant = badge_variant(status) - klass = "js-ci-status-badge-legacy #{ci_icon_class_for_status(status)} d-inline-flex gl-line-height-1 #{cssclass}" - title = "#{type.titleize}: #{ci_label_for_status(status)}" - data = { toggle: 'tooltip', placement: tooltip_placement, container: container, testid: 'ci-status-badge-legacy' } - badge_classes = 'gl-px-2 gl-ml-3' + klass = "js-ci-status-badge-legacy ci-status-icon #{ci_icon_class_for_status(status)} gl-rounded-full gl-justify-content-center gl-line-height-0" + title = "#{_('Pipeline')}: #{ci_label_for_status(status)}" + data = { toggle: 'tooltip', placement: tooltip_placement, container: container, testid: 'ci-icon' } + badge_classes = "ci-icon gl-p-2 #{option_css_classes}" gl_badge_tag(variant: variant, size: :md, href: path, class: badge_classes, title: title, data: data) do - content_tag :span, ci_icon_for_status(status, size: icon_size), - class: klass + if show_status_text + content_tag(:span, ci_icon_for_status(status), { class: klass }) + content_tag(:span, status.label, { class: 'gl-mx-2 gl-white-space-nowrap' }) + else + content_tag(:span, ci_icon_for_status(status), { class: klass }) + end end end diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml deleted file mode 100644 index e3b409dea762e8..00000000000000 --- a/app/views/ci/status/_badge.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- status = local_assigns.fetch(:status) -- link = local_assigns.fetch(:link, true) -- title = local_assigns.fetch(:title, nil) -- css_classes = "gl-display-inline-flex gl-align-items-center gl-gap-2 gl-line-height-0 gl-px-3 gl-py-2 gl-rounded-base ci-status ci-#{status.group} #{'has-tooltip' if title.present?}" - -- if link && status.has_details? - = link_to status.details_path, class: css_classes, title: title, data: { html: title.present? } do - = sprite_icon(status.icon) - = status.text -- else - %span{ class: css_classes, title: title, data: { html: title.present? } } - = sprite_icon(status.icon) - = status.text diff --git a/app/views/ci/status/_icon.html.haml b/app/views/ci/status/_icon.html.haml index 48e4472c117671..bcb83874bfb79e 100644 --- a/app/views/ci/status/_icon.html.haml +++ b/app/views/ci/status/_icon.html.haml @@ -1,10 +1,7 @@ - status = local_assigns.fetch(:status) -- tooltip_placement = local_assigns.fetch(:tooltip_placement, "left") - path = local_assigns.fetch(:path, status.has_details? ? status.details_path : nil) -- option_css_classes = local_assigns.fetch(:option_css_classes, '') -- css_classes = "gl-px-2 #{option_css_classes}" -- ci_css_classes = "ci-status-icon ci-status-icon-#{status.group} gl-line-height-1" -- title = s_("PipelineStatusTooltip|Pipeline: %{ci_status}") % {ci_status: status.label} +- tooltip_placement = local_assigns.fetch(:tooltip_placement, "left") +- option_css_classes = local_assigns.fetch(:option_css_classes, nil) +- show_status_text = local_assigns.fetch(:show_status_text, false) -= gl_badge_tag(variant: badge_variant(status), size: :md, href: path, class: css_classes, title: title, data: { toggle: 'tooltip', placement: tooltip_placement, testid: "ci-status-badge" }) do - = content_tag :span, sprite_icon(status.icon, size: 16), class: ci_css_classes += render_ci_icon(status, path, tooltip_placement: tooltip_placement, option_css_classes: option_css_classes, show_status_text: show_status_text) diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 61961172eb28a8..360e38afb5d16c 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -28,7 +28,7 @@ .pipeline-status.d-none.d-md-block< - if commit_status - = render 'ci/status/icon', size: 16, status: commit_status + = render 'ci/status/icon', status: commit_status - elsif show_commit_status .gl-display-inline-flex.gl-vertical-align-middle.gl-mr-3 %svg.s16 diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 4017db459a9bf6..a622895b4de158 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -14,7 +14,7 @@ %td.status -# Sending 'status' prevents calling the user relation inside the presenter, generating N+1, -# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68743 - = render "ci/status/badge", status: status, title: job.status_title(status) + = render "ci/status/icon", status: status, show_status_text: true %td - if can?(current_user, :read_build, job) diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml index a3569d41714ad2..e766536f12bf73 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -7,7 +7,7 @@ %tr.generic-commit-status{ class: ('retried' if retried) } %td.status - = render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user) + = render 'ci/status/icon', status: generic_commit_status.detailed_status(current_user), show_status_text: true %td = generic_commit_status.name diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml index ba5c41be7c665f..1a6edb288b5aa5 100644 --- a/app/views/projects/issues/_related_branches.html.haml +++ b/app/views/projects/issues/_related_branches.html.haml @@ -18,8 +18,8 @@ .item-contents.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-flex-grow-1.gl-min-h-7 .item-title.gl-display-flex.mb-xl-0.gl-min-w-0.gl-align-items-center - if branch[:pipeline_status].present? - %span.related-branch-ci-status - = render 'ci/status/icon', status: branch[:pipeline_status], option_css_classes: 'gl-display-block gl-mr-3' + %span.gl-mt-n2.gl-mb-n2.gl-mr-3 + = render 'ci/status/icon', status: branch[:pipeline_status] %span.related-branch-info %strong = link_to branch[:name], branch[:link], class: "ref-name" diff --git a/app/views/projects/jobs/_header.html.haml b/app/views/projects/jobs/_header.html.haml index 018ff09347593b..a77e8f2d0b471e 100644 --- a/app/views/projects/jobs/_header.html.haml +++ b/app/views/projects/jobs/_header.html.haml @@ -2,7 +2,7 @@ .content-block.build-header.top-area.page-content-header .header-content - = render 'ci/status/badge', status: @build.detailed_status(current_user), link: false, title: @build.status_title + = render 'ci/status/icon', status: @build.detailed_status(current_user), show_status_text: true %strong Job = link_to "##{@build.id}", project_job_path(@project, @build), class: 'js-build-id' diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index cc49ff9e293699..f04d6ab341fad8 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -30,7 +30,7 @@ = render partial: 'projects/commit/signature', object: tag.signature - if commit_status - = render 'ci/status/icon', size: 24, status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5' + = render 'ci/status/icon', status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5' - elsif @tag_pipeline_statuses && @tag_pipeline_statuses.any? .gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5 %svg.s24 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4ba49ace5c768d..0e28b52f02e8cf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -34701,9 +34701,6 @@ msgstr "" msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}" msgstr "" -msgid "PipelineStatusTooltip|Pipeline: %{ci_status}" -msgstr "" - msgid "PipelineWizardDefaultCommitMessage|Add %{filename}" msgstr "" @@ -57287,9 +57284,6 @@ msgstr "" msgid "personal access tokens" msgstr "" -msgid "pipeline" -msgstr "" - msgid "pipelineEditorWalkthrough|Let's do this!" msgstr "" diff --git a/qa/qa/page/component/ci_icon.rb b/qa/qa/page/component/ci_icon.rb new file mode 100644 index 00000000000000..1ddcc810f95547 --- /dev/null +++ b/qa/qa/page/component/ci_icon.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module CiIcon + extend QA::Page::PageConcern + + # rubocop:disable Layout/LineLength + COMPLETED_STATUSES = %w[Passed Failed Canceled Blocked Skipped Manual].freeze # excludes Created, Pending, Running + # rubocop:enable Layout/LineLength + INCOMPLETE_STATUSES = %w[Pending Created Running].freeze + + # e.g. def passed?(timeout: nil); status_badge == 'Passed'; end + COMPLETED_STATUSES.map do |status| + define_method "#{status.downcase}?" do |timeout: nil| + timeout ? completed?(timeout: timeout) : completed? + status_badge == status + end + + # has_passed? => passed? + # has_failed? => failed? + alias_method :"has_#{status.downcase}?", :"#{status.downcase}?" + end + + # e.g. def pending?; status_badge == 'Pending'; end + INCOMPLETE_STATUSES.map do |status| + define_method "#{status.downcase}?" do + status_badge == status + end + end + + def self.included(base) + super + + base.view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do + element 'ci-icon-text' + end + end + + def status_badge + # There are more than 1 on job details page + all_elements('ci-icon-text', minimum: 1).first.text + end + + def completed?(timeout: 60) + wait_until(reload: false, sleep_interval: 3.0, max_duration: timeout) do + COMPLETED_STATUSES.include?(status_badge) + end + end + end + end + end +end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 5f880af37dc383..1df1b7373d911f 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -81,7 +81,7 @@ it 'shows correct build status from default branch' do page.within("//li[@id='commit-#{pipeline.short_sha}']") do - expect(page).to have_css("[data-testid='ci-status-badge-legacy']") + expect(page).to have_css("[data-testid='ci-icon']") expect(page).to have_css('.ci-status-icon-success') end end diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 90ad6fcea25400..65436b35cd7708 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -153,7 +153,7 @@ page.within('[data-testid="project_controls"]') do expect(page).to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']") - expect(page).to have_css("[data-testid='ci-status-badge']") + expect(page).to have_css("[data-testid='ci-icon']") expect(page).to have_css('.ci-status-icon-success') expect(page).to have_link('Pipeline: passed') end @@ -165,7 +165,7 @@ page.within('[data-testid="project_controls"]') do expect(page).not_to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']") - expect(page).not_to have_css("[data-testid='ci-status-badge']") + expect(page).not_to have_css("[data-testid='ci-icon']") expect(page).not_to have_css('.ci-status-icon-success') expect(page).not_to have_link('Pipeline: passed') end diff --git a/spec/helpers/ci/status_helper_spec.rb b/spec/helpers/ci/status_helper_spec.rb index dc56ec96e3b487..18983c832625bf 100644 --- a/spec/helpers/ci/status_helper_spec.rb +++ b/spec/helpers/ci/status_helper_spec.rb @@ -8,18 +8,6 @@ let(:success_commit) { double("Ci::Pipeline", status: 'success') } let(:failed_commit) { double("Ci::Pipeline", status: 'failed') } - describe '#ci_icon_for_status' do - it 'renders to correct svg on success' do - expect(helper.ci_icon_for_status('success').to_s) - .to include 'status_success' - end - - it 'renders the correct svg on failure' do - expect(helper.ci_icon_for_status('failed').to_s) - .to include 'status_failed' - end - end - describe "#pipeline_status_cache_key" do it "builds a cache key for pipeline status" do pipeline_status = Gitlab::Cache::Ci::ProjectPipelineStatus.new( @@ -33,12 +21,8 @@ end end - describe "#render_status_with_link" do - subject { helper.render_status_with_link("success") } - - it "renders a passed status icon" do - is_expected.to include("