diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue index 67962d69fa5..db9ef4df8af 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue @@ -127,8 +127,12 @@ export default {

-
-
+
+
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 573f996a254..b391252ce28 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 @@ -1,16 +1,25 @@ diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js index 1887c48dd1b..9ba5e17237a 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js +++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js @@ -40,6 +40,7 @@ export const ACTION_LABELS = { trialRequired: true, section: 'workspace', position: 4, + videoTutorial: 'https://vimeo.com/670896787', }, requiredMrApprovalsEnabled: { title: s__('LearnGitLab|Add merge request approval'), @@ -48,6 +49,7 @@ export const ACTION_LABELS = { trialRequired: true, section: 'workspace', position: 5, + videoTutorial: 'https://vimeo.com/670904904', }, mergeRequestCreated: { title: s__('LearnGitLab|Submit a merge request'), diff --git a/app/assets/stylesheets/page_bundles/learn_gitlab.scss b/app/assets/stylesheets/page_bundles/learn_gitlab.scss index 10a4a210d41..189aefb330b 100644 --- a/app/assets/stylesheets/page_bundles/learn_gitlab.scss +++ b/app/assets/stylesheets/page_bundles/learn_gitlab.scss @@ -1,11 +1,3 @@ .learn-gitlab-info-card-content { height: 200px; } - -.learn-gitlab-section-card { - height: 400px; -} - -.learn-gitlab-section-card-header { - height: 165px; -} diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb index 177533b89c8..b9f9a1810b7 100644 --- a/app/controllers/projects/learn_gitlab_controller.rb +++ b/app/controllers/projects/learn_gitlab_controller.rb @@ -4,6 +4,7 @@ class Projects::LearnGitlabController < Projects::ApplicationController before_action :authenticate_user! before_action :check_experiment_enabled? before_action :enable_invite_for_help_continuous_onboarding_experiment + before_action :enable_video_tutorials_continuous_onboarding_experiment feature_category :users @@ -24,4 +25,8 @@ class Projects::LearnGitlabController < Projects::ApplicationController e.publish_to_database end end + + def enable_video_tutorials_continuous_onboarding_experiment + experiment(:video_tutorials_continuous_onboarding, namespace: project&.namespace).publish + end end diff --git a/app/experiments/video_tutorials_continuous_onboarding_experiment.rb b/app/experiments/video_tutorials_continuous_onboarding_experiment.rb new file mode 100644 index 00000000000..3cb676b25f2 --- /dev/null +++ b/app/experiments/video_tutorials_continuous_onboarding_experiment.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class VideoTutorialsContinuousOnboardingExperiment < ApplicationExperiment + control { } + candidate { } +end diff --git a/app/graphql/mutations/user_preferences/update.rb b/app/graphql/mutations/user_preferences/update.rb index c92c6d725b7..b71c952b0f2 100644 --- a/app/graphql/mutations/user_preferences/update.rb +++ b/app/graphql/mutations/user_preferences/update.rb @@ -14,6 +14,15 @@ module Mutations null: true, description: 'User preferences after mutation.' + def ready?(**args) + if disabled_sort_value?(args) + raise Gitlab::Graphql::Errors::ArgumentError, + 'Feature flag `incident_escalations` must be enabled to use this sort order.' + end + + super + end + def resolve(**attributes) user_preferences = current_user.user_preference user_preferences.update(attributes) @@ -23,6 +32,14 @@ module Mutations errors: errors_on_object(user_preferences) } end + + private + + def disabled_sort_value?(args) + return false unless [:escalation_status_asc, :escalation_status_desc].include?(args[:issues_sort]) + + Feature.disabled?(:incident_escalations) + end end end end diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb index 3e7509b4068..c5b228749de 100644 --- a/app/graphql/resolvers/base_issues_resolver.rb +++ b/app/graphql/resolvers/base_issues_resolver.rb @@ -17,7 +17,8 @@ module Resolvers NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc popularity_asc popularity_desc label_priority_asc label_priority_desc - milestone_due_asc milestone_due_desc].freeze + milestone_due_asc milestone_due_desc + escalation_status_asc escalation_status_desc].freeze def continue_issue_resolve(parent, finder, **args) issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all { |q| apply_lookahead(q) } @@ -31,6 +32,13 @@ module Resolvers end end + def prepare_params(args, parent) + return unless [:escalation_status_asc, :escalation_status_desc].include?(args[:sort]) + return if Feature.enabled?(:incident_escalations, parent) + + args[:sort] = :created_desc # default for sort argument + end + private def unconditional_includes diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb index 38c79ff52ac..432d6f48607 100644 --- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb +++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb @@ -84,6 +84,7 @@ module IssueResolverArguments prepare_assignee_username_params(args) prepare_release_tag_params(args) + prepare_params(args, parent) if defined?(prepare_params) finder = IssuesFinder.new(current_user, args) diff --git a/app/graphql/types/issue_sort_enum.rb b/app/graphql/types/issue_sort_enum.rb index f8825ff6c46..db51e491d4e 100644 --- a/app/graphql/types/issue_sort_enum.rb +++ b/app/graphql/types/issue_sort_enum.rb @@ -14,6 +14,8 @@ module Types value 'TITLE_DESC', 'Title by descending order.', value: :title_desc value 'POPULARITY_ASC', 'Number of upvotes (awarded "thumbs up" emoji) by ascending order.', value: :popularity_asc value 'POPULARITY_DESC', 'Number of upvotes (awarded "thumbs up" emoji) by descending order.', value: :popularity_desc + value 'ESCALATION_STATUS_ASC', 'Status from triggered to resolved. Defaults to `CREATED_DESC` if `incident_escalations` feature flag is disabled.', value: :escalation_status_asc + value 'ESCALATION_STATUS_DESC', 'Status from resolved to triggered. Defaults to `CREATED_DESC` if `incident_escalations` feature flag is disabled.', value: :escalation_status_desc end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 75727fff2cd..91d4b78f7c8 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -125,6 +125,8 @@ class Issue < ApplicationRecord scope :order_created_at_desc, -> { reorder(created_at: :desc) } scope :order_severity_asc, -> { includes(:issuable_severity).order('issuable_severities.severity ASC NULLS FIRST') } scope :order_severity_desc, -> { includes(:issuable_severity).order('issuable_severities.severity DESC NULLS LAST') } + scope :order_escalation_status_asc, -> { includes(:incident_management_issuable_escalation_status).order(::Gitlab::Database.nulls_last_order('incident_management_issuable_escalation_status.status')) } + scope :order_escalation_status_desc, -> { includes(:incident_management_issuable_escalation_status).order(::Gitlab::Database.nulls_last_order('incident_management_issuable_escalation_status.status', 'DESC')) } scope :preload_associated_models, -> { preload(:assignees, :labels, project: :namespace) } scope :with_web_entity_associations, -> { preload(:author, project: [:project_feature, :route, namespace: :route]) } @@ -327,6 +329,8 @@ class Issue < ApplicationRecord when 'relative_position', 'relative_position_asc' then order_by_relative_position when 'severity_asc' then order_severity_asc.with_order_id_desc when 'severity_desc' then order_severity_desc.with_order_id_desc + when 'escalation_status_asc' then order_escalation_status_asc.with_order_id_desc + when 'escalation_status_desc' then order_escalation_status_desc.with_order_id_desc else super end diff --git a/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml b/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml new file mode 100644 index 00000000000..6dc3f798f63 --- /dev/null +++ b/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml @@ -0,0 +1,8 @@ +--- +name: video_tutorials_continuous_onboarding +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82274 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351916 +milestone: '14.9' +type: experiment +group: group::adoption +default_enabled: false diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 434e0c43edf..d1ab2cb0d79 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -18298,6 +18298,8 @@ Values for sorting issues. | `CREATED_DESC` | Created at descending order. | | `DUE_DATE_ASC` | Due date by ascending order. | | `DUE_DATE_DESC` | Due date by descending order. | +| `ESCALATION_STATUS_ASC` | Status from triggered to resolved. Defaults to `CREATED_DESC` if `incident_escalations` feature flag is disabled. | +| `ESCALATION_STATUS_DESC` | Status from resolved to triggered. Defaults to `CREATED_DESC` if `incident_escalations` feature flag is disabled. | | `LABEL_PRIORITY_ASC` | Label priority by ascending order. | | `LABEL_PRIORITY_DESC` | Label priority by descending order. | | `MILESTONE_DUE_ASC` | Milestone due date by ascending order. | diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md index c7ed386f505..bf20119e20b 100644 --- a/doc/operations/incident_management/incidents.md +++ b/doc/operations/incident_management/incidents.md @@ -255,7 +255,12 @@ Add a to-do for incidents that you want to track in your to-do list. Click the ### Change incident status -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9. +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `incident_escalations`. Disabled by default. + +FLAG: +By default this feature is not available. To make it available per project or for your entire +instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) +named `incident_escalations`. For users with the Developer role or higher, select **Edit** in the **Status** section of the right-hand side bar of an incident, then select a status. **Triggered** is the default status for @@ -273,7 +278,12 @@ updating the incident status also updates the alert status. ## Change escalation policy **(PREMIUM)** -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9. +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `incident_escalations`. Disabled by default. + +FLAG: +By default this feature is not available. To make it available per project or for your entire +instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) +named `incident_escalations`. For users with the Developer role or higher, select **Edit** in the **Escalation policy** section of the right-hand side bar of an incident, then select a policy. By default, new incidents do not have diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md index 27854a9e201..dd1532e26bf 100644 --- a/doc/operations/incident_management/paging.md +++ b/doc/operations/incident_management/paging.md @@ -50,7 +50,12 @@ or stop alert escalations by [updating the alert's status](alerts.md#update-an-a ### Escalating an incident -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9. +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5716) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `incident_escalations`. Disabled by default. + +FLAG: +By default this feature is not available. To make it available per project or for your entire +instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) +named `incident_escalations`. For incidents, paging on-call responders is optional for each individual incident. To begin escalating the incident, [set the incident's escalation policy](incidents.md#change-escalation-policy). diff --git a/doc/user/project/integrations/webhook_events.md b/doc/user/project/integrations/webhook_events.md index d37196ec114..53c56a7c9af 100644 --- a/doc/user/project/integrations/webhook_events.md +++ b/doc/user/project/integrations/webhook_events.md @@ -203,7 +203,7 @@ The `assignee` and `assignee_id` keys are deprecated and contain the first assignee only. The `escalation_status` and `escalation_policy` fields are -only available for issue types which support escalations, +only available for issue types which [support escalations](../../../operations/incident_management/paging.md#paging), such as incidents. Request header: diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c71c614ebda..36f573bb5a3 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -41559,6 +41559,9 @@ msgstr "" msgid "Warning: Synchronizing LDAP removes direct members' access." msgstr "" +msgid "Watch how" +msgstr "" + msgid "We are currently unable to fetch data for the pipeline header." msgstr "" diff --git a/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb b/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb new file mode 100644 index 00000000000..596791308a4 --- /dev/null +++ b/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe VideoTutorialsContinuousOnboardingExperiment do + it "defines a control and candidate" do + expect(subject.behaviors.keys).to match_array(%w[control candidate]) + end +end diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap index 9e00ace761c..83feb621478 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap +++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap @@ -2,31 +2,26 @@ exports[`Learn GitLab Section Card renders correctly 1`] = ` -
- - -

- Set up your workspace -

- -

- Complete these tasks first so you can enjoy GitLab's features to their fullest: -

-
+ +

+ Set up your workspace +

+ +

+ Complete these tasks first so you can enjoy GitLab's features to their fullest: +

- +
+ + +

+ Set up your workspace +

+ +

+ Complete these tasks first so you can enjoy GitLab's features to their fullest: +

+
-
- - -

- Set up your workspace -

- -

- Complete these tasks first so you can enjoy GitLab's features to their fullest: -

-
-
- + +
- - - Invite your colleagues - - - - + + + Invite your colleagues + + + + +
- + +
- - - Create or import a repository - - - - + + + Create or import a repository + + + + +
- - - Add code owners - - - - - - Trial only + Trial only - +
+ +
- - - Add merge request approval - - - - - - Trial only + Trial only - +
+ +
@@ -222,71 +256,81 @@ exports[`Learn GitLab renders correctly 1`] = `
- +
+ + +

+ Plan and execute +

+ +

+ Create a workflow for your new workspace, and learn how GitLab features work together: +

+
-
- - -

- Plan and execute -

- -

- Create a workflow for your new workspace, and learn how GitLab features work together: -

-
-
@@ -294,54 +338,58 @@ exports[`Learn GitLab renders correctly 1`] = `
- +
+ + +

+ Deploy +

+ +

+ Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure: +

+
-
- - -

- Deploy -

- -

- Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure: -

-
-
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js index e21371123e8..551c68a99ab 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js +++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import { stubExperiments } from 'helpers/experimentation_helper'; import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper'; import eventHub from '~/invite_members/event_hub'; @@ -26,7 +26,7 @@ describe('Learn GitLab Section Link', () => { }); const createWrapper = (action = defaultAction, props = {}) => { - wrapper = shallowMount(LearnGitlabSectionLink, { + wrapper = mount(LearnGitlabSectionLink, { propsData: { action, value: { ...defaultProps, ...props } }, }); }; @@ -36,6 +36,8 @@ describe('Learn GitLab Section Link', () => { const findUncompletedLink = () => wrapper.find('[data-testid="uncompleted-learn-gitlab-link"]'); + const videoTutorialLink = () => wrapper.find('[data-testid="video-tutorial-link"]'); + it('renders no icon when not completed', () => { createWrapper(undefined, { completed: false }); @@ -130,4 +132,44 @@ describe('Learn GitLab Section Link', () => { unmockTracking(); }); }); + + describe('video_tutorials_continuous_onboarding experiment', () => { + describe('when control', () => { + beforeEach(() => { + stubExperiments({ video_tutorials_continuous_onboarding: 'control' }); + createWrapper('codeOwnersEnabled'); + }); + + it('renders no video link', () => { + expect(videoTutorialLink().exists()).toBe(false); + }); + }); + + describe('when candidate', () => { + beforeEach(() => { + stubExperiments({ video_tutorials_continuous_onboarding: 'candidate' }); + createWrapper('codeOwnersEnabled'); + }); + + it('renders video link with blank target', () => { + const videoLinkElement = videoTutorialLink(); + + expect(videoLinkElement.exists()).toBe(true); + expect(videoLinkElement.attributes('target')).toEqual('_blank'); + }); + + it('tracks the click', () => { + const trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn); + + videoTutorialLink().trigger('click'); + + expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_video_link', { + label: 'Add code owners', + property: 'Growth::Conversion::Experiment::LearnGitLab', + }); + + unmockTracking(); + }); + }); + }); }); diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb index 5e9a3d0a68b..81aeee0a3d2 100644 --- a/spec/graphql/resolvers/issues_resolver_spec.rb +++ b/spec/graphql/resolvers/issues_resolver_spec.rb @@ -522,11 +522,53 @@ RSpec.describe Resolvers::IssuesResolver do end end + context 'when sorting by escalation status' do + let_it_be(:project) { create(:project, :public) } + let_it_be(:triggered_incident) { create(:incident, :with_escalation_status, project: project) } + let_it_be(:issue_no_status) { create(:issue, project: project) } + let_it_be(:resolved_incident) do + create(:incident, :with_escalation_status, project: project) + .tap { |issue| issue.escalation_status.resolve } + end + + it 'sorts issues ascending' do + issues = resolve_issues(sort: :escalation_status_asc).to_a + expect(issues).to eq([triggered_incident, resolved_incident, issue_no_status]) + end + + it 'sorts issues descending' do + issues = resolve_issues(sort: :escalation_status_desc).to_a + expect(issues).to eq([resolved_incident, triggered_incident, issue_no_status]) + end + + it 'sorts issues created_at' do + issues = resolve_issues(sort: :created_desc).to_a + expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident]) + end + + context 'when incident_escalations feature flag is disabled' do + before do + stub_feature_flags(incident_escalations: false) + end + + it 'defaults ascending status sort to created_desc' do + issues = resolve_issues(sort: :escalation_status_asc).to_a + expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident]) + end + + it 'defaults descending status sort to created_desc' do + issues = resolve_issues(sort: :escalation_status_desc).to_a + expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident]) + end + end + end + context 'when sorting with non-stable cursors' do %i[priority_asc priority_desc popularity_asc popularity_desc label_priority_asc label_priority_desc - milestone_due_asc milestone_due_desc].each do |sort_by| + milestone_due_asc milestone_due_desc + escalation_status_asc escalation_status_desc].each do |sort_by| it "uses offset-pagination when sorting by #{sort_by}" do resolved = resolve_issues(sort: sort_by) diff --git a/spec/graphql/types/issue_sort_enum_spec.rb b/spec/graphql/types/issue_sort_enum_spec.rb index 4433709d193..95184477e75 100644 --- a/spec/graphql/types/issue_sort_enum_spec.rb +++ b/spec/graphql/types/issue_sort_enum_spec.rb @@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['IssueSort'] do it 'exposes all the existing issue sort values' do expect(described_class.values.keys).to include( - *%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC SEVERITY_ASC SEVERITY_DESC] + *%w[DUE_DATE_ASC DUE_DATE_DESC RELATIVE_POSITION_ASC SEVERITY_ASC SEVERITY_DESC ESCALATION_STATUS_ASC ESCALATION_STATUS_DESC] ) end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 29305ba435c..61ad9dc26be 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -238,6 +238,24 @@ RSpec.describe Issue do end end + context 'order by escalation status' do + let_it_be(:triggered_incident) { create(:incident_management_issuable_escalation_status, :triggered).issue } + let_it_be(:resolved_incident) { create(:incident_management_issuable_escalation_status, :resolved).issue } + let_it_be(:issue_no_status) { create(:issue) } + + describe '.order_escalation_status_asc' do + subject { described_class.order_escalation_status_asc } + + it { is_expected.to eq([triggered_incident, resolved_incident, issue_no_status]) } + end + + describe '.order_escalation_status_desc' do + subject { described_class.order_escalation_status_desc } + + it { is_expected.to eq([resolved_incident, triggered_incident, issue_no_status]) } + end + end + # TODO: Remove when NOT NULL constraint is added to the relationship describe '#work_item_type' do let(:issue) { create(:issue, :incident, project: reusable_project, work_item_type: nil) } diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb index e1c7fd9d60d..85194e6eb20 100644 --- a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb +++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb @@ -28,6 +28,17 @@ RSpec.describe Mutations::UserPreferences::Update do expect(current_user.user_preference.persisted?).to eq(true) expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s) end + + context 'when incident_escalations feature flag is disabled' do + let(:sort_value) { 'ESCALATION_STATUS_ASC' } + + before do + stub_feature_flags(incident_escalations: false) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: ['Feature flag `incident_escalations` must be enabled to use this sort order.'] + end end context 'when user has existing preference' do @@ -45,5 +56,16 @@ RSpec.describe Mutations::UserPreferences::Update do expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s) end + + context 'when incident_escalations feature flag is disabled' do + let(:sort_value) { 'ESCALATION_STATUS_DESC' } + + before do + stub_feature_flags(incident_escalations: false) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: ['Feature flag `incident_escalations` must be enabled to use this sort order.'] + end end end