diff options
author | Clement Ho <ClemMakesApps@gmail.com> | 2018-05-08 18:49:30 +0300 |
---|---|---|
committer | Clement Ho <ClemMakesApps@gmail.com> | 2018-05-08 18:49:30 +0300 |
commit | 5955caed321e242bfebe52a4b47346a01a50e4f6 (patch) | |
tree | d9710c0732ce21801b4a79a281bec0bd39582a95 /spec/features | |
parent | f9e2b4730f58ba630344c9554eb907ab003abbd5 (diff) | |
parent | 533593e95cd3a922a2ec2ea43b345862361dfd67 (diff) |
Merge branch 'master' into bootstrap4
Diffstat (limited to 'spec/features')
41 files changed, 1525 insertions, 441 deletions
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 8de2e3d199b..3465ccfc423 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -59,6 +59,47 @@ describe "Admin Runners" do expect(page).to have_text 'No runners found' end end + + context 'group runner' do + let(:group) { create(:group) } + let!(:runner) { create(:ci_runner, groups: [group], runner_type: :group_type) } + + it 'shows the label and does not show the project count' do + visit admin_runners_path + + within "#runner_#{runner.id}" do + expect(page).to have_selector '.label', text: 'group' + expect(page).to have_text 'n/a' + end + end + end + + context 'shared runner' do + it 'shows the label and does not show the project count' do + runner = create :ci_runner, :shared + + visit admin_runners_path + + within "#runner_#{runner.id}" do + expect(page).to have_selector '.label', text: 'shared' + expect(page).to have_text 'n/a' + end + end + end + + context 'specific runner' do + it 'shows the label and the project count' do + project = create :project + runner = create :ci_runner, projects: [project] + + visit admin_runners_path + + within "#runner_#{runner.id}" do + expect(page).to have_selector '.label', text: 'specific' + expect(page).to have_text '1' + end + end + end end describe "Runner show page" do diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 7853d2952ea..f2f9b734c39 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -2,10 +2,13 @@ require 'spec_helper' feature 'Admin updates settings' do include StubENV + include TermsHelper + + let(:admin) { create(:admin) } before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - sign_in(create(:admin)) + sign_in(admin) visit admin_application_settings_path end @@ -85,6 +88,22 @@ feature 'Admin updates settings' do expect(page).to have_content "Application settings saved successfully" end + scenario 'Terms of Service' do + # Already have the admin accept terms, so they don't need to accept in this spec. + _existing_terms = create(:term) + accept_terms(admin) + + page.within('.as-terms') do + check 'Require all users to accept Terms of Service when they access GitLab.' + fill_in 'Terms of Service Agreement', with: 'Be nice!' + click_button 'Save changes' + end + + expect(Gitlab::CurrentSettings.enforce_terms).to be(true) + expect(Gitlab::CurrentSettings.terms).to eq 'Be nice!' + expect(page).to have_content 'Application settings saved successfully' + end + scenario 'Modify oauth providers' do expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 9ec8bb0aefe..9e3221577c7 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -285,7 +285,7 @@ describe "Admin::Users" do it "lists group projects" do within(:css, '.append-bottom-default + .card') do expect(page).to have_content 'Group projects' - expect(page).to have_link group.name, admin_group_path(group) + expect(page).to have_link group.name, href: admin_group_path(group) end end diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index f1ac73ff819..90cf5a53787 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -19,7 +19,7 @@ feature 'Admin uses repository checks' do expect(page).to have_content('Repository check was triggered') end - scenario 'to see a single failed repository check' do + scenario 'to see a single failed repository check', :js do project = create(:project) project.update_columns( last_repository_check_failed: true, diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index ff2a0e15719..fd0aa6cf3a3 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -161,6 +161,7 @@ feature 'Issues > User uses quick actions', :js do before do target_project.add_master(user) + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end @@ -178,9 +179,10 @@ feature 'Issues > User uses quick actions', :js do end context 'when the project is valid but the user not authorized' do - let(:project_unauthorized) {create(:project, :public)} + let(:project_unauthorized) { create(:project, :public) } before do + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end @@ -195,6 +197,7 @@ feature 'Issues > User uses quick actions', :js do context 'when the project is invalid' do before do + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end @@ -218,6 +221,7 @@ feature 'Issues > User uses quick actions', :js do before do target_project.add_master(user) + gitlab_sign_out sign_in(user) visit project_issue_path(project, issue) end diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb index dbca279569a..42c279af117 100644 --- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb +++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb @@ -19,7 +19,7 @@ describe 'Merge request > User selects branches for new MR', :js do expect(page).to have_content('Target branch') first('.js-source-branch').click - find('.dropdown-source-branch .dropdown-content a', match: :first).click + find('.js-source-branch-dropdown .dropdown-content a', match: :first).click expect(page).to have_content "b83d6e3" end @@ -35,22 +35,16 @@ describe 'Merge request > User selects branches for new MR', :js do expect(page).to have_content('Target branch') first('.js-target-branch').click - find('.dropdown-target-branch .dropdown-content a', text: 'v1.1.0', match: :first).click + find('.js-target-branch-dropdown .dropdown-content a', text: 'v1.1.0', match: :first).click expect(page).to have_content "b83d6e3" end it 'generates a diff for an orphaned branch' do - visit project_merge_requests_path(project) - - page.within '.content' do - click_link 'New merge request' - end - expect(page).to have_content('Source branch') - expect(page).to have_content('Target branch') + visit project_new_merge_request_path(project) find('.js-source-branch', match: :first).click - find('.dropdown-source-branch .dropdown-content a', text: 'orphaned-branch', match: :first).click + find('.js-source-branch-dropdown .dropdown-content a', text: 'orphaned-branch', match: :first).click click_button "Compare branches" click_link "Changes" @@ -71,19 +65,18 @@ describe 'Merge request > User selects branches for new MR', :js do first('.js-source-branch').click - input = find('.dropdown-source-branch .dropdown-input-field') - input.click - input.send_keys('orphaned-branch') + page.within '.js-source-branch-dropdown' do + input = find('.dropdown-input-field') + input.click + input.send_keys('orphaned-branch') - find('.dropdown-source-branch .dropdown-content li', match: :first) - source_items = all('.dropdown-source-branch .dropdown-content li') - - expect(source_items.count).to eq(1) + expect(page).to have_css('.dropdown-content li', count: 1) + end first('.js-target-branch').click - find('.dropdown-target-branch .dropdown-content li', match: :first) - target_items = all('.dropdown-target-branch .dropdown-content li') + find('.js-target-branch-dropdown .dropdown-content li', match: :first) + target_items = all('.js-target-branch-dropdown .dropdown-content li') expect(target_items.count).to be > 1 end @@ -171,7 +164,6 @@ describe 'Merge request > User selects branches for new MR', :js do page.within('.merge-request') do click_link 'Pipelines' - wait_for_requests expect(page).to have_content "##{pipeline.id}" end diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb new file mode 100644 index 00000000000..4045cfd21c4 --- /dev/null +++ b/spec/features/profiles/active_sessions_spec.rb @@ -0,0 +1,89 @@ +require 'rails_helper' + +feature 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do + let(:user) do + create(:user).tap do |user| + user.current_sign_in_at = Time.current + end + end + + around do |example| + Timecop.freeze(Time.zone.parse('2018-03-12 09:06')) do + example.run + end + end + + scenario 'User sees their active sessions' do + Capybara::Session.new(:session1) + Capybara::Session.new(:session2) + + # note: headers can only be set on the non-js (aka. rack-test) driver + using_session :session1 do + Capybara.page.driver.header( + 'User-Agent', + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' + ) + + gitlab_sign_in(user) + end + + # set an additional session on another device + using_session :session2 do + Capybara.page.driver.header( + 'User-Agent', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B466 [FBDV/iPhone7,2]' + ) + + gitlab_sign_in(user) + end + + using_session :session1 do + visit profile_active_sessions_path + + expect(page).to have_content( + '127.0.0.1 ' \ + 'This is your current session ' \ + 'Firefox on Ubuntu ' \ + 'Signed in on 12 Mar 09:06' + ) + + expect(page).to have_selector '[title="Desktop"]', count: 1 + + expect(page).to have_content( + '127.0.0.1 ' \ + 'Last accessed on 12 Mar 09:06 ' \ + 'Mobile Safari on iOS ' \ + 'Signed in on 12 Mar 09:06' + ) + + expect(page).to have_selector '[title="Smartphone"]', count: 1 + end + end + + scenario 'User can revoke a session', :js, :redis_session_store do + Capybara::Session.new(:session1) + Capybara::Session.new(:session2) + + # set an additional session in another browser + using_session :session2 do + gitlab_sign_in(user) + end + + using_session :session1 do + gitlab_sign_in(user) + visit profile_active_sessions_path + + expect(page).to have_link('Revoke', count: 1) + + accept_confirm { click_on 'Revoke' } + + expect(page).not_to have_link('Revoke') + end + + using_session :session2 do + visit profile_active_sessions_path + + expect(page).to have_content('You need to sign in or sign up before continuing.') + end + end +end diff --git a/spec/features/projects/artifacts/browse_spec.rb b/spec/features/projects/artifacts/browse_spec.rb deleted file mode 100644 index cb69aff8d5f..00000000000 --- a/spec/features/projects/artifacts/browse_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -feature 'Browse artifact', :js do - let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, project: project) } - let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } - let(:browse_url) do - browse_path('other_artifacts_0.1.2') - end - - def browse_path(path) - browse_project_job_artifacts_path(project, job, path) - end - - context 'when visiting old URL' do - before do - visit browse_url.sub('/-/jobs', '/builds') - end - - it "redirects to new URL" do - expect(page.current_path).to eq(browse_url) - end - end - - context 'when browsing a directory with an text file' do - let(:txt_entry) { job.artifacts_metadata_entry('other_artifacts_0.1.2/doc_sample.txt') } - - before do - allow(Gitlab.config.pages).to receive(:enabled).and_return(true) - allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true) - end - - context 'when the project is public' do - it "shows external link icon and styles" do - visit browse_url - - link = first('.tree-item-file-external-link') - - expect(page).to have_link('doc_sample.txt', href: file_project_job_artifacts_path(project, job, path: txt_entry.blob.path)) - expect(link[:target]).to eq('_blank') - expect(link[:rel]).to include('noopener') - expect(link[:rel]).to include('noreferrer') - expect(page).to have_selector('.js-artifact-tree-external-icon') - end - end - - context 'when the project is private' do - let!(:private_project) { create(:project, :private) } - let(:pipeline) { create(:ci_empty_pipeline, project: private_project) } - let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } - let(:user) { create(:user) } - - before do - private_project.add_developer(user) - - sign_in(user) - end - - it 'shows internal link styles' do - visit browse_project_job_artifacts_path(private_project, job, 'other_artifacts_0.1.2') - - expect(page).to have_link('doc_sample.txt') - expect(page).not_to have_selector('.js-artifact-tree-external-icon') - end - end - end -end diff --git a/spec/features/projects/artifacts/download_spec.rb b/spec/features/projects/artifacts/download_spec.rb deleted file mode 100644 index 6f76c14910b..00000000000 --- a/spec/features/projects/artifacts/download_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'spec_helper' - -feature 'Download artifact' do - let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) } - let(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) } - - shared_examples 'downloading' do - it 'downloads the zip' do - expect(page.response_headers['Content-Disposition']) - .to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"}) - - # Check the content does match, but don't print this as error message - expect(page.source.b == job.artifacts_file.file.read.b) - end - end - - context 'when downloading' do - before do - visit download_url - end - - context 'via job id' do - let(:download_url) do - download_project_job_artifacts_path(project, job) - end - - it_behaves_like 'downloading' - end - - context 'via branch name and job name' do - let(:download_url) do - latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) - end - - it_behaves_like 'downloading' - end - end - - context 'when visiting old URL' do - before do - visit download_url.sub('/-/jobs', '/builds') - end - - context 'via job id' do - let(:download_url) do - download_project_job_artifacts_path(project, job) - end - - it_behaves_like 'downloading' - end - - context 'via branch name and job name' do - let(:download_url) do - latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) - end - - it_behaves_like 'downloading' - end - end -end diff --git a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb new file mode 100644 index 00000000000..9ebbbaea911 --- /dev/null +++ b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb @@ -0,0 +1,110 @@ +require "spec_helper" + +describe "User browses artifacts" do + let(:project) { create(:project, :public) } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } + let(:browse_url) { browse_project_job_artifacts_path(project, job, "other_artifacts_0.1.2") } + + context "when visiting old URL" do + it "redirects to new URL" do + visit(browse_url.sub("/-/jobs", "/builds")) + + expect(page.current_path).to eq(browse_url) + end + end + + context "when browsing artifacts root directory" do + before do + visit(browse_project_job_artifacts_path(project, job)) + end + + it "shows artifacts" do + expect(page).not_to have_selector(".build-sidebar") + + page.within(".tree-table") do + expect(page).to have_no_content("..") + .and have_content("other_artifacts_0.1.2") + .and have_content("ci_artifacts.txt") + .and have_content("rails_sample.jpg") + end + + page.within(".build-header") do + expect(page).to have_content("Job ##{job.id} in pipeline ##{pipeline.id} for #{pipeline.short_sha}") + end + end + + it "shows an artifact" do + click_link("ci_artifacts.txt") + + expect(page).to have_link("download it") + end + end + + context "when browsing a directory with UTF-8 characters in its name" do + before do + visit(browse_project_job_artifacts_path(project, job)) + end + + it "shows correct content", :js do + page.within(".tree-table") do + click_link("tests_encoding") + + expect(page).to have_no_content("non-utf8-dir") + + click_link("utf8 test dir ✓") + + expect(page).to have_content("..").and have_content("regular_file_2") + end + end + end + + context "when browsing a directory with a text file" do + let(:txt_entry) { job.artifacts_metadata_entry("other_artifacts_0.1.2/doc_sample.txt") } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true) + end + + context "when the project is public" do + before do + visit(browse_url) + end + + it "shows correct content" do + link = first(".tree-item-file-external-link") + + expect(link[:target]).to eq("_blank") + expect(link[:rel]).to include("noopener").and include("noreferrer") + expect(page).to have_link("doc_sample.txt", href: file_project_job_artifacts_path(project, job, path: txt_entry.blob.path)) + .and have_selector(".js-artifact-tree-external-icon") + + page.within(".tree-table") do + expect(page).to have_content("..").and have_content("another-subdirectory") + end + + page.within(".repo-breadcrumb") do + expect(page).to have_content("other_artifacts_0.1.2") + end + end + end + + context "when the project is private" do + let!(:private_project) { create(:project, :private) } + let(:pipeline) { create(:ci_empty_pipeline, project: private_project) } + let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } + let(:user) { create(:user) } + + before do + private_project.add_developer(user) + + sign_in(user) + + visit(browse_project_job_artifacts_path(private_project, job, "other_artifacts_0.1.2")) + end + + it { expect(page).to have_link("doc_sample.txt").and have_no_selector(".js-artifact-tree-external-icon") } + end + end +end diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb new file mode 100644 index 00000000000..67ed2f18d76 --- /dev/null +++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb @@ -0,0 +1,44 @@ +require "spec_helper" + +describe "User downloads artifacts" do + set(:project) { create(:project, :public) } + set(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) } + set(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) } + + shared_examples "downloading" do + it "downloads the zip" do + expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"}) + expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary") + expect(page.response_headers['Content-Type']).to eq("application/zip") + expect(page.source.b).to eq(job.artifacts_file.file.read.b) + end + end + + context "when downloading" do + before do + visit(url) + end + + context "via job id" do + set(:url) { download_project_job_artifacts_path(project, job) } + + it_behaves_like "downloading" + end + + context "via branch name and job name" do + set(:url) { latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) } + + it_behaves_like "downloading" + end + + context "via clicking the `Download` button" do + set(:url) { project_job_path(project, job) } + + before do + click_link("Download") + end + + it_behaves_like "downloading" + end + end +end diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index dfe8e02dce0..fe334b531f0 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -184,4 +184,44 @@ feature 'Gcp Cluster', :js do expect(page).to have_css('.signin-with-google') end end + + context 'when user has not dismissed GCP signup offer' do + before do + visit project_clusters_path(project) + end + + it 'user sees offer on cluster index page' do + expect(page).to have_css('.gcp-signup-offer') + end + + it 'user sees offer on cluster create page' do + click_link 'Add Kubernetes cluster' + + expect(page).to have_css('.gcp-signup-offer') + end + + it 'user sees offer on cluster GCP login page' do + click_link 'Add Kubernetes cluster' + click_link 'Create on Google Kubernetes Engine' + + expect(page).to have_css('.gcp-signup-offer') + end + end + + context 'when user has dismissed GCP signup offer' do + before do + visit project_clusters_path(project) + end + + it 'user does not see offer after dismissing' do + expect(page).to have_css('.gcp-signup-offer') + + find('.gcp-signup-offer .close').click + wait_for_requests + + click_link 'Add Kubernetes cluster' + + expect(page).not_to have_css('.gcp-signup-offer') + end + end end diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb index b650c1f4197..35ed6620548 100644 --- a/spec/features/projects/commits/user_browses_commits_spec.rb +++ b/spec/features/projects/commits/user_browses_commits_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe 'User browses commits' do + include RepoHelpers + let(:user) { create(:user) } let(:project) { create(:project, :repository, namespace: user.namespace) } @@ -9,13 +11,68 @@ describe 'User browses commits' do sign_in(user) end + it 'renders commit' do + visit project_commit_path(project, sample_commit.id) + + expect(page).to have_content(sample_commit.message) + .and have_content("Showing #{sample_commit.files_changed_count} changed files") + .and have_content('Side-by-side') + end + + it 'fill commit sha when click new tag from commit page' do + visit project_commit_path(project, sample_commit.id) + click_link 'Tag' + + expect(page).to have_selector("input[value='#{sample_commit.id}']", visible: false) + end + + it 'renders inline diff button when click side-by-side diff button' do + visit project_commit_path(project, sample_commit.id) + find('#parallel-diff-btn').click + + expect(page).to have_content 'Inline' + end + + it 'renders breadcrumbs on specific commit path' do + visit project_commits_path(project, project.repository.root_ref + '/files/ruby/regex.rb', limit: 5) + + expect(page).to have_selector('ul.breadcrumb') + .and have_selector('ul.breadcrumb a', count: 4) + end + + it 'renders diff links to both the previous and current image' do + visit project_commit_path(project, sample_image_commit.id) + + links = page.all('.file-actions a') + expect(links[0]['href']).to match %r{blob/#{sample_image_commit.old_blob_id}} + expect(links[1]['href']).to match %r{blob/#{sample_image_commit.new_blob_id}} + end + + context 'when commit has ci status' do + let(:pipeline) { create(:ci_pipeline, project: project, sha: sample_commit.id) } + + before do + project.enable_ci + + create(:ci_build, pipeline: pipeline) + + allow_any_instance_of(Ci::Pipeline).to receive(:ci_yaml_file).and_return('') + end + + it 'renders commit ci info' do + visit project_commit_path(project, sample_commit.id) + + expect(page).to have_content "Pipeline ##{pipeline.id} pending" + end + end + context 'primary email' do it 'finds a commit by a primary email' do user = create(:user, email: 'dmitriy.zaporozhets@gmail.com') - visit(project_commit_path(project, RepoHelpers.sample_commit.id)) + visit(project_commit_path(project, sample_commit.id)) - check_author_link(RepoHelpers.sample_commit.author_email, user) + check_author_link(sample_commit.author_email, user) end end @@ -26,9 +83,9 @@ describe 'User browses commits' do create(:email, { user: user, email: 'dmitriy.zaporozhets@gmail.com' }) end - visit(project_commit_path(project, RepoHelpers.sample_commit.parent_id)) + visit(project_commit_path(project, sample_commit.parent_id)) - check_author_link(RepoHelpers.sample_commit.author_email, user) + check_author_link(sample_commit.author_email, user) end end @@ -44,6 +101,135 @@ describe 'User browses commits' do expect(find('.diff-file-changes', visible: false)).to have_content('No file name available') end end + + describe 'commits list' do + let(:visit_commits_page) do + visit project_commits_path(project, project.repository.root_ref, limit: 5) + end + + it 'searches commit', :js do + visit_commits_page + fill_in 'commits-search', with: 'submodules' + + expect(page).to have_content 'More submodules' + expect(page).not_to have_content 'Change some files' + end + + it 'renders commits atom feed' do + visit_commits_page + click_link('Commits feed') + + commit = project.repository.commit + + expect(response_headers['Content-Type']).to have_content("application/atom+xml") + expect(body).to have_selector('title', text: "#{project.name}:master commits") + .and have_selector('author email', text: commit.author_email) + .and have_selector('entry summary', text: commit.description[0..10].delete("\r\n")) + end + + context 'master branch' do + before do + visit_commits_page + end + + it 'renders project commits' do + commit = project.repository.commit + + expect(page).to have_content(project.name) + .and have_content(commit.message[0..20]) + .and have_content(commit.short_id) + end + + it 'does not render create merge request button' do + expect(page).not_to have_link 'Create merge request' + end + + context 'when click the compare tab' do + before do + click_link('Compare') + end + + it 'does not render create merge request button' do + expect(page).not_to have_link 'Create merge request' + end + end + end + + context 'feature branch' do + let(:visit_commits_page) do + visit project_commits_path(project, 'feature') + end + + context 'when project does not have open merge requests' do + before do + visit_commits_page + end + + it 'renders project commits' do + commit = project.repository.commit('0b4bc9a') + + expect(page).to have_content(project.name) + .and have_content(commit.message[0..12]) + .and have_content(commit.short_id) + end + + it 'renders create merge request button' do + expect(page).to have_link 'Create merge request' + end + + context 'when click the compare tab' do + before do + click_link('Compare') + end + + it 'renders create merge request button' do + expect(page).to have_link 'Create merge request' + end + end + end + + context 'when project have open merge request' do + let!(:merge_request) do + create( + :merge_request, + title: 'Feature', + source_project: project, + source_branch: 'feature', + target_branch: 'master', + author: project.users.first + ) + end + + before do + visit_commits_page + end + + it 'renders project commits' do + commit = project.repository.commit('0b4bc9a') + + expect(page).to have_content(project.name) + .and have_content(commit.message[0..12]) + .and have_content(commit.short_id) + end + + it 'renders button to the merge request' do + expect(page).not_to have_link 'Create merge request' + expect(page).to have_link 'View open merge request', href: project_merge_request_path(project, merge_request) + end + + context 'when click the compare tab' do + before do + click_link('Compare') + end + + it 'renders button to the merge request' do + expect(page).not_to have_link 'Create merge request' + expect(page).to have_link 'View open merge request', href: project_merge_request_path(project, merge_request) + end + end + end + end + end end private diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb index 1fb22fd0e4c..7e863d9df32 100644 --- a/spec/features/projects/compare_spec.rb +++ b/spec/features/projects/compare_spec.rb @@ -7,16 +7,19 @@ describe "Compare", :js do before do project.add_master(user) sign_in user - visit project_compare_index_path(project, from: "master", to: "master") end describe "branches" do it "pre-populates fields" do + visit project_compare_index_path(project, from: "master", to: "master") + expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("master") expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("master") end it "compares branches" do + visit project_compare_index_path(project, from: "master", to: "master") + select_using_dropdown "from", "feature" expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("feature") @@ -26,9 +29,58 @@ describe "Compare", :js do click_button "Compare" expect(page).to have_content "Commits" + expect(page).to have_link 'Create merge request' + end + + it 'renders additions info when click unfold diff' do + visit project_compare_index_path(project) + + select_using_dropdown('from', RepoHelpers.sample_commit.parent_id, commit: true) + select_using_dropdown('to', RepoHelpers.sample_commit.id, commit: true) + + click_button 'Compare' + expect(page).to have_content 'Commits (1)' + expect(page).to have_content "Showing 2 changed files" + + diff = first('.js-unfold') + diff.click + wait_for_requests + + page.within diff.query_scope do + expect(first('.new_line').text).not_to have_content "..." + end + end + + context 'when project have an open merge request' do + let!(:merge_request) do + create( + :merge_request, + title: 'Feature', + source_project: project, + source_branch: 'feature', + target_branch: 'master', + author: project.users.first + ) + end + + it 'compares branches' do + visit project_compare_index_path(project) + + select_using_dropdown('from', 'master') + select_using_dropdown('to', 'feature') + + click_button 'Compare' + + expect(page).to have_content 'Commits (1)' + expect(page).to have_content 'Showing 1 changed file with 5 additions and 0 deletions' + expect(page).to have_link 'View open merge request', href: project_merge_request_path(project, merge_request) + expect(page).not_to have_link 'Create merge request' + end end it "filters branches" do + visit project_compare_index_path(project, from: "master", to: "master") + select_using_dropdown("from", "wip") find(".js-compare-from-dropdown .compare-dropdown-toggle").click @@ -39,6 +91,8 @@ describe "Compare", :js do describe "tags" do it "compares tags" do + visit project_compare_index_path(project, from: "master", to: "master") + select_using_dropdown "from", "v1.0.0" expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("v1.0.0") @@ -50,15 +104,20 @@ describe "Compare", :js do end end - def select_using_dropdown(dropdown_type, selection) + def select_using_dropdown(dropdown_type, selection, commit: false) dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click # find input before using to wait for the inputs visiblity dropdown.find('.dropdown-menu') dropdown.fill_in("Filter by Git revision", with: selection) wait_for_requests - # find before all to wait for the items visiblity - dropdown.find("a[data-ref=\"#{selection}\"]", match: :first) - dropdown.all("a[data-ref=\"#{selection}\"]").last.click + + if commit + dropdown.find('input[type="search"]').send_keys(:return) + else + # find before all to wait for the items visiblity + dropdown.find("a[data-ref=\"#{selection}\"]", match: :first) + dropdown.all("a[data-ref=\"#{selection}\"]").last.click + end end end diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb index 886c56e7163..43a23c42f83 100644 --- a/spec/features/projects/deploy_keys_spec.rb +++ b/spec/features/projects/deploy_keys_spec.rb @@ -18,12 +18,12 @@ describe 'Project deploy keys', :js do visit project_settings_repository_path(project) page.within(find('.deploy-keys')) do - expect(page).to have_selector('.deploy-keys li', count: 1) + expect(page).to have_selector('.deploy-key', count: 1) - accept_confirm { find(:button, text: 'Remove').send_keys(:return) } + accept_confirm { find('.ic-remove').click() } expect(page).not_to have_selector('.fa-spinner', count: 0) - expect(page).to have_selector('.deploy-keys li', count: 0) + expect(page).to have_selector('.deploy-key', count: 0) end end end diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb index 9c1f11f4c12..41f6c52fb8a 100644 --- a/spec/features/projects/files/user_browses_files_spec.rb +++ b/spec/features/projects/files/user_browses_files_spec.rb @@ -1,14 +1,12 @@ -require 'spec_helper' +require "spec_helper" -describe 'Projects > Files > User browses files' do +describe "User browses files" do let(:fork_message) do "You're not allowed to make changes to this project directly. "\ "A fork of this project has been created that you can make changes in, so you can submit a merge request." end - let(:project) { create(:project, :repository, name: 'Shop') } - let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } - let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } - let(:tree_path_ref_6d39438) { project_tree_path(project, '6d39438') } + let(:project) { create(:project, :repository, name: "Shop") } + let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") } let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } let(:user) { project.owner } @@ -16,57 +14,55 @@ describe 'Projects > Files > User browses files' do sign_in(user) end - it 'shows last commit for current directory' do + it "shows last commit for current directory" do visit(tree_path_root_ref) - click_link 'files' + click_link("files") - last_commit = project.repository.last_commit_for_path(project.default_branch, 'files') - page.within('.blob-commit-info') do - expect(page).to have_content last_commit.short_id - expect(page).to have_content last_commit.author_name + last_commit = project.repository.last_commit_for_path(project.default_branch, "files") + + page.within(".blob-commit-info") do + expect(page).to have_content(last_commit.short_id).and have_content(last_commit.author_name) end end - context 'when browsing the master branch' do + context "when browsing the master branch" do before do visit(tree_path_root_ref) end - it 'shows files from a repository' do - expect(page).to have_content('VERSION') - expect(page).to have_content('.gitignore') - expect(page).to have_content('LICENSE') + it "shows files from a repository" do + expect(page).to have_content("VERSION") + .and have_content(".gitignore") + .and have_content("LICENSE") end - it 'shows the "Browse Directory" link' do - click_link('files') - click_link('History') + it "shows the `Browse Directory` link" do + click_link("files") + click_link("History") - expect(page).to have_link('Browse Directory') - expect(page).not_to have_link('Browse Code') + expect(page).to have_link("Browse Directory").and have_no_link("Browse Code") end - it 'shows the "Browse File" link' do - page.within('.tree-table') do - click_link('README.md') + it "shows the `Browse File` link" do + page.within(".tree-table") do + click_link("README.md") end - click_link('History') - expect(page).to have_link('Browse File') - expect(page).not_to have_link('Browse Files') + click_link("History") + + expect(page).to have_link("Browse File").and have_no_link("Browse Files") end - it 'shows the "Browse Files" link' do - click_link('History') + it "shows the `Browse Files` link" do + click_link("History") - expect(page).to have_link('Browse Files') - expect(page).not_to have_link('Browse Directory') + expect(page).to have_link("Browse Files").and have_no_link("Browse Directory") end - it 'redirects to the permalink URL' do - click_link('.gitignore') - click_link('Permalink') + it "redirects to the permalink URL" do + click_link(".gitignore") + click_link("Permalink") permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore") @@ -74,80 +70,180 @@ describe 'Projects > Files > User browses files' do end end - context 'when browsing a specific ref' do + context "when browsing the `markdown` branch", :js do + context "when browsing the root" do + before do + visit(project_tree_path(project, "markdown")) + end + + it "shows correct files and links" do + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_tree_url(project, "markdown") + find("a", text: /^#id$/)["href"] == project_tree_url(project, "markdown", anchor: "#id") + find("a", text: %r{^/#id$})["href"] == project_tree_url(project, "markdown", anchor: "#id") + find("a", text: /^README.md#id$/)["href"] == project_blob_url(project, "markdown/README.md", anchor: "#id") + find("a", text: %r{^d/README.md#id$})["href"] == project_blob_url(project, "d/markdown/README.md", anchor: "#id") + # rubocop:enable Lint/Void + + expect(current_path).to eq(project_tree_path(project, "markdown")) + expect(page).to have_content("README.md") + .and have_content("CHANGELOG") + .and have_content("Welcome to GitLab GitLab is a free project and repository management application") + .and have_link("GitLab API doc") + .and have_link("GitLab API website") + .and have_link("Rake tasks") + .and have_link("backup and restore procedure") + .and have_link("GitLab API doc directory") + .and have_link("Maintenance") + .and have_header_with_correct_id_and_link(2, "Application details", "application-details") + end + + it "shows correct content of file" do + click_link("GitLab API doc") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/README.md")) + expect(page).to have_content("All API requests require authentication") + .and have_content("Contents") + .and have_link("Users") + .and have_link("Rake tasks") + .and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api") + + click_link("Users") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/users.md")) + expect(page).to have_content("Get a list of users.") + + page.go_back + + click_link("Rake tasks") + + expect(current_path).to eq(project_tree_path(project, "markdown/doc/raketasks")) + expect(page).to have_content("backup_restore.md").and have_content("maintenance.md") + + click_link("shop") + click_link("Maintenance") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/raketasks/maintenance.md")) + expect(page).to have_content("bundle exec rake gitlab:env:info RAILS_ENV=production") + + click_link("shop") + + page.within(".tree-table") do + click_link("README.md") + end + + page.go_back + + page.within(".tree-table") do + click_link("d") + end + + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_tree_url(project, "markdown/d") + # rubocop:enable Lint/Void + + page.within(".tree-table") do + click_link("README.md") + end + + # rubocop:disable Lint/Void + # Test the full URLs of links instead of relative paths by `have_link(text: "...", href: "...")`. + find("a", text: /^empty$/)["href"] == project_blob_url(project, "markdown/d/README.md") + # rubocop:enable Lint/Void + end + + it "shows correct content of directory" do + click_link("GitLab API doc directory") + + expect(current_path).to eq(project_tree_path(project, "markdown/doc/api")) + expect(page).to have_content("README.md").and have_content("users.md") + + click_link("Users") + + expect(current_path).to eq(project_blob_path(project, "markdown/doc/api/users.md")) + expect(page).to have_content("List users").and have_content("Get a list of users.") + end + end + end + + context "when browsing a specific ref" do + let(:ref) { project_tree_path(project, "6d39438") } + before do - visit(tree_path_ref_6d39438) + visit(ref) end - it 'shows files from a repository for "6d39438"' do - expect(current_path).to eq(tree_path_ref_6d39438) - expect(page).to have_content('.gitignore') - expect(page).to have_content('LICENSE') + it "shows files from a repository for `6d39438`" do + expect(current_path).to eq(ref) + expect(page).to have_content(".gitignore").and have_content("LICENSE") end - it 'shows files from a repository with apostroph in its name', :js do - first('.js-project-refs-dropdown').click + it "shows files from a repository with apostroph in its name", :js do + first(".js-project-refs-dropdown").click - page.within('.project-refs-form') do + page.within(".project-refs-form") do click_link("'test'") end - expect(page).to have_selector('.dropdown-toggle-text', text: "'test'") + expect(page).to have_selector(".dropdown-toggle-text", text: "'test'") visit(project_tree_path(project, "'test'")) - expect(page).to have_css('.tree-commit-link', visible: true) - expect(page).not_to have_content('Loading commit data...') + expect(page).to have_css(".tree-commit-link").and have_no_content("Loading commit data...") end - it 'shows the code with a leading dot in the directory', :js do - first('.js-project-refs-dropdown').click + it "shows the code with a leading dot in the directory", :js do + first(".js-project-refs-dropdown").click - page.within('.project-refs-form') do - click_link('fix') + page.within(".project-refs-form") do + click_link("fix") end - visit(project_tree_path(project, 'fix/.testdir')) + visit(project_tree_path(project, "fix/.testdir")) - expect(page).to have_css('.tree-commit-link', visible: true) - expect(page).not_to have_content('Loading commit data...') + expect(page).to have_css(".tree-commit-link").and have_no_content("Loading commit data...") end - it 'does not show the permalink link' do - click_link('.gitignore') + it "does not show the permalink link" do + click_link(".gitignore") - expect(page).not_to have_link('permalink') + expect(page).not_to have_link("permalink") end end - context 'when browsing a file content' do + context "when browsing a file content" do before do visit(tree_path_root_ref) - click_link('.gitignore') + + click_link(".gitignore") end - it 'shows a file content', :js do - wait_for_requests - expect(page).to have_content('*.rbc') + it "shows a file content", :js do + expect(page).to have_content("*.rbc") end - it 'is possible to blame' do - click_link 'Blame' + it "is possible to blame" do + click_link("Blame") - expect(page).to have_content "*.rb" - expect(page).to have_content "Dmitriy Zaporozhets" - expect(page).to have_content "Initial commit" + expect(page).to have_content("*.rb") + .and have_content("Dmitriy Zaporozhets") + .and have_content("Initial commit") end end - context 'when browsing a raw file' do + context "when browsing a raw file" do before do - visit(project_blob_path(project, File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path))) + path = File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path) + + visit(project_blob_path(project, path)) end - it 'shows a raw file content' do - click_link('Open raw') - expect(source).to eq('') # Body is filled in by gitlab-workhorse + it "shows a raw file content" do + click_link("Open raw") + + expect(source).to eq("") # Body is filled in by gitlab-workhorse end end end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index b25f5161748..60fe30bd898 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -46,7 +46,7 @@ feature 'Import/Export - project import integration test', :js do expect(project.merge_requests).not_to be_empty expect(project_hook_exists?(project)).to be true expect(wiki_exists?(project)).to be true - expect(project.import_status).to eq('finished') + expect(project.import_state.status).to eq('finished') end end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index a00db6dd161..9d1c4cbad8b 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require 'tempfile' -feature 'Jobs' do +feature 'Jobs', :clean_gitlab_redis_shared_state do let(:user) { create(:user) } let(:user_access_level) { :developer } let(:project) { create(:project, :repository) } @@ -282,7 +282,7 @@ feature 'Jobs' do it 'loads job trace' do expect(page).to have_content 'BUILD TRACE' - job.trace.write do |stream| + job.trace.write('a+b') do |stream| stream.append(' and more trace', 11) end @@ -593,44 +593,6 @@ feature 'Jobs' do end end - context 'storage form' do - let(:existing_file) { Tempfile.new('existing-trace-file').path } - - before do - job.run! - end - - context 'when job has trace in file', :js do - before do - allow_any_instance_of(Gitlab::Ci::Trace) - .to receive(:paths) - .and_return([existing_file]) - end - - it 'sends the right headers' do - requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do - visit raw_project_job_path(project, job) - end - expect(requests.first.response_headers['Content-Type']).to eq('text/plain; charset=utf-8') - expect(requests.first.response_headers['X-Sendfile']).to eq(existing_file) - end - end - - 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).not_to have_selector('.js-raw-link-controller') - end - end - end - context "when visiting old URL" do let(:raw_job_url) do raw_project_job_path(project, job) diff --git a/spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb b/spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb index c35ba2d7016..01aeed93947 100644 --- a/spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb +++ b/spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb @@ -10,6 +10,15 @@ describe 'User accepts a merge request', :js do sign_in(user) end + it 'presents merged merge request content' do + visit(merge_request_path(merge_request)) + + click_button('Merge') + + expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with \ + #{merge_request.short_merge_commit_sha}") + end + context 'with removing the source branch' do before do visit(merge_request_path(merge_request)) diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 3c9ab583032..af2a9567a47 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -3,10 +3,11 @@ require 'spec_helper' describe 'Pipeline', :js do let(:project) { create(:project) } let(:user) { create(:user) } + let(:role) { :developer } before do sign_in(user) - project.add_developer(user) + project.add_role(user, role) end shared_context 'pipeline builds' do @@ -153,9 +154,10 @@ describe 'Pipeline', :js do end context 'page tabs' do - it 'shows Pipeline and Jobs tabs with link' do + it 'shows Pipeline, Jobs and Failed Jobs tabs with link' do expect(page).to have_link('Pipeline') expect(page).to have_link('Jobs') + expect(page).to have_link('Failed Jobs') end it 'shows counter in Jobs tab' do @@ -165,6 +167,16 @@ describe 'Pipeline', :js do it 'shows Pipeline tab as active' do expect(page).to have_css('.js-pipeline-tab-link .active') end + + context 'without permission to access builds' do + let(:project) { create(:project, :public, :repository, public_builds: false) } + let(:role) { :guest } + + it 'does not show failed jobs tab pane' do + expect(page).to have_link('Pipeline') + expect(page).not_to have_content('Failed Jobs') + end + end end context 'retrying jobs' do @@ -308,8 +320,7 @@ describe 'Pipeline', :js do end describe 'GET /:project/pipelines/:id/failures' do - let(:project) { create(:project, :repository) } - let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: '1234') } let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) } let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) } @@ -340,11 +351,39 @@ describe 'Pipeline', :js do visit pipeline_failures_page end - it 'includes failed jobs' do + it 'shows jobs tab pane as active' do + expect(page).to have_content('Failed Jobs') + expect(page).to have_css('#js-tab-failures.active') + end + + it 'lists failed builds' do + expect(page).to have_content(failed_build.name) + expect(page).to have_content(failed_build.stage) + end + + it 'does not show trace' do expect(page).to have_content('No job trace') end end + context 'without permission to access builds' do + let(:role) { :guest } + + before do + project.update(public_builds: false) + end + + context 'when accessing failed jobs page' do + before do + visit pipeline_failures_page + end + + it 'fails to access the page' do + expect(page).to have_content('Access Denied') + end + end + end + context 'without failures' do before do failed_build.update!(status: :success) diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index b9249e3b7e4..d66ad6ab7f6 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -388,9 +388,9 @@ describe 'Pipelines', :js do it 'should be possible to cancel pending build' do find('.js-builds-dropdown-button').click - find('a.js-ci-action-icon').click + find('.js-ci-action').click + wait_for_requests - expect(page).to have_content('canceled') expect(build.reload).to be_canceled end end @@ -407,7 +407,7 @@ describe 'Pipelines', :js do within('.js-builds-dropdown-list') do build_element = page.find('.mini-pipeline-graph-dropdown-item') - expect(build_element['data-title']).to eq('build - failed <br> (unknown failure)') + expect(build_element['data-original-title']).to eq('build - failed <br> (unknown failure)') end end end @@ -517,16 +517,31 @@ describe 'Pipelines', :js do end it 'creates a new pipeline' do - expect { click_on 'Run pipeline' } + expect { click_on 'Create pipeline' } .to change { Ci::Pipeline.count }.by(1) expect(Ci::Pipeline.last).to be_web end + + context 'when variables are specified' do + it 'creates a new pipeline with variables' do + page.within '.ci-variable-row-body' do + fill_in "Input variable key", with: "key_name" + fill_in "Input variable value", with: "value" + end + + expect { click_on 'Create pipeline' } + .to change { Ci::Pipeline.count }.by(1) + + expect(Ci::Pipeline.last.variables.map { |var| var.slice(:key, :secret_value) }) + .to eq [{ key: "key_name", secret_value: "value" }.with_indifferent_access] + end + end end context 'without gitlab-ci.yml' do before do - click_on 'Run pipeline' + click_on 'Create pipeline' end it { expect(page).to have_content('Missing .gitlab-ci.yml file') } @@ -539,7 +554,7 @@ describe 'Pipelines', :js do click_link 'master' end - expect { click_on 'Run pipeline' } + expect { click_on 'Create pipeline' } .to change { Ci::Pipeline.count }.by(1) end end @@ -557,7 +572,7 @@ describe 'Pipelines', :js do it 'has field to add a new pipeline' do expect(page).to have_selector('.js-branch-select') expect(find('.js-branch-select')).to have_content project.default_branch - expect(page).to have_content('Run on') + expect(page).to have_content('Create for') end end diff --git a/spec/features/projects/remote_mirror_spec.rb b/spec/features/projects/remote_mirror_spec.rb new file mode 100644 index 00000000000..81a6b613cc8 --- /dev/null +++ b/spec/features/projects/remote_mirror_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +feature 'Project remote mirror', :feature do + let(:project) { create(:project, :repository, :remote_mirror) } + let(:remote_mirror) { project.remote_mirrors.first } + let(:user) { create(:user) } + + describe 'On a project', :js do + before do + project.add_master(user) + sign_in user + end + + context 'when last_error is present but last_update_at is not' do + it 'renders error message without timstamp' do + remote_mirror.update_attributes(last_error: 'Some new error', last_update_at: nil) + + visit project_mirror_path(project) + + expect(page).to have_content('The remote repository failed to update.') + end + end + + context 'when last_error and last_update_at are present' do + it 'renders error message with timestamp' do + remote_mirror.update_attributes(last_error: 'Some new error', last_update_at: Time.now - 5.minutes) + + visit project_mirror_path(project) + + expect(page).to have_content('The remote repository failed to update 5 minutes ago.') + end + end + end +end diff --git a/spec/features/projects/settings/lfs_settings_spec.rb b/spec/features/projects/settings/lfs_settings_spec.rb index 0fd28a5681c..342be1d2a9d 100644 --- a/spec/features/projects/settings/lfs_settings_spec.rb +++ b/spec/features/projects/settings/lfs_settings_spec.rb @@ -1,21 +1,27 @@ require 'rails_helper' describe 'Projects > Settings > LFS settings' do - let(:admin) { create(:admin) } let(:project) { create(:project) } + let(:user) { create(:user) } + let(:role) { :master } context 'LFS enabled setting' do before do allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) - sign_in(admin) + sign_in(user) + project.add_role(user, role) end - it 'displays the correct elements', :js do - visit edit_project_path(project) + context 'for master' do + let(:role) { :master } - expect(page).to have_content('Git Large File Storage') - expect(page).to have_selector('input[name="project[lfs_enabled]"] + button', visible: true) + it 'displays the correct elements', :js do + visit edit_project_path(project) + + expect(page).to have_content('Git Large File Storage') + expect(page).to have_selector('input[name="project[lfs_enabled]"] + button', visible: true) + end end end end diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb index e1dfe617691..08b40653764 100644 --- a/spec/features/projects/settings/repository_settings_spec.rb +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -54,7 +54,7 @@ describe 'Projects > Settings > Repository settings' do project.deploy_keys << private_deploy_key visit project_settings_repository_path(project) - find('li', text: private_deploy_key.title).click_link('Edit') + find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click() fill_in 'deploy_key_title', with: 'updated_deploy_key' check 'deploy_key_deploy_keys_projects_attributes_0_can_push' @@ -71,11 +71,15 @@ describe 'Projects > Settings > Repository settings' do visit project_settings_repository_path(project) - find('li', text: private_deploy_key.title).click_link('Edit') + find('.js-deployKeys-tab-available_project_keys').click() + + find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click() fill_in 'deploy_key_title', with: 'updated_deploy_key' click_button 'Save changes' + find('.js-deployKeys-tab-available_project_keys').click() + expect(page).to have_content('updated_deploy_key') end @@ -83,7 +87,7 @@ describe 'Projects > Settings > Repository settings' do project.deploy_keys << private_deploy_key visit project_settings_repository_path(project) - accept_confirm { find('li', text: private_deploy_key.title).click_button('Remove') } + accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click() } expect(page).not_to have_content(private_deploy_key.title) end @@ -115,5 +119,20 @@ describe 'Projects > Settings > Repository settings' do expect(page).to have_content('Your new project deploy token has been created') end end + + context 'remote mirror settings' do + let(:user2) { create(:user) } + + before do + project.add_master(user2) + + visit project_settings_repository_path(project) + end + + it 'shows push mirror settings' do + expect(page).to have_selector('#project_remote_mirrors_attributes_0_enabled') + expect(page).to have_selector('#project_remote_mirrors_attributes_0_url') + end + end end end diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb index b242e41df1c..3017048e506 100644 --- a/spec/features/projects/tree/create_directory_spec.rb +++ b/spec/features/projects/tree/create_directory_spec.rb @@ -44,12 +44,17 @@ feature 'Multi-file editor new directory', :js do wait_for_requests - click_button 'Stage all' + find('.js-ide-commit-mode').click + + find('.multi-file-commit-list-item').hover + first('.multi-file-discard-btn .btn').click fill_in('commit-message', with: 'commit message ide') click_button('Commit') + find('.js-ide-edit-mode').click + expect(page).to have_content('folder name') end end diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb index 7d65456e049..56471c8e7aa 100644 --- a/spec/features/projects/tree/create_file_spec.rb +++ b/spec/features/projects/tree/create_file_spec.rb @@ -34,7 +34,10 @@ feature 'Multi-file editor new file', :js do wait_for_requests - click_button 'Stage all' + find('.js-ide-commit-mode').click + + find('.multi-file-commit-list-item').hover + first('.multi-file-discard-btn .btn').click fill_in('commit-message', with: 'commit message ide') diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index 006c15d60c5..6586ccaa400 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' feature 'Projects > Wiki > User previews markdown changes', :js do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:wiki_content) do <<-HEREDOC [regular link](regular) diff --git a/spec/features/projects/wiki/shortcuts_spec.rb b/spec/features/projects/wiki/shortcuts_spec.rb index f70d1e710dd..6178361082e 100644 --- a/spec/features/projects/wiki/shortcuts_spec.rb +++ b/spec/features/projects/wiki/shortcuts_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' feature 'Wiki shortcuts', :js do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: 'Home page' }) } before 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 4a9d1cb87e1..9989e1ffda7 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -1,6 +1,6 @@ -require 'spec_helper' +require "spec_helper" -describe 'User creates wiki page' do +describe "User creates wiki page" do let(:user) { create(:user) } before do @@ -10,67 +10,104 @@ describe 'User creates wiki page' do visit(project_wikis_path(project)) end - context 'when wiki is empty' do - context 'in a user namespace' do - let(:project) { create(:project, namespace: user.namespace) } + context "when wiki is empty" do + context "in a user namespace" do + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - it 'shows validation error message' do - page.within('.wiki-form') do - fill_in(:wiki_content, with: '') - click_on('Create page') + it "shows validation error message" do + page.within(".wiki-form") do + fill_in(:wiki_content, with: "") + + click_on("Create page") end - expect(page).to have_content('The form contains the following error:') - expect(page).to have_content("Content can't be blank") + expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "[link test](test)") - page.within('.wiki-form') do - fill_in(:wiki_content, with: '[link test](test)') - click_on('Create page') + click_on("Create page") end - expect(page).to have_content('Home') - expect(page).to have_content('link test') + expect(page).to have_content("Home").and have_content("link test") - click_link('link test') + click_link("link test") - expect(page).to have_content('Create Page') + expect(page).to have_content("Create Page") end - it 'shows non-escaped link in the pages list', :js do - click_link('New page') + it "shows non-escaped link in the pages list", :js do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'one/two/three-test') - click_on('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "one/two/three-test") + + click_on("Create page") end - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') + page.within(".wiki-form") do + fill_in(:wiki_content, with: "wiki content") + + click_on("Create page") end - expect(current_path).to include('one/two/three-test') + expect(current_path).to include("one/two/three-test") expect(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']") end - it 'has "Create home" as a commit message' do - expect(page).to have_field('wiki[message]', with: 'Create home') + it "has `Create home` as a commit message" do + expect(page).to have_field("wiki[message]", with: "Create home") end - it 'creates a page from the home page' do - fill_in(:wiki_content, with: 'My awesome wiki!') + it "creates a page from the home page" do + fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n") + fill_in(:wiki_message, with: "Adding links to wiki") + + page.within(".wiki-form") do + click_button("Create page") + end + + expect(current_path).to eq(project_wiki_path(project, "home")) + expect(page).to have_content("test GitLab API doc Rake tasks Wiki header") + .and have_content("Home") + .and have_content("Last edited by #{user.name}") + .and have_header_with_correct_id_and_link(1, "Wiki header", "wiki-header") + + click_link("test") - page.within('.wiki-form') do - click_button('Create page') + expect(current_path).to eq(project_wiki_path(project, "test")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Test").and have_content("Create Page") + end + + click_link("Home") + + expect(current_path).to eq(project_wiki_path(project, "home")) + + click_link("GitLab API") + + expect(current_path).to eq(project_wiki_path(project, "api")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create").and have_content("Api") end - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + click_link("Home") + + expect(current_path).to eq(project_wiki_path(project, "home")) + + click_link("Rake tasks") + + expect(current_path).to eq(project_wiki_path(project, "raketasks")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create").and have_content("Rake") + end end - it 'creates ASCII wiki with LaTeX blocks', :js do - stub_application_setting(plantuml_url: 'http://localhost', plantuml_enabled: true) + it "creates ASCII wiki with LaTeX blocks", :js do + stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true) ascii_content = <<~MD :stem: latexmath @@ -90,153 +127,164 @@ describe 'User creates wiki page' do stem:[2+2] is 4 MD - find('#wiki_format option[value=asciidoc]').select_option + find("#wiki_format option[value=asciidoc]").select_option + fill_in(:wiki_content, with: ascii_content) - page.within('.wiki-form') do - click_button('Create page') + page.within(".wiki-form") do + click_button("Create page") end - page.within '.wiki' do - expect(page).to have_selector('.katex', count: 3) - expect(page).to have_content('2+2 is 4') + page.within ".wiki" do + expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4") end end end - context 'in a group namespace', :js do - let(:project) { create(:project, namespace: create(:group, :public)) } + context "in a group namespace", :js do + let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - it 'has "Create home" as a commit message' do - expect(page).to have_field('wiki[message]', with: 'Create home') + it "has `Create home` as a commit message" do + expect(page).to have_field("wiki[message]", with: "Create home") end - it 'creates a page from from the home page' do - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + it "creates a page from from the home page" do + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") + + click_button("Create page") end - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Home") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end end - context 'when wiki is not empty', :js do + context "when wiki is not empty", :js do before do - create(:wiki_page, wiki: create(:project, namespace: user.namespace).wiki, attrs: { title: 'home', content: 'Home page' }) + create(:wiki_page, wiki: create(:project, :wiki_repo, namespace: user.namespace).wiki, attrs: { title: "home", content: "Home page" }) end - context 'in a user namespace' do - let(:project) { create(:project, namespace: user.namespace) } + context "in a user namespace" do + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - context 'via the "new wiki page" page' do - it 'creates a page with a single word' do - click_link('New page') + context "via the `new wiki page` page" do + it "creates a page with a single word" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'foo') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "foo") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create foo') + expect(page).to have_field("wiki[message]", with: "Create foo") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Foo') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Foo") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end - it 'creates a page with spaces in the name' do - click_link('New page') + it "creates a page with spaces in the name" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'Spaces in the name') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "Spaces in the name") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create spaces in the name') + expect(page).to have_field("wiki[message]", with: "Create spaces in the name") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Spaces in the name') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Spaces in the name") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end - it 'creates a page with hyphens in the name' do - click_link('New page') + it "creates a page with hyphens in the name" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'hyphens-in-the-name') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "hyphens-in-the-name") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create hyphens in the name') + expect(page).to have_field("wiki[message]", with: "Create hyphens in the name") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Hyphens in the name') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Hyphens in the name") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end - it 'shows the autocompletion dropdown' do - click_link('New page') + it "shows the autocompletion dropdown" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'test-autocomplete') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "test-autocomplete") + + click_button("Create page") end - page.within('.wiki-form') do - find('#wiki_content').native.send_keys('') - fill_in(:wiki_content, with: '@') + page.within(".wiki-form") do + find("#wiki_content").native.send_keys("") + + fill_in(:wiki_content, with: "@") end - expect(page).to have_selector('.atwho-view') + expect(page).to have_selector(".atwho-view") end end - context 'in a group namespace' do - let(:project) { create(:project, namespace: create(:group, :public)) } + context "in a group namespace" do + let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - context 'via the "new wiki page" page' do - it 'creates a page' do - click_link('New page') + context "via the `new wiki page` page" do + it "creates a page" do + click_link("New page") - page.within('#modal-new-wiki') do - fill_in(:new_wiki_path, with: 'foo') - click_button('Create page') + page.within("#modal-new-wiki") do + fill_in(:new_wiki_path, with: "foo") + + click_button("Create page") end # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Create foo') + expect(page).to have_field("wiki[message]", with: "Create foo") + + page.within(".wiki-form") do + fill_in(:wiki_content, with: "My awesome wiki!") - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Create page') + click_button("Create page") end - expect(page).to have_content('Foo') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') + expect(page).to have_content("Foo") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") end end end diff --git a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb index 605e332196b..ab9420fc38f 100644 --- a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' feature 'User deletes wiki page' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:wiki_page) { create(:wiki_page, wiki: project.wiki) } before 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 37a118c34ab..823399ac3c3 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 @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Projects > Wiki > User views Git access wiki page' do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :wiki_repo, :public) } let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) } before do 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 ef1bb712846..e019e3ce5a5 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -14,7 +14,7 @@ describe 'User updates wiki page' do end context 'in a user namespace' do - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } it 'redirects back to the home edit page' do page.within(:css, '.wiki-form .form-actions') do @@ -66,7 +66,7 @@ describe 'User updates wiki page' do end context 'in a user namespace' do - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } it 'updates a page' do click_link('Edit') @@ -134,7 +134,7 @@ describe 'User updates wiki page' do end context 'in a group namespace' do - let(:project) { create(:project, namespace: create(:group, :public)) } + let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } it 'updates a page' do click_link('Edit') @@ -154,7 +154,7 @@ describe 'User updates wiki page' do end context 'when the page is in a subdir' do - let!(:project) { create(:project, namespace: user.namespace) } + let!(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) } let(:page_name) { 'page_name' } let(:page_dir) { "foo/bar/#{page_name}" } 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 2682b62fa04..92b50169476 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 @@ -11,6 +11,7 @@ describe 'Projects > Wiki > User views wiki in project page' do context 'when repository is disabled for project' do let(:project) do create(:project, + :wiki_repo, :repository_disabled, :merge_requests_disabled, :builds_disabled) diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb index 306e382119a..6661714222a 100644 --- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'User views a wiki page' do shared_examples 'wiki page user view' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:wiki_page) do create(:wiki_page, wiki: project.wiki, diff --git a/spec/features/raven_js_spec.rb b/spec/features/raven_js_spec.rb index 74890c86047..a9e815eaf4f 100644 --- a/spec/features/raven_js_spec.rb +++ b/spec/features/raven_js_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' feature 'RavenJS' do - let(:raven_path) { '/raven.bundle.js' } + let(:raven_path) { '/raven.chunk.js' } it 'should not load raven if sentry is disabled' do visit new_user_session_path diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index df65c2d2f83..e0cd963fe39 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -15,7 +15,7 @@ feature 'Runners' do end scenario 'user can see a button to install runners on kubernetes clusters' do - visit runners_path(project) + visit project_runners_path(project) expect(page).to have_link('Install Runner on Kubernetes', href: project_clusters_path(project)) end @@ -36,7 +36,7 @@ feature 'Runners' do end scenario 'user sees the specific runner' do - visit runners_path(project) + visit project_runners_path(project) within '.activated-specific-runners' do expect(page).to have_content(specific_runner.display_name) @@ -48,7 +48,7 @@ feature 'Runners' do end scenario 'user can pause and resume the specific runner' do - visit runners_path(project) + visit project_runners_path(project) within '.activated-specific-runners' do expect(page).to have_content('Pause') @@ -68,7 +68,7 @@ feature 'Runners' do end scenario 'user removes an activated specific runner if this is last project for that runners' do - visit runners_path(project) + visit project_runners_path(project) within '.activated-specific-runners' do click_on 'Remove Runner' @@ -78,7 +78,7 @@ feature 'Runners' do end scenario 'user edits the runner to be protected' do - visit runners_path(project) + visit project_runners_path(project) within '.activated-specific-runners' do first('.edit-runner > a').click @@ -98,7 +98,7 @@ feature 'Runners' do end scenario 'user edits runner not to run untagged jobs' do - visit runners_path(project) + visit project_runners_path(project) within '.activated-specific-runners' do first('.edit-runner > a').click @@ -117,7 +117,7 @@ feature 'Runners' do given!(:shared_runner) { create(:ci_runner, :shared) } scenario 'user sees CI/CD setting page' do - visit runners_path(project) + visit project_runners_path(project) expect(page.find('.available-shared-runners')).to have_content(shared_runner.display_name) end @@ -134,7 +134,7 @@ feature 'Runners' do end scenario 'user enables and disables a specific runner' do - visit runners_path(project) + visit project_runners_path(project) within '.available-specific-runners' do click_on 'Enable for this project' @@ -159,7 +159,7 @@ feature 'Runners' do end scenario 'user sees shared runners description' do - visit runners_path(project) + visit project_runners_path(project) expect(page.find('.shared-runners-description')).to have_content(shared_runners_html) end @@ -174,11 +174,185 @@ feature 'Runners' do end scenario 'user enables shared runners' do - visit runners_path(project) + visit project_runners_path(project) click_on 'Enable shared Runners' expect(page.find('.shared-runners-description')).to have_content('Disable shared Runners') end end + + context 'group runners in project settings' do + background do + project.add_master(user) + end + + given(:group) { create :group } + + context 'as project and group master' do + background do + group.add_master(user) + end + + context 'project with a group but no group runner' do + given(:project) { create :project, group: group } + + scenario 'group runners are not available' do + visit project_runners_path(project) + + expect(page).to have_content 'This group does not provide any group Runners yet' + + expect(page).to have_content 'Group masters can register group runners in the Group CI/CD settings' + expect(page).not_to have_content 'Ask your group master to setup a group Runner' + end + end + end + + context 'as project master' do + context 'project without a group' do + given(:project) { create :project } + + scenario 'group runners are not available' do + visit project_runners_path(project) + + expect(page).to have_content 'This project does not belong to a group and can therefore not make use of group Runners.' + end + end + + context 'project with a group but no group runner' do + given(:group) { create :group } + given(:project) { create :project, group: group } + + scenario 'group runners are not available' do + visit project_runners_path(project) + + expect(page).to have_content 'This group does not provide any group Runners yet.' + + expect(page).not_to have_content 'Group masters can register group runners in the Group CI/CD settings' + expect(page).to have_content 'Ask your group master to setup a group Runner.' + end + end + + context 'project with a group and a group runner' do + given(:group) { create :group } + given(:project) { create :project, group: group } + given!(:ci_runner) { create :ci_runner, groups: [group], description: 'group-runner' } + + scenario 'group runners are available' do + visit project_runners_path(project) + + expect(page).to have_content 'Available group Runners : 1' + expect(page).to have_content 'group-runner' + end + + scenario 'group runners may be disabled for a project' do + visit project_runners_path(project) + + click_on 'Disable group Runners' + + expect(page).to have_content 'Enable group Runners' + expect(project.reload.group_runners_enabled).to be false + + click_on 'Enable group Runners' + + expect(page).to have_content 'Disable group Runners' + expect(project.reload.group_runners_enabled).to be true + end + end + end + end + + context 'group runners in group settings' do + given(:group) { create :group } + background do + group.add_master(user) + end + + context 'group with no runners' do + scenario 'there are no runners displayed' do + visit group_settings_ci_cd_path(group) + + expect(page).to have_content 'This group does not provide any group Runners yet' + end + end + + context 'group with a runner' do + let!(:runner) { create :ci_runner, groups: [group], description: 'group-runner' } + + scenario 'the runner is visible' do + visit group_settings_ci_cd_path(group) + + expect(page).not_to have_content 'This group does not provide any group Runners yet' + expect(page).to have_content 'Available group Runners : 1' + expect(page).to have_content 'group-runner' + end + + scenario 'user can pause and resume the group runner' do + visit group_settings_ci_cd_path(group) + + expect(page).to have_content('Pause') + expect(page).not_to have_content('Resume') + + click_on 'Pause' + + expect(page).not_to have_content('Pause') + expect(page).to have_content('Resume') + + click_on 'Resume' + + expect(page).to have_content('Pause') + expect(page).not_to have_content('Resume') + end + + scenario 'user can view runner details' do + visit group_settings_ci_cd_path(group) + + expect(page).to have_content(runner.display_name) + + click_on runner.short_sha + + expect(page).to have_content(runner.platform) + end + + scenario 'user can remove a group runner' do + visit group_settings_ci_cd_path(group) + + click_on 'Remove Runner' + + expect(page).not_to have_content(runner.display_name) + end + + scenario 'user edits the runner to be protected' do + visit group_settings_ci_cd_path(group) + + first('.edit-runner > a').click + + expect(page.find_field('runner[access_level]')).not_to be_checked + + check 'runner_access_level' + click_button 'Save changes' + + expect(page).to have_content 'Protected Yes' + end + + context 'when a runner has a tag' do + background do + runner.update(tag_list: ['tag']) + end + + scenario 'user edits runner not to run untagged jobs' do + visit group_settings_ci_cd_path(group) + + first('.edit-runner > a').click + + expect(page.find_field('runner[run_untagged]')).to be_checked + + uncheck 'runner_run_untagged' + click_button 'Save changes' + + expect(page).to have_content 'Can run untagged jobs No' + end + end + end + end end diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb index 7934779058f..5098fb49ee1 100644 --- a/spec/features/search/user_searches_for_wiki_pages_spec.rb +++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'User searches for wiki pages', :js do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'test_wiki', content: 'Some Wiki content' }) } before do diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb new file mode 100644 index 00000000000..631d7e3bced --- /dev/null +++ b/spec/features/users/active_sessions_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +feature 'Active user sessions', :clean_gitlab_redis_shared_state do + scenario 'Successful login adds a new active user login' do + now = Time.zone.parse('2018-03-12 09:06') + Timecop.freeze(now) do + user = create(:user) + gitlab_sign_in(user) + expect(current_path).to eq root_path + + sessions = ActiveSession.list(user) + expect(sessions.count).to eq 1 + + # refresh the current page updates the updated_at + Timecop.freeze(now + 1.minute) do + visit current_path + + sessions = ActiveSession.list(user) + expect(sessions.first).to have_attributes( + created_at: Time.zone.parse('2018-03-12 09:06'), + updated_at: Time.zone.parse('2018-03-12 09:07') + ) + end + end + end + + scenario 'Successful login cleans up obsolete entries' do + user = create(:user) + + Gitlab::Redis::SharedState.with do |redis| + redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + end + + gitlab_sign_in(user) + + Gitlab::Redis::SharedState.with do |redis| + expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).not_to include '59822c7d9fcdfa03725eff41782ad97d' + end + end + + scenario 'Sessionless login does not clean up obsolete entries' do + user = create(:user) + personal_access_token = create(:personal_access_token, user: user) + + Gitlab::Redis::SharedState.with do |redis| + redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + end + + visit user_path(user, :atom, private_token: personal_access_token.token) + expect(page.status_code).to eq 200 + + Gitlab::Redis::SharedState.with do |redis| + expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to include '59822c7d9fcdfa03725eff41782ad97d' + end + end + + scenario 'Logout deletes the active user login' do + user = create(:user) + gitlab_sign_in(user) + expect(current_path).to eq root_path + + expect(ActiveSession.list(user).count).to eq 1 + + gitlab_sign_out + expect(current_path).to eq new_user_session_path + + expect(ActiveSession.list(user)).to be_empty + end +end diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index 9e10bfb2adc..94a2b289e64 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'Login' do + include TermsHelper + scenario 'Successful user signin invalidates password reset token' do user = create(:user) @@ -399,4 +401,41 @@ feature 'Login' do expect(page).to have_selector('.tab-pane.active', count: 1) end end + + context 'when terms are enforced' do + let(:user) { create(:user) } + + before do + enforce_terms + end + + it 'asks to accept the terms on first login' do + visit new_user_session_path + + fill_in 'user_login', with: user.email + fill_in 'user_password', with: '12345678' + + click_button 'Sign in' + + expect_to_be_on_terms_page + + click_button 'Accept terms' + + expect(current_path).to eq(root_path) + expect(page).not_to have_content('You are already signed in.') + end + + it 'does not ask for terms when the user already accepted them' do + accept_terms(user) + + visit new_user_session_path + + fill_in 'user_login', with: user.email + fill_in 'user_password', with: '12345678' + + click_button 'Sign in' + + expect(current_path).to eq(root_path) + end + end end diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index 5d539f0ccbe..b5bd5c505f2 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe 'Signup' do + include TermsHelper + let(:new_user) { build_stubbed(:user) } describe 'username validation', :js do @@ -132,4 +134,27 @@ describe 'Signup' do expect(page.body).not_to match(/#{new_user.password}/) end end + + context 'when terms are enforced' do + before do + enforce_terms + end + + it 'asks the user to accept terms before going to the dashboard' do + visit root_path + + fill_in 'new_user_name', with: new_user.name + fill_in 'new_user_username', with: new_user.username + fill_in 'new_user_email', with: new_user.email + fill_in 'new_user_email_confirmation', with: new_user.email + fill_in 'new_user_password', with: new_user.password + click_button "Register" + + expect_to_be_on_terms_page + + click_button 'Accept terms' + + expect(current_path).to eq dashboard_projects_path + end + end end diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb new file mode 100644 index 00000000000..bf6b5fa3d6a --- /dev/null +++ b/spec/features/users/terms_spec.rb @@ -0,0 +1,84 @@ +require 'spec_helper' + +describe 'Users > Terms' do + include TermsHelper + + let(:user) { create(:user) } + let!(:term) { create(:term, terms: 'By accepting, you promise to be nice!') } + + before do + stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') + sign_in(user) + end + + it 'shows the terms' do + visit terms_path + + expect(page).to have_content('By accepting, you promise to be nice!') + end + + context 'declining the terms' do + it 'returns the user to the app' do + visit terms_path + + click_button 'Decline and sign out' + + expect(page).not_to have_content(term.terms) + expect(user.reload.terms_accepted?).to be(false) + end + end + + context 'accepting the terms' do + it 'returns the user to the app' do + visit terms_path + + click_button 'Accept terms' + + expect(page).not_to have_content(term.terms) + expect(user.reload.terms_accepted?).to be(true) + end + end + + context 'terms were enforced while session is active', :js do + let(:project) { create(:project) } + + before do + project.add_developer(user) + end + + it 'redirects to terms and back to where the user was going' do + visit project_path(project) + + enforce_terms + + within('.nav-sidebar') do + click_link 'Issues' + end + + expect_to_be_on_terms_page + + click_button('Accept terms') + + expect(current_path).to eq(project_issues_path(project)) + end + + it 'redirects back to the page the user was trying to save' do + visit new_project_issue_path(project) + + fill_in :issue_title, with: 'Hello world, a new issue' + fill_in :issue_description, with: "We don't want to lose what the user typed" + + enforce_terms + + click_button 'Submit issue' + + expect(current_path).to eq(terms_path) + + click_button('Accept terms') + + expect(current_path).to eq(new_project_issue_path(project)) + expect(find_field('issue_title').value).to eq('Hello world, a new issue') + expect(find_field('issue_description').value).to eq("We don't want to lose what the user typed") + end + end +end |