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:
-rw-r--r--.rubocop_todo/layout/line_length.yml1
-rw-r--r--.rubocop_todo/rspec/context_wording.yml1
-rw-r--r--.rubocop_todo/rspec/missing_feature_category.yml1
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue6
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue149
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue92
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue184
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue6
-rw-r--r--app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue1
-rw-r--r--app/finders/metrics/dashboards/annotations_finder.rb43
-rw-r--r--app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb5
-rw-r--r--lib/api/time_tracking_endpoints.rb13
-rw-r--r--locale/gitlab.pot47
-rw-r--r--qa/qa/page/merge_request/show.rb15
-rw-r--r--spec/finders/metrics/dashboards/annotations_finder_spec.rb108
-rw-r--r--spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js10
-rw-r--r--spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js6
-rw-r--r--spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js32
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph_spec.js123
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph_spec.js122
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js179
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js14
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js16
-rw-r--r--spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb34
-rw-r--r--spec/support/rspec_order_todo.yml1
-rw-r--r--spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb43
29 files changed, 571 insertions, 701 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index b6f3dfc793d..f483c9ac5f2 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -3446,7 +3446,6 @@ Layout/LineLength:
- 'spec/finders/members_finder_spec.rb'
- 'spec/finders/merge_requests/by_approvals_finder_spec.rb'
- 'spec/finders/merge_requests_finder_spec.rb'
- - 'spec/finders/metrics/dashboards/annotations_finder_spec.rb'
- 'spec/finders/metrics/users_starred_dashboards_finder_spec.rb'
- 'spec/finders/milestones_finder_spec.rb'
- 'spec/finders/namespaces/projects_finder_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 21d8fbcc31a..8e5d9e1e54e 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -1334,7 +1334,6 @@ RSpec/ContextWording:
- 'spec/finders/merge_request_target_project_finder_spec.rb'
- 'spec/finders/merge_requests/by_approvals_finder_spec.rb'
- 'spec/finders/merge_requests_finder_spec.rb'
- - 'spec/finders/metrics/dashboards/annotations_finder_spec.rb'
- 'spec/finders/metrics/users_starred_dashboards_finder_spec.rb'
- 'spec/finders/milestones_finder_spec.rb'
- 'spec/finders/notes_finder_spec.rb'
diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml
index a7c375afcff..edd083de8d9 100644
--- a/.rubocop_todo/rspec/missing_feature_category.yml
+++ b/.rubocop_todo/rspec/missing_feature_category.yml
@@ -1875,7 +1875,6 @@ RSpec/MissingFeatureCategory:
- 'spec/finders/merge_request_target_project_finder_spec.rb'
- 'spec/finders/merge_requests/by_approvals_finder_spec.rb'
- 'spec/finders/merge_requests/oldest_per_commit_finder_spec.rb'
- - 'spec/finders/metrics/dashboards/annotations_finder_spec.rb'
- 'spec/finders/metrics/users_starred_dashboards_finder_spec.rb'
- 'spec/finders/milestones_finder_spec.rb'
- 'spec/finders/namespaces/projects_finder_spec.rb'
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
index 656b1a6c347..f1c9770714a 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue
@@ -1,7 +1,7 @@
<script>
import { __ } from '~/locale';
import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
import { PIPELINE_FAILURE } from '../../constants';
@@ -10,7 +10,7 @@ export default {
linkedPipelinesFetchError: __('Unable to fetch upstream and downstream pipelines.'),
},
components: {
- PipelineMiniGraph,
+ LegacyPipelineMiniGraph,
},
inject: ['projectFullPath'],
props: {
@@ -84,7 +84,7 @@ export default {
</script>
<template>
- <pipeline-mini-graph
+ <legacy-pipeline-mini-graph
v-if="hasPipelineStages"
:downstream-pipelines="downstreamPipelines"
:pipeline-path="pipelinePath"
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
index bb79a4d74da..3bce50224d9 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
@@ -11,7 +11,7 @@ import {
} from '~/pipelines/components/graph/utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import GraphqlPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue';
+import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
import PipelineEditorMiniGraph from './pipeline_editor_mini_graph.vue';
const POLL_INTERVAL = 10000;
@@ -34,8 +34,8 @@ export default {
GlLink,
GlLoadingIcon,
GlSprintf,
- GraphqlPipelineMiniGraph,
PipelineEditorMiniGraph,
+ PipelineMiniGraph,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -179,7 +179,7 @@ export default {
</span>
</div>
<div class="gl-display-flex gl-flex-wrap-wrap">
- <graphql-pipeline-mini-graph
+ <pipeline-mini-graph
v-if="isUsingPipelineMiniGraphQueries"
:full-path="projectFullPath"
:iid="pipeline.iid"
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue
deleted file mode 100644
index 91630d4cfd4..00000000000
--- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue
+++ /dev/null
@@ -1,149 +0,0 @@
-<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import { createAlert } from '~/alert';
-import { __ } from '~/locale';
-import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
-import {
- getQueryHeaders,
- toggleQueryPollingByVisibility,
-} from '~/pipelines/components/graph/utils';
-import { PIPELINE_MINI_GRAPH_POLL_INTERVAL } from '~/pipelines/constants';
-import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
-import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
-import PipelineMiniGraph from './pipeline_mini_graph.vue';
-
-export default {
- i18n: {
- linkedPipelinesFetchError: __('There was a problem fetching linked pipelines.'),
- stagesFetchError: __('There was a problem fetching the pipeline stages.'),
- },
- components: {
- GlLoadingIcon,
- PipelineMiniGraph,
- },
- props: {
- pipelineEtag: {
- type: String,
- required: true,
- },
- fullPath: {
- type: String,
- required: true,
- },
- iid: {
- type: String,
- required: true,
- },
- isMergeTrain: {
- type: Boolean,
- required: false,
- default: false,
- },
- pollInterval: {
- type: Number,
- required: false,
- default: PIPELINE_MINI_GRAPH_POLL_INTERVAL,
- },
- },
- data() {
- return {
- linkedPipelines: null,
- pipelineStages: [],
- };
- },
- apollo: {
- linkedPipelines: {
- context() {
- return getQueryHeaders(this.pipelineEtag);
- },
- query: getLinkedPipelinesQuery,
- pollInterval() {
- return this.pollInterval;
- },
- variables() {
- return {
- fullPath: this.fullPath,
- iid: this.iid,
- };
- },
- update({ project }) {
- return project?.pipeline || this.linkedpipelines;
- },
- error() {
- createAlert({ message: this.$options.i18n.linkedPipelinesFetchError });
- },
- },
- pipelineStages: {
- context() {
- return getQueryHeaders(this.pipelineEtag);
- },
- query: getPipelineStagesQuery,
- pollInterval() {
- return this.pollInterval;
- },
- variables() {
- return {
- fullPath: this.fullPath,
- iid: this.iid,
- };
- },
- update({ project }) {
- return project?.pipeline?.stages?.nodes || this.pipelineStages;
- },
- error() {
- createAlert({ message: this.$options.i18n.stagesFetchError });
- },
- },
- },
- computed: {
- downstreamPipelines() {
- return keepLatestDownstreamPipelines(this.linkedPipelines?.downstream?.nodes);
- },
- formattedStages() {
- return this.pipelineStages.map((stage) => {
- const { name, detailedStatus } = stage;
- return {
- // TODO: Once we fetch stage by ID with GraphQL,
- // this method will change.
- // see https://gitlab.com/gitlab-org/gitlab/-/issues/384853
- id: stage.id,
- dropdown_path: `${this.pipelinePath}/stage.json?stage=${name}`,
- name,
- path: `${this.pipelinePath}#${name}`,
- status: {
- details_path: `${this.pipelinePath}#${name}`,
- has_details: detailedStatus?.hasDetails || false,
- ...detailedStatus,
- },
- title: `${name}: ${detailedStatus?.text || ''}`,
- };
- });
- },
- pipelinePath() {
- return this.linkedPipelines?.path || '';
- },
- upstreamPipeline() {
- return this.linkedPipelines?.upstream;
- },
- },
- mounted() {
- toggleQueryPollingByVisibility(this.$apollo.queries.linkedPipelines);
- toggleQueryPollingByVisibility(this.$apollo.queries.pipelineStages);
- },
-};
-</script>
-
-<template>
- <div>
- <gl-loading-icon v-if="$apollo.queries.pipelineStages.loading" />
- <pipeline-mini-graph
- v-else
- data-testid="graphql-pipeline-mini-graph"
- :downstream-pipelines="downstreamPipelines"
- :is-merge-train="isMergeTrain"
- :pipeline-path="pipelinePath"
- :stages="formattedStages"
- :upstream-pipeline="upstreamPipeline"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue
new file mode 100644
index 00000000000..b505422b073
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue
@@ -0,0 +1,92 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import PipelineStages from './pipeline_stages.vue';
+import LinkedPipelinesMiniList from './linked_pipelines_mini_list.vue';
+/**
+ * Renders the pipeline mini graph.
+ * Once all apps that use this component are updated to GraphQL, we will rename this file to `pipeline_mini_graph_wrapper.vue`
+ */
+export default {
+ components: {
+ GlIcon,
+ LinkedPipelinesMiniList,
+ PipelineStages,
+ },
+ arrowStyles: [
+ 'arrow-icon gl-display-inline-block gl-mx-1 gl-text-gray-500 gl-vertical-align-middle!',
+ ],
+ props: {
+ downstreamPipelines: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isMergeTrain: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pipelinePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ stages: {
+ type: Array,
+ required: true,
+ default: () => [],
+ },
+ updateDropdown: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ upstreamPipeline: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ },
+ computed: {
+ hasDownstreamPipelines() {
+ return Boolean(this.downstreamPipelines.length);
+ },
+ },
+};
+</script>
+<template>
+ <div data-testid="pipeline-mini-graph">
+ <linked-pipelines-mini-list
+ v-if="upstreamPipeline"
+ :triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
+ upstreamPipeline,
+ ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
+ data-testid="pipeline-mini-graph-upstream"
+ />
+ <gl-icon
+ v-if="upstreamPipeline"
+ :class="$options.arrowStyles"
+ name="long-arrow"
+ data-testid="upstream-arrow-icon"
+ />
+ <pipeline-stages
+ :is-merge-train="isMergeTrain"
+ :stages="stages"
+ :update-dropdown="updateDropdown"
+ data-testid="pipeline-stages"
+ @miniGraphStageClick="$emit('miniGraphStageClick')"
+ />
+ <gl-icon
+ v-if="hasDownstreamPipelines"
+ :class="$options.arrowStyles"
+ name="long-arrow"
+ data-testid="downstream-arrow-icon"
+ />
+ <linked-pipelines-mini-list
+ v-if="hasDownstreamPipelines"
+ :triggered="downstreamPipelines"
+ :pipeline-path="pipelinePath"
+ data-testid="pipeline-mini-graph-downstream"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
index 827adf9f7f7..5dd9683f7d8 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
@@ -1,91 +1,149 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import PipelineStages from './pipeline_stages.vue';
-import LinkedPipelinesMiniList from './linked_pipelines_mini_list.vue';
-/**
- * Renders the pipeline mini graph.
- */
+import { GlLoadingIcon } from '@gitlab/ui';
+import { createAlert } from '~/alert';
+import { __ } from '~/locale';
+import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
+import {
+ getQueryHeaders,
+ toggleQueryPollingByVisibility,
+} from '~/pipelines/components/graph/utils';
+import { PIPELINE_MINI_GRAPH_POLL_INTERVAL } from '~/pipelines/constants';
+import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
+import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
+import LegacyPipelineMiniGraph from './legacy_pipeline_mini_graph.vue';
+
export default {
+ i18n: {
+ linkedPipelinesFetchError: __('There was a problem fetching linked pipelines.'),
+ stagesFetchError: __('There was a problem fetching the pipeline stages.'),
+ },
components: {
- GlIcon,
- LinkedPipelinesMiniList,
- PipelineStages,
+ GlLoadingIcon,
+ LegacyPipelineMiniGraph,
},
- arrowStyles: [
- 'arrow-icon gl-display-inline-block gl-mx-1 gl-text-gray-500 gl-vertical-align-middle!',
- ],
props: {
- downstreamPipelines: {
- type: Array,
- required: false,
- default: () => [],
- },
- isMergeTrain: {
- type: Boolean,
- required: false,
- default: false,
+ pipelineEtag: {
+ type: String,
+ required: true,
},
- pipelinePath: {
+ fullPath: {
type: String,
- required: false,
- default: '',
+ required: true,
},
- stages: {
- type: Array,
+ iid: {
+ type: String,
required: true,
- default: () => [],
},
- updateDropdown: {
+ isMergeTrain: {
type: Boolean,
required: false,
default: false,
},
- upstreamPipeline: {
- type: Object,
+ pollInterval: {
+ type: Number,
required: false,
- default: () => {},
+ default: PIPELINE_MINI_GRAPH_POLL_INTERVAL,
+ },
+ },
+ data() {
+ return {
+ linkedPipelines: null,
+ pipelineStages: [],
+ };
+ },
+ apollo: {
+ linkedPipelines: {
+ context() {
+ return getQueryHeaders(this.pipelineEtag);
+ },
+ query: getLinkedPipelinesQuery,
+ pollInterval() {
+ return this.pollInterval;
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update({ project }) {
+ return project?.pipeline || this.linkedpipelines;
+ },
+ error() {
+ createAlert({ message: this.$options.i18n.linkedPipelinesFetchError });
+ },
+ },
+ pipelineStages: {
+ context() {
+ return getQueryHeaders(this.pipelineEtag);
+ },
+ query: getPipelineStagesQuery,
+ pollInterval() {
+ return this.pollInterval;
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update({ project }) {
+ return project?.pipeline?.stages?.nodes || this.pipelineStages;
+ },
+ error() {
+ createAlert({ message: this.$options.i18n.stagesFetchError });
+ },
},
},
computed: {
- hasDownstreamPipelines() {
- return Boolean(this.downstreamPipelines.length);
+ downstreamPipelines() {
+ return keepLatestDownstreamPipelines(this.linkedPipelines?.downstream?.nodes);
+ },
+ formattedStages() {
+ return this.pipelineStages.map((stage) => {
+ const { name, detailedStatus } = stage;
+ return {
+ // TODO: Once we fetch stage by ID with GraphQL,
+ // this method will change.
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/384853
+ id: stage.id,
+ dropdown_path: `${this.pipelinePath}/stage.json?stage=${name}`,
+ name,
+ path: `${this.pipelinePath}#${name}`,
+ status: {
+ details_path: `${this.pipelinePath}#${name}`,
+ has_details: detailedStatus?.hasDetails || false,
+ ...detailedStatus,
+ },
+ title: `${name}: ${detailedStatus?.text || ''}`,
+ };
+ });
+ },
+ pipelinePath() {
+ return this.linkedPipelines?.path || '';
},
+ upstreamPipeline() {
+ return this.linkedPipelines?.upstream;
+ },
+ },
+ mounted() {
+ toggleQueryPollingByVisibility(this.$apollo.queries.linkedPipelines);
+ toggleQueryPollingByVisibility(this.$apollo.queries.pipelineStages);
},
};
</script>
+
<template>
- <div data-testid="pipeline-mini-graph">
- <linked-pipelines-mini-list
- v-if="upstreamPipeline"
- :triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
- upstreamPipeline,
- ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
- data-testid="pipeline-mini-graph-upstream"
- />
- <gl-icon
- v-if="upstreamPipeline"
- :class="$options.arrowStyles"
- name="long-arrow"
- data-testid="upstream-arrow-icon"
- />
- <pipeline-stages
+ <div>
+ <gl-loading-icon v-if="$apollo.queries.pipelineStages.loading" />
+ <legacy-pipeline-mini-graph
+ v-else
+ data-testid="pipeline-mini-graph"
+ :downstream-pipelines="downstreamPipelines"
:is-merge-train="isMergeTrain"
- :stages="stages"
- :update-dropdown="updateDropdown"
- data-testid="pipeline-stages"
- @miniGraphStageClick="$emit('miniGraphStageClick')"
- />
- <gl-icon
- v-if="hasDownstreamPipelines"
- :class="$options.arrowStyles"
- name="long-arrow"
- data-testid="downstream-arrow-icon"
- />
- <linked-pipelines-mini-list
- v-if="hasDownstreamPipelines"
- :triggered="downstreamPipelines"
:pipeline-path="pipelinePath"
- data-testid="pipeline-mini-graph-downstream"
+ :stages="formattedStages"
+ :upstream-pipeline="upstreamPipeline"
/>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
index 85fe8d9df3c..073204fc983 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -5,7 +5,7 @@ import { s__, __ } from '~/locale';
import Tracking from '~/tracking';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import PipelineFailedJobsWidget from '~/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue';
import eventHub from '../../event_hub';
import { TRACKING_CATEGORIES } from '../../constants';
@@ -22,8 +22,8 @@ const DEFAULT_TH_CLASSES =
export default {
components: {
GlTableLite,
+ LegacyPipelineMiniGraph,
PipelineFailedJobsWidget,
- PipelineMiniGraph,
PipelineOperations,
PipelinesStatusBadge,
PipelineStopModal,
@@ -208,7 +208,7 @@ export default {
</template>
<template #cell(stages)="{ item }">
- <pipeline-mini-graph
+ <legacy-pipeline-mini-graph
:downstream-pipelines="getDownstreamPipelines(item)"
:pipeline-path="item.path"
:stages="item.details.stages"
diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
index 84e7edb48c1..fe6a56c776b 100644
--- a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
+++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue
@@ -7,8 +7,8 @@ import {
toggleQueryPollingByVisibility,
} from '~/pipelines/components/graph/utils';
import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
-import GraphqlPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
@@ -23,7 +23,7 @@ export default {
},
components: {
GlLoadingIcon,
- GraphqlPipelineMiniGraph,
+ LegacyPipelineMiniGraph,
PipelineMiniGraph,
},
mixins: [glFeatureFlagsMixin()],
@@ -139,14 +139,14 @@ export default {
<div>
<gl-loading-icon v-if="$apollo.queries.pipeline.loading" />
<template v-else>
- <graphql-pipeline-mini-graph
+ <pipeline-mini-graph
v-if="isUsingPipelineMiniGraphQueries"
data-testid="commit-box-pipeline-mini-graph"
:pipeline-etag="graphqlResourceEtag"
:full-path="fullPath"
:iid="iid"
/>
- <pipeline-mini-graph
+ <legacy-pipeline-mini-graph
v-else
data-testid="commit-box-pipeline-mini-graph"
:downstream-pipelines="downstreamPipelines"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index b7e658f677c..e94e0fbe6dc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -13,7 +13,7 @@ import { s__, n__ } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { keepLatestDownstreamPipelines } from '~/pipelines/components/parsing_utils';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { MT_MERGE_STRATEGY } from '../constants';
@@ -27,8 +27,8 @@ export default {
GlIcon,
GlSprintf,
GlTooltip,
+ LegacyPipelineMiniGraph,
PipelineArtifacts,
- PipelineMiniGraph,
TimeAgoTooltip,
TooltipOnTruncate,
},
@@ -221,7 +221,7 @@ export default {
<div
class="gl-align-items-center gl-display-inline-flex gl-flex-grow-1 gl-justify-content-space-between"
>
- <pipeline-mini-graph
+ <legacy-pipeline-mini-graph
v-if="pipeline.details.stages"
:downstream-pipelines="downstreamPipelines"
:is-merge-train="isMergeTrain"
diff --git a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
index 815f1a0e151..3b1b075559a 100644
--- a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
@@ -59,6 +59,7 @@ export default {
:chart-data="chart.data"
:area-chart-options="chartOptions"
>
+ <slot name="alerts"></slot>
<p>{{ dateRange }}</p>
<slot name="metrics" :selected-chart="selectedChart"></slot>
<template #tooltip-title>
diff --git a/app/finders/metrics/dashboards/annotations_finder.rb b/app/finders/metrics/dashboards/annotations_finder.rb
deleted file mode 100644
index e97704738ea..00000000000
--- a/app/finders/metrics/dashboards/annotations_finder.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module Metrics
- module Dashboards
- class AnnotationsFinder
- def initialize(dashboard:, params:)
- @dashboard = dashboard
- @params = params
- end
-
- def execute
- if dashboard.environment
- apply_filters_to(annotations_for_environment)
- else
- Metrics::Dashboard::Annotation.none
- end
- end
-
- private
-
- attr_reader :dashboard, :params
-
- def apply_filters_to(annotations)
- annotations = annotations.after(params[:from]) if params[:from].present?
- annotations = annotations.before(params[:to]) if params[:to].present? && valid_timespan_boundaries?
-
- by_dashboard(annotations)
- end
-
- def annotations_for_environment
- dashboard.environment.metrics_dashboard_annotations
- end
-
- def by_dashboard(annotations)
- annotations.for_dashboard(dashboard.path)
- end
-
- def valid_timespan_boundaries?
- params[:from].blank? || params[:to] >= params[:from]
- end
- end
- end
-end
diff --git a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
index aad9bbebafb..b967460c7ff 100644
--- a/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
+++ b/app/graphql/resolvers/metrics/dashboards/annotation_resolver.rb
@@ -16,11 +16,10 @@ module Resolvers
alias_method :dashboard, :object
- def resolve(**args)
+ def resolve(**_args)
return if Feature.enabled?(:remove_monitor_metrics)
- return [] unless dashboard
- ::Metrics::Dashboards::AnnotationsFinder.new(dashboard: dashboard, params: args).execute
+ []
end
end
end
diff --git a/lib/api/time_tracking_endpoints.rb b/lib/api/time_tracking_endpoints.rb
index 3534edc3831..d68057a1947 100644
--- a/lib/api/time_tracking_endpoints.rb
+++ b/lib/api/time_tracking_endpoints.rb
@@ -55,10 +55,11 @@ module API
issuable_key = "#{issuable_name}_iid".to_sym
desc "Set a time estimate for a #{issuable_name}" do
- detail " Sets an estimated time of work for this #{issuable_name}."
+ detail "Sets an estimated time of work for this #{issuable_name}."
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
+ { code: 400, message: 'Bad request' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
@@ -70,8 +71,14 @@ module API
post ":id/#{issuable_collection_name}/:#{issuable_key}/time_estimate" do
authorize! admin_issuable_key, load_issuable
- status :ok
- update_issuable(time_estimate: Gitlab::TimeTrackingFormatter.parse(params.delete(:duration)))
+ time_estimate = Gitlab::TimeTrackingFormatter.parse(params.delete(:duration), keep_zero: true)
+
+ if time_estimate && time_estimate >= 0
+ status :ok
+ update_issuable(time_estimate: time_estimate)
+ else
+ bad_request!(reason: 'Time estimate must have a valid format and be greater than or equal to zero.')
+ end
end
desc "Reset the time estimate for a project #{issuable_name}" do
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 7708473064f..269c4d9d9aa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5863,6 +5863,9 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
+msgid "ApprovalRule|Greater than"
+msgstr ""
+
msgid "ApprovalRule|Improve your organization's code review with required approvals."
msgstr ""
@@ -5872,6 +5875,9 @@ msgstr ""
msgid "ApprovalRule|Learn more about merge request approval rules."
msgstr ""
+msgid "ApprovalRule|Less than"
+msgstr ""
+
msgid "ApprovalRule|More than"
msgstr ""
@@ -5917,9 +5923,21 @@ msgstr ""
msgid "ApprovalRule|all groups"
msgstr ""
+msgid "ApprovalRule|day(s)"
+msgstr ""
+
+msgid "ApprovalRule|month(s)"
+msgstr ""
+
msgid "ApprovalRule|project groups"
msgstr ""
+msgid "ApprovalRule|week(s)"
+msgstr ""
+
+msgid "ApprovalRule||year(s)"
+msgstr ""
+
msgid "ApprovalSettings|Keep approvals"
msgstr ""
@@ -14331,6 +14349,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service (median days)"
msgstr ""
+msgid "DORA4Metrics|To help us improve the Show forecast feature, please share feedback about your experience in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "DORA4Metrics|Took 1 day or less to restore service when a service incident or a defect that impacts users occurs."
msgstr ""
@@ -40926,6 +40947,12 @@ msgstr ""
msgid "ScanResultPolicy|Add new criteria"
msgstr ""
+msgid "ScanResultPolicy|Age criteria can only be added for pre-existing vulnerabilities"
+msgstr ""
+
+msgid "ScanResultPolicy|Age is:"
+msgstr ""
+
msgid "ScanResultPolicy|Choose an option"
msgstr ""
@@ -40950,10 +40977,7 @@ msgstr ""
msgid "ScanResultPolicy|Matching"
msgstr ""
-msgid "ScanResultPolicy|Maximum number of severity-criteria is one"
-msgstr ""
-
-msgid "ScanResultPolicy|Maximum number of status-criteria is two"
+msgid "ScanResultPolicy|New age"
msgstr ""
msgid "ScanResultPolicy|New severity"
@@ -40965,6 +40989,15 @@ msgstr ""
msgid "ScanResultPolicy|Newly Detected"
msgstr ""
+msgid "ScanResultPolicy|Only 1 age criteria is allowed"
+msgstr ""
+
+msgid "ScanResultPolicy|Only 1 severity is allowed"
+msgstr ""
+
+msgid "ScanResultPolicy|Only 2 status criteria are allowed"
+msgstr ""
+
msgid "ScanResultPolicy|Pre-existing"
msgstr ""
@@ -47212,9 +47245,6 @@ msgstr ""
msgid "This PDF is too large to display. Please download to view."
msgstr ""
-msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
-msgstr ""
-
msgid "This URL already exists."
msgstr ""
@@ -47719,6 +47749,9 @@ msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project is archived and read-only. To resume pull mirroring, unarchive the project."
+msgstr ""
+
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
msgstr ""
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 4ec8cf27c76..fc1ccddb3f3 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -310,13 +310,14 @@ module QA
end
end
- # Check if the MR is able to be merged
- # Waits up 10 seconds and returns false if the MR can't be merged
- def mergeable?
- # The merge button is enabled via JS, but `has_element?` calls
- # `wait_for_requests`, which should ensure the disabled/enabled
- # state of the element is reliable
- has_element?(:merge_button, disabled: false)
+ RSpec::Matchers.define :be_mergeable do
+ match do |page|
+ page.has_element?(:merge_button, disabled: false)
+ end
+
+ match_when_negated do |page|
+ page.has_no_element?(:merge_button, disabled: false)
+ end
end
# Waits up 10 seconds and returns false if the Revert button is not enabled
diff --git a/spec/finders/metrics/dashboards/annotations_finder_spec.rb b/spec/finders/metrics/dashboards/annotations_finder_spec.rb
deleted file mode 100644
index 7c5932dde1e..00000000000
--- a/spec/finders/metrics/dashboards/annotations_finder_spec.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Metrics::Dashboards::AnnotationsFinder do
- describe '#execute' do
- subject(:annotations) { described_class.new(dashboard: dashboard, params: params).execute }
-
- let_it_be(:current_user) { create(:user) }
-
- let(:path) { 'config/prometheus/common_metrics.yml' }
- let(:params) { {} }
- let(:environment) { create(:environment) }
- let(:dashboard) { PerformanceMonitoring::PrometheusDashboard.new(path: path, environment: environment) }
-
- context 'there are no annotations records' do
- it 'returns empty array' do
- expect(annotations).to be_empty
- end
- end
-
- context 'with annotation records' do
- let!(:nine_minutes_old_annotation) { create(:metrics_dashboard_annotation, environment: environment, starting_at: 9.minutes.ago, dashboard_path: path) }
- let!(:fifteen_minutes_old_annotation) { create(:metrics_dashboard_annotation, environment: environment, starting_at: 15.minutes.ago, dashboard_path: path) }
- let!(:just_created_annotation) { create(:metrics_dashboard_annotation, environment: environment, dashboard_path: path) }
- let!(:annotation_for_different_env) { create(:metrics_dashboard_annotation, dashboard_path: path) }
- let!(:annotation_for_different_dashboard) { create(:metrics_dashboard_annotation, dashboard_path: '.gitlab/dashboards/test.yml') }
-
- it 'loads annotations' do
- expect(annotations).to match_array [fifteen_minutes_old_annotation, nine_minutes_old_annotation, just_created_annotation]
- end
-
- context 'when the from filter is present' do
- let(:params) do
- {
- from: 14.minutes.ago
- }
- end
-
- it 'loads only younger annotations' do
- expect(annotations).to match_array [nine_minutes_old_annotation, just_created_annotation]
- end
- end
-
- context 'when the to filter is present' do
- let(:params) do
- {
- to: 5.minutes.ago
- }
- end
-
- it 'loads only older annotations' do
- expect(annotations).to match_array [fifteen_minutes_old_annotation, nine_minutes_old_annotation]
- end
- end
-
- context 'when from and to filters are present' do
- context 'and to is bigger than from' do
- let(:params) do
- {
- from: 14.minutes.ago,
- to: 5.minutes.ago
- }
- end
-
- it 'loads only annotations assigned to this interval' do
- expect(annotations).to match_array [nine_minutes_old_annotation]
- end
- end
-
- context 'and from is bigger than to' do
- let(:params) do
- {
- to: 14.minutes.ago,
- from: 5.minutes.ago
- }
- end
-
- it 'ignores to parameter and returns annotations starting at from filter' do
- expect(annotations).to match_array [just_created_annotation]
- end
- end
-
- context 'when from or to filters are empty strings' do
- let(:params) do
- {
- from: '',
- to: ''
- }
- end
-
- it 'ignores this parameters' do
- expect(annotations).to match_array [fifteen_minutes_old_annotation, nine_minutes_old_annotation, just_created_annotation]
- end
- end
- end
-
- context 'dashboard environment is missing' do
- let(:dashboard) { PerformanceMonitoring::PrometheusDashboard.new(path: path, environment: nil) }
-
- it 'returns empty relation', :aggregate_failures do
- expect(annotations).to be_kind_of ::ActiveRecord::Relation
- expect(annotations).to be_empty
- end
- end
- end
- end
-end
diff --git a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
index 29759f828e4..f5e0b65d615 100644
--- a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_mini_graph_spec.js
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PipelineEditorMiniGraph from '~/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
import { PIPELINE_FAILURE } from '~/ci/pipeline_editor/constants';
import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data';
@@ -41,7 +41,7 @@ describe('Pipeline Status', () => {
});
};
- const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
beforeEach(() => {
mockLinkedPipelinesQuery = jest.fn();
@@ -53,7 +53,7 @@ describe('Pipeline Status', () => {
});
it('renders pipeline mini graph', () => {
- expect(findPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
});
});
@@ -63,7 +63,7 @@ describe('Pipeline Status', () => {
});
it('does not render pipeline mini graph', () => {
- expect(findPipelineMiniGraph().exists()).toBe(false);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(false);
});
});
@@ -85,7 +85,7 @@ describe('Pipeline Status', () => {
});
it('renders only the latest downstream pipelines', () => {
- expect(findPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
+ expect(findLegacyPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
});
});
diff --git a/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
index 9d93ba332e9..858cf24061a 100644
--- a/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/header/pipeline_status_spec.js
@@ -6,7 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PipelineStatus, { i18n } from '~/ci/pipeline_editor/components/header/pipeline_status.vue';
import getPipelineQuery from '~/ci/pipeline_editor/graphql/queries/pipeline.query.graphql';
-import GraphqlPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue';
+import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
import PipelineEditorMiniGraph from '~/ci/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
@@ -38,7 +38,7 @@ describe('Pipeline Status', () => {
const findIcon = () => wrapper.findComponent(GlIcon);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findGraphqlPipelineMiniGraph = () => wrapper.findComponent(GraphqlPipelineMiniGraph);
+ const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
const findPipelineEditorMiniGraph = () => wrapper.findComponent(PipelineEditorMiniGraph);
const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]');
const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]');
@@ -153,7 +153,7 @@ describe('Pipeline Status', () => {
await waitForPromises();
expect(findPipelineEditorMiniGraph().exists()).toBe(showPipelineMiniGraph);
- expect(findGraphqlPipelineMiniGraph().exists()).toBe(showGraphqlPipelineMiniGraph);
+ expect(findPipelineMiniGraph().exists()).toBe(showGraphqlPipelineMiniGraph);
},
);
});
diff --git a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
index 7983f8fddf5..79e1e087001 100644
--- a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
+++ b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
@@ -7,8 +7,8 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/alert';
import CommitBoxPipelineMiniGraph from '~/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue';
-import GraphqlPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import { COMMIT_BOX_POLL_INTERVAL } from '~/projects/commit_box/info/constants';
import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
@@ -29,8 +29,8 @@ describe('Commit box pipeline mini graph', () => {
let wrapper;
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findGraphqlPipelineMiniGraph = () => wrapper.findComponent(GraphqlPipelineMiniGraph);
const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
const downstreamHandler = jest.fn().mockResolvedValue(mockDownstreamQueryResponse);
const failedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
@@ -79,7 +79,7 @@ describe('Commit box pipeline mini graph', () => {
createComponent();
expect(findLoadingIcon().exists()).toBe(true);
- expect(findPipelineMiniGraph().exists()).toBe(false);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(false);
});
});
@@ -90,11 +90,11 @@ describe('Commit box pipeline mini graph', () => {
it('should not display loading state after the query is resolved', () => {
expect(findLoadingIcon().exists()).toBe(false);
- expect(findPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
});
it('should display the pipeline mini graph', () => {
- expect(findPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
});
});
@@ -127,7 +127,7 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- expect(findPipelineMiniGraph().props('stages')).toEqual(expectedStages);
+ expect(findLegacyPipelineMiniGraph().props('stages')).toEqual(expectedStages);
});
it('should render a downstream pipeline only', async () => {
@@ -135,8 +135,8 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- const downstreamPipelines = findPipelineMiniGraph().props('downstreamPipelines');
- const upstreamPipeline = findPipelineMiniGraph().props('upstreamPipeline');
+ const downstreamPipelines = findLegacyPipelineMiniGraph().props('downstreamPipelines');
+ const upstreamPipeline = findLegacyPipelineMiniGraph().props('upstreamPipeline');
expect(downstreamPipelines).toEqual(expect.any(Array));
expect(upstreamPipeline).toEqual(null);
@@ -147,7 +147,7 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- const downstreamPipelines = findPipelineMiniGraph().props('downstreamPipelines');
+ const downstreamPipelines = findLegacyPipelineMiniGraph().props('downstreamPipelines');
expect(downstreamPipelines).toHaveLength(1);
});
@@ -158,7 +158,7 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
const expectedPath = mockDownstreamQueryResponse.data.project.pipeline.path;
- const pipelinePath = findPipelineMiniGraph().props('pipelinePath');
+ const pipelinePath = findLegacyPipelineMiniGraph().props('pipelinePath');
expect(pipelinePath).toBe(expectedPath);
});
@@ -168,8 +168,8 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- const downstreamPipelines = findPipelineMiniGraph().props('downstreamPipelines');
- const upstreamPipeline = findPipelineMiniGraph().props('upstreamPipeline');
+ const downstreamPipelines = findLegacyPipelineMiniGraph().props('downstreamPipelines');
+ const upstreamPipeline = findLegacyPipelineMiniGraph().props('upstreamPipeline');
expect(upstreamPipeline).toEqual(samplePipeline);
expect(downstreamPipelines).toHaveLength(0);
@@ -180,8 +180,8 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- const downstreamPipelines = findPipelineMiniGraph().props('downstreamPipelines');
- const upstreamPipeline = findPipelineMiniGraph().props('upstreamPipeline');
+ const downstreamPipelines = findLegacyPipelineMiniGraph().props('downstreamPipelines');
+ const upstreamPipeline = findLegacyPipelineMiniGraph().props('upstreamPipeline');
expect(upstreamPipeline).toEqual(samplePipeline);
expect(downstreamPipelines).toEqual(
@@ -273,8 +273,8 @@ describe('Commit box pipeline mini graph', () => {
await waitForPromises();
- expect(findPipelineMiniGraph().exists()).toBe(showPipelineMiniGraph);
- expect(findGraphqlPipelineMiniGraph().exists()).toBe(showGraphqlPipelineMiniGraph);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(showPipelineMiniGraph);
+ expect(findPipelineMiniGraph().exists()).toBe(showGraphqlPipelineMiniGraph);
},
);
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph_spec.js
deleted file mode 100644
index 69b223461bd..00000000000
--- a/spec/frontend/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph_spec.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import { GlLoadingIcon } from '@gitlab/ui';
-
-import { createAlert } from '~/alert';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import createMockApollo from 'helpers/mock_apollo_helper';
-
-import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
-import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
-import GraphqlPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/graphql_pipeline_mini_graph.vue';
-import * as sharedGraphQlUtils from '~/graphql_shared/utils';
-
-import {
- linkedPipelinesFetchError,
- stagesFetchError,
- mockPipelineStagesQueryResponse,
- mockUpstreamDownstreamQueryResponse,
-} from './mock_data';
-
-Vue.use(VueApollo);
-jest.mock('~/alert');
-
-describe('GraphqlPipelineMiniGraph', () => {
- let wrapper;
- let linkedPipelinesResponse;
- let pipelineStagesResponse;
-
- const fullPath = 'gitlab-org/gitlab';
- const iid = '315';
- const pipelineEtag = '/api/graphql:pipelines/id/315';
-
- const createComponent = ({
- pipelineStagesHandler = pipelineStagesResponse,
- linkedPipelinesHandler = linkedPipelinesResponse,
- } = {}) => {
- const handlers = [
- [getLinkedPipelinesQuery, linkedPipelinesHandler],
- [getPipelineStagesQuery, pipelineStagesHandler],
- ];
- const mockApollo = createMockApollo(handlers);
-
- wrapper = shallowMountExtended(GraphqlPipelineMiniGraph, {
- propsData: {
- fullPath,
- iid,
- pipelineEtag,
- },
- apolloProvider: mockApollo,
- });
-
- return waitForPromises();
- };
-
- const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
-
- beforeEach(() => {
- linkedPipelinesResponse = jest.fn().mockResolvedValue(mockUpstreamDownstreamQueryResponse);
- pipelineStagesResponse = jest.fn().mockResolvedValue(mockPipelineStagesQueryResponse);
- });
-
- describe('when initial queries are loading', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('shows a loading icon and no mini graph', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findPipelineMiniGraph().exists()).toBe(false);
- });
- });
-
- describe('when queries have loaded', () => {
- it('does not show a loading icon', async () => {
- await createComponent();
-
- expect(findLoadingIcon().exists()).toBe(false);
- });
-
- it('renders the Pipeline Mini Graph', async () => {
- await createComponent();
-
- expect(findPipelineMiniGraph().exists()).toBe(true);
- });
-
- it('fires the queries', async () => {
- await createComponent();
-
- expect(linkedPipelinesResponse).toHaveBeenCalledWith({ iid, fullPath });
- expect(pipelineStagesResponse).toHaveBeenCalledWith({ iid, fullPath });
- });
- });
-
- describe('polling', () => {
- it('toggles query polling with visibility check', async () => {
- jest.spyOn(sharedGraphQlUtils, 'toggleQueryPollingByVisibility');
-
- createComponent();
-
- await waitForPromises();
-
- expect(sharedGraphQlUtils.toggleQueryPollingByVisibility).toHaveBeenCalledTimes(2);
- });
- });
-
- describe('when pipeline queries are unsuccessful', () => {
- const failedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
- it.each`
- query | handlerName | errorMessage
- ${'pipeline stages'} | ${'pipelineStagesHandler'} | ${stagesFetchError}
- ${'linked pipelines'} | ${'linkedPipelinesHandler'} | ${linkedPipelinesFetchError}
- `('throws an error for the $query query', async ({ errorMessage, handlerName }) => {
- await createComponent({ [handlerName]: failedHandler });
-
- await waitForPromises();
-
- expect(createAlert).toHaveBeenCalledWith({ message: errorMessage });
- });
- });
-});
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph_spec.js
new file mode 100644
index 00000000000..6661bb079d2
--- /dev/null
+++ b/spec/frontend/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph_spec.js
@@ -0,0 +1,122 @@
+import { mount } from '@vue/test-utils';
+import { pipelines } from 'test_fixtures/pipelines/pipelines.json';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
+import PipelineStages from '~/pipelines/components/pipeline_mini_graph/pipeline_stages.vue';
+import mockLinkedPipelines from './linked_pipelines_mock_data';
+
+const mockStages = pipelines[0].details.stages;
+
+describe('Legacy Pipeline Mini Graph', () => {
+ let wrapper;
+
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
+ const findPipelineStages = () => wrapper.findComponent(PipelineStages);
+
+ const findLinkedPipelineUpstream = () =>
+ wrapper.findComponent('[data-testid="pipeline-mini-graph-upstream"]');
+ const findLinkedPipelineDownstream = () =>
+ wrapper.findComponent('[data-testid="pipeline-mini-graph-downstream"]');
+ const findDownstreamArrowIcon = () => wrapper.find('[data-testid="downstream-arrow-icon"]');
+ const findUpstreamArrowIcon = () => wrapper.find('[data-testid="upstream-arrow-icon"]');
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(LegacyPipelineMiniGraph, {
+ propsData: {
+ stages: mockStages,
+ ...props,
+ },
+ });
+ };
+
+ describe('rendered state without upstream or downstream pipelines', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should render the pipeline stages', () => {
+ expect(findPipelineStages().exists()).toBe(true);
+ });
+
+ it('should have the correct props', () => {
+ expect(findLegacyPipelineMiniGraph().props()).toMatchObject({
+ downstreamPipelines: [],
+ isMergeTrain: false,
+ pipelinePath: '',
+ stages: expect.any(Array),
+ updateDropdown: false,
+ upstreamPipeline: undefined,
+ });
+ });
+
+ it('should have no linked pipelines', () => {
+ expect(findLinkedPipelineDownstream().exists()).toBe(false);
+ expect(findLinkedPipelineUpstream().exists()).toBe(false);
+ });
+
+ it('should not render arrow icons', () => {
+ expect(findUpstreamArrowIcon().exists()).toBe(false);
+ expect(findDownstreamArrowIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('rendered state with upstream pipeline', () => {
+ beforeEach(() => {
+ createComponent({
+ upstreamPipeline: mockLinkedPipelines.triggered_by,
+ });
+ });
+
+ it('should have the correct props', () => {
+ expect(findLegacyPipelineMiniGraph().props()).toMatchObject({
+ downstreamPipelines: [],
+ isMergeTrain: false,
+ pipelinePath: '',
+ stages: expect.any(Array),
+ updateDropdown: false,
+ upstreamPipeline: expect.any(Object),
+ });
+ });
+
+ it('should render the upstream linked pipelines mini list only', () => {
+ expect(findLinkedPipelineUpstream().exists()).toBe(true);
+ expect(findLinkedPipelineDownstream().exists()).toBe(false);
+ });
+
+ it('should render an upstream arrow icon only', () => {
+ expect(findDownstreamArrowIcon().exists()).toBe(false);
+ expect(findUpstreamArrowIcon().exists()).toBe(true);
+ expect(findUpstreamArrowIcon().props('name')).toBe('long-arrow');
+ });
+ });
+
+ describe('rendered state with downstream pipelines', () => {
+ beforeEach(() => {
+ createComponent({
+ downstreamPipelines: mockLinkedPipelines.triggered,
+ pipelinePath: 'my/pipeline/path',
+ });
+ });
+
+ it('should have the correct props', () => {
+ expect(findLegacyPipelineMiniGraph().props()).toMatchObject({
+ downstreamPipelines: expect.any(Array),
+ isMergeTrain: false,
+ pipelinePath: 'my/pipeline/path',
+ stages: expect.any(Array),
+ updateDropdown: false,
+ upstreamPipeline: undefined,
+ });
+ });
+
+ it('should render the downstream linked pipelines mini list only', () => {
+ expect(findLinkedPipelineDownstream().exists()).toBe(true);
+ expect(findLinkedPipelineUpstream().exists()).toBe(false);
+ });
+
+ it('should render a downstream arrow icon only', () => {
+ expect(findUpstreamArrowIcon().exists()).toBe(false);
+ expect(findDownstreamArrowIcon().exists()).toBe(true);
+ expect(findDownstreamArrowIcon().props('name')).toBe('long-arrow');
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
index e7415a6c596..b3e157f75f6 100644
--- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
+++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_mini_graph_spec.js
@@ -1,122 +1,123 @@
-import { mount } from '@vue/test-utils';
-import { pipelines } from 'test_fixtures/pipelines/pipelines.json';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlLoadingIcon } from '@gitlab/ui';
+
+import { createAlert } from '~/alert';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'helpers/mock_apollo_helper';
+
+import getLinkedPipelinesQuery from '~/pipelines/graphql/queries/get_linked_pipelines.query.graphql';
+import getPipelineStagesQuery from '~/pipelines/graphql/queries/get_pipeline_stages.query.graphql';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
-import PipelineStages from '~/pipelines/components/pipeline_mini_graph/pipeline_stages.vue';
-import mockLinkedPipelines from './linked_pipelines_mock_data';
+import * as sharedGraphQlUtils from '~/graphql_shared/utils';
-const mockStages = pipelines[0].details.stages;
+import {
+ linkedPipelinesFetchError,
+ stagesFetchError,
+ mockPipelineStagesQueryResponse,
+ mockUpstreamDownstreamQueryResponse,
+} from './mock_data';
-describe('Pipeline Mini Graph', () => {
- let wrapper;
-
- const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
- const findPipelineStages = () => wrapper.findComponent(PipelineStages);
-
- const findLinkedPipelineUpstream = () =>
- wrapper.findComponent('[data-testid="pipeline-mini-graph-upstream"]');
- const findLinkedPipelineDownstream = () =>
- wrapper.findComponent('[data-testid="pipeline-mini-graph-downstream"]');
- const findDownstreamArrowIcon = () => wrapper.find('[data-testid="downstream-arrow-icon"]');
- const findUpstreamArrowIcon = () => wrapper.find('[data-testid="upstream-arrow-icon"]');
+Vue.use(VueApollo);
+jest.mock('~/alert');
- const createComponent = (props = {}) => {
- wrapper = mount(PipelineMiniGraph, {
+describe('PipelineMiniGraph', () => {
+ let wrapper;
+ let linkedPipelinesResponse;
+ let pipelineStagesResponse;
+
+ const fullPath = 'gitlab-org/gitlab';
+ const iid = '315';
+ const pipelineEtag = '/api/graphql:pipelines/id/315';
+
+ const createComponent = ({
+ pipelineStagesHandler = pipelineStagesResponse,
+ linkedPipelinesHandler = linkedPipelinesResponse,
+ } = {}) => {
+ const handlers = [
+ [getLinkedPipelinesQuery, linkedPipelinesHandler],
+ [getPipelineStagesQuery, pipelineStagesHandler],
+ ];
+ const mockApollo = createMockApollo(handlers);
+
+ wrapper = shallowMountExtended(PipelineMiniGraph, {
propsData: {
- stages: mockStages,
- ...props,
+ fullPath,
+ iid,
+ pipelineEtag,
},
+ apolloProvider: mockApollo,
});
+
+ return waitForPromises();
};
- describe('rendered state without upstream or downstream pipelines', () => {
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+
+ beforeEach(() => {
+ linkedPipelinesResponse = jest.fn().mockResolvedValue(mockUpstreamDownstreamQueryResponse);
+ pipelineStagesResponse = jest.fn().mockResolvedValue(mockPipelineStagesQueryResponse);
+ });
+
+ describe('when initial queries are loading', () => {
beforeEach(() => {
createComponent();
});
- it('should render the pipeline stages', () => {
- expect(findPipelineStages().exists()).toBe(true);
+ it('shows a loading icon and no mini graph', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(false);
});
+ });
- it('should have the correct props', () => {
- expect(findPipelineMiniGraph().props()).toMatchObject({
- downstreamPipelines: [],
- isMergeTrain: false,
- pipelinePath: '',
- stages: expect.any(Array),
- updateDropdown: false,
- upstreamPipeline: undefined,
- });
+ describe('when queries have loaded', () => {
+ it('does not show a loading icon', async () => {
+ await createComponent();
+
+ expect(findLoadingIcon().exists()).toBe(false);
});
- it('should have no linked pipelines', () => {
- expect(findLinkedPipelineDownstream().exists()).toBe(false);
- expect(findLinkedPipelineUpstream().exists()).toBe(false);
+ it('renders the Pipeline Mini Graph', async () => {
+ await createComponent();
+
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
});
- it('should not render arrow icons', () => {
- expect(findUpstreamArrowIcon().exists()).toBe(false);
- expect(findDownstreamArrowIcon().exists()).toBe(false);
+ it('fires the queries', async () => {
+ await createComponent();
+
+ expect(linkedPipelinesResponse).toHaveBeenCalledWith({ iid, fullPath });
+ expect(pipelineStagesResponse).toHaveBeenCalledWith({ iid, fullPath });
});
});
- describe('rendered state with upstream pipeline', () => {
- beforeEach(() => {
- createComponent({
- upstreamPipeline: mockLinkedPipelines.triggered_by,
- });
- });
+ describe('polling', () => {
+ it('toggles query polling with visibility check', async () => {
+ jest.spyOn(sharedGraphQlUtils, 'toggleQueryPollingByVisibility');
- it('should have the correct props', () => {
- expect(findPipelineMiniGraph().props()).toMatchObject({
- downstreamPipelines: [],
- isMergeTrain: false,
- pipelinePath: '',
- stages: expect.any(Array),
- updateDropdown: false,
- upstreamPipeline: expect.any(Object),
- });
- });
+ createComponent();
- it('should render the upstream linked pipelines mini list only', () => {
- expect(findLinkedPipelineUpstream().exists()).toBe(true);
- expect(findLinkedPipelineDownstream().exists()).toBe(false);
- });
+ await waitForPromises();
- it('should render an upstream arrow icon only', () => {
- expect(findDownstreamArrowIcon().exists()).toBe(false);
- expect(findUpstreamArrowIcon().exists()).toBe(true);
- expect(findUpstreamArrowIcon().props('name')).toBe('long-arrow');
+ expect(sharedGraphQlUtils.toggleQueryPollingByVisibility).toHaveBeenCalledTimes(2);
});
});
- describe('rendered state with downstream pipelines', () => {
- beforeEach(() => {
- createComponent({
- downstreamPipelines: mockLinkedPipelines.triggered,
- pipelinePath: 'my/pipeline/path',
- });
- });
+ describe('when pipeline queries are unsuccessful', () => {
+ const failedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+ it.each`
+ query | handlerName | errorMessage
+ ${'pipeline stages'} | ${'pipelineStagesHandler'} | ${stagesFetchError}
+ ${'linked pipelines'} | ${'linkedPipelinesHandler'} | ${linkedPipelinesFetchError}
+ `('throws an error for the $query query', async ({ errorMessage, handlerName }) => {
+ await createComponent({ [handlerName]: failedHandler });
- it('should have the correct props', () => {
- expect(findPipelineMiniGraph().props()).toMatchObject({
- downstreamPipelines: expect.any(Array),
- isMergeTrain: false,
- pipelinePath: 'my/pipeline/path',
- stages: expect.any(Array),
- updateDropdown: false,
- upstreamPipeline: undefined,
- });
- });
-
- it('should render the downstream linked pipelines mini list only', () => {
- expect(findLinkedPipelineDownstream().exists()).toBe(true);
- expect(findLinkedPipelineUpstream().exists()).toBe(false);
- });
+ await waitForPromises();
- it('should render a downstream arrow icon only', () => {
- expect(findUpstreamArrowIcon().exists()).toBe(false);
- expect(findDownstreamArrowIcon().exists()).toBe(true);
- expect(findDownstreamArrowIcon().props('name')).toBe('long-arrow');
+ expect(createAlert).toHaveBeenCalledWith({ message: errorMessage });
});
});
});
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index e8a5e256a45..950a6b21e16 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -4,7 +4,7 @@ import { mount } from '@vue/test-utils';
import fixture from 'test_fixtures/pipelines/pipelines.json';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import PipelineFailedJobsWidget from '~/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue';
import PipelineOperations from '~/pipelines/components/pipelines_list/pipeline_operations.vue';
import PipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_triggerer.vue';
@@ -71,7 +71,7 @@ describe('Pipelines Table', () => {
const findCiBadgeLink = () => wrapper.findComponent(CiBadgeLink);
const findPipelineInfo = () => wrapper.findComponent(PipelineUrl);
const findTriggerer = () => wrapper.findComponent(PipelineTriggerer);
- const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
const findTimeAgo = () => wrapper.findComponent(PipelinesTimeago);
const findActions = () => wrapper.findComponent(PipelineOperations);
@@ -126,12 +126,12 @@ describe('Pipelines Table', () => {
describe('stages cell', () => {
it('should render pipeline mini graph', () => {
- expect(findPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
});
it('should render the right number of stages', () => {
const stagesLength = pipeline.details.stages.length;
- expect(findPipelineMiniGraph().props('stages').length).toBe(stagesLength);
+ expect(findLegacyPipelineMiniGraph().props('stages').length).toBe(stagesLength);
});
it('should render the latest downstream pipelines only', () => {
@@ -139,7 +139,7 @@ describe('Pipelines Table', () => {
// because we retried the trigger job, so the mini pipeline graph will only
// render the newly created downstream pipeline instead
expect(pipeline.triggered).toHaveLength(2);
- expect(findPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
+ expect(findLegacyPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
});
describe('when pipeline does not have stages', () => {
@@ -151,7 +151,7 @@ describe('Pipelines Table', () => {
});
it('stages are not rendered', () => {
- expect(findPipelineMiniGraph().props('stages')).toHaveLength(0);
+ expect(findLegacyPipelineMiniGraph().props('stages')).toHaveLength(0);
});
});
});
@@ -269,7 +269,7 @@ describe('Pipelines Table', () => {
});
it('tracks pipeline mini graph stage click', () => {
- findPipelineMiniGraph().vm.$emit('miniGraphStageClick');
+ findLegacyPipelineMiniGraph().vm.$emit('miniGraphStageClick');
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_minigraph', {
label: TRACKING_CATEGORIES.table,
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
index 98534624b32..a0064224b46 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
@@ -6,7 +6,7 @@ import { trimText } from 'helpers/text_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import MRWidgetPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
-import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
+import LegacyPipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import { SUCCESS } from '~/vue_merge_request_widget/constants';
import mockData from '../mock_data';
@@ -37,7 +37,7 @@ describe('MRWidgetPipeline', () => {
wrapper.findByTestId('pipeline-coverage-tooltip').text();
const findPipelineCoverageDeltaTooltipText = () =>
wrapper.findByTestId('pipeline-coverage-delta-tooltip').text();
- const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ const findLegacyPipelineMiniGraph = () => wrapper.findComponent(LegacyPipelineMiniGraph);
const findMonitoringPipelineMessage = () => wrapper.findByTestId('monitoring-pipeline-message');
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -101,8 +101,8 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline graph', () => {
const stagesCount = mockData.pipeline.details.stages.length;
- expect(findPipelineMiniGraph().exists()).toBe(true);
- expect(findPipelineMiniGraph().props('stages')).toHaveLength(stagesCount);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().props('stages')).toHaveLength(stagesCount);
});
it('should render the latest downstream pipelines only', () => {
@@ -110,7 +110,7 @@ describe('MRWidgetPipeline', () => {
// because we retried the trigger job, so the mini pipeline graph will only
// render the newly created downstream pipeline instead
expect(mockData.pipeline.triggered).toHaveLength(2);
- expect(findPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
+ expect(findLegacyPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
});
describe('should render pipeline coverage information', () => {
@@ -182,8 +182,8 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline graph', () => {
const stagesCount = mockData.pipeline.details.stages.length;
- expect(findPipelineMiniGraph().exists()).toBe(true);
- expect(findPipelineMiniGraph().props('stages')).toHaveLength(stagesCount);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(true);
+ expect(findLegacyPipelineMiniGraph().props('stages')).toHaveLength(stagesCount);
});
it('should render coverage information', () => {
@@ -215,7 +215,7 @@ describe('MRWidgetPipeline', () => {
});
it('should not render a pipeline graph', () => {
- expect(findPipelineMiniGraph().exists()).toBe(false);
+ expect(findLegacyPipelineMiniGraph().exists()).toBe(false);
});
});
diff --git a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
index 2ca194d519c..16e619cf9cd 100644
--- a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
+++ b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
@@ -30,36 +30,6 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver, feature_categ
end
context 'with annotation records' do
- let_it_be(:annotation_1) { create(:metrics_dashboard_annotation, environment: environment, starting_at: 9.minutes.ago, dashboard_path: path) }
-
- it 'loads annotations with usage of finder class', :aggregate_failures do
- expect_next_instance_of(::Metrics::Dashboards::AnnotationsFinder, dashboard: dashboard, params: args) do |finder|
- expect(finder).to receive(:execute).and_return [annotation_1]
- end
-
- expect(resolve_annotations).to eql [annotation_1]
- end
-
- context 'dashboard is missing' do
- let(:dashboard) { nil }
-
- it 'returns empty array', :aggregate_failures do
- expect(::Metrics::Dashboards::AnnotationsFinder).not_to receive(:new)
-
- expect(resolve_annotations).to be_empty
- end
- end
-
- context 'there are no annotations records' do
- it 'returns empty array' do
- allow_next_instance_of(::Metrics::Dashboards::AnnotationsFinder) do |finder|
- allow(finder).to receive(:execute).and_return []
- end
-
- expect(resolve_annotations).to be_empty
- end
- end
-
context 'when metrics dashboard feature is unavailable' do
before do
stub_feature_flags(remove_monitor_metrics: true)
@@ -69,6 +39,10 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver, feature_categ
expect(resolve_annotations).to be_nil
end
end
+
+ it 'returns [] all the time' do
+ expect(resolve_annotations).to be_empty
+ end
end
end
end
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index 0e48845a1dd..c208c98404e 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -4368,7 +4368,6 @@
- './spec/finders/merge_requests_finder_spec.rb'
- './spec/finders/merge_requests/oldest_per_commit_finder_spec.rb'
- './spec/finders/merge_request_target_project_finder_spec.rb'
-- './spec/finders/metrics/dashboards/annotations_finder_spec.rb'
- './spec/finders/metrics/users_starred_dashboards_finder_spec.rb'
- './spec/finders/milestones_finder_spec.rb'
- './spec/finders/namespaces/projects_finder_spec.rb'
diff --git a/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb b/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb
index 398421c7a79..dec15cb68b3 100644
--- a/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb
@@ -20,40 +20,49 @@ RSpec.shared_examples 'time tracking endpoints' do |issuable_name|
issuable_collection_name = issuable_name.pluralize
describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_estimate" do
+ subject(:set_time_estimate) do
+ post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: duration })
+ end
+
+ let(:duration) { '2h' }
+
context 'with an unauthorized user' do
- subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", non_member), params: { duration: '1w' }) }
+ let(:user) { non_member }
it_behaves_like 'an unauthorized API user'
it_behaves_like 'API user with insufficient permissions'
end
- it "sets the time estimate for #{issuable_name}" do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '1w' }
+ context 'with an authorized user' do
+ it "sets the time estimate for #{issuable_name}" do
+ set_time_estimate
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['human_time_estimate']).to eq('1w')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['time_estimate']).to eq(7200)
+ end
end
describe 'updating the current estimate' do
before do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '1w' }
+ post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '2h' })
end
- context 'when duration has a bad format' do
- it 'does not modify the original estimate' do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: 'foo' }
+ using RSpec::Parameterized::TableSyntax
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(issuable.reload.human_time_estimate).to eq('1w')
- end
+ where(:updated_duration, :expected_http_status, :expected_time_estimate) do
+ 'foo' | :bad_request | 7200
+ '-1' | :bad_request | 7200
+ '1h' | :ok | 3600
+ '0' | :ok | 0
end
- context 'with a valid duration' do
- it 'updates the estimate' do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '3w1h' }
+ with_them do
+ let(:duration) { updated_duration }
+ it 'returns expected HTTP status and time estimate' do
+ set_time_estimate
- expect(response).to have_gitlab_http_status(:ok)
- expect(issuable.reload.human_time_estimate).to eq('3w 1h')
+ expect(response).to have_gitlab_http_status(expected_http_status)
+ expect(issuable.reload.time_estimate).to eq(expected_time_estimate)
end
end
end