Shave spec/features/issues/filtered_search/dropdown_label_spec.rb from 10 minutes to 1.5 minutes

- Don't use `sleep` (most of the time was wasted by that)
- Expect some elements to be visible instead: capybara is smart enough
  to retry a few times if it cannot find an element
- See
  https://github.com/teamcapybara/capybara#asynchronous-javascript-ajax-and-friends
- Don't create unneccessary DB records
- Group some examples together to shave some setup time (where it makes
  sense)

Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
Rémy Coutable 2017-02-01 17:53:41 +01:00
parent ee59a64b20
commit 7bff17eb75
2 changed files with 128 additions and 109 deletions

View File

@ -1,39 +1,47 @@
require 'rails_helper' require 'spec_helper'
describe 'Dropdown label', js: true, feature: true do describe 'Dropdown label', js: true, feature: true do
include WaitForAjax let(:project) { create(:empty_project) }
let(:user) { create(:user) }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_label) { '#js-dropdown-label' }
let(:filter_dropdown) { find("#{js_dropdown_label} .filter-dropdown") }
let!(:project) { create(:empty_project) } shared_context 'with labels' do
let!(:user) { create(:user) } let!(:bug_label) { create(:label, project: project, title: 'bug-label') }
let!(:bug_label) { create(:label, project: project, title: 'bug') } let!(:uppercase_label) { create(:label, project: project, title: 'BUG-LABEL') }
let!(:uppercase_label) { create(:label, project: project, title: 'BUG') }
let!(:two_words_label) { create(:label, project: project, title: 'High Priority') } let!(:two_words_label) { create(:label, project: project, title: 'High Priority') }
let!(:wont_fix_label) { create(:label, project: project, title: 'Won"t Fix') } let!(:wont_fix_label) { create(:label, project: project, title: 'Won"t Fix') }
let!(:wont_fix_single_label) { create(:label, project: project, title: 'Won\'t Fix') } let!(:wont_fix_single_label) { create(:label, project: project, title: 'Won\'t Fix') }
let!(:special_label) { create(:label, project: project, title: '!@#$%^+&*()') } let!(:special_label) { create(:label, project: project, title: '!@#$%^+&*()') }
let!(:long_label) { create(:label, project: project, title: 'this is a very long title this is a very long title this is a very long title this is a very long title this is a very long title') } let!(:long_label) { create(:label, project: project, title: 'this is a very long title this is a very long title this is a very long title this is a very long title this is a very long title') }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_label) { '#js-dropdown-label' }
def send_keys_to_filtered_search(input)
input.split("").each do |i|
filtered_search.send_keys(i)
sleep 3
wait_for_ajax
sleep 3
end
end end
def dropdown_label_size def init_label_search
page.all('#js-dropdown-label .filter-dropdown .filter-dropdown-item').size filtered_search.set('label:')
# This ensures the dropdown is shown
expect(find(js_dropdown_label)).not_to have_css('.filter-dropdown-loading')
end
def search_for_label(label)
init_label_search
filtered_search.send_keys(label)
end end
def click_label(text) def click_label(text)
find('#js-dropdown-label .filter-dropdown .filter-dropdown-item', text: text).click filter_dropdown.find('.filter-dropdown-item', text: text).click
end
def dropdown_label_size
filter_dropdown.all('.filter-dropdown-item').size
end
def clear_search_field
find('.filtered-search-input-container .clear-search').click
end end
before do before do
project.team << [user, :master] project.add_master(user)
login_as(user) login_as(user)
create(:issue, project: project) create(:issue, project: project)
@ -42,11 +50,12 @@ describe 'Dropdown label', js: true, feature: true do
describe 'keyboard navigation' do describe 'keyboard navigation' do
it 'selects label' do it 'selects label' do
send_keys_to_filtered_search('label:') bug_label = create(:label, project: project, title: 'bug-label')
init_label_search
filtered_search.native.send_keys(:down, :down, :enter) filtered_search.native.send_keys(:down, :down, :enter)
expect(filtered_search.value).to eq("label:~#{special_label.name} ") expect(filtered_search.value).to eq("label:~#{bug_label.title} ")
end end
end end
@ -54,171 +63,177 @@ describe 'Dropdown label', js: true, feature: true do
it 'opens when the search bar has label:' do it 'opens when the search bar has label:' do
filtered_search.set('label:') filtered_search.set('label:')
expect(page).to have_css(js_dropdown_label, visible: true) expect(page).to have_css(js_dropdown_label)
end end
it 'closes when the search bar is unfocused' do it 'closes when the search bar is unfocused' do
find('body').click() find('body').click
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
end end
it 'should show loading indicator when opened' do it 'shows loading indicator when opened and hides it when loaded' do
filtered_search.set('label:') filtered_search.set('label:')
expect(page).to have_css('#js-dropdown-label .filter-dropdown-loading', visible: true) expect(find(js_dropdown_label)).to have_css('.filter-dropdown-loading')
expect(find(js_dropdown_label)).not_to have_css('.filter-dropdown-loading')
end end
it 'should hide loading indicator when loaded' do it 'loads all the labels when opened' do
send_keys_to_filtered_search('label:') bug_label = create(:label, project: project, title: 'bug-label')
filtered_search.set('label:')
expect(page).not_to have_css('#js-dropdown-label .filter-dropdown-loading') expect(filter_dropdown).to have_content(bug_label.title)
end expect(dropdown_label_size).to eq(1)
it 'should load all the labels when opened' do
send_keys_to_filtered_search('label:')
expect(dropdown_label_size).to be > 0
end end
end end
describe 'filtering' do describe 'filtering' do
include_context 'with labels'
before do before do
filtered_search.set('label') init_label_search
end end
it 'filters by name' do it 'filters by case-insensitive name with or without symbol' do
send_keys_to_filtered_search(':b') search_for_label('b')
expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
expect(dropdown_label_size).to eq(2)
clear_search_field
init_label_search
search_for_label('~bu')
expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
expect(dropdown_label_size).to eq(2) expect(dropdown_label_size).to eq(2)
end end
it 'filters by case insensitive name' do it 'filters by multiple words with or without symbol' do
send_keys_to_filtered_search(':B') filtered_search.send_keys('Hig')
expect(dropdown_label_size).to eq(2) expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
end expect(dropdown_label_size).to eq(1)
it 'filters by name with symbol' do clear_search_field
send_keys_to_filtered_search(':~bu') init_label_search
expect(dropdown_label_size).to eq(2) filtered_search.send_keys('~Hig')
end
it 'filters by case insensitive name with symbol' do
send_keys_to_filtered_search(':~BU')
expect(dropdown_label_size).to eq(2)
end
it 'filters by multiple words' do
send_keys_to_filtered_search(':Hig')
expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
expect(dropdown_label_size).to eq(1) expect(dropdown_label_size).to eq(1)
end end
it 'filters by multiple words with symbol' do it 'filters by multiple words containing single quotes with or without symbol' do
send_keys_to_filtered_search(':~Hig') filtered_search.send_keys('won\'t')
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
expect(dropdown_label_size).to eq(1)
clear_search_field
init_label_search
filtered_search.send_keys('~won\'t')
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
expect(dropdown_label_size).to eq(1) expect(dropdown_label_size).to eq(1)
end end
it 'filters by multiple words containing single quotes' do it 'filters by multiple words containing double quotes with or without symbol' do
send_keys_to_filtered_search(':won\'t') filtered_search.send_keys('won"t')
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
expect(dropdown_label_size).to eq(1)
clear_search_field
init_label_search
filtered_search.send_keys('~won"t')
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
expect(dropdown_label_size).to eq(1) expect(dropdown_label_size).to eq(1)
end end
it 'filters by multiple words containing single quotes with symbol' do it 'filters by special characters with or without symbol' do
send_keys_to_filtered_search(':~won\'t') filtered_search.send_keys('^+')
expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
expect(dropdown_label_size).to eq(1) expect(dropdown_label_size).to eq(1)
end
it 'filters by multiple words containing double quotes' do clear_search_field
send_keys_to_filtered_search(':won"t') init_label_search
expect(dropdown_label_size).to eq(1) filtered_search.send_keys('~^+')
end
it 'filters by multiple words containing double quotes with symbol' do
send_keys_to_filtered_search(':~won"t')
expect(dropdown_label_size).to eq(1)
end
it 'filters by special characters' do
send_keys_to_filtered_search(':^+')
expect(dropdown_label_size).to eq(1)
end
it 'filters by special characters with symbol' do
send_keys_to_filtered_search(':~^+')
expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
expect(dropdown_label_size).to eq(1) expect(dropdown_label_size).to eq(1)
end end
end end
describe 'selecting from dropdown' do describe 'selecting from dropdown' do
include_context 'with labels'
before do before do
filtered_search.set('label:') init_label_search
end end
it 'fills in the label name when the label has not been filled' do it 'fills in the label name when the label has not been filled' do
click_label(bug_label.title) click_label(bug_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~#{bug_label.title} ") expect(filtered_search.value).to eq("label:~#{bug_label.title} ")
end end
it 'fills in the label name when the label is partially filled' do it 'fills in the label name when the label is partially filled' do
send_keys_to_filtered_search('bu') filtered_search.send_keys('bu')
click_label(bug_label.title) click_label(bug_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~#{bug_label.title} ") expect(filtered_search.value).to eq("label:~#{bug_label.title} ")
end end
it 'fills in the label name that contains multiple words' do it 'fills in the label name that contains multiple words' do
click_label(two_words_label.title) click_label(two_words_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~\"#{two_words_label.title}\" ") expect(filtered_search.value).to eq("label:~\"#{two_words_label.title}\" ")
end end
it 'fills in the label name that contains multiple words and is very long' do it 'fills in the label name that contains multiple words and is very long' do
click_label(long_label.title) click_label(long_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~\"#{long_label.title}\" ") expect(filtered_search.value).to eq("label:~\"#{long_label.title}\" ")
end end
it 'fills in the label name that contains double quotes' do it 'fills in the label name that contains double quotes' do
click_label(wont_fix_label.title) click_label(wont_fix_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~'#{wont_fix_label.title}' ") expect(filtered_search.value).to eq("label:~'#{wont_fix_label.title}' ")
end end
it 'fills in the label name with the correct capitalization' do it 'fills in the label name with the correct capitalization' do
click_label(uppercase_label.title) click_label(uppercase_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~#{uppercase_label.title} ") expect(filtered_search.value).to eq("label:~#{uppercase_label.title} ")
end end
it 'fills in the label name with special characters' do it 'fills in the label name with special characters' do
click_label(special_label.title) click_label(special_label.title)
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:~#{special_label.title} ") expect(filtered_search.value).to eq("label:~#{special_label.title} ")
end end
it 'selects `no label`' do it 'selects `no label`' do
find('#js-dropdown-label .filter-dropdown-item', text: 'No Label').click find("#{js_dropdown_label} .filter-dropdown-item", text: 'No Label').click
expect(page).to have_css(js_dropdown_label, visible: false) expect(page).not_to have_css(js_dropdown_label)
expect(filtered_search.value).to eq("label:none ") expect(filtered_search.value).to eq("label:none ")
end end
end end
@ -226,44 +241,47 @@ describe 'Dropdown label', js: true, feature: true do
describe 'input has existing content' do describe 'input has existing content' do
it 'opens label dropdown with existing search term' do it 'opens label dropdown with existing search term' do
filtered_search.set('searchTerm label:') filtered_search.set('searchTerm label:')
expect(page).to have_css(js_dropdown_label, visible: true)
expect(page).to have_css(js_dropdown_label)
end end
it 'opens label dropdown with existing author' do it 'opens label dropdown with existing author' do
filtered_search.set('author:@person label:') filtered_search.set('author:@person label:')
expect(page).to have_css(js_dropdown_label, visible: true)
expect(page).to have_css(js_dropdown_label)
end end
it 'opens label dropdown with existing assignee' do it 'opens label dropdown with existing assignee' do
filtered_search.set('assignee:@person label:') filtered_search.set('assignee:@person label:')
expect(page).to have_css(js_dropdown_label, visible: true)
expect(page).to have_css(js_dropdown_label)
end end
it 'opens label dropdown with existing label' do it 'opens label dropdown with existing label' do
filtered_search.set('label:~urgent label:') filtered_search.set('label:~urgent label:')
expect(page).to have_css(js_dropdown_label, visible: true)
expect(page).to have_css(js_dropdown_label)
end end
it 'opens label dropdown with existing milestone' do it 'opens label dropdown with existing milestone' do
filtered_search.set('milestone:%v2.0 label:') filtered_search.set('milestone:%v2.0 label:')
expect(page).to have_css(js_dropdown_label, visible: true)
expect(page).to have_css(js_dropdown_label)
end end
end end
describe 'caching requests' do describe 'caching requests' do
it 'caches requests after the first load' do it 'caches requests after the first load' do
filtered_search.set('label') create(:label, project: project, title: 'bug-label')
send_keys_to_filtered_search(':') init_label_search
initial_size = dropdown_label_size
expect(initial_size).to be > 0 expect(dropdown_label_size).to eq(1)
create(:label, project: project) create(:label, project: project)
find('.filtered-search-input-container .clear-search').click clear_search_field
filtered_search.set('label') init_label_search
send_keys_to_filtered_search(':')
expect(dropdown_label_size).to eq(initial_size) expect(dropdown_label_size).to eq(1)
end end
end end
end end

View File

@ -35,6 +35,7 @@ RSpec.configure do |config|
config.include Warden::Test::Helpers, type: :request config.include Warden::Test::Helpers, type: :request
config.include LoginHelpers, type: :feature config.include LoginHelpers, type: :feature
config.include SearchHelpers, type: :feature config.include SearchHelpers, type: :feature
config.include WaitForAjax, type: :feature
config.include StubConfiguration config.include StubConfiguration
config.include EmailHelpers, type: :mailer config.include EmailHelpers, type: :mailer
config.include TestEnv config.include TestEnv