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
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-10-31 03:16:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-31 03:16:38 +0300
commit453bb35fc81741c1dd7178cde1f64df2c9ec7252 (patch)
tree44edb488772b5fc89967865e4e0e70c8feab832f /spec
parent892e58c41fd07cc59b9e06b2a856ee61790d5bc4 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/fixtures/api/schemas/group_link/group_link.json5
-rw-r--r--spec/frontend/helpers/init_simple_app_helper_spec.js37
-rw-r--r--spec/frontend/members/components/avatars/group_avatar_spec.js25
-rw-r--r--spec/frontend/members/components/icons/private_icon_spec.js30
-rw-r--r--spec/frontend/members/components/table/member_source_spec.js15
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js19
-rw-r--r--spec/frontend/members/mock_data.js13
-rw-r--r--spec/helpers/colors_helper_spec.rb47
-rw-r--r--spec/helpers/environment_helper_spec.rb39
-rw-r--r--spec/helpers/environments_helper_spec.rb13
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb12
-rw-r--r--spec/helpers/members_helper_spec.rb15
-rw-r--r--spec/helpers/users/callouts_helper_spec.rb2
-rw-r--r--spec/policies/group_group_link_policy_spec.rb63
-rw-r--r--spec/policies/project_group_link_policy_spec.rb95
-rw-r--r--spec/serializers/group_link/group_group_link_entity_spec.rb65
-rw-r--r--spec/serializers/group_link/project_group_link_entity_spec.rb62
17 files changed, 366 insertions, 191 deletions
diff --git a/spec/fixtures/api/schemas/group_link/group_link.json b/spec/fixtures/api/schemas/group_link/group_link.json
index 885ed6d18e0..4db38952ecc 100644
--- a/spec/fixtures/api/schemas/group_link/group_link.json
+++ b/spec/fixtures/api/schemas/group_link/group_link.json
@@ -44,6 +44,9 @@
"valid_roles": {
"type": "object"
},
+ "is_shared_with_group_private": {
+ "type": "boolean"
+ },
"shared_with_group": {
"type": "object",
"required": [
@@ -89,4 +92,4 @@
"type": "boolean"
}
}
-} \ No newline at end of file
+}
diff --git a/spec/frontend/helpers/init_simple_app_helper_spec.js b/spec/frontend/helpers/init_simple_app_helper_spec.js
index 7938e3851d0..de39a6f9d70 100644
--- a/spec/frontend/helpers/init_simple_app_helper_spec.js
+++ b/spec/frontend/helpers/init_simple_app_helper_spec.js
@@ -1,7 +1,9 @@
import { createWrapper } from '@vue/test-utils';
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { initSimpleApp } from '~/helpers/init_simple_app_helper';
+import createDefaultClient from '~/lib/graphql';
const MockComponent = Vue.component('MockComponent', {
props: {
@@ -25,10 +27,10 @@ const findMock = () => wrapper.findComponent(MockComponent);
const didCreateApp = () => wrapper !== undefined;
-const initMock = (html, props = {}) => {
+const initMock = (html, options = {}) => {
setHTMLFixture(html);
- const app = initSimpleApp('#mount-here', MockComponent, { props });
+ const app = initSimpleApp('#mount-here', MockComponent, options);
wrapper = app ? createWrapper(app) : undefined;
};
@@ -58,4 +60,35 @@ describe('helpers/init_simple_app_helper/initSimpleApp', () => {
count: 123,
});
});
+
+ describe('options', () => {
+ describe('withApolloProvider', () => {
+ describe('if not true or not VueApollo', () => {
+ it('apolloProvider not created', () => {
+ initMock('<div id="mount-here"></div>', { withApolloProvider: false });
+
+ expect(wrapper.vm.$apollo).toBeUndefined();
+ });
+ });
+
+ describe('if true, creates default provider', () => {
+ it('creates a default apolloProvider', () => {
+ initMock('<div id="mount-here"></div>', { withApolloProvider: true });
+
+ expect(wrapper.vm.$apollo).not.toBeUndefined();
+ });
+ });
+
+ describe('if VueApollo, sets as default provider', () => {
+ it('uses the provided apolloClient', () => {
+ Vue.use(VueApollo);
+ const apolloProvider = new VueApollo({ defaultClient: createDefaultClient() });
+
+ initMock('<div id="mount-here"></div>', { withApolloProvider: apolloProvider });
+
+ expect(wrapper.vm.$apolloProvider).toBe(apolloProvider);
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/members/components/avatars/group_avatar_spec.js b/spec/frontend/members/components/avatars/group_avatar_spec.js
index 8e4263f88fe..1463aa5ae59 100644
--- a/spec/frontend/members/components/avatars/group_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/group_avatar_spec.js
@@ -1,8 +1,9 @@
-import { GlAvatarLink } from '@gitlab/ui';
+import { GlAvatarLabeled, GlAvatarLink } from '@gitlab/ui';
import { getByText as getByTextHelper } from '@testing-library/dom';
import { mount, createWrapper } from '@vue/test-utils';
import GroupAvatar from '~/members/components/avatars/group_avatar.vue';
-import { group as member } from '../../mock_data';
+import PrivateIcon from '~/members/components/icons/private_icon.vue';
+import { group as member, privateGroup as privateMember } from '../../mock_data';
describe('MemberList', () => {
let wrapper;
@@ -21,11 +22,9 @@ describe('MemberList', () => {
const getByText = (text, options) =>
createWrapper(getByTextHelper(wrapper.element, text, options));
- beforeEach(() => {
+ it('renders link to group', () => {
createComponent();
- });
- it('renders link to group', () => {
const link = wrapper.findComponent(GlAvatarLink);
expect(link.exists()).toBe(true);
@@ -33,10 +32,26 @@ describe('MemberList', () => {
});
it("renders group's full name", () => {
+ createComponent();
+
expect(getByText(group.fullName).exists()).toBe(true);
});
it("renders group's avatar", () => {
+ createComponent();
+
expect(wrapper.find('img').attributes('src')).toBe(group.avatarUrl);
});
+
+ describe('when group is private', () => {
+ beforeEach(() => {
+ createComponent({ member: privateMember });
+ });
+
+ it('renders private avatar with icon', () => {
+ expect(wrapper.findComponent(GlAvatarLink).exists()).toBe(false);
+ expect(wrapper.findComponent(GlAvatarLabeled).props('label')).toBe('Private');
+ expect(wrapper.findComponent(PrivateIcon).exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/members/components/icons/private_icon_spec.js b/spec/frontend/members/components/icons/private_icon_spec.js
new file mode 100644
index 00000000000..ea2b65e3307
--- /dev/null
+++ b/spec/frontend/members/components/icons/private_icon_spec.js
@@ -0,0 +1,30 @@
+import { GlIcon } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import PrivateIcon from '~/members/components/icons/private_icon.vue';
+
+describe('PrivateIcon', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = mountExtended(PrivateIcon, {
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders private icon with tooltip', () => {
+ const icon = wrapper.findComponent(GlIcon);
+ const tooltipDirective = getBinding(icon.element, 'gl-tooltip');
+
+ expect(icon.props('name')).toBe('eye-slash');
+ expect(tooltipDirective.value).toBe(
+ 'Private group information is only accessible to its members.',
+ );
+ });
+});
diff --git a/spec/frontend/members/components/table/member_source_spec.js b/spec/frontend/members/components/table/member_source_spec.js
index bbfbb19fd92..16b8d239944 100644
--- a/spec/frontend/members/components/table/member_source_spec.js
+++ b/spec/frontend/members/components/table/member_source_spec.js
@@ -1,6 +1,7 @@
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import MemberSource from '~/members/components/table/member_source.vue';
+import PrivateIcon from '~/members/components/icons/private_icon.vue';
describe('MemberSource', () => {
let wrapper;
@@ -30,6 +31,20 @@ describe('MemberSource', () => {
const getTooltipDirective = (elementWrapper) => getBinding(elementWrapper.element, 'gl-tooltip');
+ describe('when source is private', () => {
+ beforeEach(() => {
+ createComponent({
+ isSharedWithGroupPrivate: true,
+ isDirectMember: false,
+ });
+ });
+
+ it('displays private with icon', () => {
+ expect(wrapper.findByText('Private').exists()).toBe(true);
+ expect(wrapper.findComponent(PrivateIcon).exists()).toBe(true);
+ });
+ });
+
describe('direct member', () => {
describe('when created by is available', () => {
it('displays "Direct member by <user name>"', () => {
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 4539478bf9a..791155fcd1b 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -27,6 +27,7 @@ import {
directMember,
invite,
accessRequest,
+ privateGroup,
pagination,
} from '../../mock_data';
@@ -245,6 +246,24 @@ describe('MembersTable', () => {
});
});
});
+
+ describe('Source field', () => {
+ beforeEach(() => {
+ createComponent({
+ members: [privateGroup],
+ tableFields: ['source'],
+ });
+ });
+
+ it('passes correct props to `MemberSource` component', () => {
+ expect(wrapper.findComponent(MemberSource).props()).toMatchObject({
+ memberSource: {},
+ isDirectMember: true,
+ isSharedWithGroupPrivate: true,
+ createdBy: null,
+ });
+ });
+ });
});
describe('when `members` is an empty array', () => {
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 4598c74757e..4fb0b76fa49 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -70,6 +70,19 @@ export const group = {
validRoles: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
};
+export const privateGroup = {
+ accessLevel: { integerValue: 10, stringValue: 'Guest' },
+ isSharedWithGroupPrivate: true,
+ sharedWithGroup: {
+ id: 24,
+ },
+ id: 3,
+ isDirectMember: true,
+ createdAt: '2020-08-06T15:31:07.662Z',
+ expiresAt: null,
+ validRoles: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
+};
+
export const modalData = {
isAccessRequest: true,
isInvite: true,
diff --git a/spec/helpers/colors_helper_spec.rb b/spec/helpers/colors_helper_spec.rb
index ca5cafb7ebe..328796ef1ae 100644
--- a/spec/helpers/colors_helper_spec.rb
+++ b/spec/helpers/colors_helper_spec.rb
@@ -39,51 +39,4 @@ RSpec.describe ColorsHelper do
end
end
end
-
- describe '#rgb_array_to_hex_color' do
- context 'valid RGB array' do
- where(:rgb_array, :hex_color) do
- [0, 0, 0] | '#000000'
- [0, 0, 255] | '#0000ff'
- [0, 255, 0] | '#00ff00'
- [255, 0, 0] | '#ff0000'
- [12, 34, 56] | '#0c2238'
- [222, 111, 88] | '#de6f58'
- [255, 255, 255] | '#ffffff'
- end
-
- with_them do
- it 'returns correct hex color' do
- expect(helper.rgb_array_to_hex_color(rgb_array)).to eq(hex_color)
- end
- end
- end
-
- context 'invalid RGB array' do
- where(:rgb_array) do
- [
- '',
- '#000000',
- 0,
- nil,
- [],
- [0],
- [0, 0],
- [0, 0, 0, 0],
- [-1, 0, 0],
- [0, -1, 0],
- [0, 0, -1],
- [256, 0, 0],
- [0, 256, 0],
- [0, 0, 256]
- ]
- end
-
- with_them do
- it 'raise ArgumentError' do
- expect { helper.rgb_array_to_hex_color(rgb_array) }.to raise_error(ArgumentError)
- end
- end
- end
- end
end
diff --git a/spec/helpers/environment_helper_spec.rb b/spec/helpers/environment_helper_spec.rb
index 1383bf34881..0c04417fca6 100644
--- a/spec/helpers/environment_helper_spec.rb
+++ b/spec/helpers/environment_helper_spec.rb
@@ -3,45 +3,6 @@
require 'spec_helper'
RSpec.describe EnvironmentHelper, feature_category: :environment_management do
- describe '#render_deployment_status' do
- context 'when using a manual deployment' do
- it 'renders a span tag' do
- deploy = build(:deployment, deployable: nil, status: :success)
- html = helper.render_deployment_status(deploy)
-
- expect(html).to have_css('span.ci-status.ci-success')
- end
- end
-
- context 'when using a deployment from a build' do
- it 'renders a link tag' do
- deploy = build(:deployment, status: :success)
- html = helper.render_deployment_status(deploy)
-
- expect(html).to have_css('a.ci-status.ci-success')
- end
- end
-
- context 'when deploying from a bridge' do
- it 'renders a span tag' do
- deploy = build(:deployment, deployable: create(:ci_bridge), status: :success)
- html = helper.render_deployment_status(deploy)
-
- expect(html).to have_css('span.ci-status.ci-success')
- end
- end
-
- context 'for a blocked deployment' do
- subject { helper.render_deployment_status(deployment) }
-
- let(:deployment) { build(:deployment, :blocked) }
-
- it 'indicates the status' do
- expect(subject).to have_text('blocked')
- end
- end
- end
-
describe '#environments_detail_data_json' do
subject { helper.environments_detail_data_json(user, project, environment) }
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
index 6624404bc49..997f9e6eac7 100644
--- a/spec/helpers/environments_helper_spec.rb
+++ b/spec/helpers/environments_helper_spec.rb
@@ -95,17 +95,4 @@ RSpec.describe EnvironmentsHelper, feature_category: :environment_management do
expect(subject).to eq(true)
end
end
-
- describe '#environment_logs_data' do
- it 'returns logs data' do
- expected_data = {
- "environment_name": environment.name,
- "environments_path": api_v4_projects_environments_path(id: project.id),
- "environment_id": environment.id,
- "clusters_path": project_clusters_path(project, format: :json)
- }
-
- expect(helper.environment_logs_data(project, environment)).to eq(expected_data)
- end
- end
end
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index a9c6822e2c1..3a7c852b683 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -19,14 +19,9 @@ RSpec.describe Groups::GroupMembersHelper do
let(:members_collection) { members }
before do
- allow(helper).to receive(:can?).with(current_user, :export_group_memberships, group).and_return(false)
- allow(helper).to receive(:can?).with(current_user, :owner_access, group).and_return(true)
allow(helper).to receive(:current_user).and_return(current_user)
- allow(helper).to receive(:can?).with(current_user, :export_group_memberships, shared_group).and_return(true)
allow(helper).to receive(:group_group_member_path).with(shared_group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
allow(helper).to receive(:group_group_link_path).with(shared_group, ':id').and_return('/groups/foo-bar/-/group_links/:id')
- allow(helper).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true)
- allow(helper).to receive(:can?).with(current_user, :admin_member_access_request, shared_group).and_return(true)
end
subject do
@@ -54,8 +49,8 @@ RSpec.describe Groups::GroupMembersHelper do
it 'returns expected json' do
expected = {
source_id: shared_group.id,
- can_manage_members: true,
- can_manage_access_requests: true,
+ can_manage_members: be_in([true, false]),
+ can_manage_access_requests: be_in([true, false]),
group_name: shared_group.name,
group_path: shared_group.full_path
}
@@ -102,9 +97,6 @@ RSpec.describe Groups::GroupMembersHelper do
before do
allow(helper).to receive(:group_group_member_path).with(sub_shared_group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
allow(helper).to receive(:group_group_link_path).with(sub_shared_group, ':id').and_return('/groups/foo-bar/-/group_links/:id')
- allow(helper).to receive(:can?).with(current_user, :admin_group_member, sub_shared_group).and_return(true)
- allow(helper).to receive(:can?).with(current_user, :admin_member_access_request, sub_shared_group).and_return(true)
- allow(helper).to receive(:can?).with(current_user, :export_group_memberships, sub_shared_group).and_return(true)
end
subject do
diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb
index 68a12d8dbf7..d2d758cdc7c 100644
--- a/spec/helpers/members_helper_spec.rb
+++ b/spec/helpers/members_helper_spec.rb
@@ -45,21 +45,6 @@ RSpec.describe MembersHelper do
end
end
- describe '#remove_member_title' do
- let(:requester) { create(:user) }
- let(:project) { create(:project, :public) }
- let(:project_member) { build(:project_member, project: project) }
- let(:project_member_request) { project.request_access(requester) }
- let(:group) { create(:group) }
- let(:group_member) { build(:group_member, group: group) }
- let(:group_member_request) { group.request_access(requester) }
-
- it { expect(remove_member_title(project_member)).to eq 'Remove user from project' }
- it { expect(remove_member_title(project_member_request)).to eq 'Deny access request from project' }
- it { expect(remove_member_title(group_member)).to eq 'Remove user from group and any subresources' }
- it { expect(remove_member_title(group_member_request)).to eq 'Deny access request from group' }
- end
-
describe '#leave_confirmation_message' do
let(:project) { build_stubbed(:project) }
let(:group) { build_stubbed(:group) }
diff --git a/spec/helpers/users/callouts_helper_spec.rb b/spec/helpers/users/callouts_helper_spec.rb
index 10f021330db..2a0ba1279b0 100644
--- a/spec/helpers/users/callouts_helper_spec.rb
+++ b/spec/helpers/users/callouts_helper_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
-RSpec.describe Users::CalloutsHelper do
+RSpec.describe Users::CalloutsHelper, feature_category: :navigation do
let_it_be(:user, refind: true) { create(:user) }
before do
diff --git a/spec/policies/group_group_link_policy_spec.rb b/spec/policies/group_group_link_policy_spec.rb
new file mode 100644
index 00000000000..34bc1bc3bec
--- /dev/null
+++ b/spec/policies/group_group_link_policy_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupGroupLinkPolicy, feature_category: :system_access do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:group2) { create(:group, :private) }
+
+ let(:group_group_link) do
+ create(:group_group_link, shared_group: group, shared_with_group: group2)
+ end
+
+ subject(:policy) { described_class.new(user, group_group_link) }
+
+ describe 'read_shared_with_group' do
+ context 'when the user is a shared_group member' do
+ before_all do
+ group.add_guest(user)
+ end
+
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
+ end
+ end
+
+ context 'when the user is not a shared_group member' do
+ context 'when user is not a shared_with_group member' do
+ context 'when the shared_with_group is private' do
+ it 'cannot read_shared_with_group' do
+ expect(policy).to be_disallowed(:read_shared_with_group)
+ end
+
+ context 'when the shared group is public' do
+ let_it_be(:group) { create(:group, :public) }
+
+ it 'cannot read_shared_with_group' do
+ expect(policy).to be_disallowed(:read_shared_with_group)
+ end
+ end
+ end
+
+ context 'when the shared_with_group is public' do
+ let_it_be(:group2) { create(:group, :public) }
+
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
+ end
+ end
+ end
+
+ context 'when user is a shared_with_group member' do
+ before_all do
+ group2.add_developer(user)
+ end
+
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/policies/project_group_link_policy_spec.rb b/spec/policies/project_group_link_policy_spec.rb
index 9461f33decb..1047d3acb1e 100644
--- a/spec/policies/project_group_link_policy_spec.rb
+++ b/spec/policies/project_group_link_policy_spec.rb
@@ -4,9 +4,8 @@ require 'spec_helper'
RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do
let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group, :private) }
let_it_be(:group2) { create(:group, :private) }
- let_it_be(:project) { create(:project, :private, group: group) }
+ let_it_be(:project) { create(:project, :private) }
let(:project_group_link) do
create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::DEVELOPER)
@@ -14,42 +13,92 @@ RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do
subject(:policy) { described_class.new(user, project_group_link) }
- context 'when the user is a group owner' do
- before do
- project_group_link.group.add_owner(user)
- end
+ describe 'admin_project_group_link' do
+ context 'when the user is a group owner' do
+ before_all do
+ group2.add_owner(user)
+ end
- context 'when user is not project maintainer' do
- it 'can admin group_project_link' do
- expect(policy).to be_allowed(:admin_project_group_link)
+ context 'when user is not project maintainer' do
+ it 'can admin group_project_link' do
+ expect(policy).to be_allowed(:admin_project_group_link)
+ end
+ end
+
+ context 'when user is a project maintainer' do
+ before do
+ project_group_link.project.add_maintainer(user)
+ end
+
+ it 'can admin group_project_link' do
+ expect(policy).to be_allowed(:admin_project_group_link)
+ end
end
end
- context 'when user is a project maintainer' do
- before do
- project_group_link.project.add_maintainer(user)
+ context 'when user is not a group owner' do
+ context 'when user is a project maintainer' do
+ it 'can admin group_project_link' do
+ project_group_link.project.add_maintainer(user)
+
+ expect(policy).to be_allowed(:admin_project_group_link)
+ end
end
- it 'can admin group_project_link' do
- expect(policy).to be_allowed(:admin_project_group_link)
+ context 'when user is not a project maintainer' do
+ it 'cannot admin group_project_link' do
+ project_group_link.project.add_developer(user)
+
+ expect(policy).to be_disallowed(:admin_project_group_link)
+ end
end
end
end
- context 'when user is not a group owner' do
- context 'when user is a project maintainer' do
- it 'can admin group_project_link' do
- project_group_link.project.add_maintainer(user)
+ describe 'read_shared_with_group' do
+ context 'when the user is a project member' do
+ before_all do
+ project.add_guest(user)
+ end
- expect(policy).to be_allowed(:admin_project_group_link)
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
end
end
- context 'when user is not a project maintainer' do
- it 'cannot admin group_project_link' do
- project_group_link.project.add_developer(user)
+ context 'when the user is not a project member' do
+ context 'when user is not a group member' do
+ context 'when the group is private' do
+ it 'cannot read_shared_with_group' do
+ expect(policy).to be_disallowed(:read_shared_with_group)
+ end
+
+ context 'when the project is public' do
+ let_it_be(:project) { create(:project, :public) }
+
+ it 'cannot read_shared_with_group' do
+ expect(policy).to be_disallowed(:read_shared_with_group)
+ end
+ end
+ end
+
+ context 'when the group is public' do
+ let_it_be(:group2) { create(:group, :public) }
+
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
+ end
+ end
+ end
+
+ context 'when user is a group member' do
+ before_all do
+ group2.add_guest(user)
+ end
- expect(policy).to be_disallowed(:admin_project_group_link)
+ it 'can read_shared_with_group' do
+ expect(policy).to be_allowed(:read_shared_with_group)
+ end
end
end
end
diff --git a/spec/serializers/group_link/group_group_link_entity_spec.rb b/spec/serializers/group_link/group_group_link_entity_spec.rb
index 502cdc5c048..8f31c53e841 100644
--- a/spec/serializers/group_link/group_group_link_entity_spec.rb
+++ b/spec/serializers/group_link/group_group_link_entity_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
let(:entity) { described_class.new(group_group_link, { current_user: current_user, source: shared_group }) }
- before do
- allow(entity).to receive(:current_user).and_return(current_user)
+ subject(:as_json) do
+ entity.as_json
end
it 'matches json schema' do
@@ -19,7 +19,7 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
context 'source' do
it 'exposes `source`' do
- expect(entity.as_json[:source]).to include(
+ expect(as_json[:source]).to include(
id: shared_group.id,
full_name: shared_group.full_name,
web_url: shared_group.web_url
@@ -38,9 +38,9 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
end
end
- context 'when current user has `:admin_group_member` permissions' do
- before do
- allow(entity).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true)
+ context 'when current user has owner permissions for the shared group' do
+ before_all do
+ shared_group.add_owner(current_user)
end
context 'when direct_member? is true' do
@@ -49,10 +49,8 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
end
it 'exposes `can_update` and `can_remove` as `true`' do
- json = entity.as_json
-
- expect(json[:can_update]).to be true
- expect(json[:can_remove]).to be true
+ expect(as_json[:can_update]).to be true
+ expect(as_json[:can_remove]).to be true
end
end
@@ -62,10 +60,51 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
end
it 'exposes `can_update` and `can_remove` as `true`' do
- json = entity.as_json
+ expect(as_json[:can_update]).to be false
+ expect(as_json[:can_remove]).to be false
+ end
+ end
+ end
+
+ context 'when current user is not a group member' do
+ context 'when shared with group is public' do
+ it 'does expose shared_with_group details' do
+ expect(as_json[:shared_with_group].keys).to include(:id, :avatar_url, :web_url, :name)
+ end
+
+ it 'does expose source details' do
+ expect(as_json[:source].keys).to include(:id, :full_name)
+ end
+
+ it 'sets is_shared_with_group_private to false' do
+ expect(as_json[:is_shared_with_group_private]).to be false
+ end
+ end
+
+ context 'when shared with group is private' do
+ let_it_be(:shared_with_group) { create(:group, :private) }
+
+ let_it_be(:group_group_link) do
+ create(
+ :group_group_link,
+ {
+ shared_group: shared_group,
+ shared_with_group: shared_with_group,
+ expires_at: '2020-05-12'
+ }
+ )
+ end
+
+ it 'does not expose shared_with_group details' do
+ expect(as_json[:shared_with_group].keys).to contain_exactly(:id)
+ end
+
+ it 'does not expose source details' do
+ expect(as_json[:source]).to be_nil
+ end
- expect(json[:can_update]).to be false
- expect(json[:can_remove]).to be false
+ it 'sets is_shared_with_group_private to true' do
+ expect(as_json[:is_shared_with_group_private]).to be true
end
end
end
diff --git a/spec/serializers/group_link/project_group_link_entity_spec.rb b/spec/serializers/group_link/project_group_link_entity_spec.rb
index 1a8fcb2cfd3..00bfc43f17e 100644
--- a/spec/serializers/group_link/project_group_link_entity_spec.rb
+++ b/spec/serializers/group_link/project_group_link_entity_spec.rb
@@ -8,51 +8,69 @@ RSpec.describe GroupLink::ProjectGroupLinkEntity do
let(:entity) { described_class.new(project_group_link, { current_user: current_user, source: project_group_link.project }) }
- before do
- allow(entity).to receive(:current_user).and_return(current_user)
+ subject(:as_json) do
+ entity.as_json
end
it 'matches json schema' do
expect(entity.to_json).to match_schema('group_link/project_group_link')
end
- context 'when current user has `admin_project_member` permissions' do
- before do
- allow(entity).to receive(:can?).with(current_user, :admin_project_group_link, project_group_link).and_return(false)
- allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(true)
+ context 'when current user is a project maintainer' do
+ before_all do
+ project_group_link.project.add_maintainer(current_user)
end
it 'exposes `can_update` and `can_remove` as `true`' do
- json = entity.as_json
-
- expect(json[:can_update]).to be true
- expect(json[:can_remove]).to be false
+ expect(as_json[:can_update]).to be true
+ expect(as_json[:can_remove]).to be true
end
end
context 'when current user is a group owner' do
- before do
- allow(entity).to receive(:can?).with(current_user, :admin_project_group_link, project_group_link).and_return(true)
- allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(false)
+ before_all do
+ project_group_link.group.add_owner(current_user)
end
it 'exposes `can_remove` as true' do
- json = entity.as_json
-
- expect(json[:can_remove]).to be true
+ expect(as_json[:can_remove]).to be true
end
end
context 'when current user is not a group owner' do
- before do
- allow(entity).to receive(:can?).with(current_user, :admin_project_group_link, project_group_link).and_return(false)
- allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(false)
+ it 'exposes `can_remove` as false' do
+ expect(as_json[:can_remove]).to be false
end
- it 'exposes `can_remove` as false' do
- json = entity.as_json
+ context 'when group is public' do
+ it 'does expose shared_with_group details' do
+ expect(as_json[:shared_with_group].keys).to include(:id, :avatar_url, :web_url, :name)
+ end
+
+ it 'does expose source details' do
+ expect(as_json[:source].keys).to include(:id, :full_name)
+ end
+
+ it 'sets is_shared_with_group_private to false' do
+ expect(as_json[:is_shared_with_group_private]).to be false
+ end
+ end
+
+ context 'when group is private' do
+ let_it_be(:private_group) { create(:group, :private) }
+ let_it_be(:project_group_link) { create(:project_group_link, group: private_group) }
+
+ it 'does not expose shared_with_group details' do
+ expect(as_json[:shared_with_group].keys).to contain_exactly(:id)
+ end
+
+ it 'does not expose source details' do
+ expect(as_json[:source]).to be_nil
+ end
- expect(json[:can_remove]).to be false
+ it 'sets is_shared_with_group_private to true' do
+ expect(as_json[:is_shared_with_group_private]).to be true
+ end
end
end
end