Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f8dfaa8d41
commit
06071708b3
32 changed files with 132 additions and 142 deletions
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { pickBy, isEmpty } from 'lodash';
|
||||
import { pickBy, isEmpty, mapValues } from 'lodash';
|
||||
import { mapActions } from 'vuex';
|
||||
import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
|
||||
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
|
||||
|
@ -251,7 +251,8 @@ export default {
|
|||
);
|
||||
}
|
||||
|
||||
return {
|
||||
return mapValues(
|
||||
{
|
||||
...notParams,
|
||||
author_username: authorUsername,
|
||||
'label_name[]': labelName,
|
||||
|
@ -266,7 +267,20 @@ export default {
|
|||
my_reaction_emoji: myReactionEmoji,
|
||||
release_tag: releaseTag,
|
||||
confidential,
|
||||
};
|
||||
},
|
||||
(value) => {
|
||||
if (value || value === false) {
|
||||
// note: need to check array for labels.
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((valueItem) => encodeURIComponent(valueItem));
|
||||
}
|
||||
|
||||
return encodeURIComponent(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
|
|
@ -20,8 +20,8 @@ export default {
|
|||
NamespaceSelect,
|
||||
},
|
||||
props: {
|
||||
parentGroups: {
|
||||
type: Object,
|
||||
groupNamespaces: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
isPaidGroup: {
|
||||
|
@ -60,7 +60,7 @@ export default {
|
|||
<gl-form-group v-if="!isPaidGroup">
|
||||
<namespace-select
|
||||
:default-text="$options.i18n.dropdownTitle"
|
||||
:data="parentGroups"
|
||||
:group-namespaces="groupNamespaces"
|
||||
:empty-namespace-title="$options.i18n.emptyNamespaceTitle"
|
||||
:include-headers="false"
|
||||
include-empty-namespace
|
||||
|
|
|
@ -5,15 +5,13 @@ import TransferGroupForm, { i18n } from './components/transfer_group_form.vue';
|
|||
|
||||
const prepareGroups = (rawGroups) => {
|
||||
if (!rawGroups) {
|
||||
return { group: [] };
|
||||
return [];
|
||||
}
|
||||
|
||||
const group = JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
|
||||
return JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
|
||||
id,
|
||||
humanName,
|
||||
}));
|
||||
|
||||
return { group };
|
||||
};
|
||||
|
||||
export default () => {
|
||||
|
@ -38,7 +36,7 @@ export default () => {
|
|||
render(createElement) {
|
||||
return createElement(TransferGroupForm, {
|
||||
props: {
|
||||
parentGroups: prepareGroups(parentGroups),
|
||||
groupNamespaces: prepareGroups(parentGroups),
|
||||
isPaidGroup: parseBoolean(isPaidGroup),
|
||||
confirmButtonText,
|
||||
confirmationPhrase: groupName,
|
||||
|
|
|
@ -11,8 +11,12 @@ export default {
|
|||
ConfirmDanger,
|
||||
},
|
||||
props: {
|
||||
namespaces: {
|
||||
type: Object,
|
||||
groupNamespaces: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
userNamespaces: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
confirmationPhrase: {
|
||||
|
@ -46,7 +50,8 @@ export default {
|
|||
<namespace-select
|
||||
data-testid="transfer-project-namespace"
|
||||
:full-width="true"
|
||||
:data="namespaces"
|
||||
:group-namespaces="groupNamespaces"
|
||||
:user-namespaces="userNamespaces"
|
||||
:selected-namespace="selectedNamespace"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
|
|
|
@ -3,10 +3,14 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
|||
import TransferProjectForm from './components/transfer_project_form.vue';
|
||||
|
||||
const prepareNamespaces = (rawNamespaces = '') => {
|
||||
if (!rawNamespaces) {
|
||||
return { groupNamespaces: [], userNamespaces: [] };
|
||||
}
|
||||
|
||||
const data = JSON.parse(rawNamespaces);
|
||||
return {
|
||||
group: data?.group.map(convertObjectPropsToCamelCase),
|
||||
user: data?.user.map(convertObjectPropsToCamelCase),
|
||||
groupNamespaces: data?.group?.map(convertObjectPropsToCamelCase) || [],
|
||||
userNamespaces: data?.user?.map(convertObjectPropsToCamelCase) || [],
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -35,7 +39,7 @@ export default () => {
|
|||
props: {
|
||||
confirmButtonText,
|
||||
confirmationPhrase,
|
||||
namespaces: prepareNamespaces(namespaces),
|
||||
...prepareNamespaces(namespaces),
|
||||
},
|
||||
on: {
|
||||
selectNamespace: (id) => {
|
||||
|
|
|
@ -34,9 +34,15 @@ export default {
|
|||
GlSearchBoxByType,
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
groupNamespaces: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
userNamespaces: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
fullWidth: {
|
||||
type: Boolean,
|
||||
|
@ -72,18 +78,18 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
hasUserNamespaces() {
|
||||
return this.data.user?.length;
|
||||
return this.userNamespaces.length;
|
||||
},
|
||||
hasGroupNamespaces() {
|
||||
return this.data.group?.length;
|
||||
return this.groupNamespaces.length;
|
||||
},
|
||||
filteredGroupNamespaces() {
|
||||
if (!this.hasGroupNamespaces) return [];
|
||||
return filterByName(this.data.group, this.searchTerm);
|
||||
return filterByName(this.groupNamespaces, this.searchTerm);
|
||||
},
|
||||
filteredUserNamespaces() {
|
||||
if (!this.hasUserNamespaces) return [];
|
||||
return filterByName(this.data.user, this.searchTerm);
|
||||
return filterByName(this.userNamespaces, this.searchTerm);
|
||||
},
|
||||
selectedNamespaceText() {
|
||||
return this.selectedNamespace?.humanName || this.defaultText;
|
||||
|
|
|
@ -25,14 +25,20 @@ export default {
|
|||
workItemTypes() {
|
||||
return this.workItemHierarchy.reduce(
|
||||
(itemTypes, item) => {
|
||||
const skipItem = workItemTypes[item.type].isWorkItem && !window.gon?.features?.workItems;
|
||||
|
||||
if (skipItem) {
|
||||
return itemTypes;
|
||||
}
|
||||
const key = item.available ? 'available' : 'unavailable';
|
||||
const nestedTypes = item.nestedTypes?.map((type) => workItemTypes[type]);
|
||||
|
||||
itemTypes[key].push({
|
||||
...item,
|
||||
...workItemTypes[item.type],
|
||||
nestedTypes: item.nestedTypes
|
||||
? item.nestedTypes.map((type) => workItemTypes[type])
|
||||
: null,
|
||||
nestedTypes,
|
||||
});
|
||||
|
||||
return itemTypes;
|
||||
},
|
||||
{ available: [], unavailable: [] },
|
||||
|
|
|
@ -31,6 +31,7 @@ export const workItemTypes = {
|
|||
icon: 'task-done',
|
||||
color: '#217645',
|
||||
backgroundColor: '#C3E6CD',
|
||||
isWorkItem: true,
|
||||
},
|
||||
INCIDENT: {
|
||||
title: __('Incident'),
|
||||
|
|
|
@ -370,7 +370,7 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def check_ban_user_feature_flag
|
||||
access_denied! unless Feature.enabled?(:ban_user_feature_flag)
|
||||
access_denied! unless Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
def log_impersonation_event
|
||||
|
|
|
@ -7,8 +7,6 @@ module PlanningHierarchy
|
|||
def planning_hierarchy
|
||||
return access_denied! unless can?(current_user, :read_planning_hierarchy, @project)
|
||||
|
||||
return render_404 unless Feature.enabled?(:work_items_hierarchy, @project, default_enabled: :yaml)
|
||||
|
||||
render 'shared/planning_hierarchy'
|
||||
end
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||
|
|
|
@ -42,6 +42,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml)
|
||||
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
|
||||
push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml)
|
||||
push_frontend_feature_flag(:work_items, @project, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
layout :determine_layout
|
||||
|
|
|
@ -169,7 +169,7 @@ module Types
|
|||
end
|
||||
|
||||
def hidden?
|
||||
object.hidden? if Feature.enabled?(:ban_user_feature_flag)
|
||||
object.hidden? if Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
def escalation_status
|
||||
|
|
|
@ -63,7 +63,7 @@ module IssuesHelper
|
|||
end
|
||||
|
||||
def issue_hidden?(issue)
|
||||
Feature.enabled?(:ban_user_feature_flag) && issue.hidden?
|
||||
Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml) && issue.hidden?
|
||||
end
|
||||
|
||||
def hidden_issue_icon(issue)
|
||||
|
|
|
@ -125,7 +125,7 @@ module UsersHelper
|
|||
end
|
||||
|
||||
def ban_feature_available?
|
||||
Feature.enabled?(:ban_user_feature_flag)
|
||||
Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
def confirm_user_data(user)
|
||||
|
|
|
@ -143,7 +143,7 @@ class Issue < ApplicationRecord
|
|||
scope :confidential_only, -> { where(confidential: true) }
|
||||
|
||||
scope :without_hidden, -> {
|
||||
if Feature.enabled?(:ban_user_feature_flag)
|
||||
if Feature.enabled?(:ban_user_feature_flag, default_enabled: :yaml)
|
||||
where('NOT EXISTS (?)', Users::BannedUser.select(1).where('issues.author_id = banned_users.user_id'))
|
||||
else
|
||||
all
|
||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330667
|
|||
milestone: '13.12'
|
||||
type: development
|
||||
group: group::access
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: work_items_hierarchy
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79315
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350451
|
||||
milestone: '14.8'
|
||||
type: development
|
||||
group: group::product planning
|
||||
default_enabled: false
|
|
@ -208,7 +208,13 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
|
|||
|
||||
## Ban and unban users
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.2.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.2 [with a flag](../../administration/feature_flags.md) named `ban_user_feature_flag`. Disabled by default.
|
||||
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/330667) in GitLab 14.8.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available.
|
||||
To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `ban_user_feature_flag`.
|
||||
On GitLab.com, this feature is available to GitLab.com administrators only.
|
||||
|
||||
GitLab administrators can ban and unban users. Banned users are blocked, and their issues are hidden.
|
||||
The banned user's comments are still displayed. Hiding a banned user's comments is [tracked in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327356).
|
||||
|
|
|
@ -57,7 +57,7 @@ Example request using a personal access token:
|
|||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--upload-file path/to/file.txt \
|
||||
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt?status=hidden"
|
||||
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt"
|
||||
```
|
||||
|
||||
Example response without attribute `select`:
|
||||
|
|
|
@ -19,7 +19,6 @@ module Sidebars
|
|||
end
|
||||
|
||||
def show_hierarachy_menu_item?(container)
|
||||
Feature.enabled?(:work_items_hierarchy, container, default_enabled: :yaml) &&
|
||||
can?(context.current_user, :read_planning_hierarchy, container)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -120,7 +120,7 @@ describe('BoardFilteredSearch', () => {
|
|||
{ type: 'author', value: { data: 'root', operator: '=' } },
|
||||
{ type: 'assignee', value: { data: 'root', operator: '=' } },
|
||||
{ type: 'label', value: { data: 'label', operator: '=' } },
|
||||
{ type: 'label', value: { data: 'label2', operator: '=' } },
|
||||
{ type: 'label', value: { data: 'label&2', operator: '=' } },
|
||||
{ type: 'milestone', value: { data: 'New Milestone', operator: '=' } },
|
||||
{ type: 'type', value: { data: 'INCIDENT', operator: '=' } },
|
||||
{ type: 'weight', value: { data: '2', operator: '=' } },
|
||||
|
@ -134,7 +134,7 @@ describe('BoardFilteredSearch', () => {
|
|||
title: '',
|
||||
replace: true,
|
||||
url:
|
||||
'http://test.host/?author_username=root&label_name[]=label&label_name[]=label2&assignee_username=root&milestone_title=New+Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0',
|
||||
'http://test.host/?author_username=root&label_name[]=label&label_name[]=label%262&assignee_username=root&milestone_title=New%20Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0',
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ describe('Dropdown User', () => {
|
|||
});
|
||||
|
||||
describe('hideCurrentUser', () => {
|
||||
const fixtureTemplate = 'issues/issue_list.html';
|
||||
const fixtureTemplate = 'merge_requests/merge_request_list.html';
|
||||
|
||||
let dropdown;
|
||||
let authorFilterDropdownElement;
|
||||
|
|
|
@ -4,7 +4,7 @@ import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dro
|
|||
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
|
||||
|
||||
describe('Dropdown Utils', () => {
|
||||
const issueListFixture = 'issues/issue_list.html';
|
||||
const issuableListFixture = 'merge_requests/merge_request_list.html';
|
||||
|
||||
describe('getEscapedText', () => {
|
||||
it('should return same word when it has no space', () => {
|
||||
|
@ -350,7 +350,7 @@ describe('Dropdown Utils', () => {
|
|||
let authorToken;
|
||||
|
||||
beforeEach(() => {
|
||||
loadFixtures(issueListFixture);
|
||||
loadFixtures(issuableListFixture);
|
||||
|
||||
authorToken = FilteredSearchSpecHelper.createFilterVisualToken('author', '=', '@user');
|
||||
const searchTermToken = FilteredSearchSpecHelper.createSearchVisualToken('search term');
|
||||
|
|
|
@ -37,17 +37,6 @@ RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', type: :contr
|
|||
render_issue(create(:closed_issue, project: project))
|
||||
end
|
||||
|
||||
it 'issues/issue_list.html' do
|
||||
create(:issue, project: project)
|
||||
|
||||
get :index, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project
|
||||
}
|
||||
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_issue(issue)
|
||||
|
|
|
@ -119,6 +119,17 @@ RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type:
|
|||
end
|
||||
end
|
||||
|
||||
it 'merge_requests/merge_request_list.html' do
|
||||
create(:merge_request, source_project: project, target_project: project)
|
||||
|
||||
get :index, params: {
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project
|
||||
}
|
||||
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_discussions_json(merge_request)
|
||||
|
|
|
@ -10,7 +10,7 @@ describe('Transfer group form', () => {
|
|||
const confirmButtonText = 'confirm';
|
||||
const confirmationPhrase = 'confirmation-phrase';
|
||||
const paidGroupHelpLink = 'some/fake/link';
|
||||
const groups = [
|
||||
const groupNamespaces = [
|
||||
{
|
||||
id: 1,
|
||||
humanName: 'Group 1',
|
||||
|
@ -22,7 +22,7 @@ describe('Transfer group form', () => {
|
|||
];
|
||||
|
||||
const defaultProps = {
|
||||
parentGroups: { groups },
|
||||
groupNamespaces,
|
||||
paidGroupHelpLink,
|
||||
isPaidGroup: false,
|
||||
confirmationPhrase,
|
||||
|
@ -63,7 +63,7 @@ describe('Transfer group form', () => {
|
|||
includeHeaders: false,
|
||||
emptyNamespaceTitle: 'No parent group',
|
||||
includeEmptyNamespace: true,
|
||||
data: { groups },
|
||||
groupNamespaces,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -91,7 +91,7 @@ describe('Transfer group form', () => {
|
|||
});
|
||||
|
||||
describe('with a selected project', () => {
|
||||
const [firstGroup] = groups;
|
||||
const [firstGroup] = groupNamespaces;
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent();
|
||||
findNamespaceSelect().vm.$emit('select', firstGroup);
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import { namespaces } from 'jest/vue_shared/components/namespace_select/mock_data';
|
||||
import {
|
||||
groupNamespaces,
|
||||
userNamespaces,
|
||||
} from 'jest/vue_shared/components/namespace_select/mock_data';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import TransferProjectForm from '~/projects/settings/components/transfer_project_form.vue';
|
||||
import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
|
||||
|
@ -13,7 +16,8 @@ describe('Transfer project form', () => {
|
|||
const createComponent = () =>
|
||||
shallowMountExtended(TransferProjectForm, {
|
||||
propsData: {
|
||||
namespaces,
|
||||
userNamespaces,
|
||||
groupNamespaces,
|
||||
confirmButtonText,
|
||||
confirmationPhrase,
|
||||
},
|
||||
|
@ -43,7 +47,7 @@ describe('Transfer project form', () => {
|
|||
});
|
||||
|
||||
describe('with a selected namespace', () => {
|
||||
const [selectedItem] = namespaces.group;
|
||||
const [selectedItem] = groupNamespaces;
|
||||
|
||||
beforeEach(() => {
|
||||
findNamespaceSelect().vm.$emit('select', selectedItem);
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
export const group = [
|
||||
export const groupNamespaces = [
|
||||
{ id: 1, name: 'Group 1', humanName: 'Group 1' },
|
||||
{ id: 2, name: 'Subgroup 1', humanName: 'Group 1 / Subgroup 1' },
|
||||
];
|
||||
|
||||
export const user = [{ id: 3, name: 'User namespace 1', humanName: 'User namespace 1' }];
|
||||
|
||||
export const namespaces = {
|
||||
group,
|
||||
user,
|
||||
};
|
||||
export const userNamespaces = [{ id: 3, name: 'User namespace 1', humanName: 'User namespace 1' }];
|
||||
|
|
|
@ -5,9 +5,9 @@ import NamespaceSelect, {
|
|||
i18n,
|
||||
EMPTY_NAMESPACE_ID,
|
||||
} from '~/vue_shared/components/namespace_select/namespace_select.vue';
|
||||
import { user, group, namespaces } from './mock_data';
|
||||
import { userNamespaces, groupNamespaces } from './mock_data';
|
||||
|
||||
const FLAT_NAMESPACES = [...group, ...user];
|
||||
const FLAT_NAMESPACES = [...groupNamespaces, ...userNamespaces];
|
||||
const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
|
||||
const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
|
||||
|
||||
|
@ -17,7 +17,8 @@ describe('Namespace Select', () => {
|
|||
const createComponent = (props = {}) =>
|
||||
shallowMountExtended(NamespaceSelect, {
|
||||
propsData: {
|
||||
data: namespaces,
|
||||
userNamespaces,
|
||||
groupNamespaces,
|
||||
...props,
|
||||
},
|
||||
stubs: {
|
||||
|
@ -89,11 +90,11 @@ describe('Namespace Select', () => {
|
|||
describe('with search', () => {
|
||||
it.each`
|
||||
term | includeEmptyNamespace | expectedItems
|
||||
${''} | ${false} | ${[...namespaces.group, ...namespaces.user]}
|
||||
${'sub'} | ${false} | ${[namespaces.group[1]]}
|
||||
${'User'} | ${false} | ${[...namespaces.user]}
|
||||
${'User'} | ${true} | ${[...namespaces.user]}
|
||||
${'namespace'} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...namespaces.user]}
|
||||
${''} | ${false} | ${[...groupNamespaces, ...userNamespaces]}
|
||||
${'sub'} | ${false} | ${[groupNamespaces[1]]}
|
||||
${'User'} | ${false} | ${[...userNamespaces]}
|
||||
${'User'} | ${true} | ${[...userNamespaces]}
|
||||
${'namespace'} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...userNamespaces]}
|
||||
`(
|
||||
'with term=$term and includeEmptyNamespace=$includeEmptyNamespace, should show $expectedItems.length',
|
||||
async ({ term, includeEmptyNamespace, expectedItems }) => {
|
||||
|
@ -115,7 +116,7 @@ describe('Namespace Select', () => {
|
|||
|
||||
describe('with a selected namespace', () => {
|
||||
const selectedGroupIndex = 1;
|
||||
const selectedItem = group[selectedGroupIndex];
|
||||
const selectedItem = groupNamespaces[selectedGroupIndex];
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent();
|
||||
|
|
|
@ -5,23 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe Sidebars::Concerns::WorkItemHierarchy do
|
||||
shared_examples 'hierarchy menu' do
|
||||
let(:item_id) { :hierarchy }
|
||||
|
||||
context 'when the feature is disabled does not render' do
|
||||
before do
|
||||
stub_feature_flags(work_items_hierarchy: false)
|
||||
end
|
||||
|
||||
specify { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when the feature is enabled does render' do
|
||||
before do
|
||||
stub_feature_flags(work_items_hierarchy: true)
|
||||
end
|
||||
|
||||
specify { is_expected.not_to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Project hierarchy menu item' do
|
||||
let_it_be_with_reload(:project) { create(:project, :repository) }
|
||||
|
|
|
@ -63,21 +63,7 @@ RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do
|
|||
describe 'Hierarchy' do
|
||||
let(:item_id) { :hierarchy }
|
||||
|
||||
context 'when the feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(work_items_hierarchy: false)
|
||||
end
|
||||
|
||||
specify { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when the feature is enabled' do
|
||||
before do
|
||||
stub_feature_flags(work_items_hierarchy: true)
|
||||
end
|
||||
|
||||
specify { is_expected.not_to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,21 +14,10 @@ RSpec.describe PlanningHierarchy, type: :request do
|
|||
|
||||
describe 'GET #planning_hierarchy' do
|
||||
it 'renders planning hierarchy' do
|
||||
stub_feature_flags(work_items_hierarchy: true)
|
||||
|
||||
get project_planning_hierarchy_path(project)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response.body).to match(/id="js-work-items-hierarchy"/)
|
||||
end
|
||||
|
||||
it 'renders 404 page' do
|
||||
stub_feature_flags(work_items_hierarchy: false)
|
||||
|
||||
get project_planning_hierarchy_path(project)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
expect(response.body).not_to match(/id="js-work-items-hierarchy"/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue