diff options
author | Dylan Griffith <dyl.griffith@gmail.com> | 2018-05-03 10:54:12 +0300 |
---|---|---|
committer | Dylan Griffith <dyl.griffith@gmail.com> | 2018-05-03 10:54:12 +0300 |
commit | d39b3d4b8d2d4c5ded46182a5353c68a8f5bb5cd (patch) | |
tree | e8f2fac760b252928ff23074dea9d1f209838a33 /spec/features | |
parent | dcb67951a817db262ddcd3b777fafc4e1995fc04 (diff) | |
parent | 2c9568edeea7d95b6e4ec3c23cdc1c027bf86d5f (diff) |
Merge branch 'master' into feature/runner-per-group
Diffstat (limited to 'spec/features')
15 files changed, 588 insertions, 338 deletions
diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index f1ac73ff819..90cf5a53787 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -19,7 +19,7 @@ feature 'Admin uses repository checks' do expect(page).to have_content('Repository check was triggered') end - scenario 'to see a single failed repository check' do + scenario 'to see a single failed repository check', :js do project = create(:project) project.update_columns( last_repository_check_failed: true, diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb index a71020002dc..ed47f7ed390 100644 --- a/spec/features/dashboard/groups_list_spec.rb +++ b/spec/features/dashboard/groups_list_spec.rb @@ -40,7 +40,7 @@ feature 'Dashboard Groups page', :js do expect(page).to have_content(nested_group.name) end - describe 'when filtering groups', :nested_groups do + context 'when filtering groups', :nested_groups do before do group.add_owner(user) nested_group.add_owner(user) @@ -75,7 +75,7 @@ feature 'Dashboard Groups page', :js do end end - describe 'group with subgroups', :nested_groups do + context 'with subgroups', :nested_groups do let!(:subgroup) { create(:group, :public, parent: group) } before do @@ -106,7 +106,7 @@ feature 'Dashboard Groups page', :js do end end - describe 'when using pagination' do + context 'when using pagination' do let(:group) { create(:group, created_at: 5.days.ago) } let(:group2) { create(:group, created_at: 2.days.ago) } @@ -141,4 +141,20 @@ feature 'Dashboard Groups page', :js do expect(page).not_to have_selector("#group-#{group2.id}") end end + + context 'when signed in as admin' do + let(:admin) { create(:admin) } + + it 'shows only groups admin is member of' do + group.add_owner(admin) + expect(another_group).to be_persisted + + sign_in(admin) + visit dashboard_groups_path + wait_for_requests + + expect(page).to have_content(group.name) + expect(page).not_to have_content(another_group.name) + end + end end diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb index c965b565ca3..8cd57f4f327 100644 --- a/spec/features/dashboard/milestone_filter_spec.rb +++ b/spec/features/dashboard/milestone_filter_spec.rb @@ -10,13 +10,16 @@ feature 'Dashboard > milestone filter', :js do let!(:issue) { create :issue, author: user, project: project, milestone: milestone } let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 } + dropdown_toggle_button = '.js-milestone-select' + before do sign_in(user) - visit issues_dashboard_path(author_id: user.id) end context 'default state' do it 'shows issues with Any Milestone' do + visit issues_dashboard_path(author_id: user.id) + page.all('.issue-info').each do |issue_info| expect(issue_info.text).to match(/v\d.0/) end @@ -24,31 +27,51 @@ feature 'Dashboard > milestone filter', :js do end context 'filtering by milestone' do - milestone_select_selector = '.js-milestone-select' - before do - filter_item_select('v1.0', milestone_select_selector) - find(milestone_select_selector).click + visit issues_dashboard_path(author_id: user.id) + filter_item_select('v1.0', dropdown_toggle_button) + find(dropdown_toggle_button).click wait_for_requests end it 'shows issues with Milestone v1.0' do expect(find('.issues-list')).to have_selector('.issue', count: 1) - expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1) + expect(find('.milestone-filter .dropdown-content')).to have_selector('a.is-active', count: 1) end it 'should not change active Milestone unless clicked' do - expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1) + page.within '.milestone-filter' do + expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1) + + find('.dropdown-menu-close').click - # open & close dropdown - find('.dropdown-menu-close').click + expect(page).not_to have_selector('.dropdown.open') + + find(dropdown_toggle_button).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') + end + end + end + + context 'with milestone filter in URL' do + before do + visit issues_dashboard_path(author_id: user.id, milestone_title: milestone.title) + find(dropdown_toggle_button).click + wait_for_requests + end + + it 'has milestone selected' do + expect(find('.milestone-filter .dropdown-content')).to have_css('.is-active', text: milestone.title) + end - expect(find('.milestone-filter')).not_to have_selector('.dropdown.open') + it 'removes milestone filter from URL after clicking "Any Milestone"' do + expect(current_url).to include("milestone_title=#{milestone.title}") - find(milestone_select_selector).click + find('.milestone-filter .dropdown-content li', text: 'Any Milestone').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') + expect(current_url).not_to include('milestone_title') end end end diff --git a/spec/features/groups/members/manage_access_requests_spec.rb b/spec/features/groups/members/manage_access_requests_spec.rb deleted file mode 100644 index b83cd657ef7..00000000000 --- a/spec/features/groups/members/manage_access_requests_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -feature 'Groups > Members > Manage access requests' do - let(:user) { create(:user) } - let(:owner) { create(:user) } - let(:group) { create(:group, :public, :access_requestable) } - - background do - group.request_access(user) - group.add_owner(owner) - sign_in(owner) - end - - scenario 'owner can see access requests' do - visit group_group_members_path(group) - - expect_visible_access_request(group, user) - end - - scenario 'owner can grant access' do - visit group_group_members_path(group) - - expect_visible_access_request(group, user) - - perform_enqueued_jobs { click_on 'Grant access' } - - expect(ActionMailer::Base.deliveries.last.to).to eq [user.notification_email] - expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{group.name} group was granted" - end - - scenario 'owner can deny access' do - visit group_group_members_path(group) - - expect_visible_access_request(group, user) - - perform_enqueued_jobs { click_on 'Deny access' } - - expect(ActionMailer::Base.deliveries.last.to).to eq [user.notification_email] - expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{group.name} group was denied" - end - - def expect_visible_access_request(group, user) - expect(group.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "Users requesting access to #{group.name} 1" - expect(page).to have_content user.name - end -end diff --git a/spec/features/groups/members/master_manages_access_requests_spec.rb b/spec/features/groups/members/master_manages_access_requests_spec.rb new file mode 100644 index 00000000000..2fd6d1ec599 --- /dev/null +++ b/spec/features/groups/members/master_manages_access_requests_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +feature 'Groups > Members > Master manages access requests' do + it_behaves_like 'Master manages access requests' do + let(:entity) { create(:group, :public, :access_requestable) } + let(:members_page_path) { group_group_members_path(entity) } + end +end diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index ff2a0e15719..ddd64fa1412 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -178,9 +178,10 @@ feature 'Issues > User uses quick actions', :js do end context 'when the project is valid but the user not authorized' do - let(:project_unauthorized) {create(:project, :public)} + let(:project_unauthorized) { create(:project, :public) } before do + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end @@ -195,6 +196,7 @@ feature 'Issues > User uses quick actions', :js do context 'when the project is invalid' do before do + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb index dbca279569a..42c279af117 100644 --- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb +++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb @@ -19,7 +19,7 @@ describe 'Merge request > User selects branches for new MR', :js do expect(page).to have_content('Target branch') first('.js-source-branch').click - find('.dropdown-source-branch .dropdown-content a', match: :first).click + find('.js-source-branch-dropdown .dropdown-content a', match: :first).click expect(page).to have_content "b83d6e3" end @@ -35,22 +35,16 @@ describe 'Merge request > User selects branches for new MR', :js do expect(page).to have_content('Target branch') first('.js-target-branch').click - find('.dropdown-target-branch .dropdown-content a', text: 'v1.1.0', match: :first).click + find('.js-target-branch-dropdown .dropdown-content a', text: 'v1.1.0', match: :first).click expect(page).to have_content "b83d6e3" end it 'generates a diff for an orphaned branch' do - visit project_merge_requests_path(project) - - page.within '.content' do - click_link 'New merge request' - end - expect(page).to have_content('Source branch') - expect(page).to have_content('Target branch') + visit project_new_merge_request_path(project) find('.js-source-branch', match: :first).click - find('.dropdown-source-branch .dropdown-content a', text: 'orphaned-branch', match: :first).click + find('.js-source-branch-dropdown .dropdown-content a', text: 'orphaned-branch', match: :first).click click_button "Compare branches" click_link "Changes" @@ -71,19 +65,18 @@ describe 'Merge request > User selects branches for new MR', :js do first('.js-source-branch').click - input = find('.dropdown-source-branch .dropdown-input-field') - input.click - input.send_keys('orphaned-branch') + page.within '.js-source-branch-dropdown' do + input = find('.dropdown-input-field') + input.click + input.send_keys('orphaned-branch') - find('.dropdown-source-branch .dropdown-content li', match: :first) - source_items = all('.dropdown-source-branch .dropdown-content li') - - expect(source_items.count).to eq(1) + expect(page).to have_css('.dropdown-content li', count: 1) + end first('.js-target-branch').click - find('.dropdown-target-branch .dropdown-content li', match: :first) - target_items = all('.dropdown-target-branch .dropdown-content li') + find('.js-target-branch-dropdown .dropdown-content li', match: :first) + target_items = all('.js-target-branch-dropdown .dropdown-content li') expect(target_items.count).to be > 1 end @@ -171,7 +164,6 @@ describe 'Merge request > User selects branches for new MR', :js do page.within('.merge-request') do click_link 'Pipelines' - wait_for_requests expect(page).to have_content "##{pipeline.id}" end diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb new file mode 100644 index 00000000000..4045cfd21c4 --- /dev/null +++ b/spec/features/profiles/active_sessions_spec.rb @@ -0,0 +1,89 @@ +require 'rails_helper' + +feature 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do + let(:user) do + create(:user).tap do |user| + user.current_sign_in_at = Time.current + end + end + + around do |example| + Timecop.freeze(Time.zone.parse('2018-03-12 09:06')) do + example.run + end + end + + scenario 'User sees their active sessions' do + Capybara::Session.new(:session1) + Capybara::Session.new(:session2) + + # note: headers can only be set on the non-js (aka. rack-test) driver + using_session :session1 do + Capybara.page.driver.header( + 'User-Agent', + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' + ) + + gitlab_sign_in(user) + end + + # set an additional session on another device + using_session :session2 do + Capybara.page.driver.header( + 'User-Agent', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B466 [FBDV/iPhone7,2]' + ) + + gitlab_sign_in(user) + end + + using_session :session1 do + visit profile_active_sessions_path + + expect(page).to have_content( + '127.0.0.1 ' \ + 'This is your current session ' \ + 'Firefox on Ubuntu ' \ + 'Signed in on 12 Mar 09:06' + ) + + expect(page).to have_selector '[title="Desktop"]', count: 1 + + expect(page).to have_content( + '127.0.0.1 ' \ + 'Last accessed on 12 Mar 09:06 ' \ + 'Mobile Safari on iOS ' \ + 'Signed in on 12 Mar 09:06' + ) + + expect(page).to have_selector '[title="Smartphone"]', count: 1 + end + end + + scenario 'User can revoke a session', :js, :redis_session_store do + Capybara::Session.new(:session1) + Capybara::Session.new(:session2) + + # set an additional session in another browser + using_session :session2 do + gitlab_sign_in(user) + end + + using_session :session1 do + gitlab_sign_in(user) + visit profile_active_sessions_path + + expect(page).to have_link('Revoke', count: 1) + + accept_confirm { click_on 'Revoke' } + + expect(page).not_to have_link('Revoke') + end + + using_session :session2 do + visit profile_active_sessions_path + + expect(page).to have_content('You need to sign in or sign up before continuing.') + end + end +end diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb index 9c1f11f4c12..41f6c52fb8a 100644 --- a/spec/features/projects/files/user_browses_files_spec.rb +++ b/spec/features/projects/files/user_browses_files_spec.rb @@ -1,14 +1,12 @@ -require 'spec_helper' +require "spec_helper" -describe 'Projects > Files > User browses files' do +describe "User browses files" do let(:fork_message) do "You're not allowed to make changes to this project directly. "\ "A fork of this project has been created that you can make changes in, so you can submit a merge request." end - let(:project) { create(:project, :repository, name: 'Shop') } - let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } - let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } - let(:tree_path_ref_6d39438) { project_tree_path(project, '6d39438') } + let(:project) { create(:project, :repository, name: "Shop") } + let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") } let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } let(:user) { project.owner } @@ -16,57 +14,55 @@ describe 'Projects > Files > User browses files' do sign_in(user) end - it 'shows last commit for current directory' do + it "shows last commit for current directory" do visit(tree_path_root_ref) - click_link 'files' + click_link("files") - last_commit = project.repository.last_commit_for_path(project.default_branch, 'files') - page.within('.blob-commit-info') do - expect(page).to have_content last_commit.short_id - expect(page).to have_content last_commit.author_name + last_commit = project.repository.last_commit_for_path(project.default_branch, "files") + + page.within(".blob-commit-info") do + expect(page).to have_content(last_commit.short_id).and have_content(last_commit.author_name) end end - context 'when browsing the master branch' do + context "when browsing the master branch" do before do visit(tree_path_root_ref) end - it 'shows files from a repository' do - expect(page).to have_content('VERSION') - expect(page).to have_content('.gitignore') - expect(page).to have_content('LICENSE') + it "shows files from a repository" do + expect(page).to have_content("VERSION") + .and have_content(".gitignore") + .and have_content("LICENSE") end - it 'shows the "Browse Directory" link' do - click_link('files') - click_link('History') + it "shows the `Browse Directory` link" do + click_link("files") + click_link("History") - expect(page).to have_link('Browse Directory') - expect(page).not_to have_link('Browse Code') + expect(page).to have_link("Browse Directory").and have_no_link("Browse Code") end - it 'shows the "Browse File" link' do - page.within('.tree-table') do - click_link('README.md') + it "shows the `Browse File` link" do + page.within(".tree-table") do + click_link("README.md") end - click_link('History') - expect(page).to have_link('Browse File') - expect(page).not_to have_link('Browse Files') + click_link("History") + + expect(page).to have_link("Browse File").and have_no_link("Browse Files") end - it 'shows the "Browse Files" link' do - click_link('History') + it "shows the `Browse Files` link" do + click_link("History") - expect(page).to have_link('Browse Files') - expect(page).not_to have_link('Browse Directory') + expect(page).to have_link("Browse Files").and have_no_link("Browse Directory") end - it 'redirects to the permalink URL' do - click_link('.gitignore') - click_link('Permalink') + it "redirects to the permalink URL" do + click_link(".gitignore") + click_link("Permalink") permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore") @@ -74,80 +70,180 @@ describe 'Projects > Files > User browses files' do end end - context 'when browsing a specific ref' do + context "when browsing the `markdown` branch", :js do + context "when browsing the root" do + before do + visit(project_tree_path(project, "markdown")) + end + + it "shows correct files and links" do + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_tree_url(project, "markdown") + find("a", text: /^#id$/)["href"] == project_tree_url(project, "markdown", anchor: "#id") + find("a", text: %r{^/#id$})["href"] == project_tree_url(project, "markdown", anchor: "#id") + find("a", text: /^README.md#id$/)["href"] == project_blob_url(project, "markdown/README.md", anchor: "#id") + find("a", text: %r{^d/README.md#id$})["href"] == project_blob_url(project, "d/markdown/README.md", anchor: "#id") + # rubocop:enable Lint/Void + + expect(current_path).to eq(project_tree_path(project, "markdown")) + expect(page).to have_content("README.md") + .and have_content("CHANGELOG") + .and have_content("Welcome to GitLab GitLab is a free project and repository management application") + .and have_link("GitLab API doc") + .and have_link("GitLab API website") + .and have_link("Rake tasks") + .and have_link("backup and restore procedure") + .and have_link("GitLab API doc directory") + .and have_link("Maintenance") + .and have_header_with_correct_id_and_link(2, "Application details", "application-details") + end + + it "shows correct content of file" do + click_link("GitLab API doc") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/README.md")) + expect(page).to have_content("All API requests require authentication") + .and have_content("Contents") + .and have_link("Users") + .and have_link("Rake tasks") + .and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api") + + click_link("Users") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/users.md")) + expect(page).to have_content("Get a list of users.") + + page.go_back + + click_link("Rake tasks") + + expect(current_path).to eq(project_tree_path(project, "markdown/doc/raketasks")) + expect(page).to have_content("backup_restore.md").and have_content("maintenance.md") + + click_link("shop") + click_link("Maintenance") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/raketasks/maintenance.md")) + expect(page).to have_content("bundle exec rake gitlab:env:info RAILS_ENV=production") + + click_link("shop") + + page.within(".tree-table") do + click_link("README.md") + end + + page.go_back + + page.within(".tree-table") do + click_link("d") + end + + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_tree_url(project, "markdown/d") + # rubocop:enable Lint/Void + + page.within(".tree-table") do + click_link("README.md") + end + + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_blob_url(project, "markdown/d/README.md") + # rubocop:enable Lint/Void + end + + it "shows correct content of directory" do + click_link("GitLab API doc directory") + + expect(current_path).to eq(project_tree_path(project, "markdown/doc/api")) + expect(page).to have_content("README.md").and have_content("users.md") + + click_link("Users") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/users.md")) + expect(page).to have_content("List users").and have_content("Get a list of users.") + end + end + end + + context "when browsing a specific ref" do + let(:ref) { project_tree_path(project, "6d39438") } + before do - visit(tree_path_ref_6d39438) + visit(ref) end - it 'shows files from a repository for "6d39438"' do - expect(current_path).to eq(tree_path_ref_6d39438) - expect(page).to have_content('.gitignore') - expect(page).to have_content('LICENSE') + it "shows files from a repository for `6d39438`" do + expect(current_path).to eq(ref) + expect(page).to have_content(".gitignore").and have_content("LICENSE") end - it 'shows files from a repository with apostroph in its name', :js do - first('.js-project-refs-dropdown').click + it "shows files from a repository with apostroph in its name", :js do + first(".js-project-refs-dropdown").click - page.within('.project-refs-form') do + page.within(".project-refs-form") do click_link("'test'") end - expect(page).to have_selector('.dropdown-toggle-text', text: "'test'") + expect(page).to have_selector(".dropdown-toggle-text", text: "'test'") visit(project_tree_path(project, "'test'")) - expect(page).to have_css('.tree-commit-link', visible: true) - expect(page).not_to have_content('Loading commit data...') + expect(page).to have_css(".tree-commit-link").and have_no_content("Loading commit data...") end - it 'shows the code with a leading dot in the directory', :js do - first('.js-project-refs-dropdown').click + it "shows the code with a leading dot in the directory", :js do + first(".js-project-refs-dropdown").click - page.within('.project-refs-form') do - click_link('fix') + page.within(".project-refs-form") do + click_link("fix") end - visit(project_tree_path(project, 'fix/.testdir')) + visit(project_tree_path(project, "fix/.testdir")) - expect(page).to have_css('.tree-commit-link', visible: true) - expect(page).not_to have_content('Loading commit data...') + expect(page).to have_css(".tree-commit-link").and have_no_content("Loading commit data...") end - it 'does not show the permalink link' do - click_link('.gitignore') + it "does not show the permalink link" do + click_link(".gitignore") - expect(page).not_to have_link('permalink') + expect(page).not_to have_link("permalink") end end - context 'when browsing a file content' do + context "when browsing a file content" do before do visit(tree_path_root_ref) - click_link('.gitignore') + + click_link(".gitignore") end - it 'shows a file content', :js do - wait_for_requests - expect(page).to have_content('*.rbc') + it "shows a file content", :js do + expect(page).to have_content("*.rbc") end - it 'is possible to blame' do - click_link 'Blame' + it "is possible to blame" do + click_link("Blame") - expect(page).to have_content "*.rb" - expect(page).to have_content "Dmitriy Zaporozhets" - expect(page).to have_content "Initial commit" + expect(page).to have_content("*.rb") + .and have_content("Dmitriy Zaporozhets") + .and have_content("Initial commit") end end - context 'when browsing a raw file' do + context "when browsing a raw file" do before do - visit(project_blob_path(project, File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path))) + path = File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path) + + visit(project_blob_path(project, path)) end - it 'shows a raw file content' do - click_link('Open raw') - expect(source).to eq('') # Body is filled in by gitlab-workhorse + it "shows a raw file content" do + click_link("Open raw") + + expect(source).to eq("") # Body is filled in by gitlab-workhorse end end end diff --git a/spec/features/projects/issues/user_toggles_subscription_spec.rb b/spec/features/projects/issues/user_toggles_subscription_spec.rb index 117a614b980..c2b2a193682 100644 --- a/spec/features/projects/issues/user_toggles_subscription_spec.rb +++ b/spec/features/projects/issues/user_toggles_subscription_spec.rb @@ -1,9 +1,9 @@ require "spec_helper" describe "User toggles subscription", :js do - set(:project) { create(:project_empty_repo, :public) } - set(:user) { create(:user) } - set(:issue) { create(:issue, project: project, author: user) } + let(:project) { create(:project_empty_repo, :public) } + let(:user) { create(:user) } + let(:issue) { create(:issue, project: project, author: user) } before do project.add_developer(user) @@ -12,7 +12,7 @@ describe "User toggles subscription", :js do visit(project_issue_path(project, issue)) end - it "unsibscribes from issue" do + it "unsubscribes from issue" do subscription_button = find(".js-issuable-subscribe-button") # Check we're subscribed. diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb index 1f4eec0a317..3ac6ca4fc86 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -1,47 +1,8 @@ require 'spec_helper' feature 'Projects > Members > Master manages access requests' do - let(:user) { create(:user) } - let(:master) { create(:user) } - let(:project) { create(:project, :public, :access_requestable) } - - background do - project.request_access(user) - project.add_master(master) - sign_in(master) - end - - scenario 'master can see access requests' do - visit project_project_members_path(project) - - expect_visible_access_request(project, user) - end - - scenario 'master can grant access' do - visit project_project_members_path(project) - - expect_visible_access_request(project, user) - - perform_enqueued_jobs { click_on 'Grant access' } - - expect(ActionMailer::Base.deliveries.last.to).to eq [user.notification_email] - expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{project.full_name} project was granted" - end - - scenario 'master can deny access' do - visit project_project_members_path(project) - - expect_visible_access_request(project, user) - - perform_enqueued_jobs { click_on 'Deny access' } - - expect(ActionMailer::Base.deliveries.last.to).to eq [user.notification_email] - expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{project.full_name} project was denied" - end - - def expect_visible_access_request(project, user) - expect(project.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "Users requesting access to #{project.name} 1" - expect(page).to have_content user.name + it_behaves_like 'Master manages access requests' do + let(:entity) { create(:project, :public, :access_requestable) } + let(:members_page_path) { project_project_members_path(entity) } end end diff --git a/spec/features/projects/settings/lfs_settings_spec.rb b/spec/features/projects/settings/lfs_settings_spec.rb index 0fd28a5681c..342be1d2a9d 100644 --- a/spec/features/projects/settings/lfs_settings_spec.rb +++ b/spec/features/projects/settings/lfs_settings_spec.rb @@ -1,21 +1,27 @@ require 'rails_helper' describe 'Projects > Settings > LFS settings' do - let(:admin) { create(:admin) } let(:project) { create(:project) } + let(:user) { create(:user) } + let(:role) { :master } context 'LFS enabled setting' do before do allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) - sign_in(admin) + sign_in(user) + project.add_role(user, role) end - it 'displays the correct elements', :js do - visit edit_project_path(project) + context 'for master' do + let(:role) { :master } - expect(page).to have_content('Git Large File Storage') - expect(page).to have_selector('input[name="project[lfs_enabled]"] + button', visible: true) + it 'displays the correct elements', :js do + visit edit_project_path(project) + + expect(page).to have_content('Git Large File Storage') + expect(page).to have_selector('input[name="project[lfs_enabled]"] + button', visible: true) + end end end end diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb index 8e53ae15700..4dfc325b37e 100644 --- a/spec/features/projects/tree/upload_file_spec.rb +++ b/spec/features/projects/tree/upload_file_spec.rb @@ -35,17 +35,4 @@ feature 'Multi-file editor upload file', :js do expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt') expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline)) end - - it 'uploads image file' do - find('.add-to-tree').click - - # make the field visible so capybara can use it - execute_script('document.querySelector("#file-upload").classList.remove("hidden")') - attach_file('file-upload', img_file) - - find('.add-to-tree').click - - expect(page).to have_selector('.multi-file-tab', text: 'dk.png') - expect(page).not_to have_selector('.monaco-editor') - end end diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb index 4a9d1cb87e1..fe6fa55fa75 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -1,6 +1,6 @@ -require 'spec_helper' +require "spec_helper" -describe 'User creates wiki page' do +describe "User creates wiki page" do let(:user) { create(:user) } before do @@ -10,67 +10,104 @@ describe 'User creates wiki page' do visit(project_wikis_path(project)) end - context 'when wiki is empty' do - context 'in a user namespace' do + context "when wiki is empty" do + context "in a user namespace" do let(:project) { create(:project, namespace: user.namespace) } - it 'shows validation error message' do - page.within('.wiki-form') do - fill_in(:wiki_content, with: '') - click_on('Create page') + it "shows validation error message" do + page.within(".wiki-form") do + fill_in(:wiki_content, with: "") + + click_on("Create page") end - expect(page).to have_content('The form contains the following error:') - expect(page).to have_content("Content can't be blank") + expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "[link test](test)") - page.within('.wiki-form') do - fill_in(:wiki_content, with: '[link test](test)') - click_on('Create page') + click_on("Create page") end - expect(page).to have_content('Home') - expect(page).to have_content('link test') + expect(page).to have_content("Home").and have_content("link test") - click_link('link test') + click_link("link test") - expect(page).to have_content('Create Page') + expect(page).to have_content("Create Page") end - it 'shows non-escaped link in the pages list', :js do - click_link('New page') + it "shows non-escaped link in the pages list", :js do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'one/two/three-test') - click_on('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "one/two/three-test") + + click_on("Create page") end - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') + page.within(".wiki-form") do + fill_in(:wiki_content, with: "wiki content") + + click_on("Create page") end - expect(current_path).to include('one/two/three-test') + expect(current_path).to include("one/two/three-test") expect(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']") end - it 'has "Create home" as a commit message' do - expect(page).to have_field('wiki[message]', with: 'Create home') + it "has `Create home` as a commit message" do + expect(page).to have_field("wiki[message]", with: "Create home") end - it 'creates a page from the home page' do - fill_in(:wiki_content, with: 'My awesome wiki!') + it "creates a page from the home page" do + fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n") + fill_in(:wiki_message, with: "Adding links to wiki") + + page.within(".wiki-form") do + click_button("Create page") + end + + expect(current_path).to eq(project_wiki_path(project, "home")) + expect(page).to have_content("test GitLab API doc Rake tasks Wiki header") + .and have_content("Home") + .and have_content("Last edited by #{user.name}") + .and have_header_with_correct_id_and_link(1, "Wiki header", "wiki-header") + + click_link("test") - page.within('.wiki-form') do - click_button('Create page') + expect(current_path).to eq(project_wiki_path(project, "test")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Test").and have_content("Create Page") + end + + click_link("Home") + + expect(current_path).to eq(project_wiki_path(project, "home")) + + click_link("GitLab API") + + expect(current_path).to eq(project_wiki_path(project, "api")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create").and have_content("Api") end - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + click_link("Home") + + expect(current_path).to eq(project_wiki_path(project, "home")) + + click_link("Rake tasks") + + expect(current_path).to eq(project_wiki_path(project, "raketasks")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create").and have_content("Rake") + end end - it 'creates ASCII wiki with LaTeX blocks', :js do - stub_application_setting(plantuml_url: 'http://localhost', plantuml_enabled: true) + it "creates ASCII wiki with LaTeX blocks", :js do + stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true) ascii_content = <<~MD :stem: latexmath @@ -90,153 +127,164 @@ describe 'User creates wiki page' do stem:[2+2] is 4 MD - find('#wiki_format option[value=asciidoc]').select_option + find("#wiki_format option[value=asciidoc]").select_option + fill_in(:wiki_content, with: ascii_content) - page.within('.wiki-form') do - click_button('Create page') + page.within(".wiki-form") do + click_button("Create page") end - page.within '.wiki' do - expect(page).to have_selector('.katex', count: 3) - expect(page).to have_content('2+2 is 4') + page.within ".wiki" do + expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4") end end end - context 'in a group namespace', :js do + context "in a group namespace", :js do let(:project) { create(:project, namespace: create(:group, :public)) } - it 'has "Create home" as a commit message' do - expect(page).to have_field('wiki[message]', with: 'Create home') + it "has `Create home` as a commit message" do + expect(page).to have_field("wiki[message]", with: "Create home") end - it 'creates a page from from the home page' do - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + it "creates a page from from the home page" do + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") + + click_button("Create page") end - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Home") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end end - context 'when wiki is not empty', :js do + context "when wiki is not empty", :js do before do - create(:wiki_page, wiki: create(:project, namespace: user.namespace).wiki, attrs: { title: 'home', content: 'Home page' }) + create(:wiki_page, wiki: create(:project, namespace: user.namespace).wiki, attrs: { title: "home", content: "Home page" }) end - context 'in a user namespace' do + context "in a user namespace" do let(:project) { create(:project, namespace: user.namespace) } - context 'via the "new wiki page" page' do - it 'creates a page with a single word' do - click_link('New page') + context "via the `new wiki page` page" do + it "creates a page with a single word" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'foo') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "foo") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create foo') + expect(page).to have_field("wiki[message]", with: "Create foo") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Foo') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Foo") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end - it 'creates a page with spaces in the name' do - click_link('New page') + it "creates a page with spaces in the name" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'Spaces in the name') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "Spaces in the name") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create spaces in the name') + expect(page).to have_field("wiki[message]", with: "Create spaces in the name") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Spaces in the name') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Spaces in the name") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end - it 'creates a page with hyphens in the name' do - click_link('New page') + it "creates a page with hyphens in the name" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'hyphens-in-the-name') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "hyphens-in-the-name") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create hyphens in the name') + expect(page).to have_field("wiki[message]", with: "Create hyphens in the name") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Hyphens in the name') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Hyphens in the name") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end - it 'shows the autocompletion dropdown' do - click_link('New page') + it "shows the autocompletion dropdown" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'test-autocomplete') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "test-autocomplete") + + click_button("Create page") end - page.within('.wiki-form') do - find('#wiki_content').native.send_keys('') - fill_in(:wiki_content, with: '@') + page.within(".wiki-form") do + find("#wiki_content").native.send_keys("") + + fill_in(:wiki_content, with: "@") end - expect(page).to have_selector('.atwho-view') + expect(page).to have_selector(".atwho-view") end end - context 'in a group namespace' do + context "in a group namespace" do let(:project) { create(:project, namespace: create(:group, :public)) } - context 'via the "new wiki page" page' do - it 'creates a page' do - click_link('New page') + context "via the `new wiki page` page" do + it "creates a page" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'foo') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "foo") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create foo') + expect(page).to have_field("wiki[message]", with: "Create foo") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Foo') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Foo") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end end diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb new file mode 100644 index 00000000000..631d7e3bced --- /dev/null +++ b/spec/features/users/active_sessions_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +feature 'Active user sessions', :clean_gitlab_redis_shared_state do + scenario 'Successful login adds a new active user login' do + now = Time.zone.parse('2018-03-12 09:06') + Timecop.freeze(now) do + user = create(:user) + gitlab_sign_in(user) + expect(current_path).to eq root_path + + sessions = ActiveSession.list(user) + expect(sessions.count).to eq 1 + + # refresh the current page updates the updated_at + Timecop.freeze(now + 1.minute) do + visit current_path + + sessions = ActiveSession.list(user) + expect(sessions.first).to have_attributes( + created_at: Time.zone.parse('2018-03-12 09:06'), + updated_at: Time.zone.parse('2018-03-12 09:07') + ) + end + end + end + + scenario 'Successful login cleans up obsolete entries' do + user = create(:user) + + Gitlab::Redis::SharedState.with do |redis| + redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + end + + gitlab_sign_in(user) + + Gitlab::Redis::SharedState.with do |redis| + expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).not_to include '59822c7d9fcdfa03725eff41782ad97d' + end + end + + scenario 'Sessionless login does not clean up obsolete entries' do + user = create(:user) + personal_access_token = create(:personal_access_token, user: user) + + Gitlab::Redis::SharedState.with do |redis| + redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + end + + visit user_path(user, :atom, private_token: personal_access_token.token) + expect(page.status_code).to eq 200 + + Gitlab::Redis::SharedState.with do |redis| + expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to include '59822c7d9fcdfa03725eff41782ad97d' + end + end + + scenario 'Logout deletes the active user login' do + user = create(:user) + gitlab_sign_in(user) + expect(current_path).to eq root_path + + expect(ActiveSession.list(user).count).to eq 1 + + gitlab_sign_out + expect(current_path).to eq new_user_session_path + + expect(ActiveSession.list(user)).to be_empty + end +end |