summaryrefslogtreecommitdiff
path: root/spec/frontend/groups
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 11:59:07 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 11:59:07 +0000
commit8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch)
tree544930fb309b30317ae9797a9683768705d664c4 /spec/frontend/groups
parent4b1de649d0168371549608993deac953eb692019 (diff)
downloadgitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'spec/frontend/groups')
-rw-r--r--spec/frontend/groups/components/app_spec.js2
-rw-r--r--spec/frontend/groups/components/group_item_spec.js49
-rw-r--r--spec/frontend/groups/components/visibility_level_dropdown_spec.js73
-rw-r--r--spec/frontend/groups/members/components/app_spec.js30
-rw-r--r--spec/frontend/groups/members/index_spec.js32
-rw-r--r--spec/frontend/groups/members/utils_spec.js2
-rw-r--r--spec/frontend/groups/store/groups_store_spec.js27
-rw-r--r--spec/frontend/groups/store/utils_spec.js44
8 files changed, 237 insertions, 22 deletions
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 691f8896d74..72d8e23f28b 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -35,7 +35,7 @@ describe('AppComponent', () => {
let mock;
let getGroupsSpy;
- const store = new GroupsStore(false);
+ const store = new GroupsStore({ hideProjects: false });
const service = new GroupsService(mockEndpoint);
const createShallowComponent = (hideProjects = false) => {
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index 83acbb152b5..32bae812c86 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import groupItemComponent from '~/groups/components/group_item.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
+import { getGroupItemMicrodata } from '~/groups/store/utils';
import eventHub from '~/groups/event_hub';
import * as urlUtilities from '~/lib/utils/url_utility';
import { mockParentGroupItem, mockChildren } from '../mock_data';
@@ -30,6 +31,11 @@ describe('GroupItemComponent', () => {
vm.$destroy();
});
+ const withMicrodata = group => ({
+ ...group,
+ microdata: getGroupItemMicrodata(group),
+ });
+
describe('computed', () => {
describe('groupDomId', () => {
it('should return ID string suffixed with group ID', () => {
@@ -212,4 +218,47 @@ describe('GroupItemComponent', () => {
expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
});
});
+ describe('schema.org props', () => {
+ describe('when showSchemaMarkup is disabled on the group', () => {
+ it.each(['itemprop', 'itemtype', 'itemscope'], 'it does not set %s', attr => {
+ expect(vm.$el.getAttribute(attr)).toBeNull();
+ });
+ it.each(
+ ['.js-group-avatar', '.js-group-name', '.js-group-description'],
+ 'it does not set `itemprop` on sub-nodes',
+ selector => {
+ expect(vm.$el.querySelector(selector).getAttribute('itemprop')).toBeNull();
+ },
+ );
+ });
+ describe('when group has microdata', () => {
+ beforeEach(() => {
+ const group = withMicrodata({
+ ...mockParentGroupItem,
+ avatarUrl: 'http://foo.bar',
+ description: 'Foo Bar',
+ });
+
+ vm = createComponent(group);
+ });
+
+ it.each`
+ attr | value
+ ${'itemscope'} | ${'itemscope'}
+ ${'itemtype'} | ${'https://schema.org/Organization'}
+ ${'itemprop'} | ${'subOrganization'}
+ `('it does set correct $attr', ({ attr, value } = {}) => {
+ expect(vm.$el.getAttribute(attr)).toBe(value);
+ });
+
+ it.each`
+ selector | propValue
+ ${'[data-testid="group-avatar"]'} | ${'logo'}
+ ${'[data-testid="group-name"]'} | ${'name'}
+ ${'[data-testid="group-description"]'} | ${'description'}
+ `('it does set correct $selector', ({ selector, propValue } = {}) => {
+ expect(vm.$el.querySelector(selector).getAttribute('itemprop')).toBe(propValue);
+ });
+ });
+ });
});
diff --git a/spec/frontend/groups/components/visibility_level_dropdown_spec.js b/spec/frontend/groups/components/visibility_level_dropdown_spec.js
new file mode 100644
index 00000000000..bf9508dc768
--- /dev/null
+++ b/spec/frontend/groups/components/visibility_level_dropdown_spec.js
@@ -0,0 +1,73 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Component from '~/groups/components/visibility_level_dropdown.vue';
+
+describe('Visibility Level Dropdown', () => {
+ let wrapper;
+
+ const options = [
+ { level: 0, label: 'Private', description: 'Private description' },
+ { level: 20, label: 'Public', description: 'Public description' },
+ ];
+ const defaultLevel = 0;
+
+ const createComponent = propsData => {
+ wrapper = shallowMount(Component, {
+ propsData,
+ });
+ };
+
+ beforeEach(() => {
+ createComponent({
+ visibilityLevelOptions: options,
+ defaultLevel,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const hiddenInputValue = () =>
+ wrapper.find("input[name='group[visibility_level]']").attributes('value');
+ const dropdownText = () => wrapper.find(GlDropdown).props('text');
+ const findDropdownItems = () =>
+ wrapper.findAll(GlDropdownItem).wrappers.map(option => ({
+ text: option.text(),
+ secondaryText: option.props('secondaryText'),
+ }));
+
+ describe('Default values', () => {
+ it('sets the value of the hidden input to the default value', () => {
+ expect(hiddenInputValue()).toBe(options[0].level.toString());
+ });
+
+ it('sets the text of the dropdown to the default value', () => {
+ expect(dropdownText()).toBe(options[0].label);
+ });
+
+ it('shows all dropdown options', () => {
+ expect(findDropdownItems()).toEqual(
+ options.map(({ label, description }) => ({ text: label, secondaryText: description })),
+ );
+ });
+ });
+
+ describe('Selecting an option', () => {
+ beforeEach(() => {
+ wrapper
+ .findAll(GlDropdownItem)
+ .at(1)
+ .vm.$emit('click');
+ });
+
+ it('sets the value of the hidden input to the selected value', () => {
+ expect(hiddenInputValue()).toBe(options[1].level.toString());
+ });
+
+ it('sets the text of the dropdown to the selected value', () => {
+ expect(dropdownText()).toBe(options[1].label);
+ });
+ });
+});
diff --git a/spec/frontend/groups/members/components/app_spec.js b/spec/frontend/groups/members/components/app_spec.js
index de9f30649e9..208e2fc35b6 100644
--- a/spec/frontend/groups/members/components/app_spec.js
+++ b/spec/frontend/groups/members/components/app_spec.js
@@ -3,12 +3,10 @@ import { nextTick } from 'vue';
import Vuex from 'vuex';
import { GlAlert } from '@gitlab/ui';
import App from '~/groups/members/components/app.vue';
+import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
import * as commonUtils from '~/lib/utils/common_utils';
-import {
- RECEIVE_MEMBER_ROLE_ERROR,
- HIDE_ERROR,
-} from '~/vuex_shared/modules/members/mutation_types';
-import mutations from '~/vuex_shared/modules/members/mutations';
+import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types';
+import mutations from '~/members/store/mutations';
describe('GroupMembersApp', () => {
const localVue = createLocalVue();
@@ -17,7 +15,7 @@ describe('GroupMembersApp', () => {
let wrapper;
let store;
- const createComponent = (state = {}) => {
+ const createComponent = (state = {}, options = {}) => {
store = new Vuex.Store({
state: {
showError: true,
@@ -30,10 +28,12 @@ describe('GroupMembersApp', () => {
wrapper = shallowMount(App, {
localVue,
store,
+ ...options,
});
};
const findAlert = () => wrapper.find(GlAlert);
+ const findFilterSortContainer = () => wrapper.find(FilterSortContainer);
beforeEach(() => {
commonUtils.scrollToElement = jest.fn();
@@ -86,4 +86,22 @@ describe('GroupMembersApp', () => {
expect(findAlert().exists()).toBe(false);
});
});
+
+ describe.each`
+ featureFlagValue | exists
+ ${true} | ${true}
+ ${false} | ${false}
+ `(
+ 'when `group_members_filtered_search` feature flag is $featureFlagValue',
+ ({ featureFlagValue, exists }) => {
+ it(`${exists ? 'renders' : 'does not render'} FilterSortContainer`, () => {
+ createComponent(
+ {},
+ { provide: { glFeatures: { groupMembersFilteredSearch: featureFlagValue } } },
+ );
+
+ expect(findFilterSortContainer().exists()).toBe(exists);
+ });
+ },
+ );
});
diff --git a/spec/frontend/groups/members/index_spec.js b/spec/frontend/groups/members/index_spec.js
index aaa36665c45..5c717e53229 100644
--- a/spec/frontend/groups/members/index_spec.js
+++ b/spec/frontend/groups/members/index_spec.js
@@ -9,12 +9,13 @@ describe('initGroupMembersApp', () => {
let wrapper;
const setup = () => {
- vm = initGroupMembersApp(
- el,
- ['account'],
- { table: { 'data-qa-selector': 'members_list' } },
- () => ({}),
- );
+ vm = initGroupMembersApp(el, {
+ tableFields: ['account'],
+ tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
+ tableSortableFields: ['account'],
+ requestFormatter: () => ({}),
+ filteredSearchBar: { show: false },
+ });
wrapper = createWrapper(vm);
};
@@ -22,6 +23,7 @@ describe('initGroupMembersApp', () => {
el = document.createElement('div');
el.setAttribute('data-members', membersJsonString);
el.setAttribute('data-group-id', '234');
+ el.setAttribute('data-can-manage-members', 'true');
el.setAttribute('data-member-path', '/groups/foo-bar/-/group_members/:id');
window.gon = { current_user_id: 123 };
@@ -61,6 +63,12 @@ describe('initGroupMembersApp', () => {
expect(vm.$store.state.sourceId).toBe(234);
});
+ it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.canManageMembers).toBe(true);
+ });
+
it('parses and sets `members` in Vuex store', () => {
setup();
@@ -79,12 +87,24 @@ describe('initGroupMembersApp', () => {
expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
});
+ it('sets `tableSortableFields` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.tableSortableFields).toEqual(['account']);
+ });
+
it('sets `requestFormatter` in Vuex store', () => {
setup();
expect(vm.$store.state.requestFormatter()).toEqual({});
});
+ it('sets `filteredSearchBar` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.filteredSearchBar).toEqual({ show: false });
+ });
+
it('sets `memberPath` in Vuex store', () => {
setup();
diff --git a/spec/frontend/groups/members/utils_spec.js b/spec/frontend/groups/members/utils_spec.js
index b0921c7642f..68945174e9d 100644
--- a/spec/frontend/groups/members/utils_spec.js
+++ b/spec/frontend/groups/members/utils_spec.js
@@ -13,6 +13,7 @@ describe('group member utils', () => {
el = document.createElement('div');
el.setAttribute('data-members', membersJsonString);
el.setAttribute('data-group-id', '234');
+ el.setAttribute('data-can-manage-members', 'true');
});
afterEach(() => {
@@ -23,6 +24,7 @@ describe('group member utils', () => {
expect(parseDataAttributes(el)).toEqual({
members: membersParsed,
sourceId: 234,
+ canManageMembers: true,
});
});
});
diff --git a/spec/frontend/groups/store/groups_store_spec.js b/spec/frontend/groups/store/groups_store_spec.js
index 7d12f73d270..8ac5d7099f1 100644
--- a/spec/frontend/groups/store/groups_store_spec.js
+++ b/spec/frontend/groups/store/groups_store_spec.js
@@ -1,4 +1,5 @@
import GroupsStore from '~/groups/store/groups_store';
+import { getGroupItemMicrodata } from '~/groups/store/utils';
import {
mockGroups,
mockSearchedGroups,
@@ -17,9 +18,9 @@ describe('ProjectsStore', () => {
expect(Object.keys(store.state).length).toBe(2);
expect(Array.isArray(store.state.groups)).toBeTruthy();
expect(Object.keys(store.state.pageInfo).length).toBe(0);
- expect(store.hideProjects).not.toBeDefined();
+ expect(store.hideProjects).toBeFalsy();
- store = new GroupsStore(true);
+ store = new GroupsStore({ hideProjects: true });
expect(store.hideProjects).toBeTruthy();
});
@@ -86,22 +87,30 @@ describe('ProjectsStore', () => {
describe('formatGroupItem', () => {
it('should parse group item object and return updated object', () => {
- let store;
- let updatedGroupItem;
-
- store = new GroupsStore();
- updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
+ const store = new GroupsStore();
+ const updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].children_count);
expect(updatedGroupItem.isChildrenLoading).toBe(false);
expect(updatedGroupItem.isBeingRemoved).toBe(false);
+ expect(updatedGroupItem.microdata).toEqual({});
+ });
- store = new GroupsStore(true);
- updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
+ it('with hideProjects', () => {
+ const store = new GroupsStore({ hideProjects: true });
+ const updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].subgroup_count);
+ expect(updatedGroupItem.microdata).toEqual({});
+ });
+
+ it('with showSchemaMarkup', () => {
+ const store = new GroupsStore({ showSchemaMarkup: true });
+ const updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
+
+ expect(updatedGroupItem.microdata).toEqual(getGroupItemMicrodata(mockRawChildren[0]));
});
});
diff --git a/spec/frontend/groups/store/utils_spec.js b/spec/frontend/groups/store/utils_spec.js
new file mode 100644
index 00000000000..0961d4c72b4
--- /dev/null
+++ b/spec/frontend/groups/store/utils_spec.js
@@ -0,0 +1,44 @@
+import { getGroupItemMicrodata } from '~/groups/store/utils';
+
+describe('~/groups/store/utils', () => {
+ describe('getGroupItemMetadata', () => {
+ it('has default type', () => {
+ expect(getGroupItemMicrodata({ type: 'silly' })).toMatchInlineSnapshot(`
+ Object {
+ "descriptionItemprop": "description",
+ "imageItemprop": "image",
+ "itemprop": "owns",
+ "itemscope": true,
+ "itemtype": "https://schema.org/Thing",
+ "nameItemprop": "name",
+ }
+ `);
+ });
+
+ it('has group props', () => {
+ expect(getGroupItemMicrodata({ type: 'group' })).toMatchInlineSnapshot(`
+ Object {
+ "descriptionItemprop": "description",
+ "imageItemprop": "logo",
+ "itemprop": "subOrganization",
+ "itemscope": true,
+ "itemtype": "https://schema.org/Organization",
+ "nameItemprop": "name",
+ }
+ `);
+ });
+
+ it('has project props', () => {
+ expect(getGroupItemMicrodata({ type: 'project' })).toMatchInlineSnapshot(`
+ Object {
+ "descriptionItemprop": "description",
+ "imageItemprop": "image",
+ "itemprop": "owns",
+ "itemscope": true,
+ "itemtype": "https://schema.org/SoftwareSourceCode",
+ "nameItemprop": "name",
+ }
+ `);
+ });
+ });
+});