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>2022-08-15 09:12:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-15 09:12:42 +0300
commitdefacc074a4a576e15021ba264de745af982b45d (patch)
tree3695e700025e6501f3a61bd64f8a84eaa4b12ca4 /spec
parent1b5891ee8ce8adc6877c462ea292eaee3c4ab30b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects_controller_spec.rb1
-rw-r--r--spec/factories/projects.rb1
-rw-r--r--spec/frontend/__helpers__/matchers/index.js1
-rw-r--r--spec/frontend/__helpers__/matchers/to_equal_graphql_fixture.js28
-rw-r--r--spec/frontend/__helpers__/matchers/to_equal_graphql_fixture_spec.js58
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js1
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js28
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/mock_data.js4
-rw-r--r--spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js2
-rw-r--r--spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js2
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js6
-rw-r--r--spec/frontend/runner/components/runner_jobs_spec.js2
-rw-r--r--spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js2
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js4
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js1
-rw-r--r--spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js8
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js11
-rw-r--r--spec/frontend/work_items/components/work_item_assignees_spec.js4
-rw-r--r--spec/helpers/projects_helper_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/models/concerns/project_features_compatibility_spec.rb4
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/policies/project_policy_spec.rb68
25 files changed, 110 insertions, 137 deletions
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 388d7c2266b..94d75ab8d7d 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -919,6 +919,7 @@ RSpec.describe ProjectsController do
container_registry_access_level
environments_access_level
feature_flags_access_level
+ releases_access_level
]
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 98dfecb2888..95b72648cf5 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -39,6 +39,7 @@ FactoryBot.define do
security_and_compliance_access_level { ProjectFeature::PRIVATE }
environments_access_level { ProjectFeature::ENABLED }
feature_flags_access_level { ProjectFeature::ENABLED }
+ releases_access_level { ProjectFeature::ENABLED }
# we can't assign the delegated `#ci_cd_settings` attributes directly, as the
# `#ci_cd_settings` relation needs to be created first
diff --git a/spec/frontend/__helpers__/matchers/index.js b/spec/frontend/__helpers__/matchers/index.js
index 73464135950..5da6676cdc1 100644
--- a/spec/frontend/__helpers__/matchers/index.js
+++ b/spec/frontend/__helpers__/matchers/index.js
@@ -3,4 +3,3 @@ export * from './to_have_tracking_attributes';
export * from './to_match_interpolated_text';
export * from './to_validate_json_schema';
export * from './to_match_expected_for_markdown';
-export * from './to_equal_graphql_fixture';
diff --git a/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture.js b/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture.js
deleted file mode 100644
index 1a095de1deb..00000000000
--- a/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { isEqual } from 'lodash';
-import { stripTypenames } from 'helpers/graphql_helpers';
-
-export function toEqualGraphqlFixture(received, match) {
- let clearReceived;
- let clearMatch;
-
- try {
- clearReceived = JSON.parse(JSON.stringify(received));
- clearMatch = stripTypenames(match);
- } catch (e) {
- return { message: () => 'The comparator value is not an object', pass: false };
- }
- const pass = isEqual(clearReceived, clearMatch);
- // console.log(this.utils);
- const message = pass
- ? () => `
- Expected to not be: ${this.utils.printExpected(clearMatch)}
- Received: ${this.utils.printReceived(clearReceived)}
- `
- : () =>
- `
- Expected to be: ${this.utils.printExpected(clearMatch)}
- Received: ${this.utils.printReceived(clearReceived)}
- `;
-
- return { actual: received, message, pass };
-}
diff --git a/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture_spec.js b/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture_spec.js
deleted file mode 100644
index 00adc8cfc8d..00000000000
--- a/spec/frontend/__helpers__/matchers/to_equal_graphql_fixture_spec.js
+++ /dev/null
@@ -1,58 +0,0 @@
-describe('custom matcher toEqualGraphqlFixture', () => {
- const key = 'value';
- const key2 = 'value2';
-
- describe('positive assertion', () => {
- it.each([
- [{}, {}],
- [{ undef: undefined }, { undef: undefined }],
- [{}, { __typename: 'MyType' }],
- [{ key }, { key, __typename: 'MyType' }],
- [
- { obj: { key } },
- {
- obj: {
- key,
- __typename: 'MyNestedType',
- },
- __typename: 'MyType',
- },
- ],
- [[{ key }], [{ key }]],
- [
- [{ key }],
- [
- {
- key,
- __typename: 'MyCollectionType',
- },
- ],
- ],
- ])('%j equals %j', (received, match) => {
- expect(received).toEqualGraphqlFixture(match);
- });
- });
-
- describe('negative assertion', () => {
- it.each([
- [{ __typename: 'MyType' }, {}],
- [{ key }, { key2, __typename: 'MyType' }],
- [
- { key, key2 },
- { key2, __typename: 'MyType' },
- ],
- [[{ key }, { key2 }], [{ key }]],
- [
- [{ key, key2 }],
- [
- {
- key,
- __typename: 'MyCollectionType',
- },
- ],
- ],
- ])('%j does not equal %j', (received, match) => {
- expect(received).not.toEqualGraphqlFixture(match);
- });
- });
-});
diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index bae9f33be87..e0739df7086 100644
--- a/spec/frontend/__helpers__/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
@@ -8,7 +8,6 @@ export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {
const cache = new InMemoryCache({
possibleTypes,
typePolicies,
- addTypename: false,
...cacheOptions,
});
diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js
index 483302d525f..22236424e6a 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -141,6 +141,7 @@ export const packageData = (extend) => ({
});
export const conanMetadata = () => ({
+ __typename: 'ConanMetadata',
id: 'conan-1',
packageChannel: 'stable',
packageUsername: 'gitlab-org+gitlab-test',
@@ -148,9 +149,8 @@ export const conanMetadata = () => ({
recipePath: 'package-8/1.0.0/gitlab-org+gitlab-test/stable',
});
-const conanMetadataQuery = () => ({ ...conanMetadata(), __typename: 'ConanMetadata' });
-
export const composerMetadata = () => ({
+ __typename: 'ComposerMetadata',
targetSha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
composerJson: {
license: 'MIT',
@@ -158,19 +158,14 @@ export const composerMetadata = () => ({
},
});
-const composerMetadataQuery = () => ({
- ...composerMetadata(),
- __typename: 'ComposerMetadata',
-});
-
export const pypiMetadata = () => ({
+ __typename: 'PypiMetadata',
id: 'pypi-1',
requiredPython: '1.0.0',
});
-const pypiMetadataQuery = () => ({ ...pypiMetadata(), __typename: 'PypiMetadata' });
-
export const mavenMetadata = () => ({
+ __typename: 'MavenMetadata',
id: 'maven-1',
appName: 'appName',
appGroup: 'appGroup',
@@ -178,23 +173,20 @@ export const mavenMetadata = () => ({
path: 'path',
});
-const mavenMetadataQuery = () => ({ ...mavenMetadata(), __typename: 'MavenMetadata' });
-
export const nugetMetadata = () => ({
+ __typename: 'NugetMetadata',
id: 'nuget-1',
iconUrl: 'iconUrl',
licenseUrl: 'licenseUrl',
projectUrl: 'projectUrl',
});
-const nugetMetadataQuery = () => ({ ...nugetMetadata(), __typename: 'NugetMetadata' });
-
const packageTypeMetadataQueryMapping = {
- CONAN: conanMetadataQuery,
- COMPOSER: composerMetadataQuery,
- PYPI: pypiMetadataQuery,
- MAVEN: mavenMetadataQuery,
- NUGET: nugetMetadataQuery,
+ CONAN: conanMetadata,
+ COMPOSER: composerMetadata,
+ PYPI: pypiMetadata,
+ MAVEN: mavenMetadata,
+ NUGET: nugetMetadata,
};
export const pagination = (extend) => ({
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
index d4b6c66ddeb..0696144215c 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
@@ -1,4 +1,5 @@
export const containerExpirationPolicyData = () => ({
+ __typename: 'ContainerExpirationPolicy',
cadence: 'EVERY_DAY',
enabled: true,
keepN: 'TEN_TAGS',
@@ -13,7 +14,6 @@ export const expirationPolicyPayload = (override) => ({
project: {
id: '1',
containerExpirationPolicy: {
- __typename: 'ContainerExpirationPolicy',
...containerExpirationPolicyData(),
...override,
},
@@ -42,6 +42,7 @@ export const expirationPolicyMutationPayload = ({ override, errors = [] } = {})
});
export const packagesCleanupPolicyData = {
+ __typename: 'PackagesCleanupPolicy',
keepNDuplicatedPackageFiles: 'ALL_PACKAGE_FILES',
nextRunAt: '2020-11-19T07:37:03.941Z',
};
@@ -51,7 +52,6 @@ export const packagesCleanupPolicyPayload = (override) => ({
project: {
id: '1',
packagesCleanupPolicy: {
- __typename: 'PackagesCleanupPolicy',
...packagesCleanupPolicyData,
...override,
},
diff --git a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
index 361a9aabf33..ffe3599ac64 100644
--- a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
+++ b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
@@ -90,7 +90,7 @@ describe('AdminRunnerEditApp', () => {
loading: false,
runnerPath: mockRunnerPath,
});
- expect(findRunnerUpdateForm().props('runner')).toEqualGraphqlFixture(mockRunner);
+ expect(findRunnerUpdateForm().props('runner')).toEqual(mockRunner);
});
describe('When there is an error', () => {
diff --git a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
index 1ae6eed806f..509681c5a77 100644
--- a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
+++ b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js
@@ -256,7 +256,7 @@ describe('AdminRunnerShowApp', () => {
await createComponent({ stubs });
expect(findJobCountBadge().text()).toBe('3');
- expect(findRunnersJobs().props('runner')).toEqualGraphqlFixture({ ...mockRunner, ...runner });
+ expect(findRunnersJobs().props('runner')).toEqual({ ...mockRunner, ...runner });
});
});
});
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index f8f834c7ad4..9ba6924f5c7 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -176,7 +176,7 @@ describe('AdminRunnersApp', () => {
await createComponent();
expect(mockRunnersHandler).toHaveBeenCalledTimes(1);
- expect(findRunnerList().props('runners')).toEqualGraphqlFixture(mockRunners);
+ expect(findRunnerList().props('runners')).toEqual(mockRunners);
});
it('runner item links to the runner admin page', async () => {
@@ -197,7 +197,7 @@ describe('AdminRunnersApp', () => {
const runnerActions = wrapper.find('tr [data-testid="td-actions"]').find(RunnerActionsCell);
const runner = mockRunners[0];
- expect(runnerActions.props()).toEqualGraphqlFixture({
+ expect(runnerActions.props()).toEqual({
runner,
editUrl: runner.editAdminUrl,
});
@@ -482,7 +482,7 @@ describe('AdminRunnersApp', () => {
});
it('passes the page info', () => {
- expect(findRunnerPagination().props('pageInfo')).toEqualGraphqlFixture(pageInfo);
+ expect(findRunnerPagination().props('pageInfo')).toEqual(pageInfo);
});
it('navigates to the next page', async () => {
diff --git a/spec/frontend/runner/components/runner_jobs_spec.js b/spec/frontend/runner/components/runner_jobs_spec.js
index 8e3715e45d2..4d38afb25ee 100644
--- a/spec/frontend/runner/components/runner_jobs_spec.js
+++ b/spec/frontend/runner/components/runner_jobs_spec.js
@@ -73,7 +73,7 @@ describe('RunnerJobs', () => {
it('Shows jobs', () => {
const jobs = findRunnerJobsTable().props('jobs');
- expect(jobs).toEqualGraphqlFixture(mockJobs);
+ expect(jobs).toEqual(mockJobs);
});
describe('When "Next" page is clicked', () => {
diff --git a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
index 5d3552af322..cee1d436942 100644
--- a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
+++ b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js
@@ -107,7 +107,7 @@ describe('GroupRunnerShowApp', () => {
});
it('renders runner details component', () => {
- expect(findRunnerDetails().props('runner')).toEqualGraphqlFixture(mockRunner);
+ expect(findRunnerDetails().props('runner')).toEqual(mockRunner);
});
describe('when runner cannot be updated', () => {
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index a288d088b5b..57d64202219 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -168,7 +168,7 @@ describe('GroupRunnersApp', () => {
await createComponent();
const runners = findRunnerList().props('runners');
- expect(runners).toEqualGraphqlFixture(mockGroupRunnersEdges.map(({ node }) => node));
+ expect(runners).toEqual(mockGroupRunnersEdges.map(({ node }) => node));
});
it('requests the runners with group path and no other filters', async () => {
@@ -382,7 +382,7 @@ describe('GroupRunnersApp', () => {
});
it('passes the page info', () => {
- expect(findRunnerPagination().props('pageInfo')).toEqualGraphqlFixture(pageInfo);
+ expect(findRunnerPagination().props('pageInfo')).toEqual(pageInfo);
});
it('navigates to the next page', async () => {
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
index 5fd364afbe4..88015ed42a3 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -148,6 +148,7 @@ describe('Sidebar assignees widget', () => {
expect(findAssignees().props('users')).toEqual([
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
diff --git a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
index 338ecf944f3..859e63b3df6 100644
--- a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
+++ b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { stripTypenames } from 'helpers/graphql_helpers';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Participants from '~/sidebar/components/participants/participants.vue';
@@ -67,11 +66,9 @@ describe('Sidebar Participants Widget', () => {
});
it('passes participants to child component', () => {
- const participantsWithoutTypename = stripTypenames(
+ expect(findParticipants().props('participants')).toEqual(
epicParticipantsResponse().data.workspace.issuable.participants.nodes,
);
-
- expect(findParticipants().props('participants')).toEqual(participantsWithoutTypename);
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 86d1f21fd04..a6713b7e7e4 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -66,12 +66,14 @@ export const mockMilestones = [
export const mockCrmContacts = [
{
+ __typename: 'CustomerRelationsContact',
id: 'gid://gitlab/CustomerRelations::Contact/1',
firstName: 'John',
lastName: 'Smith',
email: 'john@smith.com',
},
{
+ __typename: 'CustomerRelationsContact',
id: 'gid://gitlab/CustomerRelations::Contact/2',
firstName: 'Andy',
lastName: 'Green',
@@ -81,10 +83,12 @@ export const mockCrmContacts = [
export const mockCrmOrganizations = [
{
+ __typename: 'CustomerRelationsOrganization',
id: 'gid://gitlab/CustomerRelations::Organization/1',
name: 'First Org Ltd.',
},
{
+ __typename: 'CustomerRelationsOrganization',
id: 'gid://gitlab/CustomerRelations::Organization/2',
name: 'Organizer S.p.a.',
},
@@ -102,11 +106,9 @@ export const mockProjectCrmContactsQueryResponse = {
__typename: 'CustomerRelationsContactConnection',
nodes: [
{
- __typename: 'CustomerRelationsContact',
...mockCrmContacts[0],
},
{
- __typename: 'CustomerRelationsContact',
...mockCrmContacts[1],
},
],
@@ -128,11 +130,9 @@ export const mockProjectCrmOrganizationsQueryResponse = {
__typename: 'CustomerRelationsOrganizationConnection',
nodes: [
{
- __typename: 'CustomerRelationsOrganization',
...mockCrmOrganizations[0],
},
{
- __typename: 'CustomerRelationsOrganization',
...mockCrmOrganizations[1],
},
],
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
index 1b27a294b90..cad401e0013 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
@@ -131,6 +131,7 @@ describe('LabelsSelectRoot', () => {
expect(findDropdownValue().exists()).toBe(true);
expect(findDropdownValue().props('selectedLabels')).toEqual([
{
+ __typename: 'Label',
color: '#330066',
description: null,
id: 'gid://gitlab/ProjectLabel/1',
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index c7b84a0f73b..4188adc72a1 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -4,7 +4,6 @@ import { cloneDeep } from 'lodash';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { stripTypenames } from 'helpers/graphql_helpers';
import waitForPromises from 'helpers/wait_for_promises';
import searchUsersQuery from '~/graphql_shared/queries/users_search.query.graphql';
import searchUsersQueryOnMR from '~/graphql_shared/queries/users_search_with_mr_permissions.graphql';
@@ -201,7 +200,7 @@ describe('User select dropdown', () => {
});
await waitForPromises();
- expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(stripTypenames(mockUser2));
+ expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(mockUser2);
});
it('moves issuable author on top of unassigned list after current user, if author and current user are unassigned project members', async () => {
@@ -216,12 +215,8 @@ describe('User select dropdown', () => {
});
await waitForPromises();
- expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(
- stripTypenames(currentUser),
- );
- expect(findUnselectedParticipantByIndex(1).props('user')).toMatchObject(
- stripTypenames(issuableAuthor),
- );
+ expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(currentUser);
+ expect(findUnselectedParticipantByIndex(1).props('user')).toMatchObject(issuableAuthor);
});
it('displays author in a designated position if author is not assigned and not a project member', async () => {
diff --git a/spec/frontend/work_items/components/work_item_assignees_spec.js b/spec/frontend/work_items/components/work_item_assignees_spec.js
index 450d9cff963..febff4554e4 100644
--- a/spec/frontend/work_items/components/work_item_assignees_spec.js
+++ b/spec/frontend/work_items/components/work_item_assignees_spec.js
@@ -344,7 +344,7 @@ describe('WorkItemAssignees component', () => {
it('adds current user to the top of dropdown items', () => {
expect(findTokenSelector().props('dropdownItems')[0]).toEqual({
- ...stripTypenames(currentUserResponse.data.currentUser),
+ ...currentUserResponse.data.currentUser,
class: expect.anything(),
});
});
@@ -354,7 +354,7 @@ describe('WorkItemAssignees component', () => {
await waitForPromises();
expect(findTokenSelector().props('dropdownItems')[0]).not.toEqual(
- stripTypenames(currentUserResponse.data.currentUser),
+ currentUserResponse.data.currentUser,
);
});
});
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 214086a3823..04c066986b7 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -968,7 +968,8 @@ RSpec.describe ProjectsHelper do
securityAndComplianceAccessLevel: project.security_and_compliance_access_level,
containerRegistryAccessLevel: project.project_feature.container_registry_access_level,
environmentsAccessLevel: project.project_feature.environments_access_level,
- featureFlagsAccessLevel: project.project_feature.feature_flags_access_level
+ featureFlagsAccessLevel: project.project_feature.feature_flags_access_level,
+ releasesAccessLevel: project.project_feature.releases_access_level
)
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 72e13943bf5..5cbe05ccf53 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -585,6 +585,7 @@ ProjectFeature:
- package_registry_access_level
- environments_access_level
- feature_flags_access_level
+- releases_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb
index 48c391451ed..b49b9ce8a2a 100644
--- a/spec/models/concerns/project_features_compatibility_spec.rb
+++ b/spec/models/concerns/project_features_compatibility_spec.rb
@@ -6,7 +6,9 @@ RSpec.describe ProjectFeaturesCompatibility do
let(:project) { create(:project) }
let(:features_enabled) { %w(issues wiki builds merge_requests snippets security_and_compliance) }
let(:features) do
- features_enabled + %w(repository pages operations container_registry package_registry environments feature_flags)
+ features_enabled + %w(
+ repository pages operations container_registry package_registry environments feature_flags releases
+ )
end
# We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 9f5ce48287f..98b202299a8 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -835,6 +835,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to delegate_method(:container_registry_access_level).to(:project_feature) }
it { is_expected.to delegate_method(:environments_access_level).to(:project_feature) }
it { is_expected.to delegate_method(:feature_flags_access_level).to(:project_feature) }
+ it { is_expected.to delegate_method(:releases_access_level).to(:project_feature) }
describe 'read project settings' do
%i(
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index c3817f67158..e8fdf9a8e25 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -2171,6 +2171,74 @@ RSpec.describe ProjectPolicy do
end
end
+ describe 'Releases feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_permissions) { [:read_release] }
+
+ let(:developer_permissions) do
+ guest_permissions + [:create_release, :update_release, :destroy_release]
+ end
+
+ let(:maintainer_permissions) do
+ developer_permissions
+ end
+
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | true
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | true
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { user_subject(role) }
+ let(:project) { project_subject(project_visibility) }
+
+ it 'allows/disallows the abilities based on the Releases access level' do
+ project.project_feature.update!(releases_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
+ end
+ end
+ end
+ end
+
describe 'access_security_and_compliance' do
context 'when the "Security & Compliance" is enabled' do
before do