summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-05 18:17:47 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-05 18:17:47 +0000
commitbc4cd6ffb93ae695f20ea54f4e4803d50c78a69e (patch)
tree2364d0f880af998b70356628f79cda64f13a11e7 /spec
parent6634288474d2a83cac7b4205f3ffc736cc6b36db (diff)
downloadgitlab-ce-bc4cd6ffb93ae695f20ea54f4e4803d50c78a69e.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/organizations.rb5
-rw-r--r--spec/features/users/login_spec.rb82
-rw-r--r--spec/frontend/graphql_shared/utils_spec.js71
-rw-r--r--spec/frontend/issues/show/components/description_spec.js9
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js41
-rw-r--r--spec/frontend/security_configuration/mock_data.js18
-rw-r--r--spec/frontend/security_configuration/utils_spec.js38
-rw-r--r--spec/frontend/work_items/components/work_item_actions_spec.js16
-rw-r--r--spec/frontend/work_items/components/work_item_assignees_spec.js27
-rw-r--r--spec/frontend/work_items/components/work_item_detail_spec.js35
-rw-r--r--spec/frontend/work_items/mock_data.js93
-rw-r--r--spec/frontend/work_items/router_spec.js4
-rw-r--r--spec/helpers/sessions_helper_spec.rb20
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb6
-rw-r--r--spec/models/integrations/prometheus_spec.rb48
-rw-r--r--spec/models/organization_spec.rb10
-rw-r--r--spec/models/project_spec.rb18
-rw-r--r--spec/models/user_spec.rb14
-rw-r--r--spec/services/members/destroy_service_spec.rb141
-rw-r--r--spec/support/helpers/user_login_helper.rb16
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb12
22 files changed, 358 insertions, 368 deletions
diff --git a/spec/factories/organizations.rb b/spec/factories/organizations.rb
new file mode 100644
index 00000000000..a6684a8f95f
--- /dev/null
+++ b/spec/factories/organizations.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :organization
+end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index e6e5a1f9894..6f155959adb 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -394,6 +394,24 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions, feature_category: :system_
providers: [mock_saml_config_with_upstream_two_factor_authn_contexts])
end
+ it 'displays the remember me checkbox' do
+ visit new_user_session_path
+
+ expect(page).to have_field('remember_me_omniauth')
+ end
+
+ context 'when remember me is not enabled' do
+ before do
+ stub_application_setting(remember_me_enabled: false)
+ end
+
+ it 'does not display the remember me checkbox' do
+ visit new_user_session_path
+
+ expect(page).not_to have_field('remember_me_omniauth')
+ end
+ end
+
context 'when authn_context is worth two factors' do
let(:mock_saml_response) do
File.read('spec/fixtures/authentication/saml_response.xml')
@@ -444,6 +462,24 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions, feature_category: :system_
end
describe 'without two-factor authentication' do
+ it 'displays the remember me checkbox' do
+ visit new_user_session_path
+
+ expect(page).to have_content(_('Remember me'))
+ end
+
+ context 'when remember me is not enabled' do
+ before do
+ stub_application_setting(remember_me_enabled: false)
+ end
+
+ it 'does not display the remember me checkbox' do
+ visit new_user_session_path
+
+ expect(page).not_to have_content(_('Remember me'))
+ end
+ end
+
context 'with correct username and password' do
let(:user) { create(:user) }
@@ -750,17 +786,37 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions, feature_category: :system_
allow(instance).to receive(:"user_#{provider}_omniauth_callback_path")
.and_return("/users/auth/#{provider}/callback")
end
-
- visit new_user_session_path
end
it 'correctly renders tabs and panes' do
+ visit new_user_session_path
+
ensure_tab_pane_correctness(['Main LDAP', 'Standard'])
end
it 'renders link to sign up path' do
+ visit new_user_session_path
+
expect(page.body).to have_link('Register now', href: new_user_registration_path)
end
+
+ it 'displays the remember me checkbox' do
+ visit new_user_session_path
+
+ ensure_remember_me_in_tab(ldap_server_config['label'])
+ end
+
+ context 'when remember me is not enabled' do
+ before do
+ stub_application_setting(remember_me_enabled: false)
+ end
+
+ it 'does not display the remember me checkbox' do
+ visit new_user_session_path
+
+ ensure_remember_me_not_in_tab(ldap_server_config['label'])
+ end
+ end
end
context 'when crowd is enabled' do
@@ -775,13 +831,31 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions, feature_category: :system_
allow(instance).to receive(:user_crowd_omniauth_authorize_path)
.and_return("/users/auth/crowd/callback")
end
-
- visit new_user_session_path
end
it 'correctly renders tabs and panes' do
+ visit new_user_session_path
+
ensure_tab_pane_correctness(%w(Crowd Standard))
end
+
+ it 'displays the remember me checkbox' do
+ visit new_user_session_path
+
+ ensure_remember_me_in_tab(_('Crowd'))
+ end
+
+ context 'when remember me is not enabled' do
+ before do
+ stub_application_setting(remember_me_enabled: false)
+ end
+
+ it 'does not display the remember me checkbox' do
+ visit new_user_session_path
+
+ ensure_remember_me_not_in_tab(_('Crowd'))
+ end
+ end
end
end
diff --git a/spec/frontend/graphql_shared/utils_spec.js b/spec/frontend/graphql_shared/utils_spec.js
index 35ae8de1b1f..f03856e5f75 100644
--- a/spec/frontend/graphql_shared/utils_spec.js
+++ b/spec/frontend/graphql_shared/utils_spec.js
@@ -3,6 +3,7 @@ import Visibility from 'visibilityjs';
import {
isGid,
getIdFromGraphQLId,
+ getTypeFromGraphQLId,
convertToGraphQLId,
convertToGraphQLIds,
convertFromGraphQLIds,
@@ -26,52 +27,30 @@ describe('isGid', () => {
});
});
-describe('getIdFromGraphQLId', () => {
- [
- {
- input: '',
- output: null,
- },
- {
- input: null,
- output: null,
- },
- {
- input: 2,
- output: 2,
- },
- {
- input: 'gid://',
- output: null,
- },
- {
- input: 'gid://gitlab/',
- output: null,
- },
- {
- input: 'gid://gitlab/Environments',
- output: null,
- },
- {
- input: 'gid://gitlab/Environments/',
- output: null,
- },
- {
- input: 'gid://gitlab/Environments/0',
- output: 0,
- },
- {
- input: 'gid://gitlab/Environments/123',
- output: 123,
- },
- {
- input: 'gid://gitlab/DesignManagement::Version/2',
- output: 2,
- },
- ].forEach(({ input, output }) => {
- it(`getIdFromGraphQLId returns ${output} when passed ${input}`, () => {
- expect(getIdFromGraphQLId(input)).toBe(output);
- });
+describe.each`
+ input | id | type
+ ${''} | ${null} | ${null}
+ ${null} | ${null} | ${null}
+ ${0} | ${0} | ${null}
+ ${'0'} | ${0} | ${null}
+ ${2} | ${2} | ${null}
+ ${'2'} | ${2} | ${null}
+ ${'gid://'} | ${null} | ${null}
+ ${'gid://gitlab'} | ${null} | ${null}
+ ${'gid://gitlab/'} | ${null} | ${null}
+ ${'gid://gitlab/Environments'} | ${null} | ${'Environments'}
+ ${'gid://gitlab/Environments/'} | ${null} | ${'Environments'}
+ ${'gid://gitlab/Environments/0'} | ${0} | ${'Environments'}
+ ${'gid://gitlab/Environments/123'} | ${123} | ${'Environments'}
+ ${'gid://gitlab/Environments/123/test'} | ${123} | ${'Environments'}
+ ${'gid://gitlab/DesignManagement::Version/123'} | ${123} | ${'DesignManagement::Version'}
+`('parses GraphQL ID `$input`', ({ input, id, type }) => {
+ it(`getIdFromGraphQLId returns ${id}`, () => {
+ expect(getIdFromGraphQLId(input)).toBe(id);
+ });
+
+ it(`getTypeFromGraphQLId returns ${type}`, () => {
+ expect(getTypeFromGraphQLId(input)).toBe(type);
});
});
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
index c6869573b2e..9a0cde15b24 100644
--- a/spec/frontend/issues/show/components/description_spec.js
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -8,7 +8,6 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createAlert } from '~/alert';
import Description from '~/issues/show/components/description.vue';
import eventHub from '~/issues/show/event_hub';
-import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutation.graphql';
import workItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
import TaskList from '~/task_list';
@@ -35,13 +34,6 @@ const $toast = {
};
const issueDetailsResponse = getIssueDetailsResponse();
-const workItemQueryResponse = {
- data: {
- workItem: null,
- },
-};
-
-const queryHandler = jest.fn().mockResolvedValue(workItemQueryResponse);
const workItemTypesQueryHandler = jest.fn().mockResolvedValue(projectWorkItemTypesQueryResponse);
describe('Description component', () => {
@@ -72,7 +64,6 @@ describe('Description component', () => {
...provide,
},
apolloProvider: createMockApollo([
- [workItemQuery, queryHandler],
[workItemTypesQuery, workItemTypesQueryHandler],
[getIssueDetailsQuery, issueDetailsQueryHandler],
[createWorkItemMutation, createWorkItemMutationHandler],
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index c4e6bef71eb..364fe733a41 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -11,7 +11,7 @@ import AutoDevopsEnabledAlert from '~/security_configuration/components/auto_dev
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from '~/security_configuration/components/constants';
import FeatureCard from '~/security_configuration/components/feature_card.vue';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
-import { complianceFeaturesMock, securityFeaturesMock, provideMock } from '../mock_data';
+import { securityFeaturesMock, provideMock } from '../mock_data';
const gitlabCiHistoryPath = 'test/historyPath';
const { vulnerabilityTrainingDocsPath, projectFullPath } = provideMock;
@@ -29,7 +29,6 @@ describe('~/security_configuration/components/app', () => {
wrapper = mountExtended(SecurityConfigurationApp, {
propsData: {
augmentedSecurityFeatures: securityFeaturesMock,
- augmentedComplianceFeatures: complianceFeaturesMock,
securityTrainingEnabled: true,
...propsData,
},
@@ -72,12 +71,7 @@ describe('~/security_configuration/components/app', () => {
text: i18n.configurationHistory,
container: findByTestId('security-testing-tab'),
});
- const findComplianceViewHistoryLink = () =>
- findLink({
- href: gitlabCiHistoryPath,
- text: i18n.configurationHistory,
- container: findByTestId('compliance-testing-tab'),
- });
+
const findAutoDevopsAlert = () => wrapper.findComponent(AutoDevopsAlert);
const findAutoDevopsEnabledAlert = () => wrapper.findComponent(AutoDevopsEnabledAlert);
const findVulnerabilityManagementTab = () => wrapper.findByTestId('vulnerability-management-tab');
@@ -94,7 +88,7 @@ describe('~/security_configuration/components/app', () => {
});
describe('tabs', () => {
- const expectedTabs = ['security-testing', 'compliance-testing', 'vulnerability-management'];
+ const expectedTabs = ['security-testing', 'vulnerability-management'];
it('renders GlTab Component', () => {
expect(findTab().exists()).toBe(true);
@@ -123,9 +117,8 @@ describe('~/security_configuration/components/app', () => {
it('renders right amount of feature cards for given props with correct props', () => {
const cards = findFeatureCards();
- expect(cards).toHaveLength(2);
+ expect(cards).toHaveLength(1);
expect(cards.at(0).props()).toEqual({ feature: securityFeaturesMock[0] });
- expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] });
});
it('renders a basic description', () => {
@@ -137,7 +130,6 @@ describe('~/security_configuration/components/app', () => {
});
it('should not show configuration History Link when gitlabCiPresent & gitlabCiHistoryPath are not defined', () => {
- expect(findComplianceViewHistoryLink().exists()).toBe(false);
expect(findSecurityViewHistoryLink().exists()).toBe(false);
});
});
@@ -158,7 +150,7 @@ describe('~/security_configuration/components/app', () => {
it('should show Alert with error Message', async () => {
expect(findManageViaMRErrorAlert().exists()).toBe(false);
- findFeatureCards().at(1).vm.$emit('error', errorMessage);
+ findFeatureCards().at(0).vm.$emit('error', errorMessage);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
@@ -166,7 +158,7 @@ describe('~/security_configuration/components/app', () => {
});
it('should hide Alert when it is dismissed', async () => {
- findFeatureCards().at(1).vm.$emit('error', errorMessage);
+ findFeatureCards().at(0).vm.$emit('error', errorMessage);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
@@ -257,7 +249,6 @@ describe('~/security_configuration/components/app', () => {
createComponent({
augmentedSecurityFeatures: securityFeaturesMock,
- augmentedComplianceFeatures: complianceFeaturesMock,
autoDevopsEnabled: true,
});
@@ -285,24 +276,6 @@ describe('~/security_configuration/components/app', () => {
latestPipelinePath: 'test/path',
});
});
-
- it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
- const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security');
-
- expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText(
- i18n.latestPipelineDescription,
- );
- expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path');
- });
-
- it('should show latest pipeline info on the compliance tab with correct link when latestPipelinePath is defined', () => {
- const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance');
-
- expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText(
- i18n.latestPipelineDescription,
- );
- expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path');
- });
});
describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
@@ -314,10 +287,8 @@ describe('~/security_configuration/components/app', () => {
});
it('should show configuration History Link', () => {
- expect(findComplianceViewHistoryLink().exists()).toBe(true);
expect(findSecurityViewHistoryLink().exists()).toBe(true);
- expect(findComplianceViewHistoryLink().attributes('href')).toBe('test/historyPath');
expect(findSecurityViewHistoryLink().attributes('href')).toBe('test/historyPath');
});
});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index 24ad8024b01..3d4f01d0da1 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -4,14 +4,8 @@ import {
SAST_DESCRIPTION,
SAST_HELP_PATH,
SAST_CONFIG_HELP_PATH,
- LICENSE_COMPLIANCE_NAME,
- LICENSE_COMPLIANCE_DESCRIPTION,
- LICENSE_COMPLIANCE_HELP_PATH,
} from '~/security_configuration/components/constants';
-import {
- REPORT_TYPE_LICENSE_COMPLIANCE,
- REPORT_TYPE_SAST,
-} from '~/vue_shared/security_reports/constants';
+import { REPORT_TYPE_SAST } from '~/vue_shared/security_reports/constants';
export const testProjectPath = 'foo/bar';
export const testProviderIds = [101, 102, 103];
@@ -128,16 +122,6 @@ export const securityFeaturesMock = [
},
];
-export const complianceFeaturesMock = [
- {
- name: LICENSE_COMPLIANCE_NAME,
- description: LICENSE_COMPLIANCE_DESCRIPTION,
- helpPath: LICENSE_COMPLIANCE_HELP_PATH,
- type: REPORT_TYPE_LICENSE_COMPLIANCE,
- configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
- },
-];
-
export const provideMock = {
upgradePath: '/upgrade',
autoDevopsHelpPagePath: '/autoDevopsHelpPagePath',
diff --git a/spec/frontend/security_configuration/utils_spec.js b/spec/frontend/security_configuration/utils_spec.js
index 241e69204d2..6e731e45da2 100644
--- a/spec/frontend/security_configuration/utils_spec.js
+++ b/spec/frontend/security_configuration/utils_spec.js
@@ -9,13 +9,6 @@ describe('augmentFeatures', () => {
},
];
- const mockComplianceFeatures = [
- {
- name: 'LICENSE_COMPLIANCE',
- type: 'LICENSE_COMPLIANCE',
- },
- ];
-
const mockFeaturesWithSecondary = [
{
name: 'DAST',
@@ -51,30 +44,25 @@ describe('augmentFeatures', () => {
const expectedOutputDefault = {
augmentedSecurityFeatures: mockSecurityFeatures,
- augmentedComplianceFeatures: mockComplianceFeatures,
};
const expectedOutputSecondary = {
augmentedSecurityFeatures: mockSecurityFeatures,
- augmentedComplianceFeatures: mockFeaturesWithSecondary,
};
const expectedOutputCustomFeature = {
augmentedSecurityFeatures: mockValidCustomFeature,
- augmentedComplianceFeatures: mockComplianceFeatures,
};
- describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
+ describe('returns an object with augmentedSecurityFeatures when', () => {
it('given an empty array', () => {
- expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
- expectedOutputDefault,
- );
+ expect(augmentFeatures(mockSecurityFeatures, [])).toEqual(expectedOutputDefault);
});
it('given an invalid populated array', () => {
- expect(
- augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
- ).toEqual(expectedOutputDefault);
+ expect(augmentFeatures(mockSecurityFeatures, mockInvalidCustomFeature)).toEqual(
+ expectedOutputDefault,
+ );
});
it('features have secondary key', () => {
@@ -84,21 +72,17 @@ describe('augmentFeatures', () => {
});
it('given a valid populated array', () => {
- expect(
- augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
- ).toEqual(expectedOutputCustomFeature);
+ expect(augmentFeatures(mockSecurityFeatures, mockValidCustomFeature)).toEqual(
+ expectedOutputCustomFeature,
+ );
});
});
describe('returns an object with camelcased keys', () => {
it('given a customfeature in snakecase', () => {
- expect(
- augmentFeatures(
- mockSecurityFeatures,
- mockComplianceFeatures,
- mockValidCustomFeatureSnakeCase,
- ),
- ).toEqual(expectedOutputCustomFeature);
+ expect(augmentFeatures(mockSecurityFeatures, mockValidCustomFeatureSnakeCase)).toEqual(
+ expectedOutputCustomFeature,
+ );
});
});
});
diff --git a/spec/frontend/work_items/components/work_item_actions_spec.js b/spec/frontend/work_items/components/work_item_actions_spec.js
index 6e8f6defb17..0045abe50d0 100644
--- a/spec/frontend/work_items/components/work_item_actions_spec.js
+++ b/spec/frontend/work_items/components/work_item_actions_spec.js
@@ -18,10 +18,10 @@ import updateWorkItemNotificationsMutation from '~/work_items/graphql/update_wor
import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
import convertWorkItemMutation from '~/work_items/graphql/work_item_convert.mutation.graphql';
import {
- workItemResponseFactory,
convertWorkItemMutationResponse,
projectWorkItemTypesQueryResponse,
convertWorkItemMutationErrorResponse,
+ workItemByIidResponseFactory,
} from '../mock_data';
jest.mock('~/lib/utils/common_utils');
@@ -211,45 +211,45 @@ describe('WorkItemActions component', () => {
describe('notifications action', () => {
const errorMessage = 'Failed to subscribe';
+ const id = 'gid://gitlab/WorkItem/1';
const notificationToggledOffMessage = 'Notifications turned off.';
const notificationToggledOnMessage = 'Notifications turned on.';
- const workItemQueryResponse = workItemResponseFactory({ canUpdate: true, canDelete: true });
const inputVariablesOff = {
- id: workItemQueryResponse.data.workItem.id,
+ id,
notificationsWidget: {
subscribed: false,
},
};
const inputVariablesOn = {
- id: workItemQueryResponse.data.workItem.id,
+ id,
notificationsWidget: {
subscribed: true,
},
};
- const notificationsOffExpectedResponse = workItemResponseFactory({
+ const notificationsOffExpectedResponse = workItemByIidResponseFactory({
subscribed: false,
});
const toggleNotificationsOffHandler = jest.fn().mockResolvedValue({
data: {
workItemUpdate: {
- workItem: notificationsOffExpectedResponse.data.workItem,
+ workItem: notificationsOffExpectedResponse.data.workspace.workItems.nodes[0],
errors: [],
},
},
});
- const notificationsOnExpectedResponse = workItemResponseFactory({
+ const notificationsOnExpectedResponse = workItemByIidResponseFactory({
subscribed: true,
});
const toggleNotificationsOnHandler = jest.fn().mockResolvedValue({
data: {
workItemUpdate: {
- workItem: notificationsOnExpectedResponse.data.workItem,
+ workItem: notificationsOnExpectedResponse.data.workspace.workItems.nodes[0],
errors: [],
},
},
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 af97b3680f9..1e336a928a0 100644
--- a/spec/frontend/work_items/components/work_item_assignees_spec.js
+++ b/spec/frontend/work_items/components/work_item_assignees_spec.js
@@ -8,9 +8,7 @@ import { mockTracking } from 'helpers/tracking_helper';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
-import { config } from '~/graphql_shared/issuable_client';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
-import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
import {
@@ -22,7 +20,6 @@ import {
import {
projectMembersResponseWithCurrentUser,
mockAssignees,
- workItemQueryResponse,
currentUserResponse,
currentUserNullResponse,
projectMembersResponseWithoutCurrentUser,
@@ -78,25 +75,11 @@ describe('WorkItemAssignees component', () => {
canInviteMembers = false,
canUpdate = true,
} = {}) => {
- const apolloProvider = createMockApollo(
- [
- [userSearchQuery, searchQueryHandler],
- [currentUserQuery, currentUserQueryHandler],
- [updateWorkItemMutation, updateWorkItemMutationHandler],
- ],
- {},
- {
- typePolicies: config.cacheConfig.typePolicies,
- },
- );
-
- apolloProvider.clients.defaultClient.writeQuery({
- query: workItemQuery,
- variables: {
- id: workItemId,
- },
- data: workItemQueryResponse.data,
- });
+ const apolloProvider = createMockApollo([
+ [userSearchQuery, searchQueryHandler],
+ [currentUserQuery, currentUserQueryHandler],
+ [updateWorkItemMutation, updateWorkItemMutationHandler],
+ ]);
wrapper = mountExtended(WorkItemAssignees, {
propsData: {
diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js
index 291dacfd844..630eb78d5c0 100644
--- a/spec/frontend/work_items/components/work_item_detail_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_spec.js
@@ -39,7 +39,7 @@ import updateWorkItemTaskMutation from '~/work_items/graphql/update_work_item_ta
import {
mockParent,
workItemDatesSubscriptionResponse,
- workItemByIidResponseFactory as workItemResponseFactory,
+ workItemByIidResponseFactory,
workItemTitleSubscriptionResponse,
workItemAssigneesSubscriptionResponse,
workItemMilestoneSubscriptionResponse,
@@ -52,8 +52,8 @@ describe('WorkItemDetail component', () => {
Vue.use(VueApollo);
- const workItemQueryResponse = workItemResponseFactory({ canUpdate: true, canDelete: true });
- const workItemQueryResponseWithoutParent = workItemResponseFactory({
+ const workItemQueryResponse = workItemByIidResponseFactory({ canUpdate: true, canDelete: true });
+ const workItemQueryResponseWithoutParent = workItemByIidResponseFactory({
parent: null,
canUpdate: true,
canDelete: true,
@@ -221,7 +221,7 @@ describe('WorkItemDetail component', () => {
describe('confidentiality', () => {
const errorMessage = 'Mutation failed';
- const confidentialWorkItem = workItemResponseFactory({
+ const confidentialWorkItem = workItemByIidResponseFactory({
confidential: true,
});
const workItem = confidentialWorkItem.data.workspace.workItems.nodes[0];
@@ -398,7 +398,7 @@ describe('WorkItemDetail component', () => {
describe('with parent', () => {
beforeEach(() => {
- const parentResponse = workItemResponseFactory(mockParent);
+ const parentResponse = workItemByIidResponseFactory(mockParent);
createComponent({ handler: jest.fn().mockResolvedValue(parentResponse) });
return waitForPromises();
@@ -437,7 +437,7 @@ describe('WorkItemDetail component', () => {
},
},
};
- const parentResponse = workItemResponseFactory(mockParentObjective);
+ const parentResponse = workItemByIidResponseFactory(mockParentObjective);
createComponent({ handler: jest.fn().mockResolvedValue(parentResponse) });
await waitForPromises();
@@ -492,7 +492,7 @@ describe('WorkItemDetail component', () => {
describe('when the assignees widget does not exist', () => {
it('does not call the assignees subscription', async () => {
- const response = workItemResponseFactory({ assigneesWidgetPresent: false });
+ const response = workItemByIidResponseFactory({ assigneesWidgetPresent: false });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -514,7 +514,7 @@ describe('WorkItemDetail component', () => {
describe('when the due date widget does not exist', () => {
it('does not call the dates subscription', async () => {
- const response = workItemResponseFactory({ datesWidgetPresent: false });
+ const response = workItemByIidResponseFactory({ datesWidgetPresent: false });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -537,7 +537,7 @@ describe('WorkItemDetail component', () => {
createComponent({
handler: jest
.fn()
- .mockResolvedValue(workItemResponseFactory({ assigneesWidgetPresent: false })),
+ .mockResolvedValue(workItemByIidResponseFactory({ assigneesWidgetPresent: false })),
});
await waitForPromises();
@@ -551,7 +551,7 @@ describe('WorkItemDetail component', () => {
${'renders when widget is returned from API'} | ${true} | ${true}
${'does not render when widget is not returned from API'} | ${false} | ${false}
`('$description', async ({ labelsWidgetPresent, exists }) => {
- const response = workItemResponseFactory({ labelsWidgetPresent });
+ const response = workItemByIidResponseFactory({ labelsWidgetPresent });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -567,7 +567,7 @@ describe('WorkItemDetail component', () => {
${'when widget is not returned from API'} | ${false} | ${false}
`('$description', ({ datesWidgetPresent, exists }) => {
it(`${datesWidgetPresent ? 'renders' : 'does not render'} due date component`, async () => {
- const response = workItemResponseFactory({ datesWidgetPresent });
+ const response = workItemByIidResponseFactory({ datesWidgetPresent });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -594,7 +594,7 @@ describe('WorkItemDetail component', () => {
${'renders when widget is returned from API'} | ${true} | ${true}
${'does not render when widget is not returned from API'} | ${false} | ${false}
`('$description', async ({ milestoneWidgetPresent, exists }) => {
- const response = workItemResponseFactory({ milestoneWidgetPresent });
+ const response = workItemByIidResponseFactory({ milestoneWidgetPresent });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -614,7 +614,7 @@ describe('WorkItemDetail component', () => {
describe('when the assignees widget does not exist', () => {
it('does not call the milestone subscription', async () => {
- const response = workItemResponseFactory({ milestoneWidgetPresent: false });
+ const response = workItemByIidResponseFactory({ milestoneWidgetPresent: false });
const handler = jest.fn().mockResolvedValue(response);
createComponent({ handler });
await waitForPromises();
@@ -632,6 +632,13 @@ describe('WorkItemDetail component', () => {
expect(successHandler).toHaveBeenCalledWith({ fullPath: 'group/project', iid: '1' });
});
+ it('skips the work item query when there is no workItemIid', async () => {
+ createComponent({ workItemIid: null });
+ await waitForPromises();
+
+ expect(successHandler).not.toHaveBeenCalled();
+ });
+
it('calls the work item query when isModal=true', async () => {
createComponent({ isModal: true });
await waitForPromises();
@@ -648,7 +655,7 @@ describe('WorkItemDetail component', () => {
});
describe('work item has children', () => {
- const objectiveWorkItem = workItemResponseFactory({
+ const objectiveWorkItem = workItemByIidResponseFactory({
workItemType: objectiveType,
confidential: true,
});
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index 2ab31908577..1c319844af3 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -684,87 +684,6 @@ export const createWorkItemMutationErrorResponse = {
},
};
-export const createWorkItemFromTaskMutationResponse = {
- data: {
- workItemCreateFromTask: {
- __typename: 'WorkItemCreateFromTaskPayload',
- errors: [],
- workItem: {
- __typename: 'WorkItem',
- description: 'New description',
- id: 'gid://gitlab/WorkItem/1',
- iid: '1',
- title: 'Updated title',
- state: 'OPEN',
- confidential: false,
- createdAt: '2022-08-03T12:41:54Z',
- closedAt: null,
- project: {
- __typename: 'Project',
- id: '1',
- fullPath: 'test-project-path',
- archived: false,
- },
- workItemType: {
- __typename: 'WorkItemType',
- id: 'gid://gitlab/WorkItems::Type/5',
- name: 'Task',
- iconName: 'issue-type-task',
- },
- userPermissions: {
- deleteWorkItem: false,
- updateWorkItem: false,
- setWorkItemMetadata: false,
- __typename: 'WorkItemPermissions',
- },
- widgets: [
- {
- __typename: 'WorkItemWidgetDescription',
- type: 'DESCRIPTION',
- description: 'New description',
- descriptionHtml: '<p>New description</p>',
- lastEditedAt: '2022-09-21T06:18:42Z',
- lastEditedBy: {
- name: 'Administrator',
- webPath: '/root',
- },
- },
- ],
- },
- newWorkItem: {
- __typename: 'WorkItem',
- id: 'gid://gitlab/WorkItem/1000000',
- iid: '100',
- title: 'Updated title',
- state: 'OPEN',
- createdAt: '2022-08-03T12:41:54Z',
- closedAt: null,
- description: '',
- confidential: false,
- project: {
- __typename: 'Project',
- id: '1',
- fullPath: 'test-project-path',
- archived: false,
- },
- workItemType: {
- __typename: 'WorkItemType',
- id: 'gid://gitlab/WorkItems::Type/5',
- name: 'Task',
- iconName: 'issue-type-task',
- },
- userPermissions: {
- deleteWorkItem: false,
- updateWorkItem: false,
- setWorkItemMetadata: false,
- __typename: 'WorkItemPermissions',
- },
- widgets: [],
- },
- },
- },
-};
-
export const deleteWorkItemResponse = {
data: { workItemDelete: { errors: [], __typename: 'WorkItemDeletePayload' } },
};
@@ -1831,18 +1750,6 @@ export const projectMilestonesResponseWithNoMilestones = {
},
};
-export const projectWorkItemResponse = {
- data: {
- workspace: {
- id: 'gid://gitlab/Project/1',
- workItems: {
- nodes: [workItemQueryResponse.data.workItem],
- },
- __typename: 'Project',
- },
- },
-};
-
export const mockWorkItemNotesResponse = {
data: {
workItem: {
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
index 86e890ea809..b5d54a7c319 100644
--- a/spec/frontend/work_items/router_spec.js
+++ b/spec/frontend/work_items/router_spec.js
@@ -6,7 +6,7 @@ import {
currentUserResponse,
workItemAssigneesSubscriptionResponse,
workItemDatesSubscriptionResponse,
- workItemByIidResponseFactory as workItemResponseFactory,
+ workItemByIidResponseFactory,
workItemTitleSubscriptionResponse,
workItemLabelsSubscriptionResponse,
workItemMilestoneSubscriptionResponse,
@@ -32,7 +32,7 @@ describe('Work items router', () => {
Vue.use(VueApollo);
- const workItemQueryHandler = jest.fn().mockResolvedValue(workItemResponseFactory());
+ const workItemQueryHandler = jest.fn().mockResolvedValue(workItemByIidResponseFactory());
const currentUserQueryHandler = jest.fn().mockResolvedValue(currentUserResponse);
const datesSubscriptionHandler = jest.fn().mockResolvedValue(workItemDatesSubscriptionResponse);
const titleSubscriptionHandler = jest.fn().mockResolvedValue(workItemTitleSubscriptionResponse);
diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb
index b8290fa2337..5a46a20ce1a 100644
--- a/spec/helpers/sessions_helper_spec.rb
+++ b/spec/helpers/sessions_helper_spec.rb
@@ -87,4 +87,24 @@ RSpec.describe SessionsHelper do
expect(subject).to eq('ma**@e******.com')
end
end
+
+ describe '#remember_me_enabled?' do
+ subject { helper.remember_me_enabled? }
+
+ context 'when application setting is enabled' do
+ before do
+ stub_application_setting(remember_me_enabled: true)
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when application setting is disabled' do
+ before do
+ stub_application_setting(remember_me_enabled: false)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index a35c9c5e526..e88c89c74dc 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -639,8 +639,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures, feature_category: :servic
create(:alert_management_alert, project: project, created_at: n.days.ago)
end
- stub_application_setting(self_monitoring_project: project)
-
for_defined_days_back do
create(:product_analytics_event, project: project, se_category: 'epics', se_action: 'promote')
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 9f292b0a294..e0bfe41a3ae 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -27,12 +27,6 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
describe 'associations' do
it do
- is_expected.to belong_to(:self_monitoring_project).class_name('Project')
- .with_foreign_key(:instance_administration_project_id)
- .inverse_of(:application_setting)
- end
-
- it do
is_expected.to belong_to(:instance_group).class_name('Group')
.with_foreign_key(:instance_administrators_group_id)
.inverse_of(:application_setting)
diff --git a/spec/models/integrations/prometheus_spec.rb b/spec/models/integrations/prometheus_spec.rb
index aa248abd3bb..a533079f906 100644
--- a/spec/models/integrations/prometheus_spec.rb
+++ b/spec/models/integrations/prometheus_spec.rb
@@ -90,37 +90,6 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching,
end
end
end
-
- context 'with self-monitoring project and internal Prometheus' do
- before do
- integration.api_url = 'http://localhost:9090'
-
- stub_application_setting(self_monitoring_project_id: project.id)
- stub_config(prometheus: { enable: true, server_address: 'localhost:9090' })
- end
-
- it 'allows self-monitoring project to connect to internal Prometheus' do
- aggregate_failures do
- ['127.0.0.1', '192.168.2.3'].each do |url|
- allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([Addrinfo.tcp(url, 80)])
-
- expect(integration.can_query?).to be true
- end
- end
- end
-
- it 'does not allow self-monitoring project to connect to other local URLs' do
- integration.api_url = 'http://localhost:8000'
-
- aggregate_failures do
- ['127.0.0.1', '192.168.2.3'].each do |url|
- allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([Addrinfo.tcp(url, 80)])
-
- expect(integration.can_query?).to be false
- end
- end
- end
- end
end
end
@@ -218,23 +187,6 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching,
it 'blocks local requests' do
expect(integration.prometheus_client).to be_nil
end
-
- context 'with self-monitoring project and internal Prometheus URL' do
- before do
- stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
- stub_application_setting(self_monitoring_project_id: project.id)
-
- stub_config(prometheus: {
- enable: true,
- server_address: api_url
- })
- end
-
- it 'allows local requests' do
- expect(integration.prometheus_client).not_to be_nil
- expect { integration.prometheus_client.ping }.not_to raise_error
- end
- end
end
context 'behind IAP' do
diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb
new file mode 100644
index 00000000000..9966a7132ce
--- /dev/null
+++ b/spec/models/organization_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# rubocop: disable Lint/EmptyBlock
+# rubocop: disable RSpec/EmptyExampleGroup
+RSpec.describe Organization, type: :model, feature_category: :cell do
+end
+# rubocop: enable RSpec/EmptyExampleGroup
+# rubocop: enable Lint/EmptyBlock
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index f25ff0884b9..b5b7a283e39 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -7551,24 +7551,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
end
end
- describe '#self_monitoring?' do
- let_it_be(:project) { create(:project) }
-
- subject { project.self_monitoring? }
-
- context 'when the project is instance self-monitoring' do
- before do
- stub_application_setting(self_monitoring_project_id: project.id)
- end
-
- it { is_expected.to be true }
- end
-
- context 'when the project is not self-monitoring' do
- it { is_expected.to be false }
- end
- end
-
describe '#add_export_job' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 60583bc351d..f1d3b17fd6f 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2174,6 +2174,20 @@ RSpec.describe User, feature_category: :user_profile do
end
end
+ describe '#sign_in_with_codes_allowed?' do
+ let_it_be(:user) { create(:user, :two_factor_via_webauthn) }
+
+ context 'when `webauthn_without_totp` disabled' do
+ before do
+ stub_feature_flags(webauthn_without_totp: false)
+ end
+
+ it { expect(user.sign_in_with_codes_allowed?).to eq(false) }
+ end
+
+ it { expect(user.sign_in_with_codes_allowed?).to eq(true) }
+ end
+
describe '#two_factor_otp_enabled?' do
let_it_be(:user) { create(:user) }
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 2b956bec469..48f59ba596b 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -463,16 +463,26 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do
end
context 'subresources' do
- let(:user) { create(:user) }
- let(:member_user) { create(:user) }
+ let_it_be_with_reload(:user) { create(:user) }
+ let_it_be_with_reload(:member_user) { create(:user) }
+
+ let_it_be_with_reload(:group) { create(:group, :public) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: group) }
+ let_it_be(:private_subgroup) { create(:group, :private, parent: group, name: 'private_subgroup') }
+ let_it_be(:private_subgroup_with_direct_membership) { create(:group, :private, parent: group) }
+ let_it_be_with_reload(:subsubgroup) { create(:group, parent: subgroup) }
+
+ let_it_be_with_reload(:group_project) { create(:project, :public, group: group) }
+ let_it_be_with_reload(:control_project) { create(:project, :private, group: subsubgroup) }
+ let_it_be_with_reload(:subsubproject) { create(:project, :public, group: subsubgroup) }
- let(:group) { create(:group, :public) }
- let(:subgroup) { create(:group, parent: group) }
- let(:subsubgroup) { create(:group, parent: subgroup) }
- let(:subsubproject) { create(:project, group: subsubgroup) }
+ let_it_be(:private_subgroup_project) do
+ create(:project, :private, group: private_subgroup, name: 'private_subgroup_project')
+ end
- let(:group_project) { create(:project, :public, group: group) }
- let(:control_project) { create(:project, group: subsubgroup) }
+ let_it_be(:private_subgroup_with_direct_membership_project) do
+ create(:project, :private, group: private_subgroup_with_direct_membership, name: 'private_subgroup_project')
+ end
context 'with memberships' do
before do
@@ -481,14 +491,68 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do
subsubproject.add_developer(member_user)
group_project.add_developer(member_user)
control_project.add_maintainer(user)
+ private_subgroup_with_direct_membership.add_developer(member_user)
group.add_owner(user)
@group_member = create(:group_member, :developer, group: group, user: member_user)
end
+ let_it_be(:todo_in_public_group_project) do
+ create(:todo, :pending,
+ project: group_project,
+ user: member_user,
+ target: create(:issue, project: group_project)
+ )
+ end
+
+ let_it_be(:mr_in_public_group_project) do
+ create(:merge_request, source_project: group_project, assignees: [member_user])
+ end
+
+ let_it_be(:todo_in_private_subgroup_project) do
+ create(:todo, :pending,
+ project: private_subgroup_project,
+ user: member_user,
+ target: create(:issue, project: private_subgroup_project)
+ )
+ end
+
+ let_it_be(:mr_in_private_subgroup_project) do
+ create(:merge_request, source_project: private_subgroup_project, assignees: [member_user])
+ end
+
+ let_it_be(:todo_in_public_subsubgroup_project) do
+ create(:todo, :pending,
+ project: subsubproject,
+ user: member_user,
+ target: create(:issue, project: subsubproject)
+ )
+ end
+
+ let_it_be(:mr_in_public_subsubgroup_project) do
+ create(:merge_request, source_project: subsubproject, assignees: [member_user])
+ end
+
+ let_it_be(:todo_in_private_subgroup_with_direct_membership_project) do
+ create(:todo, :pending,
+ project: private_subgroup_with_direct_membership_project,
+ user: member_user,
+ target: create(:issue, project: private_subgroup_with_direct_membership_project)
+ )
+ end
+
+ let_it_be(:mr_in_private_subgroup_with_direct_membership_project) do
+ create(:merge_request,
+ source_project: private_subgroup_with_direct_membership_project,
+ assignees: [member_user]
+ )
+ end
+
context 'with skipping of subresources' do
+ subject(:execute_service) { described_class.new(user).execute(@group_member, skip_subresources: true) }
+
before do
- described_class.new(user).execute(@group_member, skip_subresources: true)
+ execute_service
end
it 'removes the group membership' do
@@ -514,11 +578,35 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do
it 'does not remove the user from the control project' do
expect(control_project.members.map(&:user)).to include(user)
end
+
+ context 'todos', :sidekiq_inline do
+ it 'removes todos for which the user no longer has access' do
+ expect(member_user.todos).to include(
+ todo_in_public_group_project,
+ todo_in_public_subsubgroup_project,
+ todo_in_private_subgroup_with_direct_membership_project
+ )
+
+ expect(member_user.todos).not_to include(todo_in_private_subgroup_project)
+ end
+ end
+
+ context 'issuables', :sidekiq_inline do
+ subject(:execute_service) do
+ described_class.new(user).execute(@group_member, skip_subresources: true, unassign_issuables: true)
+ end
+
+ it 'removes assigned issuables, even in subresources' do
+ expect(member_user.assigned_merge_requests).to be_empty
+ end
+ end
end
context 'without skipping of subresources' do
+ subject(:execute_service) { described_class.new(user).execute(@group_member, skip_subresources: false) }
+
before do
- described_class.new(user).execute(@group_member, skip_subresources: false)
+ execute_service
end
it 'removes the project membership' do
@@ -544,6 +632,30 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do
it 'does not remove the user from the control project' do
expect(control_project.members.map(&:user)).to include(user)
end
+
+ context 'todos', :sidekiq_inline do
+ it 'removes todos for which the user no longer has access' do
+ expect(member_user.todos).to include(
+ todo_in_public_group_project,
+ todo_in_public_subsubgroup_project
+ )
+
+ expect(member_user.todos).not_to include(
+ todo_in_private_subgroup_project,
+ todo_in_private_subgroup_with_direct_membership_project
+ )
+ end
+ end
+
+ context 'issuables', :sidekiq_inline do
+ subject(:execute_service) do
+ described_class.new(user).execute(@group_member, skip_subresources: false, unassign_issuables: true)
+ end
+
+ it 'removes assigned issuables' do
+ expect(member_user.assigned_merge_requests).to be_empty
+ end
+ end
end
end
@@ -626,4 +738,13 @@ RSpec.describe Members::DestroyService, feature_category: :subgroups do
expect(project.members.not_accepted_invitations_by_user(member_user)).to be_empty
end
end
+
+ describe '#mark_as_recursive_call' do
+ it 'marks the instance as recursive' do
+ service = described_class.new(current_user)
+ service.mark_as_recursive_call
+
+ expect(service.send(:recursive_call?)).to eq(true)
+ end
+ end
end
diff --git a/spec/support/helpers/user_login_helper.rb b/spec/support/helpers/user_login_helper.rb
index 47e858cb68c..d8368a94ad7 100644
--- a/spec/support/helpers/user_login_helper.rb
+++ b/spec/support/helpers/user_login_helper.rb
@@ -30,4 +30,20 @@ module UserLoginHelper
def ensure_one_active_pane
expect(page).to have_selector('.tab-pane.active', count: 1)
end
+
+ def ensure_remember_me_in_tab(tab_name)
+ find_link(tab_name).click
+
+ within '.tab-pane.active' do
+ expect(page).to have_content _('Remember me')
+ end
+ end
+
+ def ensure_remember_me_not_in_tab(tab_name)
+ find_link(tab_name).click
+
+ within '.tab-pane.active' do
+ expect(page).not_to have_content _('Remember me')
+ end
+ end
end
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index fb45bc0864d..c2cc6d05630 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -961,19 +961,17 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
using RSpec::Parameterized::TableSyntax
let(:task) { 'gitlab:db:active' }
- let(:self_monitoring) { double('self_monitoring') }
- where(:needs_migration, :self_monitoring_project, :project_count, :exit_status, :exit_code) do
- true | nil | nil | 1 | false
- false | :self_monitoring | 1 | 1 | false
- false | nil | 0 | 1 | false
- false | :self_monitoring | 2 | 0 | true
+ where(:needs_migration, :project_count, :exit_status, :exit_code) do
+ true | nil | 1 | false
+ false | 1 | 0 | true
+ false | 0 | 1 | false
+ false | 2 | 0 | true
end
with_them do
it 'exits 0 or 1 depending on user modifications to the database' do
allow_any_instance_of(ActiveRecord::MigrationContext).to receive(:needs_migration?).and_return(needs_migration)
- allow_any_instance_of(ApplicationSetting).to receive(:self_monitoring_project).and_return(self_monitoring_project)
allow(Project).to receive(:count).and_return(project_count)
expect { run_rake_task(task) }.to raise_error do |error|