Commit 1c00984e authored by Peter Hegman's avatar Peter Hegman

Merge branch '347496-consolidate-rspec-test-labels-sidebar' into 'master'

Consolidate labels sidebar rspec tests [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!76905
parents c7da9ac4 c83cde68
...@@ -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