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-11 21:11:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-11 21:11:57 +0300
commit603ee53dbdbd3adaced752e1a119eb40d64e9979 (patch)
tree7c3e912fe4c02ea464063a4a224b02bbcdeea580 /spec
parentc79523e3952dad31a9ab8ccbb9e38466fec3aec3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects_controller_spec.rb81
-rw-r--r--spec/factories/projects.rb1
-rw-r--r--spec/frontend/boards/components/board_new_item_spec.js4
-rw-r--r--spec/frontend/clusters/agents/components/activity_history_item_spec.js2
-rw-r--r--spec/frontend/clusters/agents/components/create_token_modal_spec.js2
-rw-r--r--spec/frontend/clusters/agents/components/token_table_spec.js4
-rw-r--r--spec/frontend/clusters/components/new_cluster_spec.js4
-rw-r--r--spec/frontend/clusters/forms/components/integration_form_spec.js4
-rw-r--r--spec/frontend/diffs/store/utils_spec.js8
-rw-r--r--spec/frontend/dropzone_input_spec.js4
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js24
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations/merge_request_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js4
-rw-r--r--spec/frontend/sidebar/assignees_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js2
-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.rb82
-rw-r--r--spec/spec_helper.rb4
23 files changed, 194 insertions, 55 deletions
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 34477a7bb68..388d7c2266b 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -878,30 +878,81 @@ RSpec.describe ProjectsController do
end
context 'with project feature attributes' do
- using RSpec::Parameterized::TableSyntax
+ let(:initial_value) { ProjectFeature::PRIVATE }
+ let(:update_to) { ProjectFeature::ENABLED }
- where(:feature, :initial_value, :update_to) do
- :metrics_dashboard_access_level | ProjectFeature::PRIVATE | ProjectFeature::ENABLED
- :container_registry_access_level | ProjectFeature::ENABLED | ProjectFeature::PRIVATE
+ before do
+ project.project_feature.update!(feature_access_level => initial_value)
end
- with_them do
- it "updates the project_feature new" do
- params = {
- namespace_id: project.namespace,
- id: project.path,
- project: {
- project_feature_attributes: {
- "#{feature}": update_to
- }
+ def update_project_feature
+ put :update, params: {
+ namespace_id: project.namespace,
+ id: project.path,
+ project: {
+ project_feature_attributes: {
+ feature_access_level.to_s => update_to
}
}
+ }
+ end
- expect { put :update, params: params }.to change {
- project.reload.project_feature.public_send(feature)
+ shared_examples 'feature update success' do
+ it 'updates access level successfully' do
+ expect { update_project_feature }.to change {
+ project.reload.project_feature.public_send(feature_access_level)
}.from(initial_value).to(update_to)
end
end
+
+ shared_examples 'feature update failure' do
+ it 'cannot update access level' do
+ expect { update_project_feature }.not_to change {
+ project.reload.project_feature.public_send(feature_access_level)
+ }
+ end
+ end
+
+ where(:feature_access_level) do
+ %i[
+ metrics_dashboard_access_level
+ container_registry_access_level
+ environments_access_level
+ feature_flags_access_level
+ ]
+ end
+
+ with_them do
+ it_behaves_like 'feature update success'
+ end
+
+ context 'for feature_access_level operations_access_level' do
+ let(:feature_access_level) { :operations_access_level }
+
+ include_examples 'feature update failure'
+ end
+
+ context 'with feature flag split_operations_visibility_permissions disabled' do
+ before do
+ stub_feature_flags(split_operations_visibility_permissions: false)
+ end
+
+ context 'for feature_access_level operations_access_level' do
+ let(:feature_access_level) { :operations_access_level }
+
+ include_examples 'feature update success'
+ end
+
+ where(:feature_access_level) do
+ %i[
+ environments_access_level feature_flags_access_level
+ ]
+ end
+
+ with_them do
+ it_behaves_like 'feature update failure'
+ end
+ end
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 107fa28a639..98dfecb2888 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -38,6 +38,7 @@ FactoryBot.define do
container_registry_access_level { ProjectFeature::ENABLED }
security_and_compliance_access_level { ProjectFeature::PRIVATE }
environments_access_level { ProjectFeature::ENABLED }
+ feature_flags_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/boards/components/board_new_item_spec.js b/spec/frontend/boards/components/board_new_item_spec.js
index 86cebc8a719..dc6581e9360 100644
--- a/spec/frontend/boards/components/board_new_item_spec.js
+++ b/spec/frontend/boards/components/board_new_item_spec.js
@@ -93,7 +93,7 @@ describe('BoardNewItem', () => {
titleInput().setValue('Foo');
await glForm().trigger('submit');
- expect(wrapper.emitted('form-submit')).toBeTruthy();
+ expect(wrapper.emitted('form-submit')).toHaveLength(1);
expect(wrapper.emitted('form-submit')[0]).toEqual([
{
title: 'Foo',
@@ -131,7 +131,7 @@ describe('BoardNewItem', () => {
await glForm().trigger('reset');
expect(titleInput().element.value).toBe('');
- expect(wrapper.emitted('form-cancel')).toBeTruthy();
+ expect(wrapper.emitted('form-cancel')).toHaveLength(1);
});
});
});
diff --git a/spec/frontend/clusters/agents/components/activity_history_item_spec.js b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
index 100a280d0cc..68f6f11aa8f 100644
--- a/spec/frontend/clusters/agents/components/activity_history_item_spec.js
+++ b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
@@ -23,7 +23,7 @@ describe('ActivityHistoryItem', () => {
};
const findHistoryItem = () => wrapper.findComponent(HistoryItem);
- const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
+ const findTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/clusters/agents/components/create_token_modal_spec.js b/spec/frontend/clusters/agents/components/create_token_modal_spec.js
index ad48afe10b6..0d10801e80e 100644
--- a/spec/frontend/clusters/agents/components/create_token_modal_spec.js
+++ b/spec/frontend/clusters/agents/components/create_token_modal_spec.js
@@ -55,7 +55,7 @@ describe('CreateTokenModal', () => {
const findAgentInstructions = () => findModal().findComponent(AgentToken);
const findButtonByVariant = (variant) =>
findModal()
- .findAll(GlButton)
+ .findAllComponents(GlButton)
.wrappers.find((button) => button.props('variant') === variant);
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => wrapper.findByTestId('agent-token-close-button');
diff --git a/spec/frontend/clusters/agents/components/token_table_spec.js b/spec/frontend/clusters/agents/components/token_table_spec.js
index 6caeaf5c192..334615f1818 100644
--- a/spec/frontend/clusters/agents/components/token_table_spec.js
+++ b/spec/frontend/clusters/agents/components/token_table_spec.js
@@ -136,8 +136,8 @@ describe('ClusterAgentTokenTable', () => {
const token = tokens.at(lineNumber);
expect(token.text()).toContain(description);
- expect(token.find(GlTruncate).exists()).toBe(truncatesText);
- expect(token.find(GlTooltip).exists()).toBe(hasTooltip);
+ expect(token.findComponent(GlTruncate).exists()).toBe(truncatesText);
+ expect(token.findComponent(GlTooltip).exists()).toBe(hasTooltip);
},
);
diff --git a/spec/frontend/clusters/components/new_cluster_spec.js b/spec/frontend/clusters/components/new_cluster_spec.js
index f9df70b9f87..ef39c90aaef 100644
--- a/spec/frontend/clusters/components/new_cluster_spec.js
+++ b/spec/frontend/clusters/components/new_cluster_spec.js
@@ -12,9 +12,9 @@ describe('NewCluster', () => {
await nextTick();
};
- const findDescription = () => wrapper.find(GlSprintf);
+ const findDescription = () => wrapper.findComponent(GlSprintf);
- const findLink = () => wrapper.find(GlLink);
+ const findLink = () => wrapper.findComponent(GlLink);
beforeEach(() => {
return createWrapper();
diff --git a/spec/frontend/clusters/forms/components/integration_form_spec.js b/spec/frontend/clusters/forms/components/integration_form_spec.js
index 67d442bfdc5..b17886a5826 100644
--- a/spec/frontend/clusters/forms/components/integration_form_spec.js
+++ b/spec/frontend/clusters/forms/components/integration_form_spec.js
@@ -32,8 +32,8 @@ describe('ClusterIntegrationForm', () => {
wrapper = null;
};
- const findSubmitButton = () => wrapper.find(GlButton);
- const findGlToggle = () => wrapper.find(GlToggle);
+ const findSubmitButton = () => wrapper.findComponent(GlButton);
+ const findGlToggle = () => wrapper.findComponent(GlToggle);
afterEach(() => {
destroyWrapper();
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 8852c6c62c5..3f870a98396 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -424,8 +424,8 @@ describe('DiffsStoreUtils', () => {
expect(firstChar).not.toBe('+');
expect(firstChar).not.toBe('-');
- expect(preparedDiff.diff_files[0].renderIt).toBeTruthy();
- expect(preparedDiff.diff_files[0].collapsed).toBeFalsy();
+ expect(preparedDiff.diff_files[0].renderIt).toBe(true);
+ expect(preparedDiff.diff_files[0].collapsed).toBe(false);
});
it('guarantees an empty array for both diff styles', () => {
@@ -506,8 +506,8 @@ describe('DiffsStoreUtils', () => {
});
it('sets the renderIt and collapsed attribute on files', () => {
- expect(preparedDiffFiles[0].renderIt).toBeTruthy();
- expect(preparedDiffFiles[0].collapsed).toBeFalsy();
+ expect(preparedDiffFiles[0].renderIt).toBe(true);
+ expect(preparedDiffFiles[0].collapsed).toBeUndefined();
});
it('guarantees an empty array of lines for both diff styles', () => {
diff --git a/spec/frontend/dropzone_input_spec.js b/spec/frontend/dropzone_input_spec.js
index a633de9ef56..0fe70bac6b7 100644
--- a/spec/frontend/dropzone_input_spec.js
+++ b/spec/frontend/dropzone_input_spec.js
@@ -29,7 +29,9 @@ describe('dropzone_input', () => {
it('returns valid dropzone when successfully initialize', () => {
const dropzone = dropzoneInput($(TEMPLATE));
- expect(dropzone.version).toBeTruthy();
+ expect(dropzone).toMatchObject({
+ version: expect.any(String),
+ });
});
describe('handlePaste', () => {
diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
index 1ba5a505f57..b44af547658 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -41,23 +41,23 @@ describe('error tracking settings project dropdown', () => {
describe('empty project list', () => {
it('renders the dropdown', () => {
- expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ expect(wrapper.find('#project-dropdown').exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
it('shows helper text', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeTruthy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(true);
expect(wrapper.find('.js-project-dropdown-label').text()).toContain(
'To enable project selection',
);
});
it('does not show an error', () => {
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(false);
});
it('does not contain any dropdown items', () => {
- expect(wrapper.find(GlDropdownItem).exists()).toBeFalsy();
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(false);
expect(wrapper.find(GlDropdown).props('text')).toBe('No projects available');
});
});
@@ -70,12 +70,12 @@ describe('error tracking settings project dropdown', () => {
});
it('renders the dropdown', () => {
- expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ expect(wrapper.find('#project-dropdown').exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
it('contains a number of dropdown items', () => {
- expect(wrapper.find(GlDropdownItem).exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(true);
expect(wrapper.findAll(GlDropdownItem).length).toBe(2);
});
});
@@ -89,8 +89,8 @@ describe('error tracking settings project dropdown', () => {
});
it('does not show helper text', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(false);
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(false);
});
});
@@ -105,8 +105,8 @@ describe('error tracking settings project dropdown', () => {
});
it('displays a error', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeTruthy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(false);
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index d43393875eb..6e8a03b47ad 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -134,7 +134,7 @@ describe('Multi-file store tree actions', () => {
it('toggles the tree open', async () => {
await store.dispatch('toggleTreeOpen', tree.path);
- expect(tree.opened).toBeTruthy();
+ expect(tree.opened).toBe(true);
});
});
diff --git a/spec/frontend/ide/stores/mutations/merge_request_spec.js b/spec/frontend/ide/stores/mutations/merge_request_spec.js
index afbe6770c0d..2af06835181 100644
--- a/spec/frontend/ide/stores/mutations/merge_request_spec.js
+++ b/spec/frontend/ide/stores/mutations/merge_request_spec.js
@@ -30,7 +30,7 @@ describe('IDE store merge request mutations', () => {
const newMr = localState.projects.abcproject.mergeRequests[1];
expect(newMr.title).toBe('mr');
- expect(newMr.active).toBeTruthy();
+ expect(newMr.active).toBe(true);
});
it('keeps original data', () => {
diff --git a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
index ce98a16dbb7..16d4459f597 100644
--- a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
+++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
@@ -157,8 +157,8 @@ describe('AddIssuableForm', () => {
describe('categorized issuables', () => {
it.each`
issuableType | pathIdSeparator | contextHeader | contextFooter
- ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issue(s)'}
- ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epic(s)'}
+ ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issues'}
+ ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epics'}
`(
'show header text as "$contextHeader" and footer text as "$contextFooter" issuableType is set to $issuableType',
({ issuableType, contextHeader, contextFooter }) => {
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index a4474ead956..c2aff456abb 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -70,7 +70,7 @@ describe('Assignee component', () => {
wrapper.find('[data-testid="assign-yourself"]').trigger('click');
await nextTick();
- expect(wrapper.emitted('assign-self')).toBeTruthy();
+ expect(wrapper.emitted('assign-self')).toHaveLength(1);
});
});
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index ffc0f873377..9831908f806 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -125,8 +125,8 @@ describe('Markdown field header component', () => {
),
]);
- expect(wrapper.emitted('preview-markdown')).toBeFalsy();
- expect(wrapper.emitted('write-markdown')).toBeFalsy();
+ expect(wrapper.emitted('preview-markdown')).toBeUndefined();
+ expect(wrapper.emitted('write-markdown')).toBeUndefined();
});
it('blurs preview link after click', () => {
diff --git a/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js b/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
index 2cefa77b72d..1789610dba9 100644
--- a/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
+++ b/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
@@ -114,7 +114,7 @@ describe('Metric images tab', () => {
await waitForPromises();
- expect(findModal().attributes('visible')).toBeFalsy();
+ expect(findModal().attributes('visible')).toBeUndefined();
});
it('should add files and url when selected', async () => {
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 200e93f8dff..214086a3823 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -967,7 +967,8 @@ RSpec.describe ProjectsHelper do
showDefaultAwardEmojis: project.show_default_award_emojis?,
securityAndComplianceAccessLevel: project.security_and_compliance_access_level,
containerRegistryAccessLevel: project.project_feature.container_registry_access_level,
- environmentsAccessLevel: project.project_feature.environments_access_level
+ environmentsAccessLevel: project.project_feature.environments_access_level,
+ featureFlagsAccessLevel: project.project_feature.feature_flags_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 1078d4587f7..72e13943bf5 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -584,6 +584,7 @@ ProjectFeature:
- container_registry_access_level
- package_registry_access_level
- environments_access_level
+- feature_flags_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 6730b7a02f3..48c391451ed 100644
--- a/spec/models/concerns/project_features_compatibility_spec.rb
+++ b/spec/models/concerns/project_features_compatibility_spec.rb
@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe ProjectFeaturesCompatibility do
let(:project) { create(:project) }
let(:features_enabled) { %w(issues wiki builds merge_requests snippets security_and_compliance) }
- let(:features) { features_enabled + %w(repository pages operations container_registry package_registry environments) }
+ let(:features) do
+ features_enabled + %w(repository pages operations container_registry package_registry environments feature_flags)
+ end
# We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table
# All those fields got moved to a new table called project_feature and are now integers instead of booleans
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 2920278679f..05651f7d85a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -833,6 +833,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to delegate_method(:container_registry_enabled?).to(:project_feature) }
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) }
describe 'read project settings' do
%i(
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 01a0a96be30..c3817f67158 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -2100,6 +2100,77 @@ RSpec.describe ProjectPolicy do
end
end
+ describe 'feature flags feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_permissions) { [] }
+
+ let(:developer_permissions) do
+ guest_permissions + [
+ :read_feature_flag, :create_feature_flag, :update_feature_flag, :destroy_feature_flag, :admin_feature_flag,
+ :admin_feature_flags_user_lists
+ ]
+ end
+
+ let(:maintainer_permissions) do
+ developer_permissions + [:admin_feature_flags_client]
+ 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 | false
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | false
+ :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 feature flags access level' do
+ project.project_feature.update!(feature_flags_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
@@ -2566,4 +2637,15 @@ RSpec.describe ProjectPolicy do
anonymous
end
end
+
+ def permissions_abilities(role)
+ case role
+ when :maintainer
+ maintainer_permissions
+ when :developer
+ developer_permissions
+ else
+ guest_permissions
+ end
+ end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 1b3ff4bf2b9..8acf3bcf9c0 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -53,10 +53,8 @@ end
require 'rainbow/ext/string'
Rainbow.enabled = false
-# Require JH first because we need override some EE methods with JH methods,
-# if we load EE first, we can't find JH modules in prepend_mod method
-require_relative('../jh/spec/spec_helper') if Gitlab.jh?
require_relative('../ee/spec/spec_helper') if Gitlab.ee?
+require_relative('../jh/spec/spec_helper') if Gitlab.jh?
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.