Commit 78226340 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '337984-add-feature-specs-for-new-tokens' into 'master'

Add rspec tests for new filtered search tokens on boards

See merge request gitlab-org/gitlab!75315
parents 42994b87 7c53891e
......@@ -50,21 +50,21 @@ export default {
if (authorUsername) {
filteredSearchValue.push({
type: 'author_username',
type: 'author',
value: { data: authorUsername, operator: '=' },
});
}
if (assigneeUsername) {
filteredSearchValue.push({
type: 'assignee_username',
type: 'assignee',
value: { data: assigneeUsername, operator: '=' },
});
}
if (types) {
filteredSearchValue.push({
type: 'types',
type: 'type',
value: { data: types, operator: '=' },
});
}
......@@ -72,7 +72,7 @@ export default {
if (labelName?.length) {
filteredSearchValue.push(
...labelName.map((label) => ({
type: 'label_name',
type: 'label',
value: { data: label, operator: '=' },
})),
);
......@@ -101,7 +101,7 @@ export default {
if (myReactionEmoji) {
filteredSearchValue.push({
type: 'my_reaction_emoji',
type: 'my-reaction',
value: { data: myReactionEmoji, operator: '=' },
});
}
......@@ -115,14 +115,14 @@ export default {
if (epicId) {
filteredSearchValue.push({
type: 'epic_id',
type: 'epic',
value: { data: epicId, operator: '=' },
});
}
if (this.filterParams['not[authorUsername]']) {
filteredSearchValue.push({
type: 'author_username',
type: 'author',
value: { data: this.filterParams['not[authorUsername]'], operator: '!=' },
});
}
......@@ -150,7 +150,7 @@ export default {
if (this.filterParams['not[assigneeUsername]']) {
filteredSearchValue.push({
type: 'assignee_username',
type: 'assignee',
value: { data: this.filterParams['not[assigneeUsername]'], operator: '!=' },
});
}
......@@ -158,7 +158,7 @@ export default {
if (this.filterParams['not[labelName]']) {
filteredSearchValue.push(
...this.filterParams['not[labelName]'].map((label) => ({
type: 'label_name',
type: 'label',
value: { data: label, operator: '!=' },
})),
);
......@@ -166,21 +166,21 @@ export default {
if (this.filterParams['not[types]']) {
filteredSearchValue.push({
type: 'types',
type: 'type',
value: { data: this.filterParams['not[types]'], operator: '!=' },
});
}
if (this.filterParams['not[epicId]']) {
filteredSearchValue.push({
type: 'epic_id',
type: 'epic',
value: { data: this.filterParams['not[epicId]'], operator: '!=' },
});
}
if (this.filterParams['not[myReactionEmoji]']) {
filteredSearchValue.push({
type: 'my_reaction_emoji',
type: 'my-reaction',
value: { data: this.filterParams['not[myReactionEmoji]'], operator: '!=' },
});
}
......@@ -281,16 +281,16 @@ export default {
filters.forEach((filter) => {
switch (filter.type) {
case 'author_username':
case 'author':
filterParams.authorUsername = filter.value.data;
break;
case 'assignee_username':
case 'assignee':
filterParams.assigneeUsername = filter.value.data;
break;
case 'types':
case 'type':
filterParams.types = filter.value.data;
break;
case 'label_name':
case 'label':
labels.push(filter.value.data);
break;
case 'milestone':
......@@ -302,10 +302,10 @@ export default {
case 'weight':
filterParams.weight = filter.value.data;
break;
case 'epic_id':
case 'epic':
filterParams.epicId = filter.value.data;
break;
case 'my_reaction_emoji':
case 'my-reaction':
filterParams.myReactionEmoji = filter.value.data;
break;
case 'release':
......
......@@ -80,7 +80,7 @@ export default {
{
icon: 'user',
title: assignee,
type: 'assignee_username',
type: 'assignee',
operators: OPERATOR_IS_AND_IS_NOT,
token: AuthorToken,
unique: true,
......@@ -90,7 +90,7 @@ export default {
{
icon: 'pencil',
title: author,
type: 'author_username',
type: 'author',
operators: OPERATOR_IS_AND_IS_NOT,
symbol: '@',
token: AuthorToken,
......@@ -101,7 +101,7 @@ export default {
{
icon: 'labels',
title: label,
type: 'label_name',
type: 'label',
operators: OPERATOR_IS_AND_IS_NOT,
token: LabelToken,
unique: false,
......@@ -111,7 +111,7 @@ export default {
...(this.isSignedIn
? [
{
type: 'my_reaction_emoji',
type: 'my-reaction',
title: TOKEN_TITLE_MY_REACTION,
icon: 'thumb-up',
token: EmojiToken,
......@@ -146,7 +146,7 @@ export default {
{
icon: 'issues',
title: type,
type: 'types',
type: 'type',
token: GlFilteredSearchToken,
unique: true,
options: [
......
......@@ -4,6 +4,7 @@ import issueBoardFilter from '~/boards/issue_board_filters';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import { OPERATOR_IS_AND_IS_NOT } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
......@@ -12,8 +13,6 @@ export default {
search: __('Search'),
label: __('Label'),
author: __('Author'),
is: __('is'),
isNot: __('is not'),
},
components: { BoardFilteredSearch },
props: {
......@@ -34,16 +33,13 @@ export default {
this.boardType,
);
const { label, is, isNot, author } = this.$options.i18n;
const { label, author } = this.$options.i18n;
return [
{
icon: 'labels',
title: label,
type: 'label_name',
operators: [
{ value: '=', description: is },
{ value: '!=', description: isNot },
],
type: 'label',
operators: OPERATOR_IS_AND_IS_NOT,
token: LabelToken,
unique: false,
symbol: '~',
......@@ -53,11 +49,8 @@ export default {
{
icon: 'pencil',
title: author,
type: 'author_username',
operators: [
{ value: '=', description: is },
{ value: '!=', description: isNot },
],
type: 'author',
operators: OPERATOR_IS_AND_IS_NOT,
symbol: '@',
token: AuthorToken,
unique: true,
......
......@@ -36,7 +36,7 @@ export default {
return [
...this.tokensCE,
{
type: 'epic_id',
type: 'epic',
title: epic,
icon: 'epic',
token: EpicToken,
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Issue board filters', :js do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
let_it_be(:board) { create(:board, project: project) }
let_it_be(:epic) { create(:epic, group: group) }
let_it_be(:iteration) { create(:iteration, group: group) }
let_it_be(:issue) { create(:issue, project: project, weight: 2 ) }
let_it_be(:issue_2) { create(:issue, project: project, iteration: iteration, weight: 3) }
let_it_be(:epic_issue1) { create(:epic_issue, epic: epic, issue: issue, relative_position: 1) }
let(:filtered_search) { find('[data-testid="issue-board-filtered-search"]') }
let(:filter_input) { find('.gl-filtered-search-term-input')}
let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
let(:filter_submit) { find('.gl-search-box-by-click-search-button') }
before do
stub_feature_flags(issue_boards_filtered_search: true)
stub_licensed_features(epics: true, iterations: true)
project.add_maintainer(user)
sign_in(user)
visit_project_board
end
describe 'filters by epic' do
before do
set_filter('epic')
end
it 'loads all the epics when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 3)
click_on epic.title
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue.title)
end
end
describe 'filters by iteration' do
before do
set_filter('iteration')
end
it 'loads all the iterations when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 3)
click_on iteration.title
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue_2.title)
end
end
describe 'filters by weight' do
before do
set_filter('weight')
end
it 'loads all the weights when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 23)
filter_dropdown.click_on '2'
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue.title)
end
end
def set_filter(filter)
filter_input.click
filter_input.set("#{filter}:")
filter_first_suggestion.click # Select `=` operator
end
def expect_filtered_search_dropdown_results(filter_dropdown, count)
expect(filter_dropdown).to have_selector('.gl-new-dropdown-item', count: count)
end
def visit_project_board
visit project_board_path(project, board)
wait_for_requests
end
end
......@@ -45,7 +45,7 @@ describe('EpicFilteredSearch', () => {
{
icon: 'labels',
title: __('Label'),
type: 'label_name',
type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -58,7 +58,7 @@ describe('EpicFilteredSearch', () => {
{
icon: 'pencil',
title: __('Author'),
type: 'author_username',
type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......
......@@ -403,7 +403,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
{
icon: 'user',
title: __('Assignee'),
type: 'assignee_username',
type: 'assignee',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -416,7 +416,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
{
icon: 'pencil',
title: __('Author'),
type: 'author_username',
type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -430,7 +430,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
{
icon: 'labels',
title: __('Label'),
type: 'label_name',
type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -441,7 +441,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
fetchLabels,
},
{
type: 'my_reaction_emoji',
type: 'my-reaction',
icon: 'thumb-up',
title: 'My-Reaction',
unique: true,
......@@ -460,7 +460,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
{
icon: 'issues',
title: __('Type'),
type: 'types',
type: 'type',
token: GlFilteredSearchToken,
unique: true,
options: [
......@@ -476,7 +476,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
fetchReleases: expect.any(Function),
},
{
type: 'epic_id',
type: 'epic',
icon: 'epic',
title: 'Epic',
unique: true,
......
......@@ -6,14 +6,16 @@ RSpec.describe 'Issue board filters', :js do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let_it_be(:board) { create(:board, project: project) }
let_it_be(:project_label) { create(:label, project: project, title: 'Label') }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
let_it_be(:release) { create(:release, tag: 'v1.0', project: project, milestones: [milestone_1]) }
let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project, milestones: [milestone_2]) }
let_it_be(:issue) { create(:issue, project: project, milestone: milestone_1) }
let_it_be(:issue_2) { create(:issue, project: project, milestone: milestone_2) }
let_it_be(:issue_1) { create(:issue, project: project, milestone: milestone_1, author: user) }
let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label]) }
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
let(:filtered_search) { find('[data-testid="issue-board-filtered-search"]') }
let(:filtered_search) { find('[data-testid="issue_1-board-filtered-search"]') }
let(:filter_input) { find('.gl-filtered-search-term-input')}
let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
......@@ -28,6 +30,58 @@ RSpec.describe 'Issue board filters', :js do
visit_project_board
end
shared_examples 'loads all the users when opened' do
it 'and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 3)
click_on user.username
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue.title)
end
end
describe 'filters by assignee' do
before do
set_filter('assignee')
end
it_behaves_like 'loads all the users when opened' do
let(:issue) { issue_2 }
end
end
describe 'filters by author' do
before do
set_filter('author')
end
it_behaves_like 'loads all the users when opened' do
let(:issue) { issue_1 }
end
end
describe 'filters by label' do
before do
set_filter('label')
end
it 'loads all the labels when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 3)
filter_dropdown.click_on project_label.title
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue_2.title)
end
end
describe 'filters by releases' do
before do
set_filter('release')
......@@ -42,6 +96,7 @@ RSpec.describe 'Issue board filters', :js do
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue_1.title)
end
end
......@@ -68,6 +123,44 @@ RSpec.describe 'Issue board filters', :js do
end
end
describe 'filters by reaction emoji' do
before do
set_filter('my-reaction')
end
it 'loads all the emojis when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 3)
click_on 'thumbsup'
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue_1.title)
end
end
describe 'filters by type' do
let_it_be(:incident) { create(:incident, project: project)}
before do
set_filter('type')
end
it 'loads all the types when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 3)
expect_filtered_search_dropdown_results(filter_dropdown, 2)
click_on 'Incident'
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(incident.title)
end
end
def set_filter(filter)
filter_input.click
filter_input.set("#{filter}:")
......
......@@ -18,7 +18,7 @@ describe('BoardFilteredSearch', () => {
{
icon: 'labels',
title: __('Label'),
type: 'label_name',
type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -31,7 +31,7 @@ describe('BoardFilteredSearch', () => {
{
icon: 'pencil',
title: __('Author'),
type: 'author_username',
type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -97,7 +97,7 @@ describe('BoardFilteredSearch', () => {
createComponent({ props: { eeFilters: { labelName: ['label'] } } });
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
{ type: 'label_name', value: { data: 'label', operator: '=' } },
{ type: 'label', value: { data: 'label', operator: '=' } },
]);
});
});
......@@ -117,11 +117,11 @@ describe('BoardFilteredSearch', () => {
it('sets the url params to the correct results', async () => {
const mockFilters = [
{ type: 'author_username', value: { data: 'root', operator: '=' } },
{ type: 'label_name', value: { data: 'label', operator: '=' } },
{ type: 'label_name', value: { data: 'label2', operator: '=' } },
{ type: 'author', value: { data: 'root', operator: '=' } },
{ type: 'label', value: { data: 'label', operator: '=' } },
{ type: 'label', value: { data: 'label2', operator: '=' } },
{ type: 'milestone', value: { data: 'New Milestone', operator: '=' } },
{ type: 'types', value: { data: 'INCIDENT', operator: '=' } },
{ type: 'type', value: { data: 'INCIDENT', operator: '=' } },
{ type: 'weight', value: { data: '2', operator: '=' } },
{ type: 'iteration', value: { data: '3341', operator: '=' } },
{ type: 'release', value: { data: 'v1.0.0', operator: '=' } },
......@@ -147,8 +147,8 @@ describe('BoardFilteredSearch', () => {
it('passes the correct props to FilterSearchBar', () => {
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
{ type: 'author_username', value: { data: 'root', operator: '=' } },
{ type: 'label_name', value: { data: 'label', operator: '=' } },
{ type: 'author', value: { data: 'root', operator: '=' } },
{ type: 'label', value: { data: 'label', operator: '=' } },
]);
});
});
......
......@@ -544,7 +544,7 @@ export const mockMoveData = {
};
export const mockEmojiToken = {
type: 'my_reaction_emoji',
type: 'my-reaction',
icon: 'thumb-up',
title: 'My-Reaction',
unique: true,
......@@ -556,7 +556,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'user',
title: __('Assignee'),
type: 'assignee_username',
type: 'assignee',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -569,7 +569,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'pencil',
title: __('Author'),
type: 'author_username',
type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -583,7 +583,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'labels',
title: __('Label'),
type: 'label_name',
type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
......@@ -606,7 +606,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'issues',
title: __('Type'),
type: 'types',
type: 'type',
token: GlFilteredSearchToken,
unique: true,
options: [
......
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