Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-26 09:09:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-26 09:09:16 +0300
commitf803bba164be7079e79137bfe5a15ca5748aee94 (patch)
tree97bfcf3cc89a3e0f1703afdc02617fd3ba457830
parent4e5e33965fe2b22adfa26bc6c7babf67fe357207 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/show/index.js2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue320
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_details_header.vue4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js12
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js31
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue6
-rw-r--r--app/controllers/projects/pipelines_controller.rb5
-rw-r--r--app/helpers/ci/pipelines_helper.rb12
-rw-r--r--app/helpers/projects/pipeline_helper.rb2
-rw-r--r--app/presenters/ci/pipeline_presenter.rb38
-rw-r--r--app/views/projects/pipelines/_info.html.haml75
-rw-r--r--app/views/projects/pipelines/show.html.haml8
-rw-r--r--config/feature_flags/development/pipeline_details_header_vue.yml8
-rw-r--r--locale/gitlab.pot27
-rw-r--r--qa/qa/page/project/pipeline/show.rb24
-rw-r--r--spec/features/commits_spec.rb11
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb215
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb5
-rw-r--r--spec/frontend/pipelines/header_component_spec.js246
-rw-r--r--spec/frontend/pipelines/mock_data.js8
-rw-r--r--spec/frontend/sidebar/components/time_tracking/create_timelog_form_spec.js50
-rw-r--r--spec/helpers/ci/pipelines_helper_spec.rb22
-rw-r--r--spec/helpers/projects/pipeline_helper_spec.rb2
-rw-r--r--spec/presenters/ci/pipeline_presenter_spec.rb106
-rw-r--r--spec/views/projects/pipelines/show.html.haml_spec.rb1
26 files changed, 123 insertions, 1119 deletions
diff --git a/app/assets/javascripts/pages/projects/pipelines/show/index.js b/app/assets/javascripts/pages/projects/pipelines/show/index.js
index 44a384f03c6..d3f46b7e025 100644
--- a/app/assets/javascripts/pages/projects/pipelines/show/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/show/index.js
@@ -2,4 +2,4 @@ import initPipelineDetails from '~/pipelines/pipeline_details_bundle';
import initPipelines from '../init_pipelines';
initPipelines();
-initPipelineDetails(gon.features.pipelineDetailsHeaderVue);
+initPipelineDetails();
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
index 83cd64c17ed..5310165bc13 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -104,7 +104,7 @@ export default {
},
headerPipeline: {
query: getPipelineQuery,
- // this query is already being called in header_component.vue, which shares the same cache as this component
+ // this query is already being called in pipeline_details_header.vue, which shares the same cache as this component
// the skip here is to prevent sending double network requests on page load
skip() {
return !this.canRefetchHeaderPipeline;
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
deleted file mode 100644
index 27119419060..00000000000
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ /dev/null
@@ -1,320 +0,0 @@
-<script>
-import {
- GlAlert,
- GlButton,
- GlLoadingIcon,
- GlModal,
- GlModalDirective,
- GlTooltipDirective,
-} from '@gitlab/ui';
-import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
-import { __ } from '~/locale';
-import CiHeader from '~/vue_shared/components/header_ci_component.vue';
-import {
- LOAD_FAILURE,
- POST_FAILURE,
- DELETE_FAILURE,
- DEFAULT,
- BUTTON_TOOLTIP_RETRY,
- BUTTON_TOOLTIP_CANCEL,
-} from '../constants';
-import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutation.graphql';
-import deletePipelineMutation from '../graphql/mutations/delete_pipeline.mutation.graphql';
-import retryPipelineMutation from '../graphql/mutations/retry_pipeline.mutation.graphql';
-import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
-import { getQueryHeaders } from './graph/utils';
-
-const DELETE_MODAL_ID = 'pipeline-delete-modal';
-const POLL_INTERVAL = 10000;
-
-export default {
- name: 'PipelineHeaderSection',
- BUTTON_TOOLTIP_RETRY,
- BUTTON_TOOLTIP_CANCEL,
- pipelineCancel: 'pipelineCancel',
- pipelineRetry: 'pipelineRetry',
- finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
- components: {
- CiHeader,
- GlAlert,
- GlButton,
- GlLoadingIcon,
- GlModal,
- },
- directives: {
- GlModal: GlModalDirective,
- GlTooltip: GlTooltipDirective,
- },
- errorTexts: {
- [LOAD_FAILURE]: __('We are currently unable to fetch data for the pipeline header.'),
- [POST_FAILURE]: __('An error occurred while making the request.'),
- [DELETE_FAILURE]: __('An error occurred while deleting the pipeline.'),
- [DEFAULT]: __('An unknown error occurred.'),
- },
- inject: {
- graphqlResourceEtag: {
- default: '',
- },
- paths: {
- default: {},
- },
- pipelineId: {
- default: '',
- },
- pipelineIid: {
- default: '',
- },
- },
- modal: {
- id: DELETE_MODAL_ID,
- actionPrimary: {
- text: __('Delete pipeline'),
- attributes: {
- variant: 'danger',
- },
- },
- actionCancel: {
- text: __('Cancel'),
- },
- },
- apollo: {
- pipeline: {
- context() {
- return getQueryHeaders(this.graphqlResourceEtag);
- },
- query: getPipelineQuery,
- variables() {
- return {
- fullPath: this.paths.fullProject,
- iid: this.pipelineIid,
- };
- },
- update: (data) => data.project.pipeline,
- error() {
- this.reportFailure(LOAD_FAILURE);
- },
- pollInterval: POLL_INTERVAL,
- watchLoading(isLoading) {
- if (!isLoading) {
- // To ensure apollo has updated the cache,
- // we only remove the loading state in sync with GraphQL
- this.isCanceling = false;
- this.isRetrying = false;
- }
- },
- },
- },
- data() {
- return {
- pipeline: null,
- failureMessages: [],
- failureType: null,
- isCanceling: false,
- isRetrying: false,
- isDeleting: false,
- };
- },
- computed: {
- deleteModalConfirmationText() {
- return __(
- 'Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone.',
- );
- },
- hasError() {
- return this.failureType;
- },
- hasPipelineData() {
- return Boolean(this.pipeline);
- },
- isLoadingInitialQuery() {
- return this.$apollo.queries.pipeline.loading && !this.hasPipelineData;
- },
- status() {
- return this.pipeline?.status;
- },
- isFinished() {
- return this.$options.finishedStatuses.includes(this.status);
- },
- shouldRenderContent() {
- return !this.isLoadingInitialQuery && this.hasPipelineData;
- },
- failure() {
- switch (this.failureType) {
- case LOAD_FAILURE:
- return {
- text: this.$options.errorTexts[LOAD_FAILURE],
- variant: 'danger',
- };
- case POST_FAILURE:
- return {
- text: this.$options.errorTexts[POST_FAILURE],
- variant: 'danger',
- };
- case DELETE_FAILURE:
- return {
- text: this.$options.errorTexts[DELETE_FAILURE],
- variant: 'danger',
- };
- default:
- return {
- text: this.$options.errorTexts[DEFAULT],
- variant: 'danger',
- };
- }
- },
- canRetryPipeline() {
- const { retryable, userPermissions } = this.pipeline;
-
- return retryable && userPermissions.updatePipeline;
- },
- canCancelPipeline() {
- const { cancelable, userPermissions } = this.pipeline;
-
- return cancelable && userPermissions.updatePipeline;
- },
- },
- methods: {
- reportFailure(errorType, errorMessages = []) {
- this.failureType = errorType;
- this.failureMessages = errorMessages;
- },
- async postPipelineAction(name, mutation) {
- try {
- const {
- data: {
- [name]: { errors },
- },
- } = await this.$apollo.mutate({
- mutation,
- variables: { id: this.pipeline.id },
- });
-
- if (errors.length > 0) {
- this.isRetrying = false;
-
- this.reportFailure(POST_FAILURE, errors);
- } else {
- await this.$apollo.queries.pipeline.refetch();
- if (!this.isFinished) {
- this.$apollo.queries.pipeline.startPolling(POLL_INTERVAL);
- }
- }
- } catch {
- this.isRetrying = false;
-
- this.reportFailure(POST_FAILURE);
- }
- },
- cancelPipeline() {
- this.isCanceling = true;
- this.postPipelineAction(this.$options.pipelineCancel, cancelPipelineMutation);
- },
- retryPipeline() {
- this.isRetrying = true;
- this.postPipelineAction(this.$options.pipelineRetry, retryPipelineMutation);
- },
- async deletePipeline() {
- this.isDeleting = true;
- this.$apollo.queries.pipeline.stopPolling();
-
- try {
- const {
- data: {
- pipelineDestroy: { errors },
- },
- } = await this.$apollo.mutate({
- mutation: deletePipelineMutation,
- variables: {
- id: this.pipeline.id,
- },
- });
-
- if (errors.length > 0) {
- this.reportFailure(DELETE_FAILURE, errors);
- this.isDeleting = false;
- } else {
- redirectTo(setUrlFragment(this.paths.pipelinesPath, 'delete_success')); // eslint-disable-line import/no-deprecated
- }
- } catch {
- this.$apollo.queries.pipeline.startPolling(POLL_INTERVAL);
- this.reportFailure(DELETE_FAILURE);
- this.isDeleting = false;
- }
- },
- },
- DELETE_MODAL_ID,
-};
-</script>
-<template>
- <div class="js-pipeline-header-container">
- <gl-alert v-if="hasError" :title="failure.text" :variant="failure.variant" :dismissible="false">
- <div v-for="(failureMessage, index) in failureMessages" :key="`failure-message-${index}`">
- {{ failureMessage }}
- </div>
- </gl-alert>
- <ci-header
- v-if="shouldRenderContent"
- :status="pipeline.detailedStatus"
- :time="pipeline.createdAt"
- :user="pipeline.user"
- :item-id="pipelineId"
- item-name="Pipeline"
- >
- <gl-button
- v-if="canRetryPipeline"
- v-gl-tooltip
- :aria-label="$options.BUTTON_TOOLTIP_RETRY"
- :title="$options.BUTTON_TOOLTIP_RETRY"
- :loading="isRetrying"
- :disabled="isRetrying"
- variant="confirm"
- data-testid="retryPipeline"
- class="js-retry-button"
- @click="retryPipeline()"
- >
- {{ __('Retry') }}
- </gl-button>
-
- <gl-button
- v-if="canCancelPipeline"
- v-gl-tooltip
- :aria-label="$options.BUTTON_TOOLTIP_CANCEL"
- :title="$options.BUTTON_TOOLTIP_CANCEL"
- :loading="isCanceling"
- :disabled="isCanceling"
- class="gl-ml-3"
- variant="danger"
- data-testid="cancelPipeline"
- @click="cancelPipeline()"
- >
- {{ __('Cancel pipeline') }}
- </gl-button>
-
- <gl-button
- v-if="pipeline.userPermissions.destroyPipeline"
- v-gl-modal="$options.modal.id"
- :loading="isDeleting"
- :disabled="isDeleting"
- class="gl-ml-3"
- variant="danger"
- category="secondary"
- data-testid="deletePipeline"
- >
- {{ __('Delete') }}
- </gl-button>
- </ci-header>
- <gl-loading-icon v-if="isLoadingInitialQuery" size="lg" class="gl-mt-3 gl-mb-3" />
-
- <gl-modal
- :modal-id="$options.modal.id"
- :title="__('Delete pipeline')"
- :action-primary="$options.modal.actionPrimary"
- :action-cancel="$options.modal.actionCancel"
- @primary="deletePipeline()"
- >
- <p>
- {{ deleteModalConfirmationText }}
- </p>
- </gl-modal>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_details_header.vue b/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
index 8fe6707028a..fbd0fb7afbe 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_details_header.vue
@@ -387,7 +387,7 @@ export default {
</script>
<template>
- <div class="gl-my-4">
+ <div class="gl-my-4" data-testid="pipeline-details-header">
<gl-alert
v-if="hasError"
class="gl-mb-4"
@@ -447,6 +447,7 @@ export default {
class="gl-display-inline gl-mb-0"
:display-calendar-icon="false"
font-size="gl-font-md"
+ data-testid="pipeline-time-ago"
/>
</div>
</div>
@@ -527,7 +528,6 @@ export default {
:title="$options.i18n.detachedBadgeTooltip"
variant="info"
size="sm"
- data-qa-selector="merge_request_badge_tag"
>
{{ $options.i18n.detachedBadgeText }}
</gl-badge>
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 5b9bfd53b13..f9c027539f2 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -2,20 +2,18 @@ import VueRouter from 'vue-router';
import { createAlert } from '~/alert';
import { __ } from '~/locale';
import { pipelineTabName } from './constants';
-import { createPipelineHeaderApp, createPipelineDetailsHeaderApp } from './pipeline_details_header';
+import { createPipelineDetailsHeaderApp } from './pipeline_details_header';
import { apolloProvider } from './pipeline_shared_client';
const SELECTORS = {
- PIPELINE_HEADER: '#js-pipeline-header-vue',
PIPELINE_DETAILS_HEADER: '#js-pipeline-details-header-vue',
PIPELINE_TABS: '#js-pipeline-tabs',
};
-export default async function initPipelineDetailsBundle(flagEnabled) {
- const headerSelector = flagEnabled
- ? SELECTORS.PIPELINE_DETAILS_HEADER
- : SELECTORS.PIPELINE_HEADER;
- const headerApp = flagEnabled ? createPipelineDetailsHeaderApp : createPipelineHeaderApp;
+export default async function initPipelineDetailsBundle() {
+ const headerSelector = SELECTORS.PIPELINE_DETAILS_HEADER;
+
+ const headerApp = createPipelineDetailsHeaderApp;
const headerEl = document.querySelector(headerSelector);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index 807ef225edd..ab82c5837b7 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -1,41 +1,10 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { parseBoolean } from '~/lib/utils/common_utils';
-import PipelineHeader from './components/header_component.vue';
import PipelineDetailsHeader from './components/pipeline_details_header.vue';
Vue.use(VueApollo);
-export const createPipelineHeaderApp = (elSelector, apolloProvider, graphqlResourceEtag) => {
- const el = document.querySelector(elSelector);
-
- if (!el) {
- return;
- }
-
- const { fullPath, pipelineId, pipelineIid, pipelinesPath } = el.dataset;
- // eslint-disable-next-line no-new
- new Vue({
- el,
- components: {
- PipelineHeader,
- },
- apolloProvider,
- provide: {
- paths: {
- fullProject: fullPath,
- graphqlResourceEtag,
- pipelinesPath,
- },
- pipelineId,
- pipelineIid,
- },
- render(createElement) {
- return createElement('pipeline-header', {});
- },
- });
-};
-
export const createPipelineDetailsHeaderApp = (elSelector, apolloProvider, graphqlResourceEtag) => {
const el = document.querySelector(elSelector);
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 28baabbdb81..1adda905006 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -114,11 +114,7 @@ export default {
</script>
<template>
- <header
- class="page-content-header gl-md-display-flex gl-min-h-7"
- data-qa-selector="pipeline_header"
- data-testid="ci-header-content"
- >
+ <header class="page-content-header gl-md-display-flex gl-min-h-7" data-testid="ci-header-content">
<section class="header-main-content gl-mr-3">
<ci-badge-link class="gl-mr-3" :status="status" />
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 98e6459b543..a96ee2215c2 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -22,7 +22,6 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
before_action :reject_if_build_artifacts_size_refreshing!, only: [:destroy]
- before_action :push_frontend_feature_flags, only: [:show, :builds, :dag, :failures, :test_report]
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }
@@ -350,10 +349,6 @@ class Projects::PipelinesController < Projects::ApplicationController
def tracking_project_source
project
end
-
- def push_frontend_feature_flags
- push_frontend_feature_flag(:pipeline_details_header_vue, @project)
- end
end
Projects::PipelinesController.prepend_mod_with('Projects::PipelinesController')
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index b222ca5538d..a034e4331c0 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -68,18 +68,6 @@ module Ci
]
end
- def has_pipeline_badges?(pipeline)
- pipeline.schedule? ||
- pipeline.child? ||
- pipeline.latest? ||
- pipeline.merge_train_pipeline? ||
- pipeline.has_yaml_errors? ||
- pipeline.failure_reason? ||
- pipeline.auto_devops_source? ||
- pipeline.detached_merge_request_pipeline? ||
- pipeline.stuck?
- end
-
def pipelines_list_data(project, list_url)
artifacts_endpoint_placeholder = ':pipeline_artifacts_id'
diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb
index caebbd5250e..42e8e44c94c 100644
--- a/app/helpers/projects/pipeline_helper.rb
+++ b/app/helpers/projects/pipeline_helper.rb
@@ -44,7 +44,7 @@ module Projects
failed: pipeline.failure_reason?.to_s,
auto_devops: pipeline.auto_devops_source?.to_s,
detached: pipeline.detached_merge_request_pipeline?.to_s,
- stuck: pipeline.stuck?,
+ stuck: pipeline.stuck?.to_s,
ref_text: pipeline.ref_text
}
end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 3aba5a2c7ed..762ee0d92cd 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -65,28 +65,6 @@ module Ci
'%.2f' % pipeline.coverage
end
- def ref_text_legacy
- if pipeline.detached_merge_request_pipeline?
- _("for %{link_to_merge_request} with %{link_to_merge_request_source_branch}")
- .html_safe % {
- link_to_merge_request: link_to_merge_request,
- link_to_merge_request_source_branch: link_to_merge_request_source_branch
- }
- elsif pipeline.merged_result_pipeline?
- _("for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}")
- .html_safe % {
- link_to_merge_request: link_to_merge_request,
- link_to_merge_request_source_branch: link_to_merge_request_source_branch,
- link_to_merge_request_target_branch: link_to_merge_request_target_branch
- }
- elsif pipeline.ref && pipeline.ref_exists?
- _("for %{link_to_pipeline_ref}")
- .html_safe % { link_to_pipeline_ref: link_to_pipeline_ref }
- elsif pipeline.ref
- _("for %{ref}").html_safe % { ref: plain_ref_name }
- end
- end
-
def ref_text
if pipeline.detached_merge_request_pipeline?
_("Related merge request %{link_to_merge_request} to merge %{link_to_merge_request_source_branch}")
@@ -109,22 +87,6 @@ module Ci
end
end
- def all_related_merge_request_text(limit: nil)
- if all_related_merge_requests.none?
- _("No related merge requests found.")
- else
- (_("%{count} related %{pluralized_subject}: %{links}") % {
- count: all_related_merge_requests.count,
- pluralized_subject: n_('merge request', 'merge requests', all_related_merge_requests.count),
- links: all_related_merge_request_links(limit: limit).join(', ')
- }).html_safe
- end
- end
-
- def has_many_merge_requests?
- all_related_merge_requests.count > 1
- end
-
def link_to_pipeline_ref
ApplicationController.helpers.link_to(pipeline.ref,
project_commits_path(pipeline.project, pipeline.ref),
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
deleted file mode 100644
index 753bb77e755..00000000000
--- a/app/views/projects/pipelines/_info.html.haml
+++ /dev/null
@@ -1,75 +0,0 @@
-- if @pipeline.name
- .gl-border-t.gl-p-5.gl-px-0
- %h3.gl-m-0.gl-text-body
- = @pipeline.name
-- else
- .commit-box
- %h3.commit-title
- = markdown(commit.title, pipeline: :single_line)
- - if commit.description.present?
- %pre.commit-description<
- = preserve(markdown(commit.description, pipeline: :single_line))
-
-.info-well
- .well-segment.pipeline-info{ class: "gl-align-items-baseline! gl-flex-direction-column" }
- %div
- .icon-container
- = sprite_icon('clock', css_class: 'gl-top-0!')
- = n_('%d job', '%d jobs', @pipeline.total_size) % @pipeline.total_size
- = @pipeline.ref_text_legacy
- - if @pipeline.finished_at
- - duration = time_interval_in_words(@pipeline.duration)
- - queued_duration = time_interval_in_words(@pipeline.queued_duration)
- %span.gl-pl-7{ 'data-testid': 'pipeline-stats-text' }
- = render_if_exists 'projects/pipelines/pipeline_stats_text', duration: duration, pipeline: @pipeline, queued_duration: queued_duration
-
- - if has_pipeline_badges?(@pipeline)
- .well-segment
- .icon-container
- = sprite_icon('flag', css_class: 'gl-top-0!')
- - if @pipeline.schedule?
- = gl_badge_tag _('Scheduled'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-scheduled', title: _('This pipeline was triggered by a schedule.') }
- - if @pipeline.child?
- - text = sprintf(s_('Pipelines|Child pipeline (%{link_start}parent%{link_end})'), { link_start: "<a href='#{pipeline_path(@pipeline.triggered_by_pipeline)}' class='text-underline'>", link_end: "</a>"}).html_safe
- = gl_badge_tag text, { variant: :info, size: :sm }, { class: 'js-pipeline-child has-tooltip', title: s_("Pipelines|This is a child pipeline within the parent pipeline") }
- - if @pipeline.latest?
- = gl_badge_tag s_('Pipelines|latest'), { variant: :success, size: :sm }, { class: 'js-pipeline-url-latest has-tooltip', title: _("Latest pipeline for the most recent commit on this branch") }
- - if @pipeline.merge_train_pipeline?
- = gl_badge_tag s_('Pipelines|merge train'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-train has-tooltip', title: s_("Pipelines|This pipeline ran on the contents of this merge request combined with the contents of all other merge requests queued for merging into the target branch.") }
- - if @pipeline.has_yaml_errors?
- = gl_badge_tag s_('Pipelines|yaml invalid'), { variant: :danger, size: :sm }, { class: 'js-pipeline-url-yaml has-tooltip', title: @pipeline.yaml_errors }
- - if @pipeline.failure_reason?
- = gl_badge_tag s_('Pipelines|error'), { variant: :danger, size: :sm }, { class: 'js-pipeline-url-failure has-tooltip', title: @pipeline.failure_reason }
- - if @pipeline.auto_devops_source?
- - popover_title_text = html_escape(_('This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}')) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
- - popover_content_url = help_page_path('topics/autodevops/index.md')
- - popover_content_text = _('Learn more about Auto DevOps')
- = gl_badge_tag s_('Pipelines|Auto DevOps'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-autodevops', href: "#", tabindex: "0", role: "button", data: { container: 'body', toggle: 'popover', placement: 'top', html: 'true', triggers: 'focus', title: "<div class='gl-font-weight-normal gl-line-height-normal'>#{popover_title_text}</div>", content: "<a href='#{popover_content_url}' target='_blank' rel='noopener noreferrer nofollow'>#{popover_content_text}</a>" } }
- - if @pipeline.detached_merge_request_pipeline?
- = gl_badge_tag s_('Pipelines|merge request'), { variant: :info, size: :sm }, { class: 'js-pipeline-url-mergerequest has-tooltip', data: { qa_selector: 'merge_request_badge_tag' }, title: s_("Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch.") }
- - if @pipeline.stuck?
- = gl_badge_tag s_('Pipelines|stuck'), { variant: :warning, size: :sm }, { class: 'js-pipeline-url-stuck has-tooltip' }
-
- .well-segment{ 'data-testid': 'commit-row' }
- .icon-container.commit-icon
- = sprite_icon('commit', css_class: 'gl-top-0!')
- - if @pipeline.name
- = markdown(commit.title, pipeline: :single_line)
- = clipboard_button(text: @pipeline.sha, title: _("Copy commit SHA"))
- = link_to commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha"
- - else
- = link_to commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha"
- = clipboard_button(text: @pipeline.sha, title: _("Copy commit SHA"))
-
- .well-segment.related-merge-request-info
- .icon-container
- = sprite_icon("git-merge", css_class: 'gl-top-0!')
- %span.related-merge-requests
- %span.js-truncated-mr-list
- = @pipeline.all_related_merge_request_text(limit: 1)
- - if @pipeline.has_many_merge_requests?
- = link_to("#", class: "js-toggle-mr-list") do
- %span.text-expander
- = sprite_icon('ellipsis_h', size: 12)
- %span.js-full-mr-list.hide
- = @pipeline.all_related_merge_request_text
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 46e1cd07a17..bdf09e5356f 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -9,16 +9,10 @@
- add_page_startup_graphql_call('pipelines/get_pipeline_details', { projectPath: @project.full_path, iid: @pipeline.iid })
.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } }
- - if Feature.enabled?(:pipeline_details_header_vue, @project)
- #js-pipeline-details-header-vue{ data: js_pipeline_details_header_data(@project, @pipeline) }
- - else
- #js-pipeline-header-vue.pipeline-header-container{ data: { full_path: @project.full_path, graphql_resource_etag: graphql_etag_pipeline_path(@pipeline), pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id, pipelines_path: project_pipelines_path(@project) } }
+ #js-pipeline-details-header-vue{ data: js_pipeline_details_header_data(@project, @pipeline) }
= render_if_exists 'projects/pipelines/cc_validation_required_alert', pipeline: @pipeline
- - if @pipeline.commit.present? && !Feature.enabled?(:pipeline_details_header_vue, @project)
- = render "projects/pipelines/info", commit: @pipeline.commit
-
- if pipeline_has_errors
= render Pajamas::AlertComponent.new(title: s_('Pipelines|Unable to create pipeline'),
variant: :danger,
diff --git a/config/feature_flags/development/pipeline_details_header_vue.yml b/config/feature_flags/development/pipeline_details_header_vue.yml
deleted file mode 100644
index 4e4968bc686..00000000000
--- a/config/feature_flags/development/pipeline_details_header_vue.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pipeline_details_header_vue
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120634
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/411442
-milestone: '16.0'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ba7595da236..6e84e9d2e86 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -658,9 +658,6 @@ msgid_plural "%{count} projects"
msgstr[0] ""
msgstr[1] ""
-msgid "%{count} related %{pluralized_subject}: %{links}"
-msgstr ""
-
msgid "%{count} selected"
msgstr ""
@@ -30729,9 +30726,6 @@ msgstr ""
msgid "No regions configured"
msgstr ""
-msgid "No related merge requests found."
-msgstr ""
-
msgid "No repository"
msgstr ""
@@ -33733,9 +33727,6 @@ msgstr ""
msgid "Pipelines|Child pipeline (%{linkStart}parent%{linkEnd})"
msgstr ""
-msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
-msgstr ""
-
msgid "Pipelines|Clear runner caches"
msgstr ""
@@ -33901,9 +33892,6 @@ msgstr ""
msgid "Pipelines|This GitLab CI configuration is valid."
msgstr ""
-msgid "Pipelines|This is a child pipeline within the parent pipeline"
-msgstr ""
-
msgid "Pipelines|This pipeline is stuck"
msgstr ""
@@ -47205,9 +47193,6 @@ msgstr ""
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
msgstr ""
-msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
-msgstr ""
-
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
msgstr ""
@@ -54330,18 +54315,6 @@ msgstr[1] ""
msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
-msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
-msgstr ""
-
-msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
-
-msgid "for %{link_to_pipeline_ref}"
-msgstr ""
-
-msgid "for %{ref}"
-msgstr ""
-
msgid "for Workspace is required to be public"
msgstr ""
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 41c61aaecc8..c955b4d933d 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -7,19 +7,8 @@ module QA
class Show < QA::Page::Base
include Component::CiBadgeLink
- # TODO: remove element with FF pipeline_details_header_vue removal
- view 'app/assets/javascripts/vue_shared/components/header_ci_component.vue' do
- element :pipeline_header
- end
-
- # TODO: make this a requirement at page render - `required: true`
- # together with FF pipeline_details_header_vue removal
view 'app/assets/javascripts/pipelines/components/pipeline_details_header.vue' do
- element :pipeline_details_header
- end
-
- view 'app/views/projects/pipelines/_info.html.haml' do
- element :merge_request_badge_tag
+ element :pipeline_details_header, required: true
end
view 'app/assets/javascripts/pipelines/components/graph/graph_component.vue' do
@@ -63,20 +52,11 @@ module QA
end
def running?(wait: 0)
- # TODO: remove condition check together with FF pipeline_details_header_vue removal
- # issue: https://gitlab.com/gitlab-org/gitlab/-/issues/411442
-
- element = has_element?(:pipeline_details_header) ? :pipeline_details_header : :pipeline_header
-
- within_element(element) do
+ within_element(:pipeline_details_header) do
page.has_content?('running', wait: wait)
end
end
- def has_merge_request_badge_tag?
- has_element?(:merge_request_badge_tag)
- end
-
def has_build?(name, status: :success, wait: nil)
if status
within_element(:job_item_container, text: name) do
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 6d07c68dd13..b72e08b854e 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -8,7 +8,6 @@ RSpec.describe 'Commits', feature_category: :source_code_management do
describe 'CI' do
before do
- stub_feature_flags(pipeline_details_header_vue: false)
sign_in(user)
stub_ci_pipeline_to_return_yaml_file
end
@@ -41,7 +40,11 @@ RSpec.describe 'Commits', feature_category: :source_code_management do
wait_for_requests
end
- it { expect(page).to have_content pipeline.sha[0..7] }
+ it 'contains commit short id' do
+ page.within('[data-testid="pipeline-details-header"]') do
+ expect(page).to have_content pipeline.sha[0..7]
+ end
+ end
it 'contains generic commit status build' do
page.within('[data-testid="jobs-tab-table"]') do
@@ -92,7 +95,6 @@ RSpec.describe 'Commits', feature_category: :source_code_management do
it 'shows pipeline data' do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
end
end
@@ -120,7 +122,7 @@ RSpec.describe 'Commits', feature_category: :source_code_management do
describe 'Cancel build' do
it 'cancels build', :js, :sidekiq_might_not_need_inline do
visit pipeline_path(pipeline)
- find('[data-testid="cancelPipeline"]').click
+ find('[data-testid="cancel-pipeline"]').click
expect(page).to have_content 'canceled'
end
end
@@ -136,7 +138,6 @@ RSpec.describe 'Commits', feature_category: :source_code_management do
it 'renders header' do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
expect(page).not_to have_link('Cancel pipeline')
expect(page).not_to have_link('Retry')
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 6d96d77519c..1f60996fac8 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -13,7 +13,6 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
let(:role) { :developer }
before do
- stub_feature_flags(pipeline_details_header_vue: false)
sign_in(user)
project.add_role(user, role)
end
@@ -93,9 +92,9 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows the pipeline information' do
visit_pipeline
- within '.pipeline-info' do
- expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for #{pipeline.ref}")
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content("For #{pipeline.ref}")
+ expect(page).to have_content("#{pipeline.statuses.count} Jobs")
expect(page).to have_link(pipeline.ref,
href: project_commits_path(pipeline.project, pipeline.ref))
end
@@ -104,13 +103,25 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'displays pipeline name instead of commit title' do
visit_pipeline
- within 'h3' do
+ within '[data-testid="pipeline-details-header"]' do
expect(page).to have_content(pipeline.name)
+ expect(page).to have_content(project.commit.short_id)
+ expect(page).not_to have_selector('[data-testid="pipeline-commit-title"]')
end
+ end
- within '.well-segment[data-testid="commit-row"]' do
- expect(page).to have_content(project.commit.title)
- expect(page).to have_content(project.commit.short_id)
+ context 'without pipeline name' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user)
+ end
+
+ it 'displays commit title' do
+ visit_pipeline
+
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content(project.commit.title)
+ expect(page).not_to have_selector('[data-testid="pipeline-name"]')
+ end
end
end
@@ -126,110 +137,23 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
context 'pipeline has finished' do
- it 'shows pipeline stats with flag on' do
+ it 'shows time ago' do
visit project_pipeline_path(project, finished_pipeline)
- within '.pipeline-info' do
- expect(page).to have_content("in #{finished_pipeline.duration} seconds")
- expect(page).to have_content("and was queued for #{finished_pipeline.queued_duration} seconds")
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_selector('[data-testid="pipeline-time-ago"]')
end
end
end
context 'pipeline has not finished' do
- it 'does not show pipeline stats' do
- visit_pipeline
-
- within '.pipeline-info' do
- expect(page).not_to have_selector('[data-testid="pipeline-stats-text"]')
- end
- end
- end
- end
-
- describe 'related merge requests' do
- context 'when there are no related merge requests' do
- it 'shows a "no related merge requests" message' do
- visit_pipeline
-
- within '.related-merge-request-info' do
- expect(page).to have_content('No related merge requests found.')
- end
- end
- end
-
- context 'when there is one related merge request' do
- let!(:merge_request) do
- create(:merge_request,
- source_project: project,
- source_branch: pipeline.ref)
- end
-
- it 'shows a link to the merge request' do
- visit_pipeline
-
- within '.related-merge-requests' do
- expect(page).to have_content('1 related merge request: ')
- expect(page).to have_selector('.js-truncated-mr-list')
- expect(page).to have_link("#{merge_request.to_reference} #{merge_request.title}")
-
- expect(page).not_to have_selector('.js-full-mr-list')
- expect(page).not_to have_selector('.text-expander')
- end
- end
- end
-
- context 'when there are two related merge requests' do
- let!(:merge_request1) do
- create(:merge_request,
- source_project: project,
- source_branch: pipeline.ref)
- end
-
- let!(:merge_request2) do
- create(:merge_request,
- source_project: project,
- source_branch: pipeline.ref,
- target_branch: 'fix')
- end
-
- it 'links to the most recent related merge request' do
+ it 'does not show time ago' do
visit_pipeline
- within '.related-merge-requests' do
- expect(page).to have_content('2 related merge requests: ')
- expect(page).to have_link("#{merge_request2.to_reference} #{merge_request2.title}")
- expect(page).to have_selector('.text-expander')
- expect(page).to have_selector('.js-full-mr-list', visible: false)
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).not_to have_selector('[data-testid="pipeline-time-ago"]')
end
end
-
- it 'expands to show links to all related merge requests' do
- visit_pipeline
-
- within '.related-merge-requests' do
- find('.text-expander').click
-
- expect(page).to have_selector('.js-full-mr-list', visible: true)
-
- pipeline.all_merge_requests.map do |merge_request|
- expect(page).to have_link(href: project_merge_request_path(project, merge_request))
- end
- end
- end
- end
- end
-
- describe 'pipelines details view' do
- let!(:status) { create(:user_status, user: pipeline.user, emoji: 'smirk', message: 'Authoring this object') }
-
- it 'pipeline header shows the user status and emoji' do
- visit project_pipeline_path(project, pipeline)
-
- within '[data-testid="ci-header-content"]' do
- expect(page).to have_selector("[data-testid='#{status.message}']")
- expect(page).to have_selector("[data-name='#{status.emoji}']")
- end
end
end
@@ -299,8 +223,8 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
wait_for_requests
expect(page).not_to have_content('Retry job')
- within('.js-pipeline-header-container') do
- expect(page).to have_selector('.js-ci-status-icon-running')
+ within('[data-testid="pipeline-details-header"]') do
+ expect(page).to have_selector('[data-testid="ci-badge-running"]')
end
end
end
@@ -353,8 +277,8 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
wait_for_requests
expect(page).not_to have_content('Retry job')
- within('.js-pipeline-header-container') do
- expect(page).to have_selector('.js-ci-status-icon-running')
+ within('[data-testid="pipeline-details-header"]') do
+ expect(page).to have_selector('[data-testid="ci-badge-running"]')
end
end
@@ -387,8 +311,8 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
wait_for_requests
expect(page).not_to have_content('Play job')
- within('.js-pipeline-header-container') do
- expect(page).to have_selector('.js-ci-status-icon-running')
+ within('[data-testid="pipeline-details-header"]') do
+ expect(page).to have_selector('[data-testid="ci-badge-running"]')
end
end
end
@@ -601,7 +525,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
context 'when retrying' do
before do
- find('[data-testid="retryPipeline"]').click
+ find('[data-testid="retry-pipeline"]').click
wait_for_requests
end
@@ -610,8 +534,8 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'shows running status in pipeline header', :sidekiq_might_not_need_inline do
- within('.js-pipeline-header-container') do
- expect(page).to have_selector('.js-ci-status-icon-running')
+ within('[data-testid="pipeline-details-header"]') do
+ expect(page).to have_selector('[data-testid="ci-badge-running"]')
end
end
end
@@ -677,7 +601,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'does not render render raw HTML to the pipeline ref' do
- page.within '.pipeline-info' do
+ page.within '[data-testid="pipeline-details-header"]' do
expect(page).not_to have_content('<span class="ref-name"')
end
end
@@ -701,10 +625,10 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows the pipeline information' do
visit_pipeline
- within '.pipeline-info' do
- expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for !#{merge_request.iid} " \
- "with #{merge_request.source_branch}")
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content("#{pipeline.statuses.count} Jobs")
+ expect(page).to have_content("Related merge request !#{merge_request.iid} " \
+ "to merge #{merge_request.source_branch}")
expect(page).to have_link("!#{merge_request.iid}",
href: project_merge_request_path(project, merge_request))
expect(page).to have_link(merge_request.source_branch,
@@ -720,7 +644,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'does not link to the source branch commit path' do
visit_pipeline
- within '.pipeline-info' do
+ within '[data-testid="pipeline-details-header"]' do
expect(page).not_to have_link(merge_request.source_branch)
expect(page).to have_content(merge_request.source_branch)
end
@@ -735,10 +659,10 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'shows the pipeline information', :sidekiq_might_not_need_inline do
- within '.pipeline-info' do
- expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for !#{merge_request.iid} " \
- "with #{merge_request.source_branch}")
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content("#{pipeline.statuses.count} Jobs")
+ expect(page).to have_content("Related merge request !#{merge_request.iid} " \
+ "to merge #{merge_request.source_branch}")
expect(page).to have_link("!#{merge_request.iid}",
href: project_merge_request_path(project, merge_request))
expect(page).to have_link(merge_request.source_branch,
@@ -772,10 +696,10 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows the pipeline information' do
visit_pipeline
- within '.pipeline-info' do
- expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for !#{merge_request.iid} " \
- "with #{merge_request.source_branch} " \
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content("#{pipeline.statuses.count} Jobs")
+ expect(page).to have_content("Related merge request !#{merge_request.iid} " \
+ "to merge #{merge_request.source_branch} " \
"into #{merge_request.target_branch}")
expect(page).to have_link("!#{merge_request.iid}",
href: project_merge_request_path(project, merge_request))
@@ -794,7 +718,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'does not link to the target branch commit path' do
visit_pipeline
- within '.pipeline-info' do
+ within '[data-testid="pipeline-details-header"]' do
expect(page).not_to have_link(merge_request.target_branch)
expect(page).to have_content(merge_request.target_branch)
end
@@ -809,10 +733,10 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'shows the pipeline information', :sidekiq_might_not_need_inline do
- within '.pipeline-info' do
- expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for !#{merge_request.iid} " \
- "with #{merge_request.source_branch} " \
+ within '[data-testid="pipeline-details-header"]' do
+ expect(page).to have_content("#{pipeline.statuses.count} Jobs")
+ expect(page).to have_content("Related merge request !#{merge_request.iid} " \
+ "to merge #{merge_request.source_branch} " \
"into #{merge_request.target_branch}")
expect(page).to have_link("!#{merge_request.iid}",
href: project_merge_request_path(project, merge_request))
@@ -957,7 +881,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows deploy job as created' do
subject
- within('.js-pipeline-header-container') do
+ within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content('pending')
end
@@ -982,7 +906,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows deploy job as pending' do
subject
- within('.js-pipeline-header-container') do
+ within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content('running')
end
@@ -1011,7 +935,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows deploy job as waiting for resource' do
subject
- within('.js-pipeline-header-container') do
+ within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content('waiting')
end
@@ -1031,7 +955,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows deploy job as pending' do
subject
- within('.js-pipeline-header-container') do
+ within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content('running')
end
@@ -1059,7 +983,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'shows deploy job as waiting for resource' do
subject
- within('.js-pipeline-header-container') do
+ within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content('waiting')
end
@@ -1327,7 +1251,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'contains badge that indicates it is the latest build' do
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content 'latest'
end
end
@@ -1348,7 +1272,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'contains badge that indicates errors' do
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content 'yaml invalid'
end
end
@@ -1356,7 +1280,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'contains badge with tooltip which contains error' do
expect(pipeline).to have_yaml_errors
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_selector(
%{span[title="#{pipeline.yaml_errors}"]})
end
@@ -1369,25 +1293,18 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
it 'contains badge with tooltip which contains failure reason' do
expect(pipeline.failure_reason?).to eq true
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_selector(
%{span[title="#{pipeline.present.failure_reason}"]})
end
end
-
- it 'contains a pipeline header with title' do
- expect(page).to have_content "Pipeline ##{pipeline.id}"
- end
end
context 'when pipeline is stuck' do
- include_context 'pipeline builds'
-
let(:pipeline) do
create(:ci_pipeline,
project: project,
- ref: 'master',
- sha: project.commit.id,
+ status: :created,
user: user)
end
@@ -1397,7 +1314,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'contains badge that indicates being stuck' do
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content 'stuck'
end
end
@@ -1421,7 +1338,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'contains badge that indicates using auto devops' do
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content 'Auto DevOps'
end
end
@@ -1453,7 +1370,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do
end
it 'contains badge that indicates detached merge request pipeline' do
- page.within(all('.well-segment')[1]) do
+ page.within('[data-testid="pipeline-details-header"]') do
expect(page).to have_content 'merge request'
end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index a5ff4be5e07..c47c9c75f91 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -10,10 +10,6 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
let(:project) { create(:project) }
let(:expected_detached_mr_tag) { 'merge request' }
- before do
- stub_feature_flags(pipeline_details_header_vue: false)
- end
-
context 'when user is logged in' do
let(:user) { create(:user) }
@@ -656,7 +652,6 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
# header
expect(page).to have_text("##{pipeline.id}")
- expect(page).to have_selector(%(img[src="#{pipeline.user.avatar_url}"]))
expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user))
# stages
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
deleted file mode 100644
index 18def4ab62c..00000000000
--- a/spec/frontend/pipelines/header_component_spec.js
+++ /dev/null
@@ -1,246 +0,0 @@
-import { GlAlert, GlModal, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import waitForPromises from 'helpers/wait_for_promises';
-import HeaderComponent from '~/pipelines/components/header_component.vue';
-import cancelPipelineMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
-import deletePipelineMutation from '~/pipelines/graphql/mutations/delete_pipeline.mutation.graphql';
-import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
-import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL } from '~/pipelines/constants';
-import {
- mockCancelledPipelineHeader,
- mockFailedPipelineHeader,
- mockFailedPipelineNoPermissions,
- mockRunningPipelineHeader,
- mockRunningPipelineNoPermissions,
- mockSuccessfulPipelineHeader,
-} from './mock_data';
-
-describe('Pipeline details header', () => {
- let wrapper;
- let glModalDirective;
- let mutate = jest.fn();
-
- const findAlert = () => wrapper.findComponent(GlAlert);
- const findDeleteModal = () => wrapper.findComponent(GlModal);
- const findRetryButton = () => wrapper.find('[data-testid="retryPipeline"]');
- const findCancelButton = () => wrapper.find('[data-testid="cancelPipeline"]');
- const findDeleteButton = () => wrapper.find('[data-testid="deletePipeline"]');
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
-
- const defaultProvideOptions = {
- pipelineId: '14',
- pipelineIid: 1,
- paths: {
- pipelinesPath: '/namespace/my-project/-/pipelines',
- fullProject: '/namespace/my-project',
- },
- };
-
- const createComponent = (pipelineMock = mockRunningPipelineHeader, { isLoading } = false) => {
- glModalDirective = jest.fn();
-
- const $apollo = {
- queries: {
- pipeline: {
- loading: isLoading,
- stopPolling: jest.fn(),
- startPolling: jest.fn(),
- },
- },
- mutate,
- };
-
- return shallowMount(HeaderComponent, {
- data() {
- return {
- pipeline: pipelineMock,
- };
- },
- provide: {
- ...defaultProvideOptions,
- },
- directives: {
- glModal: {
- bind(_, { value }) {
- glModalDirective(value);
- },
- },
- },
- mocks: { $apollo },
- });
- };
-
- describe('initial loading', () => {
- beforeEach(() => {
- wrapper = createComponent(null, { isLoading: true });
- });
-
- it('shows a loading state while graphQL is fetching initial data', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- });
- });
-
- describe('visible state', () => {
- it.each`
- state | pipelineData | retryValue | cancelValue
- ${'cancelled'} | ${mockCancelledPipelineHeader} | ${true} | ${false}
- ${'failed'} | ${mockFailedPipelineHeader} | ${true} | ${false}
- ${'running'} | ${mockRunningPipelineHeader} | ${false} | ${true}
- ${'successful'} | ${mockSuccessfulPipelineHeader} | ${false} | ${false}
- `(
- 'with a $state pipeline, it will show actions: retry $retryValue and cancel $cancelValue',
- ({ pipelineData, retryValue, cancelValue }) => {
- wrapper = createComponent(pipelineData);
-
- expect(findRetryButton().exists()).toBe(retryValue);
- expect(findCancelButton().exists()).toBe(cancelValue);
- },
- );
- });
-
- describe('actions', () => {
- describe('Retry action', () => {
- beforeEach(() => {
- wrapper = createComponent(mockCancelledPipelineHeader);
- });
-
- it('should call retryPipeline Mutation with pipeline id', () => {
- findRetryButton().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: retryPipelineMutation,
- variables: { id: mockCancelledPipelineHeader.id },
- });
- });
-
- it('should render retry action tooltip', () => {
- expect(findRetryButton().attributes('title')).toBe(BUTTON_TOOLTIP_RETRY);
- });
-
- it('should display error message on failure', async () => {
- const failureMessage = 'failure message';
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: {
- pipelineRetry: {
- errors: [failureMessage],
- },
- },
- });
-
- findRetryButton().vm.$emit('click');
- await waitForPromises();
-
- expect(findAlert().text()).toBe(failureMessage);
- });
- });
-
- describe('Retry action failed', () => {
- beforeEach(() => {
- mutate = jest.fn().mockRejectedValue('error');
-
- wrapper = createComponent(mockCancelledPipelineHeader);
- });
-
- it('retry button loading state should reset on error', async () => {
- findRetryButton().vm.$emit('click');
-
- await nextTick();
-
- expect(findRetryButton().props('loading')).toBe(true);
-
- await waitForPromises();
-
- expect(findRetryButton().props('loading')).toBe(false);
- });
- });
-
- describe('Cancel action', () => {
- beforeEach(() => {
- wrapper = createComponent(mockRunningPipelineHeader);
- });
-
- it('should call cancelPipeline Mutation with pipeline id', () => {
- findCancelButton().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: cancelPipelineMutation,
- variables: { id: mockRunningPipelineHeader.id },
- });
- });
-
- it('should render cancel action tooltip', () => {
- expect(findCancelButton().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL);
- });
-
- it('should display error message on failure', async () => {
- const failureMessage = 'failure message';
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: {
- pipelineCancel: {
- errors: [failureMessage],
- },
- },
- });
-
- findCancelButton().vm.$emit('click');
- await waitForPromises();
-
- expect(findAlert().text()).toBe(failureMessage);
- });
- });
-
- describe('Delete action', () => {
- beforeEach(() => {
- wrapper = createComponent(mockFailedPipelineHeader);
- });
-
- it('displays delete modal when clicking on delete and does not call the delete action', () => {
- findDeleteButton().vm.$emit('click');
-
- expect(findDeleteModal().props('modalId')).toBe(wrapper.vm.$options.DELETE_MODAL_ID);
- expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.$options.DELETE_MODAL_ID);
- expect(wrapper.vm.$apollo.mutate).not.toHaveBeenCalled();
- });
-
- it('should call deletePipeline Mutation with pipeline id when modal is submitted', () => {
- findDeleteModal().vm.$emit('primary');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: deletePipelineMutation,
- variables: { id: mockFailedPipelineHeader.id },
- });
- });
-
- it('should display error message on failure', async () => {
- const failureMessage = 'failure message';
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: {
- pipelineDestroy: {
- errors: [failureMessage],
- },
- },
- });
-
- findDeleteModal().vm.$emit('primary');
- await waitForPromises();
-
- expect(findAlert().text()).toBe(failureMessage);
- });
- });
-
- describe('Permissions', () => {
- it('should not display the cancel action if user does not have permission', () => {
- wrapper = createComponent(mockRunningPipelineNoPermissions);
-
- expect(findCancelButton().exists()).toBe(false);
- });
-
- it('should not display the retry action if user does not have permission', () => {
- wrapper = createComponent(mockFailedPipelineNoPermissions);
-
- expect(findRetryButton().exists()).toBe(false);
- });
- });
- });
-});
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index 62c0d6e2d91..673db3b5178 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -26,19 +26,19 @@ export const pipelineRetryMutationResponseFailed = {
};
export const pipelineCancelMutationResponseSuccess = {
- data: { pipelineRetry: { errors: [] } },
+ data: { pipelineCancel: { errors: [] } },
};
export const pipelineCancelMutationResponseFailed = {
- data: { pipelineRetry: { errors: ['error'] } },
+ data: { pipelineCancel: { errors: ['error'] } },
};
export const pipelineDeleteMutationResponseSuccess = {
- data: { pipelineRetry: { errors: [] } },
+ data: { pipelineDestroy: { errors: [] } },
};
export const pipelineDeleteMutationResponseFailed = {
- data: { pipelineRetry: { errors: ['error'] } },
+ data: { pipelineDestroy: { errors: ['error'] } },
};
export const mockPipelineHeader = {
diff --git a/spec/frontend/sidebar/components/time_tracking/create_timelog_form_spec.js b/spec/frontend/sidebar/components/time_tracking/create_timelog_form_spec.js
index a7c3867c359..a3b32e98506 100644
--- a/spec/frontend/sidebar/components/time_tracking/create_timelog_form_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/create_timelog_form_spec.js
@@ -1,9 +1,10 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { GlAlert, GlModal } from '@gitlab/ui';
+import { GlAlert, GlModal, GlFormInput, GlDatepicker, GlFormTextarea } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { stubComponent } from 'helpers/stub_component';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import CreateTimelogForm from '~/sidebar/components/time_tracking/create_timelog_form.vue';
import createTimelogMutation from '~/sidebar/queries/create_timelog.mutation.graphql';
@@ -49,21 +50,19 @@ describe('Create Timelog Form', () => {
const findSaveButton = () => findModal().props('actionPrimary');
const findSaveButtonLoadingState = () => findSaveButton().attributes.loading;
const findSaveButtonDisabledState = () => findSaveButton().attributes.disabled;
+ const findGlFormInput = () => wrapper.findComponent(GlFormInput);
+ const findGlDatepicker = () => wrapper.findComponent(GlDatepicker);
+ const findGlFormTextarea = () => wrapper.findComponent(GlFormTextarea);
const submitForm = () => findForm().trigger('submit');
const mountComponent = (
- { props, data, providedProps } = {},
+ { props, providedProps } = {},
mutationResolverMock = rejectedMutationMock,
) => {
fakeApollo = createMockApollo([[createTimelogMutation, mutationResolverMock]]);
wrapper = shallowMountExtended(CreateTimelogForm, {
- data() {
- return {
- ...data,
- };
- },
provide: {
issuableType: 'issue',
...providedProps,
@@ -73,13 +72,17 @@ describe('Create Timelog Form', () => {
...props,
},
apolloProvider: fakeApollo,
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ methods: { close: modalCloseMock },
+ }),
+ },
});
-
- wrapper.vm.$refs.modal.close = modalCloseMock;
};
afterEach(() => {
fakeApollo = null;
+ modalCloseMock.mockClear();
});
describe('save button', () => {
@@ -90,15 +93,18 @@ describe('Create Timelog Form', () => {
expect(findSaveButtonDisabledState()).toBe(true);
});
- it('is enabled and not loading when time spent is not empty', () => {
- mountComponent({ data: { timeSpent: '2d' } });
+ it('is enabled and not loading when time spent is not empty', async () => {
+ mountComponent();
+
+ await findGlFormInput().vm.$emit('input', '2d');
expect(findSaveButtonLoadingState()).toBe(false);
expect(findSaveButtonDisabledState()).toBe(false);
});
it('is disabled and loading when the the form is submitted', async () => {
- mountComponent({ data: { timeSpent: '2d' } });
+ mountComponent();
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
@@ -109,7 +115,8 @@ describe('Create Timelog Form', () => {
});
it('is enabled and not loading the when form is submitted but the mutation has errors', async () => {
- mountComponent({ data: { timeSpent: '2d' } });
+ mountComponent();
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
@@ -121,7 +128,8 @@ describe('Create Timelog Form', () => {
});
it('is enabled and not loading the when form is submitted but the mutation returns errors', async () => {
- mountComponent({ data: { timeSpent: '2d' } }, resolvedMutationWithErrorsMock);
+ mountComponent({}, resolvedMutationWithErrorsMock);
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
@@ -145,7 +153,8 @@ describe('Create Timelog Form', () => {
});
it('closes the modal after a successful mutation', async () => {
- mountComponent({ data: { timeSpent: '2d' } }, resolvedMutationWithoutErrorsMock);
+ mountComponent({}, resolvedMutationWithoutErrorsMock);
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
@@ -166,7 +175,10 @@ describe('Create Timelog Form', () => {
const spentAt = '2022-11-20T21:53:00+0000';
const summary = 'Example';
- mountComponent({ data: { timeSpent, spentAt, summary }, providedProps: { issuableType } });
+ mountComponent({ providedProps: { issuableType } });
+ await findGlFormInput().vm.$emit('input', timeSpent);
+ await findGlDatepicker().vm.$emit('input', spentAt);
+ await findGlFormTextarea().vm.$emit('input', summary);
submitForm();
@@ -187,7 +199,8 @@ describe('Create Timelog Form', () => {
});
it('shows an error if the submission fails with a handled error', async () => {
- mountComponent({ data: { timeSpent: '2d' } }, resolvedMutationWithErrorsMock);
+ mountComponent({}, resolvedMutationWithErrorsMock);
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
@@ -198,7 +211,8 @@ describe('Create Timelog Form', () => {
});
it('shows an error if the submission fails with an unhandled error', async () => {
- mountComponent({ data: { timeSpent: '2d' } });
+ mountComponent();
+ await findGlFormInput().vm.$emit('input', '2d');
submitForm();
diff --git a/spec/helpers/ci/pipelines_helper_spec.rb b/spec/helpers/ci/pipelines_helper_spec.rb
index 61583ca1173..00bc38dbd94 100644
--- a/spec/helpers/ci/pipelines_helper_spec.rb
+++ b/spec/helpers/ci/pipelines_helper_spec.rb
@@ -72,28 +72,6 @@ RSpec.describe Ci::PipelinesHelper do
end
end
- describe 'has_pipeline_badges?' do
- let(:pipeline) { create(:ci_empty_pipeline) }
-
- subject { helper.has_pipeline_badges?(pipeline) }
-
- context 'when pipeline has a badge' do
- before do
- pipeline.drop!(:config_error)
- end
-
- it 'shows pipeline badges' do
- expect(subject).to eq(true)
- end
- end
-
- context 'when pipeline has no badges' do
- it 'shows pipeline badges' do
- expect(subject).to eq(false)
- end
- end
- end
-
describe '#pipelines_list_data' do
let_it_be(:project) { create(:project) }
diff --git a/spec/helpers/projects/pipeline_helper_spec.rb b/spec/helpers/projects/pipeline_helper_spec.rb
index a69da915990..baeafe6b7e7 100644
--- a/spec/helpers/projects/pipeline_helper_spec.rb
+++ b/spec/helpers/projects/pipeline_helper_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe Projects::PipelineHelper do
failed: pipeline.failure_reason?.to_s,
auto_devops: pipeline.auto_devops_source?.to_s,
detached: pipeline.detached_merge_request_pipeline?.to_s,
- stuck: pipeline.stuck?,
+ stuck: pipeline.stuck?.to_s,
ref_text: pipeline.ref_text
})
end
diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb
index cc68cdff7c1..fc13b377014 100644
--- a/spec/presenters/ci/pipeline_presenter_spec.rb
+++ b/spec/presenters/ci/pipeline_presenter_spec.rb
@@ -146,69 +146,6 @@ RSpec.describe Ci::PipelinePresenter do
end
end
- describe '#ref_text_legacy' do
- subject { presenter.ref_text_legacy }
-
- context 'when pipeline is detached merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.all_pipelines.last }
-
- it 'returns a correct ref text' do
- is_expected.to eq("for <a class=\"mr-iid\" href=\"#{project_merge_request_path(merge_request.project, merge_request)}\">#{merge_request.to_reference}</a> " \
- "with <a class=\"ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2\" href=\"#{project_commits_path(merge_request.source_project, merge_request.source_branch)}\">#{merge_request.source_branch}</a>")
- end
- end
-
- context 'when pipeline is merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
- let(:pipeline) { merge_request.all_pipelines.last }
-
- it 'returns a correct ref text' do
- is_expected.to eq("for <a class=\"mr-iid\" href=\"#{project_merge_request_path(merge_request.project, merge_request)}\">#{merge_request.to_reference}</a> " \
- "with <a class=\"ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2\" href=\"#{project_commits_path(merge_request.source_project, merge_request.source_branch)}\">#{merge_request.source_branch}</a> " \
- "into <a class=\"ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2\" href=\"#{project_commits_path(merge_request.target_project, merge_request.target_branch)}\">#{merge_request.target_branch}</a>")
- end
- end
-
- context 'when pipeline is branch pipeline' do
- context 'when ref exists in the repository' do
- before do
- allow(pipeline).to receive(:ref_exists?) { true }
- end
-
- it 'returns a correct ref text' do
- is_expected.to eq("for <a class=\"ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2\" href=\"#{project_commits_path(pipeline.project, pipeline.ref)}\">#{pipeline.ref}</a>")
- end
-
- context 'when ref contains malicious script' do
- let(:pipeline) { create(:ci_pipeline, ref: "<script>alter('1')</script>", project: project) }
-
- it 'does not include the malicious script' do
- is_expected.not_to include("<script>alter('1')</script>")
- end
- end
- end
-
- context 'when ref does not exist in the repository' do
- before do
- allow(pipeline).to receive(:ref_exists?) { false }
- end
-
- it 'returns a correct ref text' do
- is_expected.to eq("for <span class=\"ref-name\">#{pipeline.ref}</span>")
- end
-
- context 'when ref contains malicious script' do
- let(:pipeline) { create(:ci_pipeline, ref: "<script>alter('1')</script>", project: project) }
-
- it 'does not include the malicious script' do
- is_expected.not_to include("<script>alter('1')</script>")
- end
- end
- end
- end
- end
-
describe '#ref_text' do
subject { presenter.ref_text }
@@ -272,49 +209,6 @@ RSpec.describe Ci::PipelinePresenter do
end
end
- describe '#all_related_merge_request_text' do
- subject { presenter.all_related_merge_request_text }
-
- let_it_be(:mr_1) { create(:merge_request) }
- let_it_be(:mr_2) { create(:merge_request) }
-
- context 'with zero related merge requests (branch pipeline)' do
- it { is_expected.to eq('No related merge requests found.') }
- end
-
- context 'with one related merge request' do
- before do
- allow(pipeline).to receive(:all_merge_requests).and_return(MergeRequest.where(id: mr_1.id))
- end
-
- it {
- is_expected.to eq("1 related merge request: " \
- "<a class=\"mr-iid\" href=\"#{merge_request_path(mr_1)}\">#{mr_1.to_reference} #{mr_1.title}</a>")
- }
- end
-
- context 'with two related merge requests' do
- before do
- allow(pipeline).to receive(:all_merge_requests).and_return(MergeRequest.where(id: [mr_1.id, mr_2.id]))
- end
-
- it {
- is_expected.to eq("2 related merge requests: " \
- "<a class=\"mr-iid\" href=\"#{merge_request_path(mr_2)}\">#{mr_2.to_reference} #{mr_2.title}</a>, " \
- "<a class=\"mr-iid\" href=\"#{merge_request_path(mr_1)}\">#{mr_1.to_reference} #{mr_1.title}</a>")
- }
-
- context 'with a limit passed' do
- subject { presenter.all_related_merge_request_text(limit: 1) }
-
- it {
- is_expected.to eq("2 related merge requests: " \
- "<a class=\"mr-iid\" href=\"#{merge_request_path(mr_2)}\">#{mr_2.to_reference} #{mr_2.title}</a>")
- }
- end
- end
- end
-
describe '#all_related_merge_requests' do
subject(:all_related_merge_requests) do
presenter.send(:all_related_merge_requests)
diff --git a/spec/views/projects/pipelines/show.html.haml_spec.rb b/spec/views/projects/pipelines/show.html.haml_spec.rb
index 3c15d5846e9..81a11874886 100644
--- a/spec/views/projects/pipelines/show.html.haml_spec.rb
+++ b/spec/views/projects/pipelines/show.html.haml_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe 'projects/pipelines/show', feature_category: :pipeline_compositio
let(:presented_pipeline) { pipeline.present(current_user: user) }
before do
- stub_feature_flags(pipeline_details_header_vue: false)
assign(:project, project)
assign(:pipeline, presented_pipeline)
allow(view).to receive(:current_user) { user }