summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb8
-rw-r--r--spec/features/groups/members/manage_members_spec.rb54
-rw-r--r--spec/features/one_trust_spec.rb23
-rw-r--r--spec/frontend/header_search/components/app_spec.js72
-rw-r--r--spec/frontend/header_search/components/header_search_autocomplete_items_spec.js14
-rw-r--r--spec/frontend/header_search/components/header_search_default_items_spec.js14
-rw-r--r--spec/frontend/header_search/components/header_search_scoped_items_spec.js23
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js80
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js11
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js60
-rw-r--r--spec/helpers/invite_members_helper_spec.rb54
-rw-r--r--spec/requests/api/invitations_spec.rb14
-rw-r--r--spec/requests/api/members_spec.rb27
-rw-r--r--spec/services/ci/play_build_service_spec.rb17
-rw-r--r--spec/services/members/create_service_spec.rb70
-rw-r--r--spec/support/helpers/features/invite_members_modal_helper.rb10
-rw-r--r--spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb10
17 files changed, 233 insertions, 328 deletions
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index b5cd14154a3..4a6e745cd63 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -90,6 +90,14 @@ RSpec.describe Repositories::GitHttpController do
end
end
end
+
+ context 'when the user is a deploy token' do
+ it_behaves_like Repositories::GitHttpController do
+ let(:container) { project }
+ let(:user) { create(:deploy_token, :project, projects: [project]) }
+ let(:access_checker_class) { Gitlab::GitAccess }
+ end
+ end
end
context 'when repository container is a project wiki' do
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 1cae7cdeb16..0ce50107e54 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -85,33 +85,6 @@ RSpec.describe 'Groups > Members > Manage members' do
property: 'existing_user',
user: user1
)
- expect_no_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus'
- )
- end
-
- it 'adds a user to group with area_of_focus', :js, :snowplow, :aggregate_failures do
- stub_experiments(member_areas_of_focus: :candidate)
- group.add_owner(user1)
-
- visit group_group_members_path(group)
-
- invite_member(user2.name, role: 'Reporter', area_of_focus: true)
- wait_for_requests
-
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Contribute to the codebase',
- property: group.members.last.id.to_s
- )
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Collaborate on open issues and merge requests',
- property: group.members.last.id.to_s
- )
end
it 'do not disclose email addresses', :js do
@@ -221,36 +194,9 @@ RSpec.describe 'Groups > Members > Manage members' do
property: 'net_new_user',
user: user1
)
- expect_no_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus'
- )
end
end
- it 'invite user to group with area_of_focus', :js, :snowplow, :aggregate_failures do
- stub_experiments(member_areas_of_focus: :candidate)
- group.add_owner(user1)
-
- visit group_group_members_path(group)
-
- invite_member('test@example.com', role: 'Reporter', area_of_focus: true)
- wait_for_requests
-
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Contribute to the codebase',
- property: group.members.last.id.to_s
- )
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Collaborate on open issues and merge requests',
- property: group.members.last.id.to_s
- )
- end
-
context 'when user is a guest' do
before do
group.add_guest(user1)
diff --git a/spec/features/one_trust_spec.rb b/spec/features/one_trust_spec.rb
new file mode 100644
index 00000000000..0ed08e8b99b
--- /dev/null
+++ b/spec/features/one_trust_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'OneTrust' do
+ context 'almost there page' do
+ context 'when OneTrust is enabled' do
+ let_it_be(:onetrust_url) { 'https://*.onetrust.com' }
+ let_it_be(:one_trust_id) { SecureRandom.uuid }
+
+ before do
+ stub_config(extra: { one_trust_id: one_trust_id })
+ stub_feature_flags(ecomm_instrumentation: true)
+ visit users_almost_there_path
+ end
+
+ it 'has the OneTrust CSP settings', :aggregate_failures do
+ expect(response_headers['Content-Security-Policy']).to include("#{onetrust_url}")
+ expect(page.html).to include("https://cdn.cookielaw.org/consent/#{one_trust_id}/OtAutoBlock.js")
+ end
+ end
+ end
+end
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
index 7ecbef8af4b..194846c410a 100644
--- a/spec/frontend/header_search/components/app_spec.js
+++ b/spec/frontend/header_search/components/app_spec.js
@@ -6,6 +6,7 @@ import HeaderSearchApp from '~/header_search/components/app.vue';
import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
import HeaderSearchDefaultItems from '~/header_search/components/header_search_default_items.vue';
import HeaderSearchScopedItems from '~/header_search/components/header_search_scoped_items.vue';
+import { SEARCH_INPUT_DESCRIPTION, SEARCH_RESULTS_DESCRIPTION } from '~/header_search/constants';
import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
import { ENTER_KEY } from '~/lib/utils/keys';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -14,6 +15,7 @@ import {
MOCK_SEARCH_QUERY,
MOCK_USERNAME,
MOCK_DEFAULT_SEARCH_OPTIONS,
+ MOCK_SCOPED_SEARCH_OPTIONS,
} from '../mock_data';
Vue.use(Vuex);
@@ -59,11 +61,26 @@ describe('HeaderSearchApp', () => {
const findHeaderSearchAutocompleteItems = () =>
wrapper.findComponent(HeaderSearchAutocompleteItems);
const findDropdownKeyboardNavigation = () => wrapper.findComponent(DropdownKeyboardNavigation);
+ const findSearchInputDescription = () => wrapper.find(`#${SEARCH_INPUT_DESCRIPTION}`);
+ const findSearchResultsDescription = () => wrapper.findByTestId(SEARCH_RESULTS_DESCRIPTION);
describe('template', () => {
- it('always renders Header Search Input', () => {
- createComponent();
- expect(findHeaderSearchInput().exists()).toBe(true);
+ describe('always renders', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('Header Search Input', () => {
+ expect(findHeaderSearchInput().exists()).toBe(true);
+ });
+
+ it('Search Input Description', () => {
+ expect(findSearchInputDescription().exists()).toBe(true);
+ });
+
+ it('Search Results Description', () => {
+ expect(findSearchResultsDescription().exists()).toBe(true);
+ });
});
describe.each`
@@ -77,7 +94,7 @@ describe('HeaderSearchApp', () => {
beforeEach(() => {
window.gon.current_username = username;
createComponent();
- wrapper.setData({ showDropdown });
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
});
it(`should${showSearchDropdown ? '' : ' not'} render`, () => {
@@ -123,6 +140,53 @@ describe('HeaderSearchApp', () => {
});
},
);
+
+ describe.each`
+ username | showDropdown | expectedDesc
+ ${null} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown}
+ ${null} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown}
+ ${MOCK_USERNAME} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown}
+ ${MOCK_USERNAME} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown}
+ `('Search Input Description', ({ username, showDropdown, expectedDesc }) => {
+ describe(`current_username is ${username} and showDropdown is ${showDropdown}`, () => {
+ beforeEach(() => {
+ window.gon.current_username = username;
+ createComponent();
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
+ });
+
+ it(`sets description to ${expectedDesc}`, () => {
+ expect(findSearchInputDescription().text()).toBe(expectedDesc);
+ });
+ });
+ });
+
+ describe.each`
+ username | showDropdown | search | loading | searchOptions | expectedDesc
+ ${null} | ${true} | ${''} | ${false} | ${[]} | ${''}
+ ${MOCK_USERNAME} | ${false} | ${''} | ${false} | ${[]} | ${''}
+ ${MOCK_USERNAME} | ${true} | ${''} | ${false} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
+ ${MOCK_USERNAME} | ${true} | ${''} | ${true} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
+ ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${false} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${`Results updated. ${MOCK_SCOPED_SEARCH_OPTIONS.length} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit.`}
+ ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${true} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${HeaderSearchApp.i18n.searchResultsLoading}
+ `(
+ 'Search Results Description',
+ ({ username, showDropdown, search, loading, searchOptions, expectedDesc }) => {
+ describe(`search is ${search}, loading is ${loading}, and showSearchDropdown is ${
+ Boolean(username) && showDropdown
+ }`, () => {
+ beforeEach(() => {
+ window.gon.current_username = username;
+ createComponent({ search, loading }, { searchOptions: () => searchOptions });
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
+ });
+
+ it(`sets description to ${expectedDesc}`, () => {
+ expect(findSearchResultsDescription().text()).toBe(expectedDesc);
+ });
+ });
+ },
+ );
});
describe('events', () => {
diff --git a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
index ecfaa8e9443..bec0cbc8a5c 100644
--- a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
@@ -110,11 +110,11 @@ describe('HeaderSearchAutocompleteItems', () => {
});
describe.each`
- currentFocusedOption | isFocused
- ${null} | ${false}
- ${{ html_id: 'not-a-match' }} | ${false}
- ${MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0]} | ${true}
- `('isOptionFocused', ({ currentFocusedOption, isFocused }) => {
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
beforeEach(() => {
createComponent({}, {}, { currentFocusedOption });
@@ -123,6 +123,10 @@ describe('HeaderSearchAutocompleteItems', () => {
it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
});
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
});
});
});
diff --git a/spec/frontend/header_search/components/header_search_default_items_spec.js b/spec/frontend/header_search/components/header_search_default_items_spec.js
index afad9b5b138..abcacc487df 100644
--- a/spec/frontend/header_search/components/header_search_default_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_default_items_spec.js
@@ -83,11 +83,11 @@ describe('HeaderSearchDefaultItems', () => {
});
describe.each`
- currentFocusedOption | isFocused
- ${null} | ${false}
- ${{ html_id: 'not-a-match' }} | ${false}
- ${MOCK_DEFAULT_SEARCH_OPTIONS[0]} | ${true}
- `('isOptionFocused', ({ currentFocusedOption, isFocused }) => {
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_DEFAULT_SEARCH_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
beforeEach(() => {
createComponent({}, { currentFocusedOption });
@@ -96,6 +96,10 @@ describe('HeaderSearchDefaultItems', () => {
it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
});
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
});
});
});
diff --git a/spec/frontend/header_search/components/header_search_scoped_items_spec.js b/spec/frontend/header_search/components/header_search_scoped_items_spec.js
index 2fdd03fdae3..a65b4d8b813 100644
--- a/spec/frontend/header_search/components/header_search_scoped_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_scoped_items_spec.js
@@ -37,6 +37,8 @@ describe('HeaderSearchScopedItems', () => {
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findFirstDropdownItem = () => findDropdownItems().at(0);
const findDropdownItemTitles = () => findDropdownItems().wrappers.map((w) => trimText(w.text()));
+ const findDropdownItemAriaLabels = () =>
+ findDropdownItems().wrappers.map((w) => trimText(w.attributes('aria-label')));
const findDropdownItemLinks = () => findDropdownItems().wrappers.map((w) => w.attributes('href'));
describe('template', () => {
@@ -56,6 +58,13 @@ describe('HeaderSearchScopedItems', () => {
expect(findDropdownItemTitles()).toStrictEqual(expectedTitles);
});
+ it('renders aria-labels correctly', () => {
+ const expectedLabels = MOCK_SCOPED_SEARCH_OPTIONS.map((o) =>
+ trimText(`${MOCK_SEARCH} ${o.description} ${o.scope || ''}`),
+ );
+ expect(findDropdownItemAriaLabels()).toStrictEqual(expectedLabels);
+ });
+
it('renders links correctly', () => {
const expectedLinks = MOCK_SCOPED_SEARCH_OPTIONS.map((o) => o.url);
expect(findDropdownItemLinks()).toStrictEqual(expectedLinks);
@@ -63,11 +72,11 @@ describe('HeaderSearchScopedItems', () => {
});
describe.each`
- currentFocusedOption | isFocused
- ${null} | ${false}
- ${{ html_id: 'not-a-match' }} | ${false}
- ${MOCK_SCOPED_SEARCH_OPTIONS[0]} | ${true}
- `('isOptionFocused', ({ currentFocusedOption, isFocused }) => {
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_SCOPED_SEARCH_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
beforeEach(() => {
createComponent({}, { currentFocusedOption });
@@ -76,6 +85,10 @@ describe('HeaderSearchScopedItems', () => {
it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
});
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
});
});
});
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 24df424b40b..f3cad3fc066 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -6,7 +6,6 @@ import {
GlSprintf,
GlLink,
GlModal,
- GlFormCheckboxGroup,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { stubComponent } from 'helpers/stub_component';
@@ -19,7 +18,6 @@ import ModalConfetti from '~/invite_members/components/confetti.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import {
INVITE_MEMBERS_IN_COMMENT,
- MEMBER_AREAS_OF_FOCUS,
INVITE_MEMBERS_FOR_TASK,
CANCEL_BUTTON_TEXT,
INVITE_BUTTON_TEXT,
@@ -52,12 +50,7 @@ const inviteeType = 'members';
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = 10;
const inviteSource = 'unknown';
-const noSelectionAreasOfFocus = ['no_selection'];
const helpLink = 'https://example.com';
-const areasOfFocusOptions = [
- { text: 'area1', value: 'area1' },
- { text: 'area2', value: 'area2' },
-];
const tasksToBeDoneOptions = [
{ text: 'First task', value: 'first' },
{ text: 'Second task', value: 'second' },
@@ -96,9 +89,7 @@ const createComponent = (data = {}, props = {}) => {
isProject,
inviteeType,
accessLevels,
- areasOfFocusOptions,
defaultAccessLevel,
- noSelectionAreasOfFocus,
tasksToBeDoneOptions,
projects,
helpLink,
@@ -164,7 +155,6 @@ describe('InviteMembersModal', () => {
const membersFormGroupInvalidFeedback = () => findMembersFormGroup().props('invalidFeedback');
const membersFormGroupDescription = () => findMembersFormGroup().props('description');
const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect);
- const findAreaofFocusCheckBoxGroup = () => wrapper.findComponent(GlFormCheckboxGroup);
const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done');
const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks');
const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select');
@@ -215,21 +205,6 @@ describe('InviteMembersModal', () => {
});
});
- describe('rendering the areas_of_focus', () => {
- it('renders the areas_of_focus checkboxes', () => {
- createComponent();
-
- expect(findAreaofFocusCheckBoxGroup().props('options')).toBe(areasOfFocusOptions);
- expect(findAreaofFocusCheckBoxGroup().exists()).toBe(true);
- });
-
- it('does not render the areas_of_focus checkboxes', () => {
- createComponent({}, { areasOfFocusOptions: [] });
-
- expect(findAreaofFocusCheckBoxGroup().exists()).toBe(false);
- });
- });
-
describe('rendering the tasks to be done', () => {
const setupComponent = (
extraData = {},
@@ -442,20 +417,6 @@ describe('InviteMembersModal', () => {
"The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.";
const expectedSyntaxError = 'email contains an invalid email address';
- it('calls the API with the expected focus data when an areas_of_focus checkbox is clicked', () => {
- const spy = jest.spyOn(Api, 'addGroupMembersByUserId');
- const expectedFocus = [areasOfFocusOptions[0].value];
- createComponent({ newUsersToInvite: [user1] });
-
- findAreaofFocusCheckBoxGroup().vm.$emit('input', expectedFocus);
- clickInviteButton();
-
- expect(spy).toHaveBeenCalledWith(
- user1.id.toString(),
- expect.objectContaining({ areas_of_focus: expectedFocus }),
- );
- });
-
describe('when inviting an existing user to group by user ID', () => {
const postData = {
user_id: '1,2',
@@ -463,7 +424,6 @@ describe('InviteMembersModal', () => {
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
- areas_of_focus: noSelectionAreasOfFocus,
tasks_to_be_done: [],
tasks_project_id: '',
};
@@ -476,16 +436,6 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
});
- it('includes the non-default selected areas of focus', () => {
- const focus = ['abc'];
- const updatedPostData = { ...postData, areas_of_focus: focus };
- wrapper.setData({ selectedAreasOfFocus: focus });
-
- clickInviteButton();
-
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, updatedPostData);
- });
-
describe('when triggered from regular mounting', () => {
beforeEach(() => {
clickInviteButton();
@@ -661,7 +611,6 @@ describe('InviteMembersModal', () => {
expires_at: undefined,
email: 'email@example.com',
invite_source: inviteSource,
- areas_of_focus: noSelectionAreasOfFocus,
tasks_to_be_done: [],
tasks_project_id: '',
format: 'json',
@@ -675,16 +624,6 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
});
- it('includes the non-default selected areas of focus', () => {
- const focus = ['abc'];
- const updatedPostData = { ...postData, areas_of_focus: focus };
- wrapper.setData({ selectedAreasOfFocus: focus });
-
- clickInviteButton();
-
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, updatedPostData);
- });
-
describe('when triggered from regular mounting', () => {
beforeEach(() => {
clickInviteButton();
@@ -792,7 +731,6 @@ describe('InviteMembersModal', () => {
access_level: defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
- areas_of_focus: noSelectionAreasOfFocus,
format: 'json',
tasks_to_be_done: [],
tasks_project_id: '',
@@ -951,30 +889,12 @@ describe('InviteMembersModal', () => {
expect(ExperimentTracking).not.toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
});
- it('tracks the view for areas_of_focus', () => {
- eventHub.$emit('openModal', { inviteeType: 'members' });
-
- expect(ExperimentTracking).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.name);
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.view);
- });
-
it('tracks the view for learn_gitlab source', () => {
eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(LEARN_GITLAB);
});
-
- it('tracks the invite for areas_of_focus', () => {
- eventHub.$emit('openModal', { inviteeType: 'members' });
-
- clickInviteButton();
-
- expect(ExperimentTracking).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.name);
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
- MEMBER_AREAS_OF_FOCUS.submit,
- );
- });
});
});
});
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 4e0ea6a9717..759844b941a 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -5,7 +5,10 @@ import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import stubChildren from 'helpers/stub_children';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import SecurityConfigurationApp, { i18n } from '~/security_configuration/components/app.vue';
+import SecurityConfigurationApp, {
+ i18n,
+ TRAINING_PROVIDERS,
+} from '~/security_configuration/components/app.vue';
import AutoDevopsAlert from '~/security_configuration/components/auto_dev_ops_alert.vue';
import AutoDevopsEnabledAlert from '~/security_configuration/components/auto_dev_ops_enabled_alert.vue';
import {
@@ -20,6 +23,7 @@ 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 UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
import {
@@ -78,6 +82,7 @@ describe('App component', () => {
const findTabs = () => wrapper.findAllComponents(GlTab);
const findByTestId = (id) => wrapper.findByTestId(id);
const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
+ const findTrainingProviderList = () => wrapper.findComponent(TrainingProviderList);
const findManageViaMRErrorAlert = () => wrapper.findByTestId('manage-via-mr-error-alert');
const findLink = ({ href, text, container = wrapper }) => {
const selector = `a[href="${href}"]`;
@@ -180,6 +185,10 @@ describe('App component', () => {
expect(findComplianceViewHistoryLink().exists()).toBe(false);
expect(findSecurityViewHistoryLink().exists()).toBe(false);
});
+
+ it('renders training provider list with correct props', () => {
+ expect(findTrainingProviderList().props('providers')).toEqual(TRAINING_PROVIDERS);
+ });
});
describe('Manage via MR Error Alert', () => {
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
new file mode 100644
index 00000000000..1169a977d44
--- /dev/null
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -0,0 +1,60 @@
+import { GlLink, GlToggle, GlCard } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
+import { TRAINING_PROVIDERS } from '~/security_configuration/components/app.vue';
+
+const DEFAULT_PROPS = {
+ providers: TRAINING_PROVIDERS,
+};
+
+describe('TrainingProviderList component', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(TrainingProviderList, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ });
+ };
+
+ const findCards = () => wrapper.findAllComponents(GlCard);
+ const findLinks = () => wrapper.findAllComponents(GlLink);
+ const findToggles = () => wrapper.findAllComponents(GlToggle);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('basic structure', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders correct amount of cards', () => {
+ expect(findCards()).toHaveLength(DEFAULT_PROPS.providers.length);
+ });
+
+ DEFAULT_PROPS.providers.forEach(({ name, description, url, isEnabled }, index) => {
+ it(`shows the name for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(name);
+ });
+
+ it(`shows the description for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(description);
+ });
+
+ it(`shows the learn more link for card ${index}`, () => {
+ expect(findLinks().at(index).attributes()).toEqual({
+ target: '_blank',
+ href: url,
+ });
+ });
+
+ it(`shows the toggle with the correct value for card ${index}`, () => {
+ expect(findToggles().at(index).props('value')).toEqual(isEnabled);
+ });
+ });
+ });
+});
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index e3db2240318..d8a97b93bc9 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -16,52 +16,14 @@ RSpec.describe InviteMembersHelper do
end
describe '#common_invite_modal_dataset' do
- context 'when member_areas_of_focus is enabled', :experiment do
- context 'with control experience' do
- before do
- stub_experiments(member_areas_of_focus: :control)
- end
-
- it 'has expected attributes' do
- attributes = {
- areas_of_focus_options: [],
- no_selection_areas_of_focus: []
- }
-
- expect(helper.common_invite_modal_dataset(project)).to include(attributes)
- end
- end
-
- context 'with candidate experience' do
- before do
- stub_experiments(member_areas_of_focus: :candidate)
- end
-
- it 'has expected attributes', :aggregate_failures do
- output = helper.common_invite_modal_dataset(project)
-
- expect(output[:no_selection_areas_of_focus]).to eq ['no_selection']
- expect(Gitlab::Json.parse(output[:areas_of_focus_options]).first['value']).to eq 'Contribute to the codebase'
- end
- end
- end
-
- context 'when member_areas_of_focus is disabled' do
- before do
- stub_feature_flags(member_areas_of_focus: false)
- end
-
- it 'has expected attributes' do
- attributes = {
- id: project.id,
- name: project.name,
- default_access_level: Gitlab::Access::GUEST,
- areas_of_focus_options: [],
- no_selection_areas_of_focus: []
- }
-
- expect(helper.common_invite_modal_dataset(project)).to include(attributes)
- end
+ it 'has expected common attributes' do
+ attributes = {
+ id: project.id,
+ name: project.name,
+ default_access_level: Gitlab::Access::GUEST
+ }
+
+ expect(helper.common_invite_modal_dataset(project)).to include(attributes)
end
context 'tasks_to_be_done' do
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index 7b17a5ed1cb..702e6ef0a2a 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -152,20 +152,6 @@ RSpec.describe API::Invitations do
end
end
- context 'with areas_of_focus', :snowplow do
- it 'tracks the areas_of_focus from params' do
- post invitations_url(source, maintainer),
- params: { email: email, access_level: Member::DEVELOPER, areas_of_focus: 'Other' }
-
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
-
context 'with tasks_to_be_done and tasks_project_id in the params' do
let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index bf5b89e72c6..02061bb8ab6 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -387,33 +387,6 @@ RSpec.describe API::Members do
end
end
- context 'with areas_of_focus considerations', :snowplow do
- let(:user_id) { stranger.id }
-
- context 'when areas_of_focus is present in params' do
- it 'tracks the areas_of_focus' do
- post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
- params: { user_id: user_id, access_level: Member::DEVELOPER, areas_of_focus: 'Other' }
-
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
-
- context 'when areas_of_focus is not present in params' do
- it 'does not track the areas_of_focus' do
- post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
- params: { user_id: user_id, access_level: Member::DEVELOPER }
-
- expect_no_snowplow_event(category: 'Members::CreateService', action: 'area_of_focus')
- end
- end
- end
-
context 'with tasks_to_be_done and tasks_project_id in the params' do
let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb
index babd601e0cf..34f77260334 100644
--- a/spec/services/ci/play_build_service_spec.rb
+++ b/spec/services/ci/play_build_service_spec.rb
@@ -79,12 +79,22 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
{ key: 'second', secret_value: 'second' }]
end
+ subject { service.execute(build, job_variables) }
+
it 'assigns the variables to the build' do
- service.execute(build, job_variables)
+ subject
expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
end
+ context 'when variables are invalid' do
+ let(:job_variables) { [{}] }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
context 'when user defined variables are restricted' do
before do
project.update!(restrict_user_defined_variables: true)
@@ -96,7 +106,7 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
end
it 'assigns the variables to the build' do
- service.execute(build, job_variables)
+ subject
expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
end
@@ -104,8 +114,7 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
context 'when user is developer' do
it 'raises an error' do
- expect { service.execute(build, job_variables) }
- .to raise_error Gitlab::Access::AccessDeniedError
+ expect { subject }.to raise_error Gitlab::Access::AccessDeniedError
end
end
end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 43493deb621..13f56fe7458 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -127,76 +127,6 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
end
end
- context 'when tracking the areas of focus', :snowplow do
- context 'when areas_of_focus is not passed' do
- it 'does not track' do
- execute_service
-
- expect_no_snowplow_event(category: described_class.name, action: 'area_of_focus')
- end
- end
-
- context 'when 1 areas_of_focus is passed' do
- let(:additional_params) { { invite_source: '_invite_source_', areas_of_focus: ['no_selection'] } }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: source.members.last.id.to_s
- )
- end
-
- context 'when passing many user ids' do
- let(:another_user) { create(:user) }
- let(:user_ids) { [member.id, another_user.id].join(',') }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- members = source.members.last(2)
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: members.first.id.to_s
- )
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: members.last.id.to_s
- )
- end
- end
- end
-
- context 'when multiple areas_of_focus are passed' do
- let(:additional_params) { { invite_source: '_invite_source_', areas_of_focus: %w[no_selection Other] } }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: source.members.last.id.to_s
- )
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
- end
-
context 'when assigning tasks to be done' do
let(:additional_params) do
{ invite_source: '_invite_source_', tasks_to_be_done: %w(ci code), tasks_project_id: source.id }
diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb
index 3502558b2c2..11040562b49 100644
--- a/spec/support/helpers/features/invite_members_modal_helper.rb
+++ b/spec/support/helpers/features/invite_members_modal_helper.rb
@@ -5,7 +5,7 @@ module Spec
module Helpers
module Features
module InviteMembersModalHelper
- def invite_member(name, role: 'Guest', expires_at: nil, area_of_focus: false)
+ def invite_member(name, role: 'Guest', expires_at: nil)
click_on 'Invite members'
page.within '[data-testid="invite-members-modal"]' do
@@ -14,7 +14,6 @@ module Spec
wait_for_requests
click_button name
choose_options(role, expires_at)
- choose_area_of_focus if area_of_focus
click_button 'Invite'
@@ -44,13 +43,6 @@ module Spec
fill_in 'YYYY-MM-DD', with: expires_at.strftime('%Y-%m-%d') if expires_at
end
-
- def choose_area_of_focus
- page.within '[data-testid="area-of-focus-checks"]' do
- check 'Contribute to the codebase'
- check 'Collaborate on open issues and merge requests'
- end
- end
end
end
end
diff --git a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
index 00a0fb7e4c5..3a7588a5cc9 100644
--- a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
@@ -50,7 +50,8 @@ RSpec.shared_examples Repositories::GitHttpController do
context 'with authorized user' do
before do
- request.headers.merge! auth_env(user.username, user.password, nil)
+ password = user.try(:password) || user.try(:token)
+ request.headers.merge! auth_env(user.username, password, nil)
end
it 'returns 200' do
@@ -71,9 +72,10 @@ RSpec.shared_examples Repositories::GitHttpController do
it 'adds user info to the logs' do
get :info_refs, params: params
- expect(log_data).to include('username' => user.username,
- 'user_id' => user.id,
- 'meta.user' => user.username)
+ user_log_data = { 'username' => user.username, 'user_id' => user.id }
+ user_log_data['meta.user'] = user.username if user.is_a?(User)
+
+ expect(log_data).to include(user_log_data)
end
end
end