Commit c83cde68 authored by Florie Guibert's avatar Florie Guibert Committed by Peter Hegman

Consolidate labels sidebar rspec tests

Unify tests anbd selectors for issue board and issue page
Fix error when creating label with name taken
parent 0d25e2f1
...@@ -209,7 +209,6 @@ export default { ...@@ -209,7 +209,6 @@ export default {
/> />
<sidebar-labels-widget <sidebar-labels-widget
class="block labels" class="block labels"
data-testid="sidebar-labels"
:iid="activeBoardItem.iid" :iid="activeBoardItem.iid"
:full-path="projectPathForActiveIssue" :full-path="projectPathForActiveIssue"
:allow-label-remove="allowLabelEdit" :allow-label-remove="allowLabelEdit"
......
...@@ -16,6 +16,7 @@ export default class CreateLabelDropdown { ...@@ -16,6 +16,7 @@ export default class CreateLabelDropdown {
this.$colorPreview = $('.js-dropdown-label-color-preview', this.$el); this.$colorPreview = $('.js-dropdown-label-color-preview', this.$el);
this.$addList = $('.js-add-list', this.$el); this.$addList = $('.js-add-list', this.$el);
this.$newLabelError = $('.js-label-error', this.$el); this.$newLabelError = $('.js-label-error', this.$el);
this.$newLabelErrorContent = $('.gl-alert-content', this.$newLabelError);
this.$newLabelCreateButton = $('.js-new-label-btn', this.$el); this.$newLabelCreateButton = $('.js-new-label-btn', this.$el);
this.$colorSuggestions = $('.suggest-colors-dropdown a', this.$el); this.$colorSuggestions = $('.suggest-colors-dropdown a', this.$el);
...@@ -119,7 +120,8 @@ export default class CreateLabelDropdown { ...@@ -119,7 +120,8 @@ export default class CreateLabelDropdown {
.join('<br/>'); .join('<br/>');
} }
this.$newLabelError.html(errors).show(); this.$newLabelErrorContent.html(errors);
this.$newLabelError.show();
} else { } else {
const addNewList = this.$addList.is(':checked'); const addNewList = this.$addList.is(':checked');
this.$dropdownBack.trigger('click'); this.$dropdownBack.trigger('click');
......
<script> <script>
import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui'; import {
GlAlert,
GlTooltipDirective,
GlButton,
GlFormInput,
GlLink,
GlLoadingIcon,
} from '@gitlab/ui';
import produce from 'immer'; import produce from 'immer';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
...@@ -11,6 +18,7 @@ const errorMessage = __('Error creating label.'); ...@@ -11,6 +18,7 @@ const errorMessage = __('Error creating label.');
export default { export default {
components: { components: {
GlAlert,
GlButton, GlButton,
GlFormInput, GlFormInput,
GlLink, GlLink,
...@@ -42,6 +50,7 @@ export default { ...@@ -42,6 +50,7 @@ export default {
labelTitle: '', labelTitle: '',
selectedColor: '', selectedColor: '',
labelCreateInProgress: false, labelCreateInProgress: false,
error: undefined,
}; };
}, },
computed: { computed: {
...@@ -111,13 +120,14 @@ export default { ...@@ -111,13 +120,14 @@ export default {
) => this.updateLabelsInCache(store, label), ) => this.updateLabelsInCache(store, label),
}); });
if (labelCreate.errors.length) { if (labelCreate.errors.length) {
createFlash({ message: errorMessage }); [this.error] = labelCreate.errors;
} else {
this.$emit('hideCreateView');
} }
} catch { } catch {
createFlash({ message: errorMessage }); createFlash({ message: errorMessage });
} }
this.labelCreateInProgress = false; this.labelCreateInProgress = false;
this.$emit('hideCreateView');
}, },
}, },
}; };
...@@ -126,6 +136,9 @@ export default { ...@@ -126,6 +136,9 @@ export default {
<template> <template>
<div class="labels-select-contents-create js-labels-create"> <div class="labels-select-contents-create js-labels-create">
<div class="dropdown-input"> <div class="dropdown-input">
<gl-alert v-if="error" variant="danger" :dismissible="false" class="gl-mb-3">
{{ error }}
</gl-alert>
<gl-form-input <gl-form-input
v-model.trim="labelTitle" v-model.trim="labelTitle"
:placeholder="__('Name new label')" :placeholder="__('Name new label')"
......
...@@ -289,6 +289,7 @@ export default { ...@@ -289,6 +289,7 @@ export default {
'is-standalone': isDropdownVariantStandalone(variant), 'is-standalone': isDropdownVariantStandalone(variant),
'is-embedded': isDropdownVariantEmbedded(variant), 'is-embedded': isDropdownVariantEmbedded(variant),
}" }"
data-testid="sidebar-labels"
data-qa-selector="labels_block" data-qa-selector="labels_block"
> >
<template v-if="isDropdownVariantSidebar(variant)"> <template v-if="isDropdownVariantSidebar(variant)">
......
...@@ -68,13 +68,6 @@ ...@@ -68,13 +68,6 @@
color: $white; color: $white;
} }
.dropdown-labels-error {
padding: 5px 10px;
margin-bottom: 10px;
background-color: $red-500;
color: $white;
}
.manage-labels-list { .manage-labels-list {
padding: 0; padding: 0;
margin-bottom: 0; margin-bottom: 0;
......
...@@ -6,7 +6,10 @@ ...@@ -6,7 +6,10 @@
.dropdown-page-two.dropdown-new-label .dropdown-page-two.dropdown-new-label
= dropdown_title(create_label_title(subject), options: { back: true, close: show_close }) = dropdown_title(create_label_title(subject), options: { back: true, close: show_close })
= dropdown_content do = dropdown_content do
.dropdown-labels-error.js-label-error .js-label-error.gl-alert.gl-alert-danger.gl-mb-3
.gl-alert-container
= sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-content
%input#new_label_name.default-dropdown-input{ type: "text", placeholder: _('Name new label') } %input#new_label_name.default-dropdown-input{ type: "text", placeholder: _('Name new label') }
.suggest-colors.suggest-colors-dropdown .suggest-colors.suggest-colors-dropdown
= render_suggested_colors = render_suggested_colors
......
...@@ -152,32 +152,6 @@ RSpec.describe 'Epic boards sidebar', :js do ...@@ -152,32 +152,6 @@ RSpec.describe 'Epic boards sidebar', :js do
end end
end end
context 'labels' do
it 'adds a single label' do
click_card(card)
page.within('.labels') do
click_button 'Edit'
wait_for_requests
click_on bug.title
click_button 'Close'
wait_for_requests
page.within('.value') do
expect(page).to have_selector('.gl-label-text', count: 1)
expect(page).to have_content(bug.title)
end
end
expect(card).to have_selector('.gl-label', count: 1)
expect(card).to have_content(bug.title)
end
end
context 'confidentiality' do context 'confidentiality' do
it 'make epic confidential' do it 'make epic confidential' do
click_card(card) click_card(card)
......
...@@ -71,7 +71,6 @@ exports[`ee/BoardContentSidebar matches the snapshot 1`] = ` ...@@ -71,7 +71,6 @@ exports[`ee/BoardContentSidebar matches the snapshot 1`] = `
allowmultiselect="true" allowmultiselect="true"
attrworkspacepath="gitlab-org/gitlab-test" attrworkspacepath="gitlab-org/gitlab-test"
class="block labels" class="block labels"
data-testid="sidebar-labels"
dropdownbuttontext="Label" dropdownbuttontext="Label"
footercreatelabeltitle="Create project label" footercreatelabeltitle="Create project label"
footermanagelabeltitle="Manage project labels" footermanagelabeltitle="Manage project labels"
......
...@@ -6,9 +6,11 @@ RSpec.describe 'Project issue boards sidebar', :js do ...@@ -6,9 +6,11 @@ RSpec.describe 'Project issue boards sidebar', :js do
include BoardHelpers include BoardHelpers
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) } let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: group) }
let_it_be(:board) { create(:board, project: project) } let_it_be(:board) { create(:board, project: project) }
let_it_be(:list) { create(:list, board: board, position: 0) } let_it_be(:label) { create(:label, project: project, name: 'Label') }
let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) } let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) }
......
...@@ -8,10 +8,9 @@ RSpec.describe 'Issue Sidebar' do ...@@ -8,10 +8,9 @@ RSpec.describe 'Issue Sidebar' do
let_it_be(:group) { create(:group, :nested) } let_it_be(:group) { create(:group, :nested) }
let_it_be(:project) { create(:project, :public, namespace: group) } let_it_be(:project) { create(:project, :public, namespace: group) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:label) { create(:label, project: project, title: 'bug') } let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label]) } let_it_be(:label) { create(:label, project: project, name: 'Label') }
let_it_be(:mock_date) { Date.today.at_beginning_of_month + 2.days } let_it_be(:mock_date) { Date.today.at_beginning_of_month + 2.days }
let_it_be(:xss_label) { create(:label, project: project, title: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
before do before do
stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
...@@ -223,14 +222,6 @@ RSpec.describe 'Issue Sidebar' do ...@@ -223,14 +222,6 @@ RSpec.describe 'Issue Sidebar' do
restore_window_size restore_window_size
open_issue_sidebar open_issue_sidebar
end end
it 'escapes XSS when viewing issue labels' do
page.within('.block.labels') do
click_on 'Edit'
expect(page).to have_content '<script>alert("xss");</script>'
end
end
end end
context 'editing issue milestone', :js do context 'editing issue milestone', :js do
...@@ -242,62 +233,7 @@ RSpec.describe 'Issue Sidebar' do ...@@ -242,62 +233,7 @@ RSpec.describe 'Issue Sidebar' do
end end
context 'editing issue labels', :js do context 'editing issue labels', :js do
before do it_behaves_like 'labels sidebar widget'
issue.update!(labels: [label])
page.within('.block.labels') do
click_on 'Edit'
end
end
it 'shows the current set of labels' do
page.within('.issuable-show-labels') do
expect(page).to have_content label.title
end
end
it 'shows option to create a project label' do
page.within('.block.labels') do
expect(page).to have_content 'Create project'
end
end
context 'creating a project label', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/27992' do
before do
page.within('.block.labels') do
click_link 'Create project'
end
end
it 'shows dropdown switches to "create label" section' do
page.within('.block.labels') do
expect(page).to have_content 'Create project label'
end
end
it 'adds new label' do
page.within('.block.labels') do
fill_in 'new_label_name', with: 'wontfix'
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
page.within('.dropdown-page-one') do
expect(page).to have_content 'wontfix'
end
end
end
it 'shows error message if label title is taken' do
page.within('.block.labels') do
fill_in 'new_label_name', with: label.title
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
page.within('.dropdown-page-two') do
expect(page).to have_content 'Title has already been taken'
end
end
end
end
end end
context 'interacting with collapsed sidebar', :js do context 'interacting with collapsed sidebar', :js do
......
import { GlLoadingIcon, GlLink } from '@gitlab/ui'; import { GlAlert, GlLoadingIcon, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue'; import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
...@@ -9,6 +9,7 @@ import { workspaceLabelsQueries } from '~/sidebar/constants'; ...@@ -9,6 +9,7 @@ import { workspaceLabelsQueries } from '~/sidebar/constants';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue'; import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue';
import createLabelMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql'; import createLabelMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql';
import { import {
mockRegularLabel,
mockSuggestedColors, mockSuggestedColors,
createLabelSuccessfulResponse, createLabelSuccessfulResponse,
workspaceLabelsQueryResponse, workspaceLabelsQueryResponse,
...@@ -25,8 +26,18 @@ const userRecoverableError = { ...@@ -25,8 +26,18 @@ const userRecoverableError = {
errors: ['Houston, we have a problem'], errors: ['Houston, we have a problem'],
}; };
const titleTakenError = {
data: {
labelCreate: {
label: mockRegularLabel,
errors: ['Title has already been taken'],
},
},
};
const createLabelSuccessHandler = jest.fn().mockResolvedValue(createLabelSuccessfulResponse); const createLabelSuccessHandler = jest.fn().mockResolvedValue(createLabelSuccessfulResponse);
const createLabelUserRecoverableErrorHandler = jest.fn().mockResolvedValue(userRecoverableError); const createLabelUserRecoverableErrorHandler = jest.fn().mockResolvedValue(userRecoverableError);
const createLabelDuplicateErrorHandler = jest.fn().mockResolvedValue(titleTakenError);
const createLabelErrorHandler = jest.fn().mockRejectedValue('Houston, we have a problem'); const createLabelErrorHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
describe('DropdownContentsCreateView', () => { describe('DropdownContentsCreateView', () => {
...@@ -208,4 +219,17 @@ describe('DropdownContentsCreateView', () => { ...@@ -208,4 +219,17 @@ describe('DropdownContentsCreateView', () => {
expect(createFlash).toHaveBeenCalled(); expect(createFlash).toHaveBeenCalled();
}); });
it('displays error in alert if label title is already taken', async () => {
createComponent({ mutationHandler: createLabelDuplicateErrorHandler });
fillLabelAttributes();
await nextTick();
findCreateButton().vm.$emit('click');
await waitForPromises();
expect(wrapper.findComponent(GlAlert).text()).toEqual(
titleTakenError.data.labelCreate.errors[0],
);
});
}); });
# frozen_string_literal: true
RSpec.shared_examples 'labels sidebar widget' do
context 'editing labels' do
let_it_be(:development) { create(:group_label, group: group, name: 'Development') }
let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
let_it_be(:xss_label) { create(:label, project: project, title: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
let(:labels_widget) { find('[data-testid="sidebar-labels"]') }
before do
page.within(labels_widget) do
click_on 'Edit'
end
wait_for_all_requests
end
it 'shows labels list in the dropdown' do
expect(labels_widget.find('.gl-new-dropdown-contents')).to have_selector('li.gl-new-dropdown-item', count: 4)
end
it 'adds a label' do
within(labels_widget) do
adds_label(stretch)
page.within('[data-testid="value-wrapper"]') do
expect(page).to have_content(stretch.name)
end
end
end
it 'removes a label' do
within(labels_widget) do
adds_label(stretch)
page.within('[data-testid="value-wrapper"]') do
expect(page).to have_content(stretch.name)
end
click_on 'Remove label'
wait_for_requests
page.within('[data-testid="value-wrapper"]') do
expect(page).not_to have_content(stretch.name)
end
end
end
it 'escapes XSS when viewing issuable labels' do
page.within(labels_widget) do
expect(page).to have_content '<script>alert("xss");</script>'
end
end
it 'shows option to create a label' do
page.within(labels_widget) do
expect(page).to have_content 'Create'
end
end
context 'creating a label', :js do
before do
page.within(labels_widget) do
page.find('[data-testid="create-label-button"]').click
end
end
it 'shows dropdown switches to "create label" section' do
page.within(labels_widget) do
expect(page.find('[data-testid="dropdown-header"]')).to have_content 'Create'
end
end
it 'creates new label' do
page.within(labels_widget) do
fill_in 'Name new label', with: 'wontfix'
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
wait_for_requests
expect(page).to have_content 'wontfix'
end
end
it 'shows error message if label title is taken' do
page.within(labels_widget) do
fill_in 'Name new label', with: development.title
page.find('.suggest-colors a', match: :first).click
page.find('button', text: 'Create').click
wait_for_requests
page.within('.dropdown-input') do
expect(page.find('.gl-alert')).to have_content 'Title'
end
end
end
end
end
def adds_label(label)
click_button label.name
click_button 'Close'
wait_for_requests
end
end
...@@ -50,6 +50,10 @@ RSpec.shared_examples 'issue boards sidebar' do ...@@ -50,6 +50,10 @@ RSpec.shared_examples 'issue boards sidebar' do
it_behaves_like 'date sidebar widget' it_behaves_like 'date sidebar widget'
end end
context 'editing issue labels', :js do
it_behaves_like 'labels sidebar widget'
end
context 'in notifications subscription' do context 'in notifications subscription' do
it 'displays notifications toggle', :aggregate_failures do it 'displays notifications toggle', :aggregate_failures do
page.within('[data-testid="sidebar-notifications"]') do page.within('[data-testid="sidebar-notifications"]') do
......
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