diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2017-07-06 15:54:41 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2017-07-06 15:54:41 +0800 |
commit | ef7deb18df2b97734e98c22aff53608e4e098bc5 (patch) | |
tree | ab86b4ce8671b13673f86d002c3b2386a7dcf0e9 /spec/features/dashboard | |
parent | 6fe2b79656cca21f9f1cea504e5cbb58a51a05ab (diff) | |
parent | 7f500acb5f38f0ae5d4e2d51e27b6257e0800c3d (diff) | |
download | gitlab-ce-ef7deb18df2b97734e98c22aff53608e4e098bc5.tar.gz |
Merge remote-tracking branch 'upstream/master' into 33360-generate-kubeconfig
* upstream/master: (888 commits)
Fix Rubocop offense
Use a previous approach for cycle analytics dummy pipeline
Allow admin to disable all restricted visibility levels
Removes file_name_regex from Gitlab::Regex
Remove IIFEs around several javascript classes
Update CHANGELOG.md for 9.3.5
Add ProjectPathHelper cop
Create and use project path helpers that only need a project, no namespace
Handles realtime with 2 states for environments table
Revert "Merge branch '18000-remember-me-for-oauth-login' into 'master'"
Allow creation of files and directories with spaces in web UI
Disable Flipper memoizer in tests to avoid transient failures
Introduce cache policies for CI jobs
fix sidebar padding for full-width items (Time Tracking help)
Replace 'snippets/snippets.feature' spinach with rspec
Rename ci_config_file to ci_config_path
Add back Pipeline#ci_yaml_file_path due to all the troubles
Revert change to design. Go back to scrollable page
Fix cycle analytics tests by making pipeline valid
Fixes the column widths for the new navigation options in settings
...
Diffstat (limited to 'spec/features/dashboard')
22 files changed, 805 insertions, 62 deletions
diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb index ae750be4d4a..f7ddded10c1 100644 --- a/spec/features/dashboard/active_tab_spec.rb +++ b/spec/features/dashboard/active_tab_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' RSpec.describe 'Dashboard Active Tab', js: true, feature: true do before do - login_as :user + gitlab_sign_in :user end shared_examples 'page has active tab' do |title| diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb index 0764044260e..1e9cabe7850 100644 --- a/spec/features/dashboard/activity_spec.rb +++ b/spec/features/dashboard/activity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' RSpec.describe 'Dashboard Activity', feature: true do before do - login_as(create :user) + gitlab_sign_in(create :user) visit activity_dashboard_path end diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb index f33bcbb5318..a5ba3e7e3cf 100644 --- a/spec/features/dashboard/archived_projects_spec.rb +++ b/spec/features/dashboard/archived_projects_spec.rb @@ -9,7 +9,7 @@ RSpec.describe 'Dashboard Archived Project', feature: true do project.team << [user, :master] archived_project.team << [user, :master] - login_as(user) + gitlab_sign_in(user) visit dashboard_projects_path end diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb index 1793e323588..6931d0a840e 100644 --- a/spec/features/dashboard/datetime_on_tooltips_spec.rb +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -4,7 +4,7 @@ feature 'Tooltips on .timeago dates', feature: true, js: true do let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } let(:created_date) { Date.yesterday.to_time } - let(:expected_format) { created_date.strftime('%b %-d, %Y %l:%M%P') } + let(:expected_format) { created_date.in_time_zone.strftime('%b %-d, %Y %l:%M%P') } context 'on the activity tab' do before do @@ -13,7 +13,7 @@ feature 'Tooltips on .timeago dates', feature: true, js: true do Event.create( project: project, author_id: user.id, action: Event::JOINED, updated_at: created_date, created_at: created_date) - login_as user + gitlab_sign_in user visit user_path(user) wait_for_requests() @@ -30,7 +30,7 @@ feature 'Tooltips on .timeago dates', feature: true, js: true do project.team << [user, :master] create(:snippet, author: user, updated_at: created_date, created_at: created_date) - login_as user + gitlab_sign_in user visit user_snippets_path(user) wait_for_requests() diff --git a/spec/features/dashboard/group_spec.rb b/spec/features/dashboard/group_spec.rb index 8e20fdec8ad..2f7245950ec 100644 --- a/spec/features/dashboard/group_spec.rb +++ b/spec/features/dashboard/group_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' RSpec.describe 'Dashboard Group', feature: true do before do - login_as(:user) + gitlab_sign_in(:user) end it 'creates new group', js: true do diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb index 7eb254f8451..e520027bc38 100644 --- a/spec/features/dashboard/groups_list_spec.rb +++ b/spec/features/dashboard/groups_list_spec.rb @@ -10,7 +10,7 @@ describe 'Dashboard Groups page', js: true, feature: true do group.add_owner(user) nested_group.add_owner(user) - login_as(user) + gitlab_sign_in(user) visit dashboard_groups_path expect(page).to have_content(group.full_name) @@ -23,7 +23,7 @@ describe 'Dashboard Groups page', js: true, feature: true do group.add_owner(user) nested_group.add_owner(user) - login_as(user) + gitlab_sign_in(user) visit dashboard_groups_path end @@ -58,7 +58,7 @@ describe 'Dashboard Groups page', js: true, feature: true do group.add_owner(user) subgroup.add_owner(user) - login_as(user) + gitlab_sign_in(user) visit dashboard_groups_path end @@ -98,7 +98,7 @@ describe 'Dashboard Groups page', js: true, feature: true do allow(Kaminari.config).to receive(:default_per_page).and_return(1) - login_as(user) + gitlab_sign_in(user) visit dashboard_groups_path end diff --git a/spec/features/dashboard/help_spec.rb b/spec/features/dashboard/help_spec.rb index 2803f7ec62b..25b0f40c9cd 100644 --- a/spec/features/dashboard/help_spec.rb +++ b/spec/features/dashboard/help_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' RSpec.describe 'Dashboard Help', feature: true do before do - login_as(:user) + gitlab_sign_in(:user) end it 'renders correctly markdown' do diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb index 354267dbee7..8a8a20fd5b1 100644 --- a/spec/features/dashboard/issuables_counter_spec.rb +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -9,7 +9,7 @@ describe 'Navigation bar counter', feature: true, caching: true do before do issue.assignees = [user] merge_request.update(assignee: user) - login_as(user) + gitlab_sign_in(user) end it 'reflects dashboard issues count' do diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index 2cea6b1563e..a57962abbda 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'Dashboard Issues', feature: true do before do [project, project_with_issues_disabled].each { |project| project.team << [current_user, :master] } - login_as(current_user) + gitlab_sign_in(current_user) visit issues_dashboard_path(assignee_id: current_user.id) end @@ -59,6 +59,11 @@ RSpec.describe 'Dashboard Issues', feature: true do expect(page).to have_content(other_issue.title) end + it 'state filter tabs work' do + find('#state-closed').click + expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, scope: 'all', state: 'closed'), url: true) + end + it_behaves_like "it has an RSS button with current_user's RSS token" it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" end diff --git a/spec/features/dashboard/label_filter_spec.rb b/spec/features/dashboard/label_filter_spec.rb index 4cff12de854..88bbb9e75b9 100644 --- a/spec/features/dashboard/label_filter_spec.rb +++ b/spec/features/dashboard/label_filter_spec.rb @@ -11,7 +11,7 @@ describe 'Dashboard > label filter', feature: true, js: true do project.labels << label project2.labels << label2 - login_as(user) + gitlab_sign_in(user) visit issues_dashboard_path end diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb index bcb52f602b0..bb1fb5b3feb 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -1,18 +1,24 @@ require 'spec_helper' -describe 'Dashboard Merge Requests' do +feature 'Dashboard Merge Requests' do + include FilterItemSelectHelper + let(:current_user) { create :user } let(:project) { create(:empty_project) } - let(:project_with_merge_requests_disabled) { create(:empty_project, :merge_requests_disabled) } - before do - [project, project_with_merge_requests_disabled].each { |project| project.team << [current_user, :master] } + let(:public_project) { create(:empty_project, :public, :repository) } + let(:forked_project) { Projects::ForkService.new(public_project, current_user).execute } - login_as(current_user) + before do + project.add_master(current_user) + sign_in(current_user) end - describe 'new merge request dropdown' do + context 'new merge request dropdown' do + let(:project_with_disabled_merge_requests) { create(:empty_project, :merge_requests_disabled) } + before do + project_with_disabled_merge_requests.add_master(current_user) visit merge_requests_dashboard_path end @@ -21,26 +27,87 @@ describe 'Dashboard Merge Requests' do page.within('.select2-results') do expect(page).to have_content(project.name_with_namespace) - expect(page).not_to have_content(project_with_merge_requests_disabled.name_with_namespace) + expect(page).not_to have_content(project_with_disabled_merge_requests.name_with_namespace) end end end - it 'should show an empty state' do - visit merge_requests_dashboard_path(assignee_id: current_user.id) + context 'no merge requests exist' do + it 'shows an empty state' do + visit merge_requests_dashboard_path(assignee_id: current_user.id) - expect(page).to have_selector('.empty-state') + expect(page).to have_selector('.empty-state') + end end - context 'if there are merge requests' do - before do - create(:merge_request, assignee: current_user, source_project: project) + context 'merge requests exist' do + let!(:assigned_merge_request) do + create(:merge_request, assignee: current_user, target_project: project, source_project: project) + end + + let!(:assigned_merge_request_from_fork) do + create(:merge_request, + source_branch: 'markdown', assignee: current_user, + target_project: public_project, source_project: forked_project + ) + end + let!(:authored_merge_request) do + create(:merge_request, + source_branch: 'markdown', author: current_user, + target_project: project, source_project: project + ) + end + + let!(:authored_merge_request_from_fork) do + create(:merge_request, + source_branch: 'feature_conflict', + author: current_user, + target_project: public_project, source_project: forked_project + ) + end + + let!(:other_merge_request) do + create(:merge_request, + source_branch: 'fix', + target_project: project, source_project: project + ) + end + + before do visit merge_requests_dashboard_path(assignee_id: current_user.id) end - it 'should not show an empty state' do - expect(page).not_to have_selector('.empty-state') + it 'shows assigned merge requests' do + expect(page).to have_content(assigned_merge_request.title) + expect(page).to have_content(assigned_merge_request_from_fork.title) + + expect(page).not_to have_content(authored_merge_request.title) + expect(page).not_to have_content(authored_merge_request_from_fork.title) + expect(page).not_to have_content(other_merge_request.title) + end + + it 'shows authored merge requests', js: true do + filter_item_select('Any Assignee', '.js-assignee-search') + filter_item_select(current_user.to_reference, '.js-author-search') + + expect(page).to have_content(authored_merge_request.title) + expect(page).to have_content(authored_merge_request_from_fork.title) + + expect(page).not_to have_content(assigned_merge_request.title) + expect(page).not_to have_content(assigned_merge_request_from_fork.title) + expect(page).not_to have_content(other_merge_request.title) + end + + it 'shows all merge requests', js: true do + filter_item_select('Any Assignee', '.js-assignee-search') + filter_item_select('Any Author', '.js-author-search') + + expect(page).to have_content(authored_merge_request.title) + expect(page).to have_content(authored_merge_request_from_fork.title) + expect(page).to have_content(assigned_merge_request.title) + expect(page).to have_content(assigned_merge_request_from_fork.title) + expect(page).to have_content(other_merge_request.title) end end end diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb index b5b92c36895..b0e4036f27c 100644 --- a/spec/features/dashboard/milestone_filter_spec.rb +++ b/spec/features/dashboard/milestone_filter_spec.rb @@ -1,15 +1,17 @@ require 'spec_helper' -describe 'Dashboard > milestone filter', :feature, :js do +feature 'Dashboard > milestone filter', :feature, :js do + include FilterItemSelectHelper + let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } - let(:milestone) { create(:milestone, title: "v1.0", project: project) } - let(:milestone2) { create(:milestone, title: "v2.0", project: project) } + let(:milestone) { create(:milestone, title: 'v1.0', project: project) } + let(:milestone2) { create(:milestone, title: 'v2.0', project: project) } let!(:issue) { create :issue, author: user, project: project, milestone: milestone } let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 } before do - login_as(user) + gitlab_sign_in(user) visit issues_dashboard_path(author_id: user.id) end @@ -22,17 +24,11 @@ describe 'Dashboard > milestone filter', :feature, :js do end context 'filtering by milestone' do - milestone_select = '.js-milestone-select' + milestone_select_selector = '.js-milestone-select' before do - find(milestone_select).click - wait_for_requests - - page.within('.dropdown-content') do - click_link 'v1.0' - end - - find(milestone_select).click + filter_item_select('v1.0', milestone_select_selector) + find(milestone_select_selector).click wait_for_requests end @@ -49,7 +45,7 @@ describe 'Dashboard > milestone filter', :feature, :js do expect(find('.milestone-filter')).not_to have_selector('.dropdown.open') - find(milestone_select).click + find(milestone_select_selector).click expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1) expect(find('.dropdown-content a.is-active')).to have_content('v1.0') diff --git a/spec/features/dashboard/milestone_tabs_spec.rb b/spec/features/dashboard/milestone_tabs_spec.rb index 0c7b992c500..cc4193b180f 100644 --- a/spec/features/dashboard/milestone_tabs_spec.rb +++ b/spec/features/dashboard/milestone_tabs_spec.rb @@ -15,7 +15,7 @@ describe 'Dashboard milestone tabs', :js, :feature do before do project.add_master(user) - login_as(user) + gitlab_sign_in(user) visit dashboard_milestone_path(milestone.safe_title, title: milestone.title) end @@ -23,7 +23,7 @@ describe 'Dashboard milestone tabs', :js, :feature do it 'loads merge requests async' do click_link 'Merge Requests' - expect(page).to have_selector('.merge_requests-sortable-list') + expect(page).to have_selector('.milestone-merge_requests-list') end it 'loads participants async' do diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb index 0ba87d921d0..ea0b2e99c3e 100644 --- a/spec/features/dashboard/project_member_activity_index_spec.rb +++ b/spec/features/dashboard/project_member_activity_index_spec.rb @@ -10,7 +10,7 @@ feature 'Project member activity', feature: true, js: true do def visit_activities_and_wait_with_event(event_type) Event.create(project: project, author_id: user.id, action: event_type) - visit activity_namespace_project_path(project.namespace, project) + visit activity_project_path(project) wait_for_requests end diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 3568954a548..7d1fe2bd435 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -RSpec.describe 'Dashboard Projects', feature: true do +feature 'Dashboard Projects' do let(:user) { create(:user) } - let(:project) { create(:project, name: "awesome stuff") } + let(:project) { create(:project, name: 'awesome stuff') } let(:project2) { create(:project, :public, name: 'Community project') } before do project.team << [user, :developer] - login_as(user) + gitlab_sign_in(user) end it 'shows the project the user in a member of in the list' do @@ -15,13 +15,33 @@ RSpec.describe 'Dashboard Projects', feature: true do expect(page).to have_content('awesome stuff') end - it 'shows the last_activity_at attribute as the update date' do - now = Time.now - project.update_column(:last_activity_at, now) - + it 'shows "New project" button' do visit dashboard_projects_path - expect(page).to have_xpath("//time[@datetime='#{now.getutc.iso8601}']") + page.within '#content-body' do + expect(page).to have_link('New project') + end + end + + context 'when last_repository_updated_at, last_activity_at and update_at are present' do + it 'shows the last_repository_updated_at attribute as the update date' do + project.update_attributes!(last_repository_updated_at: Time.now, last_activity_at: 1.hour.ago) + + visit dashboard_projects_path + + expect(page).to have_xpath("//time[@datetime='#{project.last_repository_updated_at.getutc.iso8601}']") + end + end + + context 'when last_repository_updated_at and last_activity_at are missing' do + it 'shows the updated_at attribute as the update date' do + project.update_attributes!(last_repository_updated_at: nil, last_activity_at: nil) + project.touch + + visit dashboard_projects_path + + expect(page).to have_xpath("//time[@datetime='#{project.updated_at.getutc.iso8601}']") + end end context 'when on Starred projects tab' do @@ -35,8 +55,8 @@ RSpec.describe 'Dashboard Projects', feature: true do end end - describe "with a pipeline", redis: true do - let!(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha) } + describe 'with a pipeline', redis: true do + let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha) } before do # Since the cache isn't updated when a new pipeline is created @@ -48,7 +68,7 @@ RSpec.describe 'Dashboard Projects', feature: true do it 'shows that the last pipeline passed' do visit dashboard_projects_path - expect(page).to have_xpath("//a[@href='#{pipelines_namespace_project_commit_path(project.namespace, project, project.commit)}']") + expect(page).to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit)}']") end end diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index 349b948eaee..525b0e1b210 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Dashboard shortcuts', :feature, :js do context 'logged in' do before do - login_as :user + gitlab_sign_in :user visit root_dashboard_path end diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb index c6ba118220a..0c069ae5cf0 100644 --- a/spec/features/dashboard/snippets_spec.rb +++ b/spec/features/dashboard/snippets_spec.rb @@ -6,7 +6,7 @@ describe 'Dashboard snippets', feature: true do let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) } before do allow(Snippet).to receive(:default_per_page).and_return(1) - login_as(project.owner) + gitlab_sign_in(project.owner) visit dashboard_snippets_path end @@ -25,7 +25,7 @@ describe 'Dashboard snippets', feature: true do end before do - login_as(user) + gitlab_sign_in(user) visit dashboard_snippets_path end diff --git a/spec/features/dashboard/todos/target_state_spec.rb b/spec/features/dashboard/todos/target_state_spec.rb new file mode 100644 index 00000000000..030a86d1c01 --- /dev/null +++ b/spec/features/dashboard/todos/target_state_spec.rb @@ -0,0 +1,65 @@ +require 'rails_helper' + +feature 'Dashboard > Todo target states' do + let(:user) { create(:user) } + let(:author) { create(:user) } + let(:project) { create(:project, :public) } + + before do + sign_in(user) + end + + scenario 'on a closed issue todo has closed label' do + issue_closed = create(:issue, state: 'closed') + create_todo issue_closed + visit dashboard_todos_path + + page.within '.todos-list' do + expect(page).to have_content('Closed') + end + end + + scenario 'on an open issue todo does not have an open label' do + issue_open = create(:issue) + create_todo issue_open + visit dashboard_todos_path + + page.within '.todos-list' do + expect(page).not_to have_content('Open') + end + end + + scenario 'on a merged merge request todo has merged label' do + mr_merged = create(:merge_request, :simple, :merged, author: user) + create_todo mr_merged + visit dashboard_todos_path + + page.within '.todos-list' do + expect(page).to have_content('Merged') + end + end + + scenario 'on a closed merge request todo has closed label' do + mr_closed = create(:merge_request, :simple, :closed, author: user) + create_todo mr_closed + visit dashboard_todos_path + + page.within '.todos-list' do + expect(page).to have_content('Closed') + end + end + + scenario 'on an open merge request todo does not have an open label' do + mr_open = create(:merge_request, :simple, author: user) + create_todo mr_open + visit dashboard_todos_path + + page.within '.todos-list' do + expect(page).not_to have_content('Open') + end + end + + def create_todo(target) + create(:todo, :mentioned, user: user, project: project, target: target, author: author) + end +end diff --git a/spec/features/dashboard/todos/todos_filtering_spec.rb b/spec/features/dashboard/todos/todos_filtering_spec.rb new file mode 100644 index 00000000000..0a363259fe7 --- /dev/null +++ b/spec/features/dashboard/todos/todos_filtering_spec.rb @@ -0,0 +1,153 @@ +require 'spec_helper' + +feature 'Dashboard > User filters todos', js: true do + let(:user_1) { create(:user, username: 'user_1', name: 'user_1') } + let(:user_2) { create(:user, username: 'user_2', name: 'user_2') } + + let(:project_1) { create(:empty_project, name: 'project_1') } + let(:project_2) { create(:empty_project, name: 'project_2') } + + let(:issue) { create(:issue, title: 'issue', project: project_1) } + + let!(:merge_request) { create(:merge_request, source_project: project_2, title: 'merge_request') } + + before do + create(:todo, user: user_1, author: user_2, project: project_1, target: issue, action: 1) + create(:todo, user: user_1, author: user_1, project: project_2, target: merge_request, action: 2) + + project_1.team << [user_1, :developer] + project_2.team << [user_1, :developer] + sign_in(user_1) + visit dashboard_todos_path + end + + it 'filters by project' do + click_button 'Project' + within '.dropdown-menu-project' do + fill_in 'Search projects', with: project_1.name_with_namespace + click_link project_1.name_with_namespace + end + + wait_for_requests + + expect(page).to have_content project_1.name_with_namespace + expect(page).not_to have_content project_2.name_with_namespace + end + + context 'Author filter' do + it 'filters by author' do + click_button 'Author' + + within '.dropdown-menu-author' do + fill_in 'Search authors', with: user_1.name + click_link user_1.name + end + + wait_for_requests + + expect(find('.todos-list')).to have_content 'merge request' + expect(find('.todos-list')).not_to have_content 'issue' + end + + it 'shows only authors of existing todos' do + click_button 'Author' + + within '.dropdown-menu-author' do + # It should contain two users + 'Any Author' + expect(page).to have_selector('.dropdown-menu-user-link', count: 3) + expect(page).to have_content(user_1.name) + expect(page).to have_content(user_2.name) + end + end + + it 'shows only authors of existing done todos' do + user_3 = create :user + user_4 = create :user + create(:todo, user: user_1, author: user_3, project: project_1, target: issue, action: 1, state: :done) + create(:todo, user: user_1, author: user_4, project: project_2, target: merge_request, action: 2, state: :done) + + project_1.team << [user_3, :developer] + project_2.team << [user_4, :developer] + + visit dashboard_todos_path(state: 'done') + + click_button 'Author' + + within '.dropdown-menu-author' do + # It should contain two users + 'Any Author' + expect(page).to have_selector('.dropdown-menu-user-link', count: 3) + expect(page).to have_content(user_3.name) + expect(page).to have_content(user_4.name) + expect(page).not_to have_content(user_1.name) + expect(page).not_to have_content(user_2.name) + end + end + end + + it 'filters by type' do + click_button 'Type' + within '.dropdown-menu-type' do + click_link 'Issue' + end + + wait_for_requests + + expect(find('.todos-list')).to have_content issue.to_reference + expect(find('.todos-list')).not_to have_content merge_request.to_reference + end + + describe 'filter by action' do + before do + create(:todo, :build_failed, user: user_1, author: user_2, project: project_1) + create(:todo, :marked, user: user_1, author: user_2, project: project_1, target: issue) + end + + it 'filters by Assigned' do + filter_action('Assigned') + + expect_to_see_action(:assigned) + end + + it 'filters by Mentioned' do + filter_action('Mentioned') + + expect_to_see_action(:mentioned) + end + + it 'filters by Added' do + filter_action('Added') + + expect_to_see_action(:marked) + end + + it 'filters by Pipelines' do + filter_action('Pipelines') + + expect_to_see_action(:build_failed) + end + + def filter_action(name) + click_button 'Action' + within '.dropdown-menu-action' do + click_link name + end + + wait_for_requests + end + + def expect_to_see_action(action_name) + action_names = { + assigned: ' assigned you ', + mentioned: ' mentioned ', + marked: ' added a todo for ', + build_failed: ' build failed for ' + } + + action_name_text = action_names.delete(action_name) + expect(find('.todos-list')).to have_content action_name_text + action_names.each_value do |other_action_text| + expect(find('.todos-list')).not_to have_content other_action_text + end + end + end +end diff --git a/spec/features/dashboard/todos/todos_sorting_spec.rb b/spec/features/dashboard/todos/todos_sorting_spec.rb new file mode 100644 index 00000000000..5858f4aa101 --- /dev/null +++ b/spec/features/dashboard/todos/todos_sorting_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +feature 'Dashboard > User sorts todos' do + let(:user) { create(:user) } + let(:project) { create(:empty_project) } + + let(:label_1) { create(:label, title: 'label_1', project: project, priority: 1) } + let(:label_2) { create(:label, title: 'label_2', project: project, priority: 2) } + let(:label_3) { create(:label, title: 'label_3', project: project, priority: 3) } + + before do + project.team << [user, :developer] + end + + context 'sort options' do + let(:issue_1) { create(:issue, title: 'issue_1', project: project) } + let(:issue_2) { create(:issue, title: 'issue_2', project: project) } + let(:issue_3) { create(:issue, title: 'issue_3', project: project) } + let(:issue_4) { create(:issue, title: 'issue_4', project: project) } + + let!(:merge_request_1) { create(:merge_request, source_project: project, title: 'merge_request_1') } + + before do + create(:todo, user: user, project: project, target: issue_4, created_at: 5.hours.ago) + create(:todo, user: user, project: project, target: issue_2, created_at: 4.hours.ago) + create(:todo, user: user, project: project, target: issue_3, created_at: 3.hours.ago) + create(:todo, user: user, project: project, target: issue_1, created_at: 2.hours.ago) + create(:todo, user: user, project: project, target: merge_request_1, created_at: 1.hour.ago) + + merge_request_1.labels << label_1 + issue_3.labels << label_1 + issue_2.labels << label_3 + issue_1.labels << label_2 + + sign_in(user) + visit dashboard_todos_path + end + + it 'sorts with oldest created todos first' do + click_link 'Last created' + + results_list = page.find('.todos-list') + expect(results_list.all('p')[0]).to have_content('merge_request_1') + expect(results_list.all('p')[1]).to have_content('issue_1') + expect(results_list.all('p')[2]).to have_content('issue_3') + expect(results_list.all('p')[3]).to have_content('issue_2') + expect(results_list.all('p')[4]).to have_content('issue_4') + end + + it 'sorts with newest created todos first' do + click_link 'Oldest created' + + results_list = page.find('.todos-list') + expect(results_list.all('p')[0]).to have_content('issue_4') + expect(results_list.all('p')[1]).to have_content('issue_2') + expect(results_list.all('p')[2]).to have_content('issue_3') + expect(results_list.all('p')[3]).to have_content('issue_1') + expect(results_list.all('p')[4]).to have_content('merge_request_1') + end + + it 'sorts by label priority' do + click_link 'Label priority' + + results_list = page.find('.todos-list') + expect(results_list.all('p')[0]).to have_content('issue_3') + expect(results_list.all('p')[1]).to have_content('merge_request_1') + expect(results_list.all('p')[2]).to have_content('issue_1') + expect(results_list.all('p')[3]).to have_content('issue_2') + expect(results_list.all('p')[4]).to have_content('issue_4') + end + end + + context 'issues and merge requests' do + let(:issue_1) { create(:issue, id: 10000, title: 'issue_1', project: project) } + let(:issue_2) { create(:issue, id: 10001, title: 'issue_2', project: project) } + let(:merge_request_1) { create(:merge_request, id: 10000, title: 'merge_request_1', source_project: project) } + + before do + issue_1.labels << label_1 + issue_2.labels << label_2 + + create(:todo, user: user, project: project, target: issue_1) + create(:todo, user: user, project: project, target: issue_2) + create(:todo, user: user, project: project, target: merge_request_1) + + gitlab_sign_in(user) + visit dashboard_todos_path + end + + it "doesn't mix issues and merge requests label priorities" do + click_link 'Label priority' + + results_list = page.find('.todos-list') + expect(results_list.all('p')[0]).to have_content('issue_1') + expect(results_list.all('p')[1]).to have_content('issue_2') + expect(results_list.all('p')[2]).to have_content('merge_request_1') + end + end +end diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb new file mode 100644 index 00000000000..30bab7eeaa7 --- /dev/null +++ b/spec/features/dashboard/todos/todos_spec.rb @@ -0,0 +1,338 @@ +require 'spec_helper' + +feature 'Dashboard Todos' do + let(:user) { create(:user) } + let(:author) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, due_date: Date.today) } + + context 'User does not have todos' do + before do + sign_in(user) + visit dashboard_todos_path + end + + it 'shows "All done" message' do + expect(page).to have_content 'Todos let you see what you should do next.' + end + end + + context 'User has a todo', js: true do + before do + create(:todo, :mentioned, user: user, project: project, target: issue, author: author) + sign_in(user) + + visit dashboard_todos_path + end + + it 'has todo present' do + expect(page).to have_selector('.todos-list .todo', count: 1) + end + + it 'shows due date as today' do + within first('.todo') do + expect(page).to have_content 'Due today' + end + end + + shared_examples 'deleting the todo' do + before do + within first('.todo') do + click_link 'Done' + end + end + + it 'is marked as done-reversible in the list' do + expect(page).to have_selector('.todos-list .todo.todo-pending.done-reversible') + end + + it 'shows Undo button' do + expect(page).to have_selector('.js-undo-todo', visible: true) + expect(page).to have_selector('.js-done-todo', visible: false) + end + + it 'updates todo count' do + expect(page).to have_content 'To do 0' + expect(page).to have_content 'Done 1' + end + + it 'has not "All done" message' do + expect(page).not_to have_selector('.todos-all-done') + end + end + + shared_examples 'deleting and restoring the todo' do + before do + within first('.todo') do + click_link 'Done' + wait_for_requests + click_link 'Undo' + end + end + + it 'is marked back as pending in the list' do + expect(page).not_to have_selector('.todos-list .todo.todo-pending.done-reversible') + expect(page).to have_selector('.todos-list .todo.todo-pending') + end + + it 'shows Done button' do + expect(page).to have_selector('.js-undo-todo', visible: false) + expect(page).to have_selector('.js-done-todo', visible: true) + end + + it 'updates todo count' do + expect(page).to have_content 'To do 1' + expect(page).to have_content 'Done 0' + end + end + + it_behaves_like 'deleting the todo' + it_behaves_like 'deleting and restoring the todo' + + context 'todo is stale on the page' do + before do + todos = TodosFinder.new(user, state: :pending).execute + TodoService.new.mark_todos_as_done(todos, user) + end + + it_behaves_like 'deleting the todo' + it_behaves_like 'deleting and restoring the todo' + end + end + + context 'User created todos for themself' do + before do + sign_in(user) + end + + context 'issue assigned todo' do + before do + create(:todo, :assigned, user: user, project: project, target: issue, author: user) + visit dashboard_todos_path + end + + it 'shows issue assigned to yourself message' do + page.within('.js-todos-all') do + expect(page).to have_content("You assigned issue #{issue.to_reference(full: true)} to yourself") + end + end + end + + context 'marked todo' do + before do + create(:todo, :marked, user: user, project: project, target: issue, author: user) + visit dashboard_todos_path + end + + it 'shows you added a todo message' do + page.within('.js-todos-all') do + expect(page).to have_content("You added a todo for issue #{issue.to_reference(full: true)}") + expect(page).not_to have_content('to yourself') + end + end + end + + context 'mentioned todo' do + before do + create(:todo, :mentioned, user: user, project: project, target: issue, author: user) + visit dashboard_todos_path + end + + it 'shows you mentioned yourself message' do + page.within('.js-todos-all') do + expect(page).to have_content("You mentioned yourself on issue #{issue.to_reference(full: true)}") + expect(page).not_to have_content('to yourself') + end + end + end + + context 'directly_addressed todo' do + before do + create(:todo, :directly_addressed, user: user, project: project, target: issue, author: user) + visit dashboard_todos_path + end + + it 'shows you directly addressed yourself message' do + page.within('.js-todos-all') do + expect(page).to have_content("You directly addressed yourself on issue #{issue.to_reference(full: true)}") + expect(page).not_to have_content('to yourself') + end + end + end + + context 'approval todo' do + let(:merge_request) { create(:merge_request) } + + before do + create(:todo, :approval_required, user: user, project: project, target: merge_request, author: user) + visit dashboard_todos_path + end + + it 'shows you set yourself as an approver message' do + page.within('.js-todos-all') do + expect(page).to have_content("You set yourself as an approver for merge request #{merge_request.to_reference(full: true)}") + expect(page).not_to have_content('to yourself') + end + end + end + end + + context 'User has done todos', js: true do + before do + create(:todo, :mentioned, :done, user: user, project: project, target: issue, author: author) + sign_in(user) + visit dashboard_todos_path(state: :done) + end + + it 'has the done todo present' do + expect(page).to have_selector('.todos-list .todo.todo-done', count: 1) + end + + describe 'restoring the todo' do + before do + within first('.todo') do + click_link 'Add todo' + end + end + + it 'is removed from the list' do + expect(page).not_to have_selector('.todos-list .todo.todo-done') + end + + it 'updates todo count' do + expect(page).to have_content 'To do 1' + expect(page).to have_content 'Done 0' + end + end + end + + context 'User has Todos with labels spanning multiple projects' do + before do + label1 = create(:label, project: project) + note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project) + create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id) + + project2 = create(:project, :public) + label2 = create(:label, project: project2) + issue2 = create(:issue, project: project2) + note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2) + create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id) + + gitlab_sign_in(user) + visit dashboard_todos_path + end + + it 'shows page with two Todos' do + expect(page).to have_selector('.todos-list .todo', count: 2) + end + end + + context 'User has multiple pages of Todos' do + before do + allow(Todo).to receive(:default_per_page).and_return(1) + + # Create just enough records to cause us to paginate + create_list(:todo, 2, :mentioned, user: user, project: project, target: issue, author: author) + + sign_in(user) + end + + it 'is paginated' do + visit dashboard_todos_path + + expect(page).to have_selector('.gl-pagination') + end + + it 'is has the right number of pages' do + visit dashboard_todos_path + + expect(page).to have_selector('.gl-pagination .page', count: 2) + end + + describe 'mark all as done', js: true do + before do + visit dashboard_todos_path + find('.js-todos-mark-all').trigger('click') + end + + it 'shows "All done" message!' do + expect(page).to have_content 'To do 0' + expect(page).to have_content "You're all done!" + expect(page).not_to have_selector('.gl-pagination') + end + + it 'shows "Undo mark all as done" button' do + expect(page).to have_selector('.js-todos-mark-all', visible: false) + expect(page).to have_selector('.js-todos-undo-all', visible: true) + end + end + + describe 'undo mark all as done', js: true do + before do + visit dashboard_todos_path + end + + it 'shows the restored todo list' do + mark_all_and_undo + + expect(page).to have_selector('.todos-list .todo', count: 1) + expect(page).to have_selector('.gl-pagination') + expect(page).not_to have_content "You're all done!" + end + + it 'updates todo count' do + mark_all_and_undo + + expect(page).to have_content 'To do 2' + expect(page).to have_content 'Done 0' + end + + it 'shows "Mark all as done" button' do + mark_all_and_undo + + expect(page).to have_selector('.js-todos-mark-all', visible: true) + expect(page).to have_selector('.js-todos-undo-all', visible: false) + end + + context 'User has deleted a todo' do + before do + within first('.todo') do + click_link 'Done' + end + end + + it 'shows the restored todo list with the deleted todo' do + mark_all_and_undo + + expect(page).to have_selector('.todos-list .todo.todo-pending', count: 1) + end + end + + def mark_all_and_undo + find('.js-todos-mark-all').trigger('click') + wait_for_requests + find('.js-todos-undo-all').trigger('click') + wait_for_requests + end + end + end + + context 'User has a Build Failed todo' do + let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) } + + before do + sign_in(user) + visit dashboard_todos_path + end + + it 'shows the todo' do + expect(page).to have_content 'The build failed for merge request' + end + + it 'links to the pipelines for the merge request' do + href = pipelines_project_merge_request_path(project, todo.target) + + expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href + end + end +end diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb index 34d6257f5fd..e9f34760143 100644 --- a/spec/features/dashboard/user_filters_projects_spec.rb +++ b/spec/features/dashboard/user_filters_projects_spec.rb @@ -9,7 +9,7 @@ describe 'Dashboard > User filters projects', :feature do before do project.team << [user, :master] - login_as(user) + gitlab_sign_in(user) end describe 'filtering personal projects' do |