Commit 60733162 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Bob Van Landuyt

Request parent labels when subgroup selected

Fixes a 404 error when we try and request
group labels for a subgroup

For value stream analytics, when a subgroup
is selected we should only query for the labels
associated with the parent group

Updated related specs

Added changelog entry
parent cf586958
...@@ -220,10 +220,10 @@ export const requestGroupLabels = ({ commit }) => commit(types.REQUEST_GROUP_LAB ...@@ -220,10 +220,10 @@ export const requestGroupLabels = ({ commit }) => commit(types.REQUEST_GROUP_LAB
export const fetchGroupLabels = ({ dispatch, state }) => { export const fetchGroupLabels = ({ dispatch, state }) => {
dispatch('requestGroupLabels'); dispatch('requestGroupLabels');
const { const {
selectedGroup: { fullPath }, selectedGroup: { fullPath, parentId = null },
} = state; } = state;
return Api.cycleAnalyticsGroupLabels(fullPath) return Api.cycleAnalyticsGroupLabels(parentId || fullPath)
.then(({ data }) => dispatch('receiveGroupLabelsSuccess', data)) .then(({ data }) => dispatch('receiveGroupLabelsSuccess', data))
.catch(error => .catch(error =>
handleErrorOrRethrow({ error, action: () => dispatch('receiveGroupLabelsError', error) }), handleErrorOrRethrow({ error, action: () => dispatch('receiveGroupLabelsError', error) }),
......
...@@ -17,7 +17,7 @@ export const formattedDate = d => dateFormat(d, dateFormats.defaultDate); ...@@ -17,7 +17,7 @@ export const formattedDate = d => dateFormat(d, dateFormats.defaultDate);
* @returns {Object} - A group object * @returns {Object} - A group object
*/ */
export const buildGroupFromDataset = dataset => { export const buildGroupFromDataset = dataset => {
const { groupId, groupName, groupFullPath, groupAvatarUrl } = dataset; const { groupId, groupName, groupFullPath, groupAvatarUrl, groupParentId } = dataset;
if (groupId) { if (groupId) {
return { return {
...@@ -25,6 +25,7 @@ export const buildGroupFromDataset = dataset => { ...@@ -25,6 +25,7 @@ export const buildGroupFromDataset = dataset => {
name: groupName, name: groupName,
full_path: groupFullPath, full_path: groupFullPath,
avatar_url: groupAvatarUrl, avatar_url: groupAvatarUrl,
parent_id: groupParentId,
}; };
} }
...@@ -76,11 +77,18 @@ export const buildCycleAnalyticsInitialData = ({ ...@@ -76,11 +77,18 @@ export const buildCycleAnalyticsInitialData = ({
projects = null, projects = null,
groupName = null, groupName = null,
groupFullPath = null, groupFullPath = null,
groupParentId = null,
groupAvatarUrl = null, groupAvatarUrl = null,
} = {}) => ({ } = {}) => ({
group: groupId group: groupId
? convertObjectPropsToCamelCase( ? convertObjectPropsToCamelCase(
buildGroupFromDataset({ groupId, groupName, groupFullPath, groupAvatarUrl }), buildGroupFromDataset({
groupId,
groupName,
groupFullPath,
groupAvatarUrl,
groupParentId,
}),
) )
: null, : null,
createdBefore: createdBefore ? new Date(createdBefore) : null, createdBefore: createdBefore ? new Date(createdBefore) : null,
......
---
title: Use group parent for subgroup labels requests
merge_request: 27564
author:
type: fixed
...@@ -54,6 +54,7 @@ module Gitlab ...@@ -54,6 +54,7 @@ module Gitlab
{ {
id: group.id, id: group.id,
name: group.name, name: group.name,
parent_id: group.parent_id,
full_path: group.full_path, full_path: group.full_path,
avatar_url: group.avatar_url avatar_url: group.avatar_url
} }
......
...@@ -6,6 +6,7 @@ describe 'Group Value Stream Analytics', :js do ...@@ -6,6 +6,7 @@ describe 'Group Value Stream Analytics', :js do
let!(:user) { create(:user) } let!(:user) { create(:user) }
let!(:group) { create(:group, name: "CA-test-group") } let!(:group) { create(:group, name: "CA-test-group") }
let!(:sub_group) { create(:group, name: "CA-sub-group", parent: group) }
let!(:group2) { create(:group, name: "CA-bad-test-group") } let!(:group2) { create(:group, name: "CA-bad-test-group") }
let!(:project) { create(:project, :repository, namespace: group, group: group, name: "Cool fun project") } let!(:project) { create(:project, :repository, namespace: group, group: group, name: "Cool fun project") }
let!(:label) { create(:group_label, group: group) } let!(:label) { create(:group_label, group: group) }
...@@ -157,11 +158,10 @@ describe 'Group Value Stream Analytics', :js do ...@@ -157,11 +158,10 @@ describe 'Group Value Stream Analytics', :js do
expect(page).to have_selector '.js-stage-table' expect(page).to have_selector '.js-stage-table'
end end
# TODO: Followup should have tests for stub_licensed_features(cycle_analytics_for_groups: false) def select_group(name = group.name)
def select_group
dropdown = page.find('.dropdown-groups') dropdown = page.find('.dropdown-groups')
dropdown.click dropdown.click
dropdown.find('a').click dropdown.find('.js-group-path', exact_text: name).click
wait_for_stages_to_load wait_for_stages_to_load
end end
...@@ -184,11 +184,7 @@ describe 'Group Value Stream Analytics', :js do ...@@ -184,11 +184,7 @@ describe 'Group Value Stream Analytics', :js do
end end
end end
context 'with a group selected' do shared_examples 'group value stream analytics' do
before do
select_group
end
context 'summary table', :js do context 'summary table', :js do
it 'will display recent activity' do it 'will display recent activity' do
page.within(find('.js-summary-table')) do page.within(find('.js-summary-table')) do
...@@ -196,20 +192,6 @@ describe 'Group Value Stream Analytics', :js do ...@@ -196,20 +192,6 @@ describe 'Group Value Stream Analytics', :js do
expect(page).to have_content('Recent Activity') expect(page).to have_content('Recent Activity')
end end
end end
it 'displays the number of issues' do
expect(page).to have_content('New Issues')
issue_count = find(".card .header", match: :first)
expect(issue_count).to have_content('3')
end
it 'displays the number of deploys' do
expect(page).to have_content('Deploys')
deploys_count = page.all(".card .header").last
expect(deploys_count).to have_content('-')
end
end end
context 'stage panel' do context 'stage panel' do
...@@ -236,6 +218,36 @@ describe 'Group Value Stream Analytics', :js do ...@@ -236,6 +218,36 @@ describe 'Group Value Stream Analytics', :js do
end end
end end
context 'with a group selected' do
before do
select_group
end
it_behaves_like 'group value stream analytics'
it 'displays the number of issues' do
expect(page).to have_content('New Issues')
issue_count = find(".card .header", match: :first)
expect(issue_count).to have_content('3')
end
it 'displays the number of deploys' do
expect(page).to have_content('Deploys')
deploys_count = page.all(".card .header").last
expect(deploys_count).to have_content('-')
end
end
context 'with a sub group selected' do
before do
select_group(sub_group.full_name)
end
it_behaves_like 'group value stream analytics'
end
def select_stage(name) def select_stage(name)
page.find('.stage-nav .stage-nav-item .stage-name', text: name, match: :prefer_exact).click page.find('.stage-nav .stage-nav-item .stage-name', text: name, match: :prefer_exact).click
...@@ -406,8 +418,8 @@ describe 'Group Value Stream Analytics', :js do ...@@ -406,8 +418,8 @@ describe 'Group Value Stream Analytics', :js do
let(:first_custom_stage) { page.find('.stage-nav-item-cell', text: custom_stage_name).ancestor(".stage-nav-item") } let(:first_custom_stage) { page.find('.stage-nav-item-cell', text: custom_stage_name).ancestor(".stage-nav-item") }
let(:nav) { page.find(stage_nav_selector) } let(:nav) { page.find(stage_nav_selector) }
def create_custom_stage def create_custom_stage(parent_group = group)
Analytics::CycleAnalytics::Stages::CreateService.new(parent: group, params: params, current_user: user).execute Analytics::CycleAnalytics::Stages::CreateService.new(parent: parent_group, params: params, current_user: user).execute
end end
def toggle_more_options(stage) def toggle_more_options(stage)
...@@ -460,11 +472,11 @@ describe 'Group Value Stream Analytics', :js do ...@@ -460,11 +472,11 @@ describe 'Group Value Stream Analytics', :js do
end end
context 'enabled' do context 'enabled' do
context 'Manual ordering' do
before do before do
select_group select_group
end end
context 'Manual ordering' do
context 'with only default stages' do context 'with only default stages' do
it_behaves_like 'manual ordering disabled' it_behaves_like 'manual ordering disabled'
end end
...@@ -510,6 +522,10 @@ describe 'Group Value Stream Analytics', :js do ...@@ -510,6 +522,10 @@ describe 'Group Value Stream Analytics', :js do
end end
context 'Add a stage button' do context 'Add a stage button' do
before do
select_group
end
it 'is visible' do it 'is visible' do
expect(page).to have_selector(add_stage_button, visible: true) expect(page).to have_selector(add_stage_button, visible: true)
expect(page).to have_text('Add a stage') expect(page).to have_text('Add a stage')
...@@ -532,12 +548,11 @@ describe 'Group Value Stream Analytics', :js do ...@@ -532,12 +548,11 @@ describe 'Group Value Stream Analytics', :js do
end end
end end
shared_examples 'can create custom stages' do
context 'Custom stage form' do context 'Custom stage form' do
let(:show_form_add_stage_button) { '.js-add-stage-button' } let(:show_form_add_stage_button) { '.js-add-stage-button' }
before do before do
select_group
page.find(show_form_add_stage_button).click page.find(show_form_add_stage_button).click
wait_for_requests wait_for_requests
end end
...@@ -632,7 +647,9 @@ describe 'Group Value Stream Analytics', :js do ...@@ -632,7 +647,9 @@ describe 'Group Value Stream Analytics', :js do
end end
end end
end end
end
shared_examples 'can edit custom stages' do
context 'Edit stage form' do context 'Edit stage form' do
stage_form_class = '.custom-stage-form' stage_form_class = '.custom-stage-form'
stage_save_button = '.js-save-stage' stage_save_button = '.js-save-stage'
...@@ -646,13 +663,6 @@ describe 'Group Value Stream Analytics', :js do ...@@ -646,13 +663,6 @@ describe 'Group Value Stream Analytics', :js do
click_button "Edit stage" click_button "Edit stage"
end end
before do
create_custom_stage
select_group
expect(page).to have_text custom_stage_name
end
context 'with no changes to the data' do context 'with no changes to the data' do
before do before do
select_edit_stage select_edit_stage
...@@ -707,6 +717,49 @@ describe 'Group Value Stream Analytics', :js do ...@@ -707,6 +717,49 @@ describe 'Group Value Stream Analytics', :js do
end end
end end
end end
end
context 'with a group' do
context 'selected' do
before do
select_group
end
it_behaves_like 'can create custom stages'
end
context 'with a custom stage created' do
before do
create_custom_stage
select_group
expect(page).to have_text custom_stage_name
end
it_behaves_like 'can edit custom stages'
end
end
context 'with a sub group' do
context 'selected' do
before do
select_group(sub_group.full_name)
end
it_behaves_like 'can create custom stages'
end
context 'with a custom stage created' do
before do
create_custom_stage(sub_group)
select_group(sub_group.full_name)
expect(page).to have_text custom_stage_name
end
it_behaves_like 'can edit custom stages'
end
end
context 'Stage table' do context 'Stage table' do
context 'default stages' do context 'default stages' do
...@@ -865,9 +918,7 @@ describe 'Group Value Stream Analytics', :js do ...@@ -865,9 +918,7 @@ describe 'Group Value Stream Analytics', :js do
before do before do
stub_feature_flags(customizable_cycle_analytics: false) stub_feature_flags(customizable_cycle_analytics: false)
dropdown = page.find('.dropdown-groups') select_group
dropdown.click
dropdown.find('a').click
end end
context 'Add a stage button' do context 'Add a stage button' do
......
...@@ -11,6 +11,14 @@ const groupDataset = { ...@@ -11,6 +11,14 @@ const groupDataset = {
groupAvatarUrl: 'foo/bar', groupAvatarUrl: 'foo/bar',
}; };
const subGroupDataset = {
groupId: '1',
groupName: 'My Group',
groupFullPath: 'parent/my-group',
groupAvatarUrl: 'foo/bar',
groupParentId: 20,
};
const projectDataset = { const projectDataset = {
projectId: '1', projectId: '1',
projectName: 'My Project', projectName: 'My Project',
...@@ -38,6 +46,16 @@ describe('buildGroupFromDataset', () => { ...@@ -38,6 +46,16 @@ describe('buildGroupFromDataset', () => {
avatar_url: 'foo/bar', avatar_url: 'foo/bar',
}); });
}); });
it('sets the parent_id when a subgroup is given', () => {
expect(buildGroupFromDataset(subGroupDataset)).toEqual({
id: 1,
name: 'My Group',
full_path: 'parent/my-group',
avatar_url: 'foo/bar',
parent_id: 20,
});
});
}); });
describe('buildProjectFromDataset', () => { describe('buildProjectFromDataset', () => {
...@@ -80,6 +98,7 @@ describe('buildCycleAnalyticsInitialData', () => { ...@@ -80,6 +98,7 @@ describe('buildCycleAnalyticsInitialData', () => {
${'avatarUrl'} | ${null} ${'avatarUrl'} | ${null}
${'fullPath'} | ${null} ${'fullPath'} | ${null}
${'name'} | ${null} ${'name'} | ${null}
${'parentId'} | ${null}
`("will be $value if the '$field' field is not present", ({ field, value }) => { `("will be $value if the '$field' field is not present", ({ field, value }) => {
expect(buildCycleAnalyticsInitialData({ groupId: groupDataset.groupId })).toMatchObject({ expect(buildCycleAnalyticsInitialData({ groupId: groupDataset.groupId })).toMatchObject({
group: { id: 1, [field]: value }, group: { id: 1, [field]: value },
......
...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import Api from 'ee/api'; import Api from 'ee/api';
import * as cycleAnalyticsConstants from 'ee/analytics/cycle_analytics/constants'; import * as cycleAnalyticsConstants from 'ee/analytics/cycle_analytics/constants';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import * as analyticsMockData from 'ee_jest/analytics/cycle_analytics/mock_data'; import * as analyticsMockData from 'ee_jest/analytics/cycle_analytics/mock_data';
describe('Api', () => { describe('Api', () => {
...@@ -537,7 +538,7 @@ describe('Api', () => { ...@@ -537,7 +538,7 @@ describe('Api', () => {
it('fetches group level labels', done => { it('fetches group level labels', done => {
const response = []; const response = [];
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/labels`; const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/labels`;
mock.onGet(expectedUrl).reply(200, response); mock.onGet(expectedUrl).reply(httpStatus.OK, response);
Api.cycleAnalyticsGroupLabels(groupId) Api.cycleAnalyticsGroupLabels(groupId)
.then(({ data, config: { url } }) => { .then(({ data, config: { url } }) => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment