From 9b361a3f44eec7a301565318ce86742f2f139a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 23 Sep 2016 15:16:11 +0200 Subject: [PATCH] Take filters in account in issuable counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- CHANGELOG | 1 + app/finders/issuable_finder.rb | 15 +- app/helpers/application_helper.rb | 19 +-- app/views/shared/issuable/_nav.html.haml | 20 +-- spec/features/dashboard_issues_spec.rb | 15 ++ spec/features/issues/filter_by_labels_spec.rb | 141 +++++------------- spec/features/issues/filter_issues_spec.rb | 56 ++++++- .../filter_by_milestone_spec.rb | 15 ++ 8 files changed, 145 insertions(+), 137 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1eb7ea15756..9d0fd2526ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ v 8.13.0 (unreleased) - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) - Use a ConnectionPool for Rails.cache on Sidekiq servers - Only update issuable labels if they have been changed + - Take filters in account in issuable counters. !6496 - Revoke button in Applications Settings underlines on hover. - Fix Long commit messages overflow viewport in file tree - Update ruby-prof to 0.16.2. !6026 (Elan Ruusamäe) diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 8f9ef8f725c..9f170428100 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -183,17 +183,12 @@ class IssuableFinder end def by_state(items) - case params[:state] - when 'closed' - items.closed - when 'merged' - items.respond_to?(:merged) ? items.merged : items.closed - when 'all' - items - when 'opened' - items.opened + params[:state] ||= 'all' + + if items.respond_to?(params[:state]) + items.public_send(params[:state]) else - raise 'You must specify default state' + items end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1df430e6279..bbc037288db 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -280,27 +280,24 @@ module ApplicationHelper end end - def state_filters_text_for(entity, project) + def issuables_state_counter_text(state, issuables) titles = { opened: "Open" } - entity_title = titles[entity] || entity.to_s.humanize + state_title = titles[state] || state.to_s.humanize count = - if project.nil? - nil - elsif current_controller?(:issues) - project.issues.visible_to_user(current_user).send(entity).count - elsif current_controller?(:merge_requests) - project.merge_requests.send(entity).count + if @issues || @merge_requests + issuables_finder = @issues ? issues_finder : merge_requests_finder + issuables_finder.params[:state] = state + issuables_finder.execute.page(1).total_count end - html = content_tag :span, entity_title + html = content_tag(:span, state_title) if count.present? - html += " " - html += content_tag :span, number_with_delimiter(count), class: 'badge' + html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge') end html.html_safe diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml index 1d9b09a5ef1..475b99a2a07 100644 --- a/app/views/shared/issuable/_nav.html.haml +++ b/app/views/shared/issuable/_nav.html.haml @@ -1,25 +1,25 @@ +- type = local_assigns.fetch(:type, :issues) +- page_context_word = type.to_s.humanize(capitalize: false) +- issuables = @issues || @merge_requests + %ul.nav-links.issues-state-filters - - if defined?(type) && type == :merge_requests - - page_context_word = 'merge requests' - - else - - page_context_word = 'issues' %li{class: ("active" if params[:state] == 'opened')} = link_to page_filter_path(state: 'opened', label: true), title: "Filter by #{page_context_word} that are currently opened." do - #{state_filters_text_for(:opened, @project)} + #{issuables_state_counter_text(:opened, issuables)} - - if defined?(type) && type == :merge_requests + - if type == :merge_requests %li{class: ("active" if params[:state] == 'merged')} = link_to page_filter_path(state: 'merged', label: true), title: 'Filter by merge requests that are currently merged.' do - #{state_filters_text_for(:merged, @project)} + #{issuables_state_counter_text(:merged, issuables)} %li{class: ("active" if params[:state] == 'closed')} = link_to page_filter_path(state: 'closed', label: true), title: 'Filter by merge requests that are currently closed and unmerged.' do - #{state_filters_text_for(:closed, @project)} + #{issuables_state_counter_text(:closed, issuables)} - else %li{class: ("active" if params[:state] == 'closed')} = link_to page_filter_path(state: 'closed', label: true), title: 'Filter by issues that are currently closed.' do - #{state_filters_text_for(:closed, @project)} + #{issuables_state_counter_text(:closed, issuables)} %li{class: ("active" if params[:state] == 'all')} = link_to page_filter_path(state: 'all', label: true), title: "Show all #{page_context_word}." do - #{state_filters_text_for(:all, @project)} + #{issuables_state_counter_text(:all, issuables)} diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 3fb1cb37544..4dccf645454 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -21,6 +21,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'No Milestone' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_selector('.issue', count: 1) end @@ -29,6 +34,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'Any Milestone' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end expect(page).to have_selector('.issue', count: 2) end @@ -39,6 +49,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link milestone.title end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_selector('.issue', count: 1) end end diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 908b18e5339..a615174c00e 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Issue filtering by Labels', feature: true do +feature 'Issue filtering by Labels', feature: true, js: true do include WaitForAjax let(:project) { create(:project, :public) } - let!(:user) { create(:user)} + let!(:user) { create(:user) } let!(:label) { create(:label, project: project) } before do @@ -28,156 +28,85 @@ feature 'Issue filtering by Labels', feature: true do visit namespace_project_issues_path(project.namespace, project) end - context 'filter by label bug', js: true do + context 'filter by label bug' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"bug\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('bug') end - it 'shows issue "Bugfix1" and "Bugfix2" in issues list' do + it 'apply the filter' do expect(page).to have_content "Bugfix1" expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1" in issues list' do expect(page).not_to have_content "Feature1" - end - - it 'shows label "bug" in filtered-labels' do expect(find('.filtered-labels')).to have_content "bug" - end - - it 'does not show label "feature" and "enhancement" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "feature" expect(find('.filtered-labels')).not_to have_content "enhancement" - end - it 'removes label "bug"' do find('.js-label-filter-remove').click wait_for_ajax expect(find('.filtered-labels', visible: false)).to have_no_content "bug" end end - context 'filter by label feature', js: true do + context 'filter by label feature' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"feature\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('feature') end - it 'shows issue "Feature1" in issues list' do + it 'applies the filter' do expect(page).to have_content "Feature1" - end - - it 'does not show "Bugfix1" and "Bugfix2" in issues list' do expect(page).not_to have_content "Bugfix2" expect(page).not_to have_content "Bugfix1" - end - - it 'shows label "feature" in filtered-labels' do expect(find('.filtered-labels')).to have_content "feature" - end - - it 'does not show label "bug" and "enhancement" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "bug" expect(find('.filtered-labels')).not_to have_content "enhancement" end end - context 'filter by label enhancement', js: true do + context 'filter by label enhancement' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('enhancement') end - it 'shows issue "Bugfix2" in issues list' do + it 'applies the filter' do expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1" and "Bugfix1" in issues list' do expect(page).not_to have_content "Feature1" expect(page).not_to have_content "Bugfix1" - end - - it 'shows label "enhancement" in filtered-labels' do expect(find('.filtered-labels')).to have_content "enhancement" - end - - it 'does not show label "feature" and "bug" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "bug" expect(find('.filtered-labels')).not_to have_content "feature" end end - context 'filter by label enhancement or feature', js: true do + context 'filter by label enhancement and bug in issues list' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - execute_script("$('.dropdown-menu-labels li:contains(\"feature\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('bug', 'enhancement') end - it 'does not show "Bugfix1" or "Feature1" in issues list' do - expect(page).not_to have_content "Bugfix1" - expect(page).not_to have_content "Feature1" - end - - it 'shows label "enhancement" and "feature" in filtered-labels' do - expect(find('.filtered-labels')).to have_content "enhancement" - expect(find('.filtered-labels')).to have_content "feature" - end - - it 'does not show label "bug" in filtered-labels' do - expect(find('.filtered-labels')).not_to have_content "bug" - end - - it 'removes label "enhancement"' do - find('.js-label-filter-remove', match: :first).click - wait_for_ajax - expect(find('.filtered-labels')).to have_no_content "enhancement" - end - end - - context 'filter by label enhancement and bug in issues list', js: true do - before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - execute_script("$('.dropdown-menu-labels li:contains(\"bug\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax - end - - it 'shows issue "Bugfix2" in issues list' do + it 'applies the filters' do + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1"' do expect(page).not_to have_content "Feature1" - end - - it 'shows label "bug" and "enhancement" in filtered-labels' do expect(find('.filtered-labels')).to have_content "bug" expect(find('.filtered-labels')).to have_content "enhancement" - end + expect(find('.filtered-labels')).not_to have_content "feature" - it 'does not show label "feature" in filtered-labels' do + find('.js-label-filter-remove', match: :first).click + wait_for_ajax + + expect(page).to have_content "Bugfix2" + expect(page).not_to have_content "Feature1" + expect(page).not_to have_content "Bugfix1" + expect(find('.filtered-labels')).not_to have_content "bug" + expect(find('.filtered-labels')).to have_content "enhancement" expect(find('.filtered-labels')).not_to have_content "feature" end end - context 'remove filtered labels', js: true do + context 'remove filtered labels' do before do page.within '.labels-filter' do click_button 'Label' @@ -200,7 +129,7 @@ feature 'Issue filtering by Labels', feature: true do end end - context 'dropdown filtering', js: true do + context 'dropdown filtering' do it 'filters by label name' do page.within '.labels-filter' do click_button 'Label' @@ -214,4 +143,14 @@ feature 'Issue filtering by Labels', feature: true do end end end + + def select_labels(*labels) + page.find('.js-label-select').click + wait_for_ajax + labels.each do |label| + execute_script("$('.dropdown-menu-labels li:contains(\"#{label}\") a').click()") + end + page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click + wait_for_ajax + end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index d1501c9791a..8fd67acff69 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -7,15 +7,15 @@ describe 'Filter issues', feature: true do let!(:user) { create(:user)} let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } - let!(:issue1) { create(:issue, project: project) } let!(:wontfix) { create(:label, project: project, title: "Won't fix") } before do project.team << [user, :master] login_as(user) + create(:issue, project: project) end - describe 'Filter issues for assignee from issues#index' do + describe 'for assignee from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -45,7 +45,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for milestone from issues#index' do + describe 'for milestone from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -75,7 +75,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for label from issues#index', js: true do + describe 'for label from issues#index', js: true do before do visit namespace_project_issues_path(project.namespace, project) find('.js-label-select').click @@ -115,6 +115,7 @@ describe 'Filter issues', feature: true do expect(page).to have_content wontfix.title click_link wontfix.title end + expect(find('.js-label-select .dropdown-toggle-text')).to have_content(wontfix.title) end @@ -146,7 +147,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for assignee and label from issues#index' do + describe 'for assignee and label from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -226,6 +227,11 @@ describe 'Filter issues', feature: true do it 'filters by text and label' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -236,6 +242,11 @@ describe 'Filter issues', feature: true do end find('.dropdown-menu-close-icon').click + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -244,6 +255,11 @@ describe 'Filter issues', feature: true do it 'filters by text and milestone' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -253,6 +269,11 @@ describe 'Filter issues', feature: true do click_link '8' end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -261,6 +282,11 @@ describe 'Filter issues', feature: true do it 'filters by text and assignee' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -270,6 +296,11 @@ describe 'Filter issues', feature: true do click_link user.name end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -278,6 +309,11 @@ describe 'Filter issues', feature: true do it 'filters by text and author' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -287,6 +323,11 @@ describe 'Filter issues', feature: true do click_link user.name end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -315,6 +356,11 @@ describe 'Filter issues', feature: true do find('.dropdown-menu-close-icon').click wait_for_ajax + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb index bb0bb590a46..3d5d9614fb6 100644 --- a/spec/features/merge_requests/filter_by_milestone_spec.rb +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -17,6 +17,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::None.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end @@ -39,6 +44,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::Upcoming.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end @@ -61,6 +71,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(milestone.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end