Skip to content
Snippets Groups Projects
Commit 0572854f authored by Tiffany Rea's avatar Tiffany Rea
Browse files

Merge branch 'cngo-update-issues-list-feature-specs' into 'master'

Update feature specs for vue_issues_list (part 4)

See merge request !86059
parents d5f462af b8c0436c
No related branches found
No related tags found
1 merge request!86059Update feature specs for vue_issues_list (part 4)
Pipeline #527414303 passed
......@@ -4,7 +4,6 @@
RSpec.describe 'Recent searches', :js do
include FilteredSearchHelpers
include MobileHelpers
let_it_be(:project_1) { create(:project, :public) }
let_it_be(:project_2) { create(:project, :public) }
......@@ -14,116 +13,96 @@
let(:project_1_local_storage_key) { "#{project_1.full_path}-issue-recent-searches" }
before do
Capybara.ignore_hidden_elements = false
stub_feature_flags(vue_issues_list: true)
# Visit any fast-loading page so we can clear local storage without a DOM exception
visit '/404'
remove_recent_searches
end
after do
Capybara.ignore_hidden_elements = true
end
it 'searching adds to recent searches' do
visit project_issues_path(project_1)
input_filtered_search('foo', submit: true)
input_filtered_search('bar', submit: true)
items = all('.filtered-search-history-dropdown-item', visible: false, count: 2)
submit_then_clear_search 'foo'
submit_then_clear_search 'bar'
click_button 'Toggle history'
expect(items[0].text).to eq('bar')
expect(items[1].text).to eq('foo')
expect_recent_searches_history_item 'bar'
expect_recent_searches_history_item 'foo'
end
it 'visiting URL with search params adds to recent searches' do
visit project_issues_path(project_1, label_name: 'foo', search: 'bar')
visit project_issues_path(project_1, label_name: 'qux', search: 'garply')
items = all('.filtered-search-history-dropdown-item', visible: false, count: 2)
click_button 'Toggle history'
expect(items[0].text).to eq('label: = ~qux garply')
expect(items[1].text).to eq('label: = ~foo bar')
expect_recent_searches_history_item 'Label := qux garply'
expect_recent_searches_history_item 'Label := foo bar'
end
it 'saved recent searches are restored last on the list' do
set_recent_searches(project_1_local_storage_key, '["saved1", "saved2"]')
set_recent_searches(project_1_local_storage_key, '[[{"type":"filtered-search-term","value":{"data":"saved1"}}],[{"type":"filtered-search-term","value":{"data":"saved2"}}]]')
visit project_issues_path(project_1, search: 'foo')
click_button 'Toggle history'
items = all('.filtered-search-history-dropdown-item', visible: false, count: 3)
expect(items[0].text).to eq('foo')
expect(items[1].text).to eq('saved1')
expect(items[2].text).to eq('saved2')
expect_recent_searches_history_item 'foo'
expect_recent_searches_history_item 'saved1'
expect_recent_searches_history_item 'saved2'
end
it 'searches are scoped to projects' do
visit project_issues_path(project_1)
input_filtered_search('foo', submit: true)
input_filtered_search('bar', submit: true)
submit_then_clear_search 'foo'
submit_then_clear_search 'bar'
visit project_issues_path(project_2)
input_filtered_search('more', submit: true)
input_filtered_search('things', submit: true)
items = all('.filtered-search-history-dropdown-item', visible: false, count: 2)
submit_then_clear_search 'more'
submit_then_clear_search 'things'
click_button 'Toggle history'
expect(items[0].text).to eq('things')
expect(items[1].text).to eq('more')
expect_recent_searches_history_item 'things'
expect_recent_searches_history_item 'more'
end
it 'clicking item fills search input' do
set_recent_searches(project_1_local_storage_key, '["foo", "bar"]')
set_recent_searches(project_1_local_storage_key, '[[{"type":"filtered-search-term","value":{"data":"foo"}}],[{"type":"filtered-search-term","value":{"data":"bar"}}]]')
visit project_issues_path(project_1)
find('.filtered-search-history-dropdown-toggle-button').click
all('.filtered-search-history-dropdown-item', count: 2)[0].click
wait_for_filtered_search('foo')
click_button 'Toggle history'
click_button 'foo'
expect(find('.filtered-search').value.strip).to eq('foo')
expect_search_term 'foo'
end
it 'clear recent searches button, clears recent searches' do
set_recent_searches(project_1_local_storage_key, '["foo"]')
set_recent_searches(project_1_local_storage_key, '[[{"type":"filtered-search-term","value":{"data":"foo"}}]]')
visit project_issues_path(project_1)
find('.filtered-search-history-dropdown-toggle-button').click
all('.filtered-search-history-dropdown-item', count: 1)
click_button 'Toggle history'
find('.filtered-search-history-clear-button').click
items_after = all('.filtered-search-history-dropdown-item', count: 0)
expect_recent_searches_history_item_count 1
expect(items_after.count).to eq(0)
click_button 'Clear recent searches'
click_button 'Toggle history'
expect(page).to have_text "You don't have any recent searches"
expect_recent_searches_history_item_count 0
end
it 'shows flash error when failed to parse saved history' do
set_recent_searches(project_1_local_storage_key, 'fail')
visit project_issues_path(project_1)
expect(find('[data-testid="alert-danger"]')).to have_text('An error occurred while parsing recent searches')
expect(page).to have_text 'An error occurred while parsing recent searches'
end
context 'on tablet/mobile screen' do
it 'shows only the history icon in the dropdown' do
resize_screen_sm
visit project_issues_path(project_1)
expect(find('.filtered-search-history-dropdown-wrapper')).to have_selector('svg', visible: true)
expect(find('.filtered-search-history-dropdown-wrapper')).to have_selector('span', text: 'Recent searches', visible: false)
end
end
context 'on PC screen' do
it 'shows only the Recent searches text in the dropdown' do
restore_window_size
visit project_issues_path(project_1)
expect(find('.filtered-search-history-dropdown-wrapper')).to have_selector('svg', visible: false)
expect(find('.filtered-search-history-dropdown-wrapper')).to have_selector('span', text: 'Recent searches', visible: true)
end
def submit_then_clear_search(search)
click_filtered_search_bar
send_keys(search, :enter)
click_button 'Clear'
end
end
......@@ -9,102 +9,74 @@
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue, project: project) }
let(:filtered_search) { find('.filtered-search') }
before do
stub_feature_flags(vue_issues_list: true)
project.add_maintainer(user)
sign_in(user)
visit project_issues_path(project)
end
def get_left_style(style)
left_style = /left:\s\d*[.]\d*px/.match(style)
left_style.to_s.gsub('left: ', '').to_f
end
describe 'keyboard navigation' do
it 'makes item active' do
filtered_search.native.send_keys(:down)
page.within '#js-dropdown-hint' do
expect(page).to have_selector('.droplab-item-active')
end
end
it 'selects item' do
filtered_search.native.send_keys(:down, :down, :enter)
click_filtered_search_bar
send_keys :down, :enter
expect_tokens([{ name: 'Assignee' }])
expect_filtered_search_input_empty
expect_token_segment 'Assignee'
end
end
describe 'clear search button' do
it 'clears text' do
search_text = 'search_text'
filtered_search.set(search_text)
click_filtered_search_bar
send_keys search_text
expect(page).to have_field 'Search', with: search_text
expect(filtered_search.value).to eq(search_text)
find('.filtered-search-box .clear-search').click
click_button 'Clear'
expect(filtered_search.value).to eq('')
expect(page).to have_field 'Search', with: ''
end
it 'hides by default' do
expect(page).to have_css('.clear-search', visible: false)
expect(page).not_to have_button 'Clear'
end
it 'hides after clicked' do
filtered_search.set('a')
find('.filtered-search-box .clear-search').click
click_filtered_search_bar
send_keys 'a'
expect(page).to have_css('.clear-search', visible: false)
click_button 'Clear'
expect(page).not_to have_button 'Clear'
end
it 'hides when there is no text' do
filtered_search.set('a')
filtered_search.set('')
click_filtered_search_bar
send_keys 'a', :backspace, :backspace
expect(page).to have_css('.clear-search', visible: false)
expect(page).not_to have_button 'Clear'
end
it 'shows when there is text' do
filtered_search.set('a')
click_filtered_search_bar
send_keys 'a'
expect(page).to have_css('.clear-search', visible: true)
expect(page).to have_button 'Clear'
end
it 'resets the dropdown hint filter' do
filtered_search.click
original_size = page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size
filtered_search.set('autho')
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
find('.filtered-search-box .clear-search').click
filtered_search.click
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size)
end
it 'resets the dropdown filters' do
filtered_search.click
hint_offset = get_left_style(find('#js-dropdown-hint')['style'])
filtered_search.set('a')
filtered_search.set('author:')
click_filtered_search_bar
original_size = get_suggestion_count
send_keys 'autho'
find('#js-dropdown-hint', visible: false)
expect_suggestion_count 1
find('.filtered-search-box .clear-search').click
filtered_search.click
click_button 'Clear'
click_filtered_search_bar
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', minimum: 6)
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
expect_suggestion_count(original_size)
end
end
end
......@@ -14,178 +14,160 @@
let_it_be(:cc_label) { create(:label, project: project, title: 'Community Contribution') }
let_it_be(:issue) { create(:issue, project: project) }
let(:filtered_search) { find('.filtered-search') }
let(:filter_author_dropdown) { find("#js-dropdown-author .filter-dropdown") }
def is_input_focused
page.evaluate_script("document.activeElement.classList.contains('filtered-search')")
end
before do
stub_feature_flags(vue_issues_list: true)
project.add_user(user, :maintainer)
project.add_user(user_rock, :maintainer)
sign_in(user)
set_cookie('sidebar_collapsed', 'true')
visit project_issues_path(project)
end
describe 'editing a single token' do
before do
input_filtered_search('author:=@root assignee:=none', submit: false)
first('.tokens-container .filtered-search-token').click
wait_for_requests
select_tokens 'Author', '=', user.username, 'Assignee', '=', 'None'
click_token_segment(user.name)
end
it 'opens author dropdown' do
expect(page).to have_css('#js-dropdown-author', visible: true)
expect_filtered_search_input('@root')
expect_visible_suggestions_list
expect(page).to have_field('Search', with: 'root')
end
it 'filters value' do
filtered_search.send_keys(:backspace)
send_keys :backspace
expect(page).to have_css('#js-dropdown-author .filter-dropdown .filter-dropdown-item', count: 1)
expect_suggestion_count 1
end
it 'ends editing mode when document is clicked' do
find('.js-navbar').click
expect_filtered_search_input_empty
expect(page).to have_css('#js-dropdown-author', visible: false)
expect_empty_search_term
expect_hidden_suggestions_list
end
describe 'selecting different author from dropdown' do
before do
filter_author_dropdown.find('.filter-dropdown-item .dropdown-light-content', text: "@#{user_rock.username}").click
send_keys :backspace, :backspace, :backspace, :backspace
click_on user_rock.name
end
it 'changes value in visual token' do
wait_for_requests
expect(first('.tokens-container .filtered-search-token .value').text).to eq("#{user_rock.name}")
end
it 'moves input to the right' do
expect(is_input_focused).to eq(true)
expect_author_token(user_rock.name)
end
end
end
describe 'editing multiple tokens' do
before do
input_filtered_search('author:=@root assignee:=none', submit: false)
first('.tokens-container .filtered-search-token').click
select_tokens 'Author', '=', user.username, 'Assignee', '=', 'None'
click_token_segment(user.name)
end
it 'opens author dropdown' do
expect(page).to have_css('#js-dropdown-author', visible: true)
expect_visible_suggestions_list
end
it 'opens assignee dropdown' do
find('.tokens-container .filtered-search-token', text: 'Assignee').click
expect(page).to have_css('#js-dropdown-assignee', visible: true)
click_token_segment 'Assignee'
expect_visible_suggestions_list
end
end
describe 'editing a search term while editing another filter token' do
before do
input_filtered_search('foo assignee:=', submit: false)
first('.tokens-container .filtered-search-term').click
click_filtered_search_bar
send_keys 'foo '
select_tokens 'Assignee', '='
click_token_segment 'foo'
send_keys ' '
end
it 'opens author dropdown' do
find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: 'Author').click
click_on 'Author'
expect(page).to have_css('#js-dropdown-operator', visible: true)
expect(page).to have_css('#js-dropdown-author', visible: false)
expect_suggestion '='
expect_suggestion '!='
find('#js-dropdown-operator .filter-dropdown .filter-dropdown-item[data-value="="]').click
click_on '= is'
expect(page).to have_css('#js-dropdown-operator', visible: false)
expect(page).to have_css('#js-dropdown-author', visible: true)
expect_suggestion(user.name)
expect_suggestion(user_rock.name)
end
end
describe 'add new token after editing existing token' do
before do
input_filtered_search('author:=@root assignee:=none', submit: false)
first('.tokens-container .filtered-search-token').click
filtered_search.send_keys(' ')
select_tokens 'Assignee', '=', user.username, 'Label', '=', 'None'
click_token_segment(user.name)
send_keys ' '
end
describe 'opens dropdowns' do
it 'opens hint dropdown' do
expect(page).to have_css('#js-dropdown-hint', visible: true)
expect_visible_suggestions_list
end
it 'opens token dropdown' do
filtered_search.send_keys('author:=')
click_on 'Author'
expect(page).to have_css('#js-dropdown-author', visible: true)
expect_visible_suggestions_list
end
end
describe 'visual tokens' do
it 'creates visual token' do
filtered_search.send_keys('author:=@thomas ')
token = page.all('.tokens-container .filtered-search-token')[1]
click_on 'Author'
click_on '= is'
click_on 'The Rock'
expect(token.find('.name').text).to eq('Author')
expect(token.find('.value').text).to eq('@thomas')
expect_author_token 'The Rock'
end
end
it 'does not tokenize incomplete token' do
filtered_search.send_keys('author:=')
click_on 'Author'
find('.js-navbar').click
token = page.all('.tokens-container .js-visual-token')[1]
expect_filtered_search_input_empty
expect(token.find('.name').text).to eq('Author')
expect_empty_search_term
expect_token_segment 'Assignee'
end
end
describe 'search using incomplete visual tokens' do
before do
input_filtered_search('author:=@root assignee:=none', extra_space: false)
select_tokens 'Author', '=', user.username, 'Assignee', '=', 'None'
end
it 'tokenizes the search term to complete visual token' do
expect_tokens([
author_token(user.name),
assignee_token('None')
])
expect_author_token(user.name)
expect_assignee_token 'None'
end
end
it 'does retain hint token when mix of typing and clicks are performed' do
input_filtered_search('label:', extra_space: false, submit: false)
expect(page).to have_css('#js-dropdown-operator', visible: true)
find('#js-dropdown-operator li[data-value="="]').click
token = page.all('.tokens-container .js-visual-token')[0]
select_tokens 'Label'
click_on '= is'
expect(token.find('.name').text).to eq('Label')
expect(token.find('.operator').text).to eq('=')
expect_token_segment 'Label'
expect_token_segment '='
end
describe 'Any/None option' do
it 'hidden when NOT operator is selected' do
input_filtered_search('milestone:!=', extra_space: false, submit: false)
select_tokens 'Milestone', '!='
expect(page).not_to have_selector("#js-dropdown-milestone", text: 'Any')
expect(page).not_to have_selector("#js-dropdown-milestone", text: 'None')
expect_no_suggestion 'Any'
expect_no_suggestion 'None'
end
it 'shown when EQUAL operator is selected' do
input_filtered_search('milestone:=', extra_space: false, submit: false)
select_tokens 'Milestone', '='
expect(page).to have_selector("#js-dropdown-milestone", text: 'Any')
expect(page).to have_selector("#js-dropdown-milestone", text: 'None')
expect_suggestion 'Any'
expect_suggestion 'None'
end
end
end
......@@ -221,6 +221,10 @@ def click_filtered_search_bar
find('.gl-filtered-search-last-item').click
end
def click_token_segment(value)
find('.gl-filtered-search-token-segment', text: value).click
end
def expect_visible_suggestions_list
expect(page).to have_css('.gl-filtered-search-suggestion-list')
end
......@@ -233,6 +237,10 @@ def expect_suggestion(value)
expect(page).to have_css('.gl-filtered-search-suggestion', text: value)
end
def expect_no_suggestion(value)
expect(page).not_to have_css('.gl-filtered-search-suggestion', text: value)
end
def expect_suggestion_count(count)
expect(page).to have_css('.gl-filtered-search-suggestion', count: count)
end
......@@ -245,6 +253,12 @@ def expect_author_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Author = #{value}"
end
def expect_search_term(value)
value.split(' ').each do |term|
expect(page).to have_css '.gl-filtered-search-term', text: term
end
end
def expect_empty_search_term
expect(page).to have_css '.gl-filtered-search-term', text: ''
end
......@@ -252,4 +266,12 @@ def expect_empty_search_term
def expect_token_segment(value)
expect(page).to have_css '.gl-filtered-search-token-segment', text: value
end
def expect_recent_searches_history_item(value)
expect(page).to have_css '.gl-search-box-by-click-history-item', text: value
end
def expect_recent_searches_history_item_count(count)
expect(page).to have_css '.gl-search-box-by-click-history-item', count: count
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment