summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-30 21:10:23 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-30 21:10:23 +0000
commit07de48228886ca6afa348c92f8689b9027e4c195 (patch)
treea3ba7bae1edb47180352d080136141af40a3e8a2
parentd899d2a373f8be3d94760299faafa19c3c432c1e (diff)
downloadgitlab-ce-07de48228886ca6afa348c92f8689b9027e4c195.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue40
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js2
-rw-r--r--app/assets/javascripts/environments/stores/helpers.js2
-rw-r--r--app/assets/javascripts/learn_gitlab/track_learn_gitlab.js10
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue10
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue10
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/index/index.js3
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue19
-rw-r--r--app/graphql/mutations/issues/set_due_date.rb13
-rw-r--r--app/helpers/learn_gitlab_helper.rb10
-rw-r--r--app/helpers/sidebars_helper.rb1
-rw-r--r--changelogs/unreleased/accept-null-in-issuesetduedate.yml5
-rw-r--r--changelogs/unreleased/afontaine-show-deploy-boards-for-folders.yml5
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/v3_to_v4.md88
-rw-r--r--doc/user/project/deploy_boards.md12
-rw-r--r--lib/sidebars/projects/menus/learn_gitlab_menu.rb9
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/frontend/environments/environment_table_spec.js38
-rw-r--r--spec/frontend/environments/environments_store_spec.js23
-rw-r--r--spec/frontend/learn_gitlab/track_learn_gitlab_spec.js21
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap63
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap27
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js53
-rw-r--r--spec/graphql/mutations/issues/set_due_date_spec.rb19
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb33
-rw-r--r--spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb32
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb31
28 files changed, 445 insertions, 139 deletions
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index cbce887f491..f82d3065ca5 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -188,15 +188,37 @@ export default {
</div>
<template v-else>
- <div
- is="environment-item"
- v-for="(children, index) in model.children"
- :key="`env-item-${i}-${index}`"
- :model="children"
- :can-read-environment="canReadEnvironment"
- :table-data="tableData"
- data-qa-selector="environment_item"
- />
+ <template v-for="(child, index) in model.children">
+ <div
+ is="environment-item"
+ :key="`environment-row-${i}-${index}`"
+ :model="child"
+ :can-read-environment="canReadEnvironment"
+ :table-data="tableData"
+ data-qa-selector="environment_item"
+ />
+
+ <div
+ v-if="shouldRenderDeployBoard(child)"
+ :key="`deploy-board-row-${i}-${index}`"
+ class="js-deploy-board-row"
+ >
+ <div class="deploy-board-container">
+ <deploy-board
+ :deploy-board-data="child.deployBoardData"
+ :is-loading="child.isLoadingDeployBoard"
+ :is-empty="child.isEmptyDeployBoard"
+ :logs-path="child.logs_path"
+ @changeCanaryWeight="changeCanaryWeight(child, $event)"
+ />
+ </div>
+ </div>
+ <environment-alert
+ v-if="shouldRenderAlert(model)"
+ :key="`alert-row-${i}-${index}`"
+ :environment="child"
+ />
+ </template>
<div :key="`sub-div-${i}`">
<div class="text-center gl-mt-3">
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index f7fdbb03f04..a67e44b3348 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -185,6 +185,8 @@ export default class EnvironmentsStore {
updated.isChildren = true;
+ updated = setDeployBoard(env, updated);
+
return updated;
});
diff --git a/app/assets/javascripts/environments/stores/helpers.js b/app/assets/javascripts/environments/stores/helpers.js
index 89457da0614..3330edd8830 100644
--- a/app/assets/javascripts/environments/stores/helpers.js
+++ b/app/assets/javascripts/environments/stores/helpers.js
@@ -4,7 +4,7 @@
*/
export const setDeployBoard = (oldEnvironmentState, environment) => {
let parsedEnvironment = environment;
- if (environment.size === 1 && environment.rollout_status) {
+ if (!environment.isFolder && environment.rollout_status) {
parsedEnvironment = {
...environment,
hasDeployBoard: true,
diff --git a/app/assets/javascripts/learn_gitlab/track_learn_gitlab.js b/app/assets/javascripts/learn_gitlab/track_learn_gitlab.js
new file mode 100644
index 00000000000..305d130f10c
--- /dev/null
+++ b/app/assets/javascripts/learn_gitlab/track_learn_gitlab.js
@@ -0,0 +1,10 @@
+import Tracking from '~/tracking';
+
+export default function trackLearnGitlab(learnGitlabA) {
+ Tracking.event('projects:learn_gitlab:index', 'page_init', {
+ label: 'learn_gitlab',
+ property: learnGitlabA
+ ? 'Growth::Conversion::Experiment::LearnGitLabA'
+ : 'Growth::Activation::Experiment::LearnGitLabB',
+ });
+}
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
index 6cd3bbc359b..ad6dfbf41ca 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
@@ -64,7 +64,15 @@ export default {
<img :src="svg" :alt="actionLabel" />
<h6>{{ title }}</h6>
<p class="gl-font-sm gl-text-gray-700">{{ description }}</p>
- <gl-link :href="url" target="_blank">{{ actionLabel }}</gl-link>
+ <gl-link
+ :href="url"
+ target="_blank"
+ rel="noopener noreferrer"
+ data-track-action="click_link"
+ :data-track-label="actionLabel"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
+ >{{ actionLabel }}</gl-link
+ >
</div>
</gl-card>
</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
index 6f51c7372fd..3d31ac6c267 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
@@ -34,7 +34,15 @@ export default {
{{ $options.i18n.ACTION_LABELS[action].title }}
</span>
<span v-else>
- <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link>
+ <gl-link
+ target="_blank"
+ :href="value.url"
+ data-track-action="click_link"
+ :data-track-label="$options.i18n.ACTION_LABELS[action].title"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
+ >
+ {{ $options.i18n.ACTION_LABELS[action].title }}
+ </gl-link>
</span>
<span v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only">
- {{ $options.i18n.trialOnly }}
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
index c4dec89b984..d9ad29fad99 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import trackLearnGitlab from '~/learn_gitlab/track_learn_gitlab';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import LearnGitlabA from '../components/learn_gitlab_a.vue';
import LearnGitlabB from '../components/learn_gitlab_b.vue';
@@ -14,6 +15,8 @@ function initLearnGitlab() {
const { learnGitlabA } = gon.experiments;
+ trackLearnGitlab(learnGitlabA);
+
return new Vue({
el,
render(createElement) {
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
index 2edc84e62cb..47e5bb0bde8 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
@@ -1,6 +1,6 @@
<script>
-import { GlBadge, GlModal } from '@gitlab/ui';
-import { __, n__, sprintf } from '~/locale';
+import { GlBadge, GlFriendlyWrap, GlLink, GlModal } from '@gitlab/ui';
+import { __, n__, s__, sprintf } from '~/locale';
import CodeBlock from '~/vue_shared/components/code_block.vue';
export default {
@@ -8,6 +8,8 @@ export default {
components: {
CodeBlock,
GlBadge,
+ GlFriendlyWrap,
+ GlLink,
GlModal,
},
props: {
@@ -50,6 +52,7 @@ export default {
duration: __('Execution time'),
history: __('History'),
trace: __('System output'),
+ attachment: s__('TestReports|Attachment'),
},
modalCloseButton: {
text: __('Close'),
@@ -85,6 +88,18 @@ export default {
</div>
</div>
+ <div v-if="testCase.attachment_url" class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
+ <strong class="gl-text-right col-sm-3">{{ $options.text.attachment }}</strong>
+ <gl-link
+ class="col-sm-9"
+ :href="testCase.attachment_url"
+ target="_blank"
+ data-testid="test-case-attachment-url"
+ >
+ <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.attachment_url" />
+ </gl-link>
+ </div>
+
<div
v-if="testCase.system_output"
class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3"
diff --git a/app/graphql/mutations/issues/set_due_date.rb b/app/graphql/mutations/issues/set_due_date.rb
index da7892f4ed4..22a72e201ba 100644
--- a/app/graphql/mutations/issues/set_due_date.rb
+++ b/app/graphql/mutations/issues/set_due_date.rb
@@ -7,8 +7,17 @@ module Mutations
argument :due_date,
Types::TimeType,
- required: true,
- description: 'The desired due date for the issue.'
+ required: false,
+ description: 'The desired due date for the issue, ' \
+ 'due date will be removed if absent or set to null'
+
+ def ready?(**args)
+ unless args.key?(:due_date)
+ raise Gitlab::Graphql::Errors::ArgumentError, 'Argument dueDate must be provided (`null` accepted)'
+ end
+
+ super
+ end
def resolve(project_path:, iid:, due_date:)
issue = authorized_find!(project_path: project_path, iid: iid)
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index fc03c986830..51dce76c749 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -8,6 +8,16 @@ module LearnGitlabHelper
learn_gitlab_onboarding_available?(project)
end
+ def learn_gitlab_experiment_tracking_category
+ return unless current_user
+
+ if Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_a, subject: current_user)
+ Gitlab::Experimentation.get_experiment(:learn_gitlab_a).tracking_category
+ elsif Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_b, subject: current_user)
+ Gitlab::Experimentation.get_experiment(:learn_gitlab_b).tracking_category
+ end
+ end
+
def onboarding_actions_data(project)
attributes = onboarding_progress(project).attributes.symbolize_keys
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index ddf5461715f..0c9e3287e28 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -39,6 +39,7 @@ module SidebarsHelper
current_user: user,
container: project,
learn_gitlab_experiment_enabled: learn_gitlab_experiment_enabled?(project),
+ learn_gitlab_experiment_tracking_category: learn_gitlab_experiment_tracking_category,
current_ref: current_ref,
jira_issues_integration: project_jira_issues_integration?,
can_view_pipeline_editor: can_view_pipeline_editor?(project),
diff --git a/changelogs/unreleased/accept-null-in-issuesetduedate.yml b/changelogs/unreleased/accept-null-in-issuesetduedate.yml
new file mode 100644
index 00000000000..cba2b3ae340
--- /dev/null
+++ b/changelogs/unreleased/accept-null-in-issuesetduedate.yml
@@ -0,0 +1,5 @@
+---
+title: Allow issueSetDueDate GraphQL mutation to accept null values
+merge_request: 60139
+author:
+type: added
diff --git a/changelogs/unreleased/afontaine-show-deploy-boards-for-folders.yml b/changelogs/unreleased/afontaine-show-deploy-boards-for-folders.yml
new file mode 100644
index 00000000000..ff43117751f
--- /dev/null
+++ b/changelogs/unreleased/afontaine-show-deploy-boards-for-folders.yml
@@ -0,0 +1,5 @@
+---
+title: Show Deploy Boards for Environments in Folders
+merge_request: 60525
+author:
+type: added
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index fa20e0b48e9..6c170bab6e7 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -2337,7 +2337,7 @@ Input type: `IssueSetDueDateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationissuesetduedateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationissuesetduedateduedate"></a>`dueDate` | [`Time!`](#time) | The desired due date for the issue. |
+| <a id="mutationissuesetduedateduedate"></a>`dueDate` | [`Time`](#time) | The desired due date for the issue, due date will be removed if absent or set to null. |
| <a id="mutationissuesetduedateiid"></a>`iid` | [`String!`](#string) | The IID of the issue to mutate. |
| <a id="mutationissuesetduedateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project the issue to mutate is in. |
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index 38d583cf1d8..c6d883371a3 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -6,87 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# API V3 to API V4
-In GitLab 9.0 and later, API V4 is the preferred version to be used.
+WARNING:
+The GitLab API v3 was removed in [GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819).
-API V3 was unsupported from GitLab 9.5, released on August
-22, 2017. API v3 was removed in [GitLab 11.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36819).
-The V3 API documentation is still
-[available](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-16-stable/doc/api/README.md).
+For information about the current version of the GitLab API, read the [API documentation](README.md).
-Below are the changes made between V3 and V4.
+## Related links
-## 8.17
-
-- Removed `GET /projects/:search` (use: `GET /projects?search=x`) [!8877](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8877)
-- `iid` filter has been removed from `GET /projects/:id/issues` [!8967](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8967)
-- `GET /projects/:id/merge_requests?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793)
-- Endpoints under `GET /projects/merge_request/:id` have been removed (use: `GET /projects/merge_requests/:id`) [!8793](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8793)
-- Project snippets do not return deprecated field `expires_at` [!8723](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8723)
-- Endpoints under `GET /projects/:id/keys` have been removed (use `GET /projects/:id/deploy_keys`) [!8716](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8716)
-
-## 9.0
-
-- Status 409 returned for `POST /projects/:id/members` when a member already exists [!9093](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9093)
-- Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar` [!9328](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9328)
-- Removed the following deprecated Templates endpoints (these are still accessible with `/templates` prefix) [!8853](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8853)
- - `/licenses`
- - `/licenses/:key`
- - `/gitignores`
- - `/gitlab_ci_ymls`
- - `/dockerfiles`
- - `/gitignores/:key`
- - `/gitlab_ci_ymls/:key`
- - `/dockerfiles/:key`
-- Moved `POST /projects/fork/:id` to `POST /projects/:id/fork` [!8940](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8940)
-- Moved `DELETE /todos` to `POST /todos/mark_as_done` and `DELETE /todos/:todo_id` to `POST /todos/:todo_id/mark_as_done` [!9410](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9410)
-- Project filters are no longer available as `GET /projects/foo`, but as `GET /projects?foo=true` instead [!8962](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8962)
- - `GET /projects/visible` & `GET /projects/all` are consolidated into `GET /projects` and can be used with or without authorization
- - `GET /projects/owned` moved to `GET /projects?owned=true`
- - `GET /projects/starred` moved to `GET /projects?starred=true`
-- `GET /projects` returns all projects visible to current user, even if the user is not a member [!9674](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9674)
- - To get projects the user is a member of, use `GET /projects?membership=true`
-- Return pagination headers for all endpoints that return an array [!8606](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8606)
-- Added `POST /environments/:environment_id/stop` to stop an environment [!8808](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8808)
-- Removed `DELETE /projects/:id/deploy_keys/:key_id/disable`. Use `DELETE /projects/:id/deploy_keys/:key_id` instead [!9366](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9366)
-- Moved `PUT /users/:id/(block|unblock)` to `POST /users/:id/(block|unblock)` [!9371](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9371)
-- Make subscription API more RESTful. Use `POST /projects/:id/:subscribable_type/:subscribable_id/subscribe` to subscribe and `POST /projects/:id/:subscribable_type/:subscribable_id/unsubscribe` to unsubscribe from a resource. [!9325](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9325)
-- Labels filter on `GET /projects/:id/issues` and `GET /issues` now matches only issues containing all labels (i.e.: Logical AND, not OR) [!8849](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8849)
-- Renamed parameter `branch_name` to `branch` on the following endpoints [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936)
- - `POST /projects/:id/repository/branches`
- - `POST /projects/:id/repository/commits`
- - `POST/PUT/DELETE :id/repository/files`
-- Renamed the `merge_when_build_succeeds` parameter to `merge_when_pipeline_succeeds` on the following endpoints: [!9335](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/)
- - `PUT /projects/:id/merge_requests/:merge_request_id/merge`
- - `POST /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_pipeline_succeeds`
- - `POST /projects`
- - `POST /projects/user/:user_id`
- - `PUT /projects/:id`
-- Renamed `branch_name` to `branch` on `DELETE /projects/:id/repository/branches/:branch` response [!8936](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8936)
-- Remove `public` parameter from create and edit actions of projects [!8736](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8736)
-- Remove `subscribed` field from responses returning list of issues or merge
- requests. Fetch individual issues or merge requests to obtain the value
- of `subscribed`
- [!9661](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9661)
-- Use `visibility` as string parameter everywhere [!9337](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9337)
-- Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9384)
-- Return HTTP status code `400` for all validation errors when creating or updating a member instead of sometimes `422` error. [!9523](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9523)
-- Remove `GET /groups/owned`. Use `GET /groups?owned=true` instead [!9505](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9505)
-- Return 202 with JSON body on asynchronous removals on V4 API (`DELETE /projects/:id/repository/merged_branches` and `DELETE /projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9449)
-- `GET /projects/:id/milestones?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!9096](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9096)
-- Return basic information about pipeline in `GET /projects/:id/pipelines` [!8875](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8875)
-- Renamed all `build` references to `job` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463)
-- Drop `GET /projects/:id/repository/commits/:sha/jobs` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463)
-- Rename Build Triggers to be Pipeline Triggers API [!9713](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9713)
- - `POST /projects/:id/trigger/builds` to `POST /projects/:id/trigger/pipeline`
- - Require description when creating a new trigger `POST /projects/:id/triggers`
-- Simplify project payload exposed on Environment endpoints [!9675](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9675)
-- API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, to-dos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
-- API uses issue `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the issues, award emoji, to-dos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
-- Change initial page from `0` to `1` on `GET /projects/:id/repository/commits` (like on the rest of the API) [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679)
-- Return correct `Link` header data for `GET /projects/:id/repository/commits` [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679)
-- Update endpoints for repository files [!9637](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9637)
- - Moved `GET /projects/:id/repository/files?file_path=:file_path` to `GET /projects/:id/repository/files/:file_path` (`:file_path` should be URL-encoded)
- - `GET /projects/:id/repository/blobs/:sha` now returns JSON attributes for the blob identified by `:sha`, instead of finding the commit identified by `:sha` and returning the raw content of the blob in that commit identified by the required `?filepath=:filepath`
- - Moved `GET /projects/:id/repository/commits/:sha/blob?file_path=:file_path` and `GET /projects/:id/repository/blobs/:sha?file_path=:file_path` to `GET /projects/:id/repository/files/:file_path/raw?ref=:sha`
- - `GET /projects/:id/repository/tree` parameter `ref_name` has been renamed to `ref` for consistency
-- `confirm` parameter for `POST /users` has been deprecated in favor of `skip_confirmation` parameter
+- [GitLab v3 API documentation](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-16-stable/doc/api/README.md)
+- [Migration guide](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md) from
+ v3 to v4
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 368417ac00b..804c013d317 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -8,7 +8,13 @@ type: howto, reference
# Deploy Boards **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
-> - [Moved](<https://gitlab.com/gitlab-org/gitlab/-/issues/212320>) to GitLab Free in 13.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to GitLab Free in 13.8.
+> - In GitLab 13.5 and earlier, apps that consist of multiple deployments are shown as
+> duplicates on the deploy board. This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/8463)
+> in GitLab 13.6.
+> - In GitLab 13.11 and earlier, environments in folders do not show deploy boards.
+> This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60525) in
+> GitLab 13.12.
GitLab Deploy Boards offer a consolidated view of the current health and
status of each CI [environment](../../ci/environments/index.md) running on [Kubernetes](https://kubernetes.io), displaying the status
@@ -46,10 +52,6 @@ knowledge. In particular, you should be familiar with:
- [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
- [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
-In GitLab 13.5 and earlier, apps that consist of multiple deployments are shown as
-duplicates on the deploy board. This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/8463)
-in GitLab 13.6.
-
## Use cases
Since the Deploy Board is a visual representation of the Kubernetes pods for a
diff --git a/lib/sidebars/projects/menus/learn_gitlab_menu.rb b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
index 62596c4fbd7..e3fcd8f25d5 100644
--- a/lib/sidebars/projects/menus/learn_gitlab_menu.rb
+++ b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
@@ -37,7 +37,14 @@ module Sidebars
override :extra_container_html_options
def nav_link_html_options
- { class: 'home' }
+ {
+ class: 'home',
+ data: {
+ track_action: 'click_menu',
+ track_property: context.learn_gitlab_experiment_tracking_category,
+ track_label: 'learn_gitlab'
+ }
+ }
end
override :image_path
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 843f35a6863..d1904a3169e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -31588,6 +31588,9 @@ msgstr ""
msgid "TestReports|%{rate}%{sign} success rate"
msgstr ""
+msgid "TestReports|Attachment"
+msgstr ""
+
msgid "TestReports|Jobs"
msgstr ""
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index b08fa8d5117..71426ee5170 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -89,6 +89,42 @@ describe('Environment table', () => {
expect(wrapper.find('.deploy-board-icon').exists()).toBe(true);
});
+ it('should render deploy board container when data is provided for children', async () => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ logs_path: 'url',
+ id: 1,
+ isFolder: true,
+ isOpen: true,
+ children: [
+ {
+ name: 'review/test',
+ hasDeployBoard: true,
+ deployBoardData: deployBoardMockData,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ },
+ ],
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canCreateDeployment: false,
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ expect(wrapper.find('.js-deploy-board-row').exists()).toBe(true);
+ expect(wrapper.find('.deploy-board-icon').exists()).toBe(true);
+ });
+
it('should toggle deploy board visibility when arrow is clicked', (done) => {
const mockItem = {
name: 'review',
@@ -125,7 +161,7 @@ describe('Environment table', () => {
wrapper.find('.deploy-board-icon').trigger('click');
});
- it('should set the enviornment to change and weight when a change canary weight event is recevied', async () => {
+ it('should set the environment to change and weight when a change canary weight event is recevied', async () => {
const mockItem = {
name: 'review',
size: 1,
diff --git a/spec/frontend/environments/environments_store_spec.js b/spec/frontend/environments/environments_store_spec.js
index 4a07281353f..cb2394b224d 100644
--- a/spec/frontend/environments/environments_store_spec.js
+++ b/spec/frontend/environments/environments_store_spec.js
@@ -123,6 +123,29 @@ describe('Store', () => {
expect(store.state.environments[1].children.length).toEqual(serverData.length);
});
+
+ it('should parse deploy board data for children', () => {
+ store.storeEnvironments(serverData);
+
+ store.setfolderContent(store.state.environments[1], [
+ {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ rollout_status: deployBoardMockData,
+ },
+ },
+ ]);
+ const result = store.state.environments[1].children[0];
+ expect(result).toMatchObject({
+ deployBoardData: deployBoardMockData,
+ hasDeployBoard: true,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ });
+ });
});
describe('store pagination', () => {
diff --git a/spec/frontend/learn_gitlab/track_learn_gitlab_spec.js b/spec/frontend/learn_gitlab/track_learn_gitlab_spec.js
new file mode 100644
index 00000000000..3fb38a74c70
--- /dev/null
+++ b/spec/frontend/learn_gitlab/track_learn_gitlab_spec.js
@@ -0,0 +1,21 @@
+import { mockTracking } from 'helpers/tracking_helper';
+import trackLearnGitlab from '~/learn_gitlab/track_learn_gitlab';
+
+describe('trackTrialUserErrors', () => {
+ let spy;
+
+ describe('when an error is present', () => {
+ beforeEach(() => {
+ spy = mockTracking('projects:learn_gitlab_index', document.body, jest.spyOn);
+ });
+
+ it('tracks the error message', () => {
+ trackLearnGitlab();
+
+ expect(spy).toHaveBeenCalledWith('projects:learn_gitlab:index', 'page_init', {
+ label: 'learn_gitlab',
+ property: 'Growth::Activation::Experiment::LearnGitLabB',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
index 8b54a06ac7c..981e4c84323 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
@@ -134,9 +134,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Set up CI/CD"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Set up CI/CD
+
+ Set up CI/CD
+
</a>
</span>
@@ -148,9 +155,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Start a free Ultimate trial"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Start a free Ultimate trial
+
+ Start a free Ultimate trial
+
</a>
</span>
@@ -162,9 +176,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Add code owners"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Add code owners
+
+ Add code owners
+
</a>
</span>
@@ -183,9 +204,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Add merge request approval"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Add merge request approval
+
+ Add merge request approval
+
</a>
</span>
@@ -240,9 +268,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Create an issue"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Create an issue
+
+ Create an issue
+
</a>
</span>
@@ -254,9 +289,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Submit a merge request"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Submit a merge request
+
+ Submit a merge request
+
</a>
</span>
@@ -304,9 +346,16 @@ exports[`Learn GitLab Design A renders correctly 1`] = `
<span>
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Run a Security scan using CI/CD"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLabA"
href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
>
- Run a Security scan using CI/CD
+
+ Run a Security scan using CI/CD
+
</a>
</span>
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
index 07c7f2df09e..3161517c916 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
@@ -110,6 +110,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Invite your colleagues"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -168,6 +171,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Create or import a repository"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -218,6 +224,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Set-up CI/CD"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -268,6 +277,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Try GitLab Ultimate for free"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -323,6 +335,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Add code owners"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -378,6 +393,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Enable require merge approvals"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -444,6 +462,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Create an issue"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -494,6 +515,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Submit a merge request (MR)"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
@@ -560,6 +584,9 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
<a
class="gl-link"
+ data-track-action="click_link"
+ data-track-label="Run a Security scan using CI/CD"
+ data-track-property="Growth::Activation::Experiment::LearnGitLabB"
href="http://example.com/"
rel="noopener noreferrer"
target="_blank"
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
index 64c6f08dce0..c995eb864d1 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -1,5 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
@@ -18,24 +19,27 @@ describe('Test case details', () => {
system_output: 'Line 42 is broken',
};
- const findModal = () => wrapper.find(GlModal);
- const findName = () => wrapper.find('[data-testid="test-case-name"]');
- const findDuration = () => wrapper.find('[data-testid="test-case-duration"]');
- const findRecentFailures = () => wrapper.find('[data-testid="test-case-recent-failures"]');
- const findSystemOutput = () => wrapper.find('[data-testid="test-case-trace"]');
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findName = () => wrapper.findByTestId('test-case-name');
+ const findDuration = () => wrapper.findByTestId('test-case-duration');
+ const findRecentFailures = () => wrapper.findByTestId('test-case-recent-failures');
+ const findAttachmentUrl = () => wrapper.findByTestId('test-case-attachment-url');
+ const findSystemOutput = () => wrapper.findByTestId('test-case-trace');
const createComponent = (testCase = {}) => {
- wrapper = shallowMount(TestCaseDetails, {
- localVue,
- propsData: {
- modalId: 'my-modal',
- testCase: {
- ...defaultTestCase,
- ...testCase,
+ wrapper = extendedWrapper(
+ shallowMount(TestCaseDetails, {
+ localVue,
+ propsData: {
+ modalId: 'my-modal',
+ testCase: {
+ ...defaultTestCase,
+ ...testCase,
+ },
},
- },
- stubs: { CodeBlock, GlModal },
- });
+ stubs: { CodeBlock, GlModal },
+ }),
+ );
};
afterEach(() => {
@@ -91,6 +95,25 @@ describe('Test case details', () => {
});
});
+ describe('when test case has attachment URL', () => {
+ it('renders the attachment URL as a link', () => {
+ const expectedUrl = '/my/path.jpg';
+ createComponent({ attachment_url: expectedUrl });
+ const attachmentUrl = findAttachmentUrl();
+
+ expect(attachmentUrl.exists()).toBe(true);
+ expect(attachmentUrl.attributes('href')).toBe(expectedUrl);
+ });
+ });
+
+ describe('when test case does not have attachment URL', () => {
+ it('does not render the attachment URL', () => {
+ createComponent({ attachment_url: null });
+
+ expect(findAttachmentUrl().exists()).toBe(false);
+ });
+ });
+
describe('when test case has system output', () => {
it('renders the test case system output', () => {
createComponent();
diff --git a/spec/graphql/mutations/issues/set_due_date_spec.rb b/spec/graphql/mutations/issues/set_due_date_spec.rb
index 9f8d0d6c405..263122e5d5f 100644
--- a/spec/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/graphql/mutations/issues/set_due_date_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Mutations::Issues::SetDueDate do
- let(:issue) { create(:issue) }
- let(:user) { create(:user) }
+ let(:issue) { create(:issue, due_date: '2021-05-01') }
+
+ let_it_be(:user) { create(:user) }
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
@@ -23,17 +24,25 @@ RSpec.describe Mutations::Issues::SetDueDate do
issue.project.add_developer(user)
end
- it 'returns the issue with updated due date' do
+ it 'returns the issue with updated due date', :aggregate_failures do
expect(mutated_issue).to eq(issue)
expect(mutated_issue.due_date).to eq(Date.today + 2.days)
expect(subject[:errors]).to be_empty
end
+ context 'when due date is nil' do
+ let(:due_date) { nil }
+
+ it 'updates due date to be nil' do
+ expect(mutated_issue.due_date).to be nil
+ end
+ end
+
context 'when passing incorrect due date value' do
let(:due_date) { 'test' }
- it 'does not update due date' do
- expect(mutated_issue.due_date).to eq(issue.due_date)
+ it 'updates due date to be nil' do
+ expect(mutated_issue.due_date).to be nil
end
end
end
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
index 796542aa2b5..5bbe32166ab 100644
--- a/spec/helpers/learn_gitlab_helper_spec.rb
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -91,4 +91,37 @@ RSpec.describe LearnGitlabHelper do
end
end
end
+
+ describe '.learn_gitlab_experiment_tracking_category' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+
+ subject { helper.learn_gitlab_experiment_tracking_category }
+
+ where(:experiment_a, :experiment_b, :result) do
+ false | false | nil
+ false | true | 'Growth::Activation::Experiment::LearnGitLabB'
+ true | false | 'Growth::Conversion::Experiment::LearnGitLabA'
+ true | true | 'Growth::Conversion::Experiment::LearnGitLabA'
+ end
+
+ with_them do
+ before do
+ stub_experiment_for_subject(learn_gitlab_a: experiment_a, learn_gitlab_b: experiment_b)
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ context 'when not signed in' do
+ it { is_expected.to eq(nil) }
+ end
+ end
+ end
end
diff --git a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
index 6bcc62bd973..dc1aecc6546 100644
--- a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
@@ -3,9 +3,18 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do
- let(:project) { build(:project) }
- let(:experiment_enabled) { true }
- let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project, learn_gitlab_experiment_enabled: experiment_enabled) }
+ let_it_be(:project) { build(:project) }
+ let_it_be(:experiment_enabled) { true }
+ let_it_be(:tracking_category) { 'Growth::Activation::Experiment::LearnGitLabB' }
+
+ let(:context) do
+ Sidebars::Projects::Context.new(
+ current_user: nil,
+ container: project,
+ learn_gitlab_experiment_enabled: experiment_enabled,
+ learn_gitlab_experiment_tracking_category: tracking_category
+ )
+ end
subject { described_class.new(context) }
@@ -13,6 +22,23 @@ RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do
expect(subject.instance_variable_get(:@items)).to be_empty
end
+ describe '#nav_link_html_options' do
+ let_it_be(:data_tracking) do
+ {
+ class: 'home',
+ data: {
+ track_action: 'click_menu',
+ track_property: tracking_category,
+ track_label: 'learn_gitlab'
+ }
+ }
+ end
+
+ specify do
+ expect(subject.nav_link_html_options).to eq(data_tracking)
+ end
+ end
+
describe '#render?' do
context 'when learn gitlab experiment is enabled' do
it 'returns true' do
diff --git a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
index b3c9b9d4995..ea5be9f9852 100644
--- a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb
@@ -42,11 +42,34 @@ RSpec.describe 'Setting Due Date of an issue' do
expect(graphql_errors).to include(a_hash_including('message' => error))
end
- it 'updates the issue due date' do
- post_graphql_mutation(mutation, current_user: current_user)
+ context 'when due date value is a valid date' do
+ it 'updates the issue due date' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['issue']['dueDate']).to eq(2.days.since.to_date.to_s)
+ end
+ end
+
+ context 'when due date value is null' do
+ let(:input) { { due_date: nil } }
+
+ it 'updates the issue to remove the due date' do
+ post_graphql_mutation(mutation, current_user: current_user)
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['issue']['dueDate']).to eq(2.days.since.to_date.to_s)
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['issue']['dueDate']).to be nil
+ end
+ end
+
+ context 'when due date argument is not given' do
+ let(:input) { {} }
+
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(graphql_errors).to include(a_hash_including('message' => /Argument dueDate must be provided/))
+ end
end
context 'when the due date value is not a valid time' do