diff options
Diffstat (limited to 'spec/features')
20 files changed, 764 insertions, 58 deletions
diff --git a/spec/features/builds_spec.rb b/spec/features/builds_spec.rb index cab3dc1d167..0cfeb2e57d8 100644 --- a/spec/features/builds_spec.rb +++ b/spec/features/builds_spec.rb @@ -199,9 +199,13 @@ describe "Builds" do click_link 'Retry' end - it { expect(page.status_code).to eq(200) } - it { expect(page).to have_content 'pending' } - it { expect(page).to have_content 'Cancel' } + it 'shows the right status and buttons' 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 "Build from other project" do @@ -212,7 +216,25 @@ describe "Builds" do page.driver.post(retry_namespace_project_build_path(@project.namespace, @project, @build2)) end - it { expect(page.status_code).to eq(404) } + it { expect(page).to have_http_status(404) } + end + + context "Build that current user is not allowed to retry" do + before do + @build.run! + @build.cancel! + @project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + + logout_direct + login_with(create(:user)) + visit namespace_project_build_path(@project.namespace, @project, @build) + end + + it 'does not show the Retry button' do + page.within('aside.right-sidebar') do + expect(page).not_to have_content 'Retry' + end + end end end diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 7fb28f4174b..fcd41b38413 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -13,6 +13,7 @@ feature 'Environments', feature: true do describe 'when showing environments' do given!(:environment) { } given!(:deployment) { } + given!(:manual) { } before do visit namespace_project_environments_path(project.namespace, project) @@ -43,6 +44,24 @@ feature 'Environments', feature: true do scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) end + + context 'with build and manual actions' do + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + scenario 'does show a play button' do + expect(page).to have_link(manual.name.humanize) + end + + scenario 'does allow to play manual action' do + expect(manual).to be_skipped + expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + expect(page).to have_content(manual.name) + expect(manual.reload).to be_pending + end + end end end @@ -54,6 +73,7 @@ feature 'Environments', feature: true do describe 'when showing the environment' do given(:environment) { create(:environment, project: project) } given!(:deployment) { } + given!(:manual) { } before do visit namespace_project_environment_path(project.namespace, project, environment) @@ -72,20 +92,36 @@ feature 'Environments', feature: true do expect(page).to have_link(deployment.short_sha) end - scenario 'does not show a retry button for deployment without build' do - expect(page).not_to have_link('Retry') + scenario 'does not show a re-deploy button for deployment without build' do + expect(page).not_to have_link('Re-deploy') end context 'with build' do - given(:build) { create(:ci_build, project: project) } + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } scenario 'does show build name' do expect(page).to have_link("#{build.name} (##{build.id})") end - scenario 'does show retry button' do - expect(page).to have_link('Retry') + scenario 'does show re-deploy button' do + expect(page).to have_link('Re-deploy') + end + + context 'with manual action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + scenario 'does show a play button' do + expect(page).to have_link(manual.name.humanize) + end + + scenario 'does allow to play manual action' do + expect(manual).to be_skipped + expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + expect(page).to have_content(manual.name) + expect(manual.reload).to be_pending + end end end end @@ -104,7 +140,7 @@ feature 'Environments', feature: true do context 'for valid name' do before do fill_in('Name', with: 'production') - click_on 'Create environment' + click_on 'Save' end scenario 'does create a new pipeline' do @@ -115,7 +151,7 @@ feature 'Environments', feature: true do context 'for invalid name' do before do fill_in('Name', with: 'name with spaces') - click_on 'Create environment' + click_on 'Save' end scenario 'does show errors' do diff --git a/spec/features/groups/members/user_requests_access_spec.rb b/spec/features/groups/members/user_requests_access_spec.rb index d1a6a98ab72..b3baa2ab57c 100644 --- a/spec/features/groups/members/user_requests_access_spec.rb +++ b/spec/features/groups/members/user_requests_access_spec.rb @@ -12,6 +12,13 @@ feature 'Groups > Members > User requests access', feature: true do visit group_path(group) end + scenario 'request access feature is disabled' do + group.update_attributes(request_access_enabled: false) + visit group_path(group) + + expect(page).not_to have_content 'Request Access' + end + scenario 'user can request access to a group' do perform_enqueued_jobs { click_link 'Request Access' } diff --git a/spec/features/issuables/default_sort_order_spec.rb b/spec/features/issuables/default_sort_order_spec.rb new file mode 100644 index 00000000000..0d495cd04aa --- /dev/null +++ b/spec/features/issuables/default_sort_order_spec.rb @@ -0,0 +1,171 @@ +require 'spec_helper' + +describe 'Projects > Issuables > Default sort order', feature: true do + let(:project) { create(:empty_project, :public) } + + let(:first_created_issuable) { issuables.order_created_asc.first } + let(:last_created_issuable) { issuables.order_created_desc.first } + + let(:first_updated_issuable) { issuables.order_updated_asc.first } + let(:last_updated_issuable) { issuables.order_updated_desc.first } + + context 'for merge requests' do + include MergeRequestHelpers + + let!(:issuables) do + timestamps = [{ created_at: 3.minutes.ago, updated_at: 20.seconds.ago }, + { created_at: 2.minutes.ago, updated_at: 30.seconds.ago }, + { created_at: 4.minutes.ago, updated_at: 10.seconds.ago }] + + timestamps.each_with_index do |ts, i| + create issuable_type, { title: "#{issuable_type}_#{i}", + source_branch: "#{issuable_type}_#{i}", + source_project: project }.merge(ts) + end + + MergeRequest.all + end + + context 'in the "merge requests" tab', js: true do + let(:issuable_type) { :merge_request } + + it 'is "last created"' do + visit_merge_requests project + + expect(first_merge_request).to include(last_created_issuable.title) + expect(last_merge_request).to include(first_created_issuable.title) + end + end + + context 'in the "merge requests / open" tab', js: true do + let(:issuable_type) { :merge_request } + + it 'is "last created"' do + visit_merge_requests_with_state(project, 'open') + + expect(selected_sort_order).to eq('last created') + expect(first_merge_request).to include(last_created_issuable.title) + expect(last_merge_request).to include(first_created_issuable.title) + end + end + + context 'in the "merge requests / merged" tab', js: true do + let(:issuable_type) { :merged_merge_request } + + it 'is "last updated"' do + visit_merge_requests_with_state(project, 'merged') + + expect(selected_sort_order).to eq('last updated') + expect(first_merge_request).to include(last_updated_issuable.title) + expect(last_merge_request).to include(first_updated_issuable.title) + end + end + + context 'in the "merge requests / closed" tab', js: true do + let(:issuable_type) { :closed_merge_request } + + it 'is "last updated"' do + visit_merge_requests_with_state(project, 'closed') + + expect(selected_sort_order).to eq('last updated') + expect(first_merge_request).to include(last_updated_issuable.title) + expect(last_merge_request).to include(first_updated_issuable.title) + end + end + + context 'in the "merge requests / all" tab', js: true do + let(:issuable_type) { :merge_request } + + it 'is "last created"' do + visit_merge_requests_with_state(project, 'all') + + expect(selected_sort_order).to eq('last created') + expect(first_merge_request).to include(last_created_issuable.title) + expect(last_merge_request).to include(first_created_issuable.title) + end + end + end + + context 'for issues' do + include IssueHelpers + + let!(:issuables) do + timestamps = [{ created_at: 3.minutes.ago, updated_at: 20.seconds.ago }, + { created_at: 2.minutes.ago, updated_at: 30.seconds.ago }, + { created_at: 4.minutes.ago, updated_at: 10.seconds.ago }] + + timestamps.each_with_index do |ts, i| + create issuable_type, { title: "#{issuable_type}_#{i}", + project: project }.merge(ts) + end + + Issue.all + end + + context 'in the "issues" tab', js: true do + let(:issuable_type) { :issue } + + it 'is "last created"' do + visit_issues project + + expect(selected_sort_order).to eq('last created') + expect(first_issue).to include(last_created_issuable.title) + expect(last_issue).to include(first_created_issuable.title) + end + end + + context 'in the "issues / open" tab', js: true do + let(:issuable_type) { :issue } + + it 'is "last created"' do + visit_issues_with_state(project, 'open') + + expect(selected_sort_order).to eq('last created') + expect(first_issue).to include(last_created_issuable.title) + expect(last_issue).to include(first_created_issuable.title) + end + end + + context 'in the "issues / closed" tab', js: true do + let(:issuable_type) { :closed_issue } + + it 'is "last updated"' do + visit_issues_with_state(project, 'closed') + + expect(selected_sort_order).to eq('last updated') + expect(first_issue).to include(last_updated_issuable.title) + expect(last_issue).to include(first_updated_issuable.title) + end + end + + context 'in the "issues / all" tab', js: true do + let(:issuable_type) { :issue } + + it 'is "last created"' do + visit_issues_with_state(project, 'all') + + expect(selected_sort_order).to eq('last created') + expect(first_issue).to include(last_created_issuable.title) + expect(last_issue).to include(first_created_issuable.title) + end + end + end + + def selected_sort_order + find('.pull-right .dropdown button').text.downcase + end + + def visit_merge_requests_with_state(project, state) + visit_merge_requests project + visit_issuables_with_state state + end + + def visit_issues_with_state(project, state) + visit_issues project + visit_issuables_with_state state + end + + def visit_issuables_with_state(state) + within('.issues-state-filters') { find("span", text: state.titleize).click } + end +end diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 5ea02b8d39c..cb117d2476f 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -205,7 +205,7 @@ feature 'Issue filtering by Labels', feature: true do page.within '.labels-filter' do click_button 'Label' wait_for_ajax - fill_in 'label-name', with: 'bug' + find('.dropdown-input input').set 'bug' page.within '.dropdown-content' do expect(page).not_to have_content 'enhancement' diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index d51c9abea19..9c92b52898c 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe 'Issues', feature: true do + include IssueHelpers include SortingHelper let(:project) { create(:project) } @@ -186,15 +187,15 @@ describe 'Issues', feature: true do it 'sorts by newest' do visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created) - expect(first_issue).to include('baz') - expect(last_issue).to include('foo') + 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) - expect(first_issue).to include('foo') - expect(last_issue).to include('baz') + expect(first_issue).to include('baz') + expect(last_issue).to include('foo') end it 'sorts by most recently updated' do @@ -350,8 +351,8 @@ describe 'Issues', feature: true do sort: sort_value_oldest_created, assignee_id: user2.id) - expect(first_issue).to include('foo') - expect(last_issue).to include('bar') + expect(first_issue).to include('bar') + expect(last_issue).to include('foo') expect(page).not_to have_content 'baz' end end @@ -524,6 +525,35 @@ describe 'Issues', feature: true do end end + describe 'new issue by email' do + shared_examples 'show the email in the modal' do + before do + stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") + + visit namespace_project_issues_path(project.namespace, 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) + + expect(page).to have_selector("input[value='#{email}']") + end + end + end + + context 'with existing issues' do + let!(:issue) { create(:issue, project: project, author: @user) } + + it_behaves_like 'show the email in the modal' + end + + context 'without existing issues' do + it_behaves_like 'show the email in the modal' + end + end + describe 'due date' do context 'update due on issue#show', js: true do let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } @@ -561,14 +591,6 @@ describe 'Issues', feature: true do end end - def first_issue - page.all('ul.issues-list > li').first.text - end - - def last_issue - page.all('ul.issues-list > li').last.text - end - def drop_in_dropzone(file_path) # Generate a fake input selector page.execute_script <<-JS diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 09ccc77c101..32159559c37 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -236,6 +236,14 @@ describe 'GitLab Markdown', feature: true do it 'includes TaskListFilter' do expect(doc).to parse_task_lists end + + it 'includes InlineDiffFilter' do + expect(doc).to parse_inline_diffs + end + + it 'includes VideoLinkFilter' do + expect(doc).to parse_video_links + end end context 'wiki pipeline' do @@ -293,6 +301,10 @@ describe 'GitLab Markdown', feature: true do it 'includes InlineDiffFilter' do expect(doc).to parse_inline_diffs end + + it 'includes VideoLinkFilter' do + expect(doc).to parse_video_links + end end # Fake a `current_user` helper 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 1c130057c56..cabb8e455f9 100644 --- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe 'Projects > Merge requests > User lists merge requests', feature: true do + include MergeRequestHelpers include SortingHelper let(:project) { create(:project, :public) } @@ -23,10 +24,12 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true milestone: create(:milestone, due_date: '2013-12-12'), created_at: 2.minutes.ago, updated_at: 2.minutes.ago) + # lfs in itself is not a great choice for the title if one wants to match the whole body content later on + # just think about the scenario when faker generates 'Chester Runolfsson' as the user's name create(:merge_request, - title: 'lfs', + title: 'merge_lfs', source_project: project, - source_branch: 'lfs', + source_branch: 'merge_lfs', created_at: 3.minutes.ago, updated_at: 10.seconds.ago) end @@ -35,7 +38,7 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true visit_merge_requests(project, assignee_id: IssuableFinder::NONE) expect(current_path).to eq(namespace_project_merge_requests_path(project.namespace, project)) - expect(page).to have_content 'lfs' + expect(page).to have_content 'merge_lfs' expect(page).not_to have_content 'fix' expect(page).not_to have_content 'markdown' expect(count_merge_requests).to eq(1) @@ -44,7 +47,7 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true it 'filters on a specific assignee' do visit_merge_requests(project, assignee_id: user.id) - expect(page).not_to have_content 'lfs' + expect(page).not_to have_content 'merge_lfs' expect(page).to have_content 'fix' expect(page).to have_content 'markdown' expect(count_merge_requests).to eq(2) @@ -53,23 +56,23 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true it 'sorts by newest' do visit_merge_requests(project, sort: sort_value_recently_created) - expect(first_merge_request).to include('lfs') - expect(last_merge_request).to include('fix') + expect(first_merge_request).to include('fix') + expect(last_merge_request).to include('merge_lfs') expect(count_merge_requests).to eq(3) end it 'sorts by oldest' do visit_merge_requests(project, sort: sort_value_oldest_created) - expect(first_merge_request).to include('fix') - expect(last_merge_request).to include('lfs') + expect(first_merge_request).to include('merge_lfs') + expect(last_merge_request).to include('fix') expect(count_merge_requests).to eq(3) end it 'sorts by last updated' do visit_merge_requests(project, sort: sort_value_recently_updated) - expect(first_merge_request).to include('lfs') + expect(first_merge_request).to include('merge_lfs') expect(count_merge_requests).to eq(3) end @@ -143,18 +146,6 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true end end - def visit_merge_requests(project, opts = {}) - visit namespace_project_merge_requests_path(project.namespace, project, opts) - end - - def first_merge_request - page.all('ul.mr-list > li').first.text - end - - def last_merge_request - page.all('ul.mr-list > li').last.text - end - def count_merge_requests page.all('ul.mr-list > li').count end diff --git a/spec/features/pipelines_settings_spec.rb b/spec/features/pipelines_settings_spec.rb new file mode 100644 index 00000000000..dcc364a3d01 --- /dev/null +++ b/spec/features/pipelines_settings_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +feature "Pipelines settings", feature: true do + include GitlabRoutingHelper + + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:role) { :developer } + + background do + login_as(user) + project.team << [user, role] + visit namespace_project_pipelines_settings_path(project.namespace, project) + end + + context 'for developer' do + given(:role) { :developer } + + scenario 'to be disallowed to view' do + expect(page.status_code).to eq(404) + end + end + + context 'for master' do + given(:role) { :master } + + scenario 'be allowed to change' do + fill_in('Test coverage parsing', with: 'coverage_regex') + click_on 'Save changes' + + expect(page.status_code).to eq(200) + expect(page).to have_field('Test coverage parsing', with: 'coverage_regex') + end + end +end diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb index e7ee0aaea3c..377a9aba60d 100644 --- a/spec/features/pipelines_spec.rb +++ b/spec/features/pipelines_spec.rb @@ -62,6 +62,20 @@ describe "Pipelines" do end end + context 'with manual actions' do + let!(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'manual build', stage: 'test', commands: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).to have_link('Manual build') } + + context 'when playing' do + before { click_link('Manual build') } + + it { expect(manual.reload).to be_pending } + end + end + context 'for generic statuses' do context 'when running' do let!(:running) { create(:generic_commit_status, status: 'running', pipeline: pipeline, stage: 'test') } @@ -102,9 +116,19 @@ describe "Pipelines" do it { expect(page).to have_link(with_artifacts.name) } end + context 'with artifacts expired' do + let!(:with_artifacts_expired) { create(:ci_build, :artifacts_expired, :success, pipeline: pipeline, name: 'rspec', stage: 'test') } + + before { visit namespace_project_pipelines_path(project.namespace, project) } + + it { expect(page).not_to have_selector('.build-artifacts') } + end + context 'without artifacts' do let!(:without_artifacts) { create(:ci_build, :success, pipeline: pipeline, name: 'rspec', stage: 'test') } + before { visit namespace_project_pipelines_path(project.namespace, project) } + it { expect(page).not_to have_selector('.build-artifacts') } end end @@ -117,6 +141,7 @@ describe "Pipelines" do @success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build') @failed = create(:ci_build, :failed, pipeline: pipeline, stage: 'test', name: 'test', commands: 'test') @running = create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', name: 'deploy') + @manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual build') @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') end @@ -131,6 +156,7 @@ describe "Pipelines" do expect(page).to have_content(@external.id) expect(page).to have_content('Retry failed') expect(page).to have_content('Cancel running') + expect(page).to have_link('Play') end context 'retrying builds' do @@ -154,6 +180,12 @@ describe "Pipelines" do it { expect(page).to have_selector('.ci-canceled') } end end + + context 'playing manual build' do + before { click_link('Play') } + + it { expect(@manual.reload).to be_pending } + end end describe 'POST /:project/pipelines' do diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb index 01e90618a98..75166bca119 100644 --- a/spec/features/projects/badges/list_spec.rb +++ b/spec/features/projects/badges/list_spec.rb @@ -6,7 +6,7 @@ feature 'list of badges' do project = create(:project) project.team << [user, :master] login_as(user) - visit namespace_project_badges_path(project.namespace, project) + visit namespace_project_pipelines_settings_path(project.namespace, project) end scenario 'user displays list of badges' do diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb new file mode 100644 index 00000000000..79abba21854 --- /dev/null +++ b/spec/features/projects/branches_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe 'Branches', feature: true do + let(:project) { create(:project) } + let(:repository) { project.repository } + + before do + login_as :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) + + repository.branches { |branch| expect(page).to have_content("#{branch.name}") } + expect(page).to have_content("Protected branches can be managed in project settings") + end + end + + describe 'Find branches' do + it 'shows filtered branches', js: true do + visit namespace_project_branches_path(project.namespace, project, project.id) + + fill_in 'branch-search', with: 'fix' + find('#branch-search').native.send_keys(:enter) + + expect(page).to have_content('fix') + expect(find('.all-branches')).to have_selector('li', count: 1) + 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 bc3bf53fe9d..7835e1678ad 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -8,6 +8,7 @@ feature 'project import', feature: true, js: true do let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } let(:project) { Project.last } + let(:project_hook) { Gitlab::Git::Hook.new('post-receive', project.repository.path) } background do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) @@ -37,7 +38,7 @@ feature 'project import', feature: true, js: true do expect(project).not_to be_nil expect(project.issues).not_to be_empty expect(project.merge_requests).not_to be_empty - expect(project.repo_exists?).to be true + expect(project_hook).to exist expect(wiki_exists?).to be true expect(project.import_status).to eq('finished') end @@ -59,6 +60,21 @@ feature 'project import', feature: true, js: true do end end + scenario 'project with no name' do + create(:project, namespace_id: 2) + + visit new_project_path + + select2('2', from: '#project_namespace_id') + + # click on disabled element + find(:link, 'GitLab export').trigger('click') + + page.within('.flash-container') do + expect(page).to have_content('Please enter path and name') + end + end + def wiki_exists? wiki = ProjectWiki.new(project) File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty? diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index f2fe3ef364d..56ede8eb5be 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -11,6 +11,13 @@ feature 'Projects > Members > User requests access', feature: true do visit namespace_project_path(project.namespace, project) end + scenario 'request access feature is disabled' do + project.update_attributes(request_access_enabled: false) + visit namespace_project_path(project.namespace, project) + + expect(page).not_to have_content 'Request Access' + end + scenario 'user can request access to a project' do perform_enqueued_jobs { click_link 'Request Access' } diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb new file mode 100644 index 00000000000..3de25d7af7d --- /dev/null +++ b/spec/features/projects/project_settings_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe 'Edit Project Settings', feature: true do + let(:user) { create(:user) } + let(:project) { create(:empty_project, path: 'gitlab', name: 'sample') } + + before do + login_as(user) + project.team << [user, :master] + end + + describe 'Project settings', js: true do + it 'shows errors for invalid project name' do + visit edit_namespace_project_path(project.namespace, project) + + fill_in 'project_name_edit', with: 'foo&bar' + + click_button 'Save changes' + + expect(page).to have_field 'project_name_edit', with: 'foo&bar' + expect(page).to have_content "Name can contain only letters, digits, '_', '.', dash and space. It must start with letter, digit or '_'." + expect(page).to have_button 'Save changes' + end + end + + describe 'Rename repository' do + it 'shows errors for invalid project path/name' do + visit edit_namespace_project_path(project.namespace, project) + + fill_in 'Project name', with: 'foo&bar' + fill_in 'Path', with: 'foo&bar' + + click_button 'Rename project' + + expect(page).to have_field 'Project name', with: 'foo&bar' + expect(page).to have_field 'Path', with: 'foo&bar' + expect(page).to have_content "Name can contain only letters, digits, '_', '.', dash and space. It must start with letter, digit or '_'." + expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'" + end + end +end diff --git a/spec/features/projects/slack_service/slack_service_spec.rb b/spec/features/projects/slack_service/slack_service_spec.rb new file mode 100644 index 00000000000..16541f51d98 --- /dev/null +++ b/spec/features/projects/slack_service/slack_service_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +feature 'Projects > Slack service > Setup events', feature: true do + let(:user) { create(:user) } + let(:service) { SlackService.new } + let(:project) { create(:project, slack_service: service) } + + background do + service.fields + service.update_attributes(push_channel: 1, issue_channel: 2, merge_request_channel: 3, note_channel: 4, tag_push_channel: 5, build_channel: 6, wiki_page_channel: 7) + project.team << [user, :master] + login_as(user) + end + + scenario 'user can filter events by channel' do + visit edit_namespace_project_service_path(project.namespace, 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' + expect(page.find_field("service_merge_request_channel").value).to have_content '3' + expect(page.find_field("service_note_channel").value).to have_content '4' + expect(page.find_field("service_tag_push_channel").value).to have_content '5' + expect(page.find_field("service_build_channel").value).to have_content '6' + expect(page.find_field("service_wiki_page_channel").value).to have_content '7' + end +end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb new file mode 100644 index 00000000000..a1c386ddc18 --- /dev/null +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -0,0 +1,140 @@ +require 'spec_helper' + +feature 'Projects > Wiki > User previews markdown changes', feature: true, js: true do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + let(:wiki_content) do + <<-HEREDOC +[regular link](regular) +[relative link 1](../relative) +[relative link 2](./relative) +[relative link 3](./e/f/relative) + HEREDOC + end + + background do + project.team << [user, :master] + login_as(user) + + visit namespace_project_path(project.namespace, project) + click_link 'Wiki' + WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute + end + + context "while creating a new wiki page" do + context "when there are no spaces or hyphens in the page name" do + it "rewrites relative links as expected" do + click_link 'New Page' + fill_in :new_wiki_path, with: 'a/b/c/d' + click_button 'Create Page' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + + context "when there are spaces in the page name" do + it "rewrites relative links as expected" do + click_link 'New Page' + fill_in :new_wiki_path, with: 'a page/b page/c page/d page' + click_button 'Create Page' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + + context "when there are hyphens in the page name" do + it "rewrites relative links as expected" do + click_link 'New Page' + fill_in :new_wiki_path, with: 'a-page/b-page/c-page/d-page' + click_button 'Create Page' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + end + + context "while editing a wiki page" do + def create_wiki_page(path) + click_link 'New Page' + fill_in :new_wiki_path, with: path + click_button 'Create Page' + fill_in :wiki_content, with: 'content' + click_on "Create page" + end + + context "when there are no spaces or hyphens in the page name" do + it "rewrites relative links as expected" do + create_wiki_page 'a/b/c/d' + click_link 'Edit' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + + context "when there are spaces in the page name" do + it "rewrites relative links as expected" do + create_wiki_page 'a page/b page/c page/d page' + click_link 'Edit' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + + context "when there are hyphens in the page name" do + it "rewrites relative links as expected" do + create_wiki_page 'a-page/b-page/c-page/d-page' + click_link 'Edit' + + fill_in :wiki_content, with: wiki_content + click_on "Preview" + + 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>") + end + end + end +end diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb index 7e6eef65873..7afd83b7250 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -30,18 +30,48 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute end - scenario 'via the "new wiki page" page', js: true do - click_link 'New Page' + context 'via the "new wiki page" page' do + scenario 'when the wiki page has a single word name', js: true do + click_link 'New Page' - fill_in :new_wiki_path, with: 'foo' - click_button 'Create Page' + fill_in :new_wiki_path, with: 'foo' + click_button 'Create Page' - fill_in :wiki_content, with: 'My awesome wiki!' - click_button 'Create page' + fill_in :wiki_content, with: 'My awesome wiki!' + click_button 'Create page' - 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') + expect(page).to have_content("last edited by #{user.name}") + expect(page).to have_content('My awesome wiki!') + end + + scenario 'when the wiki page has spaces in the name', js: true do + click_link 'New Page' + + fill_in :new_wiki_path, with: 'Spaces in the name' + click_button 'Create Page' + + fill_in :wiki_content, with: 'My awesome wiki!' + click_button 'Create page' + + 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!') + end + + scenario 'when the wiki page has hyphens in the name', js: true do + click_link 'New Page' + + fill_in :new_wiki_path, with: 'hyphens-in-the-name' + click_button 'Create Page' + + fill_in :wiki_content, with: 'My awesome wiki!' + click_button 'Create page' + + 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!') + end end end end diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index d94dee0c797..57734b33a44 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'Projected Branches', feature: true, js: true do + include WaitForAjax + let(:user) { create(:user, :admin) } let(:project) { create(:project) } @@ -81,4 +83,68 @@ feature 'Projected Branches', feature: true, js: true do end end end + + describe "access control" do + ProtectedBranch::PushAccessLevel.human_access_levels.each do |(access_type_id, access_type_name)| + it "allows creating protected branches that #{access_type_name} can push to" do + visit namespace_project_protected_branches_path(project.namespace, project) + set_protected_branch_name('master') + within('.new_protected_branch') do + find(".allowed-to-push").click + within(".dropdown.open .dropdown-menu") { click_on access_type_name } + end + click_on "Protect" + + expect(ProtectedBranch.count).to eq(1) + expect(ProtectedBranch.last.push_access_level.access_level).to eq(access_type_id) + end + + it "allows updating protected branches so that #{access_type_name} can push to them" do + visit namespace_project_protected_branches_path(project.namespace, project) + set_protected_branch_name('master') + click_on "Protect" + + expect(ProtectedBranch.count).to eq(1) + + within(".protected-branches-list") do + find(".allowed-to-push").click + within('.dropdown-menu.push') { click_on access_type_name } + end + + wait_for_ajax + expect(ProtectedBranch.last.push_access_level.access_level).to eq(access_type_id) + end + end + + ProtectedBranch::MergeAccessLevel.human_access_levels.each do |(access_type_id, access_type_name)| + it "allows creating protected branches that #{access_type_name} can merge to" do + visit namespace_project_protected_branches_path(project.namespace, project) + set_protected_branch_name('master') + within('.new_protected_branch') do + find(".allowed-to-merge").click + within(".dropdown.open .dropdown-menu") { click_on access_type_name } + end + click_on "Protect" + + expect(ProtectedBranch.count).to eq(1) + expect(ProtectedBranch.last.merge_access_level.access_level).to eq(access_type_id) + end + + it "allows updating protected branches so that #{access_type_name} can merge to them" do + visit namespace_project_protected_branches_path(project.namespace, project) + set_protected_branch_name('master') + click_on "Protect" + + expect(ProtectedBranch.count).to eq(1) + + within(".protected-branches-list") do + find(".allowed-to-merge").click + within('.dropdown-menu.merge') { click_on access_type_name } + end + + wait_for_ajax + expect(ProtectedBranch.last.merge_access_level.access_level).to eq(access_type_id) + end + end + end end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index d0a301038c4..09f70cd3b00 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -28,6 +28,26 @@ describe "Search", feature: true do end context 'search for comments' do + context 'when comment belongs to a invalid commit' do + 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) } + + it 'finds comment' do + visit namespace_project_path(project.namespace, project) + + page.within '.search' do + fill_in 'search', with: note.note + click_button 'Go' + end + + click_link 'Comments' + + expect(page).to have_text("Commit deleted") + expect(page).to have_text("12345678") + end + end + it 'finds a snippet' do snippet = create(:project_snippet, :private, project: project, author: user, title: 'Some title') note = create(:note, |