summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-03 18:09:58 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-03 18:09:58 +0000
commit524639c7063131c40b848789ff541758b68c1cca (patch)
treeeef8ce631ab44dfaefe71c54d2a4d248d8fd3c69 /spec
parent4f41b713eb264096903c168375815adec96ab8ac (diff)
downloadgitlab-ce-524639c7063131c40b848789ff541758b68c1cca.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/admin/admin_settings_spec.rb33
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb12
-rw-r--r--spec/frontend/fixtures/startup_css.rb14
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js18
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js1
-rw-r--r--spec/frontend/integrations/edit/components/confirmation_modal_spec.js8
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js16
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js61
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js7
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js18
-rw-r--r--spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js9
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js10
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js19
-rw-r--r--spec/frontend/integrations/index/components/integrations_list_spec.js6
-rw-r--r--spec/frontend/nav/components/top_nav_container_view_spec.js6
-rw-r--r--spec/helpers/application_settings_helper_spec.rb20
-rw-r--r--spec/helpers/invite_members_helper_spec.rb65
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb320
-rw-r--r--spec/lib/gitlab/nav/top_nav_menu_item_spec.rb3
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb12
20 files changed, 489 insertions, 169 deletions
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 7cccac11363..c289c18126d 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe 'Admin updates settings' do
include UsageDataHelpers
let(:admin) { create(:admin) }
+ let(:dot_com?) { false }
context 'application setting :admin_mode is enabled', :request_store do
before do
+ allow(Gitlab).to receive(:com?).and_return(dot_com?)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
@@ -127,6 +129,37 @@ RSpec.describe 'Admin updates settings' do
expect(user_internal_regex['placeholder']).to eq 'Regex pattern'
end
+ context 'Dormant users' do
+ context 'when Gitlab.com' do
+ let(:dot_com?) { true }
+
+ it 'does not expose the setting' do
+ expect(page).to have_no_selector('#application_setting_deactivate_dormant_users')
+ end
+ end
+
+ context 'when not Gitlab.com' do
+ let(:dot_com?) { false }
+
+ it 'change Dormant users' do
+ expect(page).to have_unchecked_field('Deactivate dormant users after 90 days of inactivity')
+ expect(current_settings.deactivate_dormant_users).to be_falsey
+
+ page.within('.as-account-limit') do
+ check 'application_setting_deactivate_dormant_users'
+ click_button 'Save changes'
+ end
+
+ expect(page).to have_content "Application settings saved successfully"
+
+ page.refresh
+
+ expect(current_settings.deactivate_dormant_users).to be_truthy
+ expect(page).to have_checked_field('Deactivate dormant users after 90 days of inactivity')
+ end
+ end
+ end
+
context 'Change Sign-up restrictions' do
context 'Require Admin approval for new signup setting' do
it 'changes the setting', :js do
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index ffdfbb9fe81..613033373e8 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -12,6 +12,10 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
sign_in(user)
end
+ def find_new_menu_toggle
+ find('#js-onboarding-new-project-link')
+ end
+
context 'with developer user' do
before do
project.add_developer(user)
@@ -22,7 +26,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
# The navigation bar
page.within('.header-new') do
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
@@ -30,7 +34,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
expect(page).to have_link('New snippet', href: new_project_snippet_path(project))
end
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
end
# The dropdown above the tree
@@ -56,7 +60,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
visit project_path(project)
page.within('.header-new') do
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New issue')
@@ -64,7 +68,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
expect(page).not_to have_link('New snippet', href: new_project_snippet_path(project))
end
- find('.qa-new-menu-toggle').click
+ find_new_menu_toggle.click
end
expect(page).not_to have_selector('.qa-add-to-tree')
diff --git a/spec/frontend/fixtures/startup_css.rb b/spec/frontend/fixtures/startup_css.rb
index 134d29d3106..003f7b768dd 100644
--- a/spec/frontend/fixtures/startup_css.rb
+++ b/spec/frontend/fixtures/startup_css.rb
@@ -11,12 +11,13 @@ RSpec.describe 'Startup CSS fixtures', type: :controller do
before(:all) do
stub_feature_flags(combined_menu: true)
+ stub_feature_flags(sidebar_refactor: true)
clean_frontend_fixtures('startup_css/')
end
shared_examples 'startup css project fixtures' do |type|
let(:user) { create(:user, :admin) }
- let(:project) { create(:project, :public, :repository, description: 'Code and stuff', avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png'), creator: user) }
+ let(:project) { create(:project, :public, :repository, description: 'Code and stuff', creator: user) }
before do
sign_in(user)
@@ -42,6 +43,17 @@ RSpec.describe 'Startup CSS fixtures', type: :controller do
expect(response).to be_successful
end
+ it "startup_css/project-#{type}-legacy-sidebar.html" do
+ stub_feature_flags(sidebar_refactor: false)
+
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ id: project
+ }
+
+ expect(response).to be_successful
+ end
+
it "startup_css/project-#{type}-signed-out.html" do
sign_out(user)
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index 7a1026e8bfc..a94cb3e2fcc 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -21,13 +21,14 @@ const TEST_NAMESPACE = 'projects';
const TEST_VUEX_MODULE = 'frequentProjects';
const TEST_PROJECT = currentSession[TEST_NAMESPACE].project;
const TEST_STORAGE_KEY = currentSession[TEST_NAMESPACE].storageKey;
+const TEST_SEARCH_CLASS = 'test-search-class';
describe('Frequent Items App Component', () => {
let wrapper;
let mock;
let store;
- const createComponent = ({ currentItem = null } = {}) => {
+ const createComponent = (props = {}) => {
const session = currentSession[TEST_NAMESPACE];
gon.api_version = session.apiVersion;
@@ -36,7 +37,8 @@ describe('Frequent Items App Component', () => {
propsData: {
namespace: TEST_NAMESPACE,
currentUserName: session.username,
- currentItem: currentItem || session.project,
+ currentItem: session.project,
+ ...props,
},
provide: {
vuexModule: TEST_VUEX_MODULE,
@@ -88,7 +90,7 @@ describe('Frequent Items App Component', () => {
});
it('should render search input', () => {
- expect(findSearchInput().exists()).toBe(true);
+ expect(findSearchInput().classes()).toEqual(['search-input-container']);
});
it('should render loading animation', async () => {
@@ -159,6 +161,16 @@ describe('Frequent Items App Component', () => {
});
});
+ describe('with searchClass', () => {
+ beforeEach(() => {
+ createComponent({ searchClass: TEST_SEARCH_CLASS });
+ });
+
+ it('should render search input with searchClass', () => {
+ expect(findSearchInput().classes()).toEqual(['search-input-container', TEST_SEARCH_CLASS]);
+ });
+ });
+
describe('logging', () => {
it('when created, it should create a project storage entry and adds a project', () => {
createComponent();
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
index 0e56fb6454e..df7ffd19747 100644
--- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import { createStore } from '~/integrations/edit/store';
diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
index 1c126f60c37..805d3971994 100644
--- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
+++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
@@ -1,5 +1,6 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import { createStore } from '~/integrations/edit/store';
@@ -13,13 +14,10 @@ describe('ConfirmationModal', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlModal = () => wrapper.find(GlModal);
+ const findGlModal = () => wrapper.findComponent(GlModal);
describe('template', () => {
beforeEach(() => {
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index 2ebb3333c0f..8784b3c2b00 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
describe('DynamicField', () => {
@@ -24,17 +25,14 @@ describe('DynamicField', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlFormGroup = () => wrapper.find(GlFormGroup);
- const findGlFormCheckbox = () => wrapper.find(GlFormCheckbox);
- const findGlFormInput = () => wrapper.find(GlFormInput);
- const findGlFormSelect = () => wrapper.find(GlFormSelect);
- const findGlFormTextarea = () => wrapper.find(GlFormTextarea);
+ const findGlFormGroup = () => wrapper.findComponent(GlFormGroup);
+ const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findGlFormInput = () => wrapper.findComponent(GlFormInput);
+ const findGlFormSelect = () => wrapper.findComponent(GlFormSelect);
+ const findGlFormTextarea = () => wrapper.findComponent(GlFormTextarea);
describe('template', () => {
describe.each([
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index c015fd0b9e0..cbce26762b1 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import { setHTMLFixture } from 'helpers/fixtures';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
@@ -23,42 +23,37 @@ describe('IntegrationForm', () => {
initialState = {},
props = {},
} = {}) => {
- wrapper = extendedWrapper(
- shallowMount(IntegrationForm, {
- propsData: { ...props },
- store: createStore({
- customState: { ...mockIntegrationProps, ...customStateProps },
- ...initialState,
- }),
- stubs: {
- OverrideDropdown,
- ActiveCheckbox,
- ConfirmationModal,
- JiraTriggerFields,
- TriggerFields,
- },
- provide: {
- glFeatures: featureFlags,
- },
+ wrapper = shallowMountExtended(IntegrationForm, {
+ propsData: { ...props },
+ store: createStore({
+ customState: { ...mockIntegrationProps, ...customStateProps },
+ ...initialState,
}),
- );
+ stubs: {
+ OverrideDropdown,
+ ActiveCheckbox,
+ ConfirmationModal,
+ JiraTriggerFields,
+ TriggerFields,
+ },
+ provide: {
+ glFeatures: featureFlags,
+ },
+ });
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findOverrideDropdown = () => wrapper.find(OverrideDropdown);
- const findActiveCheckbox = () => wrapper.find(ActiveCheckbox);
- const findConfirmationModal = () => wrapper.find(ConfirmationModal);
- const findResetConfirmationModal = () => wrapper.find(ResetConfirmationModal);
- const findResetButton = () => wrapper.find('[data-testid="reset-button"]');
- const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields);
- const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields);
- const findTriggerFields = () => wrapper.find(TriggerFields);
+ const findOverrideDropdown = () => wrapper.findComponent(OverrideDropdown);
+ const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox);
+ const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
+ const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
+ const findResetButton = () => wrapper.findByTestId('reset-button');
+ const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
+ const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
+ const findTriggerFields = () => wrapper.findComponent(TriggerFields);
describe('template', () => {
describe('showActive is true', () => {
@@ -286,7 +281,7 @@ describe('IntegrationForm', () => {
</div>
`);
- it('renders `helpHtml`', async () => {
+ it('renders `helpHtml`', () => {
const mockHelpHtml = document.querySelector(`[data-testid="${mockTestId}"]`);
createComponent({
diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
index 9cc041490d0..eb5f7e9fe40 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
import eventHub from '~/integrations/edit/event_hub';
@@ -20,7 +21,7 @@ describe('JiraIssuesFields', () => {
defaultState: isInheriting ? {} : undefined,
});
- wrapper = mount(JiraIssuesFields, {
+ wrapper = mountExtended(JiraIssuesFields, {
propsData: { ...defaultProps, ...props },
store,
stubs: ['jira-issue-creation-vulnerabilities'],
@@ -37,7 +38,7 @@ describe('JiraIssuesFields', () => {
findEnableCheckbox().find('[type=checkbox]').attributes('disabled');
const findProjectKey = () => wrapper.findComponent(GlFormInput);
const findJiraUpgradeCta = () => wrapper.findComponent(JiraUpgradeCta);
- const findJiraForVulnerabilities = () => wrapper.find('[data-testid="jira-for-vulnerabilities"]');
+ const findJiraForVulnerabilities = () => wrapper.findByTestId('jira-for-vulnerabilities');
const setEnableCheckbox = async (isEnabled = true) =>
findEnableCheckbox().vm.$emit('input', isEnabled);
diff --git a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
index 5c04add61a1..9e01371f542 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -1,5 +1,6 @@
import { GlFormCheckbox } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
describe('JiraTriggerFields', () => {
@@ -12,7 +13,7 @@ describe('JiraTriggerFields', () => {
};
const createComponent = (props, isInheriting = false) => {
- wrapper = mount(JiraTriggerFields, {
+ wrapper = mountExtended(JiraTriggerFields, {
propsData: { ...defaultProps, ...props },
computed: {
isInheriting: () => isInheriting,
@@ -21,18 +22,15 @@ describe('JiraTriggerFields', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findCommentSettings = () => wrapper.find('[data-testid="comment-settings"]');
- const findCommentDetail = () => wrapper.find('[data-testid="comment-detail"]');
- const findCommentSettingsCheckbox = () => findCommentSettings().find(GlFormCheckbox);
+ const findCommentSettings = () => wrapper.findByTestId('comment-settings');
+ const findCommentDetail = () => wrapper.findByTestId('comment-detail');
+ const findCommentSettingsCheckbox = () => findCommentSettings().findComponent(GlFormCheckbox);
const findIssueTransitionEnabled = () =>
wrapper.find('[data-testid="issue-transition-enabled"] input[type="checkbox"]');
- const findIssueTransitionMode = () => wrapper.find('[data-testid="issue-transition-mode"]');
+ const findIssueTransitionMode = () => wrapper.findByTestId('issue-transition-mode');
const findIssueTransitionModeRadios = () =>
findIssueTransitionMode().findAll('input[type="radio"]');
const findIssueTransitionIdsField = () =>
diff --git a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
index e49a1619627..e90e9a5d2ac 100644
--- a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+
import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
describe('JiraUpgradeCta', () => {
@@ -18,13 +19,13 @@ describe('JiraUpgradeCta', () => {
it('displays the correct message for premium and lower users', () => {
createComponent({ showPremiumMessage: true });
- expect(wrapper.html()).toContain('This is a Premium feature');
- expect(wrapper.html()).toContain(contentMessage);
+ expect(wrapper.text()).toContain('This is a Premium feature');
+ expect(wrapper.text()).toContain(contentMessage);
});
it('displays the correct message for ultimate and lower users', () => {
createComponent({ showUltimateMessage: true });
- expect(wrapper.html()).toContain('This is an Ultimate feature');
- expect(wrapper.html()).toContain(contentMessage);
+ expect(wrapper.text()).toContain('This is an Ultimate feature');
+ expect(wrapper.text()).toContain(contentMessage);
});
});
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
index 592f4514e45..eb43d940f5e 100644
--- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -1,5 +1,6 @@
import { GlDropdown, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
import { createStore } from '~/integrations/edit/store';
@@ -26,14 +27,11 @@ describe('OverrideDropdown', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const findGlLink = () => wrapper.find(GlLink);
- const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlLink = () => wrapper.findComponent(GlLink);
+ const findGlDropdown = () => wrapper.findComponent(GlDropdown);
describe('template', () => {
describe('override prop is true', () => {
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index b9d16464e72..5f85c58da28 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -1,5 +1,6 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
describe('TriggerFields', () => {
@@ -10,7 +11,7 @@ describe('TriggerFields', () => {
};
const createComponent = (props, isInheriting = false) => {
- wrapper = mount(TriggerFields, {
+ wrapper = mountExtended(TriggerFields, {
propsData: { ...defaultProps, ...props },
computed: {
isInheriting: () => isInheriting,
@@ -19,21 +20,19 @@ describe('TriggerFields', () => {
};
afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
+ const findTriggerLabel = () => wrapper.findByTestId('trigger-fields-group').find('label');
const findAllGlFormGroups = () => wrapper.find('#trigger-fields').findAll(GlFormGroup);
- const findAllGlFormCheckboxes = () => wrapper.findAll(GlFormCheckbox);
- const findAllGlFormInputs = () => wrapper.findAll(GlFormInput);
+ const findAllGlFormCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox);
+ const findAllGlFormInputs = () => wrapper.findAllComponents(GlFormInput);
describe.each([true, false])('template, isInheriting = `%p`', (isInheriting) => {
it('renders a label with text "Trigger"', () => {
createComponent();
- const triggerLabel = wrapper.find('[data-testid="trigger-fields-group"]').find('label');
+ const triggerLabel = findTriggerLabel();
expect(triggerLabel.exists()).toBe(true);
expect(triggerLabel.text()).toBe('Trigger');
});
@@ -68,7 +67,7 @@ describe('TriggerFields', () => {
});
it('renders GlFormInput with description for each event', () => {
- const groups = wrapper.find('#trigger-fields').findAll(GlFormGroup);
+ const groups = findAllGlFormGroups();
expect(groups).toHaveLength(2);
groups.wrappers.forEach((group, index) => {
diff --git a/spec/frontend/integrations/index/components/integrations_list_spec.js b/spec/frontend/integrations/index/components/integrations_list_spec.js
index 94fd7fc84ee..ee54a5fd359 100644
--- a/spec/frontend/integrations/index/components/integrations_list_spec.js
+++ b/spec/frontend/integrations/index/components/integrations_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
import IntegrationsList from '~/integrations/index/components/integrations_list.vue';
import { mockActiveIntegrations, mockInactiveIntegrations } from '../mock_data';
@@ -10,7 +10,7 @@ describe('IntegrationsList', () => {
const findInactiveIntegrationsTable = () => wrapper.findByTestId('inactive-integrations-table');
const createComponent = (propsData = {}) => {
- wrapper = extendedWrapper(shallowMount(IntegrationsList, { propsData }));
+ wrapper = shallowMountExtended(IntegrationsList, { propsData });
};
afterEach(() => {
diff --git a/spec/frontend/nav/components/top_nav_container_view_spec.js b/spec/frontend/nav/components/top_nav_container_view_spec.js
index 12bee7a515e..311331ce8f5 100644
--- a/spec/frontend/nav/components/top_nav_container_view_spec.js
+++ b/spec/frontend/nav/components/top_nav_container_view_spec.js
@@ -16,8 +16,8 @@ const DEFAULT_PROPS = {
};
const TEST_OTHER_PROPS = {
namespace: 'projects',
- currentUserName: '',
- currentItem: {},
+ currentUserName: 'test-user',
+ currentItem: { id: 'test' },
};
describe('~/nav/components/top_nav_container_view.vue', () => {
@@ -84,7 +84,7 @@ describe('~/nav/components/top_nav_container_view.vue', () => {
it('renders frequent items app', () => {
expect(findFrequentItemsApp()).toEqual({
vuexModule: DEFAULT_PROPS.frequentItemsVuexModule,
- props: TEST_OTHER_PROPS,
+ props: expect.objectContaining(TEST_OTHER_PROPS),
attributes: expect.objectContaining(EXTRA_ATTRS),
});
});
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index c74ee3ce0ec..4c62b3e12c1 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -37,8 +37,24 @@ RSpec.describe ApplicationSettingsHelper do
it_behaves_like 'when HTTP protocol is in use', 'https'
it_behaves_like 'when HTTP protocol is in use', 'http'
- context 'with tracking parameters' do
- it { expect(visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id)) }
+ describe '.visible_attributes' do
+ it 'contains tracking parameters' do
+ expect(helper.visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id))
+ end
+
+ it 'contains :deactivate_dormant_users' do
+ expect(helper.visible_attributes).to include(:deactivate_dormant_users)
+ end
+
+ context 'when GitLab.com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ it 'does not contain :deactivate_dormant_users' do
+ expect(helper.visible_attributes).not_to include(:deactivate_dormant_users)
+ end
+ end
end
describe '.integration_expanded?' do
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 122f2339b28..3d2adaa5b5d 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -114,69 +114,4 @@ RSpec.describe InviteMembersHelper do
end
end
end
-
- describe '#dropdown_invite_members_link' do
- shared_examples_for 'dropdown invite members link' do
- let(:link_regex) do
- /data-track-event="click_link".*data-track-property="_track_property_".*Invite members/
- end
-
- before do
- allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' }
- allow(helper).to receive(:current_user) { owner }
- end
-
- it 'records the experiment' do
- allow(helper).to receive(:experiment_enabled?)
-
- helper.dropdown_invite_members_link(form_model)
-
- expect(helper).to have_received(:experiment_tracking_category_and_group).with(:invite_members_new_dropdown)
- end
-
- context 'with experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { true }
- end
-
- it 'returns link' do
- link = helper.dropdown_invite_members_link(form_model)
-
- expect(link).to match(link_regex)
- expect(link).to include(link_href)
- expect(link).to include('gl-emoji')
- end
- end
-
- context 'with no experiment enabled' do
- before do
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { false }
- end
-
- it 'returns link' do
- link = helper.dropdown_invite_members_link(form_model)
-
- expect(link).to match(link_regex)
- expect(link).to include(link_href)
- expect(link).not_to include('gl-emoji')
- end
- end
- end
-
- context 'with a project' do
- let_it_be(:form_model) { project }
-
- let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" }
-
- it_behaves_like 'dropdown invite members link'
- end
-
- context 'with a group' do
- let_it_be(:form_model) { create(:group) }
-
- let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" }
-
- it_behaves_like 'dropdown invite members link'
- end
- end
end
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb
new file mode 100644
index 00000000000..dd860ce3180
--- /dev/null
+++ b/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -0,0 +1,320 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Nav::NewDropdownHelper do
+ describe '#new_dropdown_view_model' do
+ let_it_be(:user) { build_stubbed(:user) }
+
+ let(:current_user) { user }
+ let(:current_project) { nil }
+ let(:current_group) { nil }
+
+ let(:with_can_create_project) { false }
+ let(:with_can_create_group) { false }
+ let(:with_can_create_snippet) { false }
+ let(:with_new_repo_experiment) { :control }
+ let(:with_invite_members_experiment) { false }
+ let(:with_invite_members_experiment_enabled) { false }
+
+ let(:subject) { helper.new_dropdown_view_model(project: current_project, group: current_group) }
+
+ def expected_menu_section(title:, menu_item:)
+ [
+ {
+ title: title,
+ menu_items: [menu_item]
+ }
+ ]
+ end
+
+ before do
+ stub_experiments(new_repo: with_new_repo_experiment)
+ allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment }
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled }
+ allow(helper).to receive(:tracking_label) { 'test_tracking_label' }
+ allow(helper).to receive(:experiment_tracking_category_and_group) { |x| x }
+
+ allow(helper).to receive(:current_user) { current_user }
+ allow(helper).to receive(:can?) { false }
+
+ allow(user).to receive(:can_create_project?) { with_can_create_project }
+ allow(user).to receive(:can_create_group?) { with_can_create_group }
+ allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet }
+ end
+
+ shared_examples 'new repo experiment shared example' do |title|
+ let(:with_new_repo_experiment) { :candidate }
+
+ it 'has experiment project title' do
+ expect(subject[:menu_sections]).to match(
+ expected_menu_section(
+ title: title,
+ menu_item: a_hash_including(title: 'New project/repository')
+ )
+ )
+ end
+ end
+
+ shared_examples 'invite member link shared example' do
+ it 'shows invite member link' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: expected_title,
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'invite',
+ title: 'Invite members',
+ href: expected_href,
+ data: {
+ track_event: 'click_link',
+ track_label: 'test_tracking_label',
+ track_property: :invite_members_new_dropdown
+ }
+ )
+ )
+ )
+ end
+
+ context 'with experiment enabled' do
+ let(:with_invite_members_experiment_enabled) { true }
+
+ it 'shows emoji with invite member link' do
+ expect(subject[:menu_sections]).to match(
+ expected_menu_section(
+ title: expected_title,
+ menu_item: a_hash_including(
+ emoji: 'shaking_hands'
+ )
+ )
+ )
+ end
+ end
+ end
+
+ it 'has title' do
+ expect(subject[:title]).to eq('New...')
+ end
+
+ context 'when current_user is nil (anonymous)' do
+ let(:current_user) { nil }
+
+ it 'is nil' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when group and project are nil' do
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'when can create project' do
+ let(:with_can_create_project) { true }
+
+ it 'has project menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_project',
+ title: 'New project',
+ href: '/projects/new',
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
+ )
+ )
+ )
+ end
+
+ it_behaves_like 'new repo experiment shared example', 'GitLab'
+ end
+
+ context 'when can create group' do
+ let(:with_can_create_group) { true }
+
+ it 'has group menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_group',
+ title: 'New group',
+ href: '/groups/new',
+ data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can create snippet' do
+ let(:with_can_create_snippet) { true }
+
+ it 'has new snippet menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'GitLab',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'general_new_snippet',
+ title: 'New snippet',
+ href: '/-/snippets/new',
+ data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' }
+ )
+ )
+ )
+ end
+ end
+ end
+
+ context 'with persisted group' do
+ let_it_be(:group) { build_stubbed(:group) }
+
+ let(:current_group) { group }
+ let(:with_can_create_projects_in_group) { false }
+ let(:with_can_create_subgroup_in_group) { false }
+ let(:with_can_admin_in_group) { false }
+
+ before do
+ allow(group).to receive(:persisted?) { true }
+ allow(helper).to receive(:can?).with(current_user, :create_projects, group) { with_can_create_projects_in_group }
+ allow(helper).to receive(:can?).with(current_user, :create_subgroup, group) { with_can_create_subgroup_in_group }
+ allow(helper).to receive(:can?).with(current_user, :admin_group_member, group) { with_can_admin_in_group }
+ end
+
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'when can create projects in group' do
+ let(:with_can_create_projects_in_group) { true }
+
+ it 'has new project menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This group',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_project',
+ title: 'New project',
+ href: "/projects/new?namespace_id=#{group.id}",
+ data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+
+ it_behaves_like 'new repo experiment shared example', 'This group'
+ end
+
+ context 'when can create subgroup' do
+ let(:with_can_create_subgroup_in_group) { true }
+
+ it 'has new subgroup menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This group',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_subgroup',
+ title: 'New subgroup',
+ href: "/groups/new?parent_id=#{group.id}",
+ data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can invite members' do
+ let(:with_can_admin_in_group) { true }
+ let(:with_invite_members_experiment) { true }
+ let(:expected_title) { 'This group' }
+ let(:expected_href) { "/groups/#{group.full_path}/-/group_members" }
+
+ it_behaves_like 'invite member link shared example'
+ end
+ end
+
+ context 'with persisted project' do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:merge_project) { build_stubbed(:project) }
+
+ let(:current_project) { project }
+ let(:with_show_new_issue_link) { false }
+ let(:with_merge_project) { nil }
+ let(:with_can_create_snippet_in_project) { false }
+ let(:with_can_import_members) { false }
+
+ before do
+ allow(helper).to receive(:show_new_issue_link?).with(project) { with_show_new_issue_link }
+ allow(helper).to receive(:merge_request_source_project_for_project).with(project) { with_merge_project }
+ allow(helper).to receive(:can?).with(user, :create_snippet, project) { with_can_create_snippet_in_project }
+ allow(helper).to receive(:can_import_members?) { with_can_import_members }
+ end
+
+ it 'has no menu sections' do
+ expect(subject[:menu_sections]).to eq([])
+ end
+
+ context 'with show_new_issue_link?' do
+ let(:with_show_new_issue_link) { true }
+
+ it 'shows new issue menu item' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_issue',
+ title: 'New issue',
+ href: "/#{project.path_with_namespace}/-/issues/new",
+ data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'with merge project' do
+ let(:with_merge_project) { merge_project }
+
+ it 'shows merge project' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_mr',
+ title: 'New merge request',
+ href: "/#{merge_project.path_with_namespace}/-/merge_requests/new",
+ data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when can create snippet' do
+ let(:with_can_create_snippet_in_project) { true }
+
+ it 'shows new snippet' do
+ expect(subject[:menu_sections]).to eq(
+ expected_menu_section(
+ title: 'This project',
+ menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
+ id: 'new_snippet',
+ title: 'New snippet',
+ href: "/#{project.path_with_namespace}/-/snippets/new",
+ data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' }
+ )
+ )
+ )
+ end
+ end
+
+ context 'when invite members experiment' do
+ let(:with_invite_members_experiment) { true }
+ let(:with_can_import_members) { true }
+ let(:expected_title) { 'This project' }
+ let(:expected_href) { "/#{project.path_with_namespace}/-/project_members" }
+
+ it_behaves_like 'invite member link shared example'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
index c96bed2284b..966b23bf51a 100644
--- a/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
+++ b/spec/lib/gitlab/nav/top_nav_menu_item_spec.rb
@@ -13,7 +13,8 @@ RSpec.describe ::Gitlab::Nav::TopNavMenuItem do
href: 'href',
view: 'view',
css_class: 'css_class',
- data: {}
+ data: {},
+ emoji: 'smile'
}
expect(described_class.build(**item)).to eq(item)
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index bf81ab577f7..319e7b55fc3 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -52,7 +52,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
it 'has a "New project" link' do
- render('layouts/header/new_repo_experiment')
render
expect(rendered).to have_link('New project', href: new_project_path(namespace_id: group.id))
@@ -164,7 +163,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
it 'has a "New project" link' do
- render('layouts/header/new_repo_experiment')
render
expect(rendered).to have_link('New project', href: new_project_path)
@@ -182,13 +180,13 @@ RSpec.describe 'layouts/header/_new_dropdown' do
expect(rendered).to have_link('New snippet', href: new_snippet_path)
end
- context 'when the user is not allowed to create snippets' do
+ context 'when the user is not allowed to do anything' do
let(:user) { create(:user, :external) }
- it 'has no "New snippet" link' do
- render
-
- expect(rendered).not_to have_link('New snippet', href: new_snippet_path)
+ it 'is nil' do
+ # We have to us `view.render` because `render` causes issues
+ # https://github.com/rails/rails/issues/41320
+ expect(view.render("layouts/header/new_dropdown")).to be_nil
end
end
end