diff options
Diffstat (limited to 'spec/features')
369 files changed, 7261 insertions, 3510 deletions
diff --git a/spec/features/abuse_report_spec.rb b/spec/features/abuse_report_spec.rb index 1e11fb756b2..091fdcec3db 100644 --- a/spec/features/abuse_report_spec.rb +++ b/spec/features/abuse_report_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Abuse reports', feature: true do +feature 'Abuse reports' do let(:another_user) { create(:user) } before do - login_as :user + sign_in(create(:user)) end scenario 'Report abuse' do @@ -12,7 +12,7 @@ feature 'Abuse reports', feature: true do click_link 'Report abuse' - fill_in 'abuse_report_message', with: 'This user send spam' + fill_in 'abuse_report_message', with: 'This user sends spam' click_button 'Send report' expect(page).to have_content 'Thank you for your report' diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb index 340884fc986..2144f6ba635 100644 --- a/spec/features/admin/admin_abuse_reports_spec.rb +++ b/spec/features/admin/admin_abuse_reports_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -describe "Admin::AbuseReports", feature: true, js: true do +describe "Admin::AbuseReports", js: true do let(:user) { create(:user) } context 'as an admin' do before do - login_as :admin + sign_in(create(:admin)) end describe 'if a user has been reported for abuse' do diff --git a/spec/features/admin/admin_active_tab_spec.rb b/spec/features/admin/admin_active_tab_spec.rb index 16064d60ce2..07430ecd6e0 100644 --- a/spec/features/admin/admin_active_tab_spec.rb +++ b/spec/features/admin/admin_active_tab_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' RSpec.describe 'admin active tab' do before do - login_as :admin + sign_in(create(:admin)) end shared_examples 'page has active tab' do |title| diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb index 96d715ef383..5f3a37c1dcc 100644 --- a/spec/features/admin/admin_appearance_spec.rb +++ b/spec/features/admin/admin_appearance_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Admin Appearance', feature: true do +feature 'Admin Appearance' do let!(:appearance) { create(:appearance) } scenario 'Create new appearance' do - login_as :admin + sign_in(create(:admin)) visit admin_appearances_path fill_in 'appearance_title', with: 'MyCompany' @@ -20,7 +20,7 @@ feature 'Admin Appearance', feature: true do end scenario 'Preview appearance' do - login_as :admin + sign_in(create(:admin)) visit admin_appearances_path click_link "Preview" @@ -34,7 +34,7 @@ feature 'Admin Appearance', feature: true do end scenario 'Appearance logo' do - login_as :admin + sign_in(create(:admin)) visit admin_appearances_path attach_file(:appearance_logo, logo_fixture) @@ -46,7 +46,7 @@ feature 'Admin Appearance', feature: true do end scenario 'Header logos' do - login_as :admin + sign_in(create(:admin)) visit admin_appearances_path attach_file(:appearance_header_logo, logo_fixture) @@ -63,11 +63,11 @@ feature 'Admin Appearance', feature: true do end def logo_selector - '//img[@src^="/uploads/appearance/logo"]' + '//img[data-src^="/uploads/-/system/appearance/logo"]' end def header_logo_selector - '//img[@src^="/uploads/appearance/header_logo"]' + '//img[data-src^="/uploads/-/system/appearance/header_logo"]' end def logo_fixture diff --git a/spec/features/admin/admin_broadcast_messages_spec.rb b/spec/features/admin/admin_broadcast_messages_spec.rb index d6c63f66a9b..cbccf370514 100644 --- a/spec/features/admin/admin_broadcast_messages_spec.rb +++ b/spec/features/admin/admin_broadcast_messages_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Admin Broadcast Messages', feature: true do +feature 'Admin Broadcast Messages' do before do - login_as :admin + sign_in(create(:admin)) create(:broadcast_message, :expired, message: 'Migration to new server') visit admin_broadcast_messages_path end diff --git a/spec/features/admin/admin_browse_spam_logs_spec.rb b/spec/features/admin/admin_browse_spam_logs_spec.rb index bee57472270..31d4142a8e9 100644 --- a/spec/features/admin/admin_browse_spam_logs_spec.rb +++ b/spec/features/admin/admin_browse_spam_logs_spec.rb @@ -4,7 +4,7 @@ describe 'Admin browse spam logs' do let!(:spam_log) { create(:spam_log, description: 'abcde ' * 20) } before do - login_as :admin + sign_in(create(:admin)) end scenario 'Browse spam logs' do diff --git a/spec/features/admin/admin_browses_logs_spec.rb b/spec/features/admin/admin_browses_logs_spec.rb index d880f3f07db..3e3404dfdac 100644 --- a/spec/features/admin/admin_browses_logs_spec.rb +++ b/spec/features/admin/admin_browses_logs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Admin browses logs' do before do - login_as :admin + sign_in(create(:admin)) end it 'shows available log files' do diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index 999ce3611b5..e020579f71e 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Admin Builds' do before do - login_as :admin + sign_in(create(:admin)) end describe 'GET /admin/builds' do diff --git a/spec/features/admin/admin_cohorts_spec.rb b/spec/features/admin/admin_cohorts_spec.rb index dd14ffdb2ce..bca52bf674c 100644 --- a/spec/features/admin/admin_cohorts_spec.rb +++ b/spec/features/admin/admin_cohorts_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' -feature 'Admin cohorts page', feature: true do +feature 'Admin cohorts page' do before do - login_as :admin + sign_in(create(:admin)) end scenario 'See users count per month' do diff --git a/spec/features/admin/admin_conversational_development_index_spec.rb b/spec/features/admin/admin_conversational_development_index_spec.rb index 739ab907a29..2d2c7df5364 100644 --- a/spec/features/admin/admin_conversational_development_index_spec.rb +++ b/spec/features/admin/admin_conversational_development_index_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Admin Conversational Development Index' do before do - login_as :admin + sign_in(create(:admin)) end context 'when usage ping is disabled' do diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb index c0b6995a84a..241c7cbc34e 100644 --- a/spec/features/admin/admin_deploy_keys_spec.rb +++ b/spec/features/admin/admin_deploy_keys_spec.rb @@ -1,50 +1,77 @@ require 'spec_helper' -RSpec.describe 'admin deploy keys', type: :feature do +RSpec.describe 'admin deploy keys' do let!(:deploy_key) { create(:deploy_key, public: true) } let!(:another_deploy_key) { create(:another_deploy_key, public: true) } before do - login_as(:admin) + sign_in(create(:admin)) end it 'show all public deploy keys' do visit admin_deploy_keys_path - expect(page).to have_content(deploy_key.title) - expect(page).to have_content(another_deploy_key.title) + page.within(find('.deploy-keys-list', match: :first)) do + expect(page).to have_content(deploy_key.title) + expect(page).to have_content(another_deploy_key.title) + end end - describe 'create new deploy key' do + describe 'create a new deploy key' do + let(:new_ssh_key) { attributes_for(:key)[:key] } + before do visit admin_deploy_keys_path click_link 'New deploy key' end - it 'creates new deploy key' do - fill_deploy_key + it 'creates a new deploy key' do + fill_in 'deploy_key_title', with: 'laptop' + fill_in 'deploy_key_key', with: new_ssh_key + check 'deploy_key_can_push' click_button 'Create' - expect_renders_new_key - end + expect(current_path).to eq admin_deploy_keys_path - it 'creates new deploy key with write access' do - fill_deploy_key - check "deploy_key_can_push" - click_button "Create" + page.within(find('.deploy-keys-list', match: :first)) do + expect(page).to have_content('laptop') + expect(page).to have_content('Yes') + end + end + end - expect_renders_new_key - expect(page).to have_content('Yes') + describe 'update an existing deploy key' do + before do + visit admin_deploy_keys_path + find('tr', text: deploy_key.title).click_link('Edit') end - def expect_renders_new_key + it 'updates an existing deploy key' do + fill_in 'deploy_key_title', with: 'new-title' + check 'deploy_key_can_push' + click_button 'Save changes' + expect(current_path).to eq admin_deploy_keys_path - expect(page).to have_content('laptop') + + page.within(find('.deploy-keys-list', match: :first)) do + expect(page).to have_content('new-title') + expect(page).to have_content('Yes') + end end + end - def fill_deploy_key - fill_in 'deploy_key_title', with: 'laptop' - fill_in 'deploy_key_key', with: 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzrEJUIR6Y03TCE9rIJ+GqTBvgb8t1jI9h5UBzCLuK4VawOmkLornPqLDrGbm6tcwM/wBrrLvVOqi2HwmkKEIecVO0a64A4rIYScVsXIniHRS6w5twyn1MD3sIbN+socBDcaldECQa2u1dI3tnNVcs8wi77fiRe7RSxePsJceGoheRQgC8AZ510UdIlO+9rjIHUdVN7LLyz512auAfYsgx1OfablkQ/XJcdEwDNgi9imI6nAXhmoKUm1IPLT2yKajTIC64AjLOnE0YyCh6+7RFMpiMyu1qiOCpdjYwTgBRiciNRZCH8xIedyCoAmiUgkUT40XYHwLuwiPJICpkAzp7Q== user@laptop' + describe 'remove an existing deploy key' do + before do + visit admin_deploy_keys_path + end + + it 'removes an existing deploy key' do + find('tr', text: deploy_key.title).click_link('Remove') + + expect(current_path).to eq admin_deploy_keys_path + page.within(find('.deploy-keys-list', match: :first)) do + expect(page).not_to have_content(deploy_key.title) + end end end end diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb index e8e080ce3e2..9ea3cfa72c6 100644 --- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb +++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Admin disables Git access protocol', feature: true do +feature 'Admin disables Git access protocol' do include StubENV - let(:project) { create(:empty_project, :empty_repo) } + let(:project) { create(:project, :empty_repo) } let(:admin) { create(:admin) } background do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - login_as(admin) + sign_in(admin) end context 'with HTTP disabled' do @@ -51,7 +51,7 @@ feature 'Admin disables Git access protocol', feature: true do end def visit_project - visit namespace_project_path(project.namespace, project) + visit project_path(project) end def disable_http_protocol diff --git a/spec/features/admin/admin_disables_two_factor_spec.rb b/spec/features/admin/admin_disables_two_factor_spec.rb index 71be66303d2..e214ae6b78d 100644 --- a/spec/features/admin/admin_disables_two_factor_spec.rb +++ b/spec/features/admin/admin_disables_two_factor_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' -feature 'Admin disables 2FA for a user', feature: true do +feature 'Admin disables 2FA for a user' do scenario 'successfully', js: true do - login_as(:admin) + sign_in(create(:admin)) user = create(:user, :two_factor) edit_user(user) @@ -17,7 +17,7 @@ feature 'Admin disables 2FA for a user', feature: true do end scenario 'for a user without 2FA enabled' do - login_as(:admin) + sign_in(create(:admin)) user = create(:user) edit_user(user) diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb index d5f595894d6..3768727d8ae 100644 --- a/spec/features/admin/admin_groups_spec.rb +++ b/spec/features/admin/admin_groups_spec.rb @@ -1,14 +1,15 @@ require 'spec_helper' -feature 'Admin Groups', feature: true do +feature 'Admin Groups' do include Select2Helper let(:internal) { Gitlab::VisibilityLevel::INTERNAL } let(:user) { create :user } let!(:group) { create :group } - let!(:current_user) { login_as :admin } + let!(:current_user) { create(:admin) } before do + sign_in(current_user) stub_application_setting(default_group_visibility: internal) end @@ -24,7 +25,9 @@ feature 'Admin Groups', feature: true do it 'creates new group' do visit admin_groups_path - click_link "New group" + page.within '#content-body' do + click_link "New group" + end path_component = 'gitlab' group_name = 'GitLab group name' group_description = 'Description of group for GitLab' @@ -162,7 +165,7 @@ feature 'Admin Groups', feature: true do describe 'shared projects' do it 'renders shared project' do - empty_project = create(:empty_project) + empty_project = create(:project) empty_project.project_group_links.create!( group_access: Gitlab::Access::MASTER, group: group diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb index 523afa2318f..106e7370a98 100644 --- a/spec/features/admin/admin_health_check_spec.rb +++ b/spec/features/admin/admin_health_check_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature "Admin Health Check", feature: true do +feature "Admin Health Check" do include StubENV before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - login_as :admin + sign_in(create(:admin)) end describe '#show' do diff --git a/spec/features/admin/admin_hook_logs_spec.rb b/spec/features/admin/admin_hook_logs_spec.rb index 5b67f4de6ac..710822ac042 100644 --- a/spec/features/admin/admin_hook_logs_spec.rb +++ b/spec/features/admin/admin_hook_logs_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Admin::HookLogs', feature: true do +feature 'Admin::HookLogs' do let(:project) { create(:project) } let(:system_hook) { create(:system_hook) } let(:hook_log) { create(:web_hook_log, web_hook: system_hook, internal_error_message: 'some error') } before do - login_as :admin + sign_in(create(:admin)) end scenario 'show list of hook logs' do diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index 80f7ec43c06..30fcb334b60 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe 'Admin::Hooks', feature: true do +describe 'Admin::Hooks' do before do @project = create(:project) - login_as :admin + sign_in(create(:admin)) @system_hook = create(:system_hook) end @@ -74,11 +74,13 @@ describe 'Admin::Hooks', feature: true do end end - describe 'Test' do + describe 'Test', js: true do before do WebMock.stub_request(:post, @system_hook.url) visit admin_hooks_path - click_link 'Test hook' + + find('.hook-test-button.dropdown').click + click_link 'Push events' end it { expect(current_path).to eq(admin_hooks_path) } diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb index a9251db13e5..ae9b47299e6 100644 --- a/spec/features/admin/admin_labels_spec.rb +++ b/spec/features/admin/admin_labels_spec.rb @@ -5,7 +5,7 @@ RSpec.describe 'admin issues labels' do let!(:feature_label) { Label.create(title: 'feature', template: true) } before do - login_as :admin + sign_in(create(:admin)) end describe 'list' do diff --git a/spec/features/admin/admin_manage_applications_spec.rb b/spec/features/admin/admin_manage_applications_spec.rb index 0079125889b..f979d2f6090 100644 --- a/spec/features/admin/admin_manage_applications_spec.rb +++ b/spec/features/admin/admin_manage_applications_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -RSpec.describe 'admin manage applications', feature: true do +RSpec.describe 'admin manage applications' do before do - login_as :admin + sign_in(create(:admin)) end it do @@ -13,19 +13,24 @@ RSpec.describe 'admin manage applications', feature: true do fill_in :doorkeeper_application_name, with: 'test' fill_in :doorkeeper_application_redirect_uri, with: 'https://test.com' + check :doorkeeper_application_trusted click_on 'Submit' expect(page).to have_content('Application: test') expect(page).to have_content('Application Id') expect(page).to have_content('Secret') + expect(page).to have_content('Trusted Y') click_on 'Edit' expect(page).to have_content('Edit application') fill_in :doorkeeper_application_name, with: 'test_changed' + uncheck :doorkeeper_application_trusted + click_on 'Submit' expect(page).to have_content('test_changed') expect(page).to have_content('Application Id') expect(page).to have_content('Secret') + expect(page).to have_content('Trusted N') visit admin_applications_path page.within '.oauth-applications' do diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index 9d205104ebe..77710f80036 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -1,18 +1,21 @@ require 'spec_helper' -describe "Admin::Projects", feature: true do +describe "Admin::Projects" do include Select2Helper let(:user) { create :user } - let!(:project) { create(:project) } - let!(:current_user) do - login_as :admin + let(:project) { create(:project) } + let(:current_user) { create(:admin) } + + before do + sign_in(current_user) end describe "GET /admin/projects" do let!(:archived_project) { create :project, :public, :archived } before do + expect(project).to be_persisted visit admin_projects_path end @@ -37,15 +40,14 @@ describe "Admin::Projects", feature: true do describe "GET /admin/projects/:namespace_id/:id" do before do - visit admin_projects_path - click_link "#{project.name}" - end + expect(project).to be_persisted - it do - expect(current_path).to eq admin_namespace_project_path(project.namespace, project) + visit admin_projects_path + click_link project.name end it "has project info" do + expect(current_path).to eq admin_project_path(project) expect(page).to have_content(project.path) expect(page).to have_content(project.name) expect(page).to have_content(project.name_with_namespace) @@ -54,15 +56,18 @@ describe "Admin::Projects", feature: true do end describe 'transfer project' do + # The gitlab-shell transfer will fail for a project without a repository + let(:project) { create(:project, :repository) } + before do create(:group, name: 'Web') - allow_any_instance_of(Projects::TransferService). - to receive(:move_uploads_to_new_namespace).and_return(true) + allow_any_instance_of(Projects::TransferService) + .to receive(:move_uploads_to_new_namespace).and_return(true) end it 'transfers project to group web', js: true do - visit admin_namespace_project_path(project.namespace, project) + visit admin_project_path(project) click_button 'Search for Namespace' click_link 'group: web' @@ -79,7 +84,7 @@ describe "Admin::Projects", feature: true do end it 'adds admin a to a project as developer', js: true do - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) page.within '.users-project-form' do select2(current_user.id, from: '#user_ids', multiple: true) @@ -102,7 +107,7 @@ describe "Admin::Projects", feature: true do end it 'removes admin from the project' do - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) page.within '.content-list' do expect(page).to have_content(current_user.name) diff --git a/spec/features/admin/admin_requests_profiles_spec.rb b/spec/features/admin/admin_requests_profiles_spec.rb index e8ecb70306b..380cd5d7703 100644 --- a/spec/features/admin/admin_requests_profiles_spec.rb +++ b/spec/features/admin/admin_requests_profiles_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe 'Admin::RequestsProfilesController', feature: true do +describe 'Admin::RequestsProfilesController' do before do FileUtils.mkdir_p(Gitlab::RequestProfiler::PROFILES_DIR) - login_as(:admin) + sign_in(create(:admin)) end after do diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 5dcc7d35d82..e3bb16af38a 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -5,35 +5,58 @@ describe "Admin Runners" do before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - login_as :admin + sign_in(create(:admin)) end describe "Runners page" do - before do - runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now) - pipeline = FactoryGirl.create(:ci_pipeline) - FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id) - visit admin_runners_path - end + let(:pipeline) { create(:ci_pipeline) } + + context "when there are runners" do + before do + runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now) + FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id) + visit admin_runners_path + end + + it 'has all necessary texts' do + expect(page).to have_text "How to setup" + expect(page).to have_text "Runners with last contact more than a minute ago: 1" + end + + describe 'search' do + before do + FactoryGirl.create :ci_runner, description: 'runner-foo' + FactoryGirl.create :ci_runner, description: 'runner-bar' + end + + it 'shows correct runner when description matches' do + search_form = find('#runners-search') + search_form.fill_in 'search', with: 'runner-foo' + search_form.click_button 'Search' - it 'has all necessary texts' do - expect(page).to have_text "To register a new Runner" - expect(page).to have_text "Runners with last contact more than a minute ago: 1" + expect(page).to have_content("runner-foo") + expect(page).not_to have_content("runner-bar") + end + + it 'shows no runner when description does not match' do + search_form = find('#runners-search') + search_form.fill_in 'search', with: 'runner-baz' + search_form.click_button 'Search' + + expect(page).to have_text 'No runners found' + end + end end - describe 'search' do + context "when there are no runners" do before do - FactoryGirl.create :ci_runner, description: 'runner-foo' - FactoryGirl.create :ci_runner, description: 'runner-bar' - - search_form = find('#runners-search') - search_form.fill_in 'search', with: 'runner-foo' - search_form.click_button 'Search' + visit admin_runners_path end - it 'shows correct runner' do - expect(page).to have_content("runner-foo") - expect(page).not_to have_content("runner-bar") + it 'has all necessary texts including no runner message' do + expect(page).to have_text "How to setup" + expect(page).to have_text "Runners with last contact more than a minute ago: 0" + expect(page).to have_text 'No runners found' end end end @@ -42,8 +65,8 @@ describe "Admin Runners" do let(:runner) { FactoryGirl.create :ci_runner } before do - @project1 = FactoryGirl.create(:empty_project) - @project2 = FactoryGirl.create(:empty_project) + @project1 = FactoryGirl.create(:project) + @project2 = FactoryGirl.create(:project) visit admin_runner_path(runner) end @@ -134,15 +157,17 @@ describe "Admin Runners" do describe 'runners registration token' do let!(:token) { current_application_settings.runners_registration_token } - before { visit admin_runners_path } + + before do + visit admin_runners_path + end it 'has a registration token' do - expect(page).to have_content("Registration token is #{token}") - expect(page).to have_selector('#runners-token', text: token) + expect(page.find('#registration_token')).to have_content(token) end describe 'reload registration token' do - let(:page_token) { find('#runners-token').text } + let(:page_token) { find('#registration_token').text } before do click_button 'Reset runners registration token' diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 5099441dce2..c1eced417cf 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Admin updates settings', feature: true do +feature 'Admin updates settings' do include StubENV before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - login_as :admin + sign_in(create(:admin)) visit admin_application_settings_path end @@ -16,14 +16,32 @@ feature 'Admin updates settings', feature: true do expect(page).to have_content "Application settings saved successfully" end + scenario 'Uncheck all restricted visibility levels' do + find('#application_setting_visibility_level_0').set(false) + find('#application_setting_visibility_level_10').set(false) + find('#application_setting_visibility_level_20').set(false) + + click_button 'Save' + + expect(page).to have_content "Application settings saved successfully" + expect(find('#application_setting_visibility_level_0')).not_to be_checked + expect(find('#application_setting_visibility_level_10')).not_to be_checked + expect(find('#application_setting_visibility_level_20')).not_to be_checked + end + scenario 'Change application settings' do uncheck 'Gravatar enabled' fill_in 'Home page URL', with: 'https://about.gitlab.com/' fill_in 'Help page text', with: 'Example text' + check 'Hide marketing-related entries from help' + fill_in 'Support page URL', with: 'http://example.com/help' click_button 'Save' expect(current_application_settings.gravatar_enabled).to be_falsey expect(current_application_settings.home_page_url).to eq "https://about.gitlab.com/" + expect(current_application_settings.help_page_text).to eq "Example text" + expect(current_application_settings.help_page_hide_commercial_content).to be_truthy + expect(current_application_settings.help_page_support_url).to eq "http://example.com/help" expect(page).to have_content "Application settings saved successfully" end diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb index 15482347886..1fd1cda694a 100644 --- a/spec/features/admin/admin_system_info_spec.rb +++ b/spec/features/admin/admin_system_info_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Admin System Info' do before do - login_as :admin + sign_in(create(:admin)) end describe 'GET /admin/system_info' do diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb index 0fb4baeb71c..034682dae27 100644 --- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb +++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do +describe 'Admin > Users > Impersonation Tokens', js: true do let(:admin) { create(:admin) } let!(:user) { create(:user) } @@ -8,11 +8,13 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do find(".table.active-tokens") end - def inactive_impersonation_tokens - find(".table.inactive-tokens") + def no_personal_access_tokens_message + find(".settings-message") end - before { login_as(admin) } + before do + sign_in(admin) + end describe "token creation" do it "allows creation of a token" do @@ -30,11 +32,13 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do check "api" check "read_user" - expect { click_on "Create impersonation token" }.to change { PersonalAccessTokensFinder.new(impersonation: true).execute.count } + click_on "Create impersonation token" + expect(active_impersonation_tokens).to have_text(name) expect(active_impersonation_tokens).to have_text('In') expect(active_impersonation_tokens).to have_text('api') expect(active_impersonation_tokens).to have_text('read_user') + expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1) end end @@ -58,15 +62,17 @@ describe 'Admin > Users > Impersonation Tokens', feature: true, js: true do click_on "Revoke" - expect(inactive_impersonation_tokens).to have_text(impersonation_token.name) + expect(page).to have_selector(".settings-message") + expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.") end - it "moves expired tokens to the 'inactive' section" do + it "removes expired tokens from 'active' section" do impersonation_token.update(expires_at: 5.days.ago) visit admin_user_impersonation_tokens_path(user_id: user.username) - expect(inactive_impersonation_tokens).to have_text(impersonation_token.name) + expect(page).to have_selector(".settings-message") + expect(no_personal_access_tokens_message).to have_text("This user has no active Impersonation Tokens.") end end end diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 301a47169a4..e2e2b13cf8a 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -1,11 +1,15 @@ require 'spec_helper' -describe "Admin::Users", feature: true do +describe "Admin::Users" do let!(:user) do create(:omniauth_user, provider: 'twitter', extern_uid: '123456') end - let!(:current_user) { login_as :admin } + let!(:current_user) { create(:admin) } + + before do + sign_in(current_user) + end describe "GET /admin/users" do before do @@ -78,10 +82,10 @@ describe "Admin::Users", feature: true do it "applies defaults to user" do click_button "Create user" user = User.find_by(username: 'bang') - expect(user.projects_limit). - to eq(Gitlab.config.gitlab.default_projects_limit) - expect(user.can_create_group). - to eq(Gitlab.config.gitlab.default_can_create_group) + expect(user.projects_limit) + .to eq(Gitlab.config.gitlab.default_projects_limit) + expect(user.can_create_group) + .to eq(Gitlab.config.gitlab.default_can_create_group) end it "creates user with valid data" do @@ -124,7 +128,10 @@ describe "Admin::Users", feature: true do describe 'Impersonation' do let(:another_user) { create(:user) } - before { visit admin_user_path(another_user) } + + before do + visit admin_user_path(another_user) + end context 'before impersonating' do it 'shows impersonate button for other users' do @@ -149,7 +156,9 @@ describe "Admin::Users", feature: true do end context 'when impersonating' do - before { click_link 'Impersonate' } + before do + click_link 'Impersonate' + end it 'logs in as the user when impersonate is clicked' do expect(page.find(:css, '.header-user .profile-link')['data-user']).to eql(another_user.username) diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index ab5c42365fe..c2b7543a690 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -1,15 +1,15 @@ require 'rails_helper' -feature 'Admin uses repository checks', feature: true do +feature 'Admin uses repository checks' do include StubENV before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - login_as :admin + sign_in(create(:admin)) end scenario 'to trigger a single check' do - project = create(:empty_project) + project = create(:project) visit_admin_project_page(project) page.within('.repository-check') do @@ -20,7 +20,7 @@ feature 'Admin uses repository checks', feature: true do end scenario 'to see a single failed repository check' do - project = create(:empty_project) + project = create(:project) project.update_columns( last_repository_check_failed: true, last_repository_check_at: Time.now @@ -43,6 +43,6 @@ feature 'Admin uses repository checks', feature: true do end def visit_admin_project_page(project) - visit admin_namespace_project_path(project.namespace, project) + visit admin_project_path(project) end end diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb index 711c8a710f3..5aae2dbaf91 100644 --- a/spec/features/atom/dashboard_issues_spec.rb +++ b/spec/features/atom/dashboard_issues_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Dashboard Issues Feed", feature: true do +describe "Dashboard Issues Feed" do describe "GET /issues" do let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') } let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') } diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb index 1df058b023c..321c8a2a670 100644 --- a/spec/features/atom/dashboard_spec.rb +++ b/spec/features/atom/dashboard_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Dashboard Feed", feature: true do +describe "Dashboard Feed" do describe "GET /" do let!(:user) { create(:user, name: "Jonh") } @@ -35,8 +35,8 @@ describe "Dashboard Feed", feature: true do end it "has issue comment event" do - expect(body). - to have_content("#{user.name} commented on issue ##{issue.iid}") + expect(body) + .to have_content("#{user.name} commented on issue ##{issue.iid}") end end end diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb index a61231ea254..3eeb4d35131 100644 --- a/spec/features/atom/issues_spec.rb +++ b/spec/features/atom/issues_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Issues Feed', feature: true do +describe 'Issues Feed' do describe 'GET /issues' do let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') } let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') } @@ -15,11 +15,11 @@ describe 'Issues Feed', feature: true do context 'when authenticated' do it 'renders atom feed' do - login_with user - visit namespace_project_issues_path(project.namespace, project, :atom) + sign_in user + visit project_issues_path(project, :atom) - expect(response_headers['Content-Type']). - to have_content('application/atom+xml') + expect(response_headers['Content-Type']) + .to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{project.name} issues") expect(body).to have_selector('author email', text: issue.author_public_email) expect(body).to have_selector('assignees assignee email', text: issue.assignees.first.public_email) @@ -30,11 +30,11 @@ describe 'Issues Feed', feature: true do context 'when authenticated via private token' do it 'renders atom feed' do - visit namespace_project_issues_path(project.namespace, project, :atom, + visit project_issues_path(project, :atom, private_token: user.private_token) - expect(response_headers['Content-Type']). - to have_content('application/atom+xml') + expect(response_headers['Content-Type']) + .to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{project.name} issues") expect(body).to have_selector('author email', text: issue.author_public_email) expect(body).to have_selector('assignees assignee email', text: issue.assignees.first.public_email) @@ -45,11 +45,11 @@ describe 'Issues Feed', feature: true do context 'when authenticated via RSS token' do it 'renders atom feed' do - visit namespace_project_issues_path(project.namespace, project, :atom, + visit project_issues_path(project, :atom, rss_token: user.rss_token) - expect(response_headers['Content-Type']). - to have_content('application/atom+xml') + expect(response_headers['Content-Type']) + .to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{project.name} issues") expect(body).to have_selector('author email', text: issue.author_public_email) expect(body).to have_selector('assignees assignee email', text: issue.assignees.first.public_email) @@ -59,7 +59,7 @@ describe 'Issues Feed', feature: true do end it "renders atom feed with url parameters for project issues" do - visit namespace_project_issues_path(project.namespace, project, + visit project_issues_path(project, :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id) link = find('link[type="application/atom+xml"]') diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb index fae5aaa52bd..79069bbca8e 100644 --- a/spec/features/atom/users_spec.rb +++ b/spec/features/atom/users_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "User Feed", feature: true do +describe "User Feed" do describe "GET /" do let!(:user) { create(:user) } @@ -19,7 +19,7 @@ describe "User Feed", feature: true do end context 'feed content' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:issue) do create(:issue, project: project, @@ -55,8 +55,8 @@ describe "User Feed", feature: true do end it 'has issue comment event' do - expect(body). - to have_content("#{safe_name} commented on issue ##{issue.iid}") + expect(body) + .to have_content("#{safe_name} commented on issue ##{issue.iid}") end it 'has XHTML summaries in issue descriptions' do diff --git a/spec/features/auto_deploy_spec.rb b/spec/features/auto_deploy_spec.rb index 1cf7396bbac..dff6f96b663 100644 --- a/spec/features/auto_deploy_spec.rb +++ b/spec/features/auto_deploy_spec.rb @@ -7,7 +7,7 @@ describe 'Auto deploy' do before do create :kubernetes_service, project: project project.team << [user, :master] - login_as user + sign_in user end context 'when no deployment service is active' do @@ -16,7 +16,7 @@ describe 'Auto deploy' do end it 'does not show a button to set up auto deploy' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_no_content('Set up auto deploy') end end @@ -24,7 +24,7 @@ describe 'Auto deploy' do context 'when a deployment service is active' do before do project.kubernetes_service.update!(active: true) - visit namespace_project_path(project.namespace, project) + visit project_path(project) end it 'shows a button to set up auto deploy' do diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb index 32ac265814f..a6ad5981f8f 100644 --- a/spec/features/boards/add_issues_modal_spec.rb +++ b/spec/features/boards/add_issues_modal_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' -describe 'Issue Boards add issue modal', :feature, :js do - let(:project) { create(:empty_project, :public) } +describe 'Issue Boards add issue modal', :js do + let(:project) { create(:project, :public) } let(:board) { create(:board, project: project) } let(:user) { create(:user) } let!(:planning) { create(:label, project: project, name: 'Planning') } @@ -14,14 +14,14 @@ describe 'Issue Boards add issue modal', :feature, :js do before do project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests end it 'resets filtered search state' do - visit namespace_project_board_path(project.namespace, project, board, search: 'testing') + visit project_board_path(project, board, search: 'testing') wait_for_requests @@ -231,7 +231,7 @@ describe 'Issue Boards add issue modal', :feature, :js do click_button 'Add 1 issue' end - page.within(first('.board')) do + page.within(find('.board:nth-child(2)')) do expect(page).to have_selector('.card') end end @@ -247,7 +247,7 @@ describe 'Issue Boards add issue modal', :feature, :js do click_button 'Add 1 issue' end - page.within(find('.board:nth-child(2)')) do + page.within(find('.board:nth-child(3)')) do expect(page).to have_selector('.card') end end diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index ba27db23ced..c51b81c1cff 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -1,9 +1,10 @@ require 'rails_helper' -describe 'Issue Boards', feature: true, js: true do +describe 'Issue Boards', js: true do include DragTo - let(:project) { create(:empty_project, :public) } + let(:group) { create(:group, :nested) } + let(:project) { create(:project, :public, namespace: group) } let(:board) { create(:board, project: project) } let(:user) { create(:user) } let!(:user2) { create(:user) } @@ -12,14 +13,14 @@ describe 'Issue Boards', feature: true, js: true do project.team << [user, :master] project.team << [user2, :master] - login_as(user) + sign_in(user) end context 'no lists' do before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'shows blank state' do @@ -36,18 +37,18 @@ describe 'Issue Boards', feature: true, js: true do page.within(find('.board-blank-state')) do click_button("Nevermind, I'll use my own") end - expect(page).to have_selector('.board', count: 1) + expect(page).to have_selector('.board', count: 2) end it 'creates default lists' do - lists = ['To Do', 'Doing', 'Closed'] + lists = ['Backlog', 'To Do', 'Doing', 'Closed'] page.within(find('.board-blank-state')) do click_button('Add default lists') end wait_for_requests - expect(page).to have_selector('.board', count: 3) + expect(page).to have_selector('.board', count: 4) page.all('.board').each_with_index do |list, i| expect(list.find('.board-title')).to have_content(lists[i]) @@ -81,33 +82,29 @@ describe 'Issue Boards', feature: true, js: true do let!(:issue9) { create(:labeled_issue, project: project, labels: [planning, testing, bug, accepting], relative_position: 1) } before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 3) - expect(find('.board:nth-child(1)')).to have_selector('.card') + expect(page).to have_selector('.board', count: 4) expect(find('.board:nth-child(2)')).to have_selector('.card') expect(find('.board:nth-child(3)')).to have_selector('.card') - end - - it 'shows lists' do - expect(page).to have_selector('.board', count: 3) + expect(find('.board:nth-child(4)')).to have_selector('.card') end it 'shows description tooltip on list title' do - page.within('.board:nth-child(1)') do + page.within('.board:nth-child(2)') do expect(find('.board-title span.has-tooltip')[:title]).to eq('Test') end end it 'shows issues in lists' do - wait_for_board_cards(1, 8) - wait_for_board_cards(2, 2) + wait_for_board_cards(2, 8) + wait_for_board_cards(3, 2) end it 'shows confidential issues with icon' do - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page).to have_selector('.confidential-icon', count: 1) end end @@ -118,9 +115,9 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - expect(find('.board:nth-child(1)')).to have_selector('.card', count: 0) expect(find('.board:nth-child(2)')).to have_selector('.card', count: 0) - expect(find('.board:nth-child(3)')).to have_selector('.card', count: 1) + expect(find('.board:nth-child(3)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 1) end it 'search list' do @@ -129,32 +126,32 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - expect(find('.board:nth-child(1)')).to have_selector('.card', count: 1) - expect(find('.board:nth-child(2)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 1) expect(find('.board:nth-child(3)')).to have_selector('.card', count: 0) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 0) end it 'allows user to delete board' do - page.within(find('.board:nth-child(1)')) do + page.within(find('.board:nth-child(2)')) do find('.board-delete').click end wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'removes checkmark in new list dropdown after deleting' do click_button 'Add list' wait_for_requests - page.within(find('.board:nth-child(1)')) do + page.within(find('.board:nth-child(2)')) do find('.board-delete').click end wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'infinite scrolls list' do @@ -162,21 +159,21 @@ describe 'Issue Boards', feature: true, js: true do create(:labeled_issue, project: project, labels: [planning]) end - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page.find('.board-header')).to have_content('58') expect(page).to have_selector('.card', count: 20) expect(page).to have_content('Showing 20 of 58 issues') - evaluate_script("document.querySelectorAll('.board .board-list')[0].scrollTop = document.querySelectorAll('.board .board-list')[0].scrollHeight") + evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight") wait_for_requests expect(page).to have_selector('.card', count: 40) expect(page).to have_content('Showing 40 of 58 issues') - evaluate_script("document.querySelectorAll('.board .board-list')[0].scrollTop = document.querySelectorAll('.board .board-list')[0].scrollHeight") + evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight") wait_for_requests expect(page).to have_selector('.card', count: 58) @@ -186,83 +183,83 @@ describe 'Issue Boards', feature: true, js: true do context 'closed' do it 'shows list of closed issues' do - wait_for_board_cards(3, 1) + wait_for_board_cards(4, 1) wait_for_requests end it 'moves issue to closed' do - drag(list_from_index: 0, list_to_index: 2) + drag(list_from_index: 1, list_to_index: 3) - wait_for_board_cards(1, 7) - wait_for_board_cards(2, 2) + wait_for_board_cards(2, 7) wait_for_board_cards(3, 2) + wait_for_board_cards(4, 2) - expect(find('.board:nth-child(1)')).not_to have_content(issue9.title) - expect(find('.board:nth-child(3)')).to have_selector('.card', count: 2) - expect(find('.board:nth-child(3)')).to have_content(issue9.title) - expect(find('.board:nth-child(3)')).not_to have_content(planning.title) + expect(find('.board:nth-child(2)')).not_to have_content(issue9.title) + expect(find('.board:nth-child(4)')).to have_selector('.card', count: 2) + expect(find('.board:nth-child(4)')).to have_content(issue9.title) + expect(find('.board:nth-child(4)')).not_to have_content(planning.title) end it 'removes all of the same issue to closed' do - drag(list_from_index: 0, list_to_index: 2) + drag(list_from_index: 1, list_to_index: 3) - wait_for_board_cards(1, 7) - wait_for_board_cards(2, 2) + wait_for_board_cards(2, 7) wait_for_board_cards(3, 2) + wait_for_board_cards(4, 2) - expect(find('.board:nth-child(1)')).not_to have_content(issue9.title) - expect(find('.board:nth-child(3)')).to have_content(issue9.title) - expect(find('.board:nth-child(3)')).not_to have_content(planning.title) + expect(find('.board:nth-child(2)')).not_to have_content(issue9.title) + expect(find('.board:nth-child(4)')).to have_content(issue9.title) + expect(find('.board:nth-child(4)')).not_to have_content(planning.title) end end context 'lists' do it 'changes position of list' do - drag(list_from_index: 1, list_to_index: 0, selector: '.board-header') + drag(list_from_index: 2, list_to_index: 1, selector: '.board-header') - wait_for_board_cards(1, 2) - wait_for_board_cards(2, 8) - wait_for_board_cards(3, 1) + wait_for_board_cards(2, 2) + wait_for_board_cards(3, 8) + wait_for_board_cards(4, 1) - expect(find('.board:nth-child(1)')).to have_content(development.title) - expect(find('.board:nth-child(1)')).to have_content(planning.title) + expect(find('.board:nth-child(2)')).to have_content(development.title) + expect(find('.board:nth-child(2)')).to have_content(planning.title) end it 'issue moves between lists' do - drag(list_from_index: 0, from_index: 1, list_to_index: 1) + drag(list_from_index: 1, from_index: 1, list_to_index: 2) - wait_for_board_cards(1, 7) - wait_for_board_cards(2, 2) - wait_for_board_cards(3, 1) + wait_for_board_cards(2, 7) + wait_for_board_cards(3, 2) + wait_for_board_cards(4, 1) - expect(find('.board:nth-child(2)')).to have_content(issue6.title) - expect(find('.board:nth-child(2)').all('.card').last).not_to have_content(development.title) + expect(find('.board:nth-child(3)')).to have_content(issue6.title) + expect(find('.board:nth-child(3)').all('.card').last).not_to have_content(development.title) end it 'issue moves between lists' do - drag(list_from_index: 1, list_to_index: 0) + drag(list_from_index: 2, list_to_index: 1) - wait_for_board_cards(1, 9) - wait_for_board_cards(2, 1) + wait_for_board_cards(2, 9) wait_for_board_cards(3, 1) + wait_for_board_cards(4, 1) - expect(find('.board:nth-child(1)')).to have_content(issue7.title) - expect(find('.board:nth-child(1)').all('.card').first).not_to have_content(planning.title) + expect(find('.board:nth-child(2)')).to have_content(issue7.title) + expect(find('.board:nth-child(2)').all('.card').first).not_to have_content(planning.title) end it 'issue moves from closed' do - drag(list_from_index: 2, list_to_index: 1) + drag(list_from_index: 2, list_to_index: 3) - expect(find('.board:nth-child(2)')).to have_content(issue8.title) + wait_for_board_cards(2, 8) + wait_for_board_cards(3, 1) + wait_for_board_cards(4, 2) - wait_for_board_cards(1, 8) - wait_for_board_cards(2, 3) - wait_for_board_cards(3, 0) + expect(find('.board:nth-child(4)')).to have_content(issue8.title) end context 'issue card' do it 'shows assignee' do - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page).to have_selector('.avatar', count: 1) end end @@ -290,7 +287,7 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - expect(page).to have_selector('.board', count: 4) + expect(page).to have_selector('.board', count: 5) end it 'creates new list for Backlog label' do @@ -303,7 +300,7 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - expect(page).to have_selector('.board', count: 4) + expect(page).to have_selector('.board', count: 5) end it 'creates new list for Closed label' do @@ -316,7 +313,7 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - expect(page).to have_selector('.board', count: 4) + expect(page).to have_selector('.board', count: 5) end it 'keeps dropdown open after adding new list' do @@ -348,7 +345,7 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests wait_for_requests - expect(page).to have_selector('.board', count: 4) + expect(page).to have_selector('.board', count: 5) end end end @@ -360,8 +357,8 @@ describe 'Issue Boards', feature: true, js: true do submit_filter wait_for_requests - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) end it 'filters by assignee' do @@ -371,8 +368,8 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) end it 'filters by milestone' do @@ -381,9 +378,9 @@ describe 'Issue Boards', feature: true, js: true do submit_filter wait_for_requests - wait_for_board_cards(1, 1) - wait_for_board_cards(2, 0) + wait_for_board_cards(2, 1) wait_for_board_cards(3, 0) + wait_for_board_cards(4, 0) end it 'filters by label' do @@ -392,8 +389,8 @@ describe 'Issue Boards', feature: true, js: true do submit_filter wait_for_requests - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) end it 'filters by label with space after reload' do @@ -403,17 +400,17 @@ describe 'Issue Boards', feature: true, js: true do # Test after reload page.evaluate_script 'window.location.reload()' - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) wait_for_requests - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page.find('.board-header')).to have_content('1') expect(page).to have_selector('.card', count: 1) end - page.within(find('.board:nth-child(2)')) do + page.within(find('.board:nth-child(3)')) do expect(page.find('.board-header')).to have_content('0') expect(page).to have_selector('.card', count: 0) end @@ -424,12 +421,12 @@ describe 'Issue Boards', feature: true, js: true do click_filter_link(testing.title) submit_filter - wait_for_board_cards(1, 1) + wait_for_board_cards(2, 1) find('.clear-search').click submit_filter - wait_for_board_cards(1, 8) + wait_for_board_cards(2, 8) end it 'infinite scrolls list with label filter' do @@ -443,17 +440,17 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page.find('.board-header')).to have_content('51') expect(page).to have_selector('.card', count: 20) expect(page).to have_content('Showing 20 of 51 issues') - evaluate_script("document.querySelectorAll('.board .board-list')[0].scrollTop = document.querySelectorAll('.board .board-list')[0].scrollHeight") + evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight") expect(page).to have_selector('.card', count: 40) expect(page).to have_content('Showing 40 of 51 issues') - evaluate_script("document.querySelectorAll('.board .board-list')[0].scrollTop = document.querySelectorAll('.board .board-list')[0].scrollHeight") + evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight") expect(page).to have_selector('.card', count: 51) expect(page).to have_content('Showing all issues') @@ -471,12 +468,12 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) end it 'filters by clicking label button on issue' do - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do expect(page).to have_selector('.card', count: 8) expect(find('.card', match: :first)).to have_content(bug.title) click_button(bug.title) @@ -489,12 +486,12 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - wait_for_board_cards(1, 1) - wait_for_empty_boards((2..3)) + wait_for_board_cards(2, 1) + wait_for_empty_boards((3..4)) end it 'removes label filter by clicking label button on issue' do - page.within(find('.board', match: :first)) do + page.within(find('.board:nth-child(2)')) do page.within(find('.card', match: :first)) do click_button(bug.title) end @@ -511,7 +508,7 @@ describe 'Issue Boards', feature: true, js: true do context 'keyboard shortcuts' do before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests end @@ -523,8 +520,8 @@ describe 'Issue Boards', feature: true, js: true do context 'signed out user' do before do - logout - visit namespace_project_board_path(project.namespace, project, board) + sign_out(:user) + visit project_board_path(project, board) wait_for_requests end @@ -546,9 +543,9 @@ describe 'Issue Boards', feature: true, js: true do before do project.team << [user_guest, :guest] - logout - login_as(user_guest) - visit namespace_project_board_path(project.namespace, project, board) + sign_out(:user) + sign_in(user_guest) + visit project_board_path(project, board) wait_for_requests end diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb index 6c40cb2c9eb..4cbb48e2e6e 100644 --- a/spec/features/boards/issue_ordering_spec.rb +++ b/spec/features/boards/issue_ordering_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Issue Boards', :feature, :js do +describe 'Issue Boards', :js do include DragTo - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:board) { create(:board, project: project) } let(:user) { create(:user) } let(:label) { create(:label, project: project) } @@ -15,21 +15,21 @@ describe 'Issue Boards', :feature, :js do before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'un-ordered issues' do let!(:issue4) { create(:labeled_issue, project: project, labels: [label]) } before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'has un-ordered issue as last issue' do - page.within(first('.board')) do + page.within(find('.board:nth-child(2)')) do expect(all('.card').last).to have_content(issue4.title) end end @@ -39,7 +39,7 @@ describe 'Issue Boards', :feature, :js do wait_for_requests - page.within(first('.board')) do + page.within(find('.board:nth-child(2)')) do expect(first('.card')).to have_content(issue4.title) end end @@ -47,10 +47,10 @@ describe 'Issue Boards', :feature, :js do context 'ordering in list' do before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'moves from middle to top' do @@ -110,53 +110,53 @@ describe 'Issue Boards', :feature, :js do let!(:issue6) { create(:labeled_issue, project: project, title: 'testing 3', labels: [label2], relative_position: 1.0) } before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 3) + expect(page).to have_selector('.board', count: 4) end it 'moves to top of another list' do - drag(list_from_index: 0, list_to_index: 1) + drag(list_from_index: 1, list_to_index: 2) wait_for_requests - expect(first('.board')).to have_selector('.card', count: 2) - expect(all('.board')[1]).to have_selector('.card', count: 4) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 2) + expect(all('.board')[2]).to have_selector('.card', count: 4) - page.within(all('.board')[1]) do + page.within(all('.board')[2]) do expect(first('.card')).to have_content(issue3.title) end end it 'moves to bottom of another list' do - drag(list_from_index: 0, list_to_index: 1, to_index: 2) + drag(list_from_index: 1, list_to_index: 2, to_index: 2) wait_for_requests - expect(first('.board')).to have_selector('.card', count: 2) - expect(all('.board')[1]).to have_selector('.card', count: 4) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 2) + expect(all('.board')[2]).to have_selector('.card', count: 4) - page.within(all('.board')[1]) do + page.within(all('.board')[2]) do expect(all('.card').last).to have_content(issue3.title) end end it 'moves to index of another list' do - drag(list_from_index: 0, list_to_index: 1, to_index: 1) + drag(list_from_index: 1, list_to_index: 2, to_index: 1) wait_for_requests - expect(first('.board')).to have_selector('.card', count: 2) - expect(all('.board')[1]).to have_selector('.card', count: 4) + expect(find('.board:nth-child(2)')).to have_selector('.card', count: 2) + expect(all('.board')[2]).to have_selector('.card', count: 4) - page.within(all('.board')[1]) do + page.within(all('.board')[2]) do expect(all('.card')[1]).to have_content(issue3.title) end end end - def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0) + def drag(selector: '.board-list', list_from_index: 1, from_index: 0, to_index: 0, list_to_index: 1) drag_to(selector: selector, scrollable: '#board-app', list_from_index: list_from_index, diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb index c2167ba12cd..61b53aa5d1e 100644 --- a/spec/features/boards/keyboard_shortcut_spec.rb +++ b/spec/features/boards/keyboard_shortcut_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -describe 'Issue Boards shortcut', feature: true, js: true do - let(:project) { create(:empty_project) } +describe 'Issue Boards shortcut', js: true do + let(:project) { create(:project) } before do create(:board, project: project) - login_as :admin + sign_in(create(:admin)) - visit namespace_project_path(project.namespace, project) + visit project_path(project) end it 'takes user to issue board index' do diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb index b6de6143354..422d96175f7 100644 --- a/spec/features/boards/modal_filter_spec.rb +++ b/spec/features/boards/modal_filter_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' -describe 'Issue Boards add issue modal filtering', :feature, :js do - let(:project) { create(:empty_project, :public) } +describe 'Issue Boards add issue modal filtering', :js do + let(:project) { create(:project, :public) } let(:board) { create(:board, project: project) } let(:planning) { create(:label, project: project, name: 'Planning') } let!(:list1) { create(:list, board: board, label: planning, position: 0) } @@ -12,7 +12,7 @@ describe 'Issue Boards add issue modal filtering', :feature, :js do before do project.team << [user, :master] - login_as(user) + sign_in(user) end it 'shows empty state when no results found' do @@ -202,7 +202,7 @@ describe 'Issue Boards add issue modal filtering', :feature, :js do end def visit_board - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests click_button('Add issues') diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index 0e98f994018..f67372337ec 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' -describe 'Issue Boards new issue', feature: true, js: true do - let(:project) { create(:empty_project, :public) } +describe 'Issue Boards new issue', js: true do + let(:project) { create(:project, :public) } let(:board) { create(:board, project: project) } let!(:list) { create(:list, board: board, position: 0) } let(:user) { create(:user) } @@ -10,27 +10,27 @@ describe 'Issue Boards new issue', feature: true, js: true do before do project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests - expect(page).to have_selector('.board', count: 2) + expect(page).to have_selector('.board', count: 3) end it 'displays new issue button' do - expect(page).to have_selector('.board-issue-count-holder .btn', count: 1) + expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1) end it 'does not display new issue button in closed list' do - page.within('.board:nth-child(2)') do - expect(page).not_to have_selector('.board-issue-count-holder .btn') + page.within('.board:nth-child(3)') do + expect(page).not_to have_selector('.issue-count-badge-add-button') end end it 'shows form when clicking button' do page.within(first('.board')) do - find('.board-issue-count-holder .btn').click + find('.issue-count-badge-add-button').click expect(page).to have_selector('.board-new-issue-form') end @@ -38,7 +38,7 @@ describe 'Issue Boards new issue', feature: true, js: true do it 'hides form when clicking cancel' do page.within(first('.board')) do - find('.board-issue-count-holder .btn').click + find('.issue-count-badge-add-button').click expect(page).to have_selector('.board-new-issue-form') @@ -50,7 +50,7 @@ describe 'Issue Boards new issue', feature: true, js: true do it 'creates new issue' do page.within(first('.board')) do - find('.board-issue-count-holder .btn').click + find('.issue-count-badge-add-button').click end page.within(first('.board-new-issue-form')) do @@ -60,14 +60,14 @@ describe 'Issue Boards new issue', feature: true, js: true do wait_for_requests - page.within(first('.board .board-issue-count')) do + page.within(first('.board .issue-count-badge-count')) do expect(page).to have_content('1') end end it 'shows sidebar when creating new issue' do page.within(first('.board')) do - find('.board-issue-count-holder .btn').click + find('.issue-count-badge-add-button').click end page.within(first('.board-new-issue-form')) do @@ -83,12 +83,12 @@ describe 'Issue Boards new issue', feature: true, js: true do context 'unauthorized user' do before do - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests end it 'does not display new issue button' do - expect(page).to have_selector('.board-issue-count-holder .btn', count: 0) + expect(page).to have_selector('.issue-count-badge-add-button', count: 0) end end end diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 34f4d765117..373cd92793e 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Issue Boards', feature: true, js: true do +describe 'Issue Boards', js: true do let(:user) { create(:user) } let(:user2) { create(:user) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let!(:milestone) { create(:milestone, project: project) } let!(:development) { create(:label, project: project, name: 'Development') } let!(:bug) { create(:label, project: project, name: 'Bug') } @@ -13,16 +13,16 @@ describe 'Issue Boards', feature: true, js: true do let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) } let(:board) { create(:board, project: project) } let!(:list) { create(:list, board: board, label: development, position: 0) } - let(:card) { first('.board').first('.card') } + let(:card) { find('.board:nth-child(2)').first('.card') } before do Timecop.freeze project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests end @@ -74,11 +74,27 @@ describe 'Issue Boards', feature: true, js: true do wait_for_requests - page.within(first('.board')) do + page.within(find('.board:nth-child(2)')) do expect(page).to have_selector('.card', count: 1) end end + it 'does not show remove button for backlog or closed issues' do + create(:issue, project: project) + create(:issue, :closed, project: project) + + visit project_board_path(project, board) + wait_for_requests + + click_card(find('.board:nth-child(1)').first('.card')) + + expect(find('.issue-boards-sidebar')).not_to have_button 'Remove from board' + + click_card(find('.board:nth-child(3)').first('.card')) + + expect(find('.issue-boards-sidebar')).not_to have_button 'Remove from board' + end + context 'assignee' do it 'updates the issues assignee' do click_card(card) @@ -101,7 +117,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'removes the assignee' do - card_two = first('.board').find('.card:nth-child(2)') + card_two = find('.board:nth-child(2)').find('.card:nth-child(2)') click_card(card_two) page.within('.assignee') do @@ -154,7 +170,7 @@ describe 'Issue Boards', feature: true, js: true do expect(page).to have_content(user.name) end - page.within(first('.board')) do + page.within(find('.board:nth-child(2)')) do find('.card:nth-child(2)').trigger('click') end diff --git a/spec/features/boards/sub_group_project_spec.rb b/spec/features/boards/sub_group_project_spec.rb index 4cd05010a93..11a54079f4f 100644 --- a/spec/features/boards/sub_group_project_spec.rb +++ b/spec/features/boards/sub_group_project_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Sub-group project issue boards', :feature, :js do +describe 'Sub-group project issue boards', :js do let(:group) { create(:group) } let(:nested_group_1) { create(:group, parent: group) } - let(:project) { create(:empty_project, group: nested_group_1) } + let(:project) { create(:project, group: nested_group_1) } let(:board) { create(:board, project: project) } let(:label) { create(:label, project: project) } let(:user) { create(:user) } @@ -13,9 +13,9 @@ describe 'Sub-group project issue boards', :feature, :js do before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_board_path(project.namespace, project, board) + visit project_board_path(project, board) wait_for_requests end diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index 1b6d8439f92..64fbc80cb81 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Contributions Calendar', :feature, :js do +feature 'Contributions Calendar', :js do let(:user) { create(:user) } - let(:contributed_project) { create(:empty_project, :public) } + let(:contributed_project) { create(:project, :public) } let(:issue_note) { create(:note, project: contributed_project) } # Ex/ Sunday Jan 1, 2016 @@ -68,7 +68,7 @@ feature 'Contributions Calendar', :feature, :js do end before do - login_as user + sign_in user end describe 'calendar day selection' do diff --git a/spec/features/ci_lint_spec.rb b/spec/features/ci_lint_spec.rb index 3ebc432206a..af4cc00162a 100644 --- a/spec/features/ci_lint_spec.rb +++ b/spec/features/ci_lint_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'CI Lint', js: true do before do - login_as :user + sign_in(create(:user)) end describe 'YAML parsing' do diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 2772f05982a..0c9fcc60d30 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -4,10 +4,11 @@ describe 'Commits' do include CiStatusHelper let(:project) { create(:project, :repository) } + let(:user) { create(:user) } describe 'CI' do before do - login_as :user + sign_in(user) stub_ci_pipeline_to_return_yaml_file end @@ -27,7 +28,7 @@ describe 'Commits' do let!(:status) { create(:generic_commit_status, pipeline: pipeline) } before do - project.team << [@user, :reporter] + project.team << [user, :reporter] end describe 'Commit builds' do @@ -52,7 +53,7 @@ describe 'Commits' do context 'when logged as developer' do before do - project.team << [@user, :developer] + project.team << [user, :developer] end describe 'Project commits' do @@ -65,7 +66,7 @@ describe 'Commits' do end before do - visit namespace_project_commits_path(project.namespace, project, :master) + visit project_commits_path(project, :master) end it 'shows correct build status from default branch' do @@ -76,7 +77,7 @@ describe 'Commits' do end end - describe 'Commit builds', :feature, :js do + describe 'Commit builds', :js do before do visit ci_status_path(pipeline) end @@ -146,12 +147,12 @@ describe 'Commits' do context "when logged as reporter" do before do - project.team << [@user, :reporter] + project.team << [user, :reporter] build.update_attributes(artifacts_file: artifacts_file) visit ci_status_path(pipeline) end - it 'Renders header', :feature, :js do + it 'Renders header', :js do expect(page).to have_content pipeline.sha[0..7] expect(page).to have_content pipeline.git_commit_message expect(page).to have_content pipeline.user.name @@ -164,7 +165,7 @@ describe 'Commits' do end end - context 'when accessing internal project with disallowed access', :feature, :js do + context 'when accessing internal project with disallowed access', :js do before do project.update( visibility_level: Gitlab::VisibilityLevel::INTERNAL, @@ -187,12 +188,11 @@ describe 'Commits' do context 'viewing commits for a branch' do let(:branch_name) { 'master' } - let(:user) { create(:user) } before do project.team << [user, :master] - login_with(user) - visit namespace_project_commits_path(project.namespace, project, branch_name) + sign_in(user) + visit project_commits_path(project, branch_name) end it 'includes the committed_date for each commit' do @@ -203,4 +203,105 @@ describe 'Commits' do end end end + + describe 'GPG signed commits', :js do + it 'changes from unverified to verified when the user changes his email to match the gpg key' do + user = create :user, email: 'unrelated.user@example.org' + project.team << [user, :master] + + Sidekiq::Testing.inline! do + create :gpg_key, key: GpgHelpers::User1.public_key, user: user + end + + sign_in(user) + + visit project_commits_path(project, :'signed-commits') + + within '#commits-list' do + expect(page).to have_content 'Unverified' + expect(page).not_to have_content 'Verified' + end + + # user changes his email which makes the gpg key verified + Sidekiq::Testing.inline! do + user.skip_reconfirmation! + user.update_attributes!(email: GpgHelpers::User1.emails.first) + end + + visit project_commits_path(project, :'signed-commits') + + within '#commits-list' do + expect(page).to have_content 'Unverified' + expect(page).to have_content 'Verified' + end + end + + it 'changes from unverified to verified when the user adds the missing gpg key' do + user = create :user, email: GpgHelpers::User1.emails.first + project.team << [user, :master] + + sign_in(user) + + visit project_commits_path(project, :'signed-commits') + + within '#commits-list' do + expect(page).to have_content 'Unverified' + expect(page).not_to have_content 'Verified' + end + + # user adds the gpg key which makes the signature valid + Sidekiq::Testing.inline! do + create :gpg_key, key: GpgHelpers::User1.public_key, user: user + end + + visit project_commits_path(project, :'signed-commits') + + within '#commits-list' do + expect(page).to have_content 'Unverified' + expect(page).to have_content 'Verified' + end + end + + it 'shows popover badges' do + gpg_user = create :user, email: GpgHelpers::User1.emails.first, username: 'nannie.bernhard', name: 'Nannie Bernhard' + Sidekiq::Testing.inline! do + create :gpg_key, key: GpgHelpers::User1.public_key, user: gpg_user + end + + user = create :user + project.team << [user, :master] + + sign_in(user) + visit project_commits_path(project, :'signed-commits') + + # unverified signature + click_on 'Unverified', match: :first + within '.popover' do + expect(page).to have_content 'This commit was signed with an unverified signature.' + expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}" + end + + # verified and the gpg user has a gitlab profile + click_on 'Verified', match: :first + within '.popover' do + expect(page).to have_content 'This commit was signed with a verified signature.' + expect(page).to have_content 'Nannie Bernhard' + expect(page).to have_content '@nannie.bernhard' + expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}" + end + + # verified and the gpg user's profile doesn't exist anymore + gpg_user.destroy! + + visit project_commits_path(project, :'signed-commits') + + click_on 'Verified', match: :first + within '.popover' do + expect(page).to have_content 'This commit was signed with a verified signature.' + expect(page).to have_content 'Nannie Bernhard' + expect(page).to have_content 'nannie.bernhard@example.com' + expect(page).to have_content "GPG Key ID: #{GpgHelpers::User1.primary_keyid}" + end + end + end end diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb index fa7adbe71ea..ae39ba4da6b 100644 --- a/spec/features/container_registry_spec.rb +++ b/spec/features/container_registry_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' describe "Container Registry" do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:container_repository) do create(:container_repository, name: 'my/image') end before do - login_as(user) + sign_in(user) project.add_developer(user) stub_container_registry_config(enabled: true) stub_container_registry_tags(repository: :any, tags: []) @@ -55,7 +55,6 @@ describe "Container Registry" do end def visit_container_registry - visit namespace_project_container_registry_index_path( - project.namespace, project) + visit project_container_registry_index_path(project) end end diff --git a/spec/features/copy_as_gfm_spec.rb b/spec/features/copy_as_gfm_spec.rb index 740f60c05cc..3e6a27eafd8 100644 --- a/spec/features/copy_as_gfm_spec.rb +++ b/spec/features/copy_as_gfm_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -describe 'Copy as GFM', feature: true, js: true do +describe 'Copy as GFM', js: true do include MarkupHelper include RepoHelpers include ActionView::Helpers::JavaScriptHelper before do - login_as :admin + sign_in(create(:admin)) end describe 'Copying rendered GFM' do @@ -16,7 +16,7 @@ describe 'Copy as GFM', feature: true, js: true do # `markdown` helper expects a `@project` variable @project = @feat.project - visit namespace_project_issue_path(@project.namespace, @project, @feat.issue) + visit project_issue_path(@project, @feat.issue) end # The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb convert GitLab Flavored Markdown (GFM) to HTML. @@ -121,13 +121,13 @@ describe 'Copy as GFM', feature: true, js: true do # full issue reference @feat.issue.to_reference(full: true), # issue URL - namespace_project_issue_url(@project.namespace, @project, @feat.issue), + project_issue_url(@project, @feat.issue), # issue URL with note anchor - namespace_project_issue_url(@project.namespace, @project, @feat.issue, anchor: 'note_123'), + project_issue_url(@project, @feat.issue, anchor: 'note_123'), # issue link - "[Issue](#{namespace_project_issue_url(@project.namespace, @project, @feat.issue)})", + "[Issue](#{project_issue_url(@project, @feat.issue)})", # issue link with note anchor - "[Issue](#{namespace_project_issue_url(@project.namespace, @project, @feat.issue, anchor: 'note_123')})" + "[Issue](#{project_issue_url(@project, @feat.issue, anchor: 'note_123')})" ) verify( @@ -466,7 +466,7 @@ describe 'Copy as GFM', feature: true, js: true do context 'from a diff' do before do - visit namespace_project_commit_path(project.namespace, project, sample_commit.id) + visit project_commit_path(project, sample_commit.id) end context 'selecting one word of text' do @@ -507,7 +507,7 @@ describe 'Copy as GFM', feature: true, js: true do context 'from a blob' do before do - visit namespace_project_blob_path(project.namespace, project, File.join('master', 'files/ruby/popen.rb')) + visit project_blob_path(project, File.join('master', 'files/ruby/popen.rb')) wait_for_requests end @@ -549,7 +549,7 @@ describe 'Copy as GFM', feature: true, js: true do context 'from a GFM code block' do before do - visit namespace_project_blob_path(project.namespace, project, File.join('markdown', 'doc/api/users.md')) + visit project_blob_path(project, File.join('markdown', 'doc/api/users.md')) wait_for_requests end diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index b416bbd3c79..5c60cca10b9 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Cycle Analytics', feature: true, js: true do +feature 'Cycle Analytics', js: true do let(:user) { create(:user) } let(:guest) { create(:user) } let(:project) { create(:project, :repository) } @@ -14,9 +14,9 @@ feature 'Cycle Analytics', feature: true, js: true do before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_cycle_analytics_path(project.namespace, project) + visit project_cycle_analytics_path(project) wait_for_requests end @@ -38,8 +38,8 @@ feature 'Cycle Analytics', feature: true, js: true do create_cycle deploy_master - login_as(user) - visit namespace_project_cycle_analytics_path(project.namespace, project) + sign_in(user) + visit project_cycle_analytics_path(project) end it 'shows data on each stage' do @@ -70,8 +70,8 @@ feature 'Cycle Analytics', feature: true, js: true do user.update_attribute(:preferred_language, 'es') project.team << [user, :master] - login_as(user) - visit namespace_project_cycle_analytics_path(project.namespace, project) + sign_in(user) + visit project_cycle_analytics_path(project) wait_for_requests end @@ -93,8 +93,8 @@ feature 'Cycle Analytics', feature: true, js: true do create_cycle deploy_master - login_as(guest) - visit namespace_project_cycle_analytics_path(project.namespace, project) + sign_in(guest) + visit project_cycle_analytics_path(project) wait_for_requests end diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb index ae750be4d4a..067e4337e6a 100644 --- a/spec/features/dashboard/active_tab_spec.rb +++ b/spec/features/dashboard/active_tab_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -RSpec.describe 'Dashboard Active Tab', js: true, feature: true do +RSpec.describe 'Dashboard Active Tab', js: true do before do - login_as :user + sign_in(create(: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..4917dfcf1d1 100644 --- a/spec/features/dashboard/activity_spec.rb +++ b/spec/features/dashboard/activity_spec.rb @@ -1,11 +1,162 @@ require 'spec_helper' -RSpec.describe 'Dashboard Activity', feature: true do +feature 'Dashboard > Activity' do + let(:user) { create(:user) } + before do - login_as(create :user) - visit activity_dashboard_path + sign_in(user) + end + + context 'rss' do + before do + visit activity_dashboard_path + 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 - 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" + context 'event filters', :js do + let(:project) { create(:project) } + + let(:merge_request) do + create(:merge_request, author: user, source_project: project, target_project: project) + end + + let(:push_event_data) do + { + before: Gitlab::Git::BLANK_SHA, + after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e', + ref: 'refs/heads/new_design', + user_id: user.id, + user_name: user.name, + repository: { + name: project.name, + url: 'localhost/rubinius', + description: '', + homepage: 'localhost/rubinius', + private: true + } + } + end + + let(:note) { create(:note, project: project, noteable: merge_request) } + + let!(:push_event) do + create(:event, :pushed, data: push_event_data, project: project, author: user) + end + + let!(:merged_event) do + create(:event, :merged, project: project, target: merge_request, author: user) + end + + let!(:joined_event) do + create(:event, :joined, project: project, author: user) + end + + let!(:closed_event) do + create(:event, :closed, project: project, target: merge_request, author: user) + end + + let!(:comments_event) do + create(:event, :commented, project: project, target: note, author: user) + end + + before do + project.add_master(user) + + visit activity_dashboard_path + wait_for_requests + end + + scenario 'user should see all events' do + within '.content_list' do + expect(page).to have_content('pushed new branch') + expect(page).to have_content('joined') + expect(page).to have_content('accepted') + expect(page).to have_content('closed') + expect(page).to have_content('commented on') + end + end + + scenario 'user should see only pushed events' do + click_link('Push events') + wait_for_requests + + within '.content_list' do + expect(page).to have_content('pushed new branch') + expect(page).not_to have_content('joined') + expect(page).not_to have_content('accepted') + expect(page).not_to have_content('closed') + expect(page).not_to have_content('commented on') + end + end + + scenario 'user should see only merged events' do + click_link('Merge events') + wait_for_requests + + within '.content_list' do + expect(page).not_to have_content('pushed new branch') + expect(page).not_to have_content('joined') + expect(page).to have_content('accepted') + expect(page).not_to have_content('closed') + expect(page).not_to have_content('commented on') + end + end + + scenario 'user should see only issues events' do + click_link('Issue events') + wait_for_requests + + within '.content_list' do + expect(page).not_to have_content('pushed new branch') + expect(page).not_to have_content('joined') + expect(page).not_to have_content('accepted') + expect(page).to have_content('closed') + expect(page).not_to have_content('commented on') + end + end + + scenario 'user should see only comments events' do + click_link('Comments') + wait_for_requests + + within '.content_list' do + expect(page).not_to have_content('pushed new branch') + expect(page).not_to have_content('joined') + expect(page).not_to have_content('accepted') + expect(page).not_to have_content('closed') + expect(page).to have_content('commented on') + end + end + + scenario 'user should see only joined events' do + click_link('Team') + wait_for_requests + + within '.content_list' do + expect(page).not_to have_content('pushed new branch') + expect(page).to have_content('joined') + expect(page).not_to have_content('accepted') + expect(page).not_to have_content('closed') + expect(page).not_to have_content('commented on') + end + end + + scenario 'user see selected event after page reloading' do + click_link('Push events') + wait_for_requests + visit activity_dashboard_path + wait_for_requests + + within '.content_list' do + expect(page).to have_content('pushed new branch') + expect(page).not_to have_content('joined') + expect(page).not_to have_content('accepted') + expect(page).not_to have_content('closed') + expect(page).not_to have_content('commented on') + end + end + end end diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb index f33bcbb5318..814ec0e59c7 100644 --- a/spec/features/dashboard/archived_projects_spec.rb +++ b/spec/features/dashboard/archived_projects_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -RSpec.describe 'Dashboard Archived Project', feature: true do +RSpec.describe 'Dashboard Archived Project' do let(:user) { create :user } let(:project) { create :project} let(:archived_project) { create(:project, :archived) } @@ -9,7 +9,7 @@ RSpec.describe 'Dashboard Archived Project', feature: true do project.team << [user, :master] archived_project.team << [user, :master] - login_as(user) + 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..b6dce1b8ec4 100644 --- a/spec/features/dashboard/datetime_on_tooltips_spec.rb +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Tooltips on .timeago dates', feature: true, js: true do +feature 'Tooltips on .timeago dates', 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 + 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 + 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..60a16830cdc 100644 --- a/spec/features/dashboard/group_spec.rb +++ b/spec/features/dashboard/group_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -RSpec.describe 'Dashboard Group', feature: true do +RSpec.describe 'Dashboard Group' do before do - login_as(:user) + sign_in(create(: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 b0e2953dda2..533df7a325c 100644 --- a/spec/features/dashboard/groups_list_spec.rb +++ b/spec/features/dashboard/groups_list_spec.rb @@ -1,45 +1,129 @@ require 'spec_helper' -describe 'Dashboard Groups page', js: true, feature: true do +feature 'Dashboard Groups page', :js do let!(:user) { create :user } let!(:group) { create(:group) } let!(:nested_group) { create(:group, :nested) } let!(:another_group) { create(:group) } - before do + it 'shows groups user is member of' do group.add_owner(user) nested_group.add_owner(user) - login_as(user) - + sign_in(user) visit dashboard_groups_path - end - it 'shows groups user is member of' do expect(page).to have_content(group.full_name) expect(page).to have_content(nested_group.full_name) expect(page).not_to have_content(another_group.full_name) end - it 'filters groups' do - fill_in 'filter_groups', with: group.name - wait_for_requests + describe 'when filtering groups' do + before do + group.add_owner(user) + nested_group.add_owner(user) - expect(page).to have_content(group.full_name) - expect(page).not_to have_content(nested_group.full_name) - expect(page).not_to have_content(another_group.full_name) + sign_in(user) + + visit dashboard_groups_path + end + + it 'filters groups' do + fill_in 'filter_groups', with: group.name + wait_for_requests + + expect(page).to have_content(group.full_name) + expect(page).not_to have_content(nested_group.full_name) + expect(page).not_to have_content(another_group.full_name) + end + + it 'resets search when user cleans the input' do + fill_in 'filter_groups', with: group.name + wait_for_requests + + fill_in 'filter_groups', with: '' + wait_for_requests + + expect(page).to have_content(group.full_name) + expect(page).to have_content(nested_group.full_name) + expect(page).not_to have_content(another_group.full_name) + expect(page.all('.js-groups-list-holder .content-list li').length).to eq 2 + end end - it 'resets search when user cleans the input' do - fill_in 'filter_groups', with: group.name - wait_for_requests + describe 'group with subgroups' do + let!(:subgroup) { create(:group, :public, parent: group) } - fill_in 'filter_groups', with: "" - wait_for_requests + before do + group.add_owner(user) + subgroup.add_owner(user) - expect(page).to have_content(group.full_name) - expect(page).to have_content(nested_group.full_name) - expect(page).not_to have_content(another_group.full_name) - expect(page.all('.js-groups-list-holder .content-list li').length).to eq 2 + sign_in(user) + + visit dashboard_groups_path + end + + it 'shows subgroups inside of its parent group' do + expect(page).to have_selector('.groups-list-tree-container .group-list-tree', count: 2) + expect(page).to have_selector(".groups-list-tree-container #group-#{group.id} #group-#{subgroup.id}", count: 1) + end + + it 'can toggle parent group' do + # Expanded by default + expect(page).to have_selector("#group-#{group.id} .fa-caret-down", count: 1) + expect(page).not_to have_selector("#group-#{group.id} .fa-caret-right") + + # Collapse + find("#group-#{group.id}").trigger('click') + + expect(page).not_to have_selector("#group-#{group.id} .fa-caret-down") + expect(page).to have_selector("#group-#{group.id} .fa-caret-right", count: 1) + expect(page).not_to have_selector("#group-#{group.id} #group-#{subgroup.id}") + + # Expand + find("#group-#{group.id}").trigger('click') + + expect(page).to have_selector("#group-#{group.id} .fa-caret-down", count: 1) + expect(page).not_to have_selector("#group-#{group.id} .fa-caret-right") + expect(page).to have_selector("#group-#{group.id} #group-#{subgroup.id}") + end + end + + describe 'when using pagination' do + let(:group2) { create(:group) } + + before do + group.add_owner(user) + group2.add_owner(user) + + allow(Kaminari.config).to receive(:default_per_page).and_return(1) + + sign_in(user) + visit dashboard_groups_path + end + + it 'shows pagination' do + expect(page).to have_selector('.gl-pagination') + expect(page).to have_selector('.gl-pagination .page', count: 2) + end + + it 'loads results for next page' do + # Check first page + expect(page).to have_content(group2.full_name) + expect(page).to have_selector("#group-#{group2.id}") + expect(page).not_to have_content(group.full_name) + expect(page).not_to have_selector("#group-#{group.id}") + + # Go to next page + find(".gl-pagination .page:not(.active) a").trigger('click') + + wait_for_requests + + # Check second page + expect(page).to have_content(group.full_name) + expect(page).to have_selector("#group-#{group.id}") + expect(page).not_to have_content(group2.full_name) + expect(page).not_to have_selector("#group-#{group2.id}") + end end end diff --git a/spec/features/dashboard/help_spec.rb b/spec/features/dashboard/help_spec.rb index 2803f7ec62b..68bfbf22736 100644 --- a/spec/features/dashboard/help_spec.rb +++ b/spec/features/dashboard/help_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -RSpec.describe 'Dashboard Help', feature: true do +RSpec.describe 'Dashboard Help' do before do - login_as(:user) + sign_in(create(: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..b431f72fcc9 100644 --- a/spec/features/dashboard/issuables_counter_spec.rb +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'Navigation bar counter', feature: true, caching: true do +describe 'Navigation bar counter', :use_clean_rails_memory_store_caching do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } before do issue.assignees = [user] merge_request.update(assignee: user) - login_as(user) + sign_in(user) end it 'reflects dashboard issues count' do diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index 1c53f6dff06..facb67ae787 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -1,21 +1,23 @@ require 'spec_helper' -describe "Dashboard Issues filtering", feature: true, js: true do +feature 'Dashboard Issues filtering', :js do + include SortingHelper + let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:milestone) { create(:milestone, project: project) } - context 'filtering by milestone' do - before do - project.team << [user, :master] - login_as(user) + let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + let!(:issue2) { create(:issue, project: project, author: user, assignees: [user], milestone: milestone) } - create(:issue, project: project, author: user, assignees: [user]) - create(:issue, project: project, author: user, assignees: [user], milestone: milestone) + before do + project.add_master(user) + sign_in(user) - visit_issues - end + visit_issues + end + context 'filtering by milestone' do it 'shows all issues with no milestone' do show_milestone_dropdown @@ -62,6 +64,46 @@ describe "Dashboard Issues filtering", feature: true, js: true do end end + context 'filtering by label' do + let(:label) { create(:label, project: project) } + let!(:label_link) { create(:label_link, label: label, target: issue) } + + it 'shows all issues without filter' do + page.within 'ul.content-list' do + expect(page).to have_content issue.title + expect(page).to have_content issue2.title + end + end + + it 'shows all issues with the selected label' do + page.within '.labels-filter' do + find('.dropdown').click + click_link label.title + end + + page.within 'ul.content-list' do + expect(page).to have_content issue.title + expect(page).not_to have_content issue2.title + end + end + end + + context 'sorting' do + it 'shows sorted issues' do + sorting_by('Oldest updated') + visit_issues + + expect(find('.issues-filters')).to have_content('Oldest updated') + end + + it 'keeps sorting issues after visiting Projects Issues page' do + sorting_by('Oldest updated') + visit project_issues_path(project) + + expect(find('.issues-filters')).to have_content('Oldest updated') + end + end + def show_milestone_dropdown click_button 'Milestone' expect(page).to have_selector('.dropdown-content', visible: true) diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index 2cea6b1563e..be6f78ee607 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -1,10 +1,11 @@ require 'spec_helper' -RSpec.describe 'Dashboard Issues', feature: true do +RSpec.describe 'Dashboard Issues' do let(:current_user) { create :user } - let!(:public_project) { create(:empty_project, :public) } - let(:project) { create(:empty_project) } - let(:project_with_issues_disabled) { create(:empty_project, :issues_disabled) } + let(:user) { current_user } # Shared examples depend on this being available + let!(:public_project) { create(:project, :public) } + let(:project) { create(:project) } + let(:project_with_issues_disabled) { create(:project, :issues_disabled) } let!(:authored_issue) { create :issue, author: current_user, project: project } let!(:authored_issue_on_public_project) { create :issue, author: current_user, project: public_project } let!(:assigned_issue) { create :issue, assignees: [current_user], project: project } @@ -12,7 +13,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) + sign_in(current_user) visit issues_dashboard_path(assignee_id: current_user.id) end @@ -59,6 +60,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, 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 @@ -72,5 +78,17 @@ RSpec.describe 'Dashboard Issues', feature: true do expect(page).not_to have_content(project_with_issues_disabled.name_with_namespace) end end + + it 'shows the new issue page', :js do + find('.new-project-item-select-button').trigger('click') + wait_for_requests + find('.select2-results li').click + + expect(page).to have_current_path("/#{project.path_with_namespace}/issues/new") + + page.within('#content-body') do + expect(page).to have_selector('.issue-form') + end + end end end diff --git a/spec/features/dashboard/label_filter_spec.rb b/spec/features/dashboard/label_filter_spec.rb index 4cff12de854..b1a207682c3 100644 --- a/spec/features/dashboard/label_filter_spec.rb +++ b/spec/features/dashboard/label_filter_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Dashboard > label filter', feature: true, js: true do +describe 'Dashboard > label filter', js: true do let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } let(:project2) { create(:project, name: 'test2', path: 'test2', namespace: user.namespace) } @@ -11,7 +11,7 @@ describe 'Dashboard > label filter', feature: true, js: true do project.labels << label project2.labels << label2 - login_as(user) + 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 9cebe52c444..b4992dd54a1 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -1,44 +1,130 @@ require 'spec_helper' -describe 'Dashboard Merge Requests' do +feature 'Dashboard Merge Requests' do + include FilterItemSelectHelper + include SortingHelper + let(:current_user) { create :user } - let(:project) { create(:empty_project) } - let(:project_with_merge_requests_disabled) { create(:empty_project, :merge_requests_disabled) } + let(:project) { create(:project) } - before do - [project, project_with_merge_requests_disabled].each { |project| project.team << [current_user, :master] } + let(:public_project) { create(: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 - before { visit merge_requests_dashboard_path } + context 'new merge request dropdown' do + let(:project_with_disabled_merge_requests) { create(:project, :merge_requests_disabled) } + + before do + project_with_disabled_merge_requests.add_master(current_user) + visit merge_requests_dashboard_path + end it 'shows projects only with merge requests feature enabled', js: true do find('.new-project-item-select-button').trigger('click') 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 + 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 - create(:merge_request, assignee: current_user, source_project: project) + visit merge_requests_dashboard_path(assignee_id: current_user.id) + end + + 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 + + it 'shows sorted merge requests' do + sorting_by('Oldest updated') visit merge_requests_dashboard_path(assignee_id: current_user.id) + + expect(find('.issues-filters')).to have_content('Oldest updated') end - it 'should not show an empty state' do - expect(page).not_to have_selector('.empty-state') + it 'keeps sorting merge requests after visiting Projects MR page' do + sorting_by('Oldest updated') + + visit project_merge_requests_path(project) + + expect(find('.issues-filters')).to have_content('Oldest updated') end end end diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb index b5b92c36895..c965b565ca3 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', :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) + 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 new file mode 100644 index 00000000000..6fcde35f541 --- /dev/null +++ b/spec/features/dashboard/milestone_tabs_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'Dashboard milestone tabs', :js do + let(:user) { create(:user) } + let(:project) { create(:project) } + let!(:label) { create(:label, project: project) } + let(:project_milestone) { create(:milestone, project: project) } + let(:milestone) do + DashboardMilestone.build( + [project], + project_milestone.title + ) + end + let!(:merge_request) { create(:labeled_merge_request, source_project: project, target_project: project, milestone: project_milestone, labels: [label]) } + + before do + project.add_master(user) + sign_in(user) + + visit dashboard_milestone_path(milestone.safe_title, title: milestone.title) + end + + it 'loads merge requests async' do + click_link 'Merge Requests' + + expect(page).to have_selector('.milestone-merge_requests-list') + end + + it 'loads participants async' do + click_link 'Participants' + + expect(page).to have_selector('#tab-participants .bordered-list') + end + + it 'loads labels async' do + click_link 'Labels' + + expect(page).to have_selector('#tab-labels .bordered-list') + end +end diff --git a/spec/features/dashboard_milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb index f32fddbc9fa..41d37376cfb 100644 --- a/spec/features/dashboard_milestones_spec.rb +++ b/spec/features/dashboard/milestones_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Dashboard > Milestones', feature: true do +feature 'Dashboard > Milestones' do describe 'as anonymous user' do before do visit dashboard_milestones_path @@ -13,11 +13,11 @@ feature 'Dashboard > Milestones', feature: true do describe 'as logged-in user' do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } let!(:milestone) { create(:milestone, project: project) } before do project.team << [user, :master] - login_with(user) + sign_in(user) visit dashboard_milestones_path end diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb index cdf919af9b5..4a004107408 100644 --- a/spec/features/dashboard/project_member_activity_index_spec.rb +++ b/spec/features/dashboard/project_member_activity_index_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Project member activity', feature: true, js: true do +feature 'Project member activity', js: true do let(:user) { create(:user) } - let(:project) { create(:empty_project, :public, name: 'x', namespace: user.namespace) } + let(:project) { create(:project, :public, name: 'x', namespace: user.namespace) } before do project.team << [user, :master] @@ -10,26 +10,32 @@ 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 subject { page.find(".event-title").text } context 'when a user joins the project' do - before { visit_activities_and_wait_with_event(Event::JOINED) } + before do + visit_activities_and_wait_with_event(Event::JOINED) + end it { is_expected.to eq("#{user.name} joined project") } end context 'when a user leaves the project' do - before { visit_activities_and_wait_with_event(Event::LEFT) } + before do + visit_activities_and_wait_with_event(Event::LEFT) + end it { is_expected.to eq("#{user.name} left project") } end context 'when a users membership expires for the project' do - before { visit_activities_and_wait_with_event(Event::EXPIRED) } + before do + visit_activities_and_wait_with_event(Event::EXPIRED) + end it "presents the correct message" do message = "#{user.name} removed due to membership expiration from project" diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 3568954a548..06a43909053 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -1,13 +1,19 @@ 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, :repository, name: 'awesome stuff') } let(:project2) { create(:project, :public, name: 'Community project') } before do project.team << [user, :developer] - login_as(user) + sign_in(user) + end + + it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" do + before do + visit dashboard_projects_path + end end it 'shows the project the user in a member of in the list' do @@ -15,13 +21,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 +61,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', clean_gitlab_redis_shared_state: 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,9 +74,50 @@ 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)}']") + page.within('.controls') do + expect(page).to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit)}']") + expect(page).to have_css('.ci-status-link') + expect(page).to have_css('.ci-status-icon-success') + expect(page).to have_link('Commit: passed') + end end end - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + context 'last push widget' do + let(:push_event_data) do + { + before: Gitlab::Git::BLANK_SHA, + after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e', + ref: 'refs/heads/feature', + user_id: user.id, + user_name: user.name, + repository: { + name: project.name, + url: 'localhost/rubinius', + description: '', + homepage: 'localhost/rubinius', + private: true + } + } + end + let!(:push_event) { create(:event, :pushed, data: push_event_data, project: project, author: user) } + + before do + visit dashboard_projects_path + end + + scenario 'shows "Create merge request" button' do + expect(page).to have_content 'You pushed to feature' + + within('#content-body') do + find_link('Create merge request', visible: false).click + end + + expect(page).to have_selector('.merge-request-form') + expect(current_path).to eq project_new_merge_request_path(project) + expect(find('#merge_request_target_project_id').value).to eq project.id.to_s + expect(find('input#merge_request_source_branch').value).to eq 'feature' + expect(find('input#merge_request_target_branch').value).to eq 'master' + end + end end diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index 349b948eaee..5f1f0c10339 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -feature 'Dashboard shortcuts', :feature, :js do +feature 'Dashboard shortcuts', :js do context 'logged in' do before do - login_as :user + sign_in(create(:user)) visit root_dashboard_path end diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb index c6ba118220a..fb4263d74c4 100644 --- a/spec/features/dashboard/snippets_spec.rb +++ b/spec/features/dashboard/snippets_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -describe 'Dashboard snippets', feature: true do +describe 'Dashboard snippets' do context 'when the project has snippets' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } 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) + 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) + sign_in(user) visit dashboard_snippets_path end diff --git a/spec/features/todos/target_state_spec.rb b/spec/features/dashboard/todos/target_state_spec.rb index 32fa88a2b21..030a86d1c01 100644 --- a/spec/features/todos/target_state_spec.rb +++ b/spec/features/dashboard/todos/target_state_spec.rb @@ -1,12 +1,12 @@ require 'rails_helper' -feature 'Todo target states', feature: true do +feature 'Dashboard > Todo target states' do let(:user) { create(:user) } let(:author) { create(:user) } - let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:project) { create(:project, :public) } before do - login_as user + sign_in(user) end scenario 'on a closed issue todo has closed label' do @@ -30,7 +30,7 @@ feature 'Todo target states', feature: true do end scenario 'on a merged merge request todo has merged label' do - mr_merged = create(:merge_request, :simple, author: user, state: 'merged') + mr_merged = create(:merge_request, :simple, :merged, author: user) create_todo mr_merged visit dashboard_todos_path @@ -40,7 +40,7 @@ feature 'Todo target states', feature: true do end scenario 'on a closed merge request todo has closed label' do - mr_closed = create(:merge_request, :simple, author: user, state: 'closed') + mr_closed = create(:merge_request, :simple, :closed, author: user) create_todo mr_closed visit dashboard_todos_path diff --git a/spec/features/todos/todos_filtering_spec.rb b/spec/features/dashboard/todos/todos_filtering_spec.rb index bbfa4e08379..54d477f7274 100644 --- a/spec/features/todos/todos_filtering_spec.rb +++ b/spec/features/dashboard/todos/todos_filtering_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -describe 'Dashboard > User filters todos', feature: true, js: true do +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(:project_1) { create(:project, name: 'project_1') } + let(:project_2) { create(:project, name: 'project_2') } let(:issue) { create(:issue, title: 'issue', project: project_1) } @@ -17,7 +17,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do project_1.team << [user_1, :developer] project_2.team << [user_1, :developer] - login_as(user_1) + sign_in(user_1) visit dashboard_todos_path end @@ -34,7 +34,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do expect(page).not_to have_content project_2.name_with_namespace end - context "Author filter" do + context 'Author filter' do it 'filters by author' do click_button 'Author' @@ -49,18 +49,18 @@ describe 'Dashboard > User filters todos', feature: true, js: true do expect(find('.todos-list')).not_to have_content 'issue' end - it "shows only authors of existing todos" do + it 'shows only authors of existing todos' do click_button 'Author' within '.dropdown-menu-author' do - # It should contain two users + "Any Author" + # 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 + 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) @@ -74,7 +74,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do click_button 'Author' within '.dropdown-menu-author' do - # It should contain two users + "Any Author" + # 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) diff --git a/spec/features/todos/todos_sorting_spec.rb b/spec/features/dashboard/todos/todos_sorting_spec.rb index 4d5bd476301..b7d39a872b0 100644 --- a/spec/features/todos/todos_sorting_spec.rb +++ b/spec/features/dashboard/todos/todos_sorting_spec.rb @@ -1,14 +1,16 @@ require 'spec_helper' -describe "Dashboard > User sorts todos", feature: true do +feature 'Dashboard > User sorts todos' do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(: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 { project.team << [user, :developer] } + before do + project.team << [user, :developer] + end context 'sort options' do let(:issue_1) { create(:issue, title: 'issue_1', project: project) } @@ -16,7 +18,7 @@ describe "Dashboard > User sorts todos", feature: true do 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") } + 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) @@ -30,41 +32,41 @@ describe "Dashboard > User sorts todos", feature: true do issue_2.labels << label_3 issue_1.labels << label_2 - login_as(user) + sign_in(user) visit dashboard_todos_path end - it "sorts with oldest created todos first" do - click_link "Last created" + 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") + 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" + 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") + 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" + 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") + 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 @@ -81,17 +83,17 @@ describe "Dashboard > User sorts todos", feature: true do create(:todo, user: user, project: project, target: issue_2) create(:todo, user: user, project: project, target: merge_request_1) - login_as(user) + sign_in(user) visit dashboard_todos_path end it "doesn't mix issues and merge requests label priorities" do - click_link "Label priority" + 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") + 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..c352b6ded14 100644 --- a/spec/features/dashboard/user_filters_projects_spec.rb +++ b/spec/features/dashboard/user_filters_projects_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Dashboard > User filters projects', :feature do +describe 'Dashboard > User filters projects' do let(:user) { create(:user) } let(:project) { create(:project, name: 'Victorialand', namespace: user.namespace) } let(:user2) { create(:user) } @@ -9,7 +9,7 @@ describe 'Dashboard > User filters projects', :feature do before do project.team << [user, :master] - login_as(user) + sign_in(user) end describe 'filtering personal projects' do diff --git a/spec/features/discussion_comments/commit_spec.rb b/spec/features/discussion_comments/commit_spec.rb index 96e0b78f6b9..0375d0bf8ff 100644 --- a/spec/features/discussion_comments/commit_spec.rb +++ b/spec/features/discussion_comments/commit_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' -describe 'Discussion Comments Merge Request', :feature, :js do +describe 'Discussion Comments Merge Request', :js do include RepoHelpers let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_commit_path(project.namespace, project, sample_commit.id) + visit project_commit_path(project, sample_commit.id) end it_behaves_like 'discussion comments', 'commit' diff --git a/spec/features/discussion_comments/issue_spec.rb b/spec/features/discussion_comments/issue_spec.rb index ccc9efccd18..9812eaf3420 100644 --- a/spec/features/discussion_comments/issue_spec.rb +++ b/spec/features/discussion_comments/issue_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'Discussion Comments Issue', :feature, :js do +describe 'Discussion Comments Issue', :js do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:issue) { create(:issue, project: project) } before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it_behaves_like 'discussion comments', 'issue' diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb index f99ebeb9cd9..b0019c32189 100644 --- a/spec/features/discussion_comments/merge_request_spec.rb +++ b/spec/features/discussion_comments/merge_request_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'Discussion Comments Merge Request', :feature, :js do +describe 'Discussion Comments Merge Request', :js do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it_behaves_like 'discussion comments', 'merge request' diff --git a/spec/features/discussion_comments/snippets_spec.rb b/spec/features/discussion_comments/snippets_spec.rb index 19a306511b2..1e6389d9a13 100644 --- a/spec/features/discussion_comments/snippets_spec.rb +++ b/spec/features/discussion_comments/snippets_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'Discussion Comments Issue', :feature, :js do +describe 'Discussion Comments Issue', :js do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:snippet) { create(:project_snippet, :private, project: project, author: user) } before do project.add_master(user) - login_as(user) + sign_in(user) - visit namespace_project_snippet_path(project.namespace, project, snippet) + visit project_snippet_path(project, snippet) end it_behaves_like 'discussion comments', 'snippet' diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index c4d5077e5e1..357d86497d9 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Expand and collapse diffs', js: true, feature: true do +feature 'Expand and collapse diffs', js: true do let(:branch) { 'expand-collapse-diffs' } let(:project) { create(:project, :repository) } @@ -10,11 +10,11 @@ feature 'Expand and collapse diffs', js: true, feature: true do allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes) allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes) - login_as :admin + sign_in(create(:admin)) # Ensure that undiffable.md is in .gitattributes project.repository.copy_gitattributes(branch) - visit namespace_project_commit_path(project.namespace, project, project.commit(branch)) + visit project_commit_path(project, project.commit(branch)) execute_script('window.ajaxUris = []; $(document).ajaxSend(function(event, xhr, settings) { ajaxUris.push(settings.url) });') end @@ -38,7 +38,7 @@ feature 'Expand and collapse diffs', js: true, feature: true do expect(large_diff).not_to have_selector('.code') expect(large_diff).to have_selector('.nothing-here-block') - visit namespace_project_commit_path(project.namespace, project, project.commit(branch), anchor: "#{large_diff[:id]}_0_1") + visit project_commit_path(project, project.commit(branch), anchor: "#{large_diff[:id]}_0_1") execute_script('window.location.reload()') wait_for_requests @@ -52,7 +52,7 @@ feature 'Expand and collapse diffs', js: true, feature: true do expect(large_diff).not_to have_selector('.code') expect(large_diff).to have_selector('.nothing-here-block') - visit namespace_project_commit_path(project.namespace, project, project.commit(branch), anchor: large_diff[:id]) + visit project_commit_path(project, project.commit(branch), anchor: large_diff[:id]) execute_script('window.location.reload()') wait_for_requests @@ -129,7 +129,7 @@ feature 'Expand and collapse diffs', js: true, feature: true do before do large_diff.find('.diff-line-num', match: :prefer_exact).hover - large_diff.find('.add-diff-note').click + large_diff.find('.add-diff-note', match: :prefer_exact).click large_diff.find('.note-textarea').send_keys comment_text large_diff.find_button('Comment').click wait_for_requests @@ -140,7 +140,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do end context 'reloading the page' do - before { refresh } + before do + refresh + end it 'collapses the large diff by default' do expect(large_diff).not_to have_selector('.code') @@ -262,7 +264,7 @@ feature 'Expand and collapse diffs', js: true, feature: true do # Wait for elements to appear to ensure full page reload expect(page).to have_content('This diff was suppressed by a .gitattributes entry') - expect(page).to have_content('This diff could not be displayed because it is too large.') + expect(page).to have_content('This source diff could not be displayed because it is too large.') expect(page).to have_content('too_large_image.jpg') find('.note-textarea') diff --git a/spec/features/explore/groups_list_spec.rb b/spec/features/explore/groups_list_spec.rb index d4284ed099b..b5325301968 100644 --- a/spec/features/explore/groups_list_spec.rb +++ b/spec/features/explore/groups_list_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -describe 'Explore Groups page', :js, :feature do +describe 'Explore Groups page', :js do let!(:user) { create :user } let!(:group) { create(:group) } let!(:public_group) { create(:group, :public) } let!(:private_group) { create(:group, :private) } - let!(:empty_project) { create(:empty_project, group: public_group) } + let!(:empty_project) { create(:project, group: public_group) } before do group.add_owner(user) - login_as(user) + sign_in(user) visit explore_groups_path end diff --git a/spec/features/explore/new_menu_spec.rb b/spec/features/explore/new_menu_spec.rb new file mode 100644 index 00000000000..2cd06258e22 --- /dev/null +++ b/spec/features/explore/new_menu_spec.rb @@ -0,0 +1,173 @@ +require 'spec_helper' + +feature 'Top Plus Menu', :js do + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:project, :repository, creator: user, namespace: user.namespace) } + let(:public_project) { create(:project, :public) } + + before do + group.add_owner(user) + end + + context 'used by full user' do + before do + sign_in(user) + end + + scenario 'click on New project shows new project page' do + visit root_dashboard_path + + click_topmenuitem("New project") + + expect(page).to have_content('Project path') + expect(page).to have_content('Project name') + end + + scenario 'click on New group shows new group page' do + visit root_dashboard_path + + click_topmenuitem("New group") + + expect(page).to have_content('Group path') + expect(page).to have_content('Group name') + end + + scenario 'click on New snippet shows new snippet page' do + visit root_dashboard_path + + click_topmenuitem("New snippet") + + expect(page).to have_content('New Snippet') + expect(page).to have_content('Title') + end + + scenario 'click on New issue shows new issue page' do + visit project_path(project) + + click_topmenuitem("New issue") + + expect(page).to have_content('New Issue') + expect(page).to have_content('Title') + end + + scenario 'click on New merge request shows new merge request page' do + visit project_path(project) + + click_topmenuitem("New merge request") + + expect(page).to have_content('New Merge Request') + expect(page).to have_content('Source branch') + expect(page).to have_content('Target branch') + end + + scenario 'click on New project snippet shows new snippet page' do + visit project_path(project) + + page.within '.header-content' do + find('.header-new-dropdown-toggle').trigger('click') + expect(page).to have_selector('.header-new.dropdown.open', count: 1) + find('.header-new-project-snippet a').trigger('click') + end + + expect(page).to have_content('New Snippet') + expect(page).to have_content('Title') + end + + scenario 'Click on New subgroup shows new group page' do + visit group_path(group) + + click_topmenuitem("New subgroup") + + expect(page).to have_content('Group path') + expect(page).to have_content('Group name') + end + + scenario 'Click on New project in group shows new project page' do + visit group_path(group) + + page.within '.header-content' do + find('.header-new-dropdown-toggle').trigger('click') + expect(page).to have_selector('.header-new.dropdown.open', count: 1) + find('.header-new-group-project a').trigger('click') + end + + expect(page).to have_content('Project path') + expect(page).to have_content('Project name') + end + end + + context 'used by guest user' do + let(:guest_user) { create(:user) } + + before do + group.add_guest(guest_user) + project.add_guest(guest_user) + + sign_in(guest_user) + end + + scenario 'click on New issue shows new issue page' do + visit project_path(project) + + click_topmenuitem("New issue") + + expect(page).to have_content('New Issue') + expect(page).to have_content('Title') + end + + scenario 'has no New merge request menu item' do + visit project_path(project) + + hasnot_topmenuitem("New merge request") + end + + scenario 'has no New project snippet menu item' do + visit project_path(project) + + expect(find('.header-new.dropdown')).not_to have_selector('.header-new-project-snippet') + end + + scenario 'public project has no New Issue Button' do + visit project_path(public_project) + + hasnot_topmenuitem("New issue") + end + + scenario 'public project has no New merge request menu item' do + visit project_path(public_project) + + hasnot_topmenuitem("New merge request") + end + + scenario 'public project has no New project snippet menu item' do + visit project_path(public_project) + + expect(find('.header-new.dropdown')).not_to have_selector('.header-new-project-snippet') + end + + scenario 'has no New subgroup menu item' do + visit group_path(group) + + hasnot_topmenuitem("New subgroup") + end + + scenario 'has no New project for group menu item' do + visit group_path(group) + + expect(find('.header-new.dropdown')).not_to have_selector('.header-new-group-project') + end + end + + def click_topmenuitem(item_name) + page.within '.header-content' do + find('.header-new-dropdown-toggle').trigger('click') + expect(page).to have_selector('.header-new.dropdown.open', count: 1) + click_link item_name + end + end + + def hasnot_topmenuitem(item_name) + expect(find('.header-new.dropdown')).not_to have_content(item_name) + end +end diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index 55092412340..53b3bb3b65f 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' -describe "GitLab Flavored Markdown", feature: true do - let(:project) { create(:empty_project) } +describe "GitLab Flavored Markdown" do + let(:user) { create(:user) } + let(:project) { create(:project) } let(:issue) { create(:issue, project: project) } let(:fred) do create(:user, name: 'fred') do |user| @@ -10,8 +11,8 @@ describe "GitLab Flavored Markdown", feature: true do end before do - login_as(:user) - project.add_developer(@user) + sign_in(user) + project.add_developer(user) end describe "for commits" do @@ -19,44 +20,44 @@ describe "GitLab Flavored Markdown", feature: true do let(:commit) { project.commit } before do - allow_any_instance_of(Commit).to receive(:title). - and_return("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details") + allow_any_instance_of(Commit).to receive(:title) + .and_return("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details") end it "renders title in commits#index" do - visit namespace_project_commits_path(project.namespace, project, 'master', limit: 1) + visit project_commits_path(project, 'master', limit: 1) expect(page).to have_link(issue.to_reference) end it "renders title in commits#show" do - visit namespace_project_commit_path(project.namespace, project, commit) + visit project_commit_path(project, commit) expect(page).to have_link(issue.to_reference) end it "renders description in commits#show" do - visit namespace_project_commit_path(project.namespace, project, commit) + visit project_commit_path(project, commit) expect(page).to have_link(fred.to_reference) end it "renders title in repositories#branches" do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) expect(page).to have_link(issue.to_reference) end end - describe "for issues", feature: true, js: true do + describe "for issues", js: true do before do @other_issue = create(:issue, - author: @user, - assignees: [@user], + author: user, + assignees: [user], project: project) @issue = create(:issue, - author: @user, - assignees: [@user], + author: user, + assignees: [user], project: project, title: "fix #{@other_issue.to_reference}", description: "ask #{fred.to_reference} for details") @@ -65,19 +66,19 @@ describe "GitLab Flavored Markdown", feature: true do end it "renders subject in issues#index" do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(page).to have_link(@other_issue.to_reference) end it "renders subject in issues#show" do - visit namespace_project_issue_path(project.namespace, project, @issue) + visit project_issue_path(project, @issue) expect(page).to have_link(@other_issue.to_reference) end it "renders details in issues#show" do - visit namespace_project_issue_path(project.namespace, project, @issue) + visit project_issue_path(project, @issue) expect(page).to have_link(fred.to_reference) end @@ -91,13 +92,13 @@ describe "GitLab Flavored Markdown", feature: true do end it "renders title in merge_requests#index" do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).to have_link(issue.to_reference) end it "renders title in merge_requests#show" do - visit namespace_project_merge_request_path(project.namespace, project, @merge_request) + visit project_merge_request_path(project, @merge_request) expect(page).to have_link(issue.to_reference) end @@ -112,19 +113,19 @@ describe "GitLab Flavored Markdown", feature: true do end it "renders title in milestones#index" do - visit namespace_project_milestones_path(project.namespace, project) + visit project_milestones_path(project) expect(page).to have_link(issue.to_reference) end it "renders title in milestones#show" do - visit namespace_project_milestone_path(project.namespace, project, @milestone) + visit project_milestone_path(project, @milestone) expect(page).to have_link(issue.to_reference) end it "renders description in milestones#show" do - visit namespace_project_milestone_path(project.namespace, project, @milestone) + visit project_milestone_path(project, @milestone) expect(page).to have_link(fred.to_reference) end diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb index 4b22b07494d..f04e13adba7 100644 --- a/spec/features/global_search_spec.rb +++ b/spec/features/global_search_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Global search', feature: true do +feature 'Global search' do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } before do project.team << [user, :master] - login_with(user) + sign_in(user) end describe 'I search through the issues and I see pagination' do diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb new file mode 100644 index 00000000000..37814ba6238 --- /dev/null +++ b/spec/features/group_variables_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +feature 'Group variables', js: true do + let(:user) { create(:user) } + let(:group) { create(:group) } + + background do + group.add_master(user) + gitlab_sign_in(user) + end + + context 'when user creates a new variable' do + background do + visit group_settings_ci_cd_path(group) + fill_in 'variable_key', with: 'AAA' + fill_in 'variable_value', with: 'AAA123' + find(:css, "#variable_protected").set(true) + click_on 'Add new variable' + end + + scenario 'user sees the created variable' do + page.within('.variables-table') do + expect(find(".variable-key")).to have_content('AAA') + expect(find(".variable-value")).to have_content('******') + expect(find(".variable-protected")).to have_content('Yes') + end + click_on 'Reveal Values' + page.within('.variables-table') do + expect(find(".variable-value")).to have_content('AAA123') + end + end + end + + context 'when user edits a variable' do + background do + create(:ci_group_variable, key: 'AAA', value: 'AAA123', protected: true, + group: group) + + visit group_settings_ci_cd_path(group) + + page.within('.variable-menu') do + click_on 'Update' + end + + fill_in 'variable_key', with: 'BBB' + fill_in 'variable_value', with: 'BBB123' + find(:css, "#variable_protected").set(false) + click_on 'Save variable' + end + + scenario 'user sees the updated variable' do + page.within('.variables-table') do + expect(find(".variable-key")).to have_content('BBB') + expect(find(".variable-value")).to have_content('******') + expect(find(".variable-protected")).to have_content('No') + end + end + end + + context 'when user deletes a variable' do + background do + create(:ci_group_variable, key: 'BBB', value: 'BBB123', protected: false, + group: group) + + visit group_settings_ci_cd_path(group) + + page.within('.variable-menu') do + page.accept_alert 'Are you sure?' do + click_on 'Remove' + end + end + end + + scenario 'user does not see the deleted variable' do + expect(page).to have_no_css('.variables-table') + end + end +end diff --git a/spec/features/groups/activity_spec.rb b/spec/features/groups/activity_spec.rb index 81f9c103e95..d3b25ec3d6c 100644 --- a/spec/features/groups/activity_spec.rb +++ b/spec/features/groups/activity_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Group activity page', feature: true do +feature 'Group activity page' do + let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user } let(:group) { create(:group) } let(:path) { activity_group_path(group) } context 'when signed in' do before do - user = create(:group_member, :developer, user: create(:user), group: group ).user - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb index fef8e41bffe..7f28553c44e 100644 --- a/spec/features/groups/empty_states_spec.rb +++ b/spec/features/groups/empty_states_spec.rb @@ -5,11 +5,11 @@ feature 'Groups Merge Requests Empty States' do let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user } before do - login_as(user) + sign_in(user) end context 'group has a project' do - let(:project) { create(:empty_project, namespace: group) } + let(:project) { create(:project, namespace: group) } before do project.add_master(user) diff --git a/spec/features/groups/group_name_toggle_spec.rb b/spec/features/groups/group_name_toggle_spec.rb index dfc3c84f29a..a7b8b702ab7 100644 --- a/spec/features/groups/group_name_toggle_spec.rb +++ b/spec/features/groups/group_name_toggle_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Group name toggle', feature: true, js: true do +feature 'Group name toggle', js: true do let(:group) { create(:group) } let(:nested_group_1) { create(:group, parent: group) } let(:nested_group_2) { create(:group, parent: nested_group_1) } @@ -9,7 +9,7 @@ feature 'Group name toggle', feature: true, js: true do SMALL_SCREEN = 300 before do - login_as :user + sign_in(create(:user)) end it 'is not present if enough horizontal space' do diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb index cc25db4ad60..acb21eab03f 100644 --- a/spec/features/groups/group_settings_spec.rb +++ b/spec/features/groups/group_settings_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Edit group settings', feature: true do +feature 'Edit group settings' do given(:user) { create(:user) } given(:group) { create(:group, path: 'foo') } background do group.add_owner(user) - login_as(user) + sign_in(user) end describe 'when the group path is changed' do @@ -18,14 +18,14 @@ feature 'Edit group settings', feature: true do update_path(new_group_path) visit new_group_full_path expect(current_path).to eq(new_group_full_path) - expect(find('h1.group-title')).to have_content(new_group_path) + expect(find('h1.group-title')).to have_content(group.name) end scenario 'the old group path redirects to the new path' do update_path(new_group_path) visit old_group_full_path expect(current_path).to eq(new_group_full_path) - expect(find('h1.group-title')).to have_content(new_group_path) + expect(find('h1.group-title')).to have_content(group.name) end context 'with a subgroup' do @@ -37,37 +37,42 @@ feature 'Edit group settings', feature: true do update_path(new_group_path) visit new_subgroup_full_path expect(current_path).to eq(new_subgroup_full_path) - expect(find('h1.group-title')).to have_content(subgroup.path) + expect(find('h1.group-title')).to have_content(subgroup.name) end scenario 'the old subgroup path redirects to the new path' do update_path(new_group_path) visit old_subgroup_full_path expect(current_path).to eq(new_subgroup_full_path) - expect(find('h1.group-title')).to have_content(subgroup.path) + expect(find('h1.group-title')).to have_content(subgroup.name) end end context 'with a project' do - given!(:project) { create(:project, group: group, path: 'project') } + given!(:project) { create(:project, group: group) } given(:old_project_full_path) { "/#{group.path}/#{project.path}" } given(:new_project_full_path) { "/#{new_group_path}/#{project.path}" } - - before(:context) { TestEnv.clean_test_path } - after(:example) { TestEnv.clean_test_path } + + before(:context) do + TestEnv.clean_test_path + end + + after(:example) do + TestEnv.clean_test_path + end scenario 'the project is accessible via the new path' do update_path(new_group_path) visit new_project_full_path expect(current_path).to eq(new_project_full_path) - expect(find('h1.project-title')).to have_content(project.name) + expect(find('h1.title')).to have_content(project.path) end scenario 'the old project path redirects to the new path' do update_path(new_group_path) visit old_project_full_path expect(current_path).to eq(new_project_full_path) - expect(find('h1.project-title')).to have_content(project.name) + expect(find('h1.title')).to have_content(project.path) end end end diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb index d6b88542ef7..cdf7aceb13c 100644 --- a/spec/features/groups/issues_spec.rb +++ b/spec/features/groups/issues_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' -feature 'Group issues page', feature: true do +feature 'Group issues page' do + include FilteredSearchHelpers + let(:path) { issues_group_path(group) } let(:issuable) { create(:issue, project: project, title: "this is my created issuable")} @@ -31,12 +33,10 @@ feature 'Group issues page', feature: true do let(:path) { issues_group_path(group) } it 'filters by only group users' do - click_button('Assignee') - - wait_for_requests + filtered_search.set('assignee:') - expect(find('.dropdown-menu-assignee')).to have_link(user.name) - expect(find('.dropdown-menu-assignee')).not_to have_link(user2.name) + expect(find('#js-dropdown-assignee .filter-dropdown')).to have_content(user.name) + expect(find('#js-dropdown-assignee .filter-dropdown')).not_to have_content(user2.name) end end end diff --git a/spec/features/groups/labels/edit_spec.rb b/spec/features/groups/labels/edit_spec.rb index 69281cecb7b..fb338127861 100644 --- a/spec/features/groups/labels/edit_spec.rb +++ b/spec/features/groups/labels/edit_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Edit group label', feature: true do +feature 'Edit group label' do given(:user) { create(:user) } given(:group) { create(:group) } given(:label) { create(:group_label, group: group) } background do group.add_owner(user) - login_as(user) + sign_in(user) visit edit_group_label_path(group, label) end diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb new file mode 100644 index 00000000000..1dd09d4f203 --- /dev/null +++ b/spec/features/groups/labels/subscription_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +feature 'Labels subscription' do + let(:user) { create(:user) } + let(:group) { create(:group) } + let!(:feature) { create(:group_label, group: group, title: 'feature') } + + context 'when signed in' do + before do + group.add_developer(user) + gitlab_sign_in user + end + + scenario 'users can subscribe/unsubscribe to group labels', js: true do + visit group_labels_path(group) + + expect(page).to have_content('feature') + + within "#group_label_#{feature.id}" do + expect(page).not_to have_button 'Unsubscribe' + + click_button 'Subscribe' + + expect(page).not_to have_button 'Subscribe' + expect(page).to have_button 'Unsubscribe' + + click_button 'Unsubscribe' + + expect(page).to have_button 'Subscribe' + expect(page).not_to have_button 'Unsubscribe' + end + end + end + + context 'when not signed in' do + it 'users can not subscribe/unsubscribe to labels' do + visit group_labels_path(group) + + expect(page).to have_content 'feature' + expect(page).not_to have_button('Subscribe') + end + end + + def click_link_on_dropdown(text) + find('.dropdown-group-label').click + + page.within('.dropdown-group-label') do + find('a.js-subscribe-button', text: text).click + end + end +end diff --git a/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb b/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb deleted file mode 100644 index be60b0489c7..00000000000 --- a/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -feature 'Groups > Members > Last owner cannot leave group', feature: true do - let(:owner) { create(:user) } - let(:group) { create(:group) } - - background do - group.add_owner(owner) - login_as(owner) - visit group_path(group) - end - - scenario 'user does not see a "Leave group" link' do - expect(page).not_to have_content 'Leave group' - end -end diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb new file mode 100644 index 00000000000..067a2dc850f --- /dev/null +++ b/spec/features/groups/members/leave_group_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' + +feature 'Groups > Members > Leave group' do + let(:user) { create(:user) } + let(:other_user) { create(:user) } + let(:group) { create(:group) } + + background do + gitlab_sign_in(user) + end + + scenario 'guest leaves the group' do + group.add_guest(user) + group.add_owner(other_user) + + visit group_path(group) + click_link 'Leave group' + + expect(current_path).to eq(dashboard_groups_path) + expect(page).to have_content left_group_message(group) + expect(group.users).not_to include(user) + end + + scenario 'guest leaves the group as last member' do + group.add_guest(user) + + visit group_path(group) + click_link 'Leave group' + + expect(current_path).to eq(dashboard_groups_path) + expect(page).to have_content left_group_message(group) + expect(group.users).not_to include(user) + end + + scenario 'owner leaves the group if they is not the last owner' do + group.add_owner(user) + group.add_owner(other_user) + + visit group_path(group) + click_link 'Leave group' + + expect(current_path).to eq(dashboard_groups_path) + expect(page).to have_content left_group_message(group) + expect(group.users).not_to include(user) + end + + scenario 'owner can not leave the group if they is a last owner' do + group.add_owner(user) + + visit group_path(group) + + expect(page).not_to have_content 'Leave group' + + visit group_group_members_path(group) + + expect(find(:css, '.project-members-page li', text: user.name)).not_to have_selector(:css, 'a.btn-remove') + end + + def left_group_message(group) + "You left the \"#{group.name}\"" + end +end diff --git a/spec/features/groups/members/list_members_spec.rb b/spec/features/groups/members/list_members_spec.rb new file mode 100644 index 00000000000..5c5d48c3623 --- /dev/null +++ b/spec/features/groups/members/list_members_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +feature 'Groups > Members > List members' do + include Select2Helper + + let(:user1) { create(:user, name: 'John Doe') } + let(:user2) { create(:user, name: 'Mary Jane') } + let(:group) { create(:group) } + let(:nested_group) { create(:group, parent: group) } + + background do + gitlab_sign_in(user1) + end + + scenario 'show members from current group and parent', :nested_groups do + group.add_developer(user1) + nested_group.add_developer(user2) + + visit group_group_members_path(nested_group) + + expect(first_row.text).to include(user1.name) + expect(second_row.text).to include(user2.name) + end + + scenario 'show user once if member of both current group and parent', :nested_groups do + group.add_developer(user1) + nested_group.add_developer(user1) + + visit group_group_members_path(nested_group) + + expect(first_row.text).to include(user1.name) + expect(second_row).to be_blank + end + + def first_row + page.all('ul.content-list > li')[0] + end + + def second_row + page.all('ul.content-list > li')[1] + end +end diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/manage_access_requests_spec.rb index dbe150823ba..b83cd657ef7 100644 --- a/spec/features/groups/members/owner_manages_access_requests_spec.rb +++ b/spec/features/groups/members/manage_access_requests_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Groups > Members > Owner manages access requests', feature: true do +feature 'Groups > Members > Manage access requests' do let(:user) { create(:user) } let(:owner) { create(:user) } let(:group) { create(:group, :public, :access_requestable) } @@ -8,7 +8,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do background do group.request_access(user) group.add_owner(owner) - login_as(owner) + sign_in(owner) end scenario 'owner can see access requests' do @@ -17,7 +17,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do expect_visible_access_request(group, user) end - scenario 'master can grant access' do + scenario 'owner can grant access' do visit group_group_members_path(group) expect_visible_access_request(group, user) @@ -28,7 +28,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{group.name} group was granted" end - scenario 'master can deny access' do + scenario 'owner can deny access' do visit group_group_members_path(group) expect_visible_access_request(group, user) diff --git a/spec/features/groups/members/list_spec.rb b/spec/features/groups/members/manage_members.rb index f654fa16a06..9039b283393 100644 --- a/spec/features/groups/members/list_spec.rb +++ b/spec/features/groups/members/manage_members.rb @@ -1,35 +1,14 @@ require 'spec_helper' -feature 'Groups members list', feature: true do +feature 'Groups > Members > Manage members' do include Select2Helper let(:user1) { create(:user, name: 'John Doe') } let(:user2) { create(:user, name: 'Mary Jane') } let(:group) { create(:group) } - let(:nested_group) { create(:group, parent: group) } background do - login_as(user1) - end - - scenario 'show members from current group and parent', :nested_groups do - group.add_developer(user1) - nested_group.add_developer(user2) - - visit group_group_members_path(nested_group) - - expect(first_row.text).to include(user1.name) - expect(second_row.text).to include(user2.name) - end - - scenario 'show user once if member of both current group and parent', :nested_groups do - group.add_developer(user1) - nested_group.add_developer(user1) - - visit group_group_members_path(nested_group) - - expect(first_row.text).to include(user1.name) - expect(second_row).to be_blank + sign_in(user1) end scenario 'update user to owner level', :js do @@ -59,6 +38,18 @@ feature 'Groups members list', feature: true do end end + scenario 'remove user from group', :js do + group.add_owner(user1) + group.add_developer(user2) + + visit group_group_members_path(group) + + find(:css, '.project-members-page li', text: user2.name).find(:css, 'a.btn-remove').click + + expect(page).not_to have_content(user2.name) + expect(group.users).not_to include(user2) + end + scenario 'add yourself to group when already an owner', :js do group.add_owner(user1) @@ -86,6 +77,23 @@ feature 'Groups members list', feature: true do end end + scenario 'guest can not manage other users' do + group.add_guest(user1) + group.add_developer(user2) + + visit group_group_members_path(group) + + expect(page).not_to have_button 'Add to group' + + page.within(second_row) do + # Can not modify user2 role + expect(page).not_to have_button 'Developer' + + # Can not remove user2 + expect(page).not_to have_css('a.btn-remove') + end + end + def first_row page.all('ul.content-list > li')[0] end diff --git a/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb b/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb deleted file mode 100644 index 37c433cc09a..00000000000 --- a/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -feature 'Groups > Members > Member cannot request access to his project', feature: true do - let(:member) { create(:user) } - let(:group) { create(:group) } - - background do - group.add_developer(member) - login_as(member) - visit group_path(group) - end - - scenario 'member does not see the request access button' do - expect(page).not_to have_content 'Request Access' - end -end diff --git a/spec/features/groups/members/member_leaves_group_spec.rb b/spec/features/groups/members/member_leaves_group_spec.rb deleted file mode 100644 index ac4d94658ae..00000000000 --- a/spec/features/groups/members/member_leaves_group_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'spec_helper' - -feature 'Groups > Members > Member leaves group', feature: true do - let(:user) { create(:user) } - let(:owner) { create(:user) } - let(:group) { create(:group, :public) } - - background do - group.add_owner(owner) - group.add_developer(user) - login_as(user) - visit group_path(group) - end - - scenario 'user leaves group' do - click_link 'Leave group' - - expect(current_path).to eq(dashboard_groups_path) - expect(group.users.exists?(user.id)).to be_falsey - end -end diff --git a/spec/features/groups/members/user_requests_access_spec.rb b/spec/features/groups/members/request_access_spec.rb index e4b5ea91bd3..1f3c7fd3859 100644 --- a/spec/features/groups/members/user_requests_access_spec.rb +++ b/spec/features/groups/members/request_access_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Groups > Members > User requests access', feature: true do +feature 'Groups > Members > Request access' do let(:user) { create(:user) } let(:owner) { create(:user) } let(:group) { create(:group, :public, :access_requestable) } @@ -8,7 +8,7 @@ feature 'Groups > Members > User requests access', feature: true do background do group.add_owner(owner) - login_as(user) + sign_in(user) visit group_path(group) end @@ -68,4 +68,11 @@ feature 'Groups > Members > User requests access', feature: true do expect(group.requesters.exists?(user_id: user)).to be_falsey expect(page).to have_content 'Your access request to the group has been withdrawn.' end + + scenario 'member does not see the request access button' do + group.add_owner(user) + visit group_path(group) + + expect(page).not_to have_content 'Request Access' + end end diff --git a/spec/features/groups/members/sorting_spec.rb b/spec/features/groups/members/sort_members_spec.rb index 902d3f789ff..e175ad04f86 100644 --- a/spec/features/groups/members/sorting_spec.rb +++ b/spec/features/groups/members/sort_members_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Groups > Members > Sorting', feature: true do +feature 'Groups > Members > Sort members' do let(:owner) { create(:user, name: 'John Doe') } let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) } let(:group) { create(:group) } @@ -9,7 +9,7 @@ feature 'Groups > Members > Sorting', feature: true do create(:group_member, :owner, user: owner, group: group, created_at: 5.days.ago) create(:group_member, :developer, user: developer, group: group, created_at: 3.days.ago) - login_as(owner) + sign_in(owner) end scenario 'sorts alphabetically by default' do @@ -68,7 +68,7 @@ feature 'Groups > Members > Sorting', feature: true do expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending') end - scenario 'sorts by recent sign in', :redis do + scenario 'sorts by recent sign in', :clean_gitlab_redis_shared_state do visit_members_list(sort: :recent_sign_in) expect(first_member).to include(owner.name) @@ -76,7 +76,7 @@ feature 'Groups > Members > Sorting', feature: true do expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in') end - scenario 'sorts by oldest sign in', :redis do + scenario 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do visit_members_list(sort: :oldest_sign_in) expect(first_member).to include(developer.name) diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb index b55078c3bf6..c2241feb9f7 100644 --- a/spec/features/groups/merge_requests_spec.rb +++ b/spec/features/groups/merge_requests_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Group merge requests page', feature: true do +feature 'Group merge requests page' do let(:path) { merge_requests_group_path(group) } let(:issuable) { create(:merge_request, source_project: project, target_project: project, title: 'this is my created issuable') } include_examples 'project features apply to issuables', MergeRequest context 'archived issuable' do - let(:project_archived) { create(:project, :archived, :merge_requests_enabled, group: group) } + let(:project_archived) { create(:project, :archived, :merge_requests_enabled, :repository, group: group) } let(:issuable_archived) { create(:merge_request, source_project: project_archived, target_project: project_archived, title: 'issuable of an archived project') } let(:access_level) { ProjectFeature::ENABLED } let(:user) { user_in_group } diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb index daa2c6afd63..574bbe0e0e1 100644 --- a/spec/features/groups/milestone_spec.rb +++ b/spec/features/groups/milestone_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'Group milestones', :feature, :js do +feature 'Group milestones', :js do let(:group) { create(:group) } let!(:project) { create(:project_empty_repo, group: group) } let(:user) { create(:group_member, :master, user: create(:user), group: group ).user } @@ -8,7 +8,7 @@ feature 'Group milestones', :feature, :js do before do Timecop.freeze - login_as(user) + sign_in(user) end after do @@ -33,4 +33,32 @@ feature 'Group milestones', :feature, :js do expect(find('.start_date')).to have_content(Date.today.at_beginning_of_month.strftime('%b %-d, %Y')) end end + + context 'milestones list' do + let!(:other_project) { create(:project_empty_repo, group: group) } + + let!(:active_group_milestone) { create(:milestone, group: group, state: 'active') } + let!(:active_project_milestone1) { create(:milestone, project: project, state: 'active', title: 'v1.0') } + let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.0') } + let!(:closed_group_milestone) { create(:milestone, group: group, state: 'closed') } + let!(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') } + let!(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') } + + before do + visit group_milestones_path(group) + end + + it 'counts milestones correctly' do + expect(find('.top-area .active .badge').text).to eq("2") + expect(find('.top-area .closed .badge').text).to eq("2") + expect(find('.top-area .all .badge').text).to eq("4") + end + + it 'lists legacy group milestones and group milestones' do + legacy_milestone = GroupMilestone.build_collection(group, group.projects, { state: 'active' }).first + + expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1) + expect(page).to have_selector("#milestone_#{legacy_milestone.milestones.first.id}", count: 1) + end + end end diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb index d3c49c37374..303013e59d5 100644 --- a/spec/features/groups/show_spec.rb +++ b/spec/features/groups/show_spec.rb @@ -1,13 +1,16 @@ require 'spec_helper' -feature 'Group show page', feature: true do +feature 'Group show page' do let(:group) { create(:group) } let(:path) { group_path(group) } context 'when signed in' do + let(:user) do + create(:group_member, :developer, user: create(:user), group: group ).user + end + before do - user = create(:group_member, :developer, user: create(:user), group: group ).user - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 24ea7aba0cc..e59a484d992 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Group', feature: true do +feature 'Group' do before do - login_as(:admin) + sign_in(create(:admin)) end matcher :have_namespace_error_message do @@ -12,7 +12,9 @@ feature 'Group', feature: true do end describe 'create a group' do - before { visit new_group_path } + before do + visit new_group_path + end describe 'with space in group path' do it 'renders new group form with validation errors' do @@ -106,8 +108,8 @@ feature 'Group', feature: true do before do group.add_owner(user) - logout - login_as(user) + sign_out(:user) + sign_in(user) visit subgroups_group_path(group) click_link 'New Subgroup' @@ -126,19 +128,21 @@ feature 'Group', feature: true do it 'checks permissions to avoid exposing groups by parent_id' do group = create(:group, :private, path: 'secret-group') - logout - login_as(:user) + sign_out(:user) + sign_in(create(:user)) visit new_group_path(parent_id: group.id) expect(page).not_to have_content('secret-group') end - describe 'group edit' do + describe 'group edit', js: true do let(:group) { create(:group) } let(:path) { edit_group_path(group) } let(:new_name) { 'new-name' } - before { visit path } + before do + visit path + end it 'saves new settings' do fill_in 'group_name', with: new_name @@ -153,8 +157,8 @@ feature 'Group', feature: true do end it 'removes group' do - click_link 'Remove group' - + expect { remove_with_confirm('Remove group', group.path) }.to change {Group.count}.by(-1) + expect(group.members.all.count).to be_zero expect(page).to have_content "scheduled for deletion" end end @@ -208,4 +212,10 @@ feature 'Group', feature: true do expect(page).to have_content(nested_group.name) end end + + def remove_with_confirm(button_text, confirm_with) + click_button button_text + fill_in 'confirm_name_input', with: confirm_with + click_button 'Confirm' + end end diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index e0b2404e60a..bd4f233cba9 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Help Pages', feature: true do +describe 'Help Pages' do describe 'Get the main help page' do shared_examples_for 'help page' do |prefix: ''| it 'prefixes links correctly' do @@ -34,29 +34,46 @@ describe 'Help Pages', feature: true do end end - context 'in a production environment with version check enabled', js: true do + context 'in a production environment with version check enabled', :js do before do allow(Rails.env).to receive(:production?) { true } - allow(current_application_settings).to receive(:version_check_enabled) { true } + allow_any_instance_of(ApplicationSetting).to receive(:version_check_enabled) { true } allow_any_instance_of(VersionCheck).to receive(:url) { '/version-check-url' } - login_as :user + sign_in(create(:user)) visit help_path end - it 'should display a version check image' do - expect(find('.js-version-status-badge')).to be_visible + it 'has a version check image' do + expect(find('.js-version-status-badge', visible: false)['src']).to end_with('/version-check-url') end - it 'should have a src url' do - expect(find('.js-version-status-badge')['src']).to match(/\/version-check-url/) + it 'hides the version check image if the image request fails' do + # We use '--load-images=yes' with poltergeist so the image fails to load + expect(find('.js-version-status-badge', visible: false)).not_to be_visible end + end - it 'should hide the version check image if the image request fails' do - # We use '--load-images=no' with poltergeist so we must trigger manually - execute_script("$('.js-version-status-badge').trigger('error');") + describe 'when help page is customized' do + before do + allow_any_instance_of(ApplicationSetting).to receive(:help_page_hide_commercial_content?) { true } + allow_any_instance_of(ApplicationSetting).to receive(:help_page_text) { "My Custom Text" } + allow_any_instance_of(ApplicationSetting).to receive(:help_page_support_url) { "http://example.com/help" } - expect(find('.js-version-status-badge', visible: false)).not_to be_visible + sign_in(create(:user)) + visit help_path + end + + it 'should display custom help page text' do + expect(page).to have_text "My Custom Text" + end + + it 'should hide marketing content when enabled' do + expect(page).not_to have_link "Get a support subscription" + end + + it 'should use a custom support url' do + expect(page).to have_link "See our website for getting help", href: "http://example.com/help" end end end diff --git a/spec/features/issuables/close_reopen_report_toggle_spec.rb b/spec/features/issuables/close_reopen_report_toggle_spec.rb new file mode 100644 index 00000000000..3df77a104e8 --- /dev/null +++ b/spec/features/issuables/close_reopen_report_toggle_spec.rb @@ -0,0 +1,116 @@ +require 'spec_helper' + +describe 'Issuables Close/Reopen/Report toggle' do + let(:user) { create(:user) } + + shared_examples 'an issuable close/reopen/report toggle' do + let(:container) { find('.issuable-close-dropdown') } + let(:human_model_name) { issuable.model_name.human.downcase } + + it 'shows toggle' do + expect(page).to have_link("Close #{human_model_name}") + expect(page).to have_selector('.issuable-close-dropdown') + end + + it 'opens a dropdown when toggle is clicked' do + container.find('.dropdown-toggle').click + + expect(container).to have_selector('.dropdown-menu') + expect(container).to have_content("Close #{human_model_name}") + expect(container).to have_content('Report abuse') + expect(container).to have_content("Report #{human_model_name.pluralize} that are abusive, inappropriate or spam.") + expect(container).to have_selector('.close-item.droplab-item-selected') + expect(container).to have_selector('.report-item') + expect(container).not_to have_selector('.report-item.droplab-item-selected') + expect(container).not_to have_selector('.reopen-item') + end + + it 'changes the button when an item is selected' do + button = container.find('.issuable-close-button') + + container.find('.dropdown-toggle').click + container.find('.report-item').click + + expect(container).not_to have_selector('.dropdown-menu') + expect(button).to have_content('Report abuse') + + container.find('.dropdown-toggle').click + container.find('.close-item').click + + expect(button).to have_content("Close #{human_model_name}") + end + end + + context 'on an issue' do + let(:project) { create(:project) } + let(:issuable) { create(:issue, project: project) } + + before do + project.add_master(user) + login_as user + end + + context 'when user has permission to update', :js do + before do + visit project_issue_path(project, issuable) + end + + it_behaves_like 'an issuable close/reopen/report toggle' + end + + context 'when user doesnt have permission to update' do + let(:cant_project) { create(:project) } + let(:cant_issuable) { create(:issue, project: cant_project) } + + before do + cant_project.add_guest(user) + + visit project_issue_path(cant_project, cant_issuable) + end + + it 'only shows the `Report abuse` and `New issue` buttons' do + expect(page).to have_link('Report abuse') + expect(page).to have_link('New issue') + expect(page).not_to have_link('Close issue') + expect(page).not_to have_link('Reopen issue') + expect(page).not_to have_link('Edit') + end + end + end + + context 'on a merge request' do + let(:project) { create(:project, :repository) } + let(:issuable) { create(:merge_request, source_project: project) } + + before do + project.add_master(user) + login_as user + end + + context 'when user has permission to update', :js do + before do + visit project_merge_request_path(project, issuable) + end + + it_behaves_like 'an issuable close/reopen/report toggle' + end + + context 'when user doesnt have permission to update' do + let(:cant_project) { create(:project, :repository) } + let(:cant_issuable) { create(:merge_request, source_project: cant_project) } + + before do + cant_project.add_reporter(user) + + visit project_merge_request_path(cant_project, cant_issuable) + end + + it 'only shows a `Report abuse` button' do + expect(page).to have_link('Report abuse') + expect(page).not_to have_link('Close merge request') + expect(page).not_to have_link('Reopen merge request') + expect(page).not_to have_link('Edit') + end + end + end +end diff --git a/spec/features/issuables/default_sort_order_spec.rb b/spec/features/issuables/default_sort_order_spec.rb index bfe43bff10f..b72b690110f 100644 --- a/spec/features/issuables/default_sort_order_spec.rb +++ b/spec/features/issuables/default_sort_order_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe 'Projects > Issuables > Default sort order', feature: true do - let(:project) { create(:empty_project, :public) } +describe 'Projects > Issuables > Default sort order' do + let(:project) { create(:project, :public) } let(:first_created_issuable) { issuables.order_created_asc.first } let(:last_created_issuable) { issuables.order_created_desc.first } @@ -153,7 +153,9 @@ describe 'Projects > Issuables > Default sort order', feature: true do context 'when the sort in the URL is id_desc' do let(:issuable_type) { :issue } - before { visit_issues(project, sort: 'id_desc') } + before do + visit_issues(project, sort: 'id_desc') + end it 'shows the sort order as last created' do expect(find('.issues-other-filters')).to have_content('Last created') @@ -165,7 +167,9 @@ describe 'Projects > Issuables > Default sort order', feature: true do context 'when the sort in the URL is id_asc' do let(:issuable_type) { :issue } - before { visit_issues(project, sort: 'id_asc') } + before do + visit_issues(project, sort: 'id_asc') + end it 'shows the sort order as oldest created' do expect(find('.issues-other-filters')).to have_content('Oldest created') diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb index 414838fa22e..2f45ef856a5 100644 --- a/spec/features/issuables/issuable_list_spec.rb +++ b/spec/features/issuables/issuable_list_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -describe 'issuable list', feature: true do - let(:project) { create(:empty_project) } +describe 'issuable list' do + let(:project) { create(:project) } let(:user) { create(:user) } issuable_types = [:issue, :merge_request] before do project.add_user(user, :developer) - login_as(user) + sign_in(user) issuable_types.each { |type| create_issuables(type) } end @@ -39,9 +39,9 @@ describe 'issuable list', feature: true do def visit_issuable_list(issuable_type) if issuable_type == :issue - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) else - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end end diff --git a/spec/features/issuables/markdown_references_spec.rb b/spec/features/issuables/markdown_references_spec.rb new file mode 100644 index 00000000000..dd4e10a9886 --- /dev/null +++ b/spec/features/issuables/markdown_references_spec.rb @@ -0,0 +1,193 @@ +require 'rails_helper' + +describe 'Markdown References', :js do + let(:user) { create(:user) } + let(:actual_project) { create(:project, :public, :repository) } + let(:merge_request) { create(:merge_request, target_project: actual_project, source_project: actual_project)} + let(:issue_actual_project) { create(:issue, project: actual_project) } + let!(:other_project) { create(:project, :public) } + let!(:issue_other_project) { create(:issue, project: other_project) } + let(:issues) { [issue_actual_project, issue_other_project] } + + def build_note + markdown = "Referencing internal issue #{issue_actual_project.to_reference}, " + + "cross-project #{issue_other_project.to_reference(actual_project)} external JIRA-5 " + + "and non existing #999" + + page.within('#diff-notes-app') do + fill_in 'note_note', with: markdown + end + end + + shared_examples 'correct references' do + before do + remotelink = double(:remotelink, all: [], build: double(save!: true)) + + stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5") + stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment") + allow_any_instance_of(JIRA::Resource::Issue).to receive(:remotelink).and_return(remotelink) + + sign_in(user) + visit merge_request_path(merge_request) + build_note + end + + def links_expectations + issues.each do |issue| + if referenced_issues.include?(issue) + expect(page).to have_link(issue.to_reference, href: issue_path(issue)) + else + expect(page).not_to have_link(issue.to_reference, href: issue_path(issue)) + end + end + + if jira_referenced + expect(page).to have_link('JIRA-5', href: 'https://jira.example.com/browse/JIRA-5') + else + expect(page).not_to have_link('JIRA-5', href: 'https://jira.example.com/browse/JIRA-5') + end + + expect(page).not_to have_link('#999') + end + + it 'creates a link to the referenced issue on the preview' do + find('.js-md-preview-button').click + wait_for_requests + + page.within('.md-preview-holder') do + links_expectations + end + end + + it 'creates a link to the referenced issue after submit' do + click_button 'Comment' + wait_for_requests + + page.within('#diff-notes-app') do + links_expectations + end + end + + it 'creates a note on the referenced issues' do + click_button 'Comment' + wait_for_requests + + if referenced_issues.include?(issue_actual_project) + visit issue_path(issue_actual_project) + + page.within('#notes') do + expect(page).to have_content( + "#{user.to_reference} mentioned in merge request #{merge_request.to_reference}" + ) + end + end + + if referenced_issues.include?(issue_other_project) + visit issue_path(issue_other_project) + + page.within('#notes') do + expect(page).to have_content( + "#{user.to_reference} mentioned in merge request #{merge_request.to_reference(other_project)}" + ) + end + end + end + end + + context 'when internal issues tracker is enabled for the other project' do + context 'when only internal issues tracker is enabled for the actual project' do + include_examples 'correct references' do + let(:referenced_issues) { [issue_actual_project, issue_other_project] } + let(:jira_referenced) { false } + end + end + + context 'when both external and internal issues trackers are enabled for the actual project' do + before do + create(:jira_service, project: actual_project) + end + + include_examples 'correct references' do + let(:referenced_issues) { [issue_actual_project, issue_other_project] } + let(:jira_referenced) { true } + end + end + + context 'when only external issues tracker is enabled for the actual project' do + before do + create(:jira_service, project: actual_project) + + actual_project.issues_enabled = false + actual_project.save! + end + + include_examples 'correct references' do + let(:referenced_issues) { [issue_other_project] } + let(:jira_referenced) { true } + end + end + + context 'when no tracker is enabled for the actual project' do + before do + actual_project.issues_enabled = false + actual_project.save! + end + + include_examples 'correct references' do + let(:referenced_issues) { [issue_other_project] } + let(:jira_referenced) { false } + end + end + end + + context 'when internal issues tracker is disabled for the other project' do + before do + other_project.issues_enabled = false + other_project.save! + end + + context 'when only internal issues tracker is enabled for the actual project' do + include_examples 'correct references' do + let(:referenced_issues) { [issue_actual_project] } + let(:jira_referenced) { false } + end + end + + context 'when both external and internal issues trackers are enabled for the actual project' do + before do + create(:jira_service, project: actual_project) + end + + include_examples 'correct references' do + let(:referenced_issues) { [issue_actual_project] } + let(:jira_referenced) { true } + end + end + + context 'when only external issues tracker is enabled for the actual project' do + before do + create(:jira_service, project: actual_project) + + actual_project.issues_enabled = false + actual_project.save! + end + + include_examples 'correct references' do + let(:referenced_issues) { [] } + let(:jira_referenced) { true } + end + end + + context 'when no issues tracker is enabled for the actual project' do + before do + actual_project.issues_enabled = false + actual_project.save! + end + + include_examples 'correct references' do + let(:referenced_issues) { [] } + let(:jira_referenced) { false } + end + end + end +end diff --git a/spec/features/issuables/user_sees_sidebar_spec.rb b/spec/features/issuables/user_sees_sidebar_spec.rb new file mode 100644 index 00000000000..2bd1c8aab86 --- /dev/null +++ b/spec/features/issuables/user_sees_sidebar_spec.rb @@ -0,0 +1,30 @@ +require 'rails_helper' + +describe 'Issue Sidebar on Mobile' do + include MobileHelpers + + let(:project) { create(:project, :public, :repository) } + let(:merge_request) { create(:merge_request, source_project: project) } + let(:issue) { create(:issue, project: project) } + let!(:user) { create(:user)} + + before do + sign_in(user) + end + + context 'mobile sidebar on merge requests', js: true do + before do + visit project_merge_request_path(merge_request.project, merge_request) + end + + it_behaves_like "issue sidebar stays collapsed on mobile" + end + + context 'mobile sidebar on issues', js: true do + before do + visit project_issue_path(project, issue) + end + + it_behaves_like "issue sidebar stays collapsed on mobile" + end +end diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 81ae54c7a10..134e618feac 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'Awards Emoji', feature: true do +describe 'Awards Emoji' do let!(:project) { create(:project, :public) } let!(:user) { create(:user) } let(:issue) do @@ -12,14 +12,14 @@ describe 'Awards Emoji', feature: true do context 'authorized user' do before do project.team << [user, :master] - login_as(user) + sign_in(user) end describe 'visiting an issue with a legacy award emoji that is not valid anymore' do before do # The `heart_tip` emoji is not valid anymore so we need to skip validation issue.award_emoji.build(user: user, name: 'heart_tip').save!(validate: false) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) wait_for_requests end @@ -33,7 +33,7 @@ describe 'Awards Emoji', feature: true do let!(:note) { create(:note_on_issue, noteable: issue, project: issue.project, note: "Hello world") } before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) wait_for_requests end @@ -81,13 +81,13 @@ describe 'Awards Emoji', feature: true do end end - context 'execute /award slash command' do + context 'execute /award quick action' do it 'toggles the emoji award on noteable', js: true do - execute_slash_command('/award :100:') + execute_quick_action('/award :100:') expect(find(noteable_award_counter)).to have_text("1") - execute_slash_command('/award :100:') + execute_quick_action('/award :100:') expect(page).not_to have_selector(noteable_award_counter) end @@ -97,7 +97,7 @@ describe 'Awards Emoji', feature: true do context 'unauthorized user', js: true do before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'has disabled emoji button' do @@ -105,7 +105,7 @@ describe 'Awards Emoji', feature: true do end end - def execute_slash_command(cmd) + def execute_quick_action(cmd) within('.js-main-target-form') do fill_in 'note[note]', with: cmd click_button 'Comment' diff --git a/spec/features/issues/award_spec.rb b/spec/features/issues/award_spec.rb index fcf22dd5033..e95eb19f7d1 100644 --- a/spec/features/issues/award_spec.rb +++ b/spec/features/issues/award_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Issue awards', js: true, feature: true do +feature 'Issue awards', js: true do let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:issue) { create(:issue, project: project) } describe 'logged in' do before do - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) wait_for_requests end @@ -17,7 +17,7 @@ feature 'Issue awards', js: true, feature: true do expect(page).to have_selector('.js-emoji-btn.active') expect(first('.js-emoji-btn')).to have_content '1' - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(first('.js-emoji-btn')).to have_content '1' end @@ -26,7 +26,7 @@ feature 'Issue awards', js: true, feature: true do find('.js-emoji-btn.active').click expect(first('.js-emoji-btn')).to have_content '0' - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(first('.js-emoji-btn')).to have_content '0' end @@ -40,7 +40,7 @@ feature 'Issue awards', js: true, feature: true do describe 'logged out' do before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) wait_for_requests end diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb index 95b4930cd32..847e3856ba5 100644 --- a/spec/features/issues/bulk_assignment_labels_spec.rb +++ b/spec/features/issues/bulk_assignment_labels_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'Issues > Labels bulk assignment', feature: true do +feature 'Issues > Labels bulk assignment' do let(:user) { create(:user) } let!(:project) { create(:project) } let!(:issue1) { create(:issue, project: project, title: "Issue 1") } @@ -13,7 +13,22 @@ feature 'Issues > Labels bulk assignment', feature: true do before do project.team << [user, :master] - login_as user + sign_in user + end + + context 'sidebar' do + before do + enable_bulk_update + end + + it 'is present when bulk edit is enabled' do + expect(page).to have_css('.issuable-sidebar') + end + + it 'is not present when bulk edit is disabled' do + disable_bulk_update + expect(page).not_to have_css('.issuable-sidebar') + end end context 'can bulk assign' do @@ -331,9 +346,9 @@ feature 'Issues > Labels bulk assignment', feature: true do context 'as a guest' do before do - login_as user + sign_in user - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end context 'cannot bulk assign labels' do @@ -395,7 +410,11 @@ feature 'Issues > Labels bulk assignment', feature: true do end def enable_bulk_update - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button 'Edit Issues' end + + def disable_bulk_update + click_button 'Cancel' + end end diff --git a/spec/features/issues/create_branch_merge_request_spec.rb b/spec/features/issues/create_branch_merge_request_spec.rb index 1d7d8d291b2..f59f687cf51 100644 --- a/spec/features/issues/create_branch_merge_request_spec.rb +++ b/spec/features/issues/create_branch_merge_request_spec.rb @@ -1,41 +1,39 @@ require 'rails_helper' -feature 'Create Branch/Merge Request Dropdown on issue page', feature: true, js: true do +feature 'Create Branch/Merge Request Dropdown on issue page', js: true do let(:user) { create(:user) } - let!(:project) { create(:project) } + let!(:project) { create(:project, :repository) } let(:issue) { create(:issue, project: project, title: 'Cherry-Coloured Funk') } context 'for team members' do before do project.team << [user, :developer] - login_as(user) + sign_in(user) end it 'allows creating a merge request from the issue page' do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) select_dropdown_option('create-mr') + + expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"') + expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first)) - wait_for_requests + visit project_issue_path(project, issue) expect(page).to have_content("created branch 1-cherry-coloured-funk") expect(page).to have_content("mentioned in merge request !1") - - visit namespace_project_merge_request_path(project.namespace, project, MergeRequest.first) - - expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"') - expect(current_path).to eq(namespace_project_merge_request_path(project.namespace, project, MergeRequest.first)) end it 'allows creating a branch from the issue page' do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) select_dropdown_option('create-branch') wait_for_requests expect(page).to have_selector('.dropdown-toggle-text ', text: '1-cherry-coloured-funk') - expect(current_path).to eq namespace_project_tree_path(project.namespace, project, '1-cherry-coloured-funk') + expect(current_path).to eq project_tree_path(project, '1-cherry-coloured-funk') end context "when there is a referenced merge request" do @@ -52,7 +50,7 @@ feature 'Create Branch/Merge Request Dropdown on issue page', feature: true, js: before do referenced_mr.cache_merge_request_closes_issues!(user) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'disables the create branch button' do @@ -66,7 +64,7 @@ feature 'Create Branch/Merge Request Dropdown on issue page', feature: true, js: it 'disables the create branch button' do issue = create(:issue, :confidential, project: project) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(page).not_to have_css('.create-mr-dropdown-wrap') end @@ -75,7 +73,7 @@ feature 'Create Branch/Merge Request Dropdown on issue page', feature: true, js: context 'for visitors' do before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'shows no buttons' do diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb index 24e2419b5ce..80cc8d22999 100644 --- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb @@ -1,21 +1,21 @@ require 'rails_helper' -feature 'Resolving all open discussions in a merge request from an issue', feature: true, js: true do +feature 'Resolving all open discussions in a merge request from an issue', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } let!(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } describe 'as a user with access to the project' do before do project.team << [user, :master] - login_as user - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in user + visit project_merge_request_path(project, merge_request) end it 'shows a button to resolve all discussions by creating a new issue' do within('#resolve-count-app') do - expect(page).to have_link "Resolve all discussions in new issue", href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + expect(page).to have_link "Resolve all discussions in new issue", href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end end @@ -25,13 +25,13 @@ feature 'Resolving all open discussions in a merge request from an issue', featu end it 'hides the link for creating a new issue' do - expect(page).not_to have_link "Resolve all discussions in new issue", href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + expect(page).not_to have_link "Resolve all discussions in new issue", href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end end context 'creating an issue for discussions' do before do - click_link "Resolve all discussions in new issue", href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + click_link "Resolve all discussions in new issue", href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end it_behaves_like 'creating an issue for a discussion' @@ -45,7 +45,7 @@ feature 'Resolving all open discussions in a merge request from an issue', featu context 'with the internal tracker disabled' do before do project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not show a link to create a new issue' do @@ -55,7 +55,7 @@ feature 'Resolving all open discussions in a merge request from an issue', featu context 'merge request has discussions that need to be resolved' do before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'shows a warning that the merge request contains unresolved discussions' do @@ -64,13 +64,13 @@ feature 'Resolving all open discussions in a merge request from an issue', featu it 'has a link to resolve all discussions by creating an issue' do page.within '.mr-widget-body' do - expect(page).to have_link 'Create an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + expect(page).to have_link 'Create an issue to resolve them later', href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end end context 'creating an issue for discussions' do before do - page.click_link 'Create an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + page.click_link 'Create an issue to resolve them later', href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end it_behaves_like 'creating an issue for a discussion' @@ -82,8 +82,8 @@ feature 'Resolving all open discussions in a merge request from an issue', featu describe 'as a reporter' do before do project.team << [user, :reporter] - login_as user - visit new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + sign_in user + visit new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) end it 'Shows a notice to ask someone else to resolve the discussions' do diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb index 3a5a79e03f4..ad5fd0fd97b 100644 --- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb @@ -1,22 +1,22 @@ require 'rails_helper' -feature 'Resolve an open discussion in a merge request by creating an issue', feature: true do +feature 'Resolve an open discussion in a merge request by creating an issue' do let(:user) { create(:user) } - let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) } + let(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) } let(:merge_request) { create(:merge_request, source_project: project) } let!(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } describe 'As a user with access to the project' do before do project.team << [user, :master] - login_as user - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in user + visit project_merge_request_path(project, merge_request) end context 'with the internal tracker disabled' do before do project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not show a link to create a new issue' do @@ -43,14 +43,14 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe end it 'has a link to create a new issue for a discussion' do - new_issue_link = new_namespace_project_issue_path(project.namespace, project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid) + new_issue_link = new_project_issue_path(project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid) expect(page).to have_link 'Resolve this discussion in a new issue', href: new_issue_link end context 'creating the issue' do before do - click_link 'Resolve this discussion in a new issue', href: new_namespace_project_issue_path(project.namespace, project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid) + click_link 'Resolve this discussion in a new issue', href: new_project_issue_path(project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid) end it 'has a hidden field for the discussion' do @@ -66,10 +66,9 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe describe 'as a reporter' do before do project.team << [user, :reporter] - login_as user - visit new_namespace_project_issue_path(project.namespace, project, - merge_request_to_resolve_discussions_of: merge_request.iid, - discussion_to_resolve: discussion.id) + sign_in user + visit new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid, + discussion_to_resolve: discussion.id) end it 'Shows a notice to ask someone else to resolve the discussions' do diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index 44353d880c2..a69bd8a09b7 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Dropdown assignee', :feature, :js do +describe 'Dropdown assignee', :js do include FilteredSearchHelpers - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } let!(:user_john) { create(:user, name: 'John', username: 'th0mas') } let!(:user_jacob) { create(:user, name: 'Jacob', username: 'otter32') } @@ -23,10 +23,10 @@ describe 'Dropdown assignee', :feature, :js do project.team << [user, :master] project.team << [user_john, :master] project.team << [user_jacob, :master] - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'behavior' do diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb index 6b707c4be4a..4bbf18e1dbe 100644 --- a/spec/features/issues/filtered_search/dropdown_author_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Dropdown author', js: true, feature: true do +describe 'Dropdown author', js: true do include FilteredSearchHelpers - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } let!(:user_john) { create(:user, name: 'John', username: 'th0mas') } let!(:user_jacob) { create(:user, name: 'Jacob', username: 'otter32') } @@ -31,10 +31,10 @@ describe 'Dropdown author', js: true, feature: true do project.team << [user, :master] project.team << [user_john, :master] project.team << [user_jacob, :master] - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'behavior' do diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb index b9a37cfcc22..04d6dea4b8c 100644 --- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Dropdown hint', :js, :feature do +describe 'Dropdown hint', :js do include FilteredSearchHelpers - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user) } let(:filtered_search) { find('.filtered-search') } let(:js_dropdown_hint) { '#js-dropdown-hint' } @@ -14,10 +14,10 @@ describe 'Dropdown hint', :js, :feature do before do project.team << [user, :master] - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'behavior' do diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb index abe5d61e38c..67eb0ef0119 100644 --- a/spec/features/issues/filtered_search/dropdown_label_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe 'Dropdown label', js: true, feature: true do +describe 'Dropdown label', js: true do include FilteredSearchHelpers - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:user) { create(:user) } let(:filtered_search) { find('.filtered-search') } let(:js_dropdown_label) { '#js-dropdown-label' } @@ -34,10 +34,10 @@ describe 'Dropdown label', js: true, feature: true do before do project.add_master(user) - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'keyboard navigation' do diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb index 448259057b0..456eb05f241 100644 --- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -describe 'Dropdown milestone', :feature, :js do +describe 'Dropdown milestone', :js do include FilteredSearchHelpers - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user) } let!(:milestone) { create(:milestone, title: 'v1.0', project: project) } let!(:uppercase_milestone) { create(:milestone, title: 'CAP_MILESTONE', project: project) } @@ -30,10 +30,10 @@ describe 'Dropdown milestone', :feature, :js do before do project.team << [user, :master] - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'behavior' do diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index e5e4ba06b5a..cd2cbf4bfe7 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Filter issues', js: true, feature: true do +describe 'Filter issues', js: true do include Devise::Test::IntegrationHelpers include FilteredSearchHelpers @@ -89,7 +89,7 @@ describe 'Filter issues', js: true, feature: true do milestone: future_milestone, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'filter issues by author' do @@ -459,7 +459,7 @@ describe 'Filter issues', js: true, feature: true do context 'issue label clicked' do before do - find('.issues-list .issue .issue-info a .label', text: multiple_words_label.title).click + find('.issues-list .issue .issue-main-info .issuable-info a .label', text: multiple_words_label.title).click end it 'filters' do @@ -777,17 +777,17 @@ describe 'Filter issues', js: true, feature: true do end it 'open state' do - find('.issues-state-filters a', text: 'Closed').click + find('.issues-state-filters [data-state="closed"]').click wait_for_requests - find('.issues-state-filters a', text: 'Open').click + find('.issues-state-filters [data-state="opened"]').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 4) end it 'closed state' do - find('.issues-state-filters a', text: 'Closed').click + find('.issues-state-filters [data-state="closed"]').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 1) @@ -795,7 +795,7 @@ describe 'Filter issues', js: true, feature: true do end it 'all state' do - find('.issues-state-filters a', text: 'All').click + find('.issues-state-filters [data-state="all"]').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 5) @@ -804,7 +804,7 @@ describe 'Filter issues', js: true, feature: true do describe 'RSS feeds' do it 'updates atom feed link for project issues' do - visit namespace_project_issues_path(project.namespace, project, milestone_title: milestone.title, assignee_id: user.id) + visit project_issues_path(project, milestone_title: milestone.title, assignee_id: user.id) link = find_link('Subscribe') params = CGI.parse(URI.parse(link[:href]).query) auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) @@ -836,7 +836,7 @@ describe 'Filter issues', js: true, feature: true do context 'URL has a trailing slash' do before do - visit "#{namespace_project_issues_path(project.namespace, project)}/" + visit "#{project_issues_path(project)}/" end it 'milestone dropdown loads milestones' do diff --git a/spec/features/issues/filtered_search/recent_searches_spec.rb b/spec/features/issues/filtered_search/recent_searches_spec.rb index 09f228bcf49..5eeecaeda47 100644 --- a/spec/features/issues/filtered_search/recent_searches_spec.rb +++ b/spec/features/issues/filtered_search/recent_searches_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'Recent searches', js: true, feature: true do +describe 'Recent searches', js: true do include FilteredSearchHelpers - let(:project_1) { create(:empty_project, :public) } - let(:project_2) { create(:empty_project, :public) } + let(:project_1) { create(:project, :public) } + let(:project_2) { create(:project, :public) } let(:project_1_local_storage_key) { "#{project_1.full_path}-issue-recent-searches" } before do @@ -22,7 +22,7 @@ describe 'Recent searches', js: true, feature: true do end it 'searching adds to recent searches' do - visit namespace_project_issues_path(project_1.namespace, project_1) + visit project_issues_path(project_1) input_filtered_search('foo', submit: true) input_filtered_search('bar', submit: true) @@ -35,8 +35,8 @@ describe 'Recent searches', js: true, feature: true do end it 'visiting URL with search params adds to recent searches' do - visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'foo', search: 'bar') - visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'qux', search: 'garply') + visit project_issues_path(project_1, label_name: 'foo', search: 'bar') + visit project_issues_path(project_1, label_name: 'qux', search: 'garply') items = all('.filtered-search-history-dropdown-item', visible: false) @@ -48,7 +48,7 @@ describe 'Recent searches', js: true, feature: true do it 'saved recent searches are restored last on the list' do set_recent_searches(project_1_local_storage_key, '["saved1", "saved2"]') - visit namespace_project_issues_path(project_1.namespace, project_1, search: 'foo') + visit project_issues_path(project_1, search: 'foo') items = all('.filtered-search-history-dropdown-item', visible: false) @@ -59,12 +59,12 @@ describe 'Recent searches', js: true, feature: true do end it 'searches are scoped to projects' do - visit namespace_project_issues_path(project_1.namespace, project_1) + visit project_issues_path(project_1) input_filtered_search('foo', submit: true) input_filtered_search('bar', submit: true) - visit namespace_project_issues_path(project_2.namespace, project_2) + visit project_issues_path(project_2) input_filtered_search('more', submit: true) input_filtered_search('things', submit: true) @@ -78,7 +78,7 @@ describe 'Recent searches', js: true, feature: true do it 'clicking item fills search input' do set_recent_searches(project_1_local_storage_key, '["foo", "bar"]') - visit namespace_project_issues_path(project_1.namespace, project_1) + visit project_issues_path(project_1) all('.filtered-search-history-dropdown-item', visible: false)[0].trigger('click') wait_for_filtered_search('foo') @@ -88,7 +88,7 @@ describe 'Recent searches', js: true, feature: true do it 'clear recent searches button, clears recent searches' do set_recent_searches(project_1_local_storage_key, '["foo"]') - visit namespace_project_issues_path(project_1.namespace, project_1) + visit project_issues_path(project_1) items_before = all('.filtered-search-history-dropdown-item', visible: false) @@ -102,7 +102,7 @@ describe 'Recent searches', js: true, feature: true do it 'shows flash error when failed to parse saved history' do set_recent_searches(project_1_local_storage_key, 'fail') - visit namespace_project_issues_path(project_1.namespace, project_1) + visit project_issues_path(project_1) expect(find('.flash-alert')).to have_text('An error occured while parsing recent searches') end diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb index 3ea95aed0a6..aa9d0d842de 100644 --- a/spec/features/issues/filtered_search/search_bar_spec.rb +++ b/spec/features/issues/filtered_search/search_bar_spec.rb @@ -1,18 +1,18 @@ require 'rails_helper' -describe 'Search bar', js: true, feature: true do +describe 'Search bar', js: true do include FilteredSearchHelpers - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user) } let(:filtered_search) { find('.filtered-search') } before do project.team << [user, :master] - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end def get_left_style(style) diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb index ff32b0c7d11..52efe944b69 100644 --- a/spec/features/issues/filtered_search/visual_tokens_spec.rb +++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -describe 'Visual tokens', js: true, feature: true do +describe 'Visual tokens', js: true do include FilteredSearchHelpers include WaitForRequests - let!(:project) { create(:empty_project) } + let!(:project) { create(:project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } let!(:user_rock) { create(:user, name: 'The Rock', username: 'rock') } let!(:milestone_nine) { create(:milestone, title: '9.0', project: project) } @@ -25,10 +25,10 @@ describe 'Visual tokens', js: true, feature: true do before do project.add_user(user, :master) project.add_user(user_rock, :master) - login_as(user) + sign_in(user) create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) end describe 'editing author token' do @@ -133,7 +133,7 @@ describe 'Visual tokens', js: true, feature: true do describe 'editing milestone token' do before do input_filtered_search('milestone:%10.0 author:none', submit: false) - first('.tokens-container .filtered-search-token').double_click + first('.tokens-container .filtered-search-token').click first('#js-dropdown-milestone .filter-dropdown .filter-dropdown-item') end diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 8949dbcb663..4297bfff3d9 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' -describe 'New/edit issue', :feature, :js do - include GitlabRoutingHelper +describe 'New/edit issue', :js do include ActionView::Helpers::JavaScriptHelper include FormHelper @@ -16,50 +15,30 @@ describe 'New/edit issue', :feature, :js do before do project.team << [user, :master] project.team << [user2, :master] - login_as(user) + sign_in(user) end context 'new issue' do before do - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) end describe 'shorten users API pagination limit' do before do - allow_any_instance_of(FormHelper).to receive(:issue_dropdown_options).and_wrap_original do |original, *args| - has_multiple_assignees = *args[1] - - options = { - toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data', - title: 'Select assignee', - filter: true, - dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee', - placeholder: 'Search users', - data: { - per_page: 1, - null_user: true, - current_user: true, - project_id: project.try(:id), - field_name: "issue[assignee_ids][]", - default_label: 'Assignee', - 'max-select': 1, - 'dropdown-header': 'Assignee', - multi_select: true, - 'input-meta': 'name', - 'always-show-selectbox': true - } - } - - if has_multiple_assignees - options[:title] = 'Select assignee(s)' - options[:data][:'dropdown-header'] = 'Assignee(s)' - options[:data].delete(:'max-select') - end + # Using `allow_any_instance_of`/`and_wrap_original`, `original` would + # somehow refer to the very block we defined to _wrap_ that method, instead of + # the original method, resulting in infinite recurison when called. + # This is likely a bug with helper modules included into dynamically generated view classes. + # To work around this, we have to hold on to and call to the original implementation manually. + original_issue_dropdown_options = FormHelper.instance_method(:issue_assignees_dropdown_options) + allow_any_instance_of(FormHelper).to receive(:issue_assignees_dropdown_options).and_wrap_original do |original, *args| + options = original_issue_dropdown_options.bind(original.receiver).call(*args) + options[:data][:per_page] = 2 options end - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) click_button 'Unassigned' @@ -74,6 +53,7 @@ describe 'New/edit issue', :feature, :js do click_link user2.name end + find('.js-assignee-search').click find('.js-dropdown-input-clear').click page.within '.dropdown-menu-user' do @@ -229,11 +209,18 @@ describe 'New/edit issue', :feature, :js do expect(find('.js-assignee-search')).to have_content(user2.name) end + + it 'description has autocomplete' do + find('#issue_description').native.send_keys('') + fill_in 'issue_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end end context 'edit issue' do before do - visit edit_namespace_project_issue_path(project.namespace, project, issue) + visit edit_project_issue_path(project, issue) end it 'allows user to update issue' do @@ -277,17 +264,24 @@ describe 'New/edit issue', :feature, :js do end end end + + it 'description has autocomplete' do + find('#issue_description').native.send_keys('') + fill_in 'issue_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end end describe 'sub-group project' do let(:group) { create(:group) } let(:nested_group_1) { create(:group, parent: group) } - let(:sub_group_project) { create(:empty_project, group: nested_group_1) } + let(:sub_group_project) { create(:project, group: nested_group_1) } before do sub_group_project.add_master(user) - visit new_namespace_project_issue_path(sub_group_project.namespace, sub_group_project) + visit new_project_issue_path(sub_group_project) end it 'creates new label from dropdown' do diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 350473437a8..b84635c5134 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'GFM autocomplete', feature: true, js: true do +feature 'GFM autocomplete', js: true do let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let(:project) { create(:project) } let(:label) { create(:label, project: project, title: 'special+') } @@ -8,12 +8,24 @@ feature 'GFM autocomplete', feature: true, js: true do before do project.team << [user, :master] - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) wait_for_requests end + it 'updates issue descripton with GFM reference' do + find('.issuable-edit').click + + find('#issue-description').native.send_keys("@#{user.name[0...3]}") + + find('.atwho-view .cur').trigger('click') + + click_button 'Save changes' + + expect(find('.description')).to have_content(user.to_reference) + end + it 'opens autocomplete menu when field starts with text' do page.within '.timeline-content-form' do find('#note_note').native.send_keys('') @@ -208,7 +220,7 @@ feature 'GFM autocomplete', feature: true, js: true do expect(page).not_to have_selector('.atwho-view') end - it 'triggers autocomplete after selecting a slash command' do + it 'triggers autocomplete after selecting a quick action' do note = find('#note_note') page.within '.timeline-content-form' do note.native.send_keys('') diff --git a/spec/features/issues/group_label_sidebar_spec.rb b/spec/features/issues/group_label_sidebar_spec.rb index fc8515cfe9b..9c10f78f67a 100644 --- a/spec/features/issues/group_label_sidebar_spec.rb +++ b/spec/features/issues/group_label_sidebar_spec.rb @@ -1,18 +1,14 @@ require 'rails_helper' -describe 'Group label on issue', :feature do +describe 'Group label on issue' do it 'renders link to the project issues page' do group = create(:group) - project = create(:empty_project, :public, namespace: group) + project = create(:project, :public, namespace: group) feature = create(:group_label, group: group, title: 'feature') issue = create(:labeled_issue, project: project, labels: [feature]) - label_link = namespace_project_issues_path( - project.namespace, - project, - label_name: [feature.name] - ) + label_link = project_issues_path(project, label_name: [feature.name]) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) link = find('.issuable-show-labels a') diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb new file mode 100644 index 00000000000..28b636f9359 --- /dev/null +++ b/spec/features/issues/issue_detail_spec.rb @@ -0,0 +1,43 @@ +require 'rails_helper' + +feature 'Issue Detail', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project, author: user) } + + context 'when user displays the issue' do + before do + visit project_issue_path(project, issue) + wait_for_requests + end + + it 'shows the issue' do + page.within('.issuable-details') do + expect(find('h2')).to have_content(issue.title) + end + end + end + + context 'when edited by a user who is later deleted' do + before do + sign_in(user) + visit project_issue_path(project, issue) + wait_for_requests + + click_link 'Edit' + fill_in 'issue-title', with: 'issue title' + click_button 'Save' + + visit profile_account_path + click_link 'Delete account' + + visit project_issue_path(project, issue) + end + + it 'shows the issue' do + page.within('.issuable-details') do + expect(find('h2')).to have_content(issue.reload.title) + end + end + end +end diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 96c24750250..8e22441e0e8 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'Issue Sidebar', feature: true do +feature 'Issue Sidebar' do include MobileHelpers let(:group) { create(:group, :nested) } @@ -10,7 +10,7 @@ feature 'Issue Sidebar', feature: true do let!(:label) { create(:label, project: project, title: 'bug') } before do - login_as(user) + sign_in(user) end context 'assignee', js: true do @@ -154,20 +154,6 @@ feature 'Issue Sidebar', feature: true do end end - context 'as a allowed mobile user', js: true do - before do - project.team << [user, :developer] - resize_screen_xs - visit_issue(project, issue) - end - - context 'mobile sidebar' do - it 'collapses the sidebar for small screens' do - expect(page).not_to have_css('aside.right-sidebar.right-sidebar-collapsed') - end - end - end - context 'as a guest' do before do project.team << [user, :guest] @@ -180,7 +166,7 @@ feature 'Issue Sidebar', feature: true do end def visit_issue(project, issue) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end def open_issue_sidebar diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb index c8c9c50396b..8c23fcd483b 100644 --- a/spec/features/issues/markdown_toolbar_spec.rb +++ b/spec/features/issues/markdown_toolbar_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Issue markdown toolbar', feature: true, js: true do +feature 'Issue markdown toolbar', js: true do let(:project) { create(:project, :public) } let(:issue) { create(:issue, project: project) } - let(:user) { create(:user) } + let(:user) { create(:user) } before do - login_as(user) + sign_in(user) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it "doesn't include first new line when adding bold" do diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index e75bf059218..494c309c9ea 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -2,14 +2,14 @@ require 'rails_helper' feature 'issue move to another project' do let(:user) { create(:user) } - let(:old_project) { create(:project) } + let(:old_project) { create(:project, :repository) } let(:text) { 'Some issue description' } let(:issue) do create(:issue, description: text, project: old_project, author: user) end - background { login_as(user) } + background { sign_in(user) } context 'user does not have permission to move issue' do background do @@ -41,13 +41,10 @@ feature 'issue move to another project' do find('#issuable-move', visible: false).set(new_project.id) click_button('Save changes') - wait_for_requests - - expect(current_url).to include project_path(new_project) - expect(page).to have_content("Text with #{cross_reference}#{mr.to_reference}") expect(page).to have_content("moved from #{cross_reference}#{issue.to_reference}") expect(page).to have_content(issue.title) + expect(page.current_path).to include project_path(new_project) end scenario 'searching project dropdown', js: true do @@ -98,10 +95,6 @@ feature 'issue move to another project' do end def issue_path(issue) - namespace_project_issue_path(issue.project.namespace, issue.project, issue) - end - - def project_path(project) - namespace_project_path(new_project.namespace, new_project) + project_issue_path(issue.project, issue) end end diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb index 80f57906506..9f08ecc214b 100644 --- a/spec/features/issues/note_polling_spec.rb +++ b/spec/features/issues/note_polling_spec.rb @@ -1,12 +1,14 @@ require 'spec_helper' -feature 'Issue notes polling', :feature, :js do - let(:project) { create(:empty_project, :public) } +feature 'Issue notes polling', :js do + include NoteInteractionHelpers + + let(:project) { create(:project, :public) } let(:issue) { create(:issue, project: project) } describe 'creates' do before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'displays the new comment' do @@ -25,8 +27,8 @@ feature 'Issue notes polling', :feature, :js do let!(:existing_note) { create(:note, noteable: issue, project: project, author: user, note: note_text) } before do - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) end it 'has .original-note-content to compare against' do @@ -48,7 +50,7 @@ feature 'Issue notes polling', :feature, :js do end it 'when editing but have not changed anything, and an update comes in, show the updated content in the textarea' do - find("#note_#{existing_note.id} .js-note-edit").click + click_edit_action(existing_note) expect(page).to have_field("note[note]", with: note_text) @@ -58,19 +60,18 @@ feature 'Issue notes polling', :feature, :js do end it 'when editing but you changed some things, and an update comes in, show a warning' do - find("#note_#{existing_note.id} .js-note-edit").click + click_edit_action(existing_note) expect(page).to have_field("note[note]", with: note_text) find("#note_#{existing_note.id} .js-note-text").set('something random') - update_note(existing_note, updated_text) expect(page).to have_selector(".alert") end it 'when editing but you changed some things, an update comes in, and you press cancel, show the updated content' do - find("#note_#{existing_note.id} .js-note-edit").click + click_edit_action(existing_note) expect(page).to have_field("note[note]", with: note_text) @@ -92,8 +93,8 @@ feature 'Issue notes polling', :feature, :js do let!(:existing_note) { create(:note, noteable: issue, project: project, author: user1, note: note_text) } before do - login_as(user2) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user2) + visit project_issue_path(project, issue) end it 'has .original-note-content to compare against' do @@ -113,8 +114,8 @@ feature 'Issue notes polling', :feature, :js do let!(:system_note) { create(:system_note, noteable: issue, project: project, author: user, note: note_text) } before do - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) end it 'has .original-note-content to compare against' do @@ -128,4 +129,12 @@ feature 'Issue notes polling', :feature, :js do note.update(note: new_text) page.execute_script('notes.refresh();') end + + def click_edit_action(note) + note_element = find("#note_#{note.id}") + + open_more_actions_dropdown(note) + + note_element.find('.js-note-edit').click + end end diff --git a/spec/features/issues/notes_on_issues_spec.rb b/spec/features/issues/notes_on_issues_spec.rb index 15c817cabac..05c93a19253 100644 --- a/spec/features/issues/notes_on_issues_spec.rb +++ b/spec/features/issues/notes_on_issues_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Create notes on issues', :js, :feature do +describe 'Create notes on issues', :js do let(:user) { create(:user) } shared_examples 'notes with reference' do @@ -9,8 +9,8 @@ describe 'Create notes on issues', :js, :feature do before do project.team << [user, :developer] - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) fill_in 'note[note]', with: note_text click_button 'Comment' @@ -56,21 +56,21 @@ describe 'Create notes on issues', :js, :feature do context 'mentioning merge request on a private project' do it_behaves_like 'notes with reference' do - let(:project) { create(:project, :private) } + let(:project) { create(:project, :private, :repository) } let(:mention) { create(:merge_request, source_project: project) } end end context 'mentioning merge request on an internal project' do it_behaves_like 'notes with reference' do - let(:project) { create(:project, :internal) } + let(:project) { create(:project, :internal, :repository) } let(:mention) { create(:merge_request, source_project: project) } end end context 'mentioning merge request on a public project' do it_behaves_like 'notes with reference' do - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:mention) { create(:merge_request, source_project: project) } end end diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb index 6001476d0ca..332ce78b138 100644 --- a/spec/features/issues/spam_issues_spec.rb +++ b/spec/features/issues/spam_issues_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'New issue', feature: true, js: true do +describe 'New issue', js: true do include StubENV let(:project) { create(:project, :public) } @@ -18,14 +18,14 @@ describe 'New issue', feature: true, js: true do ) project.team << [user, :master] - login_as(user) + sign_in(user) end context 'when identified as a spam' do before do WebMock.stub_request(:any, /.*akismet.com.*/).to_return(body: "true", status: 200) - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) end it 'creates an issue after solving reCaptcha' do @@ -50,7 +50,7 @@ describe 'New issue', feature: true, js: true do before do WebMock.stub_request(:any, /.*akismet.com.*/).to_return(body: 'false', status: 200) - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) end it 'creates an issue' do diff --git a/spec/features/issues/todo_spec.rb b/spec/features/issues/todo_spec.rb index 3fde85b0a5c..8405f1cd48d 100644 --- a/spec/features/issues/todo_spec.rb +++ b/spec/features/issues/todo_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Manually create a todo item from issue', feature: true, js: true do - let!(:project) { create(:project) } - let!(:issue) { create(:issue, project: project) } - let!(:user) { create(:user)} +feature 'Manually create a todo item from issue', js: true do + let!(:project) { create(:project) } + let!(:issue) { create(:issue, project: project) } + let!(:user) { create(:user)} before do project.team << [user, :master] - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) end it 'creates todo when clicking button' do @@ -21,7 +21,7 @@ feature 'Manually create a todo item from issue', feature: true, js: true do expect(page).to have_content '1' end - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) page.within '.header-content .todos-count' do expect(page).to have_content '1' @@ -36,7 +36,7 @@ feature 'Manually create a todo item from issue', feature: true, js: true do expect(page).to have_selector('.todos-count', visible: false) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(page).to have_selector('.todos-count', visible: false) end diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb index 8595847d313..5a7c4f54cb6 100644 --- a/spec/features/issues/update_issues_spec.rb +++ b/spec/features/issues/update_issues_spec.rb @@ -1,18 +1,18 @@ require 'rails_helper' -feature 'Multiple issue updating from issues#index', feature: true do +feature 'Multiple issue updating from issues#index', :js do let!(:project) { create(:project) } let!(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} before do project.team << [user, :master] - login_as(user) + sign_in(user) end - context 'status', js: true do + context 'status' do it 'sets to closed' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button 'Edit Issues' find('#check-all-issues').click @@ -25,7 +25,7 @@ feature 'Multiple issue updating from issues#index', feature: true do it 'sets to open' do create_closed - visit namespace_project_issues_path(project.namespace, project, state: 'closed') + visit project_issues_path(project, state: 'closed') click_button 'Edit Issues' find('#check-all-issues').click @@ -37,9 +37,9 @@ feature 'Multiple issue updating from issues#index', feature: true do end end - context 'assignee', js: true do + context 'assignee' do it 'updates to current user' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button 'Edit Issues' find('#check-all-issues').click @@ -55,7 +55,7 @@ feature 'Multiple issue updating from issues#index', feature: true do it 'updates to unassigned' do create_assigned - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button 'Edit Issues' find('#check-all-issues').click @@ -67,11 +67,11 @@ feature 'Multiple issue updating from issues#index', feature: true do end end - context 'milestone', js: true do - let(:milestone) { create(:milestone, project: project) } + context 'milestone' do + let!(:milestone) { create(:milestone, project: project) } it 'updates milestone' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button 'Edit Issues' find('#check-all-issues').click @@ -85,7 +85,7 @@ feature 'Multiple issue updating from issues#index', feature: true do it 'sets to no milestone' do create_with_milestone - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(first('.issue')).to have_content milestone.title diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index d14c319707c..4b63cc844f3 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -feature 'Issues > User uses slash commands', feature: true, js: true do - include SlashCommandsHelpers +feature 'Issues > User uses quick actions', js: true do + include QuickActionsHelpers - it_behaves_like 'issuable record that supports slash commands in its description and notes', :issue do + it_behaves_like 'issuable record that supports quick actions in its description and notes', :issue do let(:issuable) { create(:issue, project: project) } end @@ -13,14 +13,24 @@ feature 'Issues > User uses slash commands', feature: true, js: true do before do project.team << [user, :master] - login_with(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) end after do wait_for_requests end + describe 'time tracking' do + let(:issue) { create(:issue, project: project) } + + before do + visit project_issue_path(project, issue) + end + + it_behaves_like 'issuable time tracker' + end + describe 'adding a due date from note' do let(:issue) { create(:issue, project: project) } @@ -41,9 +51,9 @@ feature 'Issues > User uses slash commands', feature: true, js: true do let(:guest) { create(:user) } before do project.team << [guest, :guest] - logout - login_with(guest) - visit namespace_project_issue_path(project.namespace, project, issue) + gitlab_sign_out + sign_in(guest) + visit project_issue_path(project, issue) end it 'does not create a note, and sets the due date accordingly' do @@ -81,9 +91,9 @@ feature 'Issues > User uses slash commands', feature: true, js: true do let(:guest) { create(:user) } before do project.team << [guest, :guest] - logout - login_with(guest) - visit namespace_project_issue_path(project.namespace, project, issue) + gitlab_sign_out + sign_in(guest) + visit project_issue_path(project, issue) end it 'does not create a note, and sets the due date accordingly' do @@ -99,65 +109,50 @@ feature 'Issues > User uses slash commands', feature: true, js: true do end end - describe 'Issuable time tracking' do + describe 'toggling the WIP prefix from the title from note' do let(:issue) { create(:issue, project: project) } - before do - project.team << [user, :developer] - end - - context 'Issue' do - before do - visit namespace_project_issue_path(project.namespace, project, issue) - end - - it_behaves_like 'issuable time tracker' - end - - context 'Merge Request' do - let(:merge_request) { create(:merge_request, source_project: project) } - - before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) - end + it 'does not recognize the command nor create a note' do + write_note("/wip") - it_behaves_like 'issuable time tracker' + expect(page).not_to have_content '/wip' end end - describe 'Issuable time tracking' do + describe 'mark issue as duplicate' do let(:issue) { create(:issue, project: project) } + let(:original_issue) { create(:issue, project: project) } - before do - project.team << [user, :developer] - end + context 'when the current user can update issues' do + it 'does not create a note, and marks the issue as a duplicate' do + write_note("/duplicate ##{original_issue.to_reference}") - context 'Issue' do - before do - visit namespace_project_issue_path(project.namespace, project, issue) - end + expect(page).not_to have_content "/duplicate #{original_issue.to_reference}" + expect(page).to have_content 'Commands applied' + expect(page).to have_content "marked this issue as a duplicate of #{original_issue.to_reference}" - it_behaves_like 'issuable time tracker' + expect(issue.reload).to be_closed + end end - context 'Merge Request' do - let(:merge_request) { create(:merge_request, source_project: project) } - + context 'when the current user cannot update the issue' do + let(:guest) { create(:user) } before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + project.team << [guest, :guest] + gitlab_sign_out + sign_in(guest) + visit project_issue_path(project, issue) end - it_behaves_like 'issuable time tracker' - end - end - - describe 'toggling the WIP prefix from the title from note' do - let(:issue) { create(:issue, project: project) } + it 'does not create a note, and does not mark the issue as a duplicate' do + write_note("/duplicate ##{original_issue.to_reference}") - it 'does not recognize the command nor create a note' do - write_note("/wip") + expect(page).to have_content "/duplicate ##{original_issue.to_reference}" + expect(page).not_to have_content 'Commands applied' + expect(page).not_to have_content "marked this issue as a duplicate of #{original_issue.to_reference}" - expect(page).not_to have_content '/wip' + expect(issue.reload).to be_open + end end end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index eecc565d2bd..489baa4291f 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -1,29 +1,30 @@ require 'spec_helper' -describe 'Issues', feature: true do +describe 'Issues' do include DropzoneHelper include IssueHelpers include SortingHelper - let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:project) { create(:project, :public) } before do - login_as :user + sign_in(user) user2 = create(:user) - project.team << [[@user, user2], :developer] + project.team << [[user, user2], :developer] end describe 'Edit issue' do let!(:issue) do create(:issue, - author: @user, - assignees: [@user], + author: user, + assignees: [user], project: project) end before do - visit edit_namespace_project_issue_path(project.namespace, project, issue) + visit edit_project_issue_path(project, issue) find('.js-zen-enter').click end @@ -35,15 +36,15 @@ describe 'Issues', feature: true do describe 'Editing issue assignee' do let!(:issue) do create(:issue, - author: @user, - assignees: [@user], + author: user, + assignees: [user], project: project) end it 'allows user to select unassigned', js: true do - visit edit_namespace_project_issue_path(project.namespace, project, issue) + visit edit_project_issue_path(project, issue) - expect(page).to have_content "Assignee #{@user.name}" + expect(page).to have_content "Assignee #{user.name}" first('.js-user-search').click click_link 'Unassigned' @@ -61,7 +62,7 @@ describe 'Issues', feature: true do describe 'due date', js: true do context 'on new form' do before do - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) end it 'saves with due date' do @@ -86,10 +87,10 @@ describe 'Issues', feature: true do end context 'on edit form' do - let(:issue) { create(:issue, author: @user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } + let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } before do - visit edit_namespace_project_issue_path(project.namespace, project, issue) + visit edit_project_issue_path(project, issue) end it 'saves with due date' do @@ -131,10 +132,10 @@ describe 'Issues', feature: true do describe 'Issue info' do it 'excludes award_emoji from comment count' do - issue = create(:issue, author: @user, assignees: [@user], project: project, title: 'foobar') + issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar') create(:award_emoji, awardable: issue) - visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id) + visit project_issues_path(project, assignee_id: user.id) expect(page).to have_content 'foobar' expect(page.all('.no-comments').first.text).to eq "0" @@ -145,8 +146,8 @@ describe 'Issues', feature: true do before do %w(foobar barbaz gitlab).each do |title| create(:issue, - author: @user, - assignees: [@user], + author: user, + assignees: [user], project: project, title: title) end @@ -160,7 +161,7 @@ describe 'Issues', feature: true do let(:issue) { @issue } it 'allows filtering by issues with no specified assignee' do - visit namespace_project_issues_path(project.namespace, project, assignee_id: IssuableFinder::NONE) + visit project_issues_path(project, assignee_id: IssuableFinder::NONE) expect(page).to have_content 'foobar' expect(page).not_to have_content 'barbaz' @@ -168,7 +169,7 @@ describe 'Issues', feature: true do end it 'allows filtering by a specified assignee' do - visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id) + visit project_issues_path(project, assignee_id: user.id) expect(page).not_to have_content 'foobar' expect(page).to have_content 'barbaz' @@ -189,14 +190,14 @@ describe 'Issues', feature: true do let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } it 'sorts by newest' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created) + visit project_issues_path(project, sort: sort_value_recently_created) expect(first_issue).to include('foo') expect(last_issue).to include('baz') end it 'sorts by oldest' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_created) + visit project_issues_path(project, sort: sort_value_oldest_created) expect(first_issue).to include('baz') expect(last_issue).to include('foo') @@ -205,7 +206,7 @@ describe 'Issues', feature: true do it 'sorts by most recently updated' do baz.updated_at = Time.now + 100 baz.save - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_updated) + visit project_issues_path(project, sort: sort_value_recently_updated) expect(first_issue).to include('baz') end @@ -213,7 +214,7 @@ describe 'Issues', feature: true do it 'sorts by least recently updated' do baz.updated_at = Time.now - 100 baz.save - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_updated) + visit project_issues_path(project, sort: sort_value_oldest_updated) expect(first_issue).to include('baz') end @@ -225,13 +226,13 @@ describe 'Issues', feature: true do end it 'sorts by recently due date' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_soon) + visit project_issues_path(project, sort: sort_value_due_date_soon) expect(first_issue).to include('foo') end it 'sorts by least recently due date' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later) + visit project_issues_path(project, sort: sort_value_due_date_later) expect(first_issue).to include('bar') end @@ -239,19 +240,22 @@ describe 'Issues', feature: true do it 'sorts by least recently due date by excluding nil due dates' do bar.update(due_date: nil) - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later) + visit project_issues_path(project, sort: sort_value_due_date_later) expect(first_issue).to include('foo') end context 'with a filter on labels' do let(:label) { create(:label, project: project) } - before { create(:label_link, label: label, target: foo) } + + before do + create(:label_link, label: label, target: foo) + end it 'sorts by least recently due date by excluding nil due dates' do bar.update(due_date: nil) - visit namespace_project_issues_path(project.namespace, project, label_names: [label.name], sort: sort_value_due_date_later) + visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later) expect(first_issue).to include('foo') end @@ -265,7 +269,7 @@ describe 'Issues', feature: true do end it 'filters by none' do - visit namespace_project_issues_path(project.namespace, project, due_date: Issue::NoDueDate.name) + visit project_issues_path(project, due_date: Issue::NoDueDate.name) expect(page).not_to have_content('foo') expect(page).not_to have_content('bar') @@ -273,7 +277,7 @@ describe 'Issues', feature: true do end it 'filters by any' do - visit namespace_project_issues_path(project.namespace, project, due_date: Issue::AnyDueDate.name) + visit project_issues_path(project, due_date: Issue::AnyDueDate.name) expect(page).to have_content('foo') expect(page).to have_content('bar') @@ -285,7 +289,7 @@ describe 'Issues', feature: true do bar.update(due_date: Date.today.end_of_week) baz.update(due_date: Date.today - 8.days) - visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisWeek.name) + visit project_issues_path(project, due_date: Issue::DueThisWeek.name) expect(page).to have_content('foo') expect(page).to have_content('bar') @@ -297,7 +301,7 @@ describe 'Issues', feature: true do bar.update(due_date: Date.today.end_of_month) baz.update(due_date: Date.today - 50.days) - visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisMonth.name) + visit project_issues_path(project, due_date: Issue::DueThisMonth.name) expect(page).to have_content('foo') expect(page).to have_content('bar') @@ -309,7 +313,7 @@ describe 'Issues', feature: true do bar.update(due_date: Date.today + 20.days) baz.update(due_date: Date.yesterday) - visit namespace_project_issues_path(project.namespace, project, due_date: Issue::Overdue.name) + visit project_issues_path(project, due_date: Issue::Overdue.name) expect(page).not_to have_content('foo') expect(page).not_to have_content('bar') @@ -326,14 +330,14 @@ describe 'Issues', feature: true do end it 'sorts by recently due milestone' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon) + visit project_issues_path(project, sort: sort_value_milestone_soon) expect(first_issue).to include('foo') expect(last_issue).to include('baz') end it 'sorts by least recently due milestone' do - visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later) + visit project_issues_path(project, sort: sort_value_milestone_later) expect(first_issue).to include('bar') expect(last_issue).to include('baz') @@ -351,7 +355,7 @@ describe 'Issues', feature: true do end it 'sorts with a filter applied' do - visit namespace_project_issues_path(project.namespace, project, + visit project_issues_path(project, sort: sort_value_oldest_created, assignee_id: user2.id) @@ -363,13 +367,13 @@ describe 'Issues', feature: true do end describe 'when I want to reset my incoming email token' do - let(:project1) { create(:empty_project, namespace: @user.namespace) } + let(:project1) { create(:project, namespace: user.namespace) } let!(:issue) { create(:issue, project: project1) } before do stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") - project1.team << [@user, :master] - visit namespace_project_issues_path(@user.namespace, project1) + project1.team << [user, :master] + visit namespace_project_issues_path(user.namespace, project1) end it 'changes incoming email address token', js: true do @@ -380,7 +384,7 @@ describe 'Issues', feature: true do wait_for_requests expect(page).to have_no_field('issue_email', with: previous_token) - new_token = project1.new_issue_address(@user.reload) + new_token = project1.new_issue_address(user.reload) expect(page).to have_field( 'issue_email', with: new_token @@ -389,11 +393,11 @@ describe 'Issues', feature: true do end describe 'update labels from issue#show', js: true do - let(:issue) { create(:issue, project: project, author: @user, assignees: [@user]) } + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } let!(:label) { create(:label, project: project) } before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'will not send ajax request when no data is changed' do @@ -408,14 +412,14 @@ describe 'Issues', feature: true do end describe 'update assignee from issue#show' do - let(:issue) { create(:issue, project: project, author: @user, assignees: [@user]) } + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } context 'by authorized user' do it 'allows user to select unassigned', js: true do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) page.within('.assignee') do - expect(page).to have_content "#{@user.name}" + expect(page).to have_content "#{user.name}" click_link 'Edit' click_link 'Unassigned' @@ -430,8 +434,8 @@ describe 'Issues', feature: true do end it 'allows user to select an assignee', js: true do - issue2 = create(:issue, project: project, author: @user) - visit namespace_project_issue_path(project.namespace, project, issue2) + issue2 = create(:issue, project: project, author: user) + visit project_issue_path(project, issue2) page.within('.assignee') do expect(page).to have_content "No assignee" @@ -442,28 +446,28 @@ describe 'Issues', feature: true do end page.within '.dropdown-menu-user' do - click_link @user.name + click_link user.name end page.within('.assignee') do - expect(page).to have_content @user.name + expect(page).to have_content user.name end end it 'allows user to unselect themselves', js: true do - issue2 = create(:issue, project: project, author: @user) - visit namespace_project_issue_path(project.namespace, project, issue2) + issue2 = create(:issue, project: project, author: user) + visit project_issue_path(project, issue2) page.within '.assignee' do click_link 'Edit' - click_link @user.name + click_link user.name page.within '.value .author' do - expect(page).to have_content @user.name + expect(page).to have_content user.name end click_link 'Edit' - click_link @user.name + click_link user.name page.within '.value .assign-yourself' do expect(page).to have_content "No assignee" @@ -480,22 +484,22 @@ describe 'Issues', feature: true do end it 'shows assignee text', js: true do - logout - login_with guest + sign_out(:user) + sign_in(guest) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(page).to have_content issue.assignees.first.name end end end describe 'update milestone from issue#show' do - let!(:issue) { create(:issue, project: project, author: @user) } + let!(:issue) { create(:issue, project: project, author: user) } let!(:milestone) { create(:milestone, project: project) } context 'by authorized user' do it 'allows user to select unassigned', js: true do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) page.within('.milestone') do expect(page).to have_content "None" @@ -513,7 +517,7 @@ describe 'Issues', feature: true do end it 'allows user to de-select milestone', js: true do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) page.within('.milestone') do click_link 'Edit' @@ -543,10 +547,10 @@ describe 'Issues', feature: true do end it 'shows milestone text', js: true do - logout - login_with guest + sign_out(:user) + sign_in(guest) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(page).to have_content milestone.title end end @@ -557,25 +561,25 @@ describe 'Issues', feature: true do context 'by unauthenticated user' do before do - logout + sign_out(:user) end it 'redirects to signin then back to new issue after signin' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_link 'New issue' expect(current_path).to eq new_user_session_path - login_as :user + gitlab_sign_in(create(:user)) - expect(current_path).to eq new_namespace_project_issue_path(project.namespace, project) + expect(current_path).to eq new_project_issue_path(project) end end context 'dropzone upload file', js: true do before do - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) end it 'uploads file when dragging into textarea' do @@ -596,13 +600,13 @@ describe 'Issues', feature: true do before do project.repository.create_file( - @user, + user, '.gitlab/issue_templates/bug.md', 'this is a test "bug" template', message: 'added issue template', branch_name: 'master') - visit new_namespace_project_issue_path(project.namespace, project, issuable_template: 'bug') + visit new_project_issue_path(project, issuable_template: 'bug') end it 'fills in template' do @@ -619,13 +623,13 @@ describe 'Issues', feature: true do project.issues << issue stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) click_button('Email a new issue') end it 'click the button to show modal for the new email' do page.within '#issue-email-modal' do - email = project.new_issue_address(@user) + email = project.new_issue_address(user) expect(page).to have_selector("input[value='#{email}']") end @@ -633,7 +637,7 @@ describe 'Issues', feature: true do end context 'with existing issues' do - let!(:issue) { create(:issue, project: project, author: @user) } + let!(:issue) { create(:issue, project: project, author: user) } it_behaves_like 'show the email in the modal' end @@ -645,10 +649,10 @@ describe 'Issues', feature: true do describe 'due date' do context 'update due on issue#show', js: true do - let(:issue) { create(:issue, project: project, author: @user, assignees: [@user]) } + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } before do - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'adds due date to issue' do @@ -690,9 +694,9 @@ describe 'Issues', feature: true do describe 'title issue#show', js: true do it 'updates the title', js: true do - issue = create(:issue, author: @user, assignees: [@user], project: project, title: 'new title') + issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title') - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) expect(page).to have_text("new title") diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb index c82e8c03343..c9983f0941f 100644 --- a/spec/features/login_spec.rb +++ b/spec/features/login_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Login', feature: true do +feature 'Login' do describe 'initial login after setup' do it 'allows the initial admin to create a password' do # This behavior is dependent on there only being one user @@ -36,27 +36,27 @@ feature 'Login', feature: true do it 'prevents the user from logging in' do user = create(:user, :blocked) - login_with(user) + gitlab_sign_in(user) expect(page).to have_content('Your account has been blocked.') end - it 'does not update Devise trackable attributes', :redis do + it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do user = create(:user, :blocked) - expect { login_with(user) }.not_to change { user.reload.sign_in_count } + expect { gitlab_sign_in(user) }.not_to change { user.reload.sign_in_count } end end describe 'with the ghost user' do it 'disallows login' do - login_with(User.ghost) + gitlab_sign_in(User.ghost) expect(page).to have_content('Invalid Login or password.') end - it 'does not update Devise trackable attributes', :redis do - expect { login_with(User.ghost) }.not_to change { User.ghost.reload.sign_in_count } + it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do + expect { gitlab_sign_in(User.ghost) }.not_to change { User.ghost.reload.sign_in_count } end end @@ -70,7 +70,7 @@ feature 'Login', feature: true do let(:user) { create(:user, :two_factor) } before do - login_with(user, remember: true) + gitlab_sign_in(user, remember: true) expect(page).to have_content('Two-Factor Authentication') end @@ -122,8 +122,8 @@ feature 'Login', feature: true do end it 'invalidates the used code' do - expect { enter_code(codes.sample) }. - to change { user.reload.otp_backup_codes.size }.by(-1) + expect { enter_code(codes.sample) } + .to change { user.reload.otp_backup_codes.size }.by(-1) end end @@ -143,31 +143,10 @@ feature 'Login', feature: true do end context 'logging in via OAuth' do - def saml_config - OpenStruct.new(name: 'saml', label: 'saml', args: { - assertion_consumer_service_url: 'https://localhost:3443/users/auth/saml/callback', - idp_cert_fingerprint: '26:43:2C:47:AF:F0:6B:D0:07:9C:AD:A3:74:FE:5D:94:5F:4E:9E:52', - idp_sso_target_url: 'https://idp.example.com/sso/saml', - issuer: 'https://localhost:3443/', - name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' - }) - end - - def stub_omniauth_config(messages) - Rails.application.env_config['devise.mapping'] = Devise.mappings[:user] - Rails.application.routes.disable_clear_and_finalize = true - Rails.application.routes.draw do - post '/users/auth/saml' => 'omniauth_callbacks#saml' - end - allow(Gitlab::OAuth::Provider).to receive_messages(providers: [:saml], config_for: saml_config) - allow(Gitlab.config.omniauth).to receive_messages(messages) - expect_any_instance_of(Object).to receive(:omniauth_authorize_path).with(:user, "saml").and_return('/users/auth/saml') - end - it 'shows 2FA prompt after OAuth login' do - stub_omniauth_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [saml_config]) + stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config]) user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml') - login_via('saml', user, 'my-uid') + gitlab_sign_in_via('saml', user, 'my-uid') expect(page).to have_content('Two-Factor Authentication') enter_code(user.current_otp) @@ -180,19 +159,19 @@ feature 'Login', feature: true do let(:user) { create(:user) } it 'allows basic login' do - login_with(user) + gitlab_sign_in(user) expect(current_path).to eq root_path end it 'does not show a "You are already signed in." error message' do - login_with(user) + gitlab_sign_in(user) expect(page).not_to have_content('You are already signed in.') end it 'blocks invalid login' do user = create(:user, password: 'not-the-default') - login_with(user) + gitlab_sign_in(user) expect(page).to have_content('Invalid Login or password.') end end @@ -202,12 +181,14 @@ feature 'Login', feature: true do # TODO: otp_grace_period_started_at context 'global setting' do - before(:each) { stub_application_setting(require_two_factor_authentication: true) } + before do + stub_application_setting(require_two_factor_authentication: true) + end context 'with grace period defined' do - before(:each) do + before do stub_application_setting(two_factor_grace_period: 48) - login_with(user) + gitlab_sign_in(user) end context 'within the grace period' do @@ -242,9 +223,9 @@ feature 'Login', feature: true do end context 'without grace period defined' do - before(:each) do + before do stub_application_setting(two_factor_grace_period: 0) - login_with(user) + gitlab_sign_in(user) end it 'redirects to two-factor configuration page' do @@ -265,9 +246,9 @@ feature 'Login', feature: true do end context 'with grace period defined' do - before(:each) do + before do stub_application_setting(two_factor_grace_period: 48) - login_with(user) + gitlab_sign_in(user) end context 'within the grace period' do @@ -306,9 +287,9 @@ feature 'Login', feature: true do end context 'without grace period defined' do - before(:each) do + before do stub_application_setting(two_factor_grace_period: 0) - login_with(user) + gitlab_sign_in(user) end it 'redirects to two-factor configuration page' do diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index ba930de937d..b70d3060f05 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -24,7 +24,7 @@ require 'erb' # # See the MarkdownFeature class for setup details. -describe 'GitLab Markdown', feature: true do +describe 'GitLab Markdown' do include Capybara::Node::Matchers include MarkupHelper include MarkdownMatchers @@ -58,8 +58,8 @@ describe 'GitLab Markdown', feature: true do end it 'allows Markdown in tables' do - expect(doc.at_css('td:contains("Baz")').children.to_html). - to eq '<strong>Baz</strong>' + expect(doc.at_css('td:contains("Baz")').children.to_html) + .to eq '<strong>Baz</strong>' end it 'parses fenced code blocks' do @@ -100,7 +100,7 @@ describe 'GitLab Markdown', feature: true do end it 'permits img elements' do - expect(doc).to have_selector('img[src*="smile.png"]') + expect(doc).to have_selector('img[data-src*="smile.png"]') end it 'permits br elements' do @@ -158,14 +158,14 @@ describe 'GitLab Markdown', feature: true do describe 'Edge Cases' do it 'allows markup inside link elements' do aggregate_failures do - expect(doc.at_css('a[href="#link-emphasis"]').to_html). - to eq %{<a href="#link-emphasis"><em>text</em></a>} + expect(doc.at_css('a[href="#link-emphasis"]').to_html) + .to eq %{<a href="#link-emphasis"><em>text</em></a>} - expect(doc.at_css('a[href="#link-strong"]').to_html). - to eq %{<a href="#link-strong"><strong>text</strong></a>} + expect(doc.at_css('a[href="#link-strong"]').to_html) + .to eq %{<a href="#link-strong"><strong>text</strong></a>} - expect(doc.at_css('a[href="#link-code"]').to_html). - to eq %{<a href="#link-code"><code>text</code></a>} + expect(doc.at_css('a[href="#link-code"]').to_html) + .to eq %{<a href="#link-code"><code>text</code></a>} end end end diff --git a/spec/features/merge_requests/assign_issues_spec.rb b/spec/features/merge_requests/assign_issues_spec.rb index b306e2f5f75..63fa72650ac 100644 --- a/spec/features/merge_requests/assign_issues_spec.rb +++ b/spec/features/merge_requests/assign_issues_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' -feature 'Merge request issue assignment', js: true, feature: true do +feature 'Merge request issue assignment', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:issue1) { create(:issue, project: project) } let(:issue2) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, :simple, source_project: project, author: user, description: "fixes #{issue1.to_reference} and #{issue2.to_reference}") } @@ -13,8 +13,8 @@ feature 'Merge request issue assignment', js: true, feature: true do end def visit_merge_request(current_user = nil) - login_as(current_user || user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(current_user || user) + visit project_merge_request_path(project, merge_request) end context 'logged in as author' do diff --git a/spec/features/merge_requests/award_spec.rb b/spec/features/merge_requests/award_spec.rb index ac260e118d0..e886309133d 100644 --- a/spec/features/merge_requests/award_spec.rb +++ b/spec/features/merge_requests/award_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Merge request awards', js: true, feature: true do +feature 'Merge request awards', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } describe 'logged in' do before do - login_as(user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(user) + visit project_merge_request_path(project, merge_request) end it 'adds award to merge request' do @@ -16,7 +16,7 @@ feature 'Merge request awards', js: true, feature: true do expect(page).to have_selector('.js-emoji-btn.active') expect(first('.js-emoji-btn')).to have_content '1' - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(first('.js-emoji-btn')).to have_content '1' end @@ -25,7 +25,7 @@ feature 'Merge request awards', js: true, feature: true do find('.js-emoji-btn.active').click expect(first('.js-emoji-btn')).to have_content '0' - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(first('.js-emoji-btn')).to have_content '0' end @@ -39,7 +39,7 @@ feature 'Merge request awards', js: true, feature: true do describe 'logged out' do before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not see award menu button' do diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb index fa306c02a43..1f5e7b55fb0 100644 --- a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Check if mergeable with unresolved discussions', js: true, feature: true do +feature 'Check if mergeable with unresolved discussions', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } before do - login_as user + sign_in user project.team << [user, :master] end @@ -64,6 +64,6 @@ feature 'Check if mergeable with unresolved discussions', js: true, feature: tru end def visit_merge_request(merge_request) - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + visit project_merge_request_path(merge_request.project, merge_request) end end diff --git a/spec/features/merge_requests/cherry_pick_spec.rb b/spec/features/merge_requests/cherry_pick_spec.rb index 6ba681e36f7..4b1e1b9a8d4 100644 --- a/spec/features/merge_requests/cherry_pick_spec.rb +++ b/spec/features/merge_requests/cherry_pick_spec.rb @@ -3,11 +3,11 @@ require 'spec_helper' describe 'Cherry-pick Merge Requests', js: true do let(:user) { create(:user) } let(:group) { create(:group) } - let(:project) { create(:project, namespace: group) } + let(:project) { create(:project, :repository, namespace: group) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user) } before do - login_as user + sign_in user project.team << [user, :master] end @@ -28,7 +28,7 @@ describe 'Cherry-pick Merge Requests', js: true do end it "doesn't show a Cherry-pick button" do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(page).not_to have_link "Cherry-pick" end @@ -36,7 +36,7 @@ describe 'Cherry-pick Merge Requests', js: true do context "With a merge commit" do it "shows a Cherry-pick button" do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(page).to have_link "Cherry-pick" end diff --git a/spec/features/merge_requests/closes_issues_spec.rb b/spec/features/merge_requests/closes_issues_spec.rb index e627618042a..0e97254eada 100644 --- a/spec/features/merge_requests/closes_issues_spec.rb +++ b/spec/features/merge_requests/closes_issues_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Merge Request closing issues message', feature: true, js: true do +feature 'Merge Request closing issues message', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:issue_1) { create(:issue, project: project)} let(:issue_2) { create(:issue, project: project)} let(:merge_request) do @@ -20,9 +20,9 @@ feature 'Merge Request closing issues message', feature: true, js: true do before do project.team << [user, :master] - login_as user + sign_in user - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) wait_for_requests end diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 27e2d5d16f3..2c560632a1b 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -1,8 +1,13 @@ require 'spec_helper' -feature 'Merge request conflict resolution', js: true, feature: true do +feature 'Merge request conflict resolution', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } + + before do + # In order to have the diffs collapsed, we need to disable the increase feature + stub_feature_flags(gitlab_git_diff_size_limit_increase: false) + end def create_merge_request(source_branch) create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr| @@ -79,20 +84,24 @@ feature 'Merge request conflict resolution', js: true, feature: true do context 'can be resolved in the UI' do before do project.team << [user, :developer] - login_as(user) + sign_in(user) end context 'the conflicts are resolvable' do let(:merge_request) { create_merge_request('conflict-resolvable') } - before { visit namespace_project_merge_request_path(project.namespace, project, merge_request) } + before do + visit project_merge_request_path(project, merge_request) + end it 'shows a link to the conflict resolution page' do expect(page).to have_link('conflicts', href: /\/conflicts\Z/) end context 'in Inline view mode' do - before { click_link('conflicts', href: /\/conflicts\Z/) } + before do + click_link('conflicts', href: /\/conflicts\Z/) + end include_examples "conflicts are resolved in Interactive mode" include_examples "conflicts are resolved in Edit inline mode" @@ -113,7 +122,7 @@ feature 'Merge request conflict resolution', js: true, feature: true do let(:merge_request) { create_merge_request('conflict-contains-conflict-markers') } before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) click_link('conflicts', href: /\/conflicts\Z/) end @@ -160,9 +169,9 @@ feature 'Merge request conflict resolution', js: true, feature: true do before do project.team << [user, :developer] - login_as(user) + sign_in(user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not show a link to the conflict resolution page' do diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index 82987c768d1..d7f3d91e625 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' -feature 'Create New Merge Request', feature: true, js: true do +feature 'Create New Merge Request', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } before do project.team << [user, :master] - login_as user + sign_in user end it 'selects the source branch sha when a tag with the same name exists' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) click_link 'New merge request' expect(page).to have_content('Source branch') @@ -24,7 +24,7 @@ feature 'Create New Merge Request', feature: true, js: true do end it 'selects the target branch sha when a tag with the same name exists' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) click_link 'New merge request' @@ -38,7 +38,7 @@ feature 'Create New Merge Request', feature: true, js: true do end it 'generates a diff for an orphaned branch' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) page.has_link?('New Merge Request') ? click_link("New Merge Request") : click_link('New merge request') expect(page).to have_content('Source branch') @@ -63,34 +63,34 @@ feature 'Create New Merge Request', feature: true, js: true do context 'when target project cannot be viewed by the current user' do it 'does not leak the private project name & namespace' do - private_project = create(:project, :private) + private_project = create(:project, :private, :repository) - visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_project_id: private_project.id }) + visit project_new_merge_request_path(project, merge_request: { target_project_id: private_project.id }) - expect(page).not_to have_content private_project.path_with_namespace - expect(page).to have_content project.path_with_namespace + expect(page).not_to have_content private_project.full_path + expect(page).to have_content project.full_path end end context 'when source project cannot be viewed by the current user' do it 'does not leak the private project name & namespace' do - private_project = create(:project, :private) + private_project = create(:project, :private, :repository) - visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { source_project_id: private_project.id }) + visit project_new_merge_request_path(project, merge_request: { source_project_id: private_project.id }) - expect(page).not_to have_content private_project.path_with_namespace - expect(page).to have_content project.path_with_namespace + expect(page).not_to have_content private_project.full_path + expect(page).to have_content project.full_path end end it 'populates source branch button' do - visit new_namespace_project_merge_request_path(project.namespace, project, change_branches: true, merge_request: { target_branch: 'master', source_branch: 'fix' }) + visit project_new_merge_request_path(project, change_branches: true, merge_request: { target_branch: 'master', source_branch: 'fix' }) expect(find('.js-source-branch')).to have_content('fix') end it 'allows to change the diff view' do - visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'master', source_branch: 'fix' }) + visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: 'fix' }) click_link 'Changes' @@ -106,7 +106,7 @@ feature 'Create New Merge Request', feature: true, js: true do end it 'does not allow non-existing branches' do - visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'non-exist-target', source_branch: 'non-exist-source' }) + visit project_new_merge_request_path(project, merge_request: { target_branch: 'non-exist-target', source_branch: 'non-exist-source' }) expect(page).to have_content('The form contains the following errors') expect(page).to have_content('Source branch "non-exist-source" does not exist') @@ -115,7 +115,7 @@ feature 'Create New Merge Request', feature: true, js: true do context 'when a branch contains commits that both delete and add the same image' do it 'renders the diff successfully' do - visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'master', source_branch: 'deleted-image-test' }) + visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: 'deleted-image-test' }) click_link "Changes" @@ -125,7 +125,7 @@ feature 'Create New Merge Request', feature: true, js: true do # Isolates a regression (see #24627) it 'does not show error messages on initial form' do - visit new_namespace_project_merge_request_path(project.namespace, project) + visit project_new_merge_request_path(project) expect(page).not_to have_selector('#error_explanation') expect(page).not_to have_content('The form contains the following error') end @@ -138,8 +138,8 @@ feature 'Create New Merge Request', feature: true, js: true do end it 'shows pipelines for a new merge request' do - visit new_namespace_project_merge_request_path( - project.namespace, project, + visit project_new_merge_request_path( + project, merge_request: { target_branch: 'master', source_branch: 'fix' }) page.within('.merge-request') do diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb index bf34c99b92a..09541873f71 100644 --- a/spec/features/merge_requests/created_from_fork_spec.rb +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' feature 'Merge request created from fork' do given(:user) { create(:user) } - given(:project) { create(:project, :public) } - given(:fork_project) { create(:project, :public) } + given(:project) { create(:project, :public, :repository) } + given(:fork_project) { create(:project, :public, :repository) } given!(:merge_request) do create(:forked_project_link, forked_to_project: fork_project, @@ -16,7 +16,7 @@ feature 'Merge request created from fork' do background do fork_project.team << [user, :master] - login_as user + sign_in user end scenario 'user can access merge request' do @@ -25,6 +25,33 @@ feature 'Merge request created from fork' do expect(page).to have_content 'Test merge request' end + context 'when a commit comment exists on the merge request' do + given(:comment) { 'A commit comment' } + given(:reply) { 'A reply comment' } + + background do + create(:note_on_commit, note: comment, + project: fork_project, + commit_id: merge_request.commit_shas.first) + end + + scenario 'user can reply to the comment', js: true do + visit_merge_request(merge_request) + + expect(page).to have_content(comment) + + page.within('.discussion-notes') do + find('.btn-text-field').click + find('#note_note').send_keys(reply) + find('.comment-btn').click + end + + wait_for_requests + + expect(page).to have_content(reply) + end + end + context 'source project is deleted' do background do MergeRequests::MergeService.new(project, user).execute(merge_request) @@ -56,7 +83,7 @@ feature 'Merge request created from fork' do visit_merge_request(merge_request) page.within('.merge-request-tabs') { click_link 'Pipelines' } - page.within('table.ci-table') do + page.within('.ci-table') do expect(page).to have_content pipeline.status expect(page).to have_content pipeline.id end @@ -64,7 +91,6 @@ feature 'Merge request created from fork' do end def visit_merge_request(mr) - visit namespace_project_merge_request_path(project.namespace, - project, mr) + visit project_merge_request_path(project, mr) end end diff --git a/spec/features/merge_requests/deleted_source_branch_spec.rb b/spec/features/merge_requests/deleted_source_branch_spec.rb index 1723fb7d365..874c6e2ff69 100644 --- a/spec/features/merge_requests/deleted_source_branch_spec.rb +++ b/spec/features/merge_requests/deleted_source_branch_spec.rb @@ -3,19 +3,15 @@ require 'spec_helper' # This test serves as a regression test for a bug that caused an error # message to be shown by JavaScript when the source branch was deleted. # Please do not remove "js: true". -describe 'Deleted source branch', feature: true, js: true do +describe 'Deleted source branch', js: true do let(:user) { create(:user) } let(:merge_request) { create(:merge_request) } before do - login_as user + sign_in user merge_request.project.team << [user, :master] merge_request.update!(source_branch: 'this-branch-does-not-exist') - visit namespace_project_merge_request_path( - merge_request.project.namespace, - merge_request.project, - merge_request - ) + visit project_merge_request_path(merge_request.project, merge_request) end it 'shows a message about missing source branch' do diff --git a/spec/features/merge_requests/diff_notes_avatars_spec.rb b/spec/features/merge_requests/diff_notes_avatars_spec.rb index 854e2d1758f..2d9419d6124 100644 --- a/spec/features/merge_requests/diff_notes_avatars_spec.rb +++ b/spec/features/merge_requests/diff_notes_avatars_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' -feature 'Diff note avatars', feature: true, js: true do +feature 'Diff note avatars', js: true do + include NoteInteractionHelpers + let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } let(:path) { "files/ruby/popen.rb" } let(:position) do @@ -18,12 +20,12 @@ feature 'Diff note avatars', feature: true, js: true do before do project.team << [user, :master] - login_as user + sign_in user end context 'discussion tab' do before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not show avatars on discussion tab' do @@ -48,7 +50,7 @@ feature 'Diff note avatars', feature: true, js: true do context 'commit view' do before do - visit namespace_project_commit_path(project.namespace, project, merge_request.commits.first.id) + visit project_commit_path(project, merge_request.commits.first.id) end it 'does not render avatar after commenting' do @@ -63,7 +65,7 @@ feature 'Diff note avatars', feature: true, js: true do wait_for_requests end - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(page).to have_content('test comment') expect(page).not_to have_selector('.js-avatar-container') @@ -74,7 +76,7 @@ feature 'Diff note avatars', feature: true, js: true do %w(inline parallel).each do |view| context "#{view} view" do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: view) + visit diffs_project_merge_request_path(project, merge_request, view: view) wait_for_requests end @@ -110,6 +112,8 @@ feature 'Diff note avatars', feature: true, js: true do end it 'removes avatar when note is deleted' do + open_more_actions_dropdown(note) + page.within find(".note-row-#{note.id}") do find('.js-note-delete').click end @@ -164,7 +168,7 @@ feature 'Diff note avatars', feature: true, js: true do before do create_list(:diff_note_on_merge_request, 3, project: project, noteable: merge_request, in_reply_to: note) - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: view) + visit diffs_project_merge_request_path(project, merge_request, view: view) wait_for_requests end diff --git a/spec/features/merge_requests/diff_notes_resolve_spec.rb b/spec/features/merge_requests/diff_notes_resolve_spec.rb index 4d549f3bdbb..ac7f75bd308 100644 --- a/spec/features/merge_requests/diff_notes_resolve_spec.rb +++ b/spec/features/merge_requests/diff_notes_resolve_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Diff notes resolve', feature: true, js: true do +feature 'Diff notes resolve', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request) } let(:path) { "files/ruby/popen.rb" } @@ -19,7 +19,7 @@ feature 'Diff notes resolve', feature: true, js: true do context 'no discussions' do before do project.team << [user, :master] - login_as user + sign_in user note.destroy visit_merge_request end @@ -33,7 +33,7 @@ feature 'Diff notes resolve', feature: true, js: true do context 'as authorized user' do before do project.team << [user, :master] - login_as user + sign_in user visit_merge_request end @@ -402,7 +402,7 @@ feature 'Diff notes resolve', feature: true, js: true do before do project.team << [guest, :guest] - login_as guest + sign_in guest end context 'someone elses merge request' do @@ -494,6 +494,6 @@ feature 'Diff notes resolve', feature: true, js: true do def visit_merge_request(mr = nil) mr = mr || merge_request - visit namespace_project_merge_request_path(mr.project.namespace, mr.project, mr) + visit project_merge_request_path(mr.project, mr) end end diff --git a/spec/features/merge_requests/diffs_spec.rb b/spec/features/merge_requests/diffs_spec.rb index 44013df3ea0..201be4b9e40 100644 --- a/spec/features/merge_requests/diffs_spec.rb +++ b/spec/features/merge_requests/diffs_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -feature 'Diffs URL', js: true, feature: true do - let(:project) { create(:project, :public) } +feature 'Diffs URL', js: true do + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } context 'when visit with */* as accept header' do @@ -12,7 +12,7 @@ feature 'Diffs URL', js: true, feature: true do it 'renders the notes' do create :note_on_merge_request, project: project, noteable: merge_request, note: 'Rebasing with master' - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) # Load notes and diff through AJAX expect(page).to have_css('.note-text', visible: false, text: 'Rebasing with master') @@ -26,7 +26,7 @@ feature 'Diffs URL', js: true, feature: true do let(:fragment) { "#note_#{note.id}" } before do - visit "#{diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)}#{fragment}" + visit "#{diffs_project_merge_request_path(project, merge_request)}#{fragment}" end it 'shows expanded note' do @@ -39,7 +39,7 @@ feature 'Diffs URL', js: true, feature: true do let(:fragment) { "#note_#{note.id}" } before do - visit "#{diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)}#{fragment}" + visit "#{diffs_project_merge_request_path(project, merge_request)}#{fragment}" end it 'shows expanded note' do @@ -52,7 +52,7 @@ feature 'Diffs URL', js: true, feature: true do it 'displays warning' do allow(Commit).to receive(:max_diff_options).and_return(max_files: 3) - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) page.within('.alert') do expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve @@ -74,9 +74,8 @@ feature 'Diffs URL', js: true, feature: true do context 'as author' do it 'shows direct edit link' do - login_as(author_user) - - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(author_user) + visit diffs_project_merge_request_path(project, merge_request) # Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax expect(page).to have_selector("[id=\"#{changelog_id}\"] a.js-edit-blob") @@ -85,9 +84,8 @@ feature 'Diffs URL', js: true, feature: true do context 'as user who needs to fork' do it 'shows fork/cancel confirmation' do - login_as(user) - - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(user) + visit diffs_project_merge_request_path(project, merge_request) # Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax find("[id=\"#{changelog_id}\"] .js-edit-blob").click diff --git a/spec/features/merge_requests/discussion_spec.rb b/spec/features/merge_requests/discussion_spec.rb index 9db235f35ba..d1cc43e0690 100644 --- a/spec/features/merge_requests/discussion_spec.rb +++ b/spec/features/merge_requests/discussion_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Merge Request Discussions', feature: true do +feature 'Merge Request Discussions' do before do - login_as :admin + sign_in(create(:admin)) end describe "Diff discussions" do @@ -27,13 +27,13 @@ feature 'Merge Request Discussions', feature: true do let(:outdated_diff_refs) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e").diff_refs } before(:each) do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end context 'active discussions' do it 'shows a link to the diff' do within(".discussion[data-discussion-id='#{active_discussion.id}']") do - path = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, anchor: active_discussion.line_code) + path = diffs_project_merge_request_path(project, merge_request, anchor: active_discussion.line_code) expect(page).to have_link('the diff', href: path) end end @@ -42,7 +42,7 @@ feature 'Merge Request Discussions', feature: true do context 'outdated discussions' do it 'shows a link to the outdated diff' do within(".discussion[data-discussion-id='#{outdated_discussion.id}']") do - path = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, diff_id: old_merge_request_diff.id, anchor: outdated_discussion.line_code) + path = diffs_project_merge_request_path(project, merge_request, diff_id: old_merge_request_diff.id, anchor: outdated_discussion.line_code) expect(page).to have_link('an old version of the diff', href: path) end end @@ -72,7 +72,7 @@ feature 'Merge Request Discussions', feature: true do end before(:each) do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end context 'a regular commit comment' do diff --git a/spec/features/merge_requests/edit_mr_spec.rb b/spec/features/merge_requests/edit_mr_spec.rb index c77a5c68bc6..7386e78fb13 100644 --- a/spec/features/merge_requests/edit_mr_spec.rb +++ b/spec/features/merge_requests/edit_mr_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -feature 'Edit Merge Request', feature: true do +feature 'Edit Merge Request' do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, :simple, source_project: project) } before do project.team << [user, :master] - login_as user + sign_in user - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit edit_project_merge_request_path(project, merge_request) end context 'editing a MR' do @@ -33,7 +33,7 @@ feature 'Edit Merge Request', feature: true do merge_request.update(merge_params: { 'force_remove_source_branch' => '1' }) expect(merge_request.merge_params['force_remove_source_branch']).to be_truthy - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit edit_project_merge_request_path(project, merge_request) uncheck 'Remove source branch when merge request is accepted' click_button 'Save changes' diff --git a/spec/features/merge_requests/filter_by_labels_spec.rb b/spec/features/merge_requests/filter_by_labels_spec.rb index 32a9082b9b9..1d52a4659ad 100644 --- a/spec/features/merge_requests/filter_by_labels_spec.rb +++ b/spec/features/merge_requests/filter_by_labels_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Issue filtering by Labels', feature: true, js: true do +feature 'Merge Request filtering by Labels', js: true do include FilteredSearchHelpers include MergeRequestHelpers - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let!(:user) { create(:user) } let!(:label) { create(:label, project: project) } @@ -26,9 +26,9 @@ feature 'Issue filtering by Labels', feature: true, js: true do mr3.labels << feature project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end context 'filter by label bug' do diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb index 265a0cfc198..521fcabc881 100644 --- a/spec/features/merge_requests/filter_by_milestone_spec.rb +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Merge Request filtering by Milestone', feature: true do +feature 'Merge Request filtering by Milestone' do include FilteredSearchHelpers include MergeRequestHelpers - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let!(:user) { create(:user)} let(:milestone) { create(:milestone, project: project) } @@ -15,7 +15,7 @@ feature 'Merge Request filtering by Milestone', feature: true do before do project.team << [user, :master] - login_as(user) + sign_in(user) end scenario 'filters by no Milestone', js: true do diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb index 1e26b3d601e..f0019be86ad 100644 --- a/spec/features/merge_requests/filter_merge_requests_spec.rb +++ b/spec/features/merge_requests/filter_merge_requests_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -describe 'Filter merge requests', feature: true do +describe 'Filter merge requests' do include FilteredSearchHelpers include MergeRequestHelpers - let!(:project) { create(:project) } + let!(:project) { create(:project, :repository) } let!(:group) { create(:group) } let!(:user) { create(:user) } let!(:milestone) { create(:milestone, project: project) } @@ -14,10 +14,10 @@ describe 'Filter merge requests', feature: true do before do project.team << [user, :master] group.add_developer(user) - login_as(user) + sign_in(user) create(:merge_request, source_project: project, target_project: project) - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end describe 'for assignee from mr#index' do @@ -40,13 +40,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters [data-state="closed"]').click expect_assignee_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters [data-state="all"]').click expect_assignee_visual_tokens() end @@ -73,13 +73,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters [data-state="closed"]').click expect_milestone_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters [data-state="all"]').click expect_milestone_visual_tokens() end @@ -132,21 +132,13 @@ describe 'Filter merge requests', feature: true do end end - describe 'for assignee and label from issues#index' do + describe 'for assignee and label from mr#index' do let(:search_query) { "assignee:@#{user.username} label:~#{label.title}" } before do - input_filtered_search("assignee:@#{user.username}") - - expect_mr_list_count(1) - expect_tokens([{ name: 'assignee', value: "@#{user.username}" }]) - expect_filtered_search_input_empty - - input_filtered_search_keys("label:~#{label.title} ") - - expect_mr_list_count(1) + input_filtered_search(search_query) - find("#state-opened[href=\"#{URI.parse(current_url).path}?assignee_username=#{user.username}&label_name%5B%5D=#{label.title}&scope=all&state=opened\"]") + expect_mr_list_count(0) end context 'assignee and label', js: true do @@ -163,13 +155,13 @@ describe 'Filter merge requests', feature: true do end it 'does not change when closed link is clicked' do - find('.issues-state-filters a', text: "Closed").click + find('.issues-state-filters [data-state="closed"]').click expect_assignee_label_visual_tokens() end it 'does not change when all link is clicked' do - find('.issues-state-filters a', text: "All").click + find('.issues-state-filters [data-state="all"]').click expect_assignee_label_visual_tokens() end @@ -193,7 +185,7 @@ describe 'Filter merge requests', feature: true do assignee: user) mr.labels << bug_label - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end context 'only text', js: true do @@ -277,7 +269,7 @@ describe 'Filter merge requests', feature: true do mr1.labels << bug_label mr2.labels << bug_label - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it 'is able to filter and sort merge requests' do @@ -299,7 +291,7 @@ describe 'Filter merge requests', feature: true do describe 'filter by assignee id', js: true do it 'filter by current user' do - visit namespace_project_merge_requests_path(project.namespace, project, assignee_id: user.id) + visit project_merge_requests_path(project, assignee_id: user.id) expect_tokens([{ name: 'assignee', value: "@#{user.username}" }]) expect_filtered_search_input_empty @@ -309,7 +301,7 @@ describe 'Filter merge requests', feature: true do new_user = create(:user) project.add_developer(new_user) - visit namespace_project_merge_requests_path(project.namespace, project, assignee_id: new_user.id) + visit project_merge_requests_path(project, assignee_id: new_user.id) expect_tokens([{ name: 'assignee', value: "@#{new_user.username}" }]) expect_filtered_search_input_empty @@ -318,7 +310,7 @@ describe 'Filter merge requests', feature: true do describe 'filter by author id', js: true do it 'filter by current user' do - visit namespace_project_merge_requests_path(project.namespace, project, author_id: user.id) + visit project_merge_requests_path(project, author_id: user.id) expect_tokens([{ name: 'author', value: "@#{user.username}" }]) expect_filtered_search_input_empty @@ -328,7 +320,7 @@ describe 'Filter merge requests', feature: true do new_user = create(:user) project.add_developer(new_user) - visit namespace_project_merge_requests_path(project.namespace, project, author_id: new_user.id) + visit project_merge_requests_path(project, author_id: new_user.id) expect_tokens([{ name: 'author', value: "@#{new_user.username}" }]) expect_filtered_search_input_empty diff --git a/spec/features/merge_requests/form_spec.rb b/spec/features/merge_requests/form_spec.rb index 00ef1ffdddc..6ffb05c5030 100644 --- a/spec/features/merge_requests/form_spec.rb +++ b/spec/features/merge_requests/form_spec.rb @@ -1,15 +1,13 @@ require 'rails_helper' -describe 'New/edit merge request', feature: true, js: true do - include GitlabRoutingHelper - - let!(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:fork_project) { create(:project, forked_from_project: project) } - let!(:user) { create(:user)} - let!(:user2) { create(:user)} - let!(:milestone) { create(:milestone, project: project) } - let!(:label) { create(:label, project: project) } - let!(:label2) { create(:label, project: project) } +describe 'New/edit merge request', :js do + let!(:project) { create(:project, :public, :repository) } + let(:fork_project) { create(:project, :repository, forked_from_project: project) } + let!(:user) { create(:user) } + let!(:user2) { create(:user) } + let!(:milestone) { create(:milestone, project: project) } + let!(:label) { create(:label, project: project) } + let!(:label2) { create(:label, project: project) } before do project.team << [user, :master] @@ -18,13 +16,12 @@ describe 'New/edit merge request', feature: true, js: true do context 'owned projects' do before do - login_as(user) + sign_in(user) end context 'new merge request' do before do - visit new_namespace_project_merge_request_path( - project.namespace, + visit project_new_merge_request_path( project, merge_request: { source_project_id: project.id, @@ -96,6 +93,13 @@ describe 'New/edit merge request', feature: true, js: true do .to end_with(merge_request_path(merge_request)) end end + + it 'description has autocomplete' do + find('#merge_request_description').native.send_keys('') + fill_in 'merge_request_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end end context 'edit merge request' do @@ -107,7 +111,7 @@ describe 'New/edit merge request', feature: true, js: true do target_branch: 'master' ) - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit edit_project_merge_request_path(project, merge_request) end it 'updates merge request' do @@ -157,19 +161,25 @@ describe 'New/edit merge request', feature: true, js: true do end end end + + it 'description has autocomplete' do + find('#merge_request_description').native.send_keys('') + fill_in 'merge_request_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end end end context 'forked project' do before do fork_project.team << [user, :master] - login_as(user) + sign_in(user) end context 'new merge request' do before do - visit new_namespace_project_merge_request_path( - fork_project.namespace, + visit project_new_merge_request_path( fork_project, merge_request: { source_project_id: fork_project.id, @@ -237,7 +247,7 @@ describe 'New/edit merge request', feature: true, js: true do target_branch: 'master' ) - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit edit_project_merge_request_path(project, merge_request) end it 'should update merge request' do diff --git a/spec/features/merge_requests/merge_commit_message_toggle_spec.rb b/spec/features/merge_requests/merge_commit_message_toggle_spec.rb index 221ddb5873c..429bc277d73 100644 --- a/spec/features/merge_requests/merge_commit_message_toggle_spec.rb +++ b/spec/features/merge_requests/merge_commit_message_toggle_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Clicking toggle commit message link', feature: true, js: true do +feature 'Clicking toggle commit message link', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:issue_1) { create(:issue, project: project)} let(:issue_2) { create(:issue, project: project)} let(:merge_request) do @@ -34,9 +34,9 @@ feature 'Clicking toggle commit message link', feature: true, js: true do before do project.team << [user, :master] - login_as user + sign_in user - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) expect(page).not_to have_selector('.js-commit-message') click_button "Modify commit message" diff --git a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb index c1d4d508e57..0b5a595acce 100644 --- a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb +++ b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Merge immediately', :feature, :js do +feature 'Merge immediately', :js do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let!(:merge_request) do create(:merge_request_with_diffs, source_project: project, @@ -18,7 +18,9 @@ feature 'Merge immediately', :feature, :js do sha: project.repository.commit('master').id) end - before { project.team << [user, :master] } + before do + project.team << [user, :master] + end context 'when there is active pipeline for merge request' do background do @@ -26,8 +28,8 @@ feature 'Merge immediately', :feature, :js do end before do - login_as user - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + sign_in user + visit project_merge_request_path(merge_request.project, merge_request) end it 'enables merge immediately' do diff --git a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb index 09f889d4dd6..574f5fe353e 100644 --- a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Merge When Pipeline Succeeds', :feature, :js do +feature 'Merge When Pipeline Succeeds', :js do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) do create(:merge_request_with_diffs, source_project: project, @@ -28,7 +28,7 @@ feature 'Merge When Pipeline Succeeds', :feature, :js do end before do - login_as user + sign_in user visit_merge_request(merge_request) end @@ -121,7 +121,7 @@ feature 'Merge When Pipeline Succeeds', :feature, :js do end before do - login_as user + sign_in user visit_merge_request(merge_request) end @@ -155,6 +155,6 @@ feature 'Merge When Pipeline Succeeds', :feature, :js do end def visit_merge_request(merge_request) - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + visit project_merge_request_path(merge_request.project, merge_request) end end diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index 3ceb91d951d..b1215f9ba63 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' -feature 'Mini Pipeline Graph', :js, :feature do +feature 'Mini Pipeline Graph', :js do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, head_pipeline: pipeline) } let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) } @@ -11,14 +11,40 @@ feature 'Mini Pipeline Graph', :js, :feature do before do build.run - login_as(user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(user) + visit_merge_request + end + + def visit_merge_request(format = :html) + visit project_merge_request_path(project, merge_request, format: format) end it 'should display a mini pipeline graph' do expect(page).to have_selector('.mr-widget-pipeline-graph') end + context 'as json' do + let(:artifacts_file1) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + let(:artifacts_file2) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') } + + before do + create(:ci_build, pipeline: pipeline, artifacts_file: artifacts_file1) + create(:ci_build, pipeline: pipeline, when: 'manual') + end + + it 'avoids repeated database queries' do + before = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) } + + create(:ci_build, pipeline: pipeline, artifacts_file: artifacts_file2) + create(:ci_build, pipeline: pipeline, when: 'manual') + + after = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) } + + expect(before.count).to eq(after.count) + expect(before.cached_count).to eq(after.cached_count) + end + end + describe 'build list toggle' do let(:toggle) do find('.mini-pipeline-graph-dropdown-toggle') @@ -85,7 +111,7 @@ feature 'Mini Pipeline Graph', :js, :feature do build_item.click find('.build-page') - expect(current_path).to eql(namespace_project_job_path(project.namespace, project, build)) + expect(current_path).to eql(project_job_path(project, build)) end it 'should show tooltip when hovered' do diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb index b1dc81a606a..5c6eec44ff7 100644 --- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb +++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Only allow merge requests to be merged if the pipeline succeeds', feature: true, js: true do +feature 'Only allow merge requests to be merged if the pipeline succeeds', js: true do let(:merge_request) { create(:merge_request_with_diffs) } let(:project) { merge_request.target_project } before do - login_as merge_request.author + sign_in merge_request.author project.team << [merge_request.author, :master] end @@ -145,6 +145,6 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', featu end def visit_merge_request(merge_request) - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + visit project_merge_request_path(merge_request.project, merge_request) end end diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index 4c76004cb93..b3d6cf8deb4 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Pipelines for Merge Requests', feature: true, js: true do +feature 'Pipelines for Merge Requests', js: true do given(:user) { create(:user) } given(:merge_request) { create(:merge_request) } given(:project) { merge_request.target_project } before do project.team << [user, :master] - login_as user + sign_in user end context 'with pipelines' do @@ -19,7 +19,7 @@ feature 'Pipelines for Merge Requests', feature: true, js: true do end before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end scenario 'user visits merge request pipelines tab' do @@ -28,13 +28,13 @@ feature 'Pipelines for Merge Requests', feature: true, js: true do end wait_for_requests - expect(page).to have_selector('.pipeline-actions') + expect(page).to have_selector('.stage-cell') end end context 'without pipelines' do before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end scenario 'user visits merge request page' do diff --git a/spec/features/merge_requests/reset_filters_spec.rb b/spec/features/merge_requests/reset_filters_spec.rb index 275f81f50dc..c1b90e5f875 100644 --- a/spec/features/merge_requests/reset_filters_spec.rb +++ b/spec/features/merge_requests/reset_filters_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'Merge requests filter clear button', feature: true, js: true do +feature 'Merge requests filter clear button', js: true do include FilteredSearchHelpers include MergeRequestHelpers include IssueHelpers - let!(:project) { create(:project, :public) } + let!(:project) { create(:project, :public, :repository) } let!(:user) { create(:user) } let!(:milestone) { create(:milestone, project: project) } let!(:bug) { create(:label, project: project, name: 'bug')} diff --git a/spec/features/merge_requests/target_branch_spec.rb b/spec/features/merge_requests/target_branch_spec.rb index c154cf8ade9..9bbf2610bcb 100644 --- a/spec/features/merge_requests/target_branch_spec.rb +++ b/spec/features/merge_requests/target_branch_spec.rb @@ -1,19 +1,16 @@ require 'spec_helper' -describe 'Target branch', feature: true, js: true do +describe 'Target branch', js: true do let(:user) { create(:user) } let(:merge_request) { create(:merge_request) } let(:project) { merge_request.project } def path_to_merge_request - namespace_project_merge_request_path( - project.namespace, - project, merge_request - ) + project_merge_request_path(project, merge_request) end before do - login_as user + sign_in user project.team << [user, :master] end diff --git a/spec/features/merge_requests/toggle_whitespace_changes_spec.rb b/spec/features/merge_requests/toggle_whitespace_changes_spec.rb index 0f98737b700..dd989fd49b2 100644 --- a/spec/features/merge_requests/toggle_whitespace_changes_spec.rb +++ b/spec/features/merge_requests/toggle_whitespace_changes_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Toggle Whitespace Changes', js: true, feature: true do +feature 'Toggle Whitespace Changes', js: true do before do - login_as :admin + sign_in(create(:admin)) merge_request = create(:merge_request) project = merge_request.source_project - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) end it 'has a button to toggle whitespace changes' do diff --git a/spec/features/merge_requests/toggler_behavior_spec.rb b/spec/features/merge_requests/toggler_behavior_spec.rb index 3acd3f6a8b3..4e5ec9fbd2d 100644 --- a/spec/features/merge_requests/toggler_behavior_spec.rb +++ b/spec/features/merge_requests/toggler_behavior_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' -feature 'toggler_behavior', js: true, feature: true do +feature 'toggler_behavior', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project, author: user) } let(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project) } let(:fragment_id) { "#note_#{note.id}" } before do - login_as :admin + sign_in(create(:admin)) project = merge_request.source_project page.current_window.resize_to(1000, 300) - visit "#{namespace_project_merge_request_path(project.namespace, project, merge_request)}#{fragment_id}" + visit "#{project_merge_request_path(project, merge_request)}#{fragment_id}" end describe 'scroll position' do diff --git a/spec/features/merge_requests/update_merge_requests_spec.rb b/spec/features/merge_requests/update_merge_requests_spec.rb index bcdfdf78a44..cf30a687df8 100644 --- a/spec/features/merge_requests/update_merge_requests_spec.rb +++ b/spec/features/merge_requests/update_merge_requests_spec.rb @@ -1,19 +1,19 @@ require 'rails_helper' -feature 'Multiple merge requests updating from merge_requests#index', feature: true do +feature 'Multiple merge requests updating from merge_requests#index' do let!(:user) { create(:user)} - let!(:project) { create(:project) } + let!(:project) { create(:project, :repository) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'status', js: true do describe 'close merge request' do before do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it 'closes merge request' do @@ -26,7 +26,7 @@ feature 'Multiple merge requests updating from merge_requests#index', feature: t describe 'reopen merge request' do before do merge_request.close - visit namespace_project_merge_requests_path(project.namespace, project, state: 'closed') + visit project_merge_requests_path(project, state: 'closed') end it 'reopens merge request' do @@ -40,7 +40,7 @@ feature 'Multiple merge requests updating from merge_requests#index', feature: t context 'assignee', js: true do describe 'set assignee' do before do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it "updates merge request with assignee" do @@ -56,7 +56,7 @@ feature 'Multiple merge requests updating from merge_requests#index', feature: t before do merge_request.assignee = user merge_request.save - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it "removes assignee from the merge request" do @@ -72,7 +72,7 @@ feature 'Multiple merge requests updating from merge_requests#index', feature: t describe 'set milestone' do before do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it "updates merge request with milestone" do @@ -86,7 +86,7 @@ feature 'Multiple merge requests updating from merge_requests#index', feature: t before do merge_request.milestone = milestone merge_request.save - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it "removes milestone from the merge request" do diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb index cabb8e455f9..d62b035b40b 100644 --- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'Projects > Merge requests > User lists merge requests', feature: true do +describe 'Projects > Merge requests > User lists merge requests' do include MergeRequestHelpers include SortingHelper - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:user) { create(:user) } before do @@ -37,7 +37,7 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true it 'filters on no assignee' do visit_merge_requests(project, assignee_id: IssuableFinder::NONE) - expect(current_path).to eq(namespace_project_merge_requests_path(project.namespace, project)) + expect(current_path).to eq(project_merge_requests_path(project)) expect(page).to have_content 'merge_lfs' expect(page).not_to have_content 'fix' expect(page).not_to have_content 'markdown' @@ -136,7 +136,7 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true end it 'sorts by recently due milestone' do - visit namespace_project_merge_requests_path(project.namespace, project, + visit project_merge_requests_path(project, label_name: [label.name, label2.name], assignee_id: user.id, sort: sort_value_milestone_soon) diff --git a/spec/features/merge_requests/user_posts_diff_notes_spec.rb b/spec/features/merge_requests/user_posts_diff_notes_spec.rb index 14bc549c9f9..1cfd78663e5 100644 --- a/spec/features/merge_requests/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_requests/user_posts_diff_notes_spec.rb @@ -7,7 +7,7 @@ feature 'Merge requests > User posts diff notes', :js do before do project.add_developer(user) - login_as(user) + sign_in(user) end let(:comment_button_class) { '.add-diff-note' } @@ -17,7 +17,7 @@ feature 'Merge requests > User posts diff notes', :js do context 'when hovering over a parallel view diff file' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'parallel') + visit diffs_project_merge_request_path(project, merge_request, view: 'parallel') end context 'with an old line on the left and no line on the right' do @@ -92,7 +92,7 @@ feature 'Merge requests > User posts diff notes', :js do context 'when hovering over an inline view diff file' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'inline') + visit diffs_project_merge_request_path(project, merge_request, view: 'inline') end context 'with a new line' do @@ -136,9 +136,9 @@ feature 'Merge requests > User posts diff notes', :js do context 'when hovering over a diff discussion' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'inline') + visit diffs_project_merge_request_path(project, merge_request, view: 'inline') should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]')) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'does not allow commenting' do @@ -149,7 +149,7 @@ feature 'Merge requests > User posts diff notes', :js do context 'when cancelling the comment addition' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'inline') + visit diffs_project_merge_request_path(project, merge_request, view: 'inline') end context 'with a new line' do @@ -161,7 +161,7 @@ feature 'Merge requests > User posts diff notes', :js do describe 'with muliple note forms' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'inline') + visit diffs_project_merge_request_path(project, merge_request, view: 'inline') click_diff_line(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]')) click_diff_line(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]')) end @@ -181,7 +181,7 @@ feature 'Merge requests > User posts diff notes', :js do context 'when the MR only supports legacy diff notes' do before do merge_request.merge_request_diff.update_attributes(start_commit_sha: nil) - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, view: 'inline') + visit diffs_project_merge_request_path(project, merge_request, view: 'inline') end context 'with a new line' do diff --git a/spec/features/merge_requests/user_posts_notes_spec.rb b/spec/features/merge_requests/user_posts_notes_spec.rb index 06de072257a..74d21822a59 100644 --- a/spec/features/merge_requests/user_posts_notes_spec.rb +++ b/spec/features/merge_requests/user_posts_notes_spec.rb @@ -1,7 +1,9 @@ require 'spec_helper' describe 'Merge requests > User posts notes', :js do - let(:project) { create(:project) } + include NoteInteractionHelpers + + let(:project) { create(:project, :repository) } let(:merge_request) do create(:merge_request, source_project: project, target_project: project) end @@ -11,8 +13,8 @@ describe 'Merge requests > User posts notes', :js do end before do - login_as :admin - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(create(:admin)) + visit project_merge_request_path(project, merge_request) end subject { page } @@ -20,8 +22,8 @@ describe 'Merge requests > User posts notes', :js do describe 'the note form' do it 'is valid' do is_expected.to have_css('.js-main-target-form', visible: true, count: 1) - expect(find('.js-main-target-form .js-comment-button').value). - to eq('Comment') + expect(find('.js-main-target-form .js-comment-button').value) + .to eq('Comment') page.within('.js-main-target-form') do expect(page).not_to have_link('Cancel') end @@ -73,6 +75,8 @@ describe 'Merge requests > User posts notes', :js do describe 'editing the note' do before do find('.note').hover + open_more_actions_dropdown(note) + find('.js-note-edit').click end @@ -100,6 +104,8 @@ describe 'Merge requests > User posts notes', :js do wait_for_requests find('.note').hover + open_more_actions_dropdown(note) + find('.js-note-edit').click page.within('.current-note-edit-form') do @@ -117,8 +123,8 @@ describe 'Merge requests > User posts notes', :js do page.within("#note_#{note.id}") do is_expected.to have_css('.note_edited_ago') - expect(find('.note_edited_ago').text). - to match(/less than a minute ago/) + expect(find('.note_edited_ago').text) + .to match(/less than a minute ago/) end end end @@ -126,6 +132,8 @@ describe 'Merge requests > User posts notes', :js do describe 'deleting an attachment' do before do find('.note').hover + open_more_actions_dropdown(note) + find('.js-note-edit').click end diff --git a/spec/features/merge_requests/user_sees_system_notes_spec.rb b/spec/features/merge_requests/user_sees_system_notes_spec.rb index 55d0f9d728c..03dc61c2efa 100644 --- a/spec/features/merge_requests/user_sees_system_notes_spec.rb +++ b/spec/features/merge_requests/user_sees_system_notes_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' feature 'Merge requests > User sees system notes' do - let(:public_project) { create(:project, :public) } - let(:private_project) { create(:project, :private) } + let(:public_project) { create(:project, :public, :repository) } + let(:private_project) { create(:project, :private, :repository) } let(:issue) { create(:issue, project: private_project) } let(:merge_request) { create(:merge_request, source_project: public_project, source_branch: 'markdown') } let!(:note) { create(:note_on_merge_request, :system, noteable: merge_request, project: public_project, note: "mentioned in #{issue.to_reference(public_project)}") } @@ -11,11 +11,11 @@ feature 'Merge requests > User sees system notes' do before do user = create(:user) private_project.add_developer(user) - login_as(user) + sign_in(user) end it 'shows the system note' do - visit namespace_project_merge_request_path(public_project.namespace, public_project, merge_request) + visit project_merge_request_path(public_project, merge_request) expect(page).to have_css('.system-note') end @@ -23,7 +23,7 @@ feature 'Merge requests > User sees system notes' do context 'when not logged-in' do it 'hides the system note' do - visit namespace_project_merge_request_path(public_project.namespace, public_project, merge_request) + visit project_merge_request_path(public_project, merge_request) expect(page).not_to have_css('.system-note') end diff --git a/spec/features/merge_requests/user_uses_slash_commands_spec.rb b/spec/features/merge_requests/user_uses_slash_commands_spec.rb index 0e64a3e1a4b..43cab65d287 100644 --- a/spec/features/merge_requests/user_uses_slash_commands_spec.rb +++ b/spec/features/merge_requests/user_uses_slash_commands_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Merge Requests > User uses slash commands', feature: true, js: true do - include SlashCommandsHelpers +feature 'Merge Requests > User uses quick actions', js: true do + include QuickActionsHelpers let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } - it_behaves_like 'issuable record that supports slash commands in its description and notes', :merge_request do + it_behaves_like 'issuable record that supports quick actions in its description and notes', :merge_request do let(:issuable) { create(:merge_request, source_project: project) } let(:new_url_opts) { { merge_request: { source_branch: 'feature', target_branch: 'master' } } } end @@ -16,14 +16,22 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do describe 'merge-request-only commands' do before do project.team << [user, :master] - login_with(user) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(user) + visit project_merge_request_path(project, merge_request) end after do wait_for_requests end + describe 'time tracking' do + before do + visit project_merge_request_path(project, merge_request) + end + + it_behaves_like 'issuable time tracker' + end + describe 'toggling the WIP prefix in the title from note' do context 'when the current user can toggle the WIP prefix' do it 'adds the WIP: prefix to the title' do @@ -51,9 +59,9 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do let(:guest) { create(:user) } before do project.team << [guest, :guest] - logout - login_with(guest) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_out(:user) + sign_in(guest) + visit project_merge_request_path(project, merge_request) end it 'does not change the WIP prefix' do @@ -97,9 +105,9 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do let(:guest) { create(:user) } before do project.team << [guest, :guest] - logout - login_with(guest) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_out(:user) + sign_in(guest) + visit project_merge_request_path(project, merge_request) end it 'does not merge the MR' do @@ -121,17 +129,17 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do end describe '/target_branch command in merge request' do - let(:another_project) { create(:project, :public) } + let(:another_project) { create(:project, :public, :repository) } let(:new_url_opts) { { merge_request: { source_branch: 'feature' } } } before do - logout + sign_out(:user) another_project.team << [user, :master] - login_with(user) + sign_in(user) end it 'changes target_branch in new merge_request' do - visit new_namespace_project_merge_request_path(another_project.namespace, another_project, new_url_opts) + visit project_new_merge_request_path(another_project, new_url_opts) fill_in "merge_request_title", with: 'My brand new feature' fill_in "merge_request_description", with: "le feature \n/target_branch fix\nFeature description:" @@ -145,7 +153,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do it 'does not change target branch when merge request is edited' do new_merge_request = create(:merge_request, source_project: another_project) - visit edit_namespace_project_merge_request_path(another_project.namespace, another_project, new_merge_request) + visit edit_project_merge_request_path(another_project, new_merge_request) fill_in "merge_request_description", with: "Want to update target branch\n/target_branch fix\n" click_button "Save changes" @@ -181,9 +189,9 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do let(:guest) { create(:user) } before do project.team << [guest, :guest] - logout - login_with(guest) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_out(:user) + sign_in(guest) + visit project_merge_request_path(project, merge_request) end it 'does not change target branch' do diff --git a/spec/features/merge_requests/versions_spec.rb b/spec/features/merge_requests/versions_spec.rb index aad522ee26e..8e231fbc281 100644 --- a/spec/features/merge_requests/versions_spec.rb +++ b/spec/features/merge_requests/versions_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Merge Request versions', js: true, feature: true do +feature 'Merge Request versions', js: true do let(:merge_request) { create(:merge_request, importing: true) } let(:project) { merge_request.source_project } let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } @@ -8,8 +8,8 @@ feature 'Merge Request versions', js: true, feature: true do let!(:merge_request_diff3) { merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') } before do - login_as :admin - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + sign_in(create(:admin)) + visit diffs_project_merge_request_path(project, merge_request) end it 'show the latest version of the diff' do @@ -96,8 +96,7 @@ feature 'Merge Request versions', js: true, feature: true do end it 'has a path with comparison context' do - expect(page).to have_current_path diffs_namespace_project_merge_request_path( - project.namespace, + expect(page).to have_current_path diffs_project_merge_request_path( project, merge_request.iid, diff_id: merge_request_diff3.id, diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb index 118ecd9cba5..c0221525c9f 100644 --- a/spec/features/merge_requests/widget_deployments_spec.rb +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Widget Deployments Header', feature: true, js: true do +feature 'Widget Deployments Header', js: true do describe 'when deployed to an environment' do given(:user) { create(:user) } given(:project) { merge_request.target_project } @@ -12,9 +12,9 @@ feature 'Widget Deployments Header', feature: true, js: true do given!(:manual) { } background do - login_as(user) + sign_in(user) project.team << [user, role] - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end scenario 'displays that the environment is deployed' do diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index 4f3a5119915..69e31c7481f 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -1,27 +1,25 @@ require 'rails_helper' -describe 'Merge request', :feature, :js do +describe 'Merge request', :js do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'new merge request' do before do - visit new_namespace_project_merge_request_path( - project.namespace, + visit project_new_merge_request_path( project, merge_request: { source_project_id: project.id, target_project_id: project.id, source_branch: 'feature', target_branch: 'master' - } - ) + }) end it 'shows widget status after creating new merge request' do @@ -44,7 +42,7 @@ describe 'Merge request', :feature, :js do end before do - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'shows environments link' do @@ -71,7 +69,7 @@ describe 'Merge request', :feature, :js do type: 'CiService', category: 'ci') - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'has danger button while waiting for external CI status' do @@ -92,7 +90,7 @@ describe 'Merge request', :feature, :js do head_pipeline_of: merge_request) create(:ci_build, :pending, pipeline: pipeline) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'has danger button when not succeeded' do @@ -112,9 +110,7 @@ describe 'Merge request', :feature, :js do status: :manual, head_pipeline_of: merge_request) - visit namespace_project_merge_request_path(project.namespace, - project, - merge_request) + visit project_merge_request_path(project, merge_request) end it 'shows information about blocked pipeline' do @@ -136,7 +132,7 @@ describe 'Merge request', :feature, :js do head_pipeline_of: merge_request) create(:ci_build, :pending, pipeline: pipeline) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'has info button when MWBS button' do @@ -154,7 +150,7 @@ describe 'Merge request', :feature, :js do merge_error: 'Something went wrong' ) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'shows information about the merge error' do @@ -175,7 +171,7 @@ describe 'Merge request', :feature, :js do merge_error: 'Something went wrong' ) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'shows information about the merge error' do @@ -191,7 +187,7 @@ describe 'Merge request', :feature, :js do context 'merge error' do before do allow_any_instance_of(Repository).to receive(:merge).and_return(false) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'updates the MR widget' do @@ -204,15 +200,15 @@ describe 'Merge request', :feature, :js do end context 'user can merge into source project but cannot push to fork', js: true do - let(:fork_project) { create(:project, :public) } + let(:fork_project) { create(:project, :public, :repository) } let(:user2) { create(:user) } before do project.team << [user2, :master] - logout - login_as user2 + sign_out(:user) + sign_in(user2) merge_request.update(target_project: fork_project) - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + visit project_merge_request_path(project, merge_request) end it 'user can merge into the source project' do diff --git a/spec/features/merge_requests/wip_message_spec.rb b/spec/features/merge_requests/wip_message_spec.rb index 3311731b33b..b422c76249d 100644 --- a/spec/features/merge_requests/wip_message_spec.rb +++ b/spec/features/merge_requests/wip_message_spec.rb @@ -1,26 +1,24 @@ require 'spec_helper' -feature 'Work In Progress help message', feature: true do - let!(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } +feature 'Work In Progress help message' do + let!(:project) { create(:project, :public, :repository) } let!(:user) { create(:user) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'with WIP commits' do it 'shows a specific WIP hint' do - visit new_namespace_project_merge_request_path( - project.namespace, + visit project_new_merge_request_path( project, merge_request: { source_project_id: project.id, target_project_id: project.id, source_branch: 'wip', target_branch: 'master' - } - ) + }) within_wip_explanation do expect(page).to have_text( @@ -32,16 +30,14 @@ feature 'Work In Progress help message', feature: true do context 'without WIP commits' do it 'shows the regular WIP message' do - visit new_namespace_project_merge_request_path( - project.namespace, + visit project_new_merge_request_path( project, merge_request: { source_project_id: project.id, target_project_id: project.id, source_branch: 'fix', target_branch: 'master' - } - ) + }) within_wip_explanation do expect(page).not_to have_text( diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index c07de01c594..6c9dc67ad74 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -1,17 +1,19 @@ require 'rails_helper' -feature 'Milestone', feature: true do - let(:project) { create(:empty_project, :public) } +feature 'Milestone' do + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, namespace: group) } let(:user) { create(:user) } before do + create(:group_member, group: group, user: user) project.team << [user, :master] - login_as(user) + sign_in(user) end feature 'Create a milestone' do scenario 'shows an informative message for a new milestone' do - visit new_namespace_project_milestone_path(project.namespace, project) + visit new_project_milestone_path(project) page.within '.milestone-form' do fill_in "milestone_title", with: '8.7' @@ -31,23 +33,36 @@ feature 'Milestone', feature: true do milestone = create(:milestone, project: project, title: 8.7) create(:issue, title: "Bugfix1", project: project, milestone: milestone, state: "closed") - visit namespace_project_milestone_path(project.namespace, project, milestone) + visit project_milestone_path(project, milestone) expect(find('.alert-success')).to have_content('All issues for this milestone are closed. You may close this milestone now.') end end - feature 'Open a milestone with an existing title' do - scenario 'displays validation message' do + feature 'Open a project milestone with an existing title' do + scenario 'displays validation message when there is a project milestone with same title' do milestone = create(:milestone, project: project, title: 8.7) - visit new_namespace_project_milestone_path(project.namespace, project) + visit new_project_milestone_path(project) page.within '.milestone-form' do fill_in "milestone_title", with: milestone.title end find('input[name="commit"]').click - expect(find('.alert-danger')).to have_content('Title has already been taken') + expect(find('.alert-danger')).to have_content('already being used for another group or project milestone.') + end + + scenario 'displays validation message when there is a group milestone with same title' do + milestone = create(:milestone, project_id: nil, group: project.group, title: 8.7) + + visit new_group_milestone_path(project.group) + + page.within '.milestone-form' do + fill_in "milestone_title", with: milestone.title + end + find('input[name="commit"]').click + + expect(find('.alert-danger')).to have_content('already being used for another group or project milestone.') end end end diff --git a/spec/features/milestones/milestones_spec.rb b/spec/features/milestones/milestones_spec.rb deleted file mode 100644 index b3dfd6d0e81..00000000000 --- a/spec/features/milestones/milestones_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -require 'rails_helper' - -describe 'Milestone draggable', feature: true, js: true do - include DragTo - - let(:milestone) { create(:milestone, project: project, title: 8.14) } - let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - - context 'issues' do - let(:issue) { page.find_by_id('issues-list-unassigned').find('li') } - let(:issue_target) { page.find_by_id('issues-list-ongoing') } - - it 'does not allow guest to drag issue' do - create_and_drag_issue - - expect(issue_target).not_to have_selector('.issuable-row') - end - - it 'does not allow authorized user to drag issue' do - login_as(user) - create_and_drag_issue - - expect(issue_target).not_to have_selector('.issuable-row') - end - - it 'allows author to drag issue' do - login_as(user) - create_and_drag_issue(author: user) - - expect(issue_target).to have_selector('.issuable-row') - end - - it 'allows admin to drag issue' do - login_as(:admin) - create_and_drag_issue - - expect(issue_target).to have_selector('.issuable-row') - end - end - - context 'merge requests' do - let(:merge_request) { page.find_by_id('merge_requests-list-unassigned').find('li') } - let(:merge_request_target) { page.find_by_id('merge_requests-list-ongoing') } - - it 'does not allow guest to drag merge request' do - create_and_drag_merge_request - - expect(merge_request_target).not_to have_selector('.issuable-row') - end - - it 'does not allow authorized user to drag merge request' do - login_as(user) - create_and_drag_merge_request - - expect(merge_request_target).not_to have_selector('.issuable-row') - end - - it 'allows author to drag merge request' do - login_as(user) - create_and_drag_merge_request(author: user) - - expect(merge_request_target).to have_selector('.issuable-row') - end - - it 'allows admin to drag merge request' do - login_as(:admin) - create_and_drag_merge_request - - expect(merge_request_target).to have_selector('.issuable-row') - end - end - - def create_and_drag_issue(params = {}) - create(:issue, params.merge(title: 'Foo', project: project, milestone: milestone)) - - visit namespace_project_milestone_path(project.namespace, project, milestone) - scroll_into_view('.milestone-content') - drag_to(selector: '.issues-sortable-list', list_to_index: 1) - - wait_for_requests - end - - def create_and_drag_merge_request(params = {}) - create(:merge_request, params.merge(title: 'Foo', source_project: project, target_project: project, milestone: milestone)) - - visit namespace_project_milestone_path(project.namespace, project, milestone) - page.find("a[href='#tab-merge-requests']").click - - wait_for_requests - - scroll_into_view('.milestone-content') - drag_to(selector: '.merge_requests-sortable-list', list_to_index: 1) - - wait_for_requests - end - - def scroll_into_view(selector) - page.evaluate_script("document.querySelector('#{selector}').scrollIntoView();") - end -end diff --git a/spec/features/milestones/show_spec.rb b/spec/features/milestones/show_spec.rb index 227eb04ba72..20303359c46 100644 --- a/spec/features/milestones/show_spec.rb +++ b/spec/features/milestones/show_spec.rb @@ -1,19 +1,19 @@ require 'rails_helper' -describe 'Milestone show', feature: true do +describe 'Milestone show' do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:milestone) { create(:milestone, project: project) } let(:labels) { create_list(:label, 2, project: project) } let(:issue_params) { { project: project, assignees: [user], author: user, milestone: milestone, labels: labels } } before do project.add_user(user, :developer) - login_as(user) + sign_in(user) end def visit_milestone - visit namespace_project_milestone_path(project.namespace, project, milestone) + visit project_milestone_path(project, milestone) end it 'avoids N+1 database queries' do diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb new file mode 100644 index 00000000000..49d8e52f861 --- /dev/null +++ b/spec/features/oauth_login_spec.rb @@ -0,0 +1,114 @@ +require 'spec_helper' + +feature 'OAuth Login', :js, :allow_forgery_protection do + include DeviseHelpers + + def enter_code(code) + fill_in 'user_otp_attempt', with: code + click_button 'Verify code' + end + + def stub_omniauth_config(provider) + OmniAuth.config.add_mock(provider, OmniAuth::AuthHash.new(provider: provider.to_s, uid: "12345")) + set_devise_mapping(context: Rails.application) + Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[provider] + end + + providers = [:github, :twitter, :bitbucket, :gitlab, :google_oauth2, + :facebook, :cas3, :auth0, :authentiq] + + before(:all) do + # The OmniAuth `full_host` parameter doesn't get set correctly (it gets set to something like `http://localhost` + # here), and causes integration tests to fail with 404s. We set the `full_host` by removing the request path (and + # anything after it) from the request URI. + @omniauth_config_full_host = OmniAuth.config.full_host + OmniAuth.config.full_host = ->(request) { request['REQUEST_URI'].sub(/#{request['REQUEST_PATH']}.*/, '') } + end + + after(:all) do + OmniAuth.config.full_host = @omniauth_config_full_host + end + + providers.each do |provider| + context "when the user logs in using the #{provider} provider" do + context 'when two-factor authentication is disabled' do + it 'logs the user in' do + stub_omniauth_config(provider) + user = create(:omniauth_user, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid') + + expect(current_path).to eq root_path + end + end + + context 'when two-factor authentication is enabled' do + it 'logs the user in' do + stub_omniauth_config(provider) + user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid') + + enter_code(user.current_otp) + expect(current_path).to eq root_path + end + end + + context 'when "remember me" is checked' do + context 'when two-factor authentication is disabled' do + it 'remembers the user after a browser restart' do + stub_omniauth_config(provider) + user = create(:omniauth_user, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid', remember_me: true) + + clear_browser_session + + visit(root_path) + expect(current_path).to eq root_path + end + end + + context 'when two-factor authentication is enabled' do + it 'remembers the user after a browser restart' do + stub_omniauth_config(provider) + user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid', remember_me: true) + enter_code(user.current_otp) + + clear_browser_session + + visit(root_path) + expect(current_path).to eq root_path + end + end + end + + context 'when "remember me" is not checked' do + context 'when two-factor authentication is disabled' do + it 'does not remember the user after a browser restart' do + stub_omniauth_config(provider) + user = create(:omniauth_user, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid', remember_me: false) + + clear_browser_session + + visit(root_path) + expect(current_path).to eq new_user_session_path + end + end + + context 'when two-factor authentication is enabled' do + it 'does not remember the user after a browser restart' do + stub_omniauth_config(provider) + user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: provider.to_s) + login_via(provider.to_s, user, 'my-uid', remember_me: false) + enter_code(user.current_otp) + + clear_browser_session + + visit(root_path) + expect(current_path).to eq new_user_session_path + end + end + end + end + end +end diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb index 449ce80bc71..a22d548eef3 100644 --- a/spec/features/participants_autocomplete_spec.rb +++ b/spec/features/participants_autocomplete_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' feature 'Member autocomplete', :js do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:user) { create(:user) } let(:author) { create(:user) } let(:note) { create(:note, noteable: noteable, project: noteable.project) } before do note # actually create the note - login_as(user) + sign_in(user) end shared_examples "open suggestions when typing @" do @@ -29,7 +29,7 @@ feature 'Member autocomplete', :js do context 'adding a new note on a Issue' do let(:noteable) { create(:issue, author: author, project: project) } before do - visit namespace_project_issue_path(project.namespace, project, noteable) + visit project_issue_path(project, noteable) end include_examples "open suggestions when typing @" @@ -42,7 +42,7 @@ feature 'Member autocomplete', :js do target_project: project, author: author) end before do - visit namespace_project_merge_request_path(project.namespace, project, noteable) + visit project_merge_request_path(project, noteable) end include_examples "open suggestions when typing @" @@ -54,9 +54,10 @@ feature 'Member autocomplete', :js do let(:note) { create(:note_on_commit, project: project, commit_id: project.commit.id) } before do - allow_any_instance_of(Commit).to receive(:author).and_return(author) + allow(User).to receive(:find_by_any_email) + .with(noteable.author_email.downcase).and_return(author) - visit namespace_project_commit_path(project.namespace, project, noteable) + visit project_commit_path(project, noteable) end include_examples "open suggestions when typing @" diff --git a/spec/features/password_reset_spec.rb b/spec/features/password_reset_spec.rb index 257d363438c..5e1e7dc078f 100644 --- a/spec/features/password_reset_spec.rb +++ b/spec/features/password_reset_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Password reset', feature: true do +feature 'Password reset' do describe 'throttling' do it 'sends reset instructions when not previously sent' do user = create(:user) diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 7df628fd7a0..672022304da 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'Profile account page', feature: true do +describe 'Profile account page' do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) end describe 'when signup is enabled' do diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb index 05a7587f8d4..9944a6e1ff1 100644 --- a/spec/features/profiles/account_spec.rb +++ b/spec/features/profiles/account_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Profile > Account', feature: true do +feature 'Profile > Account' do given(:user) { create(:user, username: 'foo') } before do - login_as(user) + sign_in(user) end describe 'Change username' do @@ -27,25 +27,30 @@ feature 'Profile > Account', feature: true do end context 'with a project' do - given!(:project) { create(:project, namespace: user.namespace, path: 'project') } + given!(:project) { create(:project, namespace: user.namespace) } given(:new_project_path) { "/#{new_username}/#{project.path}" } given(:old_project_path) { "/#{user.username}/#{project.path}" } - before(:context) { TestEnv.clean_test_path } - after(:example) { TestEnv.clean_test_path } + before(:context) do + TestEnv.clean_test_path + end + + after(:example) do + TestEnv.clean_test_path + end scenario 'the project is accessible via the new path' do update_username(new_username) visit new_project_path expect(current_path).to eq(new_project_path) - expect(find('h1.project-title')).to have_content(project.name) + expect(find('h1.title')).to have_content(project.path) end scenario 'the old project path redirects to the new path' do update_username(new_username) visit old_project_path expect(current_path).to eq(new_project_path) - expect(find('h1.project-title')).to have_content(project.name) + expect(find('h1.title')).to have_content(project.path) end end end diff --git a/spec/features/profiles/chat_names_spec.rb b/spec/features/profiles/chat_names_spec.rb index 6f6f7029c0b..35793539e0e 100644 --- a/spec/features/profiles/chat_names_spec.rb +++ b/spec/features/profiles/chat_names_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'Profile > Chat', feature: true do +feature 'Profile > Chat' do given(:user) { create(:user) } given(:service) { create(:service) } before do - login_as(user) + sign_in(user) end describe 'uses authorization link' do diff --git a/spec/features/profiles/gpg_keys_spec.rb b/spec/features/profiles/gpg_keys_spec.rb new file mode 100644 index 00000000000..6edc482b47e --- /dev/null +++ b/spec/features/profiles/gpg_keys_spec.rb @@ -0,0 +1,58 @@ +require 'rails_helper' + +feature 'Profile > GPG Keys' do + let(:user) { create(:user, email: GpgHelpers::User2.emails.first) } + + before do + login_as(user) + end + + describe 'User adds a key' do + before do + visit profile_gpg_keys_path + end + + scenario 'saves the new key' do + fill_in('Key', with: GpgHelpers::User2.public_key) + click_button('Add key') + + expect(page).to have_content('bette.cartwright@example.com Verified') + expect(page).to have_content('bette.cartwright@example.net Unverified') + expect(page).to have_content(GpgHelpers::User2.fingerprint) + end + end + + scenario 'User sees their key' do + create(:gpg_key, user: user, key: GpgHelpers::User2.public_key) + visit profile_gpg_keys_path + + expect(page).to have_content('bette.cartwright@example.com Verified') + expect(page).to have_content('bette.cartwright@example.net Unverified') + expect(page).to have_content(GpgHelpers::User2.fingerprint) + end + + scenario 'User removes a key via the key index' do + create(:gpg_key, user: user, key: GpgHelpers::User2.public_key) + visit profile_gpg_keys_path + + click_link('Remove') + + expect(page).to have_content('Your GPG keys (0)') + end + + scenario 'User revokes a key via the key index' do + gpg_key = create :gpg_key, user: user, key: GpgHelpers::User2.public_key + gpg_signature = create :gpg_signature, gpg_key: gpg_key, valid_signature: true + + visit profile_gpg_keys_path + + click_link('Revoke') + + expect(page).to have_content('Your GPG keys (0)') + + expect(gpg_signature.reload).to have_attributes( + valid_signature: false, + gpg_key: nil + ) + end +end diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index 2f436f153aa..6541ea6bf57 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Profile > SSH Keys', feature: true do +feature 'Profile > SSH Keys' do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) end describe 'User adds a key' do diff --git a/spec/features/profiles/oauth_applications_spec.rb b/spec/features/profiles/oauth_applications_spec.rb index 1a5a9059dbd..45f78444362 100644 --- a/spec/features/profiles/oauth_applications_spec.rb +++ b/spec/features/profiles/oauth_applications_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'Profile > Applications', feature: true do +describe 'Profile > Applications' do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) end describe 'User manages applications', js: true do diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 4cbdd89d46f..2c757f99a27 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -1,44 +1,74 @@ require 'spec_helper' -describe 'Profile > Password', feature: true do - let(:user) { create(:user, password_automatically_set: true) } +describe 'Profile > Password' do + context 'Password authentication enabled' do + let(:user) { create(:user, password_automatically_set: true) } - before do - login_as(user) - visit edit_profile_password_path - end + before do + sign_in(user) + visit edit_profile_password_path + end - def fill_passwords(password, confirmation) - fill_in 'New password', with: password - fill_in 'Password confirmation', with: confirmation + def fill_passwords(password, confirmation) + fill_in 'New password', with: password + fill_in 'Password confirmation', with: confirmation - click_button 'Save password' - end + click_button 'Save password' + end + + context 'User with password automatically set' do + describe 'User puts different passwords in the field and in the confirmation' do + it 'shows an error message' do + fill_passwords('mypassword', 'mypassword2') - context 'User with password automatically set' do - describe 'User puts different passwords in the field and in the confirmation' do - it 'shows an error message' do - fill_passwords('mypassword', 'mypassword2') + page.within('.alert-danger') do + expect(page).to have_content("Password confirmation doesn't match Password") + end + end + + it 'does not contain the current password field after an error' do + fill_passwords('mypassword', 'mypassword2') - page.within('.alert-danger') do - expect(page).to have_content("Password confirmation doesn't match Password") + expect(page).to have_no_field('user[current_password]') end end - it 'does not contains the current password field after an error' do - fill_passwords('mypassword', 'mypassword2') + describe 'User puts the same passwords in the field and in the confirmation' do + it 'shows a success message' do + fill_passwords('mypassword', 'mypassword') - expect(page).to have_no_field('user[current_password]') + page.within('.flash-notice') do + expect(page).to have_content('Password was successfully updated. Please login with it') + end + end end end + end - describe 'User puts the same passwords in the field and in the confirmation' do - it 'shows a success message' do - fill_passwords('mypassword', 'mypassword') + context 'Password authentication unavailable' do + before do + gitlab_sign_in(user) + end - page.within('.flash-notice') do - expect(page).to have_content('Password was successfully updated. Please login with it') - end + context 'Regular user' do + let(:user) { create(:user) } + + it 'renders 404 when sign-in is disabled' do + stub_application_setting(password_authentication_enabled: false) + + visit edit_profile_password_path + + expect(page).to have_http_status(404) + end + end + + context 'LDAP user' do + let(:user) { create(:omniauth_user, provider: 'ldapmain') } + + it 'renders 404' do + visit edit_profile_password_path + + expect(page).to have_http_status(404) end end end diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index 27a20e78a43..f3124bbf29e 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -describe 'Profile > Personal Access Tokens', feature: true, js: true do +describe 'Profile > Personal Access Tokens', js: true do let(:user) { create(:user) } def active_personal_access_tokens find(".table.active-tokens") end - def inactive_personal_access_tokens - find(".table.inactive-tokens") + def no_personal_access_tokens_message + find(".settings-message") end def created_personal_access_token @@ -17,12 +17,13 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do def disallow_personal_access_token_saves! allow_any_instance_of(PersonalAccessToken).to receive(:save).and_return(false) + errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") } allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors) end before do - login_as(user) + sign_in(user) end describe "token creation" do @@ -79,20 +80,25 @@ describe 'Profile > Personal Access Tokens', feature: true, js: true do visit profile_personal_access_tokens_path click_on "Revoke" - expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) + expect(page).to have_selector(".settings-message") + expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.") end - it "moves expired tokens to the 'inactive' section" do + it "removes expired tokens from 'active' section" do personal_access_token.update(expires_at: 5.days.ago) visit profile_personal_access_tokens_path - expect(inactive_personal_access_tokens).to have_text(personal_access_token.name) + expect(page).to have_selector(".settings-message") + expect(no_personal_access_tokens_message).to have_text("This user has no active Personal Access Tokens.") end context "when revocation fails" do it "displays an error message" do - disallow_personal_access_token_saves! visit profile_personal_access_tokens_path + allow_any_instance_of(PersonalAccessToken).to receive(:update!).and_return(false) + + errors = ActiveModel::Errors.new(PersonalAccessToken.new).tap { |e| e.add(:name, "cannot be nil") } + allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors) click_on "Revoke" expect(active_personal_access_tokens).to have_text(personal_access_token.name) diff --git a/spec/features/profiles/preferences_spec.rb b/spec/features/profiles/preferences_spec.rb index d368bc4d753..9123aa9d155 100644 --- a/spec/features/profiles/preferences_spec.rb +++ b/spec/features/profiles/preferences_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'Profile > Preferences', feature: true do +describe 'Profile > Preferences' do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) visit profile_preferences_path end diff --git a/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb b/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb index e05fbb3715c..6a4173d43e1 100644 --- a/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb +++ b/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Profile > Notifications > User changes notified_of_own_activity setting', feature: true, js: true do +feature 'Profile > Notifications > User changes notified_of_own_activity setting', js: true do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) end scenario 'User opts into receiving notifications about their own activity' do diff --git a/spec/features/profiles/user_visits_notifications_tab_spec.rb b/spec/features/profiles/user_visits_notifications_tab_spec.rb new file mode 100644 index 00000000000..48c1787c8b7 --- /dev/null +++ b/spec/features/profiles/user_visits_notifications_tab_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +feature 'User visits the notifications tab', js: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + visit(profile_notifications_path) + end + + it 'changes the project notifications setting' do + expect(page).to have_content('Notifications') + + first('#notifications-button').trigger('click') + click_link('On mention') + + expect(page).to have_content('On mention') + end +end diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb index 3c1de5c09b2..84c2faa2015 100644 --- a/spec/features/projects/activity/rss_spec.rb +++ b/spec/features/projects/activity/rss_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' feature 'Project Activity RSS' do - let(:project) { create(:empty_project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:path) { activity_namespace_project_path(project.namespace, project) } + let(:user) { create(:user) } + let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:path) { activity_project_path(project) } before do create(:issue, project: project) @@ -10,9 +11,8 @@ feature 'Project Activity RSS' do context 'when signed in' do before do - user = create(:user) project.team << [user, :developer] - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/projects/artifacts/browse_spec.rb b/spec/features/projects/artifacts/browse_spec.rb index 68375956273..42b47cb3301 100644 --- a/spec/features/projects/artifacts/browse_spec.rb +++ b/spec/features/projects/artifacts/browse_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Browse artifact', :js, feature: true do +feature 'Browse artifact', :js do let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } def browse_path(path) - browse_namespace_project_job_artifacts_path(project.namespace, project, job, path) + browse_project_job_artifacts_path(project, job, path) end context 'when visiting old URL' do diff --git a/spec/features/projects/artifacts/download_spec.rb b/spec/features/projects/artifacts/download_spec.rb index dd9454840ee..f1bdb2812c6 100644 --- a/spec/features/projects/artifacts/download_spec.rb +++ b/spec/features/projects/artifacts/download_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Download artifact', :js, feature: true do +feature 'Download artifact', :js do let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project, sha: project.commit.sha, ref: 'master') } + let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) } let(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) } shared_examples 'downloading' do @@ -22,7 +22,7 @@ feature 'Download artifact', :js, feature: true do context 'via job id' do let(:download_url) do - download_namespace_project_job_artifacts_path(project.namespace, project, job) + download_project_job_artifacts_path(project, job) end it_behaves_like 'downloading' @@ -30,7 +30,7 @@ feature 'Download artifact', :js, feature: true do context 'via branch name and job name' do let(:download_url) do - latest_succeeded_namespace_project_artifacts_path(project.namespace, project, "#{pipeline.ref}/download", job: job.name) + latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) end it_behaves_like 'downloading' @@ -44,7 +44,7 @@ feature 'Download artifact', :js, feature: true do context 'via job id' do let(:download_url) do - download_namespace_project_job_artifacts_path(project.namespace, project, job) + download_project_job_artifacts_path(project, job) end it_behaves_like 'downloading' @@ -52,7 +52,7 @@ feature 'Download artifact', :js, feature: true do context 'via branch name and job name' do let(:download_url) do - latest_succeeded_namespace_project_artifacts_path(project.namespace, project, "#{pipeline.ref}/download", job: job.name) + latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) end it_behaves_like 'downloading' diff --git a/spec/features/projects/artifacts/file_spec.rb b/spec/features/projects/artifacts/file_spec.rb index 25c4f3c87a2..b2be10a7e0c 100644 --- a/spec/features/projects/artifacts/file_spec.rb +++ b/spec/features/projects/artifacts/file_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -feature 'Artifact file', :js, feature: true do +feature 'Artifact file', :js do let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) } def visit_file(path) @@ -10,7 +10,7 @@ feature 'Artifact file', :js, feature: true do end def file_path(path) - file_namespace_project_job_artifacts_path(project.namespace, project, build, path) + file_project_job_artifacts_path(project, build, path) end context 'Text file' do @@ -39,6 +39,7 @@ feature 'Artifact file', :js, feature: true do context 'JPG file' do before do + page.driver.browser.url_blacklist = [] visit_file('rails_sample.jpg') wait_for_requests diff --git a/spec/features/projects/artifacts/raw_spec.rb b/spec/features/projects/artifacts/raw_spec.rb index b589701729d..0bec6e9ad31 100644 --- a/spec/features/projects/artifacts/raw_spec.rb +++ b/spec/features/projects/artifacts/raw_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Raw artifact', :js, feature: true do +feature 'Raw artifact', :js do let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } def raw_path(path) - raw_namespace_project_job_artifacts_path(project.namespace, project, job, path) + raw_project_job_artifacts_path(project, job, path) end context 'when visiting old URL' do diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb index 01a95bf49ac..368a046f741 100644 --- a/spec/features/projects/badges/coverage_spec.rb +++ b/spec/features/projects/badges/coverage_spec.rb @@ -7,7 +7,7 @@ feature 'test coverage badge' do context 'when user has access to view badge' do background do project.team << [user, :developer] - login_as(user) + sign_in(user) end scenario 'user requests coverage badge image for pipeline' do @@ -45,7 +45,7 @@ feature 'test coverage badge' do end context 'when user does not have access to view badge' do - background { login_as(user) } + background { sign_in(user) } scenario 'user requests test coverage badge image' do show_test_coverage_badge @@ -55,7 +55,7 @@ feature 'test coverage badge' do end def create_pipeline - opts = { project: project, ref: 'master', sha: project.commit.id } + opts = { project: project } create(:ci_pipeline, opts).tap do |pipeline| yield pipeline @@ -70,8 +70,7 @@ feature 'test coverage badge' do end def show_test_coverage_badge(job: nil) - visit coverage_namespace_project_badges_path( - project.namespace, project, ref: :master, job: job, format: :svg) + visit coverage_project_badges_path(project, ref: :master, job: job, format: :svg) end def expect_coverage_badge(coverage) diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb index ae9db0c0d6e..89ae891037e 100644 --- a/spec/features/projects/badges/list_spec.rb +++ b/spec/features/projects/badges/list_spec.rb @@ -3,23 +3,23 @@ require 'spec_helper' feature 'list of badges' do background do user = create(:user) - project = create(:project) + project = create(:project, :repository) project.team << [user, :master] - login_as(user) - visit namespace_project_pipelines_settings_path(project.namespace, project) + sign_in(user) + visit project_pipelines_settings_path(project) end scenario 'user wants to see build status badge' do - page.within('.build-status') do - expect(page).to have_content 'build status' + page.within('.pipeline-status') do + expect(page).to have_content 'pipeline status' expect(page).to have_content 'Markdown' expect(page).to have_content 'HTML' expect(page).to have_content 'AsciiDoc' expect(page).to have_css('.highlight', count: 3) - expect(page).to have_xpath("//img[@alt='build status']") + expect(page).to have_xpath("//img[@alt='pipeline status']") page.within('.highlight', match: :first) do - expect(page).to have_content 'badges/master/build.svg' + expect(page).to have_content 'badges/master/pipeline.svg' end end end @@ -40,14 +40,14 @@ feature 'list of badges' do end scenario 'user changes current ref of build status badge', js: true do - page.within('.build-status') do + page.within('.pipeline-status') do first('.js-project-refs-dropdown').click page.within '.project-refs-form' do click_link 'improve/awesome' end - expect(page).to have_content 'badges/improve/awesome/build.svg' + expect(page).to have_content 'badges/improve/awesome/pipeline.svg' end end end diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb new file mode 100644 index 00000000000..b83ea8f4eaa --- /dev/null +++ b/spec/features/projects/badges/pipeline_badge_spec.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +feature 'Pipeline Badge' do + set(:project) { create(:project, :repository, :public) } + let(:ref) { project.default_branch } + + # this can't be tested in the controller, as it bypasses the rails router + # and constructs a route based on the controller being tested + # Keep around until 10.0, see gitlab-org/gitlab-ce#35307 + context 'when the deprecated badge is requested' do + it 'displays the badge' do + visit build_project_badges_path(project, ref: ref, format: :svg) + + expect(page.status_code).to eq(200) + end + end + + context 'when the project has a pipeline' do + let!(:pipeline) { create(:ci_empty_pipeline, project: project, ref: ref, sha: project.commit(ref).sha) } + let!(:job) { create(:ci_build, pipeline: pipeline) } + + context 'when the pipeline was successfull' do + it 'displays so on the badge' do + job.success + + visit pipeline_project_badges_path(project, ref: ref, format: :svg) + + expect(page.status_code).to eq(200) + expect_badge('passed') + end + end + + context 'when the pipeline failed' do + it 'shows displays so on the badge' do + job.drop + + visit pipeline_project_badges_path(project, ref: ref, format: :svg) + + expect(page.status_code).to eq(200) + expect_badge('failed') + end + end + + context 'when the pipeline is running' do + it 'shows displays so on the badge' do + create(:ci_build, pipeline: pipeline, name: 'second build', status_event: 'run') + + visit pipeline_project_badges_path(project, ref: ref, format: :svg) + + expect(page.status_code).to eq(200) + expect_badge('running') + end + end + + context 'when a new pipeline is created' do + it 'shows a fresh badge' do + visit pipeline_project_badges_path(project, ref: ref, format: :svg) + + expect(page.status_code).to eq(200) + expect(page.response_headers['Cache-Control']).to include 'no-cache' + end + end + + def expect_badge(status) + svg = Nokogiri::XML.parse(page.body) + expect(page.response_headers['Content-Type']).to include('image/svg+xml') + expect(svg.at(%Q{text:contains("#{status}")})).to be_truthy + end + end +end diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb index 53c5a52ce3a..1160f674974 100644 --- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb +++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, js: true do +feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', js: true do include TreeHelper let(:project) { create(:project, :public, :repository) } @@ -13,14 +13,14 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, end def visit_blob(fragment = nil) - visit namespace_project_blob_path(project.namespace, project, tree_join('master', path), anchor: fragment) + visit project_blob_path(project, tree_join('master', path), anchor: fragment) end describe 'Click "Permalink" button' do it 'works with no initial line number fragment hash' do visit_blob - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path)))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path)))) end it 'maintains intitial fragment hash' do @@ -28,7 +28,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, visit_blob(fragment) - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path), anchor: fragment))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment))) end it 'changes fragment hash if line number clicked' do @@ -39,7 +39,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, find('#L3').click find("##{ending_fragment}").click - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path), anchor: ending_fragment))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment))) end it 'with initial fragment hash, changes fragment hash if line number clicked' do @@ -51,15 +51,15 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, find('#L3').click find("##{ending_fragment}").click - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path), anchor: ending_fragment))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment))) end end - describe 'Click "Annotate" button' do + describe 'Click "Blame" button' do it 'works with no initial line number fragment hash' do visit_blob - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(namespace_project_blame_path(project.namespace, project, tree_join('master', path)))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path)))) end it 'maintains intitial fragment hash' do @@ -67,7 +67,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, visit_blob(fragment) - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(namespace_project_blame_path(project.namespace, project, tree_join('master', path), anchor: fragment))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: fragment))) end it 'changes fragment hash if line number clicked' do @@ -78,7 +78,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, find('#L3').click find("##{ending_fragment}").click - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(namespace_project_blame_path(project.namespace, project, tree_join('master', path), anchor: ending_fragment))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment))) end it 'with initial fragment hash, changes fragment hash if line number clicked' do @@ -90,7 +90,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true, find('#L3').click find("##{ending_fragment}").click - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(namespace_project_blame_path(project.namespace, project, tree_join('master', path), anchor: ending_fragment))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment))) end end end diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 82cfbfda157..3d465e709b9 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'File blob', :js, feature: true do - let(:project) { create(:project, :public) } +feature 'File blob', :js do + let(:project) { create(:project, :public, :repository) } - def visit_blob(path, fragment = nil) - visit namespace_project_blob_path(project.namespace, project, File.join('master', path), anchor: fragment) + def visit_blob(path, anchor: nil, ref: 'master') + visit project_blob_path(project, File.join(ref, path), anchor: anchor) wait_for_requests end @@ -17,6 +17,7 @@ feature 'File blob', :js, feature: true do it 'displays the blob' do aggregate_failures do # shows highlighted Ruby code + expect(page).to have_css(".js-syntax-highlight") expect(page).to have_content("require 'fileutils'") # does not show a viewer switcher @@ -71,6 +72,7 @@ feature 'File blob', :js, feature: true do expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) # shows highlighted Markdown code + expect(page).to have_css(".js-syntax-highlight") expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") # shows an enabled copy button @@ -101,7 +103,7 @@ feature 'File blob', :js, feature: true do context 'visiting with a line number anchor' do before do - visit_blob('files/markdown/ruby-style-guide.md', 'L1') + visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1') end it 'displays the blob using the simple viewer' do @@ -114,6 +116,7 @@ feature 'File blob', :js, feature: true do expect(page).to have_selector('#LC1.hll') # shows highlighted Markdown code + expect(page).to have_css(".js-syntax-highlight") expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") # shows an enabled copy button @@ -352,6 +355,37 @@ feature 'File blob', :js, feature: true do end end + context 'binary file that appears to be text in the first 1024 bytes' do + before do + visit_blob('encoding/binary-1.bin', ref: 'binary-encoding') + end + + it 'displays the blob' do + aggregate_failures do + # shows a download link + expect(page).to have_link('Download (23.8 KB)') + + # does not show a viewer switcher + expect(page).not_to have_selector('.js-blob-viewer-switcher') + + # The specs below verify an arguably incorrect result, but since we only + # learn that the file is not actually text once the text viewer content + # is loaded asynchronously, there is no straightforward way to get these + # synchronously loaded elements to display correctly. + # + # Clicking the copy button will result in nothing being copied. + # Clicking the raw button will result in the binary file being downloaded, + # as expected. + + # shows an enabled copy button, incorrectly + expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + + # shows a raw button, incorrectly + expect(page).to have_link('Open raw') + end + end + end + context '.gitlab-ci.yml' do before do project.add_master(project.creator) diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 1a38997450d..62ac9fd0e95 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -feature 'Editing file blob', feature: true, js: true do +feature 'Editing file blob', js: true do include TreeHelper - let(:project) { create(:project, :public, :test_repo) } + let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') } let(:branch) { 'master' } let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] } @@ -14,7 +14,7 @@ feature 'Editing file blob', feature: true, js: true do before do project.team << [user, role] - login_as(user) + sign_in(user) end def edit_and_commit @@ -26,7 +26,7 @@ feature 'Editing file blob', feature: true, js: true do context 'from MR diff' do before do - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) edit_and_commit end @@ -37,7 +37,7 @@ feature 'Editing file blob', feature: true, js: true do context 'from blob file path' do before do - visit namespace_project_blob_path(project.namespace, project, tree_join(branch, file_path)) + visit project_blob_path(project, tree_join(branch, file_path)) edit_and_commit end @@ -55,15 +55,15 @@ feature 'Editing file blob', feature: true, js: true do before do project.team << [user, :developer] - visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)) + visit project_edit_blob_path(project, tree_join(branch, file_path)) end it 'redirects to sign in and returns' do expect(page).to have_current_path(new_user_session_path) - login_as(user) + gitlab_sign_in(user) - expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))) + expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path))) end end @@ -71,15 +71,15 @@ feature 'Editing file blob', feature: true, js: true do let(:user) { create(:user) } before do - visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)) + visit project_edit_blob_path(project, tree_join(branch, file_path)) end it 'redirects to sign in and returns' do expect(page).to have_current_path(new_user_session_path) - login_as(user) + gitlab_sign_in(user) - expect(page).to have_current_path(namespace_project_blob_path(project.namespace, project, tree_join(branch, file_path))) + expect(page).to have_current_path(project_blob_path(project, tree_join(branch, file_path))) end end end @@ -92,27 +92,27 @@ feature 'Editing file blob', feature: true, js: true do project.team << [user, :developer] project.repository.add_branch(user, protected_branch, 'master') create(:protected_branch, project: project, name: protected_branch) - login_as(user) + sign_in(user) end context 'on some branch' do before do - visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)) + visit project_edit_blob_path(project, tree_join(branch, file_path)) end it 'shows blob editor with same branch' do - expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))) - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch) + expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path))) + expect(find('.js-branch-name').value).to eq(branch) end end context 'with protected branch' do before do - visit namespace_project_edit_blob_path(project.namespace, project, tree_join(protected_branch, file_path)) + visit project_edit_blob_path(project, tree_join(protected_branch, file_path)) end it 'shows blob editor with patch branch' do - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq('patch-1') + expect(find('.js-branch-name').value).to eq('patch-1') end end end @@ -122,13 +122,13 @@ feature 'Editing file blob', feature: true, js: true do before do project.team << [user, :master] - login_as(user) - visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)) + sign_in(user) + visit project_edit_blob_path(project, tree_join(branch, file_path)) end it 'shows blob editor with same branch' do - expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))) - expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch) + expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path))) + expect(find('.js-branch-name').value).to eq(branch) end end end diff --git a/spec/features/projects/blobs/shortcuts_blob_spec.rb b/spec/features/projects/blobs/shortcuts_blob_spec.rb index 30e2d587267..1e3080fa319 100644 --- a/spec/features/projects/blobs/shortcuts_blob_spec.rb +++ b/spec/features/projects/blobs/shortcuts_blob_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Blob shortcuts', feature: true do +feature 'Blob shortcuts' do include TreeHelper let(:project) { create(:project, :public, :repository) } let(:path) { project.repository.ls_files(project.repository.root_ref)[0] } @@ -12,7 +12,7 @@ feature 'Blob shortcuts', feature: true do end def visit_blob(fragment = nil) - visit namespace_project_blob_path(project.namespace, project, tree_join('master', path), anchor: fragment) + visit project_blob_path(project, tree_join('master', path), anchor: fragment) end describe 'pressing "y"' do @@ -21,7 +21,7 @@ feature 'Blob shortcuts', feature: true do find('body').native.send_key('y') - expect(page).to have_current_path(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path))), url: true) + expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path))), url: true) end it 'maintains fragment hash when redirecting' do @@ -30,7 +30,7 @@ feature 'Blob shortcuts', feature: true do find('body').native.send_key('y') - expect(page).to have_current_path(get_absolute_url(namespace_project_blob_path(project.namespace, project, tree_join(sha, path), anchor: fragment)), url: true) + expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment)), url: true) end end end diff --git a/spec/features/projects/blobs/user_create_spec.rb b/spec/features/projects/blobs/user_create_spec.rb deleted file mode 100644 index 4b6c55f5f44..00000000000 --- a/spec/features/projects/blobs/user_create_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'spec_helper' - -feature 'New blob creation', feature: true, js: true do - include TargetBranchHelpers - - given(:user) { create(:user) } - given(:role) { :developer } - given(:project) { create(:project) } - given(:content) { 'class NextFeature\nend\n' } - - background do - login_as(user) - project.team << [user, role] - visit namespace_project_new_blob_path(project.namespace, project, 'master') - end - - def edit_file - wait_for_requests - fill_in 'file_name', with: 'feature.rb' - execute_script("ace.edit('editor').setValue('#{content}')") - end - - def commit_file - click_button 'Commit changes' - end - - context 'with default target branch' do - background do - edit_file - commit_file - end - - scenario 'creates the blob in the default branch' do - expect(page).to have_content 'master' - expect(page).to have_content 'successfully created' - expect(page).to have_content 'NextFeature' - end - end - - context 'with different target branch' do - background do - edit_file - select_branch('feature') - commit_file - end - - scenario 'creates the blob in the different branch' do - expect(page).to have_content 'feature' - expect(page).to have_content 'successfully created' - end - end - - context 'with a new target branch' do - given(:new_branch_name) { 'new-feature' } - - background do - edit_file - create_new_branch(new_branch_name) - commit_file - end - - scenario 'creates the blob in the new branch' do - expect(page).to have_content new_branch_name - expect(page).to have_content 'successfully created' - end - scenario 'returns you to the mr' do - expect(page).to have_content 'New Merge Request' - expect(page).to have_content "From #{new_branch_name} into master" - expect(page).to have_content 'Add new file' - end - end - - context 'the file already exist in the source branch' do - background do - Files::CreateService.new( - project, - user, - start_branch: 'master', - branch_name: 'master', - commit_message: 'Create file', - file_path: 'feature.rb', - file_content: content - ).execute - edit_file - commit_file - end - - scenario 'shows error message' do - expect(page).to have_content('A file with this name already exists') - expect(page).to have_content('New file') - expect(page).to have_content('NextFeature') - end - end -end diff --git a/spec/features/projects/branches/download_buttons_spec.rb b/spec/features/projects/branches/download_buttons_spec.rb index 92028c19361..ad06cee4e81 100644 --- a/spec/features/projects/branches/download_buttons_spec.rb +++ b/spec/features/projects/branches/download_buttons_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Download buttons in branches page', feature: true do +feature 'Download buttons in branches page' do given(:user) { create(:user) } given(:role) { :developer } given(:status) { 'success' } - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given(:pipeline) do create(:ci_pipeline, @@ -22,20 +22,18 @@ feature 'Download buttons in branches page', feature: true do end background do - login_as(user) + sign_in(user) project.team << [user, role] end describe 'when checking branches' do context 'with artifacts' do before do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) end scenario 'shows download artifacts button' do - href = latest_succeeded_namespace_project_artifacts_path( - project.namespace, project, 'binary-encoding/download', - job: 'build') + href = latest_succeeded_project_artifacts_path(project, 'binary-encoding/download', job: 'build') expect(page).to have_link "Download '#{build.name}'", href: href end diff --git a/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb index c5e0a0f0517..0be434a567b 100644 --- a/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb +++ b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'New Branch Ref Dropdown', :js, :feature do +describe 'New Branch Ref Dropdown', :js do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } let(:toggle) { find('.create-from .dropdown-menu-toggle') } before do project.add_master(user) - login_as(user) - visit new_namespace_project_branch_path(project.namespace, project) + sign_in(user) + visit new_project_branch_path(project) end it 'filters a list of branches and tags' do diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 7668ce5f8be..ad4527a0b74 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' -describe 'Branches', feature: true do - let(:project) { create(:project, :public) } +describe 'Branches' do + let(:user) { create(:user) } + let(:project) { create(:project, :public, :repository) } let(:repository) { project.repository } def set_protected_branch_name(branch_name) @@ -12,30 +13,67 @@ describe 'Branches', feature: true do context 'logged in as developer' do before do - login_as :user - project.team << [@user, :developer] + sign_in(user) + project.team << [user, :developer] end describe 'Initial branches page' do it 'shows all the branches' do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) - repository.branches { |branch| expect(page).to have_content("#{branch.name}") } - expect(page).to have_content("Protected branches can be managed in project settings") + repository.branches_sorted_by(:name).first(20).each do |branch| + expect(page).to have_content("#{branch.name}") + end + end + + it 'sorts the branches by name' do + visit project_branches_path(project) + + click_button "Last updated" # Open sorting dropdown + click_link "Name" + + sorted = repository.branches_sorted_by(:name).first(20).map do |branch| + Regexp.escape(branch.name) + end + expect(page).to have_content(/#{sorted.join(".*")}/) + end + + it 'sorts the branches by last updated' do + visit project_branches_path(project) + + click_button "Last updated" # Open sorting dropdown + click_link "Last updated" + + sorted = repository.branches_sorted_by(:updated_desc).first(20).map do |branch| + Regexp.escape(branch.name) + end + expect(page).to have_content(/#{sorted.join(".*")}/) + end + + it 'sorts the branches by oldest updated' do + visit project_branches_path(project) + + click_button "Last updated" # Open sorting dropdown + click_link "Oldest updated" + + sorted = repository.branches_sorted_by(:updated_asc).first(20).map do |branch| + Regexp.escape(branch.name) + end + expect(page).to have_content(/#{sorted.join(".*")}/) end it 'avoids a N+1 query in branches index' do - control_count = ActiveRecord::QueryRecorder.new { visit namespace_project_branches_path(project.namespace, project) }.count + control_count = ActiveRecord::QueryRecorder.new { visit project_branches_path(project) }.count - %w(one two three four five).each { |ref| repository.add_branch(@user, ref, 'master') } + %w(one two three four five).each { |ref| repository.add_branch(user, ref, 'master') } - expect { visit namespace_project_branches_path(project.namespace, project) }.not_to exceed_query_limit(control_count) + expect { visit project_branches_path(project) }.not_to exceed_query_limit(control_count) end end describe 'Find branches' do it 'shows filtered branches', js: true do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) fill_in 'branch-search', with: 'fix' find('#branch-search').native.send_keys(:enter) @@ -47,7 +85,7 @@ describe 'Branches', feature: true do describe 'Delete unprotected branch' do it 'removes branch after confirmation', js: true do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) fill_in 'branch-search', with: 'fix' @@ -64,18 +102,18 @@ describe 'Branches', feature: true do describe 'Delete protected branch' do before do - project.add_user(@user, :master) - visit namespace_project_protected_branches_path(project.namespace, project) + project.add_user(user, :master) + visit project_protected_branches_path(project) set_protected_branch_name('fix') click_on "Protect" within(".protected-branches-list") { expect(page).to have_content('fix') } expect(ProtectedBranch.count).to eq(1) - project.add_user(@user, :developer) + project.add_user(user, :developer) end it 'does not allow devleoper to removes protected branch', js: true do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) fill_in 'branch-search', with: 'fix' find('#branch-search').native.send_keys(:enter) @@ -87,13 +125,21 @@ describe 'Branches', feature: true do context 'logged in as master' do before do - login_as :user - project.team << [@user, :master] + sign_in(user) + project.team << [user, :master] + end + + describe 'Initial branches page' do + it 'shows description for admin' do + visit project_branches_path(project) + + expect(page).to have_content("Protected branches can be managed in project settings") + end end describe 'Delete protected branch' do before do - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('fix') click_on "Protect" @@ -102,7 +148,7 @@ describe 'Branches', feature: true do end it 'removes branch after modal confirmation', js: true do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) fill_in 'branch-search', with: 'fix' find('#branch-search').native.send_keys(:enter) @@ -125,7 +171,7 @@ describe 'Branches', feature: true do context 'logged out' do before do - visit namespace_project_branches_path(project.namespace, project) + visit project_branches_path(project) end it 'does not show merge request button' do diff --git a/spec/features/projects/commit/builds_spec.rb b/spec/features/projects/commit/builds_spec.rb index 268d420c594..740331fe42a 100644 --- a/spec/features/projects/commit/builds_spec.rb +++ b/spec/features/projects/commit/builds_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' feature 'project commit pipelines', js: true do - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } background do user = create(:user) project.team << [user, :master] - login_as(user) + sign_in(user) end context 'when no builds triggered yet' do @@ -17,7 +17,7 @@ feature 'project commit pipelines', js: true do end scenario 'user views commit pipelines page' do - visit pipelines_namespace_project_commit_path(project.namespace, project, project.commit.sha) + visit pipelines_project_commit_path(project, project.commit.sha) page.within('.table-holder') do expect(page).to have_content project.pipelines[0].status # pipeline status diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb index bc7ca0ddd38..7086f56bb1b 100644 --- a/spec/features/projects/commit/cherry_pick_spec.rb +++ b/spec/features/projects/commit/cherry_pick_spec.rb @@ -1,15 +1,16 @@ require 'spec_helper' describe 'Cherry-pick Commits' do + let(:user) { create(:user) } let(:group) { create(:group) } - let(:project) { create(:project, namespace: group) } + let(:project) { create(:project, :repository, namespace: group) } let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') } let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') } before do - login_as :user - project.team << [@user, :master] - visit namespace_project_commit_path(project.namespace, project, master_pickable_commit.id) + sign_in(user) + project.team << [user, :master] + visit project_commit_path(project, master_pickable_commit.id) end context "I cherry-pick a commit" do @@ -42,7 +43,7 @@ describe 'Cherry-pick Commits' do uncheck 'create_merge_request' click_button 'Cherry-pick' end - visit namespace_project_commit_path(project.namespace, project, master_pickable_commit.id) + visit project_commit_path(project, master_pickable_commit.id) find("a[href='#modal-cherry-pick-commit']").click page.within('#modal-cherry-pick-commit') do uncheck 'create_merge_request' diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb index f2de195eb7f..2ef74e8857c 100644 --- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb +++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'Mini Pipeline Graph in Commit View', :js, :feature do +feature 'Mini Pipeline Graph in Commit View', :js do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } before do - login_as(user) + sign_in(user) end context 'when commit has pipelines' do @@ -22,7 +22,7 @@ feature 'Mini Pipeline Graph in Commit View', :js, :feature do before do build.run - visit namespace_project_commit_path(project.namespace, project, project.commit.id) + visit project_commit_path(project, project.commit.id) end it 'should display a mini pipeline graph' do @@ -43,7 +43,7 @@ feature 'Mini Pipeline Graph in Commit View', :js, :feature do context 'when commit does not have pipelines' do before do - visit namespace_project_commit_path(project.namespace, project, project.commit.id) + visit project_commit_path(project, project.commit.id) end it 'should not display a mini pipeline graph' do diff --git a/spec/features/projects/commit/rss_spec.rb b/spec/features/projects/commit/rss_spec.rb index 03b6d560c96..db958346f06 100644 --- a/spec/features/projects/commit/rss_spec.rb +++ b/spec/features/projects/commit/rss_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' feature 'Project Commits RSS' do + let(:user) { create(:user) } let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:path) { namespace_project_commits_path(project.namespace, project, :master) } + let(:path) { project_commits_path(project, :master) } context 'when signed in' do before do - user = create(:user) project.team << [user, :developer] - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb index ee6985ad993..82d73fe8531 100644 --- a/spec/features/projects/compare_spec.rb +++ b/spec/features/projects/compare_spec.rb @@ -2,12 +2,12 @@ require "spec_helper" describe "Compare", js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do project.team << [user, :master] - login_as user - visit namespace_project_compare_index_path(project.namespace, project, from: "master", to: "master") + sign_in user + visit project_compare_index_path(project, from: "master", to: "master") end describe "branches" do diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb index 06abfbbc86b..2d1a9b931b5 100644 --- a/spec/features/projects/deploy_keys_spec.rb +++ b/spec/features/projects/deploy_keys_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -describe 'Project deploy keys', :js, :feature do +describe 'Project deploy keys', :js do let(:user) { create(:user) } let(:project) { create(:project_empty_repo) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end describe 'removing key' do @@ -15,7 +15,7 @@ describe 'Project deploy keys', :js, :feature do end it 'removes association between project and deploy key' do - visit namespace_project_settings_repository_path(project.namespace, project) + visit project_settings_repository_path(project) page.within(find('.deploy-keys')) do expect(page).to have_selector('.deploy-keys li', count: 1) diff --git a/spec/features/projects/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/developer_views_empty_project_instructions_spec.rb index 0c51fe72ca4..fe8567ce348 100644 --- a/spec/features/projects/developer_views_empty_project_instructions_spec.rb +++ b/spec/features/projects/developer_views_empty_project_instructions_spec.rb @@ -1,13 +1,13 @@ require 'rails_helper' -feature 'Developer views empty project instructions', feature: true do - let(:project) { create(:empty_project, :empty_repo) } +feature 'Developer views empty project instructions' do + let(:project) { create(:project, :empty_repo) } let(:developer) { create(:user) } background do project.team << [developer, :developer] - login_as(developer) + sign_in(developer) end context 'without an SSH key' do @@ -47,7 +47,7 @@ feature 'Developer views empty project instructions', feature: true do end def visit_project - visit namespace_project_path(project.namespace, project) + visit project_path(project) end def select_protocol(protocol) diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb new file mode 100644 index 00000000000..bc102895aaf --- /dev/null +++ b/spec/features/projects/diffs/diff_show_spec.rb @@ -0,0 +1,137 @@ +require 'spec_helper' + +feature 'Diff file viewer', :js do + let(:project) { create(:project, :public, :repository) } + + def visit_commit(sha, anchor: nil) + visit project_commit_path(project, sha, anchor: anchor) + + wait_for_requests + end + + context 'Ruby file' do + before do + visit_commit('570e7b2abdd848b95f2f578043fc23bd6f6fd24d') + end + + it 'shows highlighted Ruby code' do + within('.diff-file[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd"]') do + expect(page).to have_css(".js-syntax-highlight") + expect(page).to have_content("def popen(cmd, path=nil)") + end + end + end + + context 'Ruby file (stored in LFS)' do + before do + project.add_master(project.creator) + + @commit_id = Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add Ruby file in LFS", + file_path: 'files/lfs/ruby.rb', + file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data + ).execute[:result] + end + + context 'when LFS is enabled on the project' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + project.update_attribute(:lfs_enabled, true) + + visit_commit(@commit_id) + end + + it 'shows an error message' do + expect(page).to have_content('This source diff could not be displayed because it is stored in LFS. You can view the blob instead.') + end + end + + context 'when LFS is disabled on the project' do + before do + visit_commit(@commit_id) + end + + it 'displays the diff' do + expect(page).to have_content('size 1575078') + end + end + end + + context 'Image file' do + before do + visit_commit('2f63565e7aac07bcdadb654e253078b727143ec4') + end + + it 'shows a rendered image' do + within('.diff-file[id="e986451b8f7397b617dbb6fffcb5539328c56921"]') do + expect(page).to have_css('img[alt="files/images/6049019_460s.jpg"]') + end + end + end + + context 'ISO file (stored in LFS)' do + context 'when LFS is enabled on the project' do + before do + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + project.update_attribute(:lfs_enabled, true) + + visit_commit('048721d90c449b244b7b4c53a9186b04330174ec') + end + + it 'shows that file was added' do + expect(page).to have_content('File added') + end + end + + context 'when LFS is disabled on the project' do + before do + visit_commit('048721d90c449b244b7b4c53a9186b04330174ec') + end + + it 'displays the diff' do + expect(page).to have_content('size 1575078') + end + end + end + + context 'ZIP file' do + before do + visit_commit('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') + end + + it 'shows that file was added' do + expect(page).to have_content('File added') + end + end + + context 'binary file that appears to be text in the first 1024 bytes' do + before do + # The file we're visiting is smaller than 10 KB and we want it collapsed + # so we need to disable the size increase feature. + stub_feature_flags(gitlab_git_diff_size_limit_increase: false) + + visit_commit('7b1cf4336b528e0f3d1d140ee50cafdbc703597c') + end + + it 'shows the diff is collapsed' do + expect(page).to have_content('This diff is collapsed. Click to expand it.') + end + + context 'expanding the diff' do + before do + # We can't use `click_link` because the "link" doesn't have an `href`. + find('a.click-to-expand').click + + wait_for_requests + end + + it 'shows there is no preview' do + expect(page).to have_content('No preview for this file type') + end + end + end +end diff --git a/spec/features/projects/edit_spec.rb b/spec/features/projects/edit_spec.rb index a263781c43c..d3b1d1f7be3 100644 --- a/spec/features/projects/edit_spec.rb +++ b/spec/features/projects/edit_spec.rb @@ -1,14 +1,14 @@ require 'rails_helper' -feature 'Project edit', feature: true, js: true do +feature 'Project edit', js: true do let(:user) { create(:user) } let(:project) { create(:project) } before do project.team << [user, :master] - login_as(user) + sign_in(user) - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) end context 'feature visibility' do diff --git a/spec/features/projects/environments/environment_metrics_spec.rb b/spec/features/projects/environments/environment_metrics_spec.rb index ee925e811e1..82a722c5960 100644 --- a/spec/features/projects/environments/environment_metrics_spec.rb +++ b/spec/features/projects/environments/environment_metrics_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Environment > Metrics', :feature do +feature 'Environment > Metrics' do include PrometheusHelpers given(:user) { create(:user) } @@ -15,7 +15,7 @@ feature 'Environment > Metrics', :feature do create(:deployment, environment: environment, deployable: build) stub_all_prometheus_requests(environment.slug) - login_as(user) + sign_in(user) visit_environment(environment) end @@ -27,13 +27,11 @@ feature 'Environment > Metrics', :feature do scenario 'shows metrics' do click_link('See metrics') - expect(page).to have_css('svg.prometheus-graph') + expect(page).to have_css('div#prometheus-graphs') end end def visit_environment(environment) - visit namespace_project_environment_path(environment.project.namespace, - environment.project, - environment) + visit project_environment_path(environment.project, environment) end end diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index 18b608c863e..56addd64056 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Environment', :feature do - given(:project) { create(:empty_project) } +feature 'Environment' do + given(:project) { create(:project) } given(:user) { create(:user) } given(:role) { :developer } background do - login_as(user) + sign_in(user) project.team << [user, role] end @@ -114,7 +114,7 @@ feature 'Environment', :feature do before do # Stub #terminals as it causes js-enabled feature specs to render the page incorrectly allow_any_instance_of(Environment).to receive(:terminals) { nil } - visit terminal_namespace_project_environment_path(project.namespace, project, environment) + visit terminal_project_environment_path(project, environment) end it 'displays a web terminal' do @@ -194,9 +194,7 @@ feature 'Environment', :feature do name: 'staging-1.0/review', state: :available) - visit folder_namespace_project_environments_path(project.namespace, - project, - id: 'staging-1.0') + visit folder_project_environments_path(project, id: 'staging-1.0') end it 'renders a correct environment folder' do @@ -207,7 +205,7 @@ feature 'Environment', :feature do end feature 'auto-close environment when branch is deleted' do - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given!(:environment) do create(:environment, :with_review_app, project: project, @@ -221,7 +219,7 @@ feature 'Environment', :feature do end scenario 'user deletes the branch with running environment' do - visit namespace_project_branches_path(project.namespace, project, search: 'feature') + visit project_branches_path(project, search: 'feature') remove_branch_with_hooks(project, user, 'feature') do page.within('.js-branch-feature') { find('a.btn-remove').click } @@ -249,12 +247,10 @@ feature 'Environment', :feature do end def visit_environment(environment) - visit namespace_project_environment_path(environment.project.namespace, - environment.project, - environment) + visit project_environment_path(environment.project, environment) end def have_terminal_button - have_link(nil, href: terminal_namespace_project_environment_path(project.namespace, project, environment)) + have_link(nil, href: terminal_project_environment_path(project, environment)) end end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 613b1edba36..1c59e57c0a4 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Environments page', :feature, :js do - given(:project) { create(:empty_project) } +feature 'Environments page', :js do + given(:project) { create(:project) } given(:user) { create(:user) } given(:role) { :developer } background do project.team << [user, role] - login_as(user) + sign_in(user) end given!(:environment) { } @@ -29,7 +29,7 @@ feature 'Environments page', :feature, :js do describe 'in available tab page' do it 'should show one environment' do - visit namespace_project_environments_path(project.namespace, project, scope: 'available') + visit project_environments_path(project, scope: 'available') expect(page).to have_css('.environments-container') expect(page.all('.environment-name').length).to eq(1) end @@ -37,7 +37,7 @@ feature 'Environments page', :feature, :js do describe 'in stopped tab page' do it 'should show no environments' do - visit namespace_project_environments_path(project.namespace, project, scope: 'stopped') + visit project_environments_path(project, scope: 'stopped') expect(page).to have_css('.environments-container') expect(page).to have_content('You don\'t have any environments right now') end @@ -49,7 +49,7 @@ feature 'Environments page', :feature, :js do describe 'in available tab page' do it 'should show no environments' do - visit namespace_project_environments_path(project.namespace, project, scope: 'available') + visit project_environments_path(project, scope: 'available') expect(page).to have_css('.environments-container') expect(page).to have_content('You don\'t have any environments right now') end @@ -57,7 +57,7 @@ feature 'Environments page', :feature, :js do describe 'in stopped tab page' do it 'should show one environment' do - visit namespace_project_environments_path(project.namespace, project, scope: 'stopped') + visit project_environments_path(project, scope: 'stopped') expect(page).to have_css('.environments-container') expect(page.all('.environment-name').length).to eq(1) end @@ -111,7 +111,7 @@ feature 'Environments page', :feature, :js do end context 'with deployments' do - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given(:deployment) do create(:deployment, environment: environment, @@ -151,7 +151,7 @@ feature 'Environments page', :feature, :js do find('.js-dropdown-play-icon-container').click expect(page).to have_content(action.name.humanize) - expect { find('.js-manual-action-link').click } + expect { find('.js-manual-action-link').trigger('click') } .not_to change { Ci::Pipeline.count } end @@ -277,10 +277,10 @@ feature 'Environments page', :feature, :js do end def have_terminal_button - have_link(nil, href: terminal_namespace_project_environment_path(project.namespace, project, environment)) + have_link(nil, href: terminal_project_environment_path(project, environment)) end def visit_environments(project) - visit namespace_project_environments_path(project.namespace, project) + visit project_environments_path(project) end end diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index c49648f54bd..4044202eb6b 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe 'Edit Project Settings', feature: true do +describe 'Edit Project Settings' do let(:member) { create(:user) } - let!(:project) { create(:project, :public, path: 'gitlab', name: 'sample') } + let!(:project) { create(:project, :public, :repository) } let!(:issue) { create(:issue, project: project) } let(:non_member) { create(:user) } describe 'project features visibility selectors', js: true do before do project.team << [member, :master] - login_as(member) + sign_in(member) end tools = { builds: "pipelines", issues: "issues", wiki: "wiki", snippets: "snippets", merge_requests: "merge_requests" } @@ -17,7 +17,7 @@ describe 'Edit Project Settings', feature: true do tools.each do |tool_name, shortcut_name| describe "feature #{tool_name}" do it 'toggles visibility' do - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) select 'Disabled', from: "project_project_feature_attributes_#{tool_name}_access_level" click_button 'Save changes' @@ -39,20 +39,31 @@ describe 'Edit Project Settings', feature: true do end end - context "When external issue tracker is enabled" do - it "does not hide issues tab" do - project.project_feature.update(issues_access_level: ProjectFeature::DISABLED) + context 'When external issue tracker is enabled and issues enabled on project settings' do + it 'does not hide issues tab' do allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(JiraService.new) - visit namespace_project_path(project.namespace, project) + visit project_path(project) - expect(page).to have_selector(".shortcuts-issues") + expect(page).to have_selector('.shortcuts-issues') + end + end + + context 'When external issue tracker is enabled and issues disabled on project settings' do + it 'hides issues tab' do + project.issues_enabled = false + project.save! + allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(JiraService.new) + + visit project_path(project) + + expect(page).not_to have_selector('.shortcuts-issues') end end context "pipelines subtabs" do it "shows builds when enabled" do - visit namespace_project_pipelines_path(project.namespace, project) + visit project_pipelines_path(project) expect(page).to have_selector(".shortcuts-builds") end @@ -60,7 +71,7 @@ describe 'Edit Project Settings', feature: true do it "hides builds when disabled" do allow(Ability).to receive(:allowed?).with(member, :read_builds, project).and_return(false) - visit namespace_project_pipelines_path(project.namespace, project) + visit project_pipelines_path(project) expect(page).not_to have_selector(".shortcuts-builds") end @@ -68,19 +79,22 @@ describe 'Edit Project Settings', feature: true do end describe 'project features visibility pages' do + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let(:job) { create(:ci_build, pipeline: pipeline) } + let(:tools) do { - builds: namespace_project_pipelines_path(project.namespace, project), - issues: namespace_project_issues_path(project.namespace, project), - wiki: namespace_project_wiki_path(project.namespace, project, :home), - snippets: namespace_project_snippets_path(project.namespace, project), - merge_requests: namespace_project_merge_requests_path(project.namespace, project) + builds: project_job_path(project, job), + issues: project_issues_path(project), + wiki: project_wiki_path(project, :home), + snippets: project_snippets_path(project), + merge_requests: project_merge_requests_path(project) } end context 'normal user' do before do - login_as(member) + sign_in(member) end it 'renders 200 if tool is enabled' do @@ -127,7 +141,7 @@ describe 'Edit Project Settings', feature: true do context 'admin user' do before do non_member.update_attribute(:admin, true) - login_as(non_member) + sign_in(non_member) end it 'renders 404 if feature is disabled' do @@ -153,8 +167,8 @@ describe 'Edit Project Settings', feature: true do describe 'repository visibility', js: true do before do project.team << [member, :master] - login_as(member) - visit edit_namespace_project_path(project.namespace, project) + sign_in(member) + visit edit_project_path(project) end it "disables repository related features" do @@ -171,7 +185,7 @@ describe 'Edit Project Settings', feature: true do click_button "Save changes" wait_for_requests - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_content "Customize your workflow!" end @@ -184,7 +198,7 @@ describe 'Edit Project Settings', feature: true do click_button "Save changes" wait_for_requests - visit activity_namespace_project_path(project.namespace, project) + visit activity_project_path(project) page.within(".event-filter") do expect(page).to have_selector("a", count: 2) @@ -202,7 +216,7 @@ describe 'Edit Project Settings', feature: true do expect(page).to have_content("Comments") end - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) select "Disabled", from: "project_project_feature_attributes_merge_requests_access_level" @@ -210,7 +224,7 @@ describe 'Edit Project Settings', feature: true do expect(page).to have_content("Comments") end - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) select "Disabled", from: "project_project_feature_attributes_repository_access_level" @@ -218,14 +232,14 @@ describe 'Edit Project Settings', feature: true do expect(page).not_to have_content("Comments") end - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) end def save_changes_and_check_activity_tab click_button "Save changes" wait_for_requests - visit activity_namespace_project_path(project.namespace, project) + visit activity_project_path(project) page.within(".event-filter") do yield @@ -239,8 +253,8 @@ describe 'Edit Project Settings', feature: true do before do project.team << [member, :guest] - login_as(member) - visit namespace_project_path(project.namespace, project) + sign_in(member) + visit project_path(project) end it "does not show project statistic for guest" do diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb index 30a1eedbb48..f62a9edd37e 100644 --- a/spec/features/projects/files/browse_files_spec.rb +++ b/spec/features/projects/files/browse_files_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -feature 'user browses project', feature: true, js: true do - let(:project) { create(:project) } +feature 'user browses project', js: true do + let(:project) { create(:project, :repository) } let(:user) { create(:user) } before do project.team << [user, :master] - login_with(user) - visit namespace_project_tree_path(project.namespace, project, project.default_branch) + sign_in(user) + visit project_tree_path(project, project.default_branch) end scenario "can see blame of '.gitignore'" do click_link ".gitignore" - click_link 'Annotate' + click_link 'Blame' expect(page).to have_content "*.rb" expect(page).to have_content "Dmitriy Zaporozhets" diff --git a/spec/features/projects/files/creating_a_file_spec.rb b/spec/features/projects/files/creating_a_file_spec.rb index 69744ac3948..e13bf4b6089 100644 --- a/spec/features/projects/files/creating_a_file_spec.rb +++ b/spec/features/projects/files/creating_a_file_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'User wants to create a file', feature: true do - let(:project) { create(:project) } +feature 'User wants to create a file' do + let(:project) { create(:project, :repository) } let(:user) { create(:user) } background do project.team << [user, :master] - login_as user - visit namespace_project_new_blob_path(project.namespace, project, project.default_branch) + sign_in user + visit project_new_blob_path(project, project.default_branch) end def submit_new_file(options) @@ -30,11 +30,6 @@ feature 'User wants to create a file', feature: true do expect(page).to have_content 'The file has been successfully created' end - scenario 'file name contains invalid characters' do - submit_new_file(file_name: '\\') - expect(page).to have_content 'Path can contain only' - end - scenario 'file name contains directory traversal' do submit_new_file(file_name: '../README.md') expect(page).to have_content 'Path cannot include directory traversal' diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb index 93909e91d05..cebb238dda1 100644 --- a/spec/features/projects/files/dockerfile_dropdown_spec.rb +++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' require 'fileutils' -feature 'User wants to add a Dockerfile file', feature: true do +feature 'User wants to add a Dockerfile file' do before do user = create(:user) - project = create(:project) + project = create(:project, :repository) project.team << [user, :master] - login_as user + sign_in user - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'Dockerfile') + visit project_new_blob_path(project, 'master', file_name: 'Dockerfile') end scenario 'user can see Dockerfile dropdown' do diff --git a/spec/features/projects/files/download_buttons_spec.rb b/spec/features/projects/files/download_buttons_spec.rb index d7c29a7e074..d2382d55c0b 100644 --- a/spec/features/projects/files/download_buttons_spec.rb +++ b/spec/features/projects/files/download_buttons_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Download buttons in files tree', feature: true do +feature 'Download buttons in files tree' do given(:user) { create(:user) } given(:role) { :developer } given(:status) { 'success' } - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given(:pipeline) do create(:ci_pipeline, @@ -22,21 +22,18 @@ feature 'Download buttons in files tree', feature: true do end background do - login_as(user) + sign_in(user) project.team << [user, role] end describe 'when files tree' do context 'with artifacts' do before do - visit namespace_project_tree_path( - project.namespace, project, project.default_branch) + visit project_tree_path(project, project.default_branch) end scenario 'shows download artifacts button' do - href = latest_succeeded_namespace_project_artifacts_path( - project.namespace, project, "#{project.default_branch}/download", - job: 'build') + href = latest_succeeded_project_artifacts_path(project, "#{project.default_branch}/download", job: 'build') expect(page).to have_link "Download '#{build.name}'", href: href end diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb index 012befa7990..c7e3f657639 100644 --- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'User uses soft wrap whilst editing file', feature: true, js: true do +feature 'User uses soft wrap whilst editing file', js: true do before do user = create(:user) - project = create(:project) + project = create(:project, :repository) project.team << [user, :master] - login_as user - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'test_file-name') + sign_in user + visit project_new_blob_path(project, 'master', file_name: 'test_file-name') editor = find('.file-editor.code') editor.click editor.send_keys 'Touch water with paw then recoil in horror chase dog then diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb index 7a3afafec29..20be968e89f 100644 --- a/spec/features/projects/files/editing_a_file_spec.rb +++ b/spec/features/projects/files/editing_a_file_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -feature 'User wants to edit a file', feature: true do - let(:project) { create(:project) } +feature 'User wants to edit a file' do + let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:commit_params) do { @@ -17,8 +17,8 @@ feature 'User wants to edit a file', feature: true do background do project.team << [user, :master] - login_as user - visit namespace_project_edit_blob_path(project.namespace, project, + sign_in user + visit project_edit_blob_path(project, File.join(project.default_branch, '.gitignore')) end diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb index 5c8105de4cb..702b99de733 100644 --- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb +++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'User views files page', feature: true do +feature 'User views files page' do let(:user) { create(:user) } let(:project) { create(:forked_project_with_submodules) } before do project.team << [user, :master] - login_as user - visit namespace_project_tree_path(project.namespace, project, project.repository.root_ref) + sign_in user + visit project_tree_path(project, project.repository.root_ref) end scenario 'user sees folders and submodules sorted together, followed by files' do diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb index ee42bcaec4b..7f97fdb8cc9 100644 --- a/spec/features/projects/files/find_file_keyboard_spec.rb +++ b/spec/features/projects/files/find_file_keyboard_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -feature 'Find file keyboard shortcuts', feature: true, js: true do +feature 'Find file keyboard shortcuts', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do project.team << [user, :master] - login_as user + sign_in user - visit namespace_project_find_file_path(project.namespace, project, project.repository.root_ref) + visit project_find_file_path(project, project.repository.root_ref) wait_for_requests end diff --git a/spec/features/projects/files/find_files_spec.rb b/spec/features/projects/files/find_files_spec.rb index 716b7591b95..57d67b28920 100644 --- a/spec/features/projects/files/find_files_spec.rb +++ b/spec/features/projects/files/find_files_spec.rb @@ -1,29 +1,22 @@ require 'spec_helper' -feature 'Find files button in the tree header', feature: true do +feature 'Find files button in the tree header' do given(:user) { create(:user) } - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } background do - login_as(user) + sign_in(user) project.team << [user, :developer] end scenario 'project main screen' do - visit namespace_project_path( - project.namespace, - project - ) + visit project_path(project) expect(page).to have_selector('.tree-controls .shortcuts-find-file') end scenario 'project tree screen' do - visit namespace_project_tree_path( - project.namespace, - project, - project.default_branch - ) + visit project_tree_path(project, project.default_branch) expect(page).to have_selector('.tree-controls .shortcuts-find-file') end diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb index e9f49453121..e2044c9d5aa 100644 --- a/spec/features/projects/files/gitignore_dropdown_spec.rb +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'User wants to add a .gitignore file', feature: true do +feature 'User wants to add a .gitignore file' do before do user = create(:user) - project = create(:project) + project = create(:project, :repository) project.team << [user, :master] - login_as user - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore') + sign_in user + visit project_new_blob_path(project, 'master', file_name: '.gitignore') end scenario 'user can see .gitignore dropdown' do diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb index 031b89d0499..ab242b0b0b5 100644 --- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb +++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'User wants to add a .gitlab-ci.yml file', feature: true do +feature 'User wants to add a .gitlab-ci.yml file' do before do user = create(:user) - project = create(:project) + project = create(:project, :repository) project.team << [user, :master] - login_as user - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitlab-ci.yml') + sign_in user + visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml') end scenario 'user can see .gitlab-ci.yml dropdown' do diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb index 8d410cc3f2e..95af263bcac 100644 --- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb +++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -feature 'project owner creates a license file', feature: true, js: true do +feature 'project owner creates a license file', js: true do let(:project_master) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } background do project.repository.delete_file(project_master, 'LICENSE', message: 'Remove LICENSE', branch_name: 'master') project.team << [project_master, :master] - login_as(project_master) - visit namespace_project_path(project.namespace, project) + sign_in(project_master) + visit project_path(project) end scenario 'project master creates a license file manually from a template' do - visit namespace_project_tree_path(project.namespace, project, project.repository.root_ref) + visit project_tree_path(project, project.repository.root_ref) find('.add-to-tree').click click_link 'New file' @@ -30,7 +30,7 @@ feature 'project owner creates a license file', feature: true, js: true do click_button 'Commit changes' expect(current_path).to eq( - namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) + project_blob_path(project, 'master/LICENSE')) expect(page).to have_content('MIT License') expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end @@ -40,7 +40,7 @@ feature 'project owner creates a license file', feature: true, js: true do expect(page).to have_content('New file') expect(current_path).to eq( - namespace_project_new_blob_path(project.namespace, project, 'master')) + project_new_blob_path(project, 'master')) expect(find('#file_name').value).to eq('LICENSE') expect(page).to have_selector('.license-selector') @@ -54,7 +54,7 @@ feature 'project owner creates a license file', feature: true, js: true do click_button 'Commit changes' expect(current_path).to eq( - namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) + project_blob_path(project, 'master/LICENSE')) expect(page).to have_content('MIT License') expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 8e197bccabf..7bcab01c739 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -1,21 +1,21 @@ require 'spec_helper' -feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do +feature 'project owner sees a link to create a license file in empty project', js: true do let(:project_master) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } background do project.team << [project_master, :master] - login_as(project_master) + sign_in(project_master) end scenario 'project master creates a license file from a template' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) click_link 'Create empty bare repository' click_on 'LICENSE' expect(page).to have_content('New file') expect(current_path).to eq( - namespace_project_new_blob_path(project.namespace, project, 'master')) + project_new_blob_path(project, 'master')) expect(find('#file_name').value).to eq('LICENSE') expect(page).to have_selector('.license-selector') @@ -31,7 +31,7 @@ feature 'project owner sees a link to create a license file in empty project', f click_button 'Commit changes' expect(current_path).to eq( - namespace_project_blob_path(project.namespace, project, 'master/LICENSE')) + project_blob_path(project, 'master/LICENSE')) expect(page).to have_content('MIT License') expect(page).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") end diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb index 9fcf12e6cb9..48003eeaa87 100644 --- a/spec/features/projects/files/template_type_dropdown_spec.rb +++ b/spec/features/projects/files/template_type_dropdown_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' feature 'Template type dropdown selector', js: true do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:user) { create(:user) } before do project.team << [user, :master] - login_as user + sign_in user end context 'editing a non-matching file' do @@ -31,7 +31,7 @@ feature 'Template type dropdown selector', js: true do context 'editing a matching file' do before do - visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, 'LICENSE')) + visit project_edit_blob_path(project, File.join(project.default_branch, 'LICENSE')) end scenario 'displayed' do @@ -61,7 +61,7 @@ feature 'Template type dropdown selector', js: true do context 'creating a matching file' do before do - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore') + visit project_new_blob_path(project, 'master', file_name: '.gitignore') end scenario 'is displayed' do @@ -79,7 +79,7 @@ feature 'Template type dropdown selector', js: true do context 'creating a file' do before do - visit namespace_project_new_blob_path(project.namespace, project, project.default_branch) + visit project_new_blob_path(project, project.default_branch) end scenario 'type selector is shown' do @@ -129,7 +129,7 @@ def check_type_selector_toggle_text(template_type) end def create_and_edit_file(file_name) - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: file_name) + visit project_new_blob_path(project, 'master', file_name: file_name) click_button "Commit changes" - visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, file_name)) + visit project_edit_blob_path(project, File.join(project.default_branch, file_name)) end diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb index de10eec0557..4238d25e9ee 100644 --- a/spec/features/projects/files/undo_template_spec.rb +++ b/spec/features/projects/files/undo_template_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' feature 'Template Undo Button', js: true do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:user) { create(:user) } before do project.team << [user, :master] - login_as user + sign_in user end context 'editing a matching file and applying a template' do before do - visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, "LICENSE")) + visit project_edit_blob_path(project, File.join(project.default_branch, "LICENSE")) select_file_template('.js-license-selector', 'Apache License 2.0') end @@ -22,7 +22,7 @@ feature 'Template Undo Button', js: true do context 'creating a non-matching file' do before do - visit namespace_project_new_blob_path(project.namespace, project, 'master') + visit project_new_blob_path(project, 'master') select_file_template_type('LICENSE') select_file_template('.js-license-selector', 'Apache License 2.0') end diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb index 67bc9142356..cff3b1f5743 100644 --- a/spec/features/projects/gfm_autocomplete_load_spec.rb +++ b/spec/features/projects/gfm_autocomplete_load_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -describe 'GFM autocomplete loading', feature: true, js: true do - let(:project) { create(:project) } +describe 'GFM autocomplete loading', js: true do + let(:project) { create(:project) } before do - login_as :admin + sign_in(create(:admin)) - visit namespace_project_path(project.namespace, project) + visit project_path(project) end it 'does not load on project#show' do @@ -14,7 +14,7 @@ describe 'GFM autocomplete loading', feature: true, js: true do end it 'loads on new issue page' do - visit new_namespace_project_issue_path(project.namespace, project) + visit new_project_issue_path(project) expect(evaluate_script('gl.GfmAutoComplete.dataSources')).not_to eq({}) end diff --git a/spec/features/projects/group_links_spec.rb b/spec/features/projects/group_links_spec.rb index 4e5682c8636..5195d027a9f 100644 --- a/spec/features/projects/group_links_spec.rb +++ b/spec/features/projects/group_links_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Project group links', :feature, :js do +feature 'Project group links', :js do include Select2Helper let(:master) { create(:user) } @@ -9,22 +9,24 @@ feature 'Project group links', :feature, :js do background do project.add_master(master) - login_as(master) + sign_in(master) end context 'setting an expiration date for a group link' do before do - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) + + click_on 'share-with-group-tab' select2 group.id, from: '#link_group_id' fill_in 'expires_at_groups', with: (Time.current + 4.5.days).strftime('%Y-%m-%d') page.find('body').click - click_on 'Share' + find('.btn-create').trigger('click') end it 'shows the expiration time with a warning class' do - page.within('.enabled-groups') do - expect(page).to have_content('expires in 4 days') + page.within('.project-members-groups') do + expect(page).to have_content('Expires in 4 days') expect(page).to have_selector('.text-warning') end end @@ -41,8 +43,9 @@ feature 'Project group links', :feature, :js do end it 'does not show ancestors', :nested_groups do - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) + click_on 'share-with-group-tab' click_link 'Search for a group' page.within '.select2-drop' do @@ -58,7 +61,7 @@ feature 'Project group links', :feature, :js do group.add_owner(master) group_two.add_owner(master) - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) execute_script 'GroupsSelect.PER_PAGE = 1;' open_select2 '#link_group_id' end diff --git a/spec/features/projects/guest_navigation_menu_spec.rb b/spec/features/projects/guest_navigation_menu_spec.rb index b91c3eff478..2385e1d9333 100644 --- a/spec/features/projects/guest_navigation_menu_spec.rb +++ b/spec/features/projects/guest_navigation_menu_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' describe 'Guest navigation menu' do - let(:project) { create(:empty_project, :private, public_builds: false) } + let(:project) { create(:project, :private, public_builds: false) } let(:guest) { create(:user) } before do project.team << [guest, :guest] - login_as(guest) + sign_in(guest) end it 'shows allowed tabs only' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) within('.layout-nav') do expect(page).to have_content 'Project' @@ -25,7 +25,7 @@ describe 'Guest navigation menu' do end it 'does not show fork button' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) within('.count-buttons') do expect(page).not_to have_link 'Fork' @@ -33,7 +33,7 @@ describe 'Guest navigation menu' do end it 'does not show clone path' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) within('.project-repo-buttons') do expect(page).not_to have_selector '.project-clone-holder' @@ -49,7 +49,7 @@ describe 'Guest navigation menu' do end it 'does not show the project file list landing page' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).not_to have_selector '.project-stats' expect(page).not_to have_selector '.project-last-commit' @@ -58,7 +58,7 @@ describe 'Guest navigation menu' do end it 'shows the customize workflow when issues and wiki are disabled' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_selector '.project-show-customize_workflow' end @@ -66,7 +66,7 @@ describe 'Guest navigation menu' do it 'shows the wiki when enabled' do project.project_feature.update!(wiki_access_level: ProjectFeature::PRIVATE) - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_selector '.project-show-wiki' end @@ -74,7 +74,7 @@ describe 'Guest navigation menu' do it 'shows the issues when enabled' do project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_selector '.issues-list' end diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 40caf89dd54..62d244ff259 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' # It looks up for any sensitive word inside the JSON, so if a sensitive word is found # we''l have to either include it adding the model that includes it to the +safe_list+ # or make sure the attribute is blacklisted in the +import_export.yml+ configuration -feature 'Import/Export - project export integration test', feature: true, js: true do +feature 'Import/Export - project export integration test', js: true do include Select2Helper include ExportFileHelper @@ -33,17 +33,17 @@ feature 'Import/Export - project export integration test', feature: true, js: tr context 'admin user' do before do - login_as(user) + sign_in(user) end scenario 'exports a project successfully' do - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) expect(page).to have_content('Export project') click_link 'Export project' - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) expect(page).to have_content('Download export') diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 583f479ec18..c0cfb9eafe2 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Import/Export - project import integration test', feature: true, js: true do +feature 'Import/Export - project import integration test', js: true do include Select2Helper let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } @@ -19,7 +19,7 @@ feature 'Import/Export - project import integration test', feature: true, js: tr let!(:namespace) { create(:namespace, name: "asd", owner: user) } before do - login_as(user) + gitlab_sign_in(user) end scenario 'user imports an exported project successfully' do @@ -53,7 +53,6 @@ feature 'Import/Export - project import integration test', feature: true, js: tr select2(namespace.id, from: '#project_namespace_id') fill_in :project_path, with: project.name, visible: true click_link 'GitLab export' - attach_file('file', file) click_on 'Import project' @@ -77,7 +76,7 @@ feature 'Import/Export - project import integration test', feature: true, js: tr context 'when limited to the default user namespace' do let(:user) { create(:user) } before do - login_as(user) + gitlab_sign_in(user) end scenario 'passes correct namespace ID in the URL' do @@ -98,6 +97,6 @@ feature 'Import/Export - project import integration test', feature: true, js: tr end def project_hook_exists?(project) - Gitlab::Git::Hook.new('post-receive', project.repository.path).exists? + Gitlab::Git::Hook.new('post-receive', project).exists? end end diff --git a/spec/features/projects/import_export/namespace_export_file_spec.rb b/spec/features/projects/import_export/namespace_export_file_spec.rb index cb399ea55df..691b0e1e4ca 100644 --- a/spec/features/projects/import_export/namespace_export_file_spec.rb +++ b/spec/features/projects/import_export/namespace_export_file_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Import/Export - Namespace export file cleanup', feature: true, js: true do +feature 'Import/Export - Namespace export file cleanup', js: true do let(:export_path) { "#{Dir.tmpdir}/import_file_spec" } let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } background do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) @@ -16,7 +16,7 @@ feature 'Import/Export - Namespace export file cleanup', feature: true, js: true context 'admin user' do before do - login_as(:admin) + sign_in(create(:admin)) end context 'moving the namespace' do @@ -48,13 +48,13 @@ feature 'Import/Export - Namespace export file cleanup', feature: true, js: true end def setup_export_project - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) expect(page).to have_content('Export project') click_link 'Export project' - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) expect(page).to have_content('Download export') end diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz Binary files differindex 4efd5a26a82..e03e7b88174 100644 --- a/spec/features/projects/import_export/test_project_export.tar.gz +++ b/spec/features/projects/import_export/test_project_export.tar.gz diff --git a/spec/features/projects/issuable_counts_caching_spec.rb b/spec/features/projects/issuable_counts_caching_spec.rb new file mode 100644 index 00000000000..1804d9dc244 --- /dev/null +++ b/spec/features/projects/issuable_counts_caching_spec.rb @@ -0,0 +1,132 @@ +require 'spec_helper' + +describe 'Issuable counts caching', :use_clean_rails_memory_store_caching do + let!(:member) { create(:user) } + let!(:member_2) { create(:user) } + let!(:non_member) { create(:user) } + let!(:project) { create(:project, :public) } + let!(:open_issue) { create(:issue, project: project) } + let!(:confidential_issue) { create(:issue, :confidential, project: project, author: non_member) } + let!(:closed_issue) { create(:issue, :closed, project: project) } + + before do + project.add_developer(member) + project.add_developer(member_2) + end + + it 'caches issuable counts correctly for non-members' do + # We can't use expect_any_instance_of because that uses a single instance. + counts = 0 + + allow_any_instance_of(IssuesFinder).to receive(:count_by_state).and_wrap_original do |m, *args| + counts += 1 + + m.call(*args) + end + + aggregate_failures 'only counts once on first load with no params, and caches for later loads' do + expect { visit project_issues_path(project) } + .to change { counts }.by(1) + + expect { visit project_issues_path(project) } + .not_to change { counts } + end + + aggregate_failures 'uses counts from cache on load from non-member' do + sign_in(non_member) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_out(non_member) + end + + aggregate_failures 'does not use the same cache for a member' do + sign_in(member) + + expect { visit project_issues_path(project) } + .to change { counts }.by(1) + + sign_out(member) + end + + aggregate_failures 'uses the same cache for all members' do + sign_in(member_2) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_out(member_2) + end + + aggregate_failures 'shares caches when params are passed' do + expect { visit project_issues_path(project, author_username: non_member.username) } + .to change { counts }.by(1) + + sign_in(member) + + expect { visit project_issues_path(project, author_username: non_member.username) } + .to change { counts }.by(1) + + sign_in(non_member) + + expect { visit project_issues_path(project, author_username: non_member.username) } + .not_to change { counts } + + sign_in(member_2) + + expect { visit project_issues_path(project, author_username: non_member.username) } + .not_to change { counts } + + sign_out(member_2) + end + + aggregate_failures 'resets caches on issue close' do + Issues::CloseService.new(project, member).execute(open_issue) + + expect { visit project_issues_path(project) } + .to change { counts }.by(1) + + sign_in(member) + + expect { visit project_issues_path(project) } + .to change { counts }.by(1) + + sign_in(non_member) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_in(member_2) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_out(member_2) + end + + aggregate_failures 'does not reset caches on issue update' do + Issues::UpdateService.new(project, member, title: 'new title').execute(open_issue) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_in(member) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_in(non_member) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_in(member_2) + + expect { visit project_issues_path(project) } + .not_to change { counts } + + sign_out(member_2) + end + end +end diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index 3076c863dcb..d2789d0aa52 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'issuable templates', feature: true, js: true do +feature 'issuable templates', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } before do project.team << [user, :master] - login_as user + sign_in user end context 'user creates an issue using templates' do @@ -28,7 +28,7 @@ feature 'issuable templates', feature: true, js: true do longtemplate_content, message: 'added issue template', branch_name: 'master') - visit edit_namespace_project_issue_path project.namespace, project, issue + visit edit_project_issue_path project, issue fill_in :'issue[title]', with: 'test issue title' end @@ -81,7 +81,7 @@ feature 'issuable templates', feature: true, js: true do template_content, message: 'added issue template', branch_name: 'master') - visit edit_namespace_project_issue_path project.namespace, project, issue + visit edit_project_issue_path project, issue fill_in :'issue[title]', with: 'test issue title' fill_in :'issue[description]', with: prior_description end @@ -105,7 +105,7 @@ feature 'issuable templates', feature: true, js: true do template_content, message: 'added merge request template', branch_name: 'master') - visit edit_namespace_project_merge_request_path project.namespace, project, merge_request + visit edit_project_merge_request_path project, merge_request fill_in :'merge_request[title]', with: 'test merge request title' end @@ -120,22 +120,25 @@ feature 'issuable templates', feature: true, js: true do context 'user creates a merge request from a forked project using templates' do let(:template_content) { 'this is a test "feature-proposal" template' } let(:fork_user) { create(:user) } - let(:fork_project) { create(:project, :public) } + let(:fork_project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, :with_diffs, source_project: fork_project, target_project: project) } background do - logout + sign_out(:user) + project.team << [fork_user, :developer] fork_project.team << [fork_user, :master] create(:forked_project_link, forked_to_project: fork_project, forked_from_project: project) - login_as fork_user + + sign_in(fork_user) + project.repository.create_file( fork_user, '.gitlab/merge_request_templates/feature-proposal.md', template_content, message: 'added merge request template', branch_name: 'master') - visit edit_namespace_project_merge_request_path project.namespace, project, merge_request + visit edit_project_merge_request_path project, merge_request fill_in :'merge_request[title]', with: 'test merge request title' end diff --git a/spec/features/projects/issues/list_spec.rb b/spec/features/projects/issues/list_spec.rb index 3137af074ca..9fc03f49f5b 100644 --- a/spec/features/projects/issues/list_spec.rb +++ b/spec/features/projects/issues/list_spec.rb @@ -2,18 +2,18 @@ require 'spec_helper' feature 'Issues List' do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } background do project.team << [user, :developer] - login_as(user) + sign_in(user) end scenario 'user does not see create new list button' do create(:issue, project: project) - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(page).not_to have_selector('.js-new-board-list') end diff --git a/spec/features/projects/issues/rss_spec.rb b/spec/features/projects/issues/rss_spec.rb index f6852192aef..58eeef8c258 100644 --- a/spec/features/projects/issues/rss_spec.rb +++ b/spec/features/projects/issues/rss_spec.rb @@ -1,18 +1,19 @@ require 'spec_helper' feature 'Project Issues RSS' do - let(:project) { create(:empty_project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:path) { namespace_project_issues_path(project.namespace, project) } + let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:path) { project_issues_path(project) } before do create(:issue, project: project) end context 'when signed in' do + let(:user) { create(:user) } + before do - user = create(:user) project.team << [user, :developer] - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 0eda46649db..037ac00d39f 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' require 'tempfile' -feature 'Jobs', :feature do +feature 'Jobs' do let(:user) { create(:user) } let(:user_access_level) { :developer } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, :trace, pipeline: pipeline) } - let(:build2) { create(:ci_build) } + let(:job) { create(:ci_build, :trace, pipeline: pipeline) } + let(:job2) { create(:ci_build) } let(:artifacts_file) do fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') @@ -16,45 +16,45 @@ feature 'Jobs', :feature do before do project.team << [user, user_access_level] - login_as(user) + sign_in(user) end describe "GET /:project/jobs" do - let!(:build) { create(:ci_build, pipeline: pipeline) } + let!(:job) { create(:ci_build, pipeline: pipeline) } context "Pending scope" do before do - visit namespace_project_jobs_path(project.namespace, project, scope: :pending) + visit project_jobs_path(project, scope: :pending) end it "shows Pending tab jobs" do expect(page).to have_link 'Cancel running' expect(page).to have_selector('.nav-links li.active', text: 'Pending') - expect(page).to have_content build.short_sha - expect(page).to have_content build.ref - expect(page).to have_content build.name + expect(page).to have_content job.short_sha + expect(page).to have_content job.ref + expect(page).to have_content job.name end end context "Running scope" do before do - build.run! - visit namespace_project_jobs_path(project.namespace, project, scope: :running) + job.run! + visit project_jobs_path(project, scope: :running) end it "shows Running tab jobs" do expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page).to have_link 'Cancel running' - expect(page).to have_content build.short_sha - expect(page).to have_content build.ref - expect(page).to have_content build.name + expect(page).to have_content job.short_sha + expect(page).to have_content job.ref + expect(page).to have_content job.name end end context "Finished scope" do before do - build.run! - visit namespace_project_jobs_path(project.namespace, project, scope: :finished) + job.run! + visit project_jobs_path(project, scope: :finished) end it "shows Finished tab jobs" do @@ -67,21 +67,21 @@ feature 'Jobs', :feature do context "All jobs" do before do project.builds.running_or_pending.each(&:success) - visit namespace_project_jobs_path(project.namespace, project) + visit project_jobs_path(project) end it "shows All tab jobs" do expect(page).to have_selector('.nav-links li.active', text: 'All') - expect(page).to have_content build.short_sha - expect(page).to have_content build.ref - expect(page).to have_content build.name + expect(page).to have_content job.short_sha + expect(page).to have_content job.ref + expect(page).to have_content job.name expect(page).not_to have_link 'Cancel running' end end context "when visiting old URL" do let(:jobs_url) do - namespace_project_jobs_path(project.namespace, project) + project_jobs_path(project) end before do @@ -96,25 +96,31 @@ feature 'Jobs', :feature do describe "POST /:project/jobs/:id/cancel_all" do before do - build.run! - visit namespace_project_jobs_path(project.namespace, project) + job.run! + visit project_jobs_path(project) click_link "Cancel running" end it 'shows all necessary content' do expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content 'canceled' - expect(page).to have_content build.short_sha - expect(page).to have_content build.ref - expect(page).to have_content build.name + expect(page).to have_content job.short_sha + expect(page).to have_content job.ref + expect(page).to have_content job.name expect(page).not_to have_link 'Cancel running' end end describe "GET /:project/jobs/:id" do context "Job from project" do + let(:job) { create(:ci_build, :success, pipeline: pipeline) } + before do - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) + end + + it 'shows status name', :js do + expect(page).to have_css('.ci-status.ci-success', text: 'passed') end it 'shows commit`s data' do @@ -124,14 +130,56 @@ feature 'Jobs', :feature do expect(page).to have_content pipeline.git_author_name end - it 'shows active build' do + it 'shows active job' do expect(page).to have_selector('.build-job.active') end end + context 'when job is not running', :js do + let(:job) { create(:ci_build, :success, pipeline: pipeline) } + + before do + visit project_job_path(project, job) + end + + it 'shows retry button' do + expect(page).to have_link('Retry') + end + + context 'if job passed' do + it 'does not show New issue button' do + expect(page).not_to have_link('New issue') + end + end + + context 'if job failed' do + let(:job) { create(:ci_build, :failed, pipeline: pipeline) } + + before do + visit project_job_path(project, job) + end + + it 'shows New issue button' do + expect(page).to have_link('New issue') + end + + it 'links to issues/new with the title and description filled in' do + button_title = "Build Failed ##{job.id}" + job_path = project_job_path(project, job) + options = { issue: { title: button_title, description: job_path } } + + href = new_project_issue_path(project, options) + + page.within('.header-action-buttons') do + expect(find('.js-new-issue')['href']).to include(href) + end + end + end + end + context "Job from other project" do before do - visit namespace_project_job_path(project.namespace, project, build2) + visit project_job_path(project, job2) end it { expect(page.status_code).to eq(404) } @@ -139,8 +187,8 @@ feature 'Jobs', :feature do context "Download artifacts" do before do - build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_job_path(project.namespace, project, build) + job.update_attributes(artifacts_file: artifacts_file) + visit project_job_path(project, job) end it 'has button to download artifacts' do @@ -150,10 +198,10 @@ feature 'Jobs', :feature do context 'Artifacts expire date' do before do - build.update_attributes(artifacts_file: artifacts_file, - artifacts_expire_at: expire_at) + job.update_attributes(artifacts_file: artifacts_file, + artifacts_expire_at: expire_at) - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) end context 'no expire date defined' do @@ -199,7 +247,7 @@ feature 'Jobs', :feature do context "when visiting old URL" do let(:job_url) do - namespace_project_job_path(project.namespace, project, build) + project_job_path(project, job) end before do @@ -213,9 +261,9 @@ feature 'Jobs', :feature do feature 'Raw trace' do before do - build.run! + job.run! - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) end it do @@ -225,16 +273,16 @@ feature 'Jobs', :feature do feature 'HTML trace', :js do before do - build.run! + job.run! - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) end context 'when job has an initial trace' do it 'loads job trace' do expect(page).to have_content 'BUILD TRACE' - build.trace.write do |stream| + job.trace.write do |stream| stream.append(' and more trace', 11) end @@ -246,12 +294,12 @@ feature 'Jobs', :feature do feature 'Variables' do let(:trigger_request) { create(:ci_trigger_request_with_variables) } - let(:build) do + let(:job) do create :ci_build, pipeline: pipeline, trigger_request: trigger_request end before do - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) end it 'shows variable key and value after click', js: true do @@ -273,20 +321,20 @@ feature 'Jobs', :feature do context 'job is successfull and has deployment' do let(:deployment) { create(:deployment) } - let(:build) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } + let(:job) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } it 'shows a link for the job' do - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) expect(page).to have_link environment.name end end context 'job is complete and not successful' do - let(:build) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } + let(:job) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } it 'shows a link for the job' do - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) expect(page).to have_link environment.name end @@ -294,10 +342,10 @@ feature 'Jobs', :feature do context 'job creates a new deployment' do let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) } - let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } + let(:job) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } it 'shows a link to latest deployment' do - visit namespace_project_job_path(project.namespace, project, build) + visit project_job_path(project, job) expect(page).to have_link('latest deployment') end @@ -305,72 +353,47 @@ feature 'Jobs', :feature do end end - describe "POST /:project/jobs/:id/cancel" do + describe "POST /:project/jobs/:id/cancel", :js do context "Job from project" do before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - click_link "Cancel" + job.run! + visit project_job_path(project, job) + find('.js-cancel-job').click() end it 'loads the page and shows all needed controls' do expect(page.status_code).to eq(200) - expect(page).to have_content 'canceled' expect(page).to have_content 'Retry' end end - - context "Job from other project" do - before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - page.driver.post(cancel_namespace_project_job_path(project.namespace, project, build2)) - end - - it { expect(page.status_code).to eq(404) } - end end describe "POST /:project/jobs/:id/retry" do - context "Job from project" do + context "Job from project", :js do before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - click_link 'Cancel' - page.within('.build-header') do - click_link 'Retry job' - end + job.run! + visit project_job_path(project, job) + find('.js-cancel-job').click() + find('.js-retry-button').trigger('click') end - it 'shows the right status and buttons' do + it 'shows the right status and buttons', :js do expect(page).to have_http_status(200) - expect(page).to have_content 'pending' page.within('aside.right-sidebar') do expect(page).to have_content 'Cancel' end end end - context "Job from other project" do - before do - build.run! - visit namespace_project_job_path(project.namespace, project, build) - click_link 'Cancel' - page.driver.post(retry_namespace_project_job_path(project.namespace, project, build2)) - end - - it { expect(page).to have_http_status(404) } - end - context "Job that current user is not allowed to retry" do before do - build.run! - build.cancel! + job.run! + job.cancel! project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - logout_direct - login_with(create(:user)) - visit namespace_project_job_path(project.namespace, project, build) + sign_out(:user) + sign_in(create(:user)) + visit project_job_path(project, job) end it 'does not show the Retry button' do @@ -383,15 +406,15 @@ feature 'Jobs', :feature do describe "GET /:project/jobs/:id/download" do before do - build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_job_path(project.namespace, project, build) + job.update_attributes(artifacts_file: artifacts_file) + visit project_job_path(project, job) click_link 'Download' end context "Build from other project" do before do - build2.update_attributes(artifacts_file: artifacts_file) - visit download_namespace_project_job_artifacts_path(project.namespace, project, build2) + job2.update_attributes(artifacts_file: artifacts_file) + visit download_project_job_artifacts_path(project, job2) end it { expect(page.status_code).to eq(404) } @@ -403,23 +426,23 @@ feature 'Jobs', :feature do context 'job from project' do before do Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' } - build.run! - visit namespace_project_job_path(project.namespace, project, build) + job.run! + visit project_job_path(project, job) find('.js-raw-link-controller').click() end it 'sends the right headers' do expect(page.status_code).to eq(200) expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8') - expect(page.response_headers['X-Sendfile']).to eq(build.trace.send(:current_path)) + expect(page.response_headers['X-Sendfile']).to eq(job.trace.send(:current_path)) end end context 'job from other project' do before do Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' } - build2.run! - visit raw_namespace_project_job_path(project.namespace, project, build2) + job2.run! + visit raw_project_job_path(project, job2) end it 'sends the right headers' do @@ -434,21 +457,18 @@ feature 'Jobs', :feature do before do Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' } - build.run! - - allow_any_instance_of(Gitlab::Ci::Trace).to receive(:paths) - .and_return(paths) - - visit namespace_project_job_path(project.namespace, project, build) + job.run! end - context 'when build has trace in file', :js do - let(:paths) do - [existing_file] - end - + context 'when job has trace in file', :js do before do - find('.js-raw-link-controller').click() + allow_any_instance_of(Gitlab::Ci::Trace) + .to receive(:paths) + .and_return([existing_file]) + + visit project_job_path(project, job) + + find('.js-raw-link-controller').click end it 'sends the right headers' do @@ -458,18 +478,24 @@ feature 'Jobs', :feature do end end - context 'when job has trace in DB' do - let(:paths) { [] } + context 'when job has trace in the database', :js do + before do + allow_any_instance_of(Gitlab::Ci::Trace) + .to receive(:paths) + .and_return([]) + + visit project_job_path(project, job) + end it 'sends the right headers' do - expect(page.status_code).not_to have_selector('.js-raw-link-controller') + expect(page).not_to have_selector('.js-raw-link-controller') end end end context "when visiting old URL" do let(:raw_job_url) do - raw_namespace_project_job_path(project.namespace, project, build) + raw_project_job_path(project, job) end before do @@ -485,7 +511,7 @@ feature 'Jobs', :feature do describe "GET /:project/jobs/:id/trace.json" do context "Job from project" do before do - visit trace_namespace_project_job_path(project.namespace, project, build, format: :json) + visit trace_project_job_path(project, job, format: :json) end it { expect(page.status_code).to eq(200) } @@ -493,7 +519,7 @@ feature 'Jobs', :feature do context "Job from other project" do before do - visit trace_namespace_project_job_path(project.namespace, project, build2, format: :json) + visit trace_project_job_path(project, job2, format: :json) end it { expect(page.status_code).to eq(404) } @@ -503,7 +529,7 @@ feature 'Jobs', :feature do describe "GET /:project/jobs/:id/status" do context "Job from project" do before do - visit status_namespace_project_job_path(project.namespace, project, build) + visit status_project_job_path(project, job) end it { expect(page.status_code).to eq(200) } @@ -511,7 +537,7 @@ feature 'Jobs', :feature do context "Job from other project" do before do - visit status_namespace_project_job_path(project.namespace, project, build2) + visit status_project_job_path(project, job2) end it { expect(page.status_code).to eq(404) } diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb index e2911a37e40..0292a3192d8 100644 --- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb +++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Issue prioritization', feature: true do +feature 'Issue prioritization' do let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } @@ -28,8 +28,8 @@ feature 'Issue prioritization', feature: true do issue_2.labels << label_4 issue_1.labels << label_5 - login_as user - visit namespace_project_issues_path(project.namespace, project, sort: 'label_priority') + sign_in user + visit project_issues_path(project, sort: 'label_priority') # Ensure we are indicating that issues are sorted by priority expect(page).to have_selector('.dropdown-toggle', text: 'Label priority') @@ -67,8 +67,8 @@ feature 'Issue prioritization', feature: true do issue_4.labels << label_4 # 7 issue_6.labels << label_5 # 8 - No priority - login_as user - visit namespace_project_issues_path(project.namespace, project, sort: 'label_priority') + sign_in user + visit project_issues_path(project, sort: 'label_priority') expect(page).to have_selector('.dropdown-toggle', text: 'Label priority') diff --git a/spec/features/projects/labels/subscription_spec.rb b/spec/features/projects/labels/subscription_spec.rb index 3130d87fba5..5716d151250 100644 --- a/spec/features/projects/labels/subscription_spec.rb +++ b/spec/features/projects/labels/subscription_spec.rb @@ -1,20 +1,20 @@ require 'spec_helper' -feature 'Labels subscription', feature: true do +feature 'Labels subscription' do let(:user) { create(:user) } let(:group) { create(:group) } - let(:project) { create(:empty_project, :public, namespace: group) } + let(:project) { create(:project, :public, namespace: group) } let!(:bug) { create(:label, project: project, title: 'bug') } let!(:feature) { create(:group_label, group: group, title: 'feature') } context 'when signed in' do before do project.team << [user, :developer] - login_as user + sign_in user end scenario 'users can subscribe/unsubscribe to labels', js: true do - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content('bug') expect(page).to have_content('feature') @@ -55,7 +55,7 @@ feature 'Labels subscription', feature: true do context 'when not signed in' do it 'users can not subscribe/unsubscribe to labels' do - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content 'bug' expect(page).to have_content 'feature' diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb index 34fafe072a3..8f85e972027 100644 --- a/spec/features/projects/labels/update_prioritization_spec.rb +++ b/spec/features/projects/labels/update_prioritization_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Prioritize labels', feature: true do +feature 'Prioritize labels' do include DragTo let(:user) { create(:user) } let(:group) { create(:group) } - let(:project) { create(:empty_project, :public, namespace: group) } + let(:project) { create(:project, :public, namespace: group) } let!(:bug) { create(:label, project: project, title: 'bug') } let!(:wontfix) { create(:label, project: project, title: 'wontfix') } let!(:feature) { create(:group_label, group: group, title: 'feature') } @@ -14,11 +14,11 @@ feature 'Prioritize labels', feature: true do before do project.team << [user, :developer] - login_as user + sign_in user end scenario 'user can prioritize a group label', js: true do - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content('Star labels to start sorting by priority') @@ -37,7 +37,7 @@ feature 'Prioritize labels', feature: true do scenario 'user can unprioritize a group label', js: true do create(:label_priority, project: project, label: feature, priority: 1) - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) page.within('.prioritized-labels') do expect(page).to have_content('feature') @@ -53,7 +53,7 @@ feature 'Prioritize labels', feature: true do end scenario 'user can prioritize a project label', js: true do - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content('Star labels to start sorting by priority') @@ -72,7 +72,7 @@ feature 'Prioritize labels', feature: true do scenario 'user can unprioritize a project label', js: true do create(:label_priority, project: project, label: bug, priority: 1) - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) page.within('.prioritized-labels') do expect(page).to have_content('bug') @@ -92,7 +92,7 @@ feature 'Prioritize labels', feature: true do create(:label_priority, project: project, label: bug, priority: 1) create(:label_priority, project: project, label: feature, priority: 2) - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content 'bug' expect(page).to have_content 'feature' @@ -114,31 +114,39 @@ feature 'Prioritize labels', feature: true do expect(page.all('li').last).to have_content('bug') end end + + it 'shows a help message about prioritized labels' do + visit project_labels_path(project) + + expect(page).to have_content 'Star a label' + end end context 'as a guest' do it 'does not prioritize labels' do guest = create(:user) - login_as guest + sign_in guest - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content 'bug' expect(page).to have_content 'wontfix' expect(page).to have_content 'feature' expect(page).not_to have_css('.prioritized-labels') + expect(page).not_to have_content 'Star a label' end end context 'as a non signed in user' do it 'does not prioritize labels' do - visit namespace_project_labels_path(project.namespace, project) + visit project_labels_path(project) expect(page).to have_content 'bug' expect(page).to have_content 'wontfix' expect(page).to have_content 'feature' expect(page).not_to have_css('.prioritized-labels') + expect(page).not_to have_content 'Star a label' end end end diff --git a/spec/features/projects/main/download_buttons_spec.rb b/spec/features/projects/main/download_buttons_spec.rb index 02198ff3e41..3f2579bb01a 100644 --- a/spec/features/projects/main/download_buttons_spec.rb +++ b/spec/features/projects/main/download_buttons_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Download buttons in project main page', feature: true do +feature 'Download buttons in project main page' do given(:user) { create(:user) } given(:role) { :developer } given(:status) { 'success' } - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given(:pipeline) do create(:ci_pipeline, @@ -22,20 +22,18 @@ feature 'Download buttons in project main page', feature: true do end background do - login_as(user) + sign_in(user) project.team << [user, role] end describe 'when checking project main page' do context 'with artifacts' do before do - visit namespace_project_path(project.namespace, project) + visit project_path(project) end scenario 'shows download artifacts button' do - href = latest_succeeded_namespace_project_artifacts_path( - project.namespace, project, "#{project.default_branch}/download", - job: 'build') + href = latest_succeeded_project_artifacts_path(project, "#{project.default_branch}/download", job: 'build') expect(page).to have_link "Download '#{build.name}'", href: href end diff --git a/spec/features/projects/main/rss_spec.rb b/spec/features/projects/main/rss_spec.rb index 53966229a2a..7914180b951 100644 --- a/spec/features/projects/main/rss_spec.rb +++ b/spec/features/projects/main/rss_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' feature 'Project RSS' do + let(:user) { create(:user) } let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:path) { namespace_project_path(project.namespace, project) } + let(:path) { project_path(project) } context 'when signed in' do before do - user = create(:user) project.team << [user, :developer] - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/projects/members/anonymous_user_sees_members_spec.rb b/spec/features/projects/members/anonymous_user_sees_members_spec.rb index d82cf53c690..bf0990d675d 100644 --- a/spec/features/projects/members/anonymous_user_sees_members_spec.rb +++ b/spec/features/projects/members/anonymous_user_sees_members_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -feature 'Projects > Members > Anonymous user sees members', feature: true do +feature 'Projects > Members > Anonymous user sees members' do let(:user) { create(:user) } let(:group) { create(:group, :public) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } background do project.team << [user, :master] @@ -11,10 +11,10 @@ feature 'Projects > Members > Anonymous user sees members', feature: true do end scenario "anonymous user visits the project's members page and sees the list of members" do - visit namespace_project_settings_members_path(project.namespace, project) + visit project_project_members_path(project) expect(current_path).to eq( - namespace_project_settings_members_path(project.namespace, project)) + project_project_members_path(project)) expect(page).to have_content(user.name) end end diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 3d253f01484..1c348b987d4 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -feature 'Projects > Members > Anonymous user sees members', feature: true, js: true do +feature 'Projects > Members > Anonymous user sees members', js: true do let(:user) { create(:user) } let(:group) { create(:group, :public) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } background do project.team << [user, :master] @group_link = create(:project_group_link, project: project, group: group) - login_as(user) - visit namespace_project_settings_members_path(project.namespace, project) + sign_in(user) + visit project_settings_members_path(project) end it 'updates group access level' do @@ -22,7 +22,7 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t wait_for_requests - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) expect(first('.group_member')).to have_content('Guest') end diff --git a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb index b483ba4c54c..6b450fa4e45 100644 --- a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb +++ b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -feature 'Projects > Members > Group member cannot leave group project', feature: true do +feature 'Projects > Members > Group member cannot leave group project' do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, namespace: group) } background do group.add_developer(user) - login_as(user) - visit namespace_project_path(project.namespace, project) + sign_in(user) + visit project_path(project) end scenario 'user does not see a "Leave project" link' do diff --git a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb index ff9b6007806..296a80a3c60 100644 --- a/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb +++ b/spec/features/projects/members/group_member_cannot_request_access_to_his_group_project_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Members > Group member cannot request access to his group project', feature: true do +feature 'Projects > Members > Group member cannot request access to his group project' do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, namespace: group) } @@ -41,7 +41,7 @@ feature 'Projects > Members > Group member cannot request access to his group pr end def login_and_visit_project_page(user) - login_as(user) - visit namespace_project_path(project.namespace, project) + sign_in(user) + visit project_path(project) end end diff --git a/spec/features/projects/members/group_members_spec.rb b/spec/features/projects/members/group_members_spec.rb index 3385e5972ff..c140fece41d 100644 --- a/spec/features/projects/members/group_members_spec.rb +++ b/spec/features/projects/members/group_members_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -feature 'Projects members', feature: true do +feature 'Projects members' do let(:user) { create(:user) } let(:developer) { create(:user) } let(:group) { create(:group, :public, :access_requestable) } - let(:project) { create(:empty_project, :public, :access_requestable, creator: user, group: group) } + let(:project) { create(:project, :public, :access_requestable, creator: user, group: group) } let(:project_invitee) { create(:project_member, project: project, invite_token: '123', invite_email: 'test1@abc.com', user: nil) } let(:group_invitee) { create(:group_member, group: group, invite_token: '123', invite_email: 'test2@abc.com', user: nil) } let(:project_requester) { create(:user) } @@ -13,13 +13,13 @@ feature 'Projects members', feature: true do background do project.team << [developer, :developer] group.add_owner(user) - login_as(user) + sign_in(user) end context 'with a group invitee' do before do group_invitee - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) end scenario 'does not appear in the project members page' do @@ -33,7 +33,7 @@ feature 'Projects members', feature: true do before do group_invitee project_invitee - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) end scenario 'shows the project invitee, the project developer, and the group owner' do @@ -54,7 +54,7 @@ feature 'Projects members', feature: true do context 'with a group requester' do before do group.request_access(group_requester) - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) end scenario 'does not appear in the project members page' do @@ -68,7 +68,7 @@ feature 'Projects members', feature: true do before do group.request_access(group_requester) project.request_access(project_requester) - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) end scenario 'shows the project requester, the project developer, and the group owner' do diff --git a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb index bdeeef57273..c8988aa63a7 100644 --- a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb +++ b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Members > Group requester cannot request access to project', feature: true, js: true do +feature 'Projects > Members > Group requester cannot request access to project', js: true do let(:user) { create(:user) } let(:owner) { create(:user) } let(:group) { create(:group, :public, :access_requestable) } @@ -8,10 +8,10 @@ feature 'Projects > Members > Group requester cannot request access to project', background do group.add_owner(owner) - login_as(user) + sign_in(user) visit group_path(group) perform_enqueued_jobs { click_link 'Request Access' } - visit namespace_project_path(project.namespace, project) + visit project_path(project) end scenario 'group requester does not see the request access / withdraw access request button' do diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb index deea34214fb..237c059e595 100644 --- a/spec/features/projects/members/list_spec.rb +++ b/spec/features/projects/members/list_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Project members list', feature: true do +feature 'Project members list' do include Select2Helper let(:user1) { create(:user, name: 'John Doe') } @@ -9,7 +9,7 @@ feature 'Project members list', feature: true do let(:project) { create(:project, namespace: group) } background do - login_as(user1) + sign_in(user1) group.add_owner(user1) end @@ -85,6 +85,6 @@ feature 'Project members list', feature: true do end def visit_members_page - visit namespace_project_settings_members_path(project.namespace, project) + visit project_settings_members_path(project) end end diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb index 1e6f15d8258..cd621b6b3ce 100644 --- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb +++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Members > Master adds member with expiration date', feature: true, js: true do +feature 'Projects > Members > Master adds member with expiration date', js: true do include Select2Helper include ActiveSupport::Testing::TimeHelpers @@ -10,13 +10,13 @@ feature 'Projects > Members > Master adds member with expiration date', feature: background do project.team << [master, :master] - login_as(master) + sign_in(master) end scenario 'expiration date is displayed in the members list' do travel_to Time.zone.parse('2016-08-06 08:00') do date = 4.days.from_now - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) page.within '.users-project-form' do select2(new_member.id, from: '#user_ids', multiple: true) @@ -34,7 +34,7 @@ feature 'Projects > Members > Master adds member with expiration date', feature: travel_to Time.zone.parse('2016-08-06 08:00') do date = 3.days.from_now project.team.add_users([new_member.id], :developer, expires_at: Date.today.to_s(:medium)) - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) page.within "#project_member_#{new_member.project_members.first.id}" do find('.js-access-expiration-date').set date.to_s(:medium) 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 143390b71cd..eb3c8034873 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -1,24 +1,24 @@ require 'spec_helper' -feature 'Projects > Members > Master manages access requests', feature: true do +feature 'Projects > Members > Master manages access requests' do let(:user) { create(:user) } let(:master) { create(:user) } - let(:project) { create(:empty_project, :public, :access_requestable) } + let(:project) { create(:project, :public, :access_requestable) } background do project.request_access(user) project.team << [master, :master] - login_as(master) + sign_in(master) end scenario 'master can see access requests' do - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) expect_visible_access_request(project, user) end scenario 'master can grant access' do - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) expect_visible_access_request(project, user) @@ -29,7 +29,7 @@ feature 'Projects > Members > Master manages access requests', feature: true do end scenario 'master can deny access' do - visit namespace_project_project_members_path(project.namespace, project) + visit project_project_members_path(project) expect_visible_access_request(project, user) diff --git a/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb index 9564347e733..04806f8fd9e 100644 --- a/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb +++ b/spec/features/projects/members/member_cannot_request_access_to_his_project_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Projects > Members > Member cannot request access to his project', feature: true do +feature 'Projects > Members > Member cannot request access to his project' do let(:member) { create(:user) } let(:project) { create(:project) } background do project.team << [member, :developer] - login_as(member) - visit namespace_project_path(project.namespace, project) + sign_in(member) + visit project_path(project) end scenario 'member does not see the request access button' do diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb index 5daa932e4e6..1bcf827d33c 100644 --- a/spec/features/projects/members/member_leaves_project_spec.rb +++ b/spec/features/projects/members/member_leaves_project_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Projects > Members > Member leaves project', feature: true do +feature 'Projects > Members > Member leaves project' do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } background do project.team << [user, :developer] - login_as(user) - visit namespace_project_path(project.namespace, project) + sign_in(user) + visit project_path(project) end scenario 'user leaves project' do diff --git a/spec/features/projects/members/owner_cannot_leave_project_spec.rb b/spec/features/projects/members/owner_cannot_leave_project_spec.rb index b26d55c5d5d..15162d01c44 100644 --- a/spec/features/projects/members/owner_cannot_leave_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_leave_project_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Projects > Members > Owner cannot leave project', feature: true do +feature 'Projects > Members > Owner cannot leave project' do let(:project) { create(:project) } background do - login_as(project.owner) - visit namespace_project_path(project.namespace, project) + sign_in(project.owner) + visit project_path(project) end scenario 'user does not see a "Leave project" link' do diff --git a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb index 4ca9272b9c1..c27925c8dc4 100644 --- a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Projects > Members > Owner cannot request access to his project', feature: true do +feature 'Projects > Members > Owner cannot request access to his project' do let(:project) { create(:project) } background do - login_as(project.owner) - visit namespace_project_path(project.namespace, project) + sign_in(project.owner) + visit project_path(project) end scenario 'owner does not see the request access button' do diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb index d428f6fcf22..afa173c59e5 100644 --- a/spec/features/projects/members/sorting_spec.rb +++ b/spec/features/projects/members/sorting_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -feature 'Projects > Members > Sorting', feature: true do +feature 'Projects > Members > Sorting' do let(:master) { create(:user, name: 'John Doe') } let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) } - let(:project) { create(:empty_project, namespace: master.namespace, creator: master) } + let(:project) { create(:project, namespace: master.namespace, creator: master) } background do create(:project_member, :developer, user: developer, project: project, created_at: 3.days.ago) - login_as(master) + sign_in(master) end scenario 'sorts alphabetically by default' do @@ -67,7 +67,7 @@ feature 'Projects > Members > Sorting', feature: true do expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending') end - scenario 'sorts by recent sign in', :redis do + scenario 'sorts by recent sign in', :clean_gitlab_redis_shared_state do visit_members_list(sort: :recent_sign_in) expect(first_member).to include(master.name) @@ -75,7 +75,7 @@ feature 'Projects > Members > Sorting', feature: true do expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in') end - scenario 'sorts by oldest sign in', :redis do + scenario 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do visit_members_list(sort: :oldest_sign_in) expect(first_member).to include(developer.name) @@ -84,7 +84,7 @@ feature 'Projects > Members > Sorting', feature: true do end def visit_members_list(sort:) - visit namespace_project_project_members_path(project.namespace.to_param, project, sort: sort) + visit project_project_members_path(project, sort: sort) end def first_member diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index ec48a4bd726..24c9f708456 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -feature 'Projects > Members > User requests access', feature: true do +feature 'Projects > Members > User requests access' do let(:user) { create(:user) } - let(:project) { create(:project, :public, :access_requestable) } + let(:project) { create(:project, :public, :access_requestable, :repository) } let(:master) { project.owner } background do - login_as(user) - visit namespace_project_path(project.namespace, project) + sign_in(user) + visit project_path(project) end scenario 'request access feature is disabled' do project.update_attributes(request_access_enabled: false) - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).not_to have_content 'Request Access' end @@ -35,7 +35,7 @@ feature 'Projects > Members > User requests access', feature: true do project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE, builds_access_level: ProjectFeature::PRIVATE, merge_requests_access_level: ProjectFeature::PRIVATE) - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_content 'Request Access' end @@ -46,10 +46,11 @@ feature 'Projects > Members > User requests access', feature: true do expect(project.requesters.exists?(user_id: user)).to be_truthy - open_project_settings_menu - click_link 'Members' + page.within('.layout-nav .nav-links') do + click_link('Members') + end - visit namespace_project_settings_members_path(project.namespace, project) + visit project_project_members_path(project) page.within('.content') do expect(page).not_to have_content(user.name) end diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb index 1370ab1c521..85d518c0cc3 100644 --- a/spec/features/projects/merge_request_button_spec.rb +++ b/spec/features/projects/merge_request_button_spec.rb @@ -1,36 +1,33 @@ require 'spec_helper' -feature 'Merge Request button', feature: true do +feature 'Merge Request button' do shared_examples 'Merge request button only shown when allowed' do let(:user) { create(:user) } - let(:project) { create(:project, :public) } - let(:forked_project) { create(:project, :public, forked_from_project: project) } + let(:project) { create(:project, :public, :repository) } + let(:forked_project) { create(:project, :public, :repository, forked_from_project: project) } context 'not logged in' do it 'does not show Create merge request button' do visit url - within("#content-body") do - expect(page).not_to have_link(label) - end + expect(page).not_to have_link(label) end end context 'logged in as developer' do before do - login_as(user) - project.team << [user, :developer] + sign_in(user) + project.add_developer(user) end it 'shows Create merge request button' do - href = new_namespace_project_merge_request_path(project.namespace, - project, - merge_request: { source_branch: 'feature', - target_branch: 'master' }) + href = project_new_merge_request_path(project, + merge_request: { source_branch: 'feature', + target_branch: 'master' }) visit url - within("#content-body") do + within('#content-body') do expect(page).to have_link(label, href: href) end end @@ -43,7 +40,7 @@ feature 'Merge Request button', feature: true do it 'does not show Create merge request button' do visit url - within("#content-body") do + within('#content-body') do expect(page).not_to have_link(label) end end @@ -52,13 +49,13 @@ feature 'Merge Request button', feature: true do context 'logged in as non-member' do before do - login_as(user) + sign_in(user) end it 'does not show Create merge request button' do visit url - within("#content-body") do + within('#content-body') do expect(page).not_to have_link(label) end end @@ -67,10 +64,9 @@ feature 'Merge Request button', feature: true do let(:user) { forked_project.owner } it 'shows Create merge request button' do - href = new_namespace_project_merge_request_path(forked_project.namespace, - forked_project, - merge_request: { source_branch: 'feature', - target_branch: 'master' }) + href = project_new_merge_request_path(forked_project, + merge_request: { source_branch: 'feature', + target_branch: 'master' }) visit fork_url @@ -85,24 +81,24 @@ feature 'Merge Request button', feature: true do context 'on branches page' do it_behaves_like 'Merge request button only shown when allowed' do let(:label) { 'Merge request' } - let(:url) { namespace_project_branches_path(project.namespace, project, search: 'feature') } - let(:fork_url) { namespace_project_branches_path(forked_project.namespace, forked_project, search: 'feature') } + let(:url) { project_branches_path(project, search: 'feature') } + let(:fork_url) { project_branches_path(forked_project, search: 'feature') } end end context 'on compare page' do it_behaves_like 'Merge request button only shown when allowed' do let(:label) { 'Create merge request' } - let(:url) { namespace_project_compare_path(project.namespace, project, from: 'master', to: 'feature') } - let(:fork_url) { namespace_project_compare_path(forked_project.namespace, forked_project, from: 'master', to: 'feature') } + let(:url) { project_compare_path(project, from: 'master', to: 'feature') } + let(:fork_url) { project_compare_path(forked_project, from: 'master', to: 'feature') } end end context 'on commits page' do it_behaves_like 'Merge request button only shown when allowed' do let(:label) { 'Create merge request' } - let(:url) { namespace_project_commits_path(project.namespace, project, 'feature') } - let(:fork_url) { namespace_project_commits_path(forked_project.namespace, forked_project, 'feature') } + let(:url) { project_commits_path(project, 'feature') } + let(:fork_url) { project_commits_path(forked_project, 'feature') } end end end diff --git a/spec/features/projects/merge_requests/list_spec.rb b/spec/features/projects/merge_requests/list_spec.rb index 7e8a796c55d..a879efef4b5 100644 --- a/spec/features/projects/merge_requests/list_spec.rb +++ b/spec/features/projects/merge_requests/list_spec.rb @@ -2,39 +2,39 @@ require 'spec_helper' feature 'Merge Requests List' do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } background do project.team << [user, :developer] - login_as(user) + sign_in(user) end scenario 'user does not see create new list button' do create(:merge_request, source_project: project) - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).not_to have_selector('.js-new-board-list') end it 'should show an empty state' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).to have_selector('.empty-state') end it 'empty state should have a create merge request button' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) - expect(page).to have_link 'New merge request', href: new_namespace_project_merge_request_path(project.namespace, project) + expect(page).to have_link 'New merge request', href: project_new_merge_request_path(project) end context 'if there are merge requests' do before do create(:merge_request, assignee: user, source_project: project) - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) end it 'should not show an empty state' do diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb index b4fc0edbde8..30de3e83fbb 100644 --- a/spec/features/projects/milestones/milestone_spec.rb +++ b/spec/features/projects/milestones/milestone_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' -feature 'Project milestone', :feature do +feature 'Project milestone' do let(:user) { create(:user) } - let(:project) { create(:empty_project, name: 'test', namespace: user.namespace) } + let(:project) { create(:project, name: 'test', namespace: user.namespace) } let(:milestone) { create(:milestone, project: project) } before do - login_as(user) + sign_in(user) end context 'when project has enabled issues' do before do - visit namespace_project_milestone_path(project.namespace, project, milestone) + visit project_milestone_path(project, milestone) end it 'shows issues tab' do @@ -38,7 +38,7 @@ feature 'Project milestone', :feature do context 'when project has disabled issues' do before do project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) - visit namespace_project_milestone_path(project.namespace, project, milestone) + visit project_milestone_path(project, milestone) end it 'hides issues tab' do @@ -68,7 +68,7 @@ feature 'Project milestone', :feature do before do create(:issue, project: project, milestone: milestone) - visit namespace_project_milestone_path(project.namespace, project, milestone) + visit project_milestone_path(project, milestone) end describe 'the collapsed sidebar' do diff --git a/spec/features/projects/milestones/milestones_sorting_spec.rb b/spec/features/projects/milestones/milestones_sorting_spec.rb index da3eaed707a..c531b81e04d 100644 --- a/spec/features/projects/milestones/milestones_sorting_spec.rb +++ b/spec/features/projects/milestones/milestones_sorting_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -feature 'Milestones sorting', :feature, :js do +feature 'Milestones sorting', :js do include SortingHelper let(:user) { create(:user) } - let(:project) { create(:empty_project, name: 'test', namespace: user.namespace) } + let(:project) { create(:project, name: 'test', namespace: user.namespace) } before do # Milestones @@ -15,11 +15,11 @@ feature 'Milestones sorting', :feature, :js do due_date: 11.days.from_now, created_at: 1.hour.ago, title: "bbb", project: project) - login_as(user) + sign_in(user) end scenario 'visit project milestones and sort by due_date_asc' do - visit namespace_project_milestones_path(project.namespace, project) + visit project_milestones_path(project) expect(page).to have_button('Due soon') diff --git a/spec/features/projects/milestones/new_spec.rb b/spec/features/projects/milestones/new_spec.rb new file mode 100644 index 00000000000..f7900210fe6 --- /dev/null +++ b/spec/features/projects/milestones/new_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +feature 'Creating a new project milestone', :js do + let(:user) { create(:user) } + let(:project) { create(:project, name: 'test', namespace: user.namespace) } + + before do + login_as(user) + visit new_project_milestone_path(project) + end + + it 'description has autocomplete' do + find('#milestone_description').native.send_keys('') + fill_in 'milestone_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end +end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index c66b9a34b86..22fb1223739 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -1,13 +1,27 @@ -require "spec_helper" +require 'spec_helper' -feature "New project", feature: true do +feature 'New project' do let(:user) { create(:admin) } before do - login_as(user) + sign_in(user) end - context "Visibility level selector" do + it 'shows "New project" page' do + visit new_project_path + + expect(page).to have_content('Project path') + expect(page).to have_content('Project name') + + expect(page).to have_link('GitHub') + expect(page).to have_link('Bitbucket') + expect(page).to have_link('GitLab.com') + expect(page).to have_link('Google Code') + expect(page).to have_button('Repo by URL') + expect(page).to have_link('GitLab export') + end + + context 'Visibility level selector' do Gitlab::VisibilityLevel.options.each do |key, level| it "sets selector to #{key}" do stub_application_setting(default_project_visibility: level) @@ -17,10 +31,10 @@ feature "New project", feature: true do expect(find_field("project_visibility_level_#{level}")).to be_checked end - it 'saves visibility level on validation error' do + it "saves visibility level #{level} on validation error" do visit new_project_path - choose(key) + choose(s_(key)) click_button('Create project') expect(find_field("project_visibility_level_#{level}")).to be_checked @@ -28,20 +42,20 @@ feature "New project", feature: true do end end - context "Namespace selector" do - context "with user namespace" do + context 'Namespace selector' do + context 'with user namespace' do before do visit new_project_path end - it "selects the user namespace" do - namespace = find("#project_namespace_id") + it 'selects the user namespace' do + namespace = find('#project_namespace_id') expect(namespace.text).to eq user.username end end - context "with group namespace" do + context 'with group namespace' do let(:group) { create(:group, :private, owner: user) } before do @@ -49,13 +63,13 @@ feature "New project", feature: true do visit new_project_path(namespace_id: group.id) end - it "selects the group namespace" do - namespace = find("#project_namespace_id option[selected]") + it 'selects the group namespace' do + namespace = find('#project_namespace_id option[selected]') expect(namespace.text).to eq group.name end - context "on validation error" do + context 'on validation error' do before do fill_in('project_path', with: 'private-group-project') choose('Internal') @@ -64,15 +78,15 @@ feature "New project", feature: true do expect(page).to have_css '.project-edit-errors .alert.alert-danger' end - it "selects the group namespace" do - namespace = find("#project_namespace_id option[selected]") + it 'selects the group namespace' do + namespace = find('#project_namespace_id option[selected]') expect(namespace.text).to eq group.name end end end - context "with subgroup namespace" do + context 'with subgroup namespace' do let(:group) { create(:group, :private, owner: user) } let(:subgroup) { create(:group, parent: group) } @@ -81,8 +95,8 @@ feature "New project", feature: true do visit new_project_path(namespace_id: subgroup.id) end - it "selects the group namespace" do - namespace = find("#project_namespace_id option[selected]") + it 'selects the group namespace' do + namespace = find('#project_namespace_id option[selected]') expect(namespace.text).to eq subgroup.full_path end @@ -94,10 +108,45 @@ feature "New project", feature: true do visit new_project_path end - it 'does not autocomplete sensitive git repo URL' do - autocomplete = find('#project_import_url')['autocomplete'] + context 'from git repository url' do + before do + first('.import_git').click + end + + it 'does not autocomplete sensitive git repo URL' do + autocomplete = find('#project_import_url')['autocomplete'] + + expect(autocomplete).to eq('off') + end + + it 'shows import instructions' do + git_import_instructions = first('.js-toggle-content') - expect(autocomplete).to eq('off') + expect(git_import_instructions).to be_visible + expect(git_import_instructions).to have_content 'Git repository URL' + end + end + + context 'from GitHub' do + before do + first('.import_github').click + end + + it 'shows import instructions' do + expect(page).to have_content('Import Projects from GitHub') + expect(current_path).to eq new_import_github_path + end + end + + context 'from Google Code' do + before do + first('.import_google_code').click + end + + it 'shows import instructions' do + expect(page).to have_content('Import projects from Google Code') + expect(current_path).to eq new_import_google_code_path + end end end end diff --git a/spec/features/projects/no_password_spec.rb b/spec/features/projects/no_password_spec.rb new file mode 100644 index 00000000000..6aff079dd39 --- /dev/null +++ b/spec/features/projects/no_password_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +feature 'No Password Alert' do + let(:project) { create(:project, :repository, namespace: user.namespace) } + + context 'with internal auth enabled' do + before do + sign_in(user) + visit project_path(project) + end + + context 'when user has a password' do + let(:user) { create(:user) } + + it 'shows no alert' do + expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you set a password on your account" + end + end + + context 'when user has password automatically set' do + let(:user) { create(:user, password_automatically_set: true) } + + it 'shows a password alert' do + expect(page).to have_content "You won't be able to pull or push project code via HTTP until you set a password on your account" + end + end + end + + context 'with internal auth disabled' do + let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') } + + before do + stub_application_setting(password_authentication_enabled?: false) + stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config]) + end + + context 'when user has no personal access tokens' do + it 'has a personal access token alert' do + gitlab_sign_in_via('saml', user, 'my-uid') + visit project_path(project) + + expect(page).to have_content "You won't be able to pull or push project code via HTTP until you create a personal access token on your account" + end + end + + context 'when user has a personal access token' do + it 'shows no alert' do + create(:personal_access_token, user: user) + gitlab_sign_in_via('saml', user, 'my-uid') + visit project_path(project) + + expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you create a personal access token on your account" + end + end + end + + context 'when user is ldap user' do + let(:user) { create(:omniauth_user, password_automatically_set: true) } + + before do + sign_in(user) + visit project_path(project) + end + + it 'shows no alert' do + expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you" + end + end +end diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb index 11793c0f303..013ed6f2e58 100644 --- a/spec/features/projects/pages_spec.rb +++ b/spec/features/projects/pages_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -feature 'Pages', feature: true do - given(:project) { create(:empty_project) } +feature 'Pages' do + given(:project) { create(:project) } given(:user) { create(:user) } given(:role) { :master } @@ -10,12 +10,12 @@ feature 'Pages', feature: true do project.team << [user, role] - login_as(user) + sign_in(user) end shared_examples 'no pages deployed' do scenario 'does not see anything to destroy' do - visit namespace_project_pages_path(project.namespace, project) + visit project_pages_path(project) expect(page).not_to have_link('Remove pages') expect(page).not_to have_text('Only the project owner can remove pages') @@ -33,7 +33,7 @@ feature 'Pages', feature: true do end scenario 'sees "Remove pages" link' do - visit namespace_project_pages_path(project.namespace, project) + visit project_pages_path(project) expect(page).to have_link('Remove pages') end @@ -49,7 +49,7 @@ feature 'Pages', feature: true do end scenario 'sees "Only the project owner can remove pages" text' do - visit namespace_project_pages_path(project.namespace, project) + visit project_pages_path(project) expect(page).to have_text('Only the project owner can remove pages') end diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 317949d6b56..605415d2af4 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -1,149 +1,268 @@ require 'spec_helper' -feature 'Pipeline Schedules', :feature do +feature 'Pipeline Schedules', :js do include PipelineSchedulesHelper - let!(:project) { create(:project) } + let!(:project) { create(:project, :repository) } let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) } let!(:pipeline) { create(:ci_pipeline, pipeline_schedule: pipeline_schedule) } let(:scope) { nil } let!(:user) { create(:user) } - before do - project.add_master(user) + context 'logged in as master' do + before do + project.add_master(user) + gitlab_sign_in(user) + end - login_as(user) - visit_page - end + describe 'GET /projects/pipeline_schedules' do + before do + visit_pipelines_schedules + end - describe 'GET /projects/pipeline_schedules' do - let(:visit_page) { visit_pipelines_schedules } + describe 'The view' do + it 'displays the required information description' do + page.within('.pipeline-schedule-table-row') do + expect(page).to have_content('pipeline schedule') + expect(find(".next-run-cell time")['data-original-title']) + .to include(pipeline_schedule.real_next_run.strftime('%b %-d, %Y')) + expect(page).to have_link('master') + expect(page).to have_link("##{pipeline.id}") + end + end - it 'avoids N + 1 queries' do - control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count + it 'creates a new scheduled pipeline' do + click_link 'New schedule' - create_list(:ci_pipeline_schedule, 2, project: project) + expect(page).to have_content('Schedule a new pipeline') + end - expect { visit_pipelines_schedules }.not_to exceed_query_limit(control_count) - end + it 'changes ownership of the pipeline' do + click_link 'Take ownership' + page.within('.pipeline-schedule-table-row') do + expect(page).not_to have_content('No owner') + expect(page).to have_link('John Doe') + end + end - describe 'The view' do - it 'displays the required information description' do - page.within('.pipeline-schedule-table-row') do - expect(page).to have_content('pipeline schedule') - expect(page).to have_content(pipeline_schedule.real_next_run.strftime('%b %d, %Y')) - expect(page).to have_link('master') - expect(page).to have_link("##{pipeline.id}") + it 'edits the pipeline' do + page.within('.pipeline-schedule-table-row') do + click_link 'Edit' + end + + expect(page).to have_content('Edit Pipeline Schedule') end - end - it 'creates a new scheduled pipeline' do - click_link 'New schedule' + it 'deletes the pipeline' do + click_link 'Delete' - expect(page).to have_content('Schedule a new pipeline') + expect(page).not_to have_css(".pipeline-schedule-table-row") + end end - it 'changes ownership of the pipeline' do - click_link 'Take ownership' - page.within('.pipeline-schedule-table-row') do - expect(page).not_to have_content('No owner') - expect(page).to have_link('John Doe') + context 'when ref is nil' do + before do + pipeline_schedule.update_attribute(:ref, nil) + visit_pipelines_schedules + end + + it 'shows a list of the pipeline schedules with empty ref column' do + expect(first('.branch-name-cell').text).to eq('') end end - it 'edits the pipeline' do - page.within('.pipeline-schedule-table-row') do - click_link 'Edit' + context 'when ref is empty' do + before do + pipeline_schedule.update_attribute(:ref, '') + visit_pipelines_schedules end - expect(page).to have_content('Edit Pipeline Schedule') + it 'shows a list of the pipeline schedules with empty ref column' do + expect(first('.branch-name-cell').text).to eq('') + end end + end - it 'deletes the pipeline' do - click_link 'Delete' + describe 'POST /projects/pipeline_schedules/new' do + before do + visit_new_pipeline_schedule + end - expect(page).not_to have_content('pipeline schedule') + it 'sets defaults for timezone and target branch' do + expect(page).to have_button('master') + expect(page).to have_button('UTC') + end + + it 'it creates a new scheduled pipeline' do + fill_in_schedule_form + save_pipeline_schedule + + expect(page).to have_content('my fancy description') + end + + it 'it prevents an invalid form from being submitted' do + save_pipeline_schedule + + expect(page).to have_content('This field is required') end end - context 'when ref is nil' do + describe 'PATCH /projects/pipelines_schedules/:id/edit' do before do - pipeline_schedule.update_attribute(:ref, nil) - visit_pipelines_schedules + edit_pipeline_schedule end - it 'shows a list of the pipeline schedules with empty ref column' do - expect(first('.branch-name-cell').text).to eq('') + it 'it displays existing properties' do + description = find_field('schedule_description').value + expect(description).to eq('pipeline schedule') + expect(page).to have_button('master') + expect(page).to have_button('UTC') end - end - end - describe 'POST /projects/pipeline_schedules/new', js: true do - let(:visit_page) { visit_new_pipeline_schedule } + it 'edits the scheduled pipeline' do + fill_in 'schedule_description', with: 'my brand new description' - it 'sets defaults for timezone and target branch' do - expect(page).to have_button('master') - expect(page).to have_button('UTC') - end + save_pipeline_schedule + + expect(page).to have_content('my brand new description') + end + + context 'when ref is nil' do + before do + pipeline_schedule.update_attribute(:ref, nil) + edit_pipeline_schedule + end + + it 'shows the pipeline schedule with default ref' do + page.within('.js-target-branch-dropdown') do + expect(first('.dropdown-toggle-text').text).to eq('master') + end + end + end - it 'it creates a new scheduled pipeline' do - fill_in_schedule_form - save_pipeline_schedule + context 'when ref is empty' do + before do + pipeline_schedule.update_attribute(:ref, '') + edit_pipeline_schedule + end - expect(page).to have_content('my fancy description') + it 'shows the pipeline schedule with default ref' do + page.within('.js-target-branch-dropdown') do + expect(first('.dropdown-toggle-text').text).to eq('master') + end + end + end end - it 'it prevents an invalid form from being submitted' do - save_pipeline_schedule + context 'when user creates a new pipeline schedule with variables' do + background do + visit_pipelines_schedules + click_link 'New schedule' + fill_in_schedule_form + all('[name="schedule[variables_attributes][][key]"]')[0].set('AAA') + all('[name="schedule[variables_attributes][][value]"]')[0].set('AAA123') + all('[name="schedule[variables_attributes][][key]"]')[1].set('BBB') + all('[name="schedule[variables_attributes][][value]"]')[1].set('BBB123') + save_pipeline_schedule + end - expect(page).to have_content('This field is required') + scenario 'user sees the new variable in edit window' do + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + page.within('.pipeline-variable-list') do + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('AAA') + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('AAA123') + expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-key-input").value).to eq('BBB') + expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-value-input").value).to eq('BBB123') + end + end end - end - describe 'PATCH /projects/pipelines_schedules/:id/edit', js: true do - let(:visit_page) do - edit_pipeline_schedule + context 'when user edits a variable of a pipeline schedule' do + background do + create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule| + create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule) + end + + visit_pipelines_schedules + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + all('[name="schedule[variables_attributes][][key]"]')[0].set('foo') + all('[name="schedule[variables_attributes][][value]"]')[0].set('bar') + click_button 'Save pipeline schedule' + end + + scenario 'user sees the updated variable in edit window' do + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + page.within('.pipeline-variable-list') do + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('foo') + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('bar') + end + end end - it 'it displays existing properties' do - description = find_field('schedule_description').value - expect(description).to eq('pipeline schedule') - expect(page).to have_button('master') - expect(page).to have_button('UTC') + context 'when user removes a variable of a pipeline schedule' do + background do + create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule| + create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule) + end + + visit_pipelines_schedules + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + find('.pipeline-variable-list .pipeline-variable-row-remove-button').click + click_button 'Save pipeline schedule' + end + + scenario 'user does not see the removed variable in edit window' do + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + page.within('.pipeline-variable-list') do + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('') + expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('') + end + end end + end - it 'edits the scheduled pipeline' do - fill_in 'schedule_description', with: 'my brand new description' + context 'logged in as non-member' do + before do + gitlab_sign_in(user) + end - save_pipeline_schedule + describe 'GET /projects/pipeline_schedules' do + before do + visit_pipelines_schedules + end - expect(page).to have_content('my brand new description') + describe 'The view' do + it 'does not show create schedule button' do + expect(page).not_to have_link('New schedule') + end + end end + end - context 'when ref is nil' do + context 'not logged in' do + describe 'GET /projects/pipeline_schedules' do before do - pipeline_schedule.update_attribute(:ref, nil) - edit_pipeline_schedule + visit_pipelines_schedules end - it 'shows the pipeline schedule with default ref' do - page.within('.git-revision-dropdown-toggle') do - expect(first('.dropdown-toggle-text').text).to eq('master') + describe 'The view' do + it 'does not show create schedule button' do + expect(page).not_to have_link('New schedule') end end end end def visit_new_pipeline_schedule - visit new_namespace_project_pipeline_schedule_path(project.namespace, project, pipeline_schedule) + visit new_project_pipeline_schedule_path(project, pipeline_schedule) end def edit_pipeline_schedule - visit edit_namespace_project_pipeline_schedule_path(project.namespace, project, pipeline_schedule) + visit edit_project_pipeline_schedule_path(project, pipeline_schedule) end def visit_pipelines_schedules - visit namespace_project_pipeline_schedules_path(project.namespace, project, scope: scope) + visit project_pipeline_schedules_path(project, scope: scope) end def select_timezone diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 36a3ddca6ef..acbc5b046e6 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -1,13 +1,11 @@ require 'spec_helper' -describe 'Pipeline', :feature, :js do - include GitlabRoutingHelper - - let(:project) { create(:empty_project) } +describe 'Pipeline', :js do + let(:project) { create(:project) } let(:user) { create(:user) } before do - login_as(user) + sign_in(user) project.team << [user, :developer] end @@ -44,10 +42,12 @@ describe 'Pipeline', :feature, :js do describe 'GET /:project/pipelines/:id' do include_context 'pipeline builds' - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user) } - before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) } + before do + visit project_pipeline_path(project, pipeline) + end it 'shows the pipeline graph' do expect(page).to have_selector('.pipeline-visualization') @@ -164,7 +164,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_content('retried') } context 'when retrying' do - before { find('.js-retry-button').trigger('click') } + before do + find('.js-retry-button').trigger('click') + end it { expect(page).not_to have_content('Retry') } end @@ -174,7 +176,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_selector('.ci-canceled') } context 'when canceling' do - before { click_on 'Cancel running' } + before do + click_on 'Cancel running' + end it { expect(page).not_to have_content('Cancel running') } end @@ -184,11 +188,11 @@ describe 'Pipeline', :feature, :js do describe 'GET /:project/pipelines/:id/builds' do include_context 'pipeline builds' - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } before do - visit builds_namespace_project_pipeline_path(project.namespace, project, pipeline) + visit builds_project_pipeline_path(project, pipeline) end it 'shows a list of jobs' do @@ -226,7 +230,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_content('retried') } context 'when retrying' do - before { find('.js-retry-button').trigger('click') } + before do + find('.js-retry-button').trigger('click') + end it { expect(page).not_to have_content('Retry') } end @@ -236,7 +242,9 @@ describe 'Pipeline', :feature, :js do it { expect(page).not_to have_selector('.ci-canceled') } context 'when canceling' do - before { click_on 'Cancel running' } + before do + click_on 'Cancel running' + end it { expect(page).not_to have_content('Cancel running') } end @@ -254,9 +262,9 @@ describe 'Pipeline', :feature, :js do end describe 'GET /:project/pipelines/:id/failures' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } - let(:pipeline_failures_page) { failures_namespace_project_pipeline_path(project.namespace, project, pipeline) } + let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) } let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) } context 'with failed build' do diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 05c2bf350f1..f7b40cb1820 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -describe 'Pipelines', :feature, :js do - let(:project) { create(:empty_project) } +describe 'Pipelines', :js do + let(:project) { create(:project) } context 'when user is logged in' do let(:user) { create(:user) } before do - login_as(user) + sign_in(user) project.team << [user, :developer] end describe 'GET /:project/pipelines' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let!(:pipeline) do create( @@ -51,7 +51,7 @@ describe 'Pipelines', :feature, :js do context 'header tabs' do before do - visit namespace_project_pipelines_path(project.namespace, project) + visit project_pipelines_path(project) wait_for_requests end @@ -149,7 +149,9 @@ describe 'Pipelines', :feature, :js do create(:ci_pipeline, :invalid, project: project) end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it 'contains badge that indicates errors' do expect(page).to have_content 'yaml invalid' @@ -171,10 +173,12 @@ describe 'Pipelines', :feature, :js do commands: 'test') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it 'has a dropdown with play button' do - expect(page).to have_selector('.dropdown-toggle.btn.btn-default .icon-play') + expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play') end it 'has link to the manual action' do @@ -204,7 +208,9 @@ describe 'Pipelines', :feature, :js do stage: 'test') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it 'is cancelable' do expect(page).to have_selector('.js-pipelines-cancel-button') @@ -215,7 +221,9 @@ describe 'Pipelines', :feature, :js do end context 'when canceling' do - before { find('.js-pipelines-cancel-button').trigger('click') } + before do + find('.js-pipelines-cancel-button').trigger('click') + end it 'indicates that pipeline was canceled' do expect(page).not_to have_selector('.js-pipelines-cancel-button') @@ -255,7 +263,9 @@ describe 'Pipelines', :feature, :js do stage: 'test') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it 'has artifats' do expect(page).to have_selector('.build-artifacts') @@ -284,7 +294,9 @@ describe 'Pipelines', :feature, :js do stage: 'test') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it { expect(page).not_to have_selector('.build-artifacts') } end @@ -297,7 +309,9 @@ describe 'Pipelines', :feature, :js do stage: 'test') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it { expect(page).not_to have_selector('.build-artifacts') } end @@ -310,7 +324,9 @@ describe 'Pipelines', :feature, :js do name: 'build') end - before { visit_project_pipelines } + before do + visit_project_pipelines + end it 'should render a mini pipeline graph' do expect(page).to have_selector('.js-mini-pipeline-graph') @@ -353,14 +369,14 @@ describe 'Pipelines', :feature, :js do end it 'should render pagination' do - visit namespace_project_pipelines_path(project.namespace, project) + visit project_pipelines_path(project) wait_for_requests expect(page).to have_selector('.gl-pagination') end it 'should render second page of pipelines' do - visit namespace_project_pipelines_path(project.namespace, project, page: '2') + visit project_pipelines_path(project, page: '2') wait_for_requests expect(page).to have_selector('.gl-pagination .page', count: 2) @@ -369,7 +385,7 @@ describe 'Pipelines', :feature, :js do end describe 'GET /:project/pipelines/show' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:pipeline) do create(:ci_empty_pipeline, @@ -389,7 +405,7 @@ describe 'Pipelines', :feature, :js do create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) - visit namespace_project_pipeline_path(project.namespace, project, pipeline) + visit project_pipeline_path(project, pipeline) wait_for_requests end @@ -421,10 +437,10 @@ describe 'Pipelines', :feature, :js do end describe 'POST /:project/pipelines' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do - visit new_namespace_project_pipeline_path(project.namespace, project) + visit new_project_pipeline_path(project) end context 'for valid commit', js: true do @@ -437,7 +453,9 @@ describe 'Pipelines', :feature, :js do end context 'with gitlab-ci.yml' do - before { stub_ci_pipeline_to_return_yaml_file } + before do + stub_ci_pipeline_to_return_yaml_file + end it 'creates a new pipeline' do expect { click_on 'Create pipeline' } @@ -448,7 +466,9 @@ describe 'Pipelines', :feature, :js do end context 'without gitlab-ci.yml' do - before { click_on 'Create pipeline' } + before do + click_on 'Create pipeline' + end it { expect(page).to have_content('Missing .gitlab-ci.yml file') } end @@ -456,10 +476,10 @@ describe 'Pipelines', :feature, :js do end describe 'Create pipelines' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do - visit new_namespace_project_pipeline_path(project.namespace, project) + visit new_project_pipeline_path(project) end describe 'new pipeline page' do @@ -488,25 +508,25 @@ describe 'Pipelines', :feature, :js do context 'when user is not logged in' do before do - visit namespace_project_pipelines_path(project.namespace, project) + visit project_pipelines_path(project) end context 'when project is public' do - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } it { expect(page).to have_content 'Build with confidence' } it { expect(page).to have_http_status(:success) } end context 'when project is private' do - let(:project) { create(:project, :private) } + let(:project) { create(:project, :private, :repository) } it { expect(page).to have_content 'You need to sign in' } end end def visit_project_pipelines(**query) - visit namespace_project_pipelines_path(project.namespace, project, query) + visit project_pipelines_path(project, query) wait_for_requests end end diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb index 11dcab4d737..59603310f51 100644 --- a/spec/features/projects/project_settings_spec.rb +++ b/spec/features/projects/project_settings_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' -describe 'Edit Project Settings', feature: true do +describe 'Edit Project Settings' do include Select2Helper let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace, path: 'gitlab', name: 'sample') } + let(:project) { create(:project, namespace: user.namespace, path: 'gitlab', name: 'sample') } before do - login_as(user) + sign_in(user) end describe 'Project settings section', js: true do it 'shows errors for invalid project name' do - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) fill_in 'project_name_edit', with: 'foo&bar' click_button 'Save changes' expect(page).to have_field 'project_name_edit', with: 'foo&bar' @@ -21,7 +21,7 @@ describe 'Edit Project Settings', feature: true do end it 'shows a successful notice when the project is updated' do - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) fill_in 'project_name_edit', with: 'hello world' click_button 'Save changes' expect(page).to have_content "Project 'hello world' was successfully updated." @@ -55,11 +55,15 @@ describe 'Edit Project Settings', feature: true do end context 'when changing project path' do - # Not using empty project because we need a repo to exist - let(:project) { create(:project, namespace: user.namespace, name: 'gitlabhq') } + let(:project) { create(:project, :repository, namespace: user.namespace, name: 'gitlabhq') } - before(:context) { TestEnv.clean_test_path } - after(:example) { TestEnv.clean_test_path } + before(:context) do + TestEnv.clean_test_path + end + + after(:example) do + TestEnv.clean_test_path + end specify 'the project is accessible via the new path' do rename_project(project, path: 'bar') @@ -70,7 +74,7 @@ describe 'Edit Project Settings', feature: true do end specify 'the project is accessible via a redirect from the old path' do - old_path = namespace_project_path(project.namespace, project) + old_path = project_path(project) rename_project(project, path: 'bar') new_path = namespace_project_path(project.namespace, 'bar') visit old_path @@ -80,9 +84,9 @@ describe 'Edit Project Settings', feature: true do context 'and a new project is added with the same path' do it 'overrides the redirect' do - old_path = namespace_project_path(project.namespace, project) + old_path = project_path(project) rename_project(project, path: 'bar') - new_project = create(:empty_project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') + new_project = create(:project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') visit old_path expect(current_path).to eq(old_path) expect(find('h1.title')).to have_content(new_project.name) @@ -92,13 +96,20 @@ describe 'Edit Project Settings', feature: true do end describe 'Transfer project section', js: true do - # Not using empty project because we need a repo to exist - let!(:project) { create(:project, namespace: user.namespace, name: 'gitlabhq') } + let!(:project) { create(:project, :repository, namespace: user.namespace, name: 'gitlabhq') } let!(:group) { create(:group) } - before(:context) { TestEnv.clean_test_path } - before(:example) { group.add_owner(user) } - after(:example) { TestEnv.clean_test_path } + before(:context) do + TestEnv.clean_test_path + end + + before(:example) do + group.add_owner(user) + end + + after(:example) do + TestEnv.clean_test_path + end specify 'the project is accessible via the new path' do transfer_project(project, group) @@ -109,7 +120,7 @@ describe 'Edit Project Settings', feature: true do end specify 'the project is accessible via a redirect from the old path' do - old_path = namespace_project_path(project.namespace, project) + old_path = project_path(project) transfer_project(project, group) new_path = namespace_project_path(group, project) visit old_path @@ -119,9 +130,9 @@ describe 'Edit Project Settings', feature: true do context 'and a new project is added with the same path' do it 'overrides the redirect' do - old_path = namespace_project_path(project.namespace, project) + old_path = project_path(project) transfer_project(project, group) - new_project = create(:empty_project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') + new_project = create(:project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') visit old_path expect(current_path).to eq(old_path) expect(find('h1.title')).to have_content(new_project.name) @@ -131,7 +142,7 @@ describe 'Edit Project Settings', feature: true do end def rename_project(project, name: nil, path: nil) - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) fill_in('project_name', with: name) if name fill_in('Path', with: path) if path click_button('Rename project') @@ -140,7 +151,7 @@ def rename_project(project, name: nil, path: nil) end def transfer_project(project, namespace) - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) select2(namespace.id, from: '#new_namespace_id') click_button('Transfer project') confirm_transfer_modal diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb index 04414490571..f0a23729220 100644 --- a/spec/features/projects/ref_switcher_spec.rb +++ b/spec/features/projects/ref_switcher_spec.rb @@ -1,13 +1,13 @@ require 'rails_helper' -feature 'Ref switcher', feature: true, js: true do +feature 'Ref switcher', js: true do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :repository) } before do project.team << [user, :master] - login_as(user) - visit namespace_project_tree_path(project.namespace, project, 'master') + sign_in(user) + visit project_tree_path(project, 'master') end it 'allow user to change ref by enter key' do @@ -19,14 +19,14 @@ feature 'Ref switcher', feature: true, js: true do input.set 'binary' wait_for_requests - expect(find('.dropdown-content ul')).to have_selector('li', count: 6) + expect(find('.dropdown-content ul')).to have_selector('li', count: 7) page.within '.dropdown-content ul' do input.native.send_keys :enter end end - expect(page).to have_title 'binary-encoding' + expect(page).to have_title 'add-pdf-text-binary' end it "user selects ref with special characters" do diff --git a/spec/features/projects/services/jira_service_spec.rb b/spec/features/projects/services/jira_service_spec.rb index c96d87e5708..65e3a487d4b 100644 --- a/spec/features/projects/services/jira_service_spec.rb +++ b/spec/features/projects/services/jira_service_spec.rb @@ -1,18 +1,17 @@ require 'spec_helper' -feature 'Setup Jira service', :feature, :js do +feature 'Setup Jira service', :js do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:service) { project.create_jira_service } let(:url) { 'http://jira.example.com' } - let(:project_url) { 'http://username:password@jira.example.com/rest/api/2/project/GitLabProject' } + let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' } def fill_form(active = true) check 'Active' if active fill_in 'service_url', with: url - fill_in 'service_project_key', with: 'GitLabProject' fill_in 'service_username', with: 'username' fill_in 'service_password', with: 'password' fill_in 'service_jira_issue_transition_id', with: '25' @@ -20,33 +19,28 @@ feature 'Setup Jira service', :feature, :js do before do project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_settings_integrations_path(project.namespace, project) + visit project_settings_integrations_path(project) end describe 'user sets and activates Jira Service' do context 'when Jira connection test succeeds' do - before do - WebMock.stub_request(:get, project_url) - end - it 'activates the JIRA service' do + server_info = { key: 'value' }.to_json + WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info) + click_link('JIRA') fill_form click_button('Test settings and save changes') wait_for_requests expect(page).to have_content('JIRA activated.') - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) end end context 'when Jira connection test fails' do - before do - WebMock.stub_request(:get, project_url).to_return(status: 401) - end - it 'shows errors when some required fields are not filled in' do click_link('JIRA') @@ -60,19 +54,22 @@ feature 'Setup Jira service', :feature, :js do end it 'activates the JIRA service' do + WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password)) + .to_raise(JIRA::HTTPError.new(double(message: 'message'))) + click_link('JIRA') fill_form click_button('Test settings and save changes') wait_for_requests - expect(find('.flash-container-page')).to have_content 'Test failed.' + expect(find('.flash-container-page')).to have_content 'Test failed. message' expect(find('.flash-container-page')).to have_content 'Save anyway' find('.flash-alert .flash-action').trigger('click') wait_for_requests expect(page).to have_content('JIRA activated.') - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) end end end @@ -85,7 +82,7 @@ feature 'Setup Jira service', :feature, :js do click_button('Save changes') expect(page).to have_content('JIRA settings saved, but not activated.') - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) end end end diff --git a/spec/features/projects/services/mattermost_slash_command_spec.rb b/spec/features/projects/services/mattermost_slash_command_spec.rb index 1fe82222e59..95d5e8b14b9 100644 --- a/spec/features/projects/services/mattermost_slash_command_spec.rb +++ b/spec/features/projects/services/mattermost_slash_command_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -feature 'Setup Mattermost slash commands', :feature, :js do +feature 'Setup Mattermost slash commands', :js do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:service) { project.create_mattermost_slash_commands_service } let(:mattermost_enabled) { true } before do stub_mattermost_setting(enabled: mattermost_enabled) project.team << [user, :master] - login_as(user) - visit edit_namespace_project_service_path(project.namespace, project, service) + sign_in(user) + visit edit_project_service_path(project, service) end describe 'user visits the mattermost slash command config page' do @@ -30,7 +30,7 @@ feature 'Setup Mattermost slash commands', :feature, :js do fill_in 'service_token', with: token click_on 'Save changes' - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) expect(page).to have_content('Mattermost slash commands settings saved, but not activated.') end @@ -41,7 +41,7 @@ feature 'Setup Mattermost slash commands', :feature, :js do check 'service_active' click_on 'Save changes' - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) expect(page).to have_content('Mattermost slash commands activated.') end @@ -159,7 +159,7 @@ feature 'Setup Mattermost slash commands', :feature, :js do it 'shows the correct trigger url' do value = find_field('request_url').value - expect(value).to match("api/v3/projects/#{project.id}/services/mattermost_slash_commands/trigger") + expect(value).to match("api/v4/projects/#{project.id}/services/mattermost_slash_commands/trigger") end it 'shows a token placeholder' do diff --git a/spec/features/projects/services/slack_service_spec.rb b/spec/features/projects/services/slack_service_spec.rb index c0a4a1e4bf5..c10ec5e2987 100644 --- a/spec/features/projects/services/slack_service_spec.rb +++ b/spec/features/projects/services/slack_service_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Slack service > Setup events', feature: true do +feature 'Projects > Slack service > Setup events' do let(:user) { create(:user) } let(:service) { SlackService.new } let(:project) { create(:project, slack_service: service) } @@ -9,11 +9,11 @@ feature 'Projects > Slack service > Setup events', feature: true do service.fields service.update_attributes(push_channel: 1, issue_channel: 2, merge_request_channel: 3, note_channel: 4, tag_push_channel: 5, pipeline_channel: 6, wiki_page_channel: 7) project.team << [user, :master] - login_as(user) + sign_in(user) end scenario 'user can filter events by channel' do - visit edit_namespace_project_service_path(project.namespace, project, service) + visit edit_project_service_path(project, service) expect(page.find_field("service_push_channel").value).to have_content '1' expect(page.find_field("service_issue_channel").value).to have_content '2' diff --git a/spec/features/projects/services/slack_slash_command_spec.rb b/spec/features/projects/services/slack_slash_command_spec.rb index f53b820c460..a8baf126269 100644 --- a/spec/features/projects/services/slack_slash_command_spec.rb +++ b/spec/features/projects/services/slack_slash_command_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -feature 'Slack slash commands', feature: true do +feature 'Slack slash commands' do given(:user) { create(:user) } given(:project) { create(:project) } given(:service) { project.create_slack_slash_commands_service } background do project.team << [user, :master] - login_as(user) - visit edit_namespace_project_service_path(project.namespace, project, service) + sign_in(user) + visit edit_project_service_path(project, service) end it 'shows a token placeholder' do @@ -25,7 +25,7 @@ feature 'Slack slash commands', feature: true do fill_in 'service_token', with: 'token' click_on 'Save' - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) expect(page).to have_content('Slack slash commands settings saved, but not activated.') end @@ -34,12 +34,12 @@ feature 'Slack slash commands', feature: true do check 'service_active' click_on 'Save' - expect(current_path).to eq(namespace_project_settings_integrations_path(project.namespace, project)) + expect(current_path).to eq(project_settings_integrations_path(project)) expect(page).to have_content('Slack slash commands activated.') end it 'shows the correct trigger url' do value = find_field('url').value - expect(value).to match("api/v3/projects/#{project.id}/services/slack_slash_commands/trigger") + expect(value).to match("api/v4/projects/#{project.id}/services/slack_slash_commands/trigger") end end diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb index fbaea14a2be..d932c4e4d9a 100644 --- a/spec/features/projects/settings/integration_settings_spec.rb +++ b/spec/features/projects/settings/integration_settings_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Integration settings', feature: true do - let(:project) { create(:empty_project) } +feature 'Integration settings' do + let(:project) { create(:project) } let(:user) { create(:user) } let(:role) { :developer } - let(:integrations_path) { namespace_project_settings_integrations_path(project.namespace, project) } + let(:integrations_path) { project_settings_integrations_path(project) } background do - login_as(user) + sign_in(user) project.team << [user, role] end @@ -36,14 +36,14 @@ feature 'Integration settings', feature: true do expect(page.status_code).to eq(200) expect(page).to have_content(hook.url) expect(page).to have_content('SSL Verification: enabled') - expect(page).to have_content('Push Events') - expect(page).to have_content('Tag Push Events') - expect(page).to have_content('Issues Events') - expect(page).to have_content('Confidential Issues Events') - expect(page).to have_content('Note Events') - expect(page).to have_content('Merge Requests Events') - expect(page).to have_content('Pipeline Events') - expect(page).to have_content('Wiki Page Events') + expect(page).to have_content('Push events') + expect(page).to have_content('Tag push events') + expect(page).to have_content('Issues events') + expect(page).to have_content('Confidential issues events') + expect(page).to have_content('Note events') + expect(page).to have_content('Merge requests events') + expect(page).to have_content('Pipeline events') + expect(page).to have_content('Wiki page events') end scenario 'create webhook' do @@ -58,8 +58,8 @@ feature 'Integration settings', feature: true do expect(page).to have_content(url) expect(page).to have_content('SSL Verification: enabled') - expect(page).to have_content('Push Events') - expect(page).to have_content('Tag Push Events') + expect(page).to have_content('Push events') + expect(page).to have_content('Tag push events') expect(page).to have_content('Job events') end @@ -76,11 +76,12 @@ feature 'Integration settings', feature: true do expect(page).to have_content(url) end - scenario 'test existing webhook' do + scenario 'test existing webhook', js: true do WebMock.stub_request(:post, hook.url) visit integrations_path - click_link 'Test' + find('.hook-test-button.dropdown').click + click_link 'Push events' expect(current_path).to eq(integrations_path) end @@ -109,7 +110,7 @@ feature 'Integration settings', feature: true do scenario 'show list of hook logs' do hook_log - visit edit_namespace_project_hook_path(project.namespace, project, hook) + visit edit_project_hook_path(project, hook) expect(page).to have_content('Recent Deliveries') expect(page).to have_content(hook_log.url) @@ -117,7 +118,7 @@ feature 'Integration settings', feature: true do scenario 'show hook log details' do hook_log - visit edit_namespace_project_hook_path(project.namespace, project, hook) + visit edit_project_hook_path(project, hook) click_link 'View details' expect(page).to have_content("POST #{hook_log.url}") @@ -129,11 +130,11 @@ feature 'Integration settings', feature: true do WebMock.stub_request(:post, hook.url) hook_log - visit edit_namespace_project_hook_path(project.namespace, project, hook) + visit edit_project_hook_path(project, hook) click_link 'View details' click_link 'Resend Request' - expect(current_path).to eq(edit_namespace_project_hook_path(project.namespace, project, hook)) + expect(current_path).to eq(edit_project_hook_path(project, hook)) end end end diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb index 321af416c91..a011fab2333 100644 --- a/spec/features/projects/settings/merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -1,14 +1,12 @@ require 'spec_helper' -feature 'Project settings > Merge Requests', feature: true, js: true do - include GitlabRoutingHelper - - let(:project) { create(:empty_project, :public) } +feature 'Project settings > Merge Requests', :js do + let(:project) { create(:project, :public) } let(:user) { create(:user) } background do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'when Merge Request and Pipelines are initially enabled' do diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb index 035c57eaa47..232d796a200 100644 --- a/spec/features/projects/settings/pipelines_settings_spec.rb +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -1,16 +1,14 @@ require 'spec_helper' -feature "Pipelines settings", feature: true do - include GitlabRoutingHelper - - let(:project) { create(:empty_project) } +feature "Pipelines settings" do + let(:project) { create(:project) } let(:user) { create(:user) } let(:role) { :developer } background do - login_as(user) + sign_in(user) project.team << [user, role] - visit namespace_project_pipelines_settings_path(project.namespace, project) + visit project_pipelines_settings_path(project) end context 'for developer' do diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb new file mode 100644 index 00000000000..15180d4b498 --- /dev/null +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -0,0 +1,95 @@ +require 'spec_helper' + +feature 'Repository settings' do + let(:project) { create(:project_empty_repo) } + let(:user) { create(:user) } + let(:role) { :developer } + + background do + project.team << [user, role] + sign_in(user) + end + + context 'for developer' do + given(:role) { :developer } + + scenario 'is not allowed to view' do + visit project_settings_repository_path(project) + + expect(page.status_code).to eq(404) + end + end + + context 'for master' do + given(:role) { :master } + + context 'Deploy Keys', js: true do + let(:private_deploy_key) { create(:deploy_key, title: 'private_deploy_key', public: false) } + let(:public_deploy_key) { create(:another_deploy_key, title: 'public_deploy_key', public: true) } + let(:new_ssh_key) { attributes_for(:key)[:key] } + + scenario 'get list of keys' do + project.deploy_keys << private_deploy_key + project.deploy_keys << public_deploy_key + + visit project_settings_repository_path(project) + + expect(page.status_code).to eq(200) + expect(page).to have_content('private_deploy_key') + expect(page).to have_content('public_deploy_key') + end + + scenario 'add a new deploy key' do + visit project_settings_repository_path(project) + + fill_in 'deploy_key_title', with: 'new_deploy_key' + fill_in 'deploy_key_key', with: new_ssh_key + check 'deploy_key_can_push' + click_button 'Add key' + + expect(page).to have_content('new_deploy_key') + expect(page).to have_content('Write access allowed') + end + + scenario 'edit an existing deploy key' do + project.deploy_keys << private_deploy_key + visit project_settings_repository_path(project) + + find('li', text: private_deploy_key.title).click_link('Edit') + + fill_in 'deploy_key_title', with: 'updated_deploy_key' + check 'deploy_key_can_push' + click_button 'Save changes' + + expect(page).to have_content('updated_deploy_key') + expect(page).to have_content('Write access allowed') + end + + scenario 'edit a deploy key from projects user has access to' do + project2 = create(:project_empty_repo) + project2.team << [user, role] + project2.deploy_keys << private_deploy_key + + visit project_settings_repository_path(project) + + find('li', text: private_deploy_key.title).click_link('Edit') + + fill_in 'deploy_key_title', with: 'updated_deploy_key' + check 'deploy_key_can_push' + click_button 'Save changes' + + expect(page).to have_content('updated_deploy_key') + expect(page).to have_content('Write access allowed') + end + + scenario 'remove an existing deploy key' do + project.deploy_keys << private_deploy_key + visit project_settings_repository_path(project) + + find('li', text: private_deploy_key.title).click_button('Remove') + + expect(page).not_to have_content(private_deploy_key.title) + end + end + end +end diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb index fac4506bdf6..1756c7d00fe 100644 --- a/spec/features/projects/settings/visibility_settings_spec.rb +++ b/spec/features/projects/settings/visibility_settings_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Visibility settings', feature: true, js: true do +feature 'Visibility settings', js: true do let(:user) { create(:user) } let(:project) { create(:project, namespace: user.namespace, visibility_level: 20) } context 'as owner' do before do - login_as(user) - visit edit_namespace_project_path(project.namespace, project) + sign_in(user) + visit edit_project_path(project) end scenario 'project visibility select is available' do @@ -32,8 +32,8 @@ feature 'Visibility settings', feature: true, js: true do before do project.team << [master_user, :master] - login_as(master_user) - visit edit_namespace_project_path(project.namespace, project) + sign_in(master_user) + visit edit_project_path(project) end scenario 'project visibility is locked' do diff --git a/spec/features/projects/shortcuts_spec.rb b/spec/features/projects/shortcuts_spec.rb index 54aa9c66a08..bf18c444c3d 100644 --- a/spec/features/projects/shortcuts_spec.rb +++ b/spec/features/projects/shortcuts_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -feature 'Project shortcuts', feature: true do +feature 'Project shortcuts' do let(:project) { create(:project, name: 'Victorialand') } let(:user) { create(:user) } describe 'On a project', js: true do before do project.team << [user, :master] - login_as user - visit namespace_project_path(project.namespace, project) + sign_in user + visit project_path(project) end describe 'pressing "i"' do diff --git a/spec/features/projects/show_project_spec.rb b/spec/features/projects/show_project_spec.rb new file mode 100644 index 00000000000..1bc6fae9e7f --- /dev/null +++ b/spec/features/projects/show_project_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'Project show page', feature: true do + context 'when project pending delete' do + let(:project) { create(:project, :empty_repo, pending_delete: true) } + + before do + sign_in(project.owner) + end + + it 'shows error message if deletion for project fails' do + project.update_attributes(delete_error: "Something went wrong", pending_delete: false) + + visit project_path(project) + + expect(page).to have_selector('.project-deletion-failed-message') + expect(page).to have_content("This project was scheduled for deletion, but failed with the following message: #{project.delete_error}") + end + end +end diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb new file mode 100644 index 00000000000..3e79dba3f19 --- /dev/null +++ b/spec/features/projects/snippets/create_snippet_spec.rb @@ -0,0 +1,86 @@ +require 'rails_helper' + +feature 'Create Snippet', :js do + include DropzoneHelper + + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + + def fill_form + fill_in 'project_snippet_title', with: 'My Snippet Title' + fill_in 'project_snippet_description', with: 'My Snippet **Description**' + page.within('.file-editor') do + find('.ace_editor').native.send_keys('Hello World!') + end + end + + context 'when a user is authenticated' do + before do + project.team << [user, :master] + sign_in(user) + + visit project_snippets_path(project) + + click_on('New snippet') + end + + it 'creates a new snippet' do + fill_form + click_button('Create snippet') + wait_for_requests + + expect(page).to have_content('My Snippet Title') + expect(page).to have_content('Hello World!') + page.within('.snippet-header .description') do + expect(page).to have_content('My Snippet Description') + expect(page).to have_selector('strong') + end + end + + it 'uploads a file when dragging into textarea' do + fill_form + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + + expect(page.find_field("project_snippet_description").value).to have_content('banana_sample') + + click_button('Create snippet') + wait_for_requests + + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/#{Regexp.escape(project.full_path) }/uploads/\h{32}/banana_sample\.gif\z}) + end + + it 'creates a snippet when all reuiqred fields are filled in after validation failing' do + fill_in 'project_snippet_title', with: 'My Snippet Title' + click_button('Create snippet') + + expect(page).to have_selector('#error_explanation') + + fill_form + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + + click_button('Create snippet') + wait_for_requests + + expect(page).to have_content('My Snippet Title') + expect(page).to have_content('Hello World!') + page.within('.snippet-header .description') do + expect(page).to have_content('My Snippet Description') + expect(page).to have_selector('strong') + end + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/#{Regexp.escape(project.full_path) }/uploads/\h{32}/banana_sample\.gif\z}) + end + end + + context 'when a user is not authenticated' do + it 'shows a public snippet on the index page but not the New snippet button' do + snippet = create(:project_snippet, :public, project: project) + + visit project_snippets_path(project) + + expect(page).to have_content(snippet.title) + expect(page).not_to have_content('New snippet') + end + end +end diff --git a/spec/features/projects/snippets/show_spec.rb b/spec/features/projects/snippets/show_spec.rb index b844e60e5d5..08dc7cf6c5b 100644 --- a/spec/features/projects/snippets/show_spec.rb +++ b/spec/features/projects/snippets/show_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Project snippet', :js, feature: true do +feature 'Project snippet', :js do let(:user) { create(:user) } let(:project) { create(:project, :repository) } let(:snippet) { create(:project_snippet, project: project, file_name: file_name, content: content) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'Ruby file' do @@ -15,7 +15,7 @@ feature 'Project snippet', :js, feature: true do let(:content) { project.repository.blob_at('master', 'files/ruby/popen.rb').data } before do - visit namespace_project_snippet_path(project.namespace, project, snippet) + visit project_snippet_path(project, snippet) wait_for_requests end @@ -46,7 +46,7 @@ feature 'Project snippet', :js, feature: true do context 'visiting directly' do before do - visit namespace_project_snippet_path(project.namespace, project, snippet) + visit project_snippet_path(project, snippet) wait_for_requests end @@ -118,7 +118,7 @@ feature 'Project snippet', :js, feature: true do context 'visiting with a line number anchor' do before do - visit namespace_project_snippet_path(project.namespace, project, snippet, anchor: 'L1') + visit project_snippet_path(project, snippet, anchor: 'L1') wait_for_requests end diff --git a/spec/features/projects/snippets_spec.rb b/spec/features/projects/snippets_spec.rb index 18689c17fe9..1cfbbb4cb62 100644 --- a/spec/features/projects/snippets_spec.rb +++ b/spec/features/projects/snippets_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -describe 'Project snippets', feature: true do +describe 'Project snippets', :js do context 'when the project has snippets' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) } let!(:other_snippet) { create(:project_snippet) } @@ -10,7 +10,7 @@ describe 'Project snippets', feature: true do before do allow(Snippet).to receive(:default_per_page).and_return(1) - visit namespace_project_snippets_path(project.namespace, project) + visit project_snippets_path(project) end it_behaves_like 'paginated snippets' @@ -18,7 +18,7 @@ describe 'Project snippets', feature: true do context 'list content' do it 'contains all project snippets' do - visit namespace_project_snippets_path(project.namespace, project) + visit project_snippets_path(project) expect(page).to have_selector('.snippet-row', count: 2) @@ -26,5 +26,19 @@ describe 'Project snippets', feature: true do expect(page).to have_content(snippets[1].title) end end + + context 'when submitting a note' do + before do + sign_in(create(:admin)) + visit project_snippet_path(project, snippets[0]) + end + + it 'should have autocomplete' do + find('#note_note').native.send_keys('') + fill_in 'note[note]', with: '@' + + expect(page).to have_selector('.atwho-view') + end + end end end diff --git a/spec/features/projects/sub_group_issuables_spec.rb b/spec/features/projects/sub_group_issuables_spec.rb index e88907b8016..aaf64d42515 100644 --- a/spec/features/projects/sub_group_issuables_spec.rb +++ b/spec/features/projects/sub_group_issuables_spec.rb @@ -1,24 +1,24 @@ require 'spec_helper' -describe 'Subgroup Issuables', :feature, :js, :nested_groups do +describe 'Subgroup Issuables', :js, :nested_groups do let!(:group) { create(:group, name: 'group') } let!(:subgroup) { create(:group, parent: group, name: 'subgroup') } - let!(:project) { create(:empty_project, namespace: subgroup, name: 'project') } + let!(:project) { create(:project, namespace: subgroup, name: 'project') } let(:user) { create(:user) } before do project.add_master(user) - login_as user + sign_in user end it 'shows the full subgroup title when issues index page is empty' do - visit namespace_project_issues_path(project.namespace.to_param, project.to_param) + visit project_issues_path(project) expect_to_have_full_subgroup_title end it 'shows the full subgroup title when merge requests index page is empty' do - visit namespace_project_merge_requests_path(project.namespace.to_param, project.to_param) + visit project_merge_requests_path(project) expect_to_have_full_subgroup_title end diff --git a/spec/features/projects/tags/download_buttons_spec.rb b/spec/features/projects/tags/download_buttons_spec.rb index dd93d25c2c6..d38a5b1324b 100644 --- a/spec/features/projects/tags/download_buttons_spec.rb +++ b/spec/features/projects/tags/download_buttons_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -feature 'Download buttons in tags page', feature: true do +feature 'Download buttons in tags page' do given(:user) { create(:user) } given(:role) { :developer } given(:status) { 'success' } given(:tag) { 'v1.0.0' } - given(:project) { create(:project) } + given(:project) { create(:project, :repository) } given(:pipeline) do create(:ci_pipeline, @@ -23,20 +23,18 @@ feature 'Download buttons in tags page', feature: true do end background do - login_as(user) + sign_in(user) project.team << [user, role] end describe 'when checking tags' do context 'with artifacts' do before do - visit namespace_project_tags_path(project.namespace, project) + visit project_tags_path(project) end scenario 'shows download artifacts button' do - href = latest_succeeded_namespace_project_artifacts_path( - project.namespace, project, "#{tag}/download", - job: 'build') + href = latest_succeeded_project_artifacts_path(project, "#{tag}/download", job: 'build') expect(page).to have_link "Download '#{build.name}'", href: href end diff --git a/spec/features/projects/tree/rss_spec.rb b/spec/features/projects/tree/rss_spec.rb index 9bf59c4139c..4f2e0a76a65 100644 --- a/spec/features/projects/tree/rss_spec.rb +++ b/spec/features/projects/tree/rss_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' feature 'Project Tree RSS' do + let(:user) { create(:user) } let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:path) { namespace_project_tree_path(project.namespace, project, :master) } + let(:path) { project_tree_path(project, :master) } context 'when signed in' do before do - user = create(:user) project.team << [user, :developer] - login_as(user) + sign_in(user) visit path end diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb new file mode 100644 index 00000000000..b7a0b72db50 --- /dev/null +++ b/spec/features/projects/user_browses_files_spec.rb @@ -0,0 +1,188 @@ +require 'spec_helper' + +describe 'User browses files' do + include DropzoneHelper + + 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(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + 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') + end + + 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') + end + + 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') + end + + it 'shows the "Browse Code" link' do + click_link('History') + + expect(page).to have_link('Browse Files') + expect(page).not_to have_link('Browse Directory') + end + + it 'redirects to the permalink URL' do + click_link('.gitignore') + click_link('Permalink') + + permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore") + + expect(current_path).to eq(permalink_path) + end + end + + context 'when browsing a specific ref' do + before do + visit(tree_path_ref_6d39438) + 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') + end + + it 'shows files from a repository with apostroph in its name', js: true do + first('.js-project-refs-dropdown').click + + page.within('.project-refs-form') do + click_link("'test'") + end + + 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...') + end + + it 'shows the code with a leading dot in the directory', js: true do + first('.js-project-refs-dropdown').click + + page.within('.project-refs-form') do + click_link('fix') + end + + 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...') + end + + it 'does not show the permalink link' do + click_link('.gitignore') + + expect(page).not_to have_link('permalink') + end + end + + context 'when browsing a file content' do + before do + visit(tree_path_root_ref) + click_link('.gitignore') + end + + it 'shows a file content', js: true do + wait_for_requests + expect(page).to have_content('*.rbc') + end + end + + context 'when browsing a raw file' do + before do + visit(project_blob_path(project, File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path))) + end + + it 'shows a raw file content' do + click_link('Open raw') + expect(source).to eq('') # Body is filled in by gitlab-workhorse + end + end + + context 'when browsing an LFS object' do + before do + allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true) + visit(project_tree_path(project, 'lfs')) + end + + it 'shows an LFS object' do + click_link('files') + click_link('lfs') + click_link('lfs_object.iso') + + expect(page).to have_content('Download (1.5 MB)') + expect(page).not_to have_content('version https://git-lfs.github.com/spec/v1') + expect(page).not_to have_content('oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897') + expect(page).not_to have_content('size 1575078') + + page.within('.content') do + expect(page).to have_content('Delete') + expect(page).to have_content('History') + expect(page).to have_content('Permalink') + expect(page).to have_content('Replace') + expect(page).not_to have_content('Annotate') + expect(page).not_to have_content('Blame') + expect(page).not_to have_content('Edit') + expect(page).to have_link('Download') + end + end + end + + context 'when previewing a file content' do + before do + visit(tree_path_root_ref) + end + + it 'shows a preview of a file content', js: true do + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Upload file') + + visit(project_blob_path(project, 'new_branch_name/logo_sample.svg')) + + expect(page).to have_css('.file-content img') + end + end +end diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb deleted file mode 100644 index 5dfdc465d7d..00000000000 --- a/spec/features/projects/user_create_dir_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'spec_helper' - -feature 'New directory creation', feature: true, js: true do - include TargetBranchHelpers - - given(:user) { create(:user) } - given(:role) { :developer } - given(:project) { create(:project) } - - background do - login_as(user) - project.team << [user, role] - visit namespace_project_tree_path(project.namespace, project, 'master') - open_new_directory_modal - fill_in 'dir_name', with: 'new_directory' - end - - def open_new_directory_modal - first('.add-to-tree').click - click_link 'New directory' - end - - def create_directory - click_button 'Create directory' - end - - context 'with default target branch' do - background do - create_directory - end - - scenario 'creates the directory in the default branch' do - expect(page).to have_content 'master' - expect(page).to have_content 'The directory has been successfully created' - expect(page).to have_content 'new_directory' - end - end - - context 'with different target branch' do - background do - select_branch('feature') - create_directory - end - - scenario 'creates the directory in the different branch' do - expect(page).to have_content 'feature' - expect(page).to have_content 'The directory has been successfully created' - end - end - - context 'with a new target branch' do - given(:new_branch_name) { 'new-feature' } - - background do - create_new_branch(new_branch_name) - create_directory - end - - scenario 'creates the directory in the new branch' do - expect(page).to have_content new_branch_name - expect(page).to have_content 'The directory has been successfully created' - end - - scenario 'redirects to the merge request' do - expect(page).to have_content 'New Merge Request' - expect(page).to have_content "From #{new_branch_name} into master" - expect(page).to have_content 'Add new directory' - expect(current_path).to eq(new_namespace_project_merge_request_path(project.namespace, project)) - end - end -end diff --git a/spec/features/projects/user_creates_directory_spec.rb b/spec/features/projects/user_creates_directory_spec.rb new file mode 100644 index 00000000000..1ba5d83eadf --- /dev/null +++ b/spec/features/projects/user_creates_directory_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +feature 'User creates a directory', js: true 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) } + 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(:user) { create(:user) } + + before do + project.team << [user, :developer] + sign_in(user) + visit project_tree_path(project, 'master') + end + + context 'with default target branch' do + before do + first('.add-to-tree').click + click_link('New directory') + end + + it 'creates the directory in the default branch' do + fill_in(:dir_name, with: 'new_directory') + click_button('Create directory') + + expect(page).to have_content('master') + expect(page).to have_content('The directory has been successfully created') + expect(page).to have_content('new_directory') + end + + it 'does not create a directory with a name of already existed directory' do + fill_in(:dir_name, with: 'files') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Create directory') + + expect(page).to have_content('A directory with this name already exists') + expect(current_path).to eq(project_tree_path(project, 'master')) + end + end + + context 'with a new target branch' do + before do + first('.add-to-tree').click + click_link('New directory') + fill_in(:dir_name, with: 'new_directory') + fill_in(:branch_name, with: 'new-feature') + click_button('Create directory') + end + + it 'creates the directory in the new branch and redirect to the merge request' do + expect(page).to have_content('new-feature') + expect(page).to have_content('The directory has been successfully created') + expect(page).to have_content('New Merge Request') + expect(page).to have_content('From new-feature into master') + expect(page).to have_content('Add new directory') + + expect(current_path).to eq(project_new_merge_request_path(project)) + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'creates a directory in a forked project' do + find('.add-to-tree').click + click_link('New directory') + + expect(page).to have_content(fork_message) + + find('.add-to-tree').click + click_link('New directory') + fill_in(:dir_name, with: 'new_directory') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Create directory') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + end + end +end diff --git a/spec/features/projects/user_creates_files_spec.rb b/spec/features/projects/user_creates_files_spec.rb new file mode 100644 index 00000000000..4b78cc4fc53 --- /dev/null +++ b/spec/features/projects/user_creates_files_spec.rb @@ -0,0 +1,153 @@ +require 'spec_helper' + +describe 'User creates 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(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + context 'without commiting a new file' do + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + end + + it 'opens new file page' do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_content('New file') + expect(page).to have_content('Commit message') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'opens new file page on a forked project' do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_selector('.file-editor') + expect(page).to have_content(fork_message) + expect(page).to have_content('New file') + expect(page).to have_content('Commit message') + end + end + end + + context 'with commiting a new file' do + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + + find('.add-to-tree').click + click_link('New file') + end + + it 'creates and commit a new file', js: true do + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + new_file_path = project_blob_path(project, 'master/not_a_file.md') + + expect(current_path).to eq(new_file_path) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'creates and commit a new file with new lines at the end of file', js: true do + execute_script('ace.edit("editor").setValue("Sample\n\n\n")') + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + new_file_path = project_blob_path(project, 'master/not_a_file.md') + + expect(current_path).to eq(new_file_path) + + find('.js-edit-blob').click + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq("Sample\n\n\n") + end + + it 'creates and commit a new file with a directory name', js: true do + fill_in(:file_name, with: 'foo/bar/baz.txt') + + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_blob_path(project, 'master/foo/bar/baz.txt')) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'creates and commit a new file specifying a new branch', js: true do + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'creates and commit new file in forked project', js: true do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + expect(page).to have_content('New commit message') + end + end + end +end diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb new file mode 100644 index 00000000000..1c3791f63ac --- /dev/null +++ b/spec/features/projects/user_creates_project_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +feature 'User creates a project', js: true do + let(:user) { create(:user) } + + before do + sign_in(user) + create(:personal_key, user: user) + visit(new_project_path) + end + + it 'creates a new project' do + fill_in(:project_path, with: 'Empty') + + page.within('#content-body') do + click_button('Create project') + end + + project = Project.last + + expect(current_path).to eq(project_path(project)) + expect(page).to have_content('Empty') + expect(page).to have_content('git init') + expect(page).to have_content('git remote') + expect(page).to have_content(project.url_to_repo) + end +end diff --git a/spec/features/projects/user_deletes_files_spec.rb b/spec/features/projects/user_deletes_files_spec.rb new file mode 100644 index 00000000000..95cd316be0e --- /dev/null +++ b/spec/features/projects/user_deletes_files_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe 'User deletes 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(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'deletes the file', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Delete') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Delete file') + + expect(current_path).to eq(project_tree_path(project, 'master')) + expect(page).not_to have_content('.gitignore') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'deletes the file in a forked project', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Delete') + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + click_on('Delete') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Delete file') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + expect(page).to have_content('New commit message') + end + end +end diff --git a/spec/features/projects/user_edits_files_spec.rb b/spec/features/projects/user_edits_files_spec.rb new file mode 100644 index 00000000000..8ae89c980b9 --- /dev/null +++ b/spec/features/projects/user_edits_files_spec.rb @@ -0,0 +1,122 @@ +require 'spec_helper' + +describe 'User edits 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(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'inserts a content of a file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca') + end + + it 'does not show the edit link if a file is binary' do + binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png') + visit(project_blob_path(project, binary_file)) + + expect(page).not_to have_link('edit') + end + + it 'commits an edited file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_blob_path(project, 'master/.gitignore')) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'commits an edited file to a new branch', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + wait_for_requests + expect(page).to have_content('*.rbca') + end + + it 'shows the diff of an edited file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + click_link('Preview changes') + + expect(page).to have_css('.line_holder.new') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'inserts a content of a file in a forked project', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + execute_script("ace.edit('editor').setValue('*.rbca')") + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca') + end + + it 'commits an edited file in a forked project', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + wait_for_requests + + expect(page).to have_content('New commit message') + end + end +end diff --git a/spec/features/projects/user_replaces_files_spec.rb b/spec/features/projects/user_replaces_files_spec.rb new file mode 100644 index 00000000000..e284fdefd4f --- /dev/null +++ b/spec/features/projects/user_replaces_files_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +describe 'User replaces files' do + include DropzoneHelper + + 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(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'replaces an existed file with a new one', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Replace') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'Replacement file commit message') + end + + click_button('Replace file') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + expect(page).to have_content('Replacement file commit message') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'replaces an existed file with a new one in a forked project', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Replace') + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + click_on('Replace') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'Replacement file commit message') + end + + click_button('Replace file') + + expect(page).to have_content('Replacement file commit message') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end +end diff --git a/spec/features/projects/user_uploads_files_spec.rb b/spec/features/projects/user_uploads_files_spec.rb new file mode 100644 index 00000000000..98871317ca3 --- /dev/null +++ b/spec/features/projects/user_uploads_files_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe 'User uploads files' do + include DropzoneHelper + + 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(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + end + + it 'uploads and commit a new file', js: true do + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Upload file') + + expect(page).to have_content('New commit message') + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'uploads and commit a new fileto a forked project', js: true do + find('.add-to-tree').click + click_link('Upload file') + + expect(page).to have_content(fork_message) + + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + click_button('Upload file') + + expect(page).to have_content('New commit message') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end +end diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb index 640f1376548..2a316a0d0db 100644 --- a/spec/features/projects/view_on_env_spec.rb +++ b/spec/features/projects/view_on_env_spec.rb @@ -50,9 +50,9 @@ describe 'View on environment', js: true do let(:merge_request) { create(:merge_request, :simple, source_project: project, source_branch: branch_name) } before do - login_as(user) + sign_in(user) - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + visit diffs_project_merge_request_path(project, merge_request) wait_for_requests end @@ -66,9 +66,9 @@ describe 'View on environment', js: true do context 'when visiting a comparison for the branch' do before do - login_as(user) + sign_in(user) - visit namespace_project_compare_path(project.namespace, project, from: 'master', to: branch_name) + visit project_compare_path(project, from: 'master', to: branch_name) wait_for_requests end @@ -80,9 +80,9 @@ describe 'View on environment', js: true do context 'when visiting a comparison for the commit' do before do - login_as(user) + sign_in(user) - visit namespace_project_compare_path(project.namespace, project, from: 'master', to: sha) + visit project_compare_path(project, from: 'master', to: sha) wait_for_requests end @@ -94,9 +94,9 @@ describe 'View on environment', js: true do context 'when visiting a blob on the branch' do before do - login_as(user) + sign_in(user) - visit namespace_project_blob_path(project.namespace, project, File.join(branch_name, file_path)) + visit project_blob_path(project, File.join(branch_name, file_path)) wait_for_requests end @@ -108,9 +108,9 @@ describe 'View on environment', js: true do context 'when visiting a blob on the commit' do before do - login_as(user) + sign_in(user) - visit namespace_project_blob_path(project.namespace, project, File.join(sha, file_path)) + visit project_blob_path(project, File.join(sha, file_path)) wait_for_requests end @@ -122,9 +122,9 @@ describe 'View on environment', js: true do context 'when visiting the commit' do before do - login_as(user) + sign_in(user) - visit namespace_project_commit_path(project.namespace, project, sha) + visit project_commit_path(project, sha) wait_for_requests end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index 49d7ef09e64..9a4ccf3c54d 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Wiki > User previews markdown changes', feature: true, js: true do +feature 'Projects > Wiki > User previews markdown changes', js: true do let(:user) { create(:user) } let(:project) { create(:project, namespace: user.namespace) } let(:wiki_content) do @@ -14,11 +14,12 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t background do project.team << [user, :master] - login_as(user) + WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute + + sign_in(user) - visit namespace_project_path(project.namespace, project) + visit project_path(project) find('.shortcuts-wiki').trigger('click') - WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute end context "while creating a new wiki page" do @@ -37,10 +38,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>") end end @@ -59,10 +60,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") end end @@ -81,10 +82,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") end end end @@ -114,10 +115,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>") end end @@ -131,10 +132,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") end end @@ -148,10 +149,10 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t expect(page).to have_content("regular link") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") + expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") end end end diff --git a/spec/features/projects/wiki/shortcuts_spec.rb b/spec/features/projects/wiki/shortcuts_spec.rb index c1f6b0cce3b..eaff5f876b6 100644 --- a/spec/features/projects/wiki/shortcuts_spec.rb +++ b/spec/features/projects/wiki/shortcuts_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -feature 'Wiki shortcuts', :feature, :js do +feature 'Wiki shortcuts', :js do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } let(:wiki_page) do WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute end before do - login_as(user) - visit namespace_project_wiki_path(project.namespace, project, wiki_page) + sign_in(user) + visit project_wiki_path(project, wiki_page) end scenario 'Visit edit wiki page using "e" keyboard shortcut' do 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 8912d575878..9d66f482c8d 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -1,20 +1,23 @@ require 'spec_helper' -feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do +feature 'Projects > Wiki > User creates wiki page', :js do let(:user) { create(:user) } background do project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_path(project.namespace, project) - find('.shortcuts-wiki').trigger('click') + visit project_path(project) end context 'in the user namespace' do let(:project) { create(:project, namespace: user.namespace) } context 'when wiki is empty' do + before do + find('.shortcuts-wiki').trigger('click') + end + scenario 'commit message field has value "Create home"' do expect(page).to have_field('wiki[message]', with: 'Create home') end @@ -67,10 +70,11 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do context 'when wiki is not empty' do before do WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute + find('.shortcuts-wiki').trigger('click') end context 'via the "new wiki page" page' do - scenario 'when the wiki page has a single word name', js: true do + scenario 'when the wiki page has a single word name' do click_link 'New page' page.within '#modal-new-wiki' do @@ -91,7 +95,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do expect(page).to have_content('My awesome wiki!') end - scenario 'when the wiki page has spaces in the name', js: true do + scenario 'when the wiki page has spaces in the name' do click_link 'New page' page.within '#modal-new-wiki' do @@ -112,7 +116,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do expect(page).to have_content('My awesome wiki!') end - scenario 'when the wiki page has hyphens in the name', js: true do + scenario 'when the wiki page has hyphens in the name' do click_link 'New page' page.within '#modal-new-wiki' do @@ -133,6 +137,22 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do expect(page).to have_content('My awesome wiki!') end end + + scenario 'content has autocomplete' do + click_link 'New 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: '@' + end + + expect(page).to have_selector('.atwho-view') + end end end @@ -140,6 +160,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do let(:project) { create(:project, namespace: create(:group, :public)) } context 'when wiki is empty' do + before do + find('.shortcuts-wiki').trigger('click') + end + scenario 'commit message field has value "Create home"' do expect(page).to have_field('wiki[message]', with: 'Create home') end @@ -159,9 +183,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do context 'when wiki is not empty' do before do WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute + find('.shortcuts-wiki').trigger('click') end - scenario 'via the "new wiki page" page', js: true do + scenario 'via the "new wiki page" page' do click_link 'New page' page.within '#modal-new-wiki' do diff --git a/spec/features/projects/wiki/user_git_access_wiki_page_spec.rb b/spec/features/projects/wiki/user_git_access_wiki_page_spec.rb index 95826e7e5be..9a92622ba2b 100644 --- a/spec/features/projects/wiki/user_git_access_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_git_access_wiki_page_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Projects > Wiki > User views Git access wiki page', :feature do +describe 'Projects > Wiki > User views Git access wiki page' do let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:wiki_page) do @@ -13,14 +13,14 @@ describe 'Projects > Wiki > User views Git access wiki page', :feature do end before do - login_as(user) + sign_in(user) end scenario 'Visit Wiki Page Current Commit' do - visit namespace_project_wiki_path(project.namespace, project, wiki_page) + visit project_wiki_path(project, wiki_page) click_link 'Clone repository' - expect(page).to have_text("Clone repository #{project.wiki.path_with_namespace}") + expect(page).to have_text("Clone repository #{project.wiki.full_path}") expect(page).to have_text(project.wiki.http_url_to_repo) end end diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb index 86cf520ea80..e3739a705bf 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -1,15 +1,14 @@ require 'spec_helper' -feature 'Projects > Wiki > User updates wiki page', feature: true do +feature 'Projects > Wiki > User updates wiki page' do let(:user) { create(:user) } + let!(:wiki_page) { WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute } background do project.team << [user, :master] - login_as(user) + sign_in(user) - visit namespace_project_path(project.namespace, project) - WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute - click_link 'Wiki' + visit project_wikis_path(project) end context 'in the user namespace' do @@ -42,6 +41,25 @@ feature 'Projects > Wiki > User updates wiki page', feature: true do expect(page).to have_content('Content can\'t be blank') expect(find('textarea#wiki_content').value).to eq '' end + + scenario 'content has autocomplete', :js do + click_link 'Edit' + + find('#wiki_content').native.send_keys('') + fill_in :wiki_content, with: '@' + + expect(page).to have_selector('.atwho-view') + end + end + + scenario 'page has been updated since the user opened the edit page' do + click_link 'Edit' + + wiki_page.update('Update') + + click_button 'Save changes' + + expect(page).to have_content 'Someone edited the page the same time you did.' end end diff --git a/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb index c17e06612de..92e96f11219 100644 --- a/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Wiki > User views the wiki page', feature: true do +feature 'Projects > Wiki > User views the wiki page' do let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:old_page_version_id) { wiki_page.versions.last.id } @@ -15,7 +15,7 @@ feature 'Projects > Wiki > User views the wiki page', feature: true do background do project.team << [user, :master] - login_as(user) + sign_in(user) WikiPages::UpdateService.new( project, user, @@ -26,18 +26,13 @@ feature 'Projects > Wiki > User views the wiki page', feature: true do end scenario 'Visit Wiki Page Current Commit' do - visit namespace_project_wiki_path(project.namespace, project, wiki_page) + visit project_wiki_path(project, wiki_page) expect(page).to have_selector('a.btn', text: 'Edit') end scenario 'Visit Wiki Page Historical Commit' do - visit namespace_project_wiki_path( - project.namespace, - project, - wiki_page, - version_id: old_page_version_id - ) + visit project_wiki_path(project, wiki_page, version_id: old_page_version_id) expect(page).not_to have_selector('a.btn', text: 'Edit') end diff --git a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb index 20219f3cc9a..cf9fe4c1ad1 100644 --- a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -describe 'Projects > Wiki > User views wiki in project page', feature: true do +describe 'Projects > Wiki > User views wiki in project page' do let(:user) { create(:user) } before do project.team << [user, :master] - login_as(user) + sign_in(user) end context 'when repository is disabled for project' do let(:project) do - create(:empty_project, + create(:project, :repository_disabled, :merge_requests_disabled, :builds_disabled) @@ -27,14 +27,10 @@ describe 'Projects > Wiki > User views wiki in project page', feature: true do end it 'displays the correct URL for the link' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) expect(page).to have_link( 'some link', - href: namespace_project_wiki_path( - project.namespace, - project, - 'other-page' - ) + href: project_wiki_path(project, 'other-page') ) end end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 060e19596ae..dbcdac902d5 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' -feature 'Project', feature: true do +feature 'Project' do describe 'description' do let(:project) { create(:project, :repository) } - let(:path) { namespace_project_path(project.namespace, project) } + let(:path) { project_path(project) } before do - login_as(:admin) + sign_in(create(:admin)) end it 'parses Markdown' do @@ -36,12 +36,12 @@ feature 'Project', feature: true do describe 'remove forked relationship', js: true do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } before do - login_with user + sign_in user create(:forked_project_link, forked_to_project: project) - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) end it 'removes fork' do @@ -57,12 +57,12 @@ feature 'Project', feature: true do describe 'removal', js: true do let(:user) { create(:user, username: 'test', name: 'test') } - let(:project) { create(:empty_project, namespace: user.namespace, name: 'project1') } + let(:project) { create(:project, namespace: user.namespace, name: 'project1') } before do - login_with(user) + sign_in(user) project.team << [user, :master] - visit edit_namespace_project_path(project.namespace, project) + visit edit_project_path(project) end it 'removes a project' do @@ -76,12 +76,12 @@ feature 'Project', feature: true do describe 'project title' do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } before do - login_with(user) + sign_in(user) project.add_user(user, Gitlab::Access::MASTER) - visit namespace_project_path(project.namespace, project) + visit project_path(project) end it 'clicks toggle and shows dropdown', js: true do @@ -92,16 +92,16 @@ feature 'Project', feature: true do describe 'project title' do let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } - let(:project2) { create(:empty_project, namespace: user.namespace, path: 'test') } + let(:project) { create(:project, namespace: user.namespace) } + let(:project2) { create(:project, namespace: user.namespace, path: 'test') } let(:issue) { create(:issue, project: project) } context 'on issues page', js: true do before do - login_with(user) + sign_in(user) project.add_user(user, Gitlab::Access::MASTER) project2.add_user(user, Gitlab::Access::MASTER) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end it 'clicks toggle and shows dropdown' do @@ -123,8 +123,8 @@ feature 'Project', feature: true do before do project.team << [user, :master] - login_as user - visit namespace_project_path(project.namespace, project) + sign_in user + visit project_path(project) end it 'has working links to files' do diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index 884d1bbb10c..3677bf38724 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -1,10 +1,12 @@ require 'spec_helper' -feature 'Projected Branches', feature: true, js: true do +feature 'Protected Branches', js: true do let(:user) { create(:user, :admin) } let(:project) { create(:project, :repository) } - before { login_as(user) } + before do + sign_in(user) + end def set_protected_branch_name(branch_name) find(".js-protected-branch-select").trigger('click') @@ -14,7 +16,7 @@ feature 'Projected Branches', feature: true, js: true do describe "explicit protected branches" do it "allows creating explicit protected branches" do - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('some-branch') click_on "Protect" @@ -27,7 +29,7 @@ feature 'Projected Branches', feature: true, js: true do commit = create(:commit, project: project) project.repository.add_branch(user, 'some-branch', commit.id) - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('some-branch') click_on "Protect" @@ -35,7 +37,7 @@ feature 'Projected Branches', feature: true, js: true do end it "displays an error message if the named branch does not exist" do - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('some-branch') click_on "Protect" @@ -45,7 +47,7 @@ feature 'Projected Branches', feature: true, js: true do describe "wildcard protected branches" do it "allows creating protected branches with a wildcard" do - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('*-stable') click_on "Protect" @@ -58,7 +60,7 @@ feature 'Projected Branches', feature: true, js: true do project.repository.add_branch(user, 'production-stable', 'master') project.repository.add_branch(user, 'staging-stable', 'master') - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('*-stable') click_on "Protect" @@ -70,11 +72,11 @@ feature 'Projected Branches', feature: true, js: true do project.repository.add_branch(user, 'staging-stable', 'master') project.repository.add_branch(user, 'development', 'master') - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) set_protected_branch_name('*-stable') click_on "Protect" - visit namespace_project_protected_branches_path(project.namespace, project) + visit project_protected_branches_path(project) click_on "2 matching branches" within(".protected-branches-list") do diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb index 66236dbc7fc..c9ba1a8c088 100644 --- a/spec/features/protected_tags_spec.rb +++ b/spec/features/protected_tags_spec.rb @@ -1,10 +1,12 @@ require 'spec_helper' -feature 'Projected Tags', feature: true, js: true do +feature 'Projected Tags', js: true do let(:user) { create(:user, :admin) } let(:project) { create(:project, :repository) } - before { login_as(user) } + before do + sign_in(user) + end def set_protected_tag_name(tag_name) find(".js-protected-tag-select").click @@ -15,7 +17,7 @@ feature 'Projected Tags', feature: true, js: true do describe "explicit protected tags" do it "allows creating explicit protected tags" do - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('some-tag') click_on "Protect" @@ -28,7 +30,7 @@ feature 'Projected Tags', feature: true, js: true do commit = create(:commit, project: project) project.repository.add_tag(user, 'some-tag', commit.id) - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('some-tag') click_on "Protect" @@ -36,7 +38,7 @@ feature 'Projected Tags', feature: true, js: true do end it "displays an error message if the named tag does not exist" do - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('some-tag') click_on "Protect" @@ -46,7 +48,7 @@ feature 'Projected Tags', feature: true, js: true do describe "wildcard protected tags" do it "allows creating protected tags with a wildcard" do - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('*-stable') click_on "Protect" @@ -59,7 +61,7 @@ feature 'Projected Tags', feature: true, js: true do project.repository.add_tag(user, 'production-stable', 'master') project.repository.add_tag(user, 'staging-stable', 'master') - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('*-stable') click_on "Protect" @@ -71,11 +73,11 @@ feature 'Projected Tags', feature: true, js: true do project.repository.add_tag(user, 'staging-stable', 'master') project.repository.add_tag(user, 'development', 'master') - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) set_protected_tag_name('*-stable') click_on "Protect" - visit namespace_project_protected_tags_path(project.namespace, project) + visit project_protected_tags_path(project) click_on "2 matching tags" within(".protected-tags-list") do diff --git a/spec/features/raven_js_spec.rb b/spec/features/raven_js_spec.rb index e8fa49c18cb..b1f51959d54 100644 --- a/spec/features/raven_js_spec.rb +++ b/spec/features/raven_js_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'RavenJS', :feature, :js do +feature 'RavenJS', :js do let(:raven_path) { '/raven.bundle.js' } it 'should not load raven if sentry is disabled' do diff --git a/spec/features/reportable_note/commit_spec.rb b/spec/features/reportable_note/commit_spec.rb new file mode 100644 index 00000000000..3bf25221e36 --- /dev/null +++ b/spec/features/reportable_note/commit_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe 'Reportable note on commit', :js do + include RepoHelpers + + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + + before do + project.add_master(user) + sign_in(user) + end + + context 'a normal note' do + let!(:note) { create(:note_on_commit, commit_id: sample_commit.id, project: project) } + + before do + visit project_commit_path(project, sample_commit.id) + end + + it_behaves_like 'reportable note' + end + + context 'a diff note' do + let!(:note) { create(:diff_note_on_commit, commit_id: sample_commit.id, project: project) } + + before do + visit project_commit_path(project, sample_commit.id) + end + + it_behaves_like 'reportable note' + end +end diff --git a/spec/features/reportable_note/issue_spec.rb b/spec/features/reportable_note/issue_spec.rb new file mode 100644 index 00000000000..21e96f6f103 --- /dev/null +++ b/spec/features/reportable_note/issue_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe 'Reportable note on issue', :js do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:issue) { create(:issue, project: project) } + let!(:note) { create(:note_on_issue, noteable: issue, project: project) } + + before do + project.add_master(user) + sign_in(user) + + visit project_issue_path(project, issue) + end + + it_behaves_like 'reportable note' +end diff --git a/spec/features/reportable_note/merge_request_spec.rb b/spec/features/reportable_note/merge_request_spec.rb new file mode 100644 index 00000000000..bb296546e06 --- /dev/null +++ b/spec/features/reportable_note/merge_request_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe 'Reportable note on merge request', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:merge_request) { create(:merge_request, source_project: project) } + + before do + project.add_master(user) + sign_in(user) + + visit project_merge_request_path(project, merge_request) + end + + context 'a normal note' do + let!(:note) { create(:note_on_merge_request, noteable: merge_request, project: project) } + + it_behaves_like 'reportable note' + end + + context 'a diff note' do + let!(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project) } + + it_behaves_like 'reportable note' + end +end diff --git a/spec/features/reportable_note/snippets_spec.rb b/spec/features/reportable_note/snippets_spec.rb new file mode 100644 index 00000000000..f1e48ed46be --- /dev/null +++ b/spec/features/reportable_note/snippets_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe 'Reportable note on snippets', :js do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + project.add_master(user) + sign_in(user) + end + + describe 'on project snippet' do + let(:snippet) { create(:project_snippet, :public, project: project, author: user) } + let!(:note) { create(:note_on_project_snippet, noteable: snippet, project: project) } + + before do + visit project_snippet_path(project, snippet) + end + + it_behaves_like 'reportable note' + end +end diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 0e1cc9a0f73..cac31c34ad1 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -1,20 +1,21 @@ require 'spec_helper' describe "Runners" do - include GitlabRoutingHelper - let(:user) { create(:user) } - before { login_as(user) } + + before do + sign_in(user) + end describe "specific runners" do before do - @project = FactoryGirl.create :empty_project, shared_runners_enabled: false + @project = FactoryGirl.create :project, shared_runners_enabled: false @project.team << [user, :master] - @project2 = FactoryGirl.create :empty_project + @project2 = FactoryGirl.create :project @project2.team << [user, :master] - @project3 = FactoryGirl.create :empty_project + @project3 = FactoryGirl.create :project @project3.team << [user, :developer] @shared_runner = FactoryGirl.create :ci_runner, :shared @@ -69,7 +70,7 @@ describe "Runners" do describe "shared runners" do before do - @project = FactoryGirl.create :empty_project, shared_runners_enabled: false + @project = FactoryGirl.create :project, shared_runners_enabled: false @project.team << [user, :master] visit runners_path(@project) end @@ -86,7 +87,7 @@ describe "Runners" do before do stub_application_setting(shared_runners_text: shared_runners_text) - project = FactoryGirl.create :empty_project, shared_runners_enabled: false + project = FactoryGirl.create :project, shared_runners_enabled: false project.team << [user, :master] visit runners_path(project) end @@ -98,7 +99,7 @@ describe "Runners" do describe "show page" do before do - @project = FactoryGirl.create :empty_project + @project = FactoryGirl.create :project @project.team << [user, :master] @specific_runner = FactoryGirl.create :ci_runner @project.runners << @specific_runner @@ -112,7 +113,7 @@ describe "Runners" do end feature 'configuring runners ability to picking untagged jobs' do - given(:project) { create(:empty_project) } + given(:project) { create(:project) } given(:runner) { create(:ci_runner) } background do @@ -121,13 +122,15 @@ describe "Runners" do end scenario 'user checks default configuration' do - visit namespace_project_runner_path(project.namespace, project, runner) + visit project_runner_path(project, runner) expect(page).to have_content 'Can run untagged jobs Yes' end context 'when runner has tags' do - before { runner.update_attribute(:tag_list, ['tag']) } + before do + runner.update_attribute(:tag_list, ['tag']) + end scenario 'user wants to prevent runner from running untagged job' do visit runners_path(project) diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index 7834807b1f1..9b49fc2225d 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe "Search", feature: true do +describe "Search" do include FilteredSearchHelpers let(:user) { create(:user) } - let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project) { create(:project, namespace: user.namespace) } let!(:issue) { create(:issue, project: project, assignees: [user]) } let!(:issue2) { create(:issue, project: project, author: user) } before do - login_with(user) + sign_in(user) project.team << [user, :reporter] visit search_path end @@ -20,7 +20,7 @@ describe "Search", feature: true do context 'search filters', js: true do let(:group) { create(:group) } - let!(:group_project) { create(:empty_project, group: group) } + let!(:group_project) { create(:project, group: group) } before do group.add_owner(user) @@ -83,10 +83,12 @@ describe "Search", feature: true do let(:project) { create(:project, :repository) } let(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'Bug here') } - before { note.update_attributes(commit_id: 12345678) } + before do + note.update_attributes(commit_id: 12345678) + end it 'finds comment' do - visit namespace_project_path(project.namespace, project) + visit project_path(project) page.within '.search' do fill_in 'search', with: note.note @@ -109,7 +111,7 @@ describe "Search", feature: true do project: project) # Must visit project dashboard since global search won't search # everything (e.g. comments, snippets, etc.) - visit namespace_project_path(project.namespace, project) + visit project_path(project) page.within '.search' do fill_in 'search', with: note.note @@ -123,7 +125,7 @@ describe "Search", feature: true do it 'finds a commit' do project = create(:project, :repository) { |p| p.add_reporter(user) } - visit namespace_project_path(project.namespace, project) + visit project_path(project) page.within '.search' do fill_in 'search', with: 'add' @@ -137,7 +139,7 @@ describe "Search", feature: true do it 'finds a code' do project = create(:project, :repository) { |p| p.add_reporter(user) } - visit namespace_project_path(project.namespace, project) + visit project_path(project) page.within '.search' do fill_in 'search', with: 'application.js' @@ -152,9 +154,9 @@ describe "Search", feature: true do end end - describe 'Right header search field', feature: true do + describe 'Right header search field' do it 'allows enter key to search', js: true do - visit namespace_project_path(project.namespace, project) + visit project_path(project) fill_in 'search', with: 'gitlab' find('#search').native.send_keys(:enter) @@ -165,7 +167,7 @@ describe "Search", feature: true do describe 'Search in project page' do before do - visit namespace_project_path(project.namespace, project) + visit project_path(project) end it 'shows top right search form' do @@ -254,7 +256,7 @@ describe "Search", feature: true do click_button 'Search' - expect(page).to have_current_path(namespace_project_commit_path(project.namespace, project, '6d394385cf567f80a8fd85055db1ab4c5295806f')) + expect(page).to have_current_path(project_commit_path(project, '6d394385cf567f80a8fd85055db1ab4c5295806f')) end it 'redirects to single commit regardless of query case' do @@ -262,7 +264,7 @@ describe "Search", feature: true do click_button 'Search' - expect(page).to have_current_path(namespace_project_commit_path(project.namespace, project, '6d394385cf567f80a8fd85055db1ab4c5295806f')) + expect(page).to have_current_path(project_commit_path(project, '6d394385cf567f80a8fd85055db1ab4c5295806f')) end it 'holds on /search page when the only commit is found by message' do diff --git a/spec/features/security/admin_access_spec.rb b/spec/features/security/admin_access_spec.rb index e180ca53eb5..3ca1303bda6 100644 --- a/spec/features/security/admin_access_spec.rb +++ b/spec/features/security/admin_access_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Admin::Projects", feature: true do +describe "Admin::Projects" do include AccessMatchers describe "GET /admin/projects" do diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb index 40f773956d1..149bd32e736 100644 --- a/spec/features/security/dashboard_access_spec.rb +++ b/spec/features/security/dashboard_access_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Dashboard access", feature: true do +describe "Dashboard access" do include AccessMatchers describe "GET /dashboard" do diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb index 87cce32d6c6..5067f0b0a49 100644 --- a/spec/features/security/group/internal_access_spec.rb +++ b/spec/features/security/group/internal_access_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'Internal Group access', feature: true do +describe 'Internal Group access' do include AccessMatchers let(:group) { create(:group, :internal) } @@ -49,6 +49,7 @@ describe 'Internal Group access', feature: true do end describe 'GET /groups/:path/merge_requests' do + let(:project) { create(:project, :internal, :repository, group: group) } subject { merge_requests_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index 1d6b3e77c22..ff32413dc7e 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'Private Group access', feature: true do +describe 'Private Group access' do include AccessMatchers let(:group) { create(:group, :private) } @@ -49,6 +49,7 @@ describe 'Private Group access', feature: true do end describe 'GET /groups/:path/merge_requests' do + let(:project) { create(:project, :private, :repository, group: group) } subject { merge_requests_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb index d7d76177269..16d114fb3f7 100644 --- a/spec/features/security/group/public_access_spec.rb +++ b/spec/features/security/group/public_access_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'Public Group access', feature: true do +describe 'Public Group access' do include AccessMatchers let(:group) { create(:group, :public) } @@ -49,6 +49,7 @@ describe 'Public Group access', feature: true do end describe 'GET /groups/:path/merge_requests' do + let(:project) { create(:project, :public, :repository, group: group) } subject { merge_requests_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index c19678ab381..41eb7b26578 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Profile access", feature: true do +describe "Profile access" do include AccessMatchers describe "GET /profile/keys" do diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 2a2655bbdb5..a7928857b7d 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe "Internal Project Access", feature: true do +describe "Internal Project Access" do include AccessMatchers - set(:project) { create(:project, :internal) } + set(:project) { create(:project, :internal, :repository) } describe "Project should be internal" do describe '#internal?' do @@ -13,7 +13,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path" do - subject { namespace_project_path(project.namespace, project) } + subject { project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -27,7 +27,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/tree/master" do - subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } + subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -41,7 +41,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/commits/master" do - subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } + subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -55,7 +55,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/commit/:sha" do - subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } + subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -69,7 +69,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/compare" do - subject { namespace_project_compare_index_path(project.namespace, project) } + subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -83,7 +83,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/settings/members" do - subject { namespace_project_settings_members_path(project.namespace, project) } + subject { project_settings_members_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -97,7 +97,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/settings/ci_cd" do - subject { namespace_project_settings_ci_cd_path(project.namespace, project) } + subject { project_settings_ci_cd_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -111,7 +111,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/settings/repository" do - subject { namespace_project_settings_repository_path(project.namespace, project) } + subject { project_settings_repository_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -126,7 +126,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/blob" do let(:commit) { project.repository.commit } - subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) } + subject { project_blob_path(project, File.join(commit.id, '.gitignore')) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -140,7 +140,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/edit" do - subject { edit_namespace_project_path(project.namespace, project) } + subject { edit_project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -154,7 +154,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/deploy_keys" do - subject { namespace_project_deploy_keys_path(project.namespace, project) } + subject { project_deploy_keys_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -168,7 +168,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/issues" do - subject { namespace_project_issues_path(project.namespace, project) } + subject { project_issues_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -183,7 +183,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } - subject { edit_namespace_project_issue_path(project.namespace, project, issue) } + subject { edit_project_issue_path(project, issue) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -197,7 +197,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -211,7 +211,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/snippets/new" do - subject { new_namespace_project_snippet_path(project.namespace, project) } + subject { new_project_snippet_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -225,7 +225,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/merge_requests" do - subject { namespace_project_merge_requests_path(project.namespace, project) } + subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -239,7 +239,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/merge_requests/new" do - subject { new_namespace_project_merge_request_path(project.namespace, project) } + subject { project_new_merge_request_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -253,7 +253,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/branches" do - subject { namespace_project_branches_path(project.namespace, project) } + subject { project_branches_path(project) } before do # Speed increase @@ -272,7 +272,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/tags" do - subject { namespace_project_tags_path(project.namespace, project) } + subject { project_tags_path(project) } before do # Speed increase @@ -291,7 +291,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/settings/integrations" do - subject { namespace_project_settings_integrations_path(project.namespace, project) } + subject { project_settings_integrations_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -305,7 +305,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/pipelines" do - subject { namespace_project_pipelines_path(project.namespace, project) } + subject { project_pipelines_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -320,7 +320,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } - subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } + subject { project_pipeline_path(project, pipeline) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -334,10 +334,12 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_jobs_path(project.namespace, project) } + subject { project_jobs_path(project) } context "when allowed for public and internal" do - before { project.update(public_builds: true) } + before do + project.update(public_builds: true) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -351,7 +353,9 @@ describe "Internal Project Access", feature: true do end context "when disallowed for public and internal" do - before { project.update(public_builds: false) } + before do + project.update(public_builds: false) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -368,10 +372,12 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_job_path(project.namespace, project, build.id) } + subject { project_job_path(project, build.id) } context "when allowed for public and internal" do - before { project.update(public_builds: true) } + before do + project.update(public_builds: true) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -385,7 +391,9 @@ describe "Internal Project Access", feature: true do end context "when disallowed for public and internal" do - before { project.update(public_builds: false) } + before do + project.update(public_builds: false) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -402,7 +410,7 @@ describe "Internal Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_job_path(project.namespace, project, build.id) } + subject { trace_project_job_path(project, build.id) } context 'when allowed for public and internal' do before do @@ -438,7 +446,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/pipeline_schedules" do - subject { namespace_project_pipeline_schedules_path(project.namespace, project) } + subject { project_pipeline_schedules_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -452,7 +460,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/environments" do - subject { namespace_project_environments_path(project.namespace, project) } + subject { project_environments_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -467,7 +475,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_path(project.namespace, project, environment) } + subject { project_environment_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -482,7 +490,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/environments/:id/deployments" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_deployments_path(project.namespace, project, environment) } + subject { project_environment_deployments_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -496,7 +504,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/environments/new" do - subject { new_namespace_project_environment_path(project.namespace, project) } + subject { new_project_environment_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -518,7 +526,7 @@ describe "Internal Project Access", feature: true do project.container_repositories << container_repository end - subject { namespace_project_container_registry_index_path(project.namespace, project) } + subject { project_container_registry_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index b676c236758..a4396b20afd 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe "Private Project Access", feature: true do +describe "Private Project Access" do include AccessMatchers - set(:project) { create(:project, :private, public_builds: false) } + set(:project) { create(:project, :private, :repository, public_builds: false) } describe "Project should be private" do describe '#private?' do @@ -13,7 +13,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path" do - subject { namespace_project_path(project.namespace, project) } + subject { project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -27,7 +27,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/tree/master" do - subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } + subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -41,7 +41,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/commits/master" do - subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } + subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -55,7 +55,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/commit/:sha" do - subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } + subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -69,7 +69,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/compare" do - subject { namespace_project_compare_index_path(project.namespace, project) } + subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -83,7 +83,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/settings/members" do - subject { namespace_project_settings_members_path(project.namespace, project) } + subject { project_settings_members_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -97,7 +97,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/settings/ci_cd" do - subject { namespace_project_settings_ci_cd_path(project.namespace, project) } + subject { project_settings_ci_cd_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -111,7 +111,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/settings/repository" do - subject { namespace_project_settings_repository_path(project.namespace, project) } + subject { project_settings_repository_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -126,7 +126,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/blob" do let(:commit) { project.repository.commit } - subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore'))} + subject { project_blob_path(project, File.join(commit.id, '.gitignore'))} it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -140,7 +140,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/edit" do - subject { edit_namespace_project_path(project.namespace, project) } + subject { edit_project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -154,7 +154,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/deploy_keys" do - subject { namespace_project_deploy_keys_path(project.namespace, project) } + subject { project_deploy_keys_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -168,7 +168,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/issues" do - subject { namespace_project_issues_path(project.namespace, project) } + subject { project_issues_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -183,7 +183,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } - subject { edit_namespace_project_issue_path(project.namespace, project, issue) } + subject { edit_project_issue_path(project, issue) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -197,7 +197,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -211,7 +211,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/merge_requests" do - subject { namespace_project_merge_requests_path(project.namespace, project) } + subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -225,7 +225,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/branches" do - subject { namespace_project_branches_path(project.namespace, project) } + subject { project_branches_path(project) } before do # Speed increase @@ -244,7 +244,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/tags" do - subject { namespace_project_tags_path(project.namespace, project) } + subject { project_tags_path(project) } before do # Speed increase @@ -263,7 +263,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/namespace/hooks" do - subject { namespace_project_settings_integrations_path(project.namespace, project) } + subject { project_settings_integrations_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -277,7 +277,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/pipelines" do - subject { namespace_project_pipelines_path(project.namespace, project) } + subject { project_pipelines_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -304,7 +304,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } - subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } + subject { project_pipeline_path(project, pipeline) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -330,7 +330,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_jobs_path(project.namespace, project) } + subject { project_jobs_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -358,7 +358,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_job_path(project.namespace, project, build.id) } + subject { project_job_path(project, build.id) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -391,7 +391,7 @@ describe "Private Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_job_path(project.namespace, project, build.id) } + subject { trace_project_job_path(project, build.id) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -421,7 +421,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/environments" do - subject { namespace_project_environments_path(project.namespace, project) } + subject { project_environments_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -436,7 +436,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_path(project.namespace, project, environment) } + subject { project_environment_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -451,7 +451,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/environments/:id/deployments" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_deployments_path(project.namespace, project, environment) } + subject { project_environment_deployments_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -465,7 +465,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/environments/new" do - subject { new_namespace_project_environment_path(project.namespace, project) } + subject { new_project_environment_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -479,7 +479,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/pipeline_schedules" do - subject { namespace_project_pipeline_schedules_path(project.namespace, project) } + subject { project_pipeline_schedules_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -493,7 +493,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/pipeline_schedules/new" do - subject { new_namespace_project_pipeline_schedule_path(project.namespace, project) } + subject { new_project_pipeline_schedule_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -507,7 +507,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/environments/new" do - subject { new_namespace_project_pipeline_schedule_path(project.namespace, project) } + subject { new_project_pipeline_schedule_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -529,7 +529,7 @@ describe "Private Project Access", feature: true do project.container_repositories << container_repository end - subject { namespace_project_container_registry_index_path(project.namespace, project) } + subject { project_container_registry_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 35d5163941e..fccdeb0e5b7 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe "Public Project Access", feature: true do +describe "Public Project Access" do include AccessMatchers - set(:project) { create(:project, :public) } + set(:project) { create(:project, :public, :repository) } describe "Project should be public" do describe '#public?' do @@ -13,7 +13,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path" do - subject { namespace_project_path(project.namespace, project) } + subject { project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -27,7 +27,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/tree/master" do - subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } + subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -41,7 +41,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/commits/master" do - subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } + subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -55,7 +55,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/commit/:sha" do - subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } + subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -69,7 +69,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/compare" do - subject { namespace_project_compare_index_path(project.namespace, project) } + subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -83,7 +83,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/settings/members" do - subject { namespace_project_settings_members_path(project.namespace, project) } + subject { project_settings_members_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -97,7 +97,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/settings/ci_cd" do - subject { namespace_project_settings_ci_cd_path(project.namespace, project) } + subject { project_settings_ci_cd_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -111,7 +111,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/settings/repository" do - subject { namespace_project_settings_repository_path(project.namespace, project) } + subject { project_settings_repository_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -125,7 +125,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/pipelines" do - subject { namespace_project_pipelines_path(project.namespace, project) } + subject { project_pipelines_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -140,7 +140,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } - subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } + subject { project_pipeline_path(project, pipeline) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -154,10 +154,12 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_jobs_path(project.namespace, project) } + subject { project_jobs_path(project) } context "when allowed for public" do - before { project.update(public_builds: true) } + before do + project.update(public_builds: true) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -171,7 +173,9 @@ describe "Public Project Access", feature: true do end context "when disallowed for public" do - before { project.update(public_builds: false) } + before do + project.update(public_builds: false) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -188,10 +192,12 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_job_path(project.namespace, project, build.id) } + subject { project_job_path(project, build.id) } context "when allowed for public" do - before { project.update(public_builds: true) } + before do + project.update(public_builds: true) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -205,7 +211,9 @@ describe "Public Project Access", feature: true do end context "when disallowed for public" do - before { project.update(public_builds: false) } + before do + project.update(public_builds: false) + end it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -222,7 +230,7 @@ describe "Public Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_job_path(project.namespace, project, build.id) } + subject { trace_project_job_path(project, build.id) } context 'when allowed for public' do before do @@ -258,7 +266,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/pipeline_schedules" do - subject { namespace_project_pipeline_schedules_path(project.namespace, project) } + subject { project_pipeline_schedules_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -272,7 +280,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/environments" do - subject { namespace_project_environments_path(project.namespace, project) } + subject { project_environments_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -287,7 +295,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_path(project.namespace, project, environment) } + subject { project_environment_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -302,7 +310,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/environments/:id/deployments" do let(:environment) { create(:environment, project: project) } - subject { namespace_project_environment_deployments_path(project.namespace, project, environment) } + subject { project_environment_deployments_path(project, environment) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -316,7 +324,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/environments/new" do - subject { new_namespace_project_environment_path(project.namespace, project) } + subject { new_project_environment_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -332,7 +340,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/blob" do let(:commit) { project.repository.commit } - subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) } + subject { project_blob_path(project, File.join(commit.id, '.gitignore')) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -345,7 +353,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/edit" do - subject { edit_namespace_project_path(project.namespace, project) } + subject { edit_project_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -359,7 +367,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/deploy_keys" do - subject { namespace_project_deploy_keys_path(project.namespace, project) } + subject { project_deploy_keys_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -373,7 +381,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/issues" do - subject { namespace_project_issues_path(project.namespace, project) } + subject { project_issues_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -388,7 +396,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } - subject { edit_namespace_project_issue_path(project.namespace, project, issue) } + subject { edit_project_issue_path(project, issue) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -402,7 +410,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -416,7 +424,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/snippets/new" do - subject { new_namespace_project_snippet_path(project.namespace, project) } + subject { new_project_snippet_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -430,7 +438,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/merge_requests" do - subject { namespace_project_merge_requests_path(project.namespace, project) } + subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -444,7 +452,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/merge_requests/new" do - subject { new_namespace_project_merge_request_path(project.namespace, project) } + subject { project_new_merge_request_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -458,7 +466,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/branches" do - subject { namespace_project_branches_path(project.namespace, project) } + subject { project_branches_path(project) } before do # Speed increase @@ -477,7 +485,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/tags" do - subject { namespace_project_tags_path(project.namespace, project) } + subject { project_tags_path(project) } before do # Speed increase @@ -496,7 +504,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/settings/integrations" do - subject { namespace_project_settings_integrations_path(project.namespace, project) } + subject { project_settings_integrations_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -518,7 +526,7 @@ describe "Public Project Access", feature: true do project.container_repositories << container_repository end - subject { namespace_project_container_registry_index_path(project.namespace, project) } + subject { project_container_registry_index_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb index 2659b3ee3ec..d7dc99c0a57 100644 --- a/spec/features/security/project/snippet/internal_access_spec.rb +++ b/spec/features/security/project/snippet/internal_access_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' -describe "Internal Project Snippets Access", feature: true do +describe "Internal Project Snippets Access" do include AccessMatchers - let(:project) { create(:empty_project, :internal) } + let(:project) { create(:project, :internal) } let(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.owner) } let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) } describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -23,7 +23,7 @@ describe "Internal Project Snippets Access", feature: true do end describe "GET /:project_path/snippets/new" do - subject { new_namespace_project_snippet_path(project.namespace, project) } + subject { new_project_snippet_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -38,7 +38,7 @@ describe "Internal Project Snippets Access", feature: true do describe "GET /:project_path/snippets/:id" do context "for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + subject { project_snippet_path(project, internal_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -52,7 +52,7 @@ describe "Internal Project Snippets Access", feature: true do end context "for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -68,7 +68,7 @@ describe "Internal Project Snippets Access", feature: true do describe "GET /:project_path/snippets/:id/raw" do context "for an internal snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } + subject { raw_project_snippet_path(project, internal_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -82,7 +82,7 @@ describe "Internal Project Snippets Access", feature: true do end context "for a private snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { raw_project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb index 6eb9f163bd5..3ec1a388185 100644 --- a/spec/features/security/project/snippet/private_access_spec.rb +++ b/spec/features/security/project/snippet/private_access_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -describe "Private Project Snippets Access", feature: true do +describe "Private Project Snippets Access" do include AccessMatchers - let(:project) { create(:empty_project, :private) } + let(:project) { create(:project, :private) } let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) } describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -22,7 +22,7 @@ describe "Private Project Snippets Access", feature: true do end describe "GET /:project_path/snippets/new" do - subject { new_namespace_project_snippet_path(project.namespace, project) } + subject { new_project_snippet_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -36,7 +36,7 @@ describe "Private Project Snippets Access", feature: true do end describe "GET /:project_path/snippets/:id for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -50,7 +50,7 @@ describe "Private Project Snippets Access", feature: true do end describe "GET /:project_path/snippets/:id/raw for a private snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { raw_project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb index f3329d0bc96..39b104bfe27 100644 --- a/spec/features/security/project/snippet/public_access_spec.rb +++ b/spec/features/security/project/snippet/public_access_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' -describe "Public Project Snippets Access", feature: true do +describe "Public Project Snippets Access" do include AccessMatchers - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:public_snippet) { create(:project_snippet, :public, project: project, author: project.owner) } let(:internal_snippet) { create(:project_snippet, :internal, project: project, author: project.owner) } let(:private_snippet) { create(:project_snippet, :private, project: project, author: project.owner) } describe "GET /:project_path/snippets" do - subject { namespace_project_snippets_path(project.namespace, project) } + subject { project_snippets_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -24,7 +24,7 @@ describe "Public Project Snippets Access", feature: true do end describe "GET /:project_path/snippets/new" do - subject { new_namespace_project_snippet_path(project.namespace, project) } + subject { new_project_snippet_path(project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -39,7 +39,7 @@ describe "Public Project Snippets Access", feature: true do describe "GET /:project_path/snippets/:id" do context "for a public snippet" do - subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } + subject { project_snippet_path(project, public_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -53,7 +53,7 @@ describe "Public Project Snippets Access", feature: true do end context "for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + subject { project_snippet_path(project, internal_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -67,7 +67,7 @@ describe "Public Project Snippets Access", feature: true do end context "for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -83,7 +83,7 @@ describe "Public Project Snippets Access", feature: true do describe "GET /:project_path/snippets/:id/raw" do context "for a public snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, public_snippet) } + subject { raw_project_snippet_path(project, public_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -97,7 +97,7 @@ describe "Public Project Snippets Access", feature: true do end context "for an internal snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } + subject { raw_project_snippet_path(project, internal_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -111,7 +111,7 @@ describe "Public Project Snippets Access", feature: true do end context "for a private snippet" do - subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + subject { raw_project_snippet_path(project, private_snippet) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index d7b6dda4946..b6367b88e17 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -1,9 +1,11 @@ require 'spec_helper' -feature 'Signup', feature: true do +feature 'Signup' do describe 'signup with no errors' do context "when sending confirmation email" do - before { stub_application_setting(send_user_confirmation_email: true) } + before do + stub_application_setting(send_user_confirmation_email: true) + end it 'creates the user account and sends a confirmation email' do user = build(:user) @@ -23,7 +25,9 @@ feature 'Signup', feature: true do end context "when not sending confirmation email" do - before { stub_application_setting(send_user_confirmation_email: false) } + before do + stub_application_setting(send_user_confirmation_email: false) + end it 'creates the user account and goes to dashboard' do user = build(:user) diff --git a/spec/features/snippets/create_snippet_spec.rb b/spec/features/snippets/create_snippet_spec.rb deleted file mode 100644 index 31a2d4ae984..00000000000 --- a/spec/features/snippets/create_snippet_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'rails_helper' - -feature 'Create Snippet', :js, feature: true do - before do - login_as :user - visit new_snippet_path - end - - scenario 'Authenticated user creates a snippet' do - fill_in 'personal_snippet_title', with: 'My Snippet Title' - page.within('.file-editor') do - find('.ace_editor').native.send_keys 'Hello World!' - end - - click_button 'Create snippet' - wait_for_requests - - expect(page).to have_content('My Snippet Title') - expect(page).to have_content('Hello World!') - end - - scenario 'Authenticated user creates a snippet with + in filename' do - fill_in 'personal_snippet_title', with: 'My Snippet Title' - page.within('.file-editor') do - find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name' - find('.ace_editor').native.send_keys 'Hello World!' - end - - click_button 'Create snippet' - wait_for_requests - - expect(page).to have_content('My Snippet Title') - expect(page).to have_content('snippet+file+name') - expect(page).to have_content('Hello World!') - end -end diff --git a/spec/features/snippets/explore_spec.rb b/spec/features/snippets/explore_spec.rb index fd097fe2e74..835fd90adc8 100644 --- a/spec/features/snippets/explore_spec.rb +++ b/spec/features/snippets/explore_spec.rb @@ -1,12 +1,12 @@ require 'rails_helper' -feature 'Explore Snippets', feature: true do +feature 'Explore Snippets' do let!(:public_snippet) { create(:personal_snippet, :public) } let!(:internal_snippet) { create(:personal_snippet, :internal) } let!(:private_snippet) { create(:personal_snippet, :private) } scenario 'User should see snippets that are not private' do - login_as create(:user) + sign_in create(:user) visit explore_snippets_path expect(page).to have_content(public_snippet.title) @@ -15,7 +15,7 @@ feature 'Explore Snippets', feature: true do end scenario 'External user should see only public snippets' do - login_as create(:user, :external) + sign_in create(:user, :external) visit explore_snippets_path expect(page).to have_content(public_snippet.title) diff --git a/spec/features/snippets/internal_snippet_spec.rb b/spec/features/snippets/internal_snippet_spec.rb index 93382f4c359..3a229612235 100644 --- a/spec/features/snippets/internal_snippet_spec.rb +++ b/spec/features/snippets/internal_snippet_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'Internal Snippets', feature: true, js: true do +feature 'Internal Snippets', js: true do let(:internal_snippet) { create(:personal_snippet, :internal) } describe 'normal user' do before do - login_as :user + sign_in(create(:user)) end scenario 'sees internal snippets' do diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb index f7afc174019..f1d0905738b 100644 --- a/spec/features/snippets/notes_on_personal_snippets_spec.rb +++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' -describe 'Comments on personal snippets', :js, feature: true do +describe 'Comments on personal snippets', :js do + include NoteInteractionHelpers + let!(:user) { create(:user) } let!(:snippet) { create(:personal_snippet, :public) } let!(:snippet_notes) do @@ -12,7 +14,7 @@ describe 'Comments on personal snippets', :js, feature: true do let!(:other_note) { create(:note_on_personal_snippet) } before do - login_as user + sign_in user visit snippet_path(snippet) end @@ -22,6 +24,8 @@ describe 'Comments on personal snippets', :js, feature: true do it 'contains notes for a snippet with correct action icons' do expect(page).to have_selector('#notes-list li', count: 2) + open_more_actions_dropdown(snippet_notes[0]) + # comment authored by current user page.within("#notes-list li#note_#{snippet_notes[0].id}") do expect(page).to have_content(snippet_notes[0].note) @@ -29,6 +33,9 @@ describe 'Comments on personal snippets', :js, feature: true do expect(page).to have_selector('.note-emoji-button') end + find('body').click # close dropdown + open_more_actions_dropdown(snippet_notes[1]) + page.within("#notes-list li#note_#{snippet_notes[1].id}") do expect(page).to have_content(snippet_notes[1].note) expect(page).not_to have_selector('.js-note-delete') @@ -40,8 +47,8 @@ describe 'Comments on personal snippets', :js, feature: true do context 'when submitting a note' do it 'shows a valid form' do is_expected.to have_css('.js-main-target-form', visible: true, count: 1) - expect(find('.js-main-target-form .js-comment-button').value). - to eq('Comment') + expect(find('.js-main-target-form .js-comment-button').value) + .to eq('Comment') page.within('.js-main-target-form') do expect(page).not_to have_link('Cancel') @@ -64,10 +71,28 @@ describe 'Comments on personal snippets', :js, feature: true do expect(find('div#notes')).to have_content('This is awesome!') end + + it 'should not have autocomplete' do + wait_for_requests + request_count_before = page.driver.network_traffic.count + + find('#note_note').native.send_keys('') + fill_in 'note[note]', with: '@' + + wait_for_requests + request_count_after = page.driver.network_traffic.count + + # This selector probably won't be in place even if autocomplete was enabled + # but we want to make sure + expect(page).not_to have_selector('.atwho-view') + expect(request_count_before).to eq(request_count_after) + end end context 'when editing a note' do it 'changes the text' do + open_more_actions_dropdown(snippet_notes[0]) + page.within("#notes-list li#note_#{snippet_notes[0].id}") do click_on 'Edit comment' end @@ -89,8 +114,10 @@ describe 'Comments on personal snippets', :js, feature: true do context 'when deleting a note' do it 'removes the note from the snippet detail page' do + open_more_actions_dropdown(snippet_notes[0]) + page.within("#notes-list li#note_#{snippet_notes[0].id}") do - click_on 'Remove comment' + click_on 'Delete comment' end wait_for_requests diff --git a/spec/features/snippets/public_snippets_spec.rb b/spec/features/snippets/public_snippets_spec.rb index afd945a8555..bdeeca7187e 100644 --- a/spec/features/snippets/public_snippets_spec.rb +++ b/spec/features/snippets/public_snippets_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'Public Snippets', :js, feature: true do +feature 'Public Snippets', :js do scenario 'Unauthenticated user should see public snippets' do public_snippet = create(:personal_snippet, :public) diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb index 146cd3af848..cd66a2cb20c 100644 --- a/spec/features/snippets/search_snippets_spec.rb +++ b/spec/features/snippets/search_snippets_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'Search Snippets', feature: true do +feature 'Search Snippets' do scenario 'User searches for snippets by title' do public_snippet = create(:personal_snippet, :public, title: 'Beginning and Middle') private_snippet = create(:personal_snippet, :private, title: 'Middle and End') - login_as private_snippet.author + sign_in private_snippet.author visit dashboard_snippets_path page.within '.search' do @@ -41,7 +41,7 @@ feature 'Search Snippets', feature: true do CONTENT ) - login_as create(:user) + sign_in create(:user) visit dashboard_snippets_path page.within '.search' do diff --git a/spec/features/snippets/show_spec.rb b/spec/features/snippets/show_spec.rb index 95fc1d2bb62..5a48f5774ca 100644 --- a/spec/features/snippets/show_spec.rb +++ b/spec/features/snippets/show_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Snippet', :js, feature: true do +feature 'Snippet', :js do let(:project) { create(:project, :repository) } let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content) } diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb new file mode 100644 index 00000000000..a919f5fa20b --- /dev/null +++ b/spec/features/snippets/user_creates_snippet_spec.rb @@ -0,0 +1,107 @@ +require 'rails_helper' + +feature 'User creates snippet', :js do + include DropzoneHelper + + let(:user) { create(:user) } + + before do + sign_in(user) + visit new_snippet_path + end + + def fill_form + fill_in 'personal_snippet_title', with: 'My Snippet Title' + fill_in 'personal_snippet_description', with: 'My Snippet **Description**' + page.within('.file-editor') do + find('.ace_editor').native.send_keys 'Hello World!' + end + end + + scenario 'Authenticated user creates a snippet' do + fill_form + + click_button('Create snippet') + wait_for_requests + + expect(page).to have_content('My Snippet Title') + page.within('.snippet-header .description') do + expect(page).to have_content('My Snippet Description') + expect(page).to have_selector('strong') + end + expect(page).to have_content('Hello World!') + end + + scenario 'previews a snippet with file' do + fill_in 'personal_snippet_description', with: 'My Snippet' + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + find('.js-md-preview-button').click + + page.within('#new_personal_snippet .md-preview') do + expect(page).to have_content('My Snippet') + + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/uploads/system/temp/\h{32}/banana_sample\.gif\z}) + + visit(link) + expect(page.status_code).to eq(200) + end + end + + scenario 'uploads a file when dragging into textarea' do + fill_form + + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + + expect(page.find_field("personal_snippet_description").value).to have_content('banana_sample') + + click_button('Create snippet') + wait_for_requests + + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/uploads/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z}) + + visit(link) + expect(page.status_code).to eq(200) + end + + scenario 'validation fails for the first time' do + fill_in 'personal_snippet_title', with: 'My Snippet Title' + click_button('Create snippet') + + expect(page).to have_selector('#error_explanation') + + fill_form + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + + click_button('Create snippet') + wait_for_requests + + expect(page).to have_content('My Snippet Title') + page.within('.snippet-header .description') do + expect(page).to have_content('My Snippet Description') + expect(page).to have_selector('strong') + end + expect(page).to have_content('Hello World!') + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/uploads/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z}) + + visit(link) + expect(page.status_code).to eq(200) + end + + scenario 'Authenticated user creates a snippet with + in filename' do + fill_in 'personal_snippet_title', with: 'My Snippet Title' + page.within('.file-editor') do + find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name' + find('.ace_editor').native.send_keys 'Hello World!' + end + + click_button 'Create snippet' + wait_for_requests + + expect(page).to have_content('My Snippet Title') + expect(page).to have_content('snippet+file+name') + expect(page).to have_content('Hello World!') + end +end diff --git a/spec/features/snippets/user_deletes_snippet_spec.rb b/spec/features/snippets/user_deletes_snippet_spec.rb new file mode 100644 index 00000000000..ae5b883c477 --- /dev/null +++ b/spec/features/snippets/user_deletes_snippet_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +feature 'User deletes snippet' do + let(:user) { create(:user) } + let(:content) { 'puts "test"' } + let(:snippet) { create(:personal_snippet, :public, content: content, author: user) } + + before do + sign_in(user) + + visit snippet_path(snippet) + end + + it 'deletes the snippet' do + first(:link, 'Delete').click + + expect(page).not_to have_content(snippet.title) + end +end diff --git a/spec/features/snippets/user_edits_snippet_spec.rb b/spec/features/snippets/user_edits_snippet_spec.rb new file mode 100644 index 00000000000..26070e508e2 --- /dev/null +++ b/spec/features/snippets/user_edits_snippet_spec.rb @@ -0,0 +1,58 @@ +require 'rails_helper' + +feature 'User edits snippet', :js do + include DropzoneHelper + + let(:file_name) { 'test.rb' } + let(:content) { 'puts "test"' } + + let(:user) { create(:user) } + let(:snippet) { create(:personal_snippet, :public, file_name: file_name, content: content, author: user) } + + before do + sign_in(user) + + visit edit_snippet_path(snippet) + wait_for_requests + end + + it 'updates the snippet' do + fill_in 'personal_snippet_title', with: 'New Snippet Title' + + click_button('Save changes') + wait_for_requests + + expect(page).to have_content('New Snippet Title') + end + + it 'updates the snippet with files attached' do + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + expect(page.find_field('personal_snippet_description').value).to have_content('banana_sample') + + click_button('Save changes') + wait_for_requests + + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/uploads/system/personal_snippet/#{snippet.id}/\h{32}/banana_sample\.gif\z}) + end + + it 'updates the snippet to make it internal' do + choose 'Internal' + + click_button 'Save changes' + wait_for_requests + + expect(page).to have_no_xpath("//i[@class='fa fa-lock']") + expect(page).to have_xpath("//i[@class='fa fa-shield']") + end + + it 'updates the snippet to make it public' do + choose 'Public' + + click_button 'Save changes' + wait_for_requests + + expect(page).to have_no_xpath("//i[@class='fa fa-lock']") + expect(page).to have_xpath("//i[@class='fa fa-globe']") + end +end diff --git a/spec/features/snippets/user_snippets_spec.rb b/spec/features/snippets/user_snippets_spec.rb index 191c2fb9a22..7bc27486787 100644 --- a/spec/features/snippets/user_snippets_spec.rb +++ b/spec/features/snippets/user_snippets_spec.rb @@ -1,13 +1,13 @@ require 'rails_helper' -feature 'User Snippets', feature: true do +feature 'User Snippets' do let(:author) { create(:user) } let!(:public_snippet) { create(:personal_snippet, :public, author: author, title: "This is a public snippet") } let!(:internal_snippet) { create(:personal_snippet, :internal, author: author, title: "This is an internal snippet") } let!(:private_snippet) { create(:personal_snippet, :private, author: author, title: "This is a private snippet") } background do - login_as author + sign_in author visit dashboard_snippets_path end diff --git a/spec/features/snippets_spec.rb b/spec/features/snippets_spec.rb index 70b16bfc810..96c50f6c804 100644 --- a/spec/features/snippets_spec.rb +++ b/spec/features/snippets_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -describe 'Snippets', feature: true do +describe 'Snippets' do context 'when the project has snippets' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } 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) diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb index af25eebed13..39d79a3327b 100644 --- a/spec/features/tags/master_creates_tag_spec.rb +++ b/spec/features/tags/master_creates_tag_spec.rb @@ -1,67 +1,85 @@ require 'spec_helper' -feature 'Master creates tag', feature: true do +feature 'Master creates tag' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :repository, namespace: user.namespace) } before do project.team << [user, :master] - login_with(user) - visit namespace_project_tags_path(project.namespace, project) + sign_in(user) end - scenario 'with an invalid name displays an error' do - create_tag_in_form(tag: 'v 1.0', ref: 'master') + context 'from tag list' do + before do + visit project_tags_path(project) + end - expect(page).to have_content 'Tag name invalid' - end + scenario 'with an invalid name displays an error' do + create_tag_in_form(tag: 'v 1.0', ref: 'master') - scenario 'with an invalid reference displays an error' do - create_tag_in_form(tag: 'v2.0', ref: 'foo') + expect(page).to have_content 'Tag name invalid' + end - expect(page).to have_content 'Target foo is invalid' - end + scenario 'with an invalid reference displays an error' do + create_tag_in_form(tag: 'v2.0', ref: 'foo') - scenario 'that already exists displays an error' do - create_tag_in_form(tag: 'v1.1.0', ref: 'master') + expect(page).to have_content 'Target foo is invalid' + end - expect(page).to have_content 'Tag v1.1.0 already exists' - end + scenario 'that already exists displays an error' do + create_tag_in_form(tag: 'v1.1.0', ref: 'master') + + expect(page).to have_content 'Tag v1.1.0 already exists' + end - scenario 'with multiline message displays the message in a <pre> block' do - create_tag_in_form(tag: 'v3.0', ref: 'master', message: "Awesome tag message\n\n- hello\n- world") + scenario 'with multiline message displays the message in a <pre> block' do + create_tag_in_form(tag: 'v3.0', ref: 'master', message: "Awesome tag message\n\n- hello\n- world") - expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v3.0')) - expect(page).to have_content 'v3.0' - page.within 'pre.wrap' do - expect(page).to have_content "Awesome tag message\n\n- hello\n- world" + expect(current_path).to eq( + project_tag_path(project, 'v3.0')) + expect(page).to have_content 'v3.0' + page.within 'pre.wrap' do + expect(page).to have_content "Awesome tag message\n\n- hello\n- world" + end end - end - scenario 'with multiline release notes parses the release note as Markdown' do - create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world") + scenario 'with multiline release notes parses the release note as Markdown' do + create_tag_in_form(tag: 'v4.0', ref: 'master', desc: "Awesome release notes\n\n- hello\n- world") - expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v4.0')) - expect(page).to have_content 'v4.0' - page.within '.description' do - expect(page).to have_content 'Awesome release notes' - expect(page).to have_selector('ul li', count: 2) + expect(current_path).to eq( + project_tag_path(project, 'v4.0')) + expect(page).to have_content 'v4.0' + page.within '.description' do + expect(page).to have_content 'Awesome release notes' + expect(page).to have_selector('ul li', count: 2) + end + end + + scenario 'opens dropdown for ref', js: true do + click_link 'New tag' + ref_row = find('.form-group:nth-of-type(2) .col-sm-10') + page.within ref_row do + ref_input = find('[name="ref"]', visible: false) + expect(ref_input.value).to eq 'master' + expect(find('.dropdown-toggle-text')).to have_content 'master' + + find('.js-branch-select').trigger('click') + + expect(find('.dropdown-menu')).to have_content 'empty-branch' + end end end - scenario 'opens dropdown for ref', js: true do - click_link 'New tag' - ref_row = find('.form-group:nth-of-type(2) .col-sm-10') - page.within ref_row do - ref_input = find('[name="ref"]', visible: false) - expect(ref_input.value).to eq 'master' - expect(find('.dropdown-toggle-text')).to have_content 'master' + context 'from new tag page' do + before do + visit new_project_tag_path(project) + end - find('.js-branch-select').trigger('click') + it 'description has autocomplete', :js do + find('#release_description').native.send_keys('') + fill_in 'release_description', with: '@' - expect(find('.dropdown-menu')).to have_content 'empty-branch' + expect(page).to have_selector('.atwho-view') end end diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb index ccfafe6db7d..4d6fc13557f 100644 --- a/spec/features/tags/master_deletes_tag_spec.rb +++ b/spec/features/tags/master_deletes_tag_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Master deletes tag', feature: true do +feature 'Master deletes tag' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :repository, namespace: user.namespace) } before do project.team << [user, :master] - login_with(user) - visit namespace_project_tags_path(project.namespace, project) + sign_in(user) + visit project_tags_path(project) end context 'from the tags list page', js: true do @@ -24,12 +24,12 @@ feature 'Master deletes tag', feature: true do scenario 'deletes the tag' do click_on 'v1.0.0' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.0.0')) + project_tag_path(project, 'v1.0.0')) click_on 'Delete tag' expect(current_path).to eq( - namespace_project_tags_path(project.namespace, project)) + project_tags_path(project)) expect(page).not_to have_content 'v1.0.0' end end diff --git a/spec/features/tags/master_updates_tag_spec.rb b/spec/features/tags/master_updates_tag_spec.rb index 6b5b3122f72..b93ad44dfd3 100644 --- a/spec/features/tags/master_updates_tag_spec.rb +++ b/spec/features/tags/master_updates_tag_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -feature 'Master updates tag', feature: true do +feature 'Master updates tag' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :repository, namespace: user.namespace) } before do project.team << [user, :master] - login_with(user) - visit namespace_project_tags_path(project.namespace, project) + sign_in(user) + visit project_tags_path(project) end context 'from the tags list page' do @@ -20,10 +20,21 @@ feature 'Master updates tag', feature: true do click_button 'Save changes' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.1.0')) + project_tag_path(project, 'v1.1.0')) expect(page).to have_content 'v1.1.0' expect(page).to have_content 'Awesome release notes' end + + scenario 'description has autocomplete', :js do + page.within(first('.content-list .controls')) do + click_link 'Edit release notes' + end + + find('#release_description').native.send_keys('') + fill_in 'release_description', with: '@' + + expect(page).to have_selector('.atwho-view') + end end context 'from a specific tag page' do @@ -34,7 +45,7 @@ feature 'Master updates tag', feature: true do click_button 'Save changes' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.1.0')) + project_tag_path(project, 'v1.1.0')) expect(page).to have_content 'v1.1.0' expect(page).to have_content 'Awesome release notes' end diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb index 922ac15a2eb..9edc7ced163 100644 --- a/spec/features/tags/master_views_tags_spec.rb +++ b/spec/features/tags/master_views_tags_spec.rb @@ -1,23 +1,23 @@ require 'spec_helper' -feature 'Master views tags', feature: true do +feature 'Master views tags' do let(:user) { create(:user) } before do project.team << [user, :master] - login_with(user) + sign_in(user) end context 'when project has no tags' do let(:project) { create(:project_empty_repo) } before do - visit namespace_project_path(project.namespace, project) + visit project_path(project) click_on 'README' fill_in :commit_message, with: 'Add a README file', visible: true # Remove pre-receive hook so we can push without auth FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive')) click_button 'Commit changes' - visit namespace_project_tags_path(project.namespace, project) + visit project_tags_path(project) end scenario 'displays a specific message' do @@ -26,19 +26,19 @@ feature 'Master views tags', feature: true do end context 'when project has tags' do - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :repository, namespace: user.namespace) } let(:repository) { project.repository } before do - visit namespace_project_tags_path(project.namespace, project) + visit project_tags_path(project) end scenario 'avoids a N+1 query in branches index' do - control_count = ActiveRecord::QueryRecorder.new { visit namespace_project_tags_path(project.namespace, project) }.count + control_count = ActiveRecord::QueryRecorder.new { visit project_tags_path(project) }.count %w(one two three four five).each { |tag| repository.add_tag(user, tag, 'master', 'foo') } - expect { visit namespace_project_tags_path(project.namespace, project) }.not_to exceed_query_limit(control_count) + expect { visit project_tags_path(project) }.not_to exceed_query_limit(control_count) end scenario 'views the tags list page' do @@ -49,7 +49,7 @@ feature 'Master views tags', feature: true do click_on 'v1.0.0' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.0.0')) + project_tag_path(project, 'v1.0.0')) expect(page).to have_content 'v1.0.0' expect(page).to have_content 'This tag has no release notes.' end @@ -59,24 +59,24 @@ feature 'Master views tags', feature: true do click_on 'v1.0.0' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.0.0')) + project_tag_path(project, 'v1.0.0')) click_on 'Browse files' expect(current_path).to eq( - namespace_project_tree_path(project.namespace, project, 'v1.0.0')) + project_tree_path(project, 'v1.0.0')) end scenario 'has a button to browse commits' do click_on 'v1.0.0' expect(current_path).to eq( - namespace_project_tag_path(project.namespace, project, 'v1.0.0')) + project_tag_path(project, 'v1.0.0')) click_on 'Browse commits' expect(current_path).to eq( - namespace_project_commits_path(project.namespace, project, 'v1.0.0')) + project_commits_path(project, 'v1.0.0')) end end end diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index 563e65d3cc5..c14826df55a 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -feature 'Task Lists', feature: true do +feature 'Task Lists' do include Warden::Test::Helpers - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:user) { create(:user) } let(:user2) { create(:user) } @@ -59,10 +59,10 @@ feature 'Task Lists', feature: true do end def visit_issue(project, issue) - visit namespace_project_issue_path(project.namespace, project, issue) + visit project_issue_path(project, issue) end - describe 'for Issues', feature: true do + describe 'for Issues' do describe 'multiple tasks', js: true do let!(:issue) { create(:issue, description: markdown, author: user, project: project) } @@ -98,7 +98,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on Issues#index' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(page).to have_content("2 of 6 tasks completed") end end @@ -116,7 +116,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on Issues#index' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(page).to have_content("0 of 1 task completed") end @@ -135,7 +135,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on Issues#index' do - visit namespace_project_issues_path(project.namespace, project) + visit project_issues_path(project) expect(page).to have_content("1 of 1 task completed") end @@ -144,7 +144,9 @@ feature 'Task Lists', feature: true do describe 'nested tasks', js: true do let(:issue) { create(:issue, description: nested_tasks_markdown, author: user, project: project) } - before { visit_issue(project, issue) } + before do + visit_issue(project, issue) + end it 'renders' do expect(page).to have_selector('ul.task-list', count: 2) @@ -240,7 +242,7 @@ feature 'Task Lists', feature: true do describe 'for Merge Requests' do def visit_merge_request(project, merge) - visit namespace_project_merge_request_path(project.namespace, project, merge) + visit project_merge_request_path(project, merge) end describe 'multiple tasks' do @@ -279,7 +281,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on MergeRequests#index' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).to have_content("2 of 6 tasks completed") end end @@ -296,7 +298,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on MergeRequests#index' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).to have_content("0 of 1 task completed") end end @@ -313,7 +315,7 @@ feature 'Task Lists', feature: true do end it 'provides a summary on MergeRequests#index' do - visit namespace_project_merge_requests_path(project.namespace, project) + visit project_merge_requests_path(project) expect(page).to have_content("1 of 1 task completed") end end diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb deleted file mode 100644 index bb4b2aed0e3..00000000000 --- a/spec/features/todos/todos_spec.rb +++ /dev/null @@ -1,378 +0,0 @@ -require 'spec_helper' - -describe 'Dashboard Todos', feature: true do - let(:user) { create(:user) } - let(:author) { create(:user) } - let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:issue) { create(:issue, due_date: Date.today) } - - describe 'GET /dashboard/todos' do - context 'User does not have todos' do - before do - login_as(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) - login_as(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 - login_as(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) - login_as(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, visibility_level: Gitlab::VisibilityLevel::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) - - login_as(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) - - login_as(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 Todo in a project pending deletion' do - before do - deleted_project = create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC, pending_delete: true) - create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author) - create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author, state: :done) - login_as(user) - visit dashboard_todos_path - end - - it 'shows "All done" message' do - within('.todos-count') { expect(page).to have_content '0' } - expect(page).to have_content 'To do 0' - expect(page).to have_content 'Done 0' - expect(page).to have_selector('.todos-all-done', count: 1) - end - end - - context 'User have large number of todos' do - before do - create_list(:todo, 101, :mentioned, user: user, project: project, target: issue, author: author) - - login_as(user) - visit dashboard_todos_path - end - - it 'shows 99+ for count >= 100 in notification' do - expect(page).to have_selector('.todos-count', text: '99+') - end - - it 'shows exact number in To do tab' do - expect(page).to have_selector('.todos-pending .badge', text: '101') - end - - it 'shows exact number for count < 100' do - 3.times { first('.js-done-todo').click } - - expect(page).to have_selector('.todos-count', text: '98') - end - end - - context 'User has a Build Failed todo' do - let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) } - - before do - login_as 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_namespace_project_merge_request_path(project.namespace, project, todo.target) - - expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href - end - end - end -end diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb index c1ae6db00c6..8d12a492feb 100644 --- a/spec/features/triggers_spec.rb +++ b/spec/features/triggers_spec.rb @@ -1,18 +1,20 @@ require 'spec_helper' -feature 'Triggers', feature: true, js: true do +feature 'Triggers', js: true do let(:trigger_title) { 'trigger desc' } let(:user) { create(:user) } let(:user2) { create(:user) } let(:guest_user) { create(:user) } - before { login_as(user) } before do - @project = create(:empty_project) + sign_in(user) + + @project = create(:project) @project.team << [user, :master] @project.team << [user2, :master] @project.team << [guest_user, :guest] - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + + visit project_settings_ci_cd_path(@project) end describe 'create trigger workflow' do @@ -31,7 +33,7 @@ feature 'Triggers', feature: true, js: true do # See if "trigger creation successful" message displayed and description and owner are correct expect(page.find('.flash-notice')).to have_content 'Trigger was created successfully.' expect(page.find('.triggers-list')).to have_content 'trigger desc' - expect(page.find('.triggers-list .trigger-owner')).to have_content @user.name + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name end end @@ -40,7 +42,7 @@ feature 'Triggers', feature: true, js: true do scenario 'click on edit trigger opens edit trigger page' do create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if edit page has correct descrption find('a[title="Edit"]').click @@ -49,7 +51,7 @@ feature 'Triggers', feature: true, js: true do scenario 'edit trigger and save' do create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if edit page opens, then fill in new description and save find('a[title="Edit"]').click @@ -59,13 +61,13 @@ feature 'Triggers', feature: true, js: true do # See if "trigger updated successfully" message displayed and description and owner are correct expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.' expect(page.find('.triggers-list')).to have_content new_trigger_title - expect(page.find('.triggers-list .trigger-owner')).to have_content @user.name + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name end scenario 'edit "legacy" trigger and save' do # Create new trigger without owner association, i.e. Legacy trigger create(:ci_trigger, owner: nil, project: @project) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if the trigger can be edited and description is blank find('a[title="Edit"]').click @@ -82,7 +84,7 @@ feature 'Triggers', feature: true, js: true do describe 'trigger "Take ownership" workflow' do before(:each) do create(:ci_trigger, owner: user2, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) end scenario 'button "Take ownership" has correct alert' do @@ -96,7 +98,7 @@ feature 'Triggers', feature: true, js: true do page.accept_confirm do expect(page.find('.flash-notice')).to have_content 'Trigger was re-assigned.' expect(page.find('.triggers-list')).to have_content trigger_title - expect(page.find('.triggers-list .trigger-owner')).to have_content @user.name + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name end end end @@ -104,7 +106,7 @@ feature 'Triggers', feature: true, js: true do describe 'trigger "Revoke" workflow' do before(:each) do create(:ci_trigger, owner: user2, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) end scenario 'button "Revoke" has correct alert' do @@ -129,7 +131,7 @@ feature 'Triggers', feature: true, js: true do scenario 'show "legacy" badge for legacy trigger' do create(:ci_trigger, owner: nil, project: @project) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if trigger without owner (i.e. legacy) shows "legacy" badge and is editable expect(page.find('.triggers-list')).to have_content 'legacy' @@ -138,7 +140,7 @@ feature 'Triggers', feature: true, js: true do scenario 'show "invalid" badge for trigger with owner having insufficient permissions' do create(:ci_trigger, owner: guest_user, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if trigger without owner (i.e. legacy) shows "legacy" badge and is non-editable expect(page.find('.triggers-list')).to have_content 'invalid' @@ -148,27 +150,27 @@ feature 'Triggers', feature: true, js: true do scenario 'do not show "Edit" or full token for not owned trigger' do # Create trigger with user different from current_user create(:ci_trigger, owner: user2, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if trigger not owned by current_user shows only first few token chars and doesn't have copy-to-clipboard button expect(page.find('.triggers-list')).to have_content(@project.triggers.first.token[0..3]) expect(page.find('.triggers-list')).not_to have_selector('button.btn-clipboard') # See if trigger owner name doesn't match with current_user and trigger is non-editable - expect(page.find('.triggers-list .trigger-owner')).not_to have_content @user.name + expect(page.find('.triggers-list .trigger-owner')).not_to have_content user.name expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]') end scenario 'show "Edit" and full token for owned trigger' do create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit namespace_project_settings_ci_cd_path(@project.namespace, @project) + visit project_settings_ci_cd_path(@project) # See if trigger shows full token and has copy-to-clipboard button expect(page.find('.triggers-list')).to have_content @project.triggers.first.token expect(page.find('.triggers-list')).to have_selector('button.btn-clipboard') # See if trigger owner name matches with current_user and is editable - expect(page.find('.triggers-list .trigger-owner')).to have_content @user.name + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]') end end diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb index 2fed8067042..f3662cb184f 100644 --- a/spec/features/u2f_spec.rb +++ b/spec/features/u2f_spec.rb @@ -1,7 +1,9 @@ require 'spec_helper' feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do - before { allow_any_instance_of(U2fHelper).to receive(:inject_u2f_api?).and_return(true) } + before do + allow_any_instance_of(U2fHelper).to receive(:inject_u2f_api?).and_return(true) + end def manage_two_factor_authentication click_on 'Manage two-factor authentication' @@ -23,12 +25,14 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do let(:user) { create(:user) } before do - login_as(user) + gitlab_sign_in(user) user.update_attribute(:otp_required_for_login, true) end describe 'when 2FA via OTP is disabled' do - before { user.update_attribute(:otp_required_for_login, false) } + before do + user.update_attribute(:otp_required_for_login, false) + end it 'does not allow registering a new device' do visit profile_account_path @@ -89,10 +93,10 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do manage_two_factor_authentication u2f_device = register_u2f_device expect(page).to have_content('Your U2F device was registered') - logout + gitlab_sign_out # Second user - user = login_as(:user) + user = gitlab_sign_in(:user) user.update_attribute(:otp_required_for_login, true) visit profile_account_path manage_two_factor_authentication @@ -143,18 +147,18 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do before do # Register and logout - login_as(user) + gitlab_sign_in(user) user.update_attribute(:otp_required_for_login, true) visit profile_account_path manage_two_factor_authentication @u2f_device = register_u2f_device - logout + gitlab_sign_out end describe "when 2FA via OTP is disabled" do it "allows logging in with the U2F device" do user.update_attribute(:otp_required_for_login, false) - login_with(user) + gitlab_sign_in(user) @u2f_device.respond_to_u2f_authentication @@ -166,7 +170,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do describe "when 2FA via OTP is enabled" do it "allows logging in with the U2F device" do user.update_attribute(:otp_required_for_login, true) - login_with(user) + gitlab_sign_in(user) @u2f_device.respond_to_u2f_authentication @@ -176,7 +180,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do end it 'persists remember_me value via hidden field' do - login_with(user, remember: true) + gitlab_sign_in(user, remember: true) @u2f_device.respond_to_u2f_authentication expect(page).to have_content('We heard back from your U2F device') @@ -191,15 +195,15 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do describe "but not the current user" do it "does not allow logging in with that particular device" do # Register current user with the different U2F device - current_user = login_as(:user) + current_user = gitlab_sign_in(:user) current_user.update_attribute(:otp_required_for_login, true) visit profile_account_path manage_two_factor_authentication register_u2f_device(name: 'My other device') - logout + gitlab_sign_out # Try authenticating user with the old U2F device - login_as(current_user) + gitlab_sign_in(current_user) @u2f_device.respond_to_u2f_authentication expect(page).to have_content('We heard back from your U2F device') expect(page).to have_content('Authentication via U2F device failed') @@ -209,15 +213,15 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do describe "and also the current user" do it "allows logging in with that particular device" do # Register current user with the same U2F device - current_user = login_as(:user) + current_user = gitlab_sign_in(:user) current_user.update_attribute(:otp_required_for_login, true) visit profile_account_path manage_two_factor_authentication register_u2f_device(@u2f_device) - logout + gitlab_sign_out # Try authenticating user with the same U2F device - login_as(current_user) + gitlab_sign_in(current_user) @u2f_device.respond_to_u2f_authentication expect(page).to have_content('We heard back from your U2F device') @@ -229,7 +233,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do describe "when a given U2F device has not been registered" do it "does not allow logging in with that particular device" do unregistered_device = FakeU2fDevice.new(page, 'My device') - login_as(user) + gitlab_sign_in(user) unregistered_device.respond_to_u2f_authentication expect(page).to have_content('We heard back from your U2F device') @@ -240,7 +244,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do describe "when more than one device has been registered by the same user" do it "allows logging in with either device" do # Register first device - user = login_as(:user) + user = gitlab_sign_in(:user) user.update_attribute(:otp_required_for_login, true) visit profile_two_factor_auth_path expect(page).to have_content("Your U2F device needs to be set up.") @@ -250,17 +254,17 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do visit profile_two_factor_auth_path expect(page).to have_content("Your U2F device needs to be set up.") second_device = register_u2f_device(name: 'My other device') - logout + gitlab_sign_out # Authenticate as both devices [first_device, second_device].each do |device| - login_as(user) + gitlab_sign_in(user) device.respond_to_u2f_authentication expect(page).to have_content('We heard back from your U2F device') expect(page).to have_css('.sign-out-link', visible: false) - logout + gitlab_sign_out end end end @@ -269,7 +273,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do let(:user) { create(:user) } before do - user = login_as(:user) + user = gitlab_sign_in(:user) user.update_attribute(:otp_required_for_login, true) visit profile_account_path manage_two_factor_authentication @@ -296,15 +300,15 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do before do # Register and logout - login_as(user) + gitlab_sign_in(user) user.update_attribute(:otp_required_for_login, true) visit profile_account_path end describe 'when no u2f device is registered' do before do - logout - login_with(user) + gitlab_sign_out + gitlab_sign_in(user) end it 'shows the fallback otp code UI' do @@ -316,8 +320,8 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do before do manage_two_factor_authentication @u2f_device = register_u2f_device - logout - login_with(user) + gitlab_sign_out + gitlab_sign_in(user) end it 'provides a button that shows the fallback otp code UI' do diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index 8509551ce4a..392d8e3e1c1 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' -describe 'Unsubscribe links', feature: true do +describe 'Unsubscribe links' do include Warden::Test::Helpers let(:recipient) { create(:user) } let(:author) { create(:user) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project, :public) } let(:params) { { title: 'A bug!', description: 'Fix it!', assignees: [recipient] } } let(:issue) { Issues::CreateService.new(project, author, params).execute } @@ -56,7 +56,9 @@ describe 'Unsubscribe links', feature: true do end context 'when logged in' do - before { login_as(recipient) } + before do + sign_in(recipient) + end it 'unsubscribes from the issue when visiting the link from the email body' do visit body_link diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb index f88a515f7fc..e8884bc1a00 100644 --- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -feature 'User uploads avatar to group', feature: true do +feature 'User uploads avatar to group' do scenario 'they see the new avatar' do user = create(:user) group = create(:group) group.add_owner(user) - login_as(user) + sign_in(user) visit edit_group_path(group) attach_file( @@ -18,7 +18,7 @@ feature 'User uploads avatar to group', feature: true do visit group_path(group) - expect(page).to have_selector(%Q(img[src$="/uploads/group/avatar/#{group.id}/dk.png"])) + expect(page).to have_selector(%Q(img[data-src$="/uploads/-/system/group/avatar/#{group.id}/dk.png"])) # Cheating here to verify something that isn't user-facing, but is important expect(group.reload.avatar.file).to exist diff --git a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb index 0dfd29045e5..52003bb0859 100644 --- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' -feature 'User uploads avatar to profile', feature: true do +feature 'User uploads avatar to profile' do scenario 'they see their new avatar' do user = create(:user) - login_as(user) + sign_in(user) visit profile_path attach_file( @@ -16,7 +16,7 @@ feature 'User uploads avatar to profile', feature: true do visit user_path(user) - expect(page).to have_selector(%Q(img[src$="/uploads/user/avatar/#{user.id}/dk.png"])) + expect(page).to have_selector(%Q(img[data-src$="/uploads/-/system/user/avatar/#{user.id}/dk.png"])) # Cheating here to verify something that isn't user-facing, but is important expect(user.reload.avatar.file).to exist diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb index 9332d3b88d2..53cad623a35 100644 --- a/spec/features/uploads/user_uploads_file_to_note_spec.rb +++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb @@ -1,15 +1,15 @@ require 'rails_helper' -feature 'User uploads file to note', feature: true do +feature 'User uploads file to note' do include DropzoneHelper let(:user) { create(:user) } - let(:project) { create(:empty_project, creator: user, namespace: user.namespace) } + let(:project) { create(:project, creator: user, namespace: user.namespace) } let(:issue) { create(:issue, project: project, author: user) } before do - login_as(user) - visit namespace_project_issue_path(project.namespace, project, issue) + sign_in(user) + visit project_issue_path(project, issue) end context 'before uploading' do diff --git a/spec/features/user_callout_spec.rb b/spec/features/user_callout_spec.rb index b84f834ff1e..37d66b618af 100644 --- a/spec/features/user_callout_spec.rb +++ b/spec/features/user_callout_spec.rb @@ -3,10 +3,10 @@ require 'spec_helper' describe 'User Callouts', js: true do let(:user) { create(:user) } let(:another_user) { create(:user) } - let(:project) { create(:empty_project, path: 'gitlab', name: 'sample') } + let(:project) { create(:project, path: 'gitlab', name: 'sample') } before do - login_as(user) + sign_in(user) project.team << [user, :master] end diff --git a/spec/features/user_can_display_performance_bar_spec.rb b/spec/features/user_can_display_performance_bar_spec.rb new file mode 100644 index 00000000000..670e8dda916 --- /dev/null +++ b/spec/features/user_can_display_performance_bar_spec.rb @@ -0,0 +1,86 @@ +require 'rails_helper' + +describe 'User can display performance bar', :js do + shared_examples 'performance bar is disabled' do + it 'does not show the performance bar by default' do + expect(page).not_to have_css('#peek') + end + + context 'when user press `pb`' do + before do + find('body').native.send_keys('pb') + end + + it 'does not show the performance bar by default' do + expect(page).not_to have_css('#peek') + end + end + end + + shared_examples 'performance bar is enabled' do + it 'does not show the performance bar by default' do + expect(page).not_to have_css('#peek') + end + + context 'when user press `pb`' do + before do + find('body').native.send_keys('pb') + end + + it 'shows the performance bar' do + expect(page).to have_css('#peek') + end + end + end + + let(:group) { create(:group) } + + context 'when user is logged-out' do + before do + visit root_path + end + + context 'when the performance_bar feature is disabled' do + before do + stub_application_setting(performance_bar_allowed_group_id: nil) + end + + it_behaves_like 'performance bar is disabled' + end + + context 'when the performance_bar feature is enabled' do + before do + stub_application_setting(performance_bar_allowed_group_id: group.id) + end + + it_behaves_like 'performance bar is disabled' + end + end + + context 'when user is logged-in' do + before do + user = create(:user) + + sign_in(user) + group.add_guest(user) + + visit root_path + end + + context 'when the performance_bar feature is disabled' do + before do + stub_application_setting(performance_bar_allowed_group_id: nil) + end + + it_behaves_like 'performance bar is disabled' + end + + context 'when the performance_bar feature is enabled' do + before do + stub_application_setting(performance_bar_allowed_group_id: group.id) + end + + it_behaves_like 'performance bar is enabled' + end + end +end diff --git a/spec/features/users/projects_spec.rb b/spec/features/users/projects_spec.rb index 67ce4b44464..f079771cee1 100644 --- a/spec/features/users/projects_spec.rb +++ b/spec/features/users/projects_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' -describe 'Projects tab on a user profile', :feature, :js do +describe 'Projects tab on a user profile', :js do let(:user) { create(:user) } - let!(:project) { create(:empty_project, namespace: user.namespace) } - let!(:project2) { create(:empty_project, namespace: user.namespace) } + let!(:project) { create(:project, namespace: user.namespace) } + let!(:project2) { create(:project, namespace: user.namespace) } before do allow(Project).to receive(:default_per_page).and_return(1) - login_as(user) + sign_in(user) visit user_path(user) diff --git a/spec/features/users/rss_spec.rb b/spec/features/users/rss_spec.rb index dbd5f66b55e..7c5abe54d56 100644 --- a/spec/features/users/rss_spec.rb +++ b/spec/features/users/rss_spec.rb @@ -1,11 +1,12 @@ require 'spec_helper' feature 'User RSS' do + let(:user) { create(:user) } let(:path) { user_path(create(:user)) } context 'when signed in' do before do - login_as(create(:user)) + sign_in(user) visit path end diff --git a/spec/features/users/snippets_spec.rb b/spec/features/users/snippets_spec.rb index 2e388115633..13760b4c2fc 100644 --- a/spec/features/users/snippets_spec.rb +++ b/spec/features/users/snippets_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Snippets tab on a user profile', feature: true, js: true do +describe 'Snippets tab on a user profile', js: true do context 'when the user has snippets' do let(:user) { create(:user) } @@ -24,7 +24,7 @@ describe 'Snippets tab on a user profile', feature: true, js: true do let!(:other_snippet) { create(:snippet, :public) } it 'contains only internal and public snippets of a user when a user is logged in' do - login_as(:user) + sign_in(create(:user)) visit user_path(user) page.within('.user-profile-nav') { click_link 'Snippets' } wait_for_requests diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index fbe078bd136..ff004d85272 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Users', feature: true, js: true do +feature 'Users', js: true do let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } scenario 'GET /users/sign_in creates a new user account' do @@ -24,7 +24,7 @@ feature 'Users', feature: true, js: true do user.reload expect(user.reset_password_token).not_to be_nil - login_with(user) + gitlab_sign_in(user) expect(current_path).to eq root_path user.reload @@ -45,7 +45,9 @@ feature 'Users', feature: true, js: true do end describe 'redirect alias routes' do - before { user } + before do + expect(user).to be_persisted + end scenario '/u/user1 redirects to user page' do visit '/u/user1' diff --git a/spec/features/variables_spec.rb b/spec/features/variables_spec.rb index d0c982919db..6794bf4f4ba 100644 --- a/spec/features/variables_spec.rb +++ b/spec/features/variables_spec.rb @@ -2,15 +2,15 @@ require 'spec_helper' describe 'Project variables', js: true do let(:user) { create(:user) } - let(:project) { create(:empty_project) } + let(:project) { create(:project) } let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') } before do - login_as(user) + sign_in(user) project.team << [user, :master] project.variables << variable - visit namespace_project_settings_ci_cd_path(project.namespace, project) + visit project_settings_ci_cd_path(project) end it 'shows list of variables' do @@ -24,7 +24,7 @@ describe 'Project variables', js: true do fill_in('variable_value', with: 'key value') click_button('Add new variable') - expect(page).to have_content('Variables were successfully updated.') + expect(page).to have_content('Variable was successfully created.') page.within('.variables-table') do expect(page).to have_content('key') expect(page).to have_content('No') @@ -36,7 +36,7 @@ describe 'Project variables', js: true do fill_in('variable_value', with: '') click_button('Add new variable') - expect(page).to have_content('Variables were successfully updated.') + expect(page).to have_content('Variable was successfully created.') page.within('.variables-table') do expect(page).to have_content('new_key') end @@ -48,7 +48,7 @@ describe 'Project variables', js: true do check('Protected') click_button('Add new variable') - expect(page).to have_content('Variables were successfully updated.') + expect(page).to have_content('Variable was successfully created.') page.within('.variables-table') do expect(page).to have_content('key') expect(page).to have_content('Yes') @@ -82,7 +82,7 @@ describe 'Project variables', js: true do it 'deletes variable' do page.within('.variables-table') do - find('.btn-variable-delete').click + click_on 'Remove' end expect(page).not_to have_selector('variables-table') @@ -90,7 +90,7 @@ describe 'Project variables', js: true do it 'edits variable' do page.within('.variables-table') do - find('.btn-variable-edit').click + click_on 'Update' end expect(page).to have_content('Update variable') @@ -104,7 +104,7 @@ describe 'Project variables', js: true do it 'edits variable with empty value' do page.within('.variables-table') do - find('.btn-variable-edit').click + click_on 'Update' end expect(page).to have_content('Update variable') @@ -117,7 +117,7 @@ describe 'Project variables', js: true do it 'edits variable to be protected' do page.within('.variables-table') do - find('.btn-variable-edit').click + click_on 'Update' end expect(page).to have_content('Update variable') @@ -132,7 +132,7 @@ describe 'Project variables', js: true do project.variables.first.update(protected: true) page.within('.variables-table') do - find('.btn-variable-edit').click + click_on 'Update' end expect(page).to have_content('Update variable') |
