summaryrefslogtreecommitdiff
path: root/spec/features/projects
diff options
context:
space:
mode:
Diffstat (limited to 'spec/features/projects')
-rw-r--r--spec/features/projects/artifacts/browse_spec.rb50
-rw-r--r--spec/features/projects/artifacts/download_spec.rb2
-rw-r--r--spec/features/projects/artifacts/file_spec.rb1
-rw-r--r--spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb104
-rw-r--r--spec/features/projects/badges/coverage_spec.rb2
-rw-r--r--spec/features/projects/badges/list_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_line_permalink_updater_spec.rb2
-rw-r--r--spec/features/projects/blobs/edit_spec.rb3
-rw-r--r--spec/features/projects/blobs/shortcuts_blob_spec.rb2
-rw-r--r--spec/features/projects/branches/download_buttons_spec.rb2
-rw-r--r--spec/features/projects/branches_spec.rb102
-rw-r--r--spec/features/projects/clusters_spec.rb111
-rw-r--r--spec/features/projects/commit/builds_spec.rb3
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb2
-rw-r--r--spec/features/projects/commit/diff_notes_spec.rb36
-rw-r--r--spec/features/projects/commit/user_reverts_commit_spec.rb56
-rw-r--r--spec/features/projects/compare_spec.rb2
-rw-r--r--spec/features/projects/deploy_keys_spec.rb2
-rw-r--r--spec/features/projects/developer_views_empty_project_instructions_spec.rb4
-rw-r--r--spec/features/projects/diffs/diff_show_spec.rb53
-rw-r--r--spec/features/projects/edit_spec.rb33
-rw-r--r--spec/features/projects/environments/environment_spec.rb8
-rw-r--r--spec/features/projects/environments/environments_spec.rb208
-rw-r--r--spec/features/projects/features_visibility_spec.rb51
-rw-r--r--spec/features/projects/files/browse_files_spec.rb2
-rw-r--r--spec/features/projects/files/creating_a_file_spec.rb2
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/edit_file_soft_wrap_spec.rb28
-rw-r--r--spec/features/projects/files/find_file_keyboard_spec.rb2
-rw-r--r--spec/features/projects/files/gitignore_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/project_owner_creates_license_file_spec.rb2
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb2
-rw-r--r--spec/features/projects/files/template_type_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/fork_spec.rb57
-rw-r--r--spec/features/projects/gfm_autocomplete_load_spec.rb2
-rw-r--r--spec/features/projects/group_links_spec.rb77
-rw-r--r--spec/features/projects/import_export/export_file_spec.rb4
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb29
-rw-r--r--spec/features/projects/import_export/namespace_export_file_spec.rb4
-rw-r--r--spec/features/projects/import_export/test_project_export.tar.gzbin681481 -> 679559 bytes
-rw-r--r--spec/features/projects/issuable_templates_spec.rb56
-rw-r--r--spec/features/projects/issues/list_spec.rb20
-rw-r--r--spec/features/projects/issues/user_views_issues_spec.rb56
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb37
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb32
-rw-r--r--spec/features/projects/jobs_spec.rb50
-rw-r--r--spec/features/projects/labels/subscription_spec.rb2
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb10
-rw-r--r--spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb2
-rw-r--r--spec/features/projects/members/groups_with_access_list_spec.rb (renamed from spec/features/projects/members/group_links_spec.rb)17
-rw-r--r--spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb6
-rw-r--r--spec/features/projects/members/share_with_group_spec.rb191
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb2
-rw-r--r--spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb84
-rw-r--r--spec/features/projects/merge_requests/user_closes_merge_request_spec.rb21
-rw-r--r--spec/features/projects/merge_requests/user_comments_on_commit_spec.rb19
-rw-r--r--spec/features/projects/merge_requests/user_comments_on_diff_spec.rb173
-rw-r--r--spec/features/projects/merge_requests/user_comments_on_merge_request_spec.rb50
-rw-r--r--spec/features/projects/merge_requests/user_creates_merge_request_spec.rb32
-rw-r--r--spec/features/projects/merge_requests/user_edits_merge_request_spec.rb26
-rw-r--r--spec/features/projects/merge_requests/user_manages_subscription_spec.rb32
-rw-r--r--spec/features/projects/merge_requests/user_reopens_merge_request_spec.rb22
-rw-r--r--spec/features/projects/merge_requests/user_reverts_merge_request_spec.rb59
-rw-r--r--spec/features/projects/merge_requests/user_sorts_merge_requests_spec.rb63
-rw-r--r--spec/features/projects/merge_requests/user_views_all_merge_requests_spec.rb15
-rw-r--r--spec/features/projects/merge_requests/user_views_closed_merge_requests_spec.rb15
-rw-r--r--spec/features/projects/merge_requests/user_views_diffs_spec.rb46
-rw-r--r--spec/features/projects/merge_requests/user_views_merged_merge_requests_spec.rb15
-rw-r--r--spec/features/projects/merge_requests/user_views_open_merge_request_spec.rb92
-rw-r--r--spec/features/projects/merge_requests/user_views_open_merge_requests_spec.rb115
-rw-r--r--spec/features/projects/milestones/user_interacts_with_labels_spec.rb40
-rw-r--r--spec/features/projects/new_project_spec.rb37
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb26
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb40
-rw-r--r--spec/features/projects/project_settings_spec.rb30
-rw-r--r--spec/features/projects/ref_switcher_spec.rb37
-rw-r--r--spec/features/projects/services/slack_service_spec.rb26
-rw-r--r--spec/features/projects/services/user_activates_asana_spec.rb24
-rw-r--r--spec/features/projects/services/user_activates_assembla_spec.rb23
-rw-r--r--spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb31
-rw-r--r--spec/features/projects/services/user_activates_emails_on_push_spec.rb23
-rw-r--r--spec/features/projects/services/user_activates_flowdock_spec.rb23
-rw-r--r--spec/features/projects/services/user_activates_hipchat_spec.rb38
-rw-r--r--spec/features/projects/services/user_activates_irker_spec.rb24
-rw-r--r--spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb26
-rw-r--r--spec/features/projects/services/user_activates_jira_spec.rb (renamed from spec/features/projects/services/jira_service_spec.rb)4
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb (renamed from spec/features/projects/services/mattermost_slash_command_spec.rb)8
-rw-r--r--spec/features/projects/services/user_activates_packagist_spec.rb24
-rw-r--r--spec/features/projects/services/user_activates_pivotaltracker_spec.rb23
-rw-r--r--spec/features/projects/services/user_activates_pushover_spec.rb27
-rw-r--r--spec/features/projects/services/user_activates_slack_notifications_spec.rb54
-rw-r--r--spec/features/projects/services/user_activates_slack_slash_command_spec.rb (renamed from spec/features/projects/services/slack_slash_command_spec.rb)0
-rw-r--r--spec/features/projects/services/user_views_services_spec.rb26
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb40
-rw-r--r--spec/features/projects/settings/integration_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/merge_requests_settings_spec.rb12
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb12
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb5
-rw-r--r--spec/features/projects/settings/user_manages_group_links_spec.rb41
-rw-r--r--spec/features/projects/settings/user_manages_project_members_spec.rb68
-rw-r--r--spec/features/projects/settings/visibility_settings_spec.rb21
-rw-r--r--spec/features/projects/shortcuts_spec.rb21
-rw-r--r--spec/features/projects/show_project_spec.rb2
-rw-r--r--spec/features/projects/snippets/create_snippet_spec.rb4
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb25
-rw-r--r--spec/features/projects/snippets/user_deletes_snippet_spec.rb20
-rw-r--r--spec/features/projects/snippets/user_updates_snippet_spec.rb25
-rw-r--r--spec/features/projects/snippets/user_views_snippets_spec.rb20
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb40
-rw-r--r--spec/features/projects/tree/create_file_spec.rb35
-rw-r--r--spec/features/projects/tree/upload_file_spec.rb46
-rw-r--r--spec/features/projects/user_archives_project_spec.rb43
-rw-r--r--spec/features/projects/user_browses_a_tree_with_a_folder_containing_only_a_folder.rb20
-rw-r--r--spec/features/projects/user_browses_files_spec.rb13
-rw-r--r--spec/features/projects/user_creates_directory_spec.rb4
-rw-r--r--spec/features/projects/user_creates_files_spec.rb18
-rw-r--r--spec/features/projects/user_creates_project_spec.rb2
-rw-r--r--spec/features/projects/user_deletes_files_spec.rb6
-rw-r--r--spec/features/projects/user_edits_files_spec.rb67
-rw-r--r--spec/features/projects/user_interacts_with_stars_spec.rb2
-rw-r--r--spec/features/projects/user_replaces_files_spec.rb6
-rw-r--r--spec/features/projects/user_uploads_files_spec.rb13
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb108
-rw-r--r--spec/features/projects/user_views_details_spec.rb151
-rw-r--r--spec/features/projects/view_on_env_spec.rb2
-rw-r--r--spec/features/projects/wiki/markdown_preview_spec.rb9
-rw-r--r--spec/features/projects/wiki/shortcuts_spec.rb4
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb231
-rw-r--r--spec/features/projects/wiki/user_deletes_wiki_page_spec.rb19
-rw-r--r--spec/features/projects/wiki/user_git_access_wiki_page_spec.rb9
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb149
-rw-r--r--spec/features/projects/wiki/user_views_project_wiki_page_spec.rb39
-rw-r--r--spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb7
-rw-r--r--spec/features/projects/wiki/user_views_wiki_page_spec.rb145
137 files changed, 3720 insertions, 824 deletions
diff --git a/spec/features/projects/artifacts/browse_spec.rb b/spec/features/projects/artifacts/browse_spec.rb
index 42b47cb3301..cb69aff8d5f 100644
--- a/spec/features/projects/artifacts/browse_spec.rb
+++ b/spec/features/projects/artifacts/browse_spec.rb
@@ -4,16 +4,15 @@ 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
- let(:browse_url) do
- browse_path('other_artifacts_0.1.2')
- end
-
before do
visit browse_url.sub('/-/jobs', '/builds')
end
@@ -22,4 +21,47 @@ feature 'Browse artifact', :js 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
index f1bdb2812c6..6f76c14910b 100644
--- a/spec/features/projects/artifacts/download_spec.rb
+++ b/spec/features/projects/artifacts/download_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Download artifact', :js do
+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) }
diff --git a/spec/features/projects/artifacts/file_spec.rb b/spec/features/projects/artifacts/file_spec.rb
index b2be10a7e0c..df1d17bdcb7 100644
--- a/spec/features/projects/artifacts/file_spec.rb
+++ b/spec/features/projects/artifacts/file_spec.rb
@@ -39,7 +39,6 @@ feature 'Artifact file', :js do
context 'JPG file' do
before do
- page.driver.browser.url_blacklist = []
visit_file('rails_sample.jpg')
wait_for_requests
diff --git a/spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb b/spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb
new file mode 100644
index 00000000000..adff0a10f0e
--- /dev/null
+++ b/spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb
@@ -0,0 +1,104 @@
+require 'spec_helper'
+
+describe 'User interacts with awards in an issue', :js do
+ let(:issue) { create(:issue, project: project)}
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_issue_path(project, issue))
+ end
+
+ it 'toggles the thumbsup award emoji' do
+ page.within('.awards') do
+ thumbsup = page.first('.award-control')
+ thumbsup.click
+ thumbsup.hover
+
+ expect(page).to have_selector('.js-emoji-btn')
+ expect(page).to have_css(".js-emoji-btn.active[data-original-title='You']")
+ expect(page.find('.js-emoji-btn.active .js-counter')).to have_content('1')
+
+ thumbsup = page.first('.award-control')
+ thumbsup.click
+ thumbsup.hover
+
+ expect(page).to have_selector('.award-control.js-emoji-btn')
+ expect(page.all('.award-control.js-emoji-btn').size).to eq(2)
+
+ page.all('.award-control.js-emoji-btn').each do |element|
+ expect(element['title']).to eq('')
+ end
+
+ page.all('.award-control .js-counter').each do |element|
+ expect(element).to have_content('0')
+ end
+
+ thumbsup = page.first('.award-control')
+ thumbsup.click
+ thumbsup.hover
+
+ expect(page).to have_selector('.js-emoji-btn')
+ expect(page).to have_css(".js-emoji-btn.active[data-original-title='You']")
+ expect(page.find('.js-emoji-btn.active .js-counter')).to have_content('1')
+ end
+ end
+
+ it 'toggles a custom award emoji' do
+ page.within('.awards') do
+ page.find('.js-add-award').click
+ end
+
+ page.find('.emoji-menu.is-visible')
+
+ expect(page).to have_selector('.js-emoji-menu-search')
+ expect(page.evaluate_script("document.activeElement.classList.contains('js-emoji-menu-search')")).to eq(true)
+
+ page.within('.emoji-menu-content') do
+ emoji_button = page.first('.js-emoji-btn')
+ emoji_button.hover
+ emoji_button.click
+ end
+
+ page.within('.awards') do
+ expect(page).to have_selector('.js-emoji-btn')
+ expect(page.find('.js-emoji-btn.active .js-counter')).to have_content('1')
+ expect(page).to have_css(".js-emoji-btn.active[data-original-title='You']")
+
+ expect do
+ page.find('.js-emoji-btn.active').click
+ wait_for_requests
+ end.to change { page.all('.award-control.js-emoji-btn').size }.from(3).to(2)
+ end
+ end
+
+ it 'shows the list of award emoji categories' do
+ page.within('.awards') do
+ page.find('.js-add-award').click
+ end
+
+ page.find('.emoji-menu.is-visible')
+
+ expect(page).to have_selector('.js-emoji-menu-search')
+ expect(page.evaluate_script("document.activeElement.classList.contains('js-emoji-menu-search')")).to eq(true)
+
+ fill_in('emoji-menu-search', with: 'hand')
+
+ page.within('.emoji-menu-content') do
+ expect(page).to have_selector('[data-name="raised_hand"]')
+ end
+ end
+
+ it 'adds an award emoji by a comment' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: ':smile:')
+
+ click_button('Comment')
+ end
+
+ expect(page).to have_selector('gl-emoji[data-name="smile"]')
+ end
+end
diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb
index 368a046f741..c68e10a2563 100644
--- a/spec/features/projects/badges/coverage_spec.rb
+++ b/spec/features/projects/badges/coverage_spec.rb
@@ -50,7 +50,7 @@ feature 'test coverage badge' do
scenario 'user requests test coverage badge image' do
show_test_coverage_badge
- expect(page).to have_http_status(404)
+ expect(page).to have_gitlab_http_status(404)
end
end
diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb
index 89ae891037e..68c4a647958 100644
--- a/spec/features/projects/badges/list_spec.rb
+++ b/spec/features/projects/badges/list_spec.rb
@@ -39,7 +39,7 @@ feature 'list of badges' do
end
end
- scenario 'user changes current ref of build status badge', js: true do
+ scenario 'user changes current ref of build status badge', :js do
page.within('.pipeline-status') do
first('.js-project-refs-dropdown').click
diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
index 1160f674974..c12e56d2c3f 100644
--- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
+++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', js: true do
+feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
include TreeHelper
let(:project) { create(:project, :public, :repository) }
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index 62ac9fd0e95..965028a6f90 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Editing file blob', js: true do
+feature 'Editing file blob', :js do
include TreeHelper
let(:project) { create(:project, :public, :repository) }
@@ -20,6 +20,7 @@ feature 'Editing file blob', js: true do
def edit_and_commit
wait_for_requests
find('.js-edit-blob').click
+ find('#editor')
execute_script('ace.edit("editor").setValue("class NextFeature\nend\n")')
click_button 'Commit changes'
end
diff --git a/spec/features/projects/blobs/shortcuts_blob_spec.rb b/spec/features/projects/blobs/shortcuts_blob_spec.rb
index 1e3080fa319..9f1fef80ab5 100644
--- a/spec/features/projects/blobs/shortcuts_blob_spec.rb
+++ b/spec/features/projects/blobs/shortcuts_blob_spec.rb
@@ -6,7 +6,7 @@ feature 'Blob shortcuts' do
let(:path) { project.repository.ls_files(project.repository.root_ref)[0] }
let(:sha) { project.repository.commit.sha }
- describe 'On a file(blob)', js: true do
+ describe 'On a file(blob)', :js do
def get_absolute_url(path = "")
"http://#{page.server.host}:#{page.server.port}#{path}"
end
diff --git a/spec/features/projects/branches/download_buttons_spec.rb b/spec/features/projects/branches/download_buttons_spec.rb
index ad06cee4e81..2f407b13c2f 100644
--- a/spec/features/projects/branches/download_buttons_spec.rb
+++ b/spec/features/projects/branches/download_buttons_spec.rb
@@ -29,7 +29,7 @@ feature 'Download buttons in branches page' do
describe 'when checking branches' do
context 'with artifacts' do
before do
- visit project_branches_path(project)
+ visit project_branches_path(project, search: 'binary-encoding')
end
scenario 'shows download artifacts button' do
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index ad4527a0b74..7a77df83034 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -5,12 +5,6 @@ describe 'Branches' do
let(:project) { create(:project, :public, :repository) }
let(:repository) { project.repository }
- def set_protected_branch_name(branch_name)
- find(".js-protected-branch-select").click
- find(".dropdown-input-field").set(branch_name)
- click_on("Create wildcard #{branch_name}")
- end
-
context 'logged in as developer' do
before do
sign_in(user)
@@ -18,12 +12,10 @@ describe 'Branches' do
end
describe 'Initial branches page' do
- it 'shows all the branches' do
+ it 'shows all the branches sorted by last updated by default' do
visit project_branches_path(project)
- repository.branches_sorted_by(:name).first(20).each do |branch|
- expect(page).to have_content("#{branch.name}")
- end
+ expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_desc))
end
it 'sorts the branches by name' do
@@ -32,22 +24,7 @@ describe 'Branches' do
click_button "Last updated" # Open sorting dropdown
click_link "Name"
- sorted = repository.branches_sorted_by(:name).first(20).map do |branch|
- Regexp.escape(branch.name)
- end
- expect(page).to have_content(/#{sorted.join(".*")}/)
- end
-
- it 'sorts the branches by last updated' do
- visit project_branches_path(project)
-
- click_button "Last updated" # Open sorting dropdown
- click_link "Last updated"
-
- sorted = repository.branches_sorted_by(:updated_desc).first(20).map do |branch|
- Regexp.escape(branch.name)
- end
- expect(page).to have_content(/#{sorted.join(".*")}/)
+ expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :name))
end
it 'sorts the branches by oldest updated' do
@@ -56,10 +33,7 @@ describe 'Branches' do
click_button "Last updated" # Open sorting dropdown
click_link "Oldest updated"
- sorted = repository.branches_sorted_by(:updated_asc).first(20).map do |branch|
- Regexp.escape(branch.name)
- end
- expect(page).to have_content(/#{sorted.join(".*")}/)
+ expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_asc))
end
it 'avoids a N+1 query in branches index' do
@@ -72,7 +46,7 @@ describe 'Branches' do
end
describe 'Find branches' do
- it 'shows filtered branches', js: true do
+ it 'shows filtered branches', :js do
visit project_branches_path(project)
fill_in 'branch-search', with: 'fix'
@@ -84,7 +58,7 @@ describe 'Branches' do
end
describe 'Delete unprotected branch' do
- it 'removes branch after confirmation', js: true do
+ it 'removes branch after confirmation', :js do
visit project_branches_path(project)
fill_in 'branch-search', with: 'fix'
@@ -93,34 +67,12 @@ describe 'Branches' do
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
- find('.js-branch-fix .btn-remove').trigger(:click)
+ accept_confirm { find('.js-branch-fix .btn-remove').click }
expect(page).not_to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 0)
end
end
-
- describe 'Delete protected branch' do
- before do
- project.add_user(user, :master)
- visit project_protected_branches_path(project)
- set_protected_branch_name('fix')
- click_on "Protect"
-
- within(".protected-branches-list") { expect(page).to have_content('fix') }
- expect(ProtectedBranch.count).to eq(1)
- project.add_user(user, :developer)
- end
-
- it 'does not allow devleoper to removes protected branch', js: true do
- visit project_branches_path(project)
-
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
-
- expect(page).to have_css('.btn-remove.disabled')
- end
- end
end
context 'logged in as master' do
@@ -136,37 +88,6 @@ describe 'Branches' do
expect(page).to have_content("Protected branches can be managed in project settings")
end
end
-
- describe 'Delete protected branch' do
- before do
- visit project_protected_branches_path(project)
- set_protected_branch_name('fix')
- click_on "Protect"
-
- within(".protected-branches-list") { expect(page).to have_content('fix') }
- expect(ProtectedBranch.count).to eq(1)
- end
-
- it 'removes branch after modal confirmation', js: true do
- visit project_branches_path(project)
-
- 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)
- page.find('[data-target="#modal-delete-branch"]').trigger(:click)
-
- expect(page).to have_css('.js-delete-branch[disabled]')
- fill_in 'delete_branch_input', with: 'fix'
- click_link 'Delete protected branch'
-
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
-
- expect(page).to have_content('No branches to show')
- end
- end
end
context 'logged out' do
@@ -180,4 +101,13 @@ describe 'Branches' do
end
end
end
+
+ def sorted_branches(repository, count:, sort_by:)
+ sorted_branches =
+ repository.branches_sorted_by(sort_by).first(count).map do |branch|
+ Regexp.escape(branch.name)
+ end
+
+ Regexp.new(sorted_branches.join('.*'))
+ end
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
new file mode 100644
index 00000000000..810f2c39b43
--- /dev/null
+++ b/spec/features/projects/clusters_spec.rb
@@ -0,0 +1,111 @@
+require 'spec_helper'
+
+feature 'Clusters', :js do
+ let!(:project) { create(:project, :repository) }
+ let!(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ gitlab_sign_in(user)
+ end
+
+ context 'when user has signed in Google' do
+ before do
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:validate_token).and_return(true)
+ end
+
+ context 'when user does not have a cluster and visits cluster index page' do
+ before do
+ visit project_clusters_path(project)
+ end
+
+ it 'user sees a new page' do
+ expect(page).to have_button('Create cluster')
+ end
+
+ context 'when user filled form with valid parameters' do
+ before do
+ double.tap do |dbl|
+ allow(dbl).to receive(:status).and_return('RUNNING')
+ allow(dbl).to receive(:self_link)
+ .and_return('projects/gcp-project-12345/zones/us-central1-a/operations/ope-123')
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_zones_clusters_create).and_return(dbl)
+ end
+
+ allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+
+ fill_in 'cluster_gcp_project_id', with: 'gcp-project-123'
+ fill_in 'cluster_gcp_cluster_name', with: 'dev-cluster'
+ click_button 'Create cluster'
+ end
+
+ it 'user sees a cluster details page and creation status' do
+ expect(page).to have_content('Cluster is being created on Google Container Engine...')
+
+ Gcp::Cluster.last.make_created!
+
+ expect(page).to have_content('Cluster was successfully created on Google Container Engine')
+ end
+ end
+
+ context 'when user filled form with invalid parameters' do
+ before do
+ click_button 'Create cluster'
+ end
+
+ it 'user sees a validation error' do
+ expect(page).to have_css('#error_explanation')
+ end
+ end
+ end
+
+ context 'when user has a cluster and visits cluster index page' do
+ let!(:cluster) { create(:gcp_cluster, :created_on_gke, :with_kubernetes_service, project: project) }
+
+ before do
+ visit project_clusters_path(project)
+ end
+
+ it 'user sees an cluster details page' do
+ expect(page).to have_button('Save')
+ expect(page.find(:css, '.cluster-name').value).to eq(cluster.gcp_cluster_name)
+ end
+
+ context 'when user disables the cluster' do
+ before do
+ page.find(:css, '.js-toggle-cluster').click
+ click_button 'Save'
+ end
+
+ it 'user sees the succeccful message' do
+ expect(page).to have_content('Cluster was successfully updated.')
+ end
+ end
+
+ context 'when user destory the cluster' do
+ before do
+ page.accept_confirm do
+ click_link 'Remove integration'
+ end
+ end
+
+ it 'user sees creation form with the succeccful message' do
+ expect(page).to have_content('Cluster integration was successfully removed.')
+ expect(page).to have_button('Create cluster')
+ end
+ end
+ end
+ end
+
+ context 'when user has not signed in Google' do
+ before do
+ visit project_clusters_path(project)
+ end
+
+ it 'user sees a login page' do
+ expect(page).to have_css('.signin-with-google')
+ end
+ end
+end
diff --git a/spec/features/projects/commit/builds_spec.rb b/spec/features/projects/commit/builds_spec.rb
index 740331fe42a..79e84a4f0a6 100644
--- a/spec/features/projects/commit/builds_spec.rb
+++ b/spec/features/projects/commit/builds_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'project commit pipelines', js: true do
+feature 'project commit pipelines', :js do
given(:project) { create(:project, :repository) }
background do
@@ -20,7 +20,6 @@ feature 'project commit pipelines', js: true do
visit pipelines_project_commit_path(project, project.commit.sha)
page.within('.table-holder') do
- expect(page).to have_content project.pipelines[0].status # pipeline status
expect(page).to have_content project.pipelines[0].id # pipeline ids
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index 7086f56bb1b..c11a95732b2 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -64,7 +64,7 @@ describe 'Cherry-pick Commits' do
end
end
- context "I cherry-pick a commit from a different branch", js: true do
+ context "I cherry-pick a commit from a different branch", :js do
it do
find('.header-action-buttons a.dropdown-toggle').click
find(:css, "a[href='#modal-cherry-pick-commit']").click
diff --git a/spec/features/projects/commit/diff_notes_spec.rb b/spec/features/projects/commit/diff_notes_spec.rb
new file mode 100644
index 00000000000..4dbfc6f6edf
--- /dev/null
+++ b/spec/features/projects/commit/diff_notes_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+feature 'Commit diff', :js do
+ include RepoHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+
+ before do
+ project.add_master(user)
+ sign_in user
+ end
+
+ %w(inline parallel).each do |view|
+ context "#{view} view" do
+ before do
+ visit project_commit_path(project, sample_commit.id, view: view)
+ end
+
+ it "adds comment to diff" do
+ diff_line_num = first('.diff-line-num.new')
+
+ diff_line_num.hover
+ diff_line_num.find('.js-add-diff-note-button').click
+
+ page.within(first('.diff-viewer')) do
+ find('.js-note-text').set 'test comment'
+
+ click_button 'Comment'
+
+ expect(page).to have_content('test comment')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/commit/user_reverts_commit_spec.rb b/spec/features/projects/commit/user_reverts_commit_spec.rb
new file mode 100644
index 00000000000..221f1d7757e
--- /dev/null
+++ b/spec/features/projects/commit/user_reverts_commit_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe 'User reverts a commit', :js do
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+
+ visit(project_commit_path(project, sample_commit.id))
+
+ find('.header-action-buttons .dropdown').click
+ find('a[href="#modal-revert-commit"]').click
+ end
+
+ context 'without creating a new merge request' do
+ before do
+ page.within('#modal-revert-commit') do
+ uncheck('create_merge_request')
+ click_button('Revert')
+ end
+ end
+
+ it 'reverts a commit' do
+ expect(page).to have_content('The commit has been successfully reverted.')
+ end
+
+ it 'does not revert a previously reverted commit' do
+ # Visit the comment again once it was reverted.
+ visit project_commit_path(project, sample_commit.id)
+
+ find('.header-action-buttons .dropdown').click
+ find('a[href="#modal-revert-commit"]').click
+
+ page.within('#modal-revert-commit') do
+ uncheck('create_merge_request')
+ click_button('Revert')
+ end
+
+ expect(page).to have_content('Sorry, we cannot revert this commit automatically.')
+ end
+ end
+
+ context 'with creating a new merge request' do
+ it 'reverts a commit' do
+ page.within('#modal-revert-commit') do
+ click_button('Revert')
+ end
+
+ expect(page).to have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.')
+ expect(page).to have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master")
+ end
+ end
+end
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index 82d73fe8531..87ffc2a0b90 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -1,6 +1,6 @@
require "spec_helper"
-describe "Compare", js: true do
+describe "Compare", :js do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index 2d1a9b931b5..e445758cb5e 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -20,7 +20,7 @@ describe 'Project deploy keys', :js do
page.within(find('.deploy-keys')) do
expect(page).to have_selector('.deploy-keys li', count: 1)
- click_on 'Remove'
+ accept_confirm { find(:button, text: 'Remove').send_keys(:return) }
expect(page).not_to have_selector('.fa-spinner', count: 0)
expect(page).to have_selector('.deploy-keys li', count: 0)
diff --git a/spec/features/projects/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/developer_views_empty_project_instructions_spec.rb
index fe8567ce348..36809240f76 100644
--- a/spec/features/projects/developer_views_empty_project_instructions_spec.rb
+++ b/spec/features/projects/developer_views_empty_project_instructions_spec.rb
@@ -17,7 +17,7 @@ feature 'Developer views empty project instructions' do
expect_instructions_for('http')
end
- scenario 'switches to SSH', js: true do
+ scenario 'switches to SSH', :js do
visit_project
select_protocol('SSH')
@@ -37,7 +37,7 @@ feature 'Developer views empty project instructions' do
expect_instructions_for('ssh')
end
- scenario 'switches to HTTP', js: true do
+ scenario 'switches to HTTP', :js do
visit_project
select_protocol('HTTP')
diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb
index bc102895aaf..c1307ab640f 100644
--- a/spec/features/projects/diffs/diff_show_spec.rb
+++ b/spec/features/projects/diffs/diff_show_spec.rb
@@ -62,13 +62,43 @@ feature 'Diff file viewer', :js do
end
context 'Image file' do
- before do
- visit_commit('2f63565e7aac07bcdadb654e253078b727143ec4')
+ context 'Replaced' do
+ before do
+ visit_commit('2f63565e7aac07bcdadb654e253078b727143ec4')
+ end
+
+ it 'shows a rendered image' do
+ within('.diff-file[id="e986451b8f7397b617dbb6fffcb5539328c56921"]') do
+ expect(page).to have_css('img[alt="files/images/6049019_460s.jpg"]')
+ end
+ end
+
+ it 'shows view replaced and view file links' do
+ expect(page.all('.file-actions a').length).to eq 2
+ expect(page.all('.file-actions a')[0]).to have_content 'View replaced file @'
+ expect(page.all('.file-actions a')[1]).to have_content 'View file @'
+ end
end
- it 'shows a rendered image' do
- within('.diff-file[id="e986451b8f7397b617dbb6fffcb5539328c56921"]') do
- expect(page).to have_css('img[alt="files/images/6049019_460s.jpg"]')
+ context 'Added' do
+ before do
+ visit_commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9')
+ end
+
+ it 'shows view file link' do
+ expect(page.all('.file-actions a').length).to eq 1
+ expect(page.all('.file-actions a')[0]).to have_content 'View file @'
+ end
+ end
+
+ context 'Deleted' do
+ before do
+ visit_commit('7fd7a459706ee87be6f855fd98ce8c552b15529a')
+ end
+
+ it 'shows view file link' do
+ expect(page.all('.file-actions a').length).to eq 1
+ expect(page.all('.file-actions a')[0]).to have_content 'View file @'
end
end
end
@@ -108,6 +138,19 @@ feature 'Diff file viewer', :js do
end
end
+ context 'renamed file' do
+ before do
+ visit_commit('6907208d755b60ebeacb2e9dfea74c92c3449a1f')
+ end
+
+ it 'shows the filename with diff highlight' do
+ within('.file-header-content') do
+ expect(page).to have_css('.idiff.left.right.deletion')
+ expect(page).to have_content('files/js/commit.coffee')
+ end
+ end
+ end
+
context 'binary file that appears to be text in the first 1024 bytes' do
before do
# The file we're visiting is smaller than 10 KB and we want it collapsed
diff --git a/spec/features/projects/edit_spec.rb b/spec/features/projects/edit_spec.rb
index d3b1d1f7be3..7a372757523 100644
--- a/spec/features/projects/edit_spec.rb
+++ b/spec/features/projects/edit_spec.rb
@@ -1,20 +1,21 @@
require 'rails_helper'
-feature 'Project edit', js: true do
+feature 'Project edit', :js do
+ let(:admin) { create(:admin) }
let(:user) { create(:user) }
let(:project) { create(:project) }
- before do
- project.team << [user, :master]
- sign_in(user)
+ context 'feature visibility' do
+ before do
+ project.team << [user, :master]
+ sign_in(user)
- visit edit_project_path(project)
- end
+ visit edit_project_path(project)
+ end
- context 'feature visibility' do
context 'merge requests select' do
it 'hides merge requests section' do
- select('Disabled', from: 'project_project_feature_attributes_merge_requests_access_level')
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
expect(page).to have_selector('.merge-requests-feature', visible: false)
end
@@ -30,7 +31,7 @@ feature 'Project edit', js: true do
context 'builds select' do
it 'hides builds select section' do
- select('Disabled', from: 'project_project_feature_attributes_builds_access_level')
+ find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
expect(page).to have_selector('.builds-feature', visible: false)
end
@@ -44,4 +45,18 @@ feature 'Project edit', js: true do
end
end
end
+
+ context 'LFS enabled setting' do
+ before do
+ sign_in(admin)
+ end
+
+ it 'displays the correct elements' do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ 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
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 56addd64056..5fc3ba54f65 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -193,12 +193,14 @@ feature 'Environment' do
create(:environment, project: project,
name: 'staging-1.0/review',
state: :available)
-
- visit folder_project_environments_path(project, id: 'staging-1.0')
end
it 'renders a correct environment folder' do
- expect(page).to have_http_status(:ok)
+ reqs = inspect_requests do
+ visit folder_project_environments_path(project, id: 'staging-1.0')
+ end
+
+ expect(reqs.first.status_code).to eq(200)
expect(page).to have_content('Environments / staging-1.0')
end
end
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 1c59e57c0a4..b4eb5795470 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -10,26 +10,23 @@ feature 'Environments page', :js do
sign_in(user)
end
- given!(:environment) { }
- given!(:deployment) { }
- given!(:action) { }
-
- before do
- visit_environments(project)
- end
-
describe 'page tabs' do
- scenario 'shows "Available" and "Stopped" tab with links' do
+ it 'shows "Available" and "Stopped" tab with links' do
+ visit_environments(project)
+
expect(page).to have_link('Available')
expect(page).to have_link('Stopped')
end
describe 'with one available environment' do
- given(:environment) { create(:environment, project: project, state: :available) }
+ before do
+ create(:environment, project: project, state: :available)
+ end
describe 'in available tab page' do
it 'should show one environment' do
- visit project_environments_path(project, scope: 'available')
+ visit_environments(project, scope: 'available')
+
expect(page).to have_css('.environments-container')
expect(page.all('.environment-name').length).to eq(1)
end
@@ -37,7 +34,8 @@ feature 'Environments page', :js do
describe 'in stopped tab page' do
it 'should show no environments' do
- visit project_environments_path(project, scope: 'stopped')
+ visit_environments(project, scope: 'stopped')
+
expect(page).to have_css('.environments-container')
expect(page).to have_content('You don\'t have any environments right now')
end
@@ -45,11 +43,14 @@ feature 'Environments page', :js do
end
describe 'with one stopped environment' do
- given(:environment) { create(:environment, project: project, state: :stopped) }
+ before do
+ create(:environment, project: project, state: :stopped)
+ end
describe 'in available tab page' do
it 'should show no environments' do
- visit project_environments_path(project, scope: 'available')
+ visit_environments(project, scope: 'available')
+
expect(page).to have_css('.environments-container')
expect(page).to have_content('You don\'t have any environments right now')
end
@@ -57,7 +58,8 @@ feature 'Environments page', :js do
describe 'in stopped tab page' do
it 'should show one environment' do
- visit project_environments_path(project, scope: 'stopped')
+ visit_environments(project, scope: 'stopped')
+
expect(page).to have_css('.environments-container')
expect(page.all('.environment-name').length).to eq(1)
end
@@ -66,108 +68,106 @@ feature 'Environments page', :js do
end
context 'without environments' do
- scenario 'does show no environments' do
- expect(page).to have_content('You don\'t have any environments right now.')
+ before do
+ visit_environments(project)
end
- scenario 'does show 0 as counter for environments in both tabs' do
+ it 'does not show environments and counters are set to zero' do
+ expect(page).to have_content('You don\'t have any environments right now.')
+
expect(page.find('.js-available-environments-count').text).to eq('0')
expect(page.find('.js-stopped-environments-count').text).to eq('0')
end
end
- describe 'when showing the environment' do
- given(:environment) { create(:environment, project: project) }
-
- scenario 'does show environment name' do
- expect(page).to have_link(environment.name)
- end
-
- scenario 'does show number of available and stopped environments' do
- expect(page.find('.js-available-environments-count').text).to eq('1')
- expect(page.find('.js-stopped-environments-count').text).to eq('0')
+ describe 'environments table' do
+ given!(:environment) do
+ create(:environment, project: project, state: :available)
end
- context 'without deployments' do
- scenario 'does show no deployments' do
- expect(page).to have_content('No deployments yet')
+ context 'when there are no deployments' do
+ before do
+ visit_environments(project)
end
- context 'for available environment' do
- given(:environment) { create(:environment, project: project, state: :available) }
+ it 'shows environments names and counters' do
+ expect(page).to have_link(environment.name)
- scenario 'does not shows stop button' do
- expect(page).not_to have_selector('.stop-env-link')
- end
+ expect(page.find('.js-available-environments-count').text).to eq('1')
+ expect(page.find('.js-stopped-environments-count').text).to eq('0')
end
- context 'for stopped environment' do
- given(:environment) { create(:environment, project: project, state: :stopped) }
+ it 'does not show deployments' do
+ expect(page).to have_content('No deployments yet')
+ end
- scenario 'does not shows stop button' do
- expect(page).not_to have_selector('.stop-env-link')
- end
+ it 'does not show stip button when environment is not stoppable' do
+ expect(page).not_to have_selector('.stop-env-link')
end
end
- context 'with deployments' do
+ context 'when there are deployments' do
given(:project) { create(:project, :repository) }
- given(:deployment) do
+ given!(:deployment) do
create(:deployment, environment: environment,
sha: project.commit.id)
end
- scenario 'does show deployment SHA' do
- expect(page).to have_link(deployment.short_sha)
- end
+ it 'shows deployment SHA and internal ID' do
+ visit_environments(project)
- scenario 'does show deployment internal id' do
+ expect(page).to have_link(deployment.short_sha)
expect(page).to have_content(deployment.iid)
end
- context 'with build and manual actions' do
- given(:pipeline) { create(:ci_pipeline, project: project) }
- given(:build) { create(:ci_build, pipeline: pipeline) }
+ context 'when builds and manual actions are present' do
+ given!(:pipeline) { create(:ci_pipeline, project: project) }
+ given!(:build) { create(:ci_build, pipeline: pipeline) }
- given(:action) do
+ given!(:action) do
create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production')
end
- given(:deployment) do
+ given!(:deployment) do
create(:deployment, environment: environment,
deployable: build,
sha: project.commit.id)
end
- scenario 'does show a play button' do
+ before do
+ visit_environments(project)
+ end
+
+ it 'shows a play button' do
find('.js-dropdown-play-icon-container').click
+
expect(page).to have_content(action.name.humanize)
end
- scenario 'does allow to play manual action', js: true do
+ it 'allows to play a manual action', :js do
expect(action).to be_manual
find('.js-dropdown-play-icon-container').click
expect(page).to have_content(action.name.humanize)
- expect { find('.js-manual-action-link').trigger('click') }
+ expect { find('.js-manual-action-link').click }
.not_to change { Ci::Pipeline.count }
end
- scenario 'does show build name and id' do
+ it 'shows build name and id' do
expect(page).to have_link("#{build.name} ##{build.id}")
end
- scenario 'does not show stop button' do
+ it 'shows a stop button' do
expect(page).not_to have_selector('.stop-env-link')
end
- scenario 'does not show external link button' do
+ it 'does not show external link button' do
expect(page).not_to have_css('external-url')
end
- scenario 'does not show terminal button' do
+ it 'does not show terminal button' do
expect(page).not_to have_terminal_button
end
@@ -176,7 +176,7 @@ feature 'Environments page', :js do
given(:build) { create(:ci_build, pipeline: pipeline) }
given(:deployment) { create(:deployment, environment: environment, deployable: build) }
- scenario 'does show an external link button' do
+ it 'shows an external link button' do
expect(page).to have_link(nil, href: environment.external_url)
end
end
@@ -192,34 +192,34 @@ feature 'Environments page', :js do
on_stop: 'close_app')
end
- scenario 'does show stop button' do
+ it 'shows a stop button' do
expect(page).to have_selector('.stop-env-link')
end
- context 'for reporter' do
+ context 'when user is a reporter' do
let(:role) { :reporter }
- scenario 'does not show stop button' do
+ it 'does not show stop button' do
expect(page).not_to have_selector('.stop-env-link')
end
end
end
- context 'with terminal' do
+ context 'when kubernetes terminal is available' do
let(:project) { create(:kubernetes_project, :test_repo) }
context 'for project master' do
let(:role) { :master }
- scenario 'it shows the terminal button' do
+ it 'shows the terminal button' do
expect(page).to have_terminal_button
end
end
- context 'for developer' do
+ context 'when user is a developer' do
let(:role) { :developer }
- scenario 'does not show terminal button' do
+ it 'does not show terminal button' do
expect(page).not_to have_terminal_button
end
end
@@ -228,59 +228,77 @@ feature 'Environments page', :js do
end
end
- scenario 'does have a New environment button' do
+ it 'does have a new environment button' do
+ visit_environments(project)
+
expect(page).to have_link('New environment')
end
- describe 'when creating a new environment' do
+ describe 'creating a new environment' do
before do
visit_environments(project)
end
- context 'when logged as developer' do
- before do
- within(".top-area") do
- click_link 'New environment'
- end
- end
+ context 'user is a developer' do
+ given(:role) { :developer }
- context 'for valid name' do
- before do
- fill_in('Name', with: 'production')
- click_on 'Save'
- end
+ scenario 'developer creates a new environment with a valid name' do
+ within(".top-area") { click_link 'New environment' }
+ fill_in('Name', with: 'production')
+ click_on 'Save'
- scenario 'does create a new pipeline' do
- expect(page).to have_content('production')
- end
+ expect(page).to have_content('production')
end
- context 'for invalid name' do
- before do
- fill_in('Name', with: 'name,with,commas')
- click_on 'Save'
- end
+ scenario 'developer creates a new environmetn with invalid name' do
+ within(".top-area") { click_link 'New environment' }
+ fill_in('Name', with: 'name,with,commas')
+ click_on 'Save'
- scenario 'does show errors' do
- expect(page).to have_content('Name can contain only letters')
- end
+ expect(page).to have_content('Name can contain only letters')
end
end
- context 'when logged as reporter' do
+ context 'user is a reporter' do
given(:role) { :reporter }
- scenario 'does not have a New environment link' do
+ scenario 'reporters tries to create a new environment' do
expect(page).not_to have_link('New environment')
end
end
end
+ describe 'environments folders' do
+ before do
+ create(:environment, project: project,
+ name: 'staging/review-1',
+ state: :available)
+ create(:environment, project: project,
+ name: 'staging/review-2',
+ state: :available)
+ end
+
+ scenario 'users unfurls an environment folder' do
+ visit_environments(project)
+
+ expect(page).not_to have_content 'review-1'
+ expect(page).not_to have_content 'review-2'
+ expect(page).to have_content 'staging 2'
+
+ within('.folder-row') do
+ find('.folder-name', text: 'staging').click
+ end
+
+ expect(page).to have_content 'review-1'
+ expect(page).to have_content 'review-2'
+ end
+ end
+
def have_terminal_button
have_link(nil, href: terminal_project_environment_path(project, environment))
end
- def visit_environments(project)
- visit project_environments_path(project)
+ def visit_environments(project, **opts)
+ visit project_environments_path(project, **opts)
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 24691629063..951456763dc 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -6,7 +6,7 @@ describe 'Edit Project Settings' do
let!(:issue) { create(:issue, project: project) }
let(:non_member) { create(:user) }
- describe 'project features visibility selectors', js: true do
+ describe 'project features visibility selectors', :js do
before do
project.team << [member, :master]
sign_in(member)
@@ -19,23 +19,18 @@ describe 'Edit Project Settings' do
it 'toggles visibility' do
visit edit_project_path(project)
- select 'Disabled', from: "project_project_feature_attributes_#{tool_name}_access_level"
+ # disable by clicking toggle
+ toggle_feature_off("project[project_feature_attributes][#{tool_name}_access_level]")
page.within('.sharing-permissions') do
- click_button 'Save changes'
+ find('input[value="Save changes"]').click
end
wait_for_requests
expect(page).not_to have_selector(".shortcuts-#{shortcut_name}")
- select 'Everyone with access', from: "project_project_feature_attributes_#{tool_name}_access_level"
+ # re-enable by clicking toggle again
+ toggle_feature_on("project[project_feature_attributes][#{tool_name}_access_level]")
page.within('.sharing-permissions') do
- click_button 'Save changes'
- end
- wait_for_requests
- expect(page).to have_selector(".shortcuts-#{shortcut_name}")
-
- select 'Only team members', from: "project_project_feature_attributes_#{tool_name}_access_level"
- page.within('.sharing-permissions') do
- click_button 'Save changes'
+ find('input[value="Save changes"]').click
end
wait_for_requests
expect(page).to have_selector(".shortcuts-#{shortcut_name}")
@@ -168,7 +163,7 @@ describe 'Edit Project Settings' do
end
end
- describe 'repository visibility', js: true do
+ describe 'repository visibility', :js do
before do
project.team << [member, :master]
sign_in(member)
@@ -176,19 +171,19 @@ describe 'Edit Project Settings' do
end
it "disables repository related features" do
- select "Disabled", from: "project_project_feature_attributes_repository_access_level"
+ toggle_feature_off('project[project_feature_attributes][repository_access_level]')
page.within('.sharing-permissions') do
click_button "Save changes"
end
- expect(find(".sharing-permissions")).to have_selector("select.disabled", count: 2)
+ expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.disabled", count: 2)
end
it "shows empty features project homepage" do
- select "Disabled", from: "project_project_feature_attributes_repository_access_level"
- select "Disabled", from: "project_project_feature_attributes_issues_access_level"
- select "Disabled", from: "project_project_feature_attributes_wiki_access_level"
+ toggle_feature_off('project[project_feature_attributes][repository_access_level]')
+ toggle_feature_off('project[project_feature_attributes][issues_access_level]')
+ toggle_feature_off('project[project_feature_attributes][wiki_access_level]')
page.within('.sharing-permissions') do
click_button "Save changes"
@@ -201,9 +196,9 @@ describe 'Edit Project Settings' do
end
it "hides project activity tabs" do
- select "Disabled", from: "project_project_feature_attributes_repository_access_level"
- select "Disabled", from: "project_project_feature_attributes_issues_access_level"
- select "Disabled", from: "project_project_feature_attributes_wiki_access_level"
+ toggle_feature_off('project[project_feature_attributes][repository_access_level]')
+ toggle_feature_off('project[project_feature_attributes][issues_access_level]')
+ toggle_feature_off('project[project_feature_attributes][wiki_access_level]')
page.within('.sharing-permissions') do
click_button "Save changes"
@@ -222,7 +217,7 @@ describe 'Edit Project Settings' do
# Regression spec for https://gitlab.com/gitlab-org/gitlab-ce/issues/25272
it "hides comments activity tab only on disabled issues, merge requests and repository" do
- select "Disabled", from: "project_project_feature_attributes_issues_access_level"
+ toggle_feature_off('project[project_feature_attributes][issues_access_level]')
save_changes_and_check_activity_tab do
expect(page).to have_content("Comments")
@@ -230,7 +225,7 @@ describe 'Edit Project Settings' do
visit edit_project_path(project)
- select "Disabled", from: "project_project_feature_attributes_merge_requests_access_level"
+ toggle_feature_off('project[project_feature_attributes][merge_requests_access_level]')
save_changes_and_check_activity_tab do
expect(page).to have_content("Comments")
@@ -238,7 +233,7 @@ describe 'Edit Project Settings' do
visit edit_project_path(project)
- select "Disabled", from: "project_project_feature_attributes_repository_access_level"
+ toggle_feature_off('project[project_feature_attributes][repository_access_level]')
save_changes_and_check_activity_tab do
expect(page).not_to have_content("Comments")
@@ -275,4 +270,12 @@ describe 'Edit Project Settings' do
expect(page).not_to have_selector('.project-stats')
end
end
+
+ def toggle_feature_off(feature_name)
+ find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle.checked").click
+ end
+
+ def toggle_feature_on(feature_name)
+ find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle:not(.checked)").click
+ end
end
diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb
index f62a9edd37e..84197e45dcb 100644
--- a/spec/features/projects/files/browse_files_spec.rb
+++ b/spec/features/projects/files/browse_files_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'user browses project', js: true do
+feature 'user browses project', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
diff --git a/spec/features/projects/files/creating_a_file_spec.rb b/spec/features/projects/files/creating_a_file_spec.rb
index e13bf4b6089..e1852a6e544 100644
--- a/spec/features/projects/files/creating_a_file_spec.rb
+++ b/spec/features/projects/files/creating_a_file_spec.rb
@@ -14,7 +14,7 @@ feature 'User wants to create a file' do
file_name = find('#file_name')
file_name.set options[:file_name] || 'README.md'
- file_content = find('#file-content')
+ file_content = find('#file-content', visible: false)
file_content.set options[:file_content] || 'Some content'
click_button 'Commit changes'
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index cebb238dda1..3c3a5326538 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -16,7 +16,7 @@ feature 'User wants to add a Dockerfile file' do
expect(page).to have_css('.dockerfile-selector')
end
- scenario 'user can pick a Dockerfile file from the dropdown', js: true do
+ scenario 'user can pick a Dockerfile file from the dropdown', :js do
find('.js-dockerfile-selector').click
wait_for_requests
diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb
index c7e3f657639..3ab43b3c656 100644
--- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb
+++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb
@@ -1,24 +1,24 @@
require 'spec_helper'
-feature 'User uses soft wrap whilst editing file', js: true do
+feature 'User uses soft wrap whilst editing file', :js do
before do
user = create(:user)
project = create(:project, :repository)
project.team << [user, :master]
sign_in user
visit project_new_blob_path(project, 'master', file_name: 'test_file-name')
- editor = find('.file-editor.code')
- editor.click
- editor.send_keys 'Touch water with paw then recoil in horror chase dog then
- run away chase the pig around the house eat owner\'s food, and knock
- dish off table head butt cant eat out of my own dish. Cat is love, cat
- is life rub face on everything poop on grasses so meow. Playing with
- balls of wool flee in terror at cucumber discovered on floor run in
- circles tuxedo cats always looking dapper, but attack dog, run away
- and pretend to be victim so all of a sudden cat goes crazy, yet chase
- laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn
- hanging out of own butt jump off balcony, onto stranger\'s head yet
- chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish
+ page.within('.file-editor.code') do
+ find('.ace_text-input', visible: false).send_keys 'Touch water with paw then recoil in horror chase dog then
+ run away chase the pig around the house eat owner\'s food, and knock
+ dish off table head butt cant eat out of my own dish. Cat is love, cat
+ is life rub face on everything poop on grasses so meow. Playing with
+ balls of wool flee in terror at cucumber discovered on floor run in
+ circles tuxedo cats always looking dapper, but attack dog, run away
+ and pretend to be victim so all of a sudden cat goes crazy, yet chase
+ laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn
+ hanging out of own butt jump off balcony, onto stranger\'s head yet
+ chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish
+ end
end
let(:toggle_button) { find('.soft-wrap-toggle') }
@@ -36,6 +36,6 @@ feature 'User uses soft wrap whilst editing file', js: true do
end
def get_content_width
- find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/)
+ find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/).to_i
end
end
diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb
index 7f97fdb8cc9..618725ee781 100644
--- a/spec/features/projects/files/find_file_keyboard_spec.rb
+++ b/spec/features/projects/files/find_file_keyboard_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Find file keyboard shortcuts', js: true do
+feature 'Find file keyboard shortcuts', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index e2044c9d5aa..81d68c3d67c 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -13,7 +13,7 @@ feature 'User wants to add a .gitignore file' do
expect(page).to have_css('.gitignore-selector')
end
- scenario 'user can pick a .gitignore file from the dropdown', js: true do
+ scenario 'user can pick a .gitignore file from the dropdown', :js do
find('.js-gitignore-selector').click
wait_for_requests
within '.gitignore-selector' do
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index ab242b0b0b5..8e58fa7bd56 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -13,7 +13,7 @@ feature 'User wants to add a .gitlab-ci.yml file' do
expect(page).to have_css('.gitlab-ci-yml-selector')
end
- scenario 'user can pick a template from the dropdown', js: true do
+ scenario 'user can pick a template from the dropdown', :js do
find('.js-gitlab-ci-yml-selector').click
wait_for_requests
within '.gitlab-ci-yml-selector' do
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index 95af263bcac..6c5b1086ec1 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'project owner creates a license file', js: true do
+feature 'project owner creates a license file', :js do
let(:project_master) { create(:user) }
let(:project) { create(:project, :repository) }
background do
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 7bcab01c739..6c616bf0456 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'project owner sees a link to create a license file in empty project', js: true do
+feature 'project owner sees a link to create a license file in empty project', :js do
let(:project_master) { create(:user) }
let(:project) { create(:project) }
background do
diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb
index 48003eeaa87..f95a60e5194 100644
--- a/spec/features/projects/files/template_type_dropdown_spec.rb
+++ b/spec/features/projects/files/template_type_dropdown_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Template type dropdown selector', js: true do
+feature 'Template type dropdown selector', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 9bcd5beabb8..64fe350f3dc 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Template Undo Button', js: true do
+feature 'Template Undo Button', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
new file mode 100644
index 00000000000..e10d29e5eea
--- /dev/null
+++ b/spec/features/projects/fork_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+describe 'Project fork' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+
+ before do
+ sign_in user
+ end
+
+ it 'allows user to fork project' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'disables fork button when user has exceeded project limit' do
+ user.projects_limit = 0
+ user.save!
+
+ visit project_path(project)
+
+ expect(page).to have_css('a.disabled', text: 'Fork')
+ end
+
+ context 'master in group' do
+ before do
+ group = create(:group)
+ group.add_master(user)
+ end
+
+ it 'allows user to fork project to group or to user namespace' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+
+ click_link 'Fork'
+
+ expect(page).to have_css('.fork-thumbnail', count: 2)
+ expect(page).not_to have_css('.fork-thumbnail.disabled')
+ end
+
+ it 'allows user to fork project to group and not user when exceeded project limit' do
+ user.projects_limit = 0
+ user.save!
+
+ visit project_path(project)
+
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+
+ click_link 'Fork'
+
+ expect(page).to have_css('.fork-thumbnail', count: 2)
+ expect(page).to have_css('.fork-thumbnail.disabled')
+ end
+ end
+end
diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb
index cff3b1f5743..1c988726ae6 100644
--- a/spec/features/projects/gfm_autocomplete_load_spec.rb
+++ b/spec/features/projects/gfm_autocomplete_load_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'GFM autocomplete loading', js: true do
+describe 'GFM autocomplete loading', :js do
let(:project) { create(:project) }
before do
diff --git a/spec/features/projects/group_links_spec.rb b/spec/features/projects/group_links_spec.rb
deleted file mode 100644
index 5195d027a9f..00000000000
--- a/spec/features/projects/group_links_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-
-feature 'Project group links', :js do
- include Select2Helper
-
- let(:master) { create(:user) }
- let(:project) { create(:project) }
- let!(:group) { create(:group) }
-
- background do
- project.add_master(master)
- sign_in(master)
- end
-
- context 'setting an expiration date for a group link' do
- before do
- visit project_settings_members_path(project)
-
- click_on 'share-with-group-tab'
-
- select2 group.id, from: '#link_group_id'
- fill_in 'expires_at_groups', with: (Time.current + 4.5.days).strftime('%Y-%m-%d')
- page.find('body').click
- find('.btn-create').trigger('click')
- end
-
- it 'shows the expiration time with a warning class' do
- page.within('.project-members-groups') do
- expect(page).to have_content('Expires in 4 days')
- expect(page).to have_selector('.text-warning')
- end
- end
- end
-
- context 'nested group project' do
- let!(:nested_group) { create(:group, parent: group) }
- let!(:another_group) { create(:group) }
- let!(:project) { create(:project, namespace: nested_group) }
-
- background do
- group.add_master(master)
- another_group.add_master(master)
- end
-
- it 'does not show ancestors', :nested_groups do
- visit project_settings_members_path(project)
-
- click_on 'share-with-group-tab'
- click_link 'Search for a group'
-
- page.within '.select2-drop' do
- expect(page).to have_content(another_group.name)
- expect(page).not_to have_content(group.name)
- end
- end
- end
-
- describe 'the groups dropdown' do
- before do
- group_two = create(:group)
- group.add_owner(master)
- group_two.add_owner(master)
-
- visit project_settings_members_path(project)
- execute_script 'GroupsSelect.PER_PAGE = 1;'
- open_select2 '#link_group_id'
- end
-
- it 'should infinitely scroll' do
- expect(find('.select2-drop .select2-results')).to have_selector('.select2-result', count: 1)
-
- scroll_select2_to_bottom('.select2-drop .select2-results:visible')
-
- expect(find('.select2-drop .select2-results')).to have_selector('.select2-result', count: 2)
- end
- end
-end
diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb
index 62d244ff259..461aa39d0ad 100644
--- a/spec/features/projects/import_export/export_file_spec.rb
+++ b/spec/features/projects/import_export/export_file_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
# It looks up for any sensitive word inside the JSON, so if a sensitive word is found
# we''l have to either include it adding the model that includes it to the +safe_list+
# or make sure the attribute is blacklisted in the +import_export.yml+ configuration
-feature 'Import/Export - project export integration test', js: true do
+feature 'Import/Export - project export integration test', :js do
include Select2Helper
include ExportFileHelper
@@ -41,7 +41,7 @@ feature 'Import/Export - project export integration test', js: true do
expect(page).to have_content('Export project')
- click_link 'Export project'
+ find(:link, 'Export project').send_keys(:return)
visit edit_project_path(project)
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index ad2db1a34f4..af125e1b9d3 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Import/Export - project import integration test', js: true do
+feature 'Import/Export - project import integration test', :js do
include Select2Helper
let(:user) { create(:user) }
@@ -18,7 +18,7 @@ feature 'Import/Export - project import integration test', js: true do
context 'when selecting the namespace' do
let(:user) { create(:admin) }
- let!(:namespace) { create(:namespace, name: 'asd', owner: user) }
+ let!(:namespace) { user.namespace }
let(:project_path) { 'test-project-path' + SecureRandom.hex }
context 'prefilled the path' do
@@ -27,6 +27,7 @@ feature 'Import/Export - project import integration test', js: true do
select2(namespace.id, from: '#project_namespace_id')
fill_in :project_path, with: project_path, visible: true
+ click_import_project_tab
click_link 'GitLab export'
expect(page).to have_content('Import an exported GitLab project')
@@ -51,6 +52,7 @@ feature 'Import/Export - project import integration test', js: true do
context 'path is not prefilled' do
scenario 'user imports an exported project successfully' do
visit new_project_path
+ click_import_project_tab
click_link 'GitLab export'
fill_in :path, with: 'test-project-path', visible: true
@@ -66,13 +68,13 @@ feature 'Import/Export - project import integration test', js: true do
end
scenario 'invalid project' do
- namespace = create(:namespace, name: 'asdf', owner: user)
- project = create(:project, namespace: namespace)
+ project = create(:project, namespace: user.namespace)
visit new_project_path
- select2(namespace.id, from: '#project_namespace_id')
+ select2(user.namespace.id, from: '#project_namespace_id')
fill_in :project_path, with: project.name, visible: true
+ click_import_project_tab
click_link 'GitLab export'
attach_file('file', file)
click_on 'Import project'
@@ -82,19 +84,6 @@ feature 'Import/Export - project import integration test', js: true do
end
end
- context 'when limited to the default user namespace' do
- scenario 'passes correct namespace ID in the URL' do
- visit new_project_path
-
- fill_in :project_path, with: 'test-project-path', visible: true
-
- click_link 'GitLab export'
-
- expect(page).to have_content('GitLab project export')
- expect(URI.parse(current_url).query).to eq("namespace_id=#{user.namespace.id}&path=test-project-path")
- end
- end
-
def wiki_exists?(project)
wiki = ProjectWiki.new(project)
File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty?
@@ -103,4 +92,8 @@ feature 'Import/Export - project import integration test', js: true do
def project_hook_exists?(project)
Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository).exists?
end
+
+ def click_import_project_tab
+ find('#import-project-tab').click
+ end
end
diff --git a/spec/features/projects/import_export/namespace_export_file_spec.rb b/spec/features/projects/import_export/namespace_export_file_spec.rb
index 691b0e1e4ca..e76bc6f1220 100644
--- a/spec/features/projects/import_export/namespace_export_file_spec.rb
+++ b/spec/features/projects/import_export/namespace_export_file_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Import/Export - Namespace export file cleanup', js: true do
+feature 'Import/Export - Namespace export file cleanup', :js do
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys }
@@ -52,7 +52,7 @@ feature 'Import/Export - Namespace export file cleanup', js: true do
expect(page).to have_content('Export project')
- click_link 'Export project'
+ find(:link, 'Export project').send_keys(:return)
visit edit_project_path(project)
diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz
index e03e7b88174..9614c72cdc3 100644
--- a/spec/features/projects/import_export/test_project_export.tar.gz
+++ b/spec/features/projects/import_export/test_project_export.tar.gz
Binary files differ
diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb
index d2789d0aa52..a012db8fd27 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -1,8 +1,11 @@
require 'spec_helper'
-feature 'issuable templates', js: true do
+feature 'issuable templates', :js do
+ include ProjectForksHelper
+
let(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
+ let(:issue_form_location) { '#content-body .issuable-details .detail-page-description' }
before do
project.team << [user, :master]
@@ -28,14 +31,17 @@ feature 'issuable templates', js: true do
longtemplate_content,
message: 'added issue template',
branch_name: 'master')
- visit edit_project_issue_path project, issue
- fill_in :'issue[title]', with: 'test issue title'
+ visit project_issue_path project, issue
+ page.within('.content .issuable-actions') do
+ click_on 'Edit'
+ end
+ fill_in :'issuable-title', with: 'test issue title'
end
scenario 'user selects "bug" template' do
select_template 'bug'
wait_for_requests
- assert_template
+ assert_template(page_part: issue_form_location)
save_changes
end
@@ -43,30 +49,19 @@ feature 'issuable templates', js: true do
select_template 'bug'
wait_for_requests
select_option 'No template'
- assert_template('')
+ assert_template(expected_content: '', page_part: issue_form_location)
save_changes('')
end
scenario 'user selects "bug" template, edits description and then selects "reset template"' do
select_template 'bug'
wait_for_requests
- find_field('issue_description').send_keys(description_addition)
- assert_template(template_content + description_addition)
+ find_field('issue-description').send_keys(description_addition)
+ assert_template(expected_content: template_content + description_addition, page_part: issue_form_location)
select_option 'Reset template'
- assert_template
+ assert_template(page_part: issue_form_location)
save_changes
end
-
- it 'updates height of markdown textarea' do
- start_height = page.evaluate_script('$(".markdown-area").outerHeight()')
-
- select_template 'test'
- wait_for_requests
-
- end_height = page.evaluate_script('$(".markdown-area").outerHeight()')
-
- expect(end_height).not_to eq(start_height)
- end
end
context 'user creates an issue using templates, with a prior description' do
@@ -81,15 +76,18 @@ feature 'issuable templates', js: true do
template_content,
message: 'added issue template',
branch_name: 'master')
- visit edit_project_issue_path project, issue
- fill_in :'issue[title]', with: 'test issue title'
- fill_in :'issue[description]', with: prior_description
+ visit project_issue_path project, issue
+ page.within('.content .issuable-actions') do
+ click_on 'Edit'
+ end
+ fill_in :'issuable-title', with: 'test issue title'
+ fill_in :'issue-description', with: prior_description
end
scenario 'user selects "bug" template' do
select_template 'bug'
wait_for_requests
- assert_template("#{template_content}")
+ assert_template(page_part: issue_form_location)
save_changes
end
end
@@ -120,15 +118,13 @@ feature 'issuable templates', js: true do
context 'user creates a merge request from a forked project using templates' do
let(:template_content) { 'this is a test "feature-proposal" template' }
let(:fork_user) { create(:user) }
- let(:fork_project) { create(:project, :public, :repository) }
- let(:merge_request) { create(:merge_request, :with_diffs, source_project: fork_project, target_project: project) }
+ let(:forked_project) { fork_project(project, fork_user, repository: true) }
+ let(:merge_request) { create(:merge_request, :with_diffs, source_project: forked_project, target_project: project) }
background do
sign_out(:user)
project.team << [fork_user, :developer]
- fork_project.team << [fork_user, :master]
- create(:forked_project_link, forked_to_project: fork_project, forked_from_project: project)
sign_in(fork_user)
@@ -154,8 +150,10 @@ feature 'issuable templates', js: true do
end
end
- def assert_template(expected_content = template_content)
- expect(find('textarea')['value']).to eq(expected_content)
+ def assert_template(expected_content: template_content, page_part: '#content-body')
+ page.within(page_part) do
+ expect(find('textarea')['value']).to eq(expected_content)
+ end
end
def save_changes(expected_content = template_content)
diff --git a/spec/features/projects/issues/list_spec.rb b/spec/features/projects/issues/list_spec.rb
deleted file mode 100644
index 9fc03f49f5b..00000000000
--- a/spec/features/projects/issues/list_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'spec_helper'
-
-feature 'Issues List' do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
-
- background do
- project.team << [user, :developer]
-
- sign_in(user)
- end
-
- scenario 'user does not see create new list button' do
- create(:issue, project: project)
-
- visit project_issues_path(project)
-
- expect(page).not_to have_selector('.js-new-board-list')
- end
-end
diff --git a/spec/features/projects/issues/user_views_issues_spec.rb b/spec/features/projects/issues/user_views_issues_spec.rb
new file mode 100644
index 00000000000..d35009b8974
--- /dev/null
+++ b/spec/features/projects/issues/user_views_issues_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe 'User views issues' do
+ set(:user) { create(:user) }
+
+ shared_examples_for 'shows issues' do
+ it 'shows issues' do
+ expect(page).to have_content(project.name)
+ .and have_content(issue1.title)
+ .and have_content(issue2.title)
+ .and have_no_selector('.js-new-board-list')
+ end
+ end
+
+ context 'when project is public' do
+ set(:project) { create(:project_empty_repo, :public) }
+ set(:issue1) { create(:issue, project: project) }
+ set(:issue2) { create(:issue, project: project) }
+
+ context 'when signed in' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(project_issues_path(project))
+ end
+
+ include_examples 'shows issues'
+ end
+
+ context 'when not signed in' do
+ before do
+ visit(project_issues_path(project))
+ end
+
+ include_examples 'shows issues'
+ end
+ end
+
+ context 'when project is internal' do
+ set(:project) { create(:project_empty_repo, :internal) }
+ set(:issue1) { create(:issue, project: project) }
+ set(:issue2) { create(:issue, project: project) }
+
+ context 'when signed in' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(project_issues_path(project))
+ end
+
+ include_examples 'shows issues'
+ end
+ end
+end
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
new file mode 100644
index 00000000000..5d9208ebadd
--- /dev/null
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'User browses a job', :js do
+ let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ project.enable_ci
+ build.success
+ build.trace.set('job trace')
+
+ sign_in(user)
+
+ visit(project_job_path(project, build))
+ end
+
+ it 'erases the job log' do
+ expect(page).to have_content("Job ##{build.id}")
+ expect(page).to have_css('#build-trace')
+
+ accept_confirm { click_link('Erase') }
+
+ expect(page).to have_no_css('.artifacts')
+ expect(build).not_to have_trace
+ expect(build.artifacts_file.exists?).to be_falsy
+ expect(build.artifacts_metadata.exists?).to be_falsy
+
+ page.within('.erased') do
+ expect(page).to have_content('Job has been erased')
+ end
+
+ expect(build.project.running_or_pending_build_count).to eq(build.project.builds.running_or_pending.count(:all))
+ end
+end
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
new file mode 100644
index 00000000000..767777f3bf9
--- /dev/null
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'User browses jobs' do
+ let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ project.enable_ci
+ project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
+
+ sign_in(user)
+
+ visit(project_jobs_path(project))
+ end
+
+ it 'shows the coverage' do
+ page.within('td.coverage') do
+ expect(page).to have_content('99.9%')
+ end
+ end
+
+ it 'shows the "CI Lint" button' do
+ page.within('.nav-controls') do
+ ci_lint_tool_link = page.find_link('CI lint')
+
+ expect(ci_lint_tool_link[:href]).to end_with(ci_lint_path)
+ end
+ end
+end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 3b5c6966287..c2a0d2395a9 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -164,9 +164,9 @@ feature 'Jobs' do
end
it 'links to issues/new with the title and description filled in' do
- button_title = "Build Failed ##{job.id}"
- job_path = project_job_path(project, job)
- options = { issue: { title: button_title, description: job_path } }
+ button_title = "Job Failed ##{job.id}"
+ job_url = project_job_path(project, job)
+ options = { issue: { title: button_title, description: "Job [##{job.id}](#{job_url}) failed for #{job.sha}:\n" } }
href = new_project_issue_path(project, options)
@@ -299,14 +299,14 @@ feature 'Jobs' do
end
shared_examples 'expected variables behavior' do
- it 'shows variable key and value after click', js: true do
- expect(page).to have_css('.reveal-variables')
+ it 'shows variable key and value after click', :js do
+ expect(page).to have_css('.js-reveal-variables')
expect(page).not_to have_css('.js-build-variable')
expect(page).not_to have_css('.js-build-value')
click_button 'Reveal Variables'
- expect(page).not_to have_css('.reveal-variables')
+ expect(page).not_to have_css('.js-reveal-variables')
expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1')
expect(page).to have_selector('.js-build-value', text: 'TRIGGER_VALUE_1')
end
@@ -380,7 +380,6 @@ feature 'Jobs' do
end
it 'loads the page and shows all needed controls' do
- expect(page.status_code).to eq(200)
expect(page).to have_content 'Retry'
end
end
@@ -392,11 +391,10 @@ feature 'Jobs' do
job.run!
visit project_job_path(project, job)
find('.js-cancel-job').click()
- find('.js-retry-button').trigger('click')
+ find('.js-retry-button').click
end
it 'shows the right status and buttons', :js do
- expect(page).to have_http_status(200)
page.within('aside.right-sidebar') do
expect(page).to have_content 'Cancel'
end
@@ -443,28 +441,30 @@ feature 'Jobs' do
context 'access source' do
context 'job from project' do
before do
- Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
job.run!
- visit project_job_path(project, job)
- find('.js-raw-link-controller').click()
end
it 'sends the right headers' do
- expect(page.status_code).to eq(200)
- expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(page.response_headers['X-Sendfile']).to eq(job.trace.send(:current_path))
+ requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do
+ visit raw_project_job_path(project, job)
+ end
+
+ expect(requests.first.status_code).to eq(200)
+ expect(requests.first.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(requests.first.response_headers['X-Sendfile']).to eq(job.trace.send(:current_path))
end
end
context 'job from other project' do
before do
- Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
job2.run!
- visit raw_project_job_path(project, job2)
end
it 'sends the right headers' do
- expect(page.status_code).to eq(404)
+ requests = inspect_requests(inject_headers: { 'X-Sendfile-Type' => 'X-Sendfile' }) do
+ visit raw_project_job_path(project, job2)
+ end
+ expect(requests.first.status_code).to eq(404)
end
end
end
@@ -473,8 +473,6 @@ feature 'Jobs' do
let(:existing_file) { Tempfile.new('existing-trace-file').path }
before do
- Capybara.current_session.driver.headers = { 'X-Sendfile-Type' => 'X-Sendfile' }
-
job.run!
end
@@ -483,16 +481,14 @@ feature 'Jobs' do
allow_any_instance_of(Gitlab::Ci::Trace)
.to receive(:paths)
.and_return([existing_file])
-
- visit project_job_path(project, job)
-
- find('.js-raw-link-controller').click
end
it 'sends the right headers' do
- expect(page.status_code).to eq(200)
- expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(page.response_headers['X-Sendfile']).to eq(existing_file)
+ 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
diff --git a/spec/features/projects/labels/subscription_spec.rb b/spec/features/projects/labels/subscription_spec.rb
index 5716d151250..e8c70dec854 100644
--- a/spec/features/projects/labels/subscription_spec.rb
+++ b/spec/features/projects/labels/subscription_spec.rb
@@ -13,7 +13,7 @@ feature 'Labels subscription' do
sign_in user
end
- scenario 'users can subscribe/unsubscribe to labels', js: true do
+ scenario 'users can subscribe/unsubscribe to labels', :js do
visit project_labels_path(project)
expect(page).to have_content('bug')
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index 8f85e972027..d063f5c27b5 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -17,7 +17,7 @@ feature 'Prioritize labels' do
sign_in user
end
- scenario 'user can prioritize a group label', js: true do
+ scenario 'user can prioritize a group label', :js do
visit project_labels_path(project)
expect(page).to have_content('Star labels to start sorting by priority')
@@ -34,7 +34,7 @@ feature 'Prioritize labels' do
end
end
- scenario 'user can unprioritize a group label', js: true do
+ scenario 'user can unprioritize a group label', :js do
create(:label_priority, project: project, label: feature, priority: 1)
visit project_labels_path(project)
@@ -52,7 +52,7 @@ feature 'Prioritize labels' do
end
end
- scenario 'user can prioritize a project label', js: true do
+ scenario 'user can prioritize a project label', :js do
visit project_labels_path(project)
expect(page).to have_content('Star labels to start sorting by priority')
@@ -69,7 +69,7 @@ feature 'Prioritize labels' do
end
end
- scenario 'user can unprioritize a project label', js: true do
+ scenario 'user can unprioritize a project label', :js do
create(:label_priority, project: project, label: bug, priority: 1)
visit project_labels_path(project)
@@ -88,7 +88,7 @@ feature 'Prioritize labels' do
end
end
- scenario 'user can sort prioritized labels and persist across reloads', js: true do
+ scenario 'user can sort prioritized labels and persist across reloads', :js do
create(:label_priority, project: project, label: bug, priority: 1)
create(:label_priority, project: project, label: feature, priority: 2)
diff --git a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
index c8988aa63a7..6d729f2f85f 100644
--- a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
+++ b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Projects > Members > Group requester cannot request access to project', js: true do
+feature 'Projects > Members > Group requester cannot request access to project', :js do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:group) { create(:group, :public, :access_requestable) }
diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb
index 1c348b987d4..7f067aadec6 100644
--- a/spec/features/projects/members/group_links_spec.rb
+++ b/spec/features/projects/members/groups_with_access_list_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Projects > Members > Anonymous user sees members', js: true do
+feature 'Projects > Members > Groups with access list', :js do
let(:user) { create(:user) }
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public) }
@@ -13,7 +13,7 @@ feature 'Projects > Members > Anonymous user sees members', js: true do
visit project_settings_members_path(project)
end
- it 'updates group access level' do
+ scenario 'updates group access level' do
click_button @group_link.human_access
page.within '.dropdown-menu' do
@@ -27,10 +27,11 @@ feature 'Projects > Members > Anonymous user sees members', js: true do
expect(first('.group_member')).to have_content('Guest')
end
- it 'updates expiry date' do
+ scenario 'updates expiry date' do
tomorrow = Date.today + 3
fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F")
+ find('body').click
wait_for_requests
page.within(find('li.group_member')) do
@@ -38,17 +39,17 @@ feature 'Projects > Members > Anonymous user sees members', js: true do
end
end
- it 'deletes group link' do
+ scenario 'deletes group link' do
page.within(first('.group_member')) do
- find('.btn-remove').click
+ accept_confirm { find('.btn-remove').click }
end
wait_for_requests
expect(page).not_to have_selector('.group_member')
end
- context 'search' do
- it 'finds no results' do
+ context 'search in existing members (yes, this filters the groups list as well)' do
+ scenario 'finds no results' do
page.within '.member-search-form' do
fill_in 'search', with: 'testing 123'
find('.member-search-btn').click
@@ -57,7 +58,7 @@ feature 'Projects > Members > Anonymous user sees members', js: true do
expect(page).not_to have_selector('.group_member')
end
- it 'finds results' do
+ scenario 'finds results' do
page.within '.member-search-form' do
fill_in 'search', with: group.name
find('.member-search-btn').click
diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
index cd621b6b3ce..0f88f4cb1e8 100644
--- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
+++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Projects > Members > Master adds member with expiration date', js: true do
+feature 'Projects > Members > Master adds member with expiration date', :js do
include Select2Helper
include ActiveSupport::Testing::TimeHelpers
@@ -20,7 +20,7 @@ feature 'Projects > Members > Master adds member with expiration date', js: true
page.within '.users-project-form' do
select2(new_member.id, from: '#user_ids', multiple: true)
- fill_in 'expires_at', with: date.to_s(:medium)
+ fill_in 'expires_at', with: date.to_s(:medium) + "\n"
click_on 'Add to project'
end
@@ -37,7 +37,7 @@ feature 'Projects > Members > Master adds member with expiration date', js: true
visit project_project_members_path(project)
page.within "#project_member_#{new_member.project_members.first.id}" do
- find('.js-access-expiration-date').set date.to_s(:medium)
+ find('.js-access-expiration-date').set date.to_s(:medium) + "\n"
wait_for_requests
expect(page).to have_content('Expires in 3 days')
end
diff --git a/spec/features/projects/members/share_with_group_spec.rb b/spec/features/projects/members/share_with_group_spec.rb
new file mode 100644
index 00000000000..3198798306c
--- /dev/null
+++ b/spec/features/projects/members/share_with_group_spec.rb
@@ -0,0 +1,191 @@
+require 'spec_helper'
+
+feature 'Project > Members > Share with Group', :js do
+ include Select2Helper
+ include ActionView::Helpers::DateHelper
+
+ let(:master) { create(:user) }
+
+ describe 'Share with group lock' do
+ shared_examples 'the project can be shared with groups' do
+ scenario 'the "Share with group" tab exists' do
+ visit project_settings_members_path(project)
+ expect(page).to have_selector('#share-with-group-tab')
+ end
+ end
+
+ shared_examples 'the project cannot be shared with groups' do
+ scenario 'the "Share with group" tab does not exist' do
+ visit project_settings_members_path(project)
+ expect(page).to have_selector('#add-member-tab')
+ expect(page).not_to have_selector('#share-with-group-tab')
+ end
+ end
+
+ context 'for a project in a root group' do
+ let!(:group_to_share_with) { create(:group) }
+ let(:project) { create(:project, namespace: create(:group)) }
+
+ background do
+ project.add_master(master)
+ sign_in(master)
+ end
+
+ context 'when the group has "Share with group lock" disabled' do
+ it_behaves_like 'the project can be shared with groups'
+
+ scenario 'the project can be shared with another group' do
+ visit project_settings_members_path(project)
+
+ click_on 'share-with-group-tab'
+
+ select2 group_to_share_with.id, from: '#link_group_id'
+ page.find('body').click
+ find('.btn-create').click
+
+ page.within('.project-members-groups') do
+ expect(page).to have_content(group_to_share_with.name)
+ end
+ end
+ end
+
+ context 'when the group has "Share with group lock" enabled' do
+ before do
+ project.namespace.update_column(:share_with_group_lock, true)
+ end
+
+ it_behaves_like 'the project cannot be shared with groups'
+ end
+ end
+
+ context 'for a project in a subgroup', :nested_groups do
+ let!(:group_to_share_with) { create(:group) }
+ let(:root_group) { create(:group) }
+ let(:subgroup) { create(:group, parent: root_group) }
+ let(:project) { create(:project, namespace: subgroup) }
+
+ background do
+ project.add_master(master)
+ sign_in(master)
+ end
+
+ context 'when the root_group has "Share with group lock" disabled' do
+ context 'when the subgroup has "Share with group lock" disabled' do
+ it_behaves_like 'the project can be shared with groups'
+ end
+
+ context 'when the subgroup has "Share with group lock" enabled' do
+ before do
+ subgroup.update_column(:share_with_group_lock, true)
+ end
+
+ it_behaves_like 'the project cannot be shared with groups'
+ end
+ end
+
+ context 'when the root_group has "Share with group lock" enabled' do
+ before do
+ root_group.update_column(:share_with_group_lock, true)
+ end
+
+ context 'when the subgroup has "Share with group lock" disabled (parent overridden)' do
+ it_behaves_like 'the project can be shared with groups'
+ end
+
+ context 'when the subgroup has "Share with group lock" enabled' do
+ before do
+ subgroup.update_column(:share_with_group_lock, true)
+ end
+
+ it_behaves_like 'the project cannot be shared with groups'
+ end
+ end
+ end
+ end
+
+ describe 'setting an expiration date for a group link' do
+ let(:project) { create(:project) }
+ let!(:group) { create(:group) }
+
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ before do
+ project.add_master(master)
+ sign_in(master)
+
+ visit project_settings_members_path(project)
+
+ click_on 'share-with-group-tab'
+
+ select2 group.id, from: '#link_group_id'
+
+ fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d')
+ page.find('body').click
+ find('.btn-create').click
+ end
+
+ scenario 'the group link shows the expiration time with a warning class' do
+ page.within('.project-members-groups') do
+ # Using distance_of_time_in_words_to_now because it is not the same as
+ # subtraction, and this way avoids time zone issues as well
+ expires_in_text = distance_of_time_in_words_to_now(project.project_group_links.first.expires_at)
+ expect(page).to have_content(expires_in_text)
+ expect(page).to have_selector('.text-warning')
+ end
+ end
+ end
+
+ describe 'the groups dropdown' do
+ context 'with multiple groups to choose from' do
+ let(:project) { create(:project) }
+
+ background do
+ project.add_master(master)
+ sign_in(master)
+
+ create(:group).add_owner(master)
+ create(:group).add_owner(master)
+
+ visit project_settings_members_path(project)
+ execute_script 'GROUP_SELECT_PER_PAGE = 1;'
+ open_select2 '#link_group_id'
+ end
+
+ it 'should infinitely scroll' do
+ expect(find('.select2-drop .select2-results')).to have_selector('.select2-result', count: 1)
+
+ scroll_select2_to_bottom('.select2-drop .select2-results:visible')
+
+ expect(find('.select2-drop .select2-results')).to have_selector('.select2-result', count: 2)
+ end
+ end
+
+ context 'for a project in a nested group' do
+ let(:group) { create(:group) }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:group_to_share_with) { create(:group) }
+ let!(:project) { create(:project, namespace: nested_group) }
+
+ background do
+ project.add_master(master)
+ sign_in(master)
+ group.add_master(master)
+ group_to_share_with.add_master(master)
+ end
+
+ scenario 'the groups dropdown does not show ancestors', :nested_groups do
+ visit project_settings_members_path(project)
+
+ click_on 'share-with-group-tab'
+ click_link 'Search for a group'
+
+ page.within '.select2-drop' do
+ expect(page).to have_content(group_to_share_with.name)
+ expect(page).not_to have_content(group.name)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index 0fbe1ddb2a5..4eb36156812 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -60,7 +60,7 @@ feature 'Projects > Members > User requests access', :js do
expect(project.requesters.exists?(user_id: user)).to be_truthy
- click_link 'Withdraw Access Request'
+ accept_confirm { click_link 'Withdraw Access Request' }
expect(project.requesters.exists?(user_id: user)).to be_falsey
expect(page).to have_content 'Your access request to the project has been withdrawn.'
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
new file mode 100644
index 00000000000..c35ba2d7016
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_accepts_merge_request_spec.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+describe 'User accepts a merge request', :js do
+ let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ context 'with removing the source branch' do
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'accepts a merge request' do
+ check('Remove source branch')
+ click_button('Merge')
+
+ expect(page).to have_content('The changes were merged into')
+ expect(page).not_to have_selector('.js-remove-branch-button')
+
+ # Wait for View Resource requests to complete so they don't blow up if they are
+ # only handled after `DatabaseCleaner` has already run.
+ wait_for_requests
+ end
+ end
+
+ context 'without removing the source branch' do
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'accepts a merge request' do
+ click_button('Merge')
+
+ expect(page).to have_content('The changes were merged into')
+ expect(page).to have_selector('.js-remove-branch-button')
+
+ # Wait for View Resource requests to complete so they don't blow up if they are
+ # only handled after `DatabaseCleaner` has already run
+ wait_for_requests
+ end
+ end
+
+ context 'when a URL has an anchor' do
+ before do
+ visit(merge_request_path(merge_request, anchor: 'note_123'))
+ end
+
+ it 'accepts a merge request' do
+ check('Remove source branch')
+ click_button('Merge')
+
+ expect(page).to have_content('The changes were merged into')
+ expect(page).not_to have_selector('.js-remove-branch-button')
+
+ # Wait for View Resource requests to complete so they don't blow up if they are
+ # only handled after `DatabaseCleaner` has already run
+ wait_for_requests
+ end
+ end
+
+ context 'when modifying the merge commit message' do
+ before do
+ merge_request.mark_as_mergeable
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'accepts a merge request' do
+ click_button('Modify commit message')
+ fill_in('Commit message', with: 'wow such merge')
+
+ click_button('Merge')
+
+ page.within('.status-box') do
+ expect(page).to have_content('Merged')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_closes_merge_request_spec.rb b/spec/features/projects/merge_requests/user_closes_merge_request_spec.rb
new file mode 100644
index 00000000000..b257f447439
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_closes_merge_request_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'User closes a merge requests', :js do
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'closes a merge request' do
+ click_link('Close merge request', match: :first)
+
+ expect(page).to have_content(merge_request.title)
+ expect(page).to have_content('Closed by')
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_comments_on_commit_spec.rb b/spec/features/projects/merge_requests/user_comments_on_commit_spec.rb
new file mode 100644
index 00000000000..0a952cfc2a9
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_comments_on_commit_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'User comments on a commit', :js do
+ include MergeRequestDiffHelpers
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_commit_path(project, sample_commit.id))
+ end
+
+ include_examples 'comment on merge request file'
+end
diff --git a/spec/features/projects/merge_requests/user_comments_on_diff_spec.rb b/spec/features/projects/merge_requests/user_comments_on_diff_spec.rb
new file mode 100644
index 00000000000..e3f90a78cb5
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_comments_on_diff_spec.rb
@@ -0,0 +1,173 @@
+require 'spec_helper'
+
+describe 'User comments on a diff', :js do
+ include MergeRequestDiffHelpers
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) do
+ create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test')
+ end
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(diffs_project_merge_request_path(project, merge_request))
+ end
+
+ context 'when viewing comments' do
+ context 'when toggling inline comments' do
+ context 'in a single file' do
+ it 'hides a comment' do
+ click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+
+ page.within('.js-discussion-note-form') do
+ fill_in('note_note', with: 'Line is wrong')
+ click_button('Comment')
+ end
+
+ page.within('.files > div:nth-child(3)') do
+ expect(page).to have_content('Line is wrong')
+
+ find('.js-toggle-diff-comments').click
+
+ expect(page).not_to have_content('Line is wrong')
+ end
+ end
+ end
+
+ context 'in multiple files' do
+ it 'toggles comments' do
+ click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
+
+ page.within('.js-discussion-note-form') do
+ fill_in('note_note', with: 'Line is correct')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ expect(page).to have_content('Line is correct')
+ end
+
+ click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+
+ page.within('.js-discussion-note-form') do
+ fill_in('note_note', with: 'Line is wrong')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ # Hide the comment.
+ page.within('.files > div:nth-child(3)') do
+ find('.js-toggle-diff-comments').click
+
+ expect(page).not_to have_content('Line is wrong')
+ end
+
+ # At this moment a user should see only one comment.
+ # The other one should be hidden.
+ page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ expect(page).to have_content('Line is correct')
+ end
+
+ # Show the comment.
+ page.within('.files > div:nth-child(3)') do
+ find('.js-toggle-diff-comments').click
+ end
+
+ # Now both the comments should be shown.
+ page.within('.files > div:nth-child(3) .note-body > .note-text') do
+ expect(page).to have_content('Line is wrong')
+ end
+
+ page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ expect(page).to have_content('Line is correct')
+ end
+
+ # Check the same comments in the side-by-side view.
+ execute_script("window.scrollTo(0,0);")
+ click_link('Side-by-side')
+
+ wait_for_requests
+
+ page.within('.files > div:nth-child(3) .parallel .note-body > .note-text') do
+ expect(page).to have_content('Line is wrong')
+ end
+
+ page.within('.files > div:nth-child(2) .parallel .note-body > .note-text') do
+ expect(page).to have_content('Line is correct')
+ end
+ end
+ end
+ end
+ end
+
+ context 'when adding comments' do
+ include_examples 'comment on merge request file'
+ end
+
+ context 'when editing comments' do
+ it 'edits a comment' do
+ click_diff_line(find("[id='#{sample_commit.line_code}']"))
+
+ page.within('.js-discussion-note-form') do
+ fill_in(:note_note, with: 'Line is wrong')
+ click_button('Comment')
+ end
+
+ page.within('.diff-file:nth-of-type(5) .note') do
+ find('.js-note-edit').click
+
+ page.within('.current-note-edit-form') do
+ fill_in('note_note', with: 'Typo, please fix')
+ click_button('Save comment')
+ end
+
+ expect(page).not_to have_button('Save comment', disabled: true)
+ end
+
+ page.within('.diff-file:nth-of-type(5) .note') do
+ expect(page).to have_content('Typo, please fix').and have_no_content('Line is wrong')
+ end
+ end
+ end
+
+ context 'when deleting comments' do
+ it 'deletes a comment' do
+ click_diff_line(find("[id='#{sample_commit.line_code}']"))
+
+ page.within('.js-discussion-note-form') do
+ fill_in(:note_note, with: 'Line is wrong')
+ click_button('Comment')
+ end
+
+ page.within('.notes-tab .badge') do
+ expect(page).to have_content('1')
+ end
+
+ page.within('.diff-file:nth-of-type(5) .note') do
+ find('.more-actions').click
+ find('.more-actions .dropdown-menu li', match: :first)
+
+ accept_confirm { find('.js-note-delete').click }
+ end
+
+ page.within('.merge-request-tabs') do
+ find('.notes-tab').click
+ end
+
+ wait_for_requests
+
+ expect(page).not_to have_css('.notes .discussion')
+
+ page.within('.notes-tab .badge') do
+ expect(page).to have_content('0')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_comments_on_merge_request_spec.rb b/spec/features/projects/merge_requests/user_comments_on_merge_request_spec.rb
new file mode 100644
index 00000000000..2eb652147ce
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_comments_on_merge_request_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+describe 'User comments on a merge request', :js do
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'adds a comment' do
+ page.within('.js-main-target-form') do
+ fill_in(:note_note, with: '# Comment with a header')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ expect(page).to have_content('Comment with a header')
+ expect(page).not_to have_css('#comment-with-a-header')
+ end
+ end
+
+ it 'loads new comment' do
+ # Add new comment in background in order to check
+ # if it's going to be loaded automatically for current user.
+ create(:diff_note_on_merge_request, project: project, noteable: merge_request, author: user, note: 'Line is wrong')
+
+ # Trigger a refresh of notes.
+ execute_script("$(document).trigger('visibilitychange');")
+ wait_for_requests
+
+ page.within('.notes .discussion') do
+ expect(page).to have_content("#{user.name} #{user.to_reference} started a discussion")
+ expect(page).to have_content(sample_commit.line_code_path)
+ expect(page).to have_content('Line is wrong')
+ end
+
+ page.within('.notes-tab .badge') do
+ expect(page).to have_content('1')
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_creates_merge_request_spec.rb b/spec/features/projects/merge_requests/user_creates_merge_request_spec.rb
new file mode 100644
index 00000000000..f285c6c8783
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_creates_merge_request_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'User creates a merge request', :js do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_new_merge_request_path(project))
+ end
+
+ it 'creates a merge request' do
+ find('.js-source-branch').click
+ click_link('fix')
+
+ find('.js-target-branch').click
+ click_link('feature')
+
+ click_button('Compare branches')
+
+ fill_in('merge_request_title', with: 'Wiki Feature')
+ click_button('Submit merge request')
+
+ page.within('.merge-request') do
+ expect(page).to have_content('Wiki Feature')
+ end
+
+ wait_for_requests
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb b/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb
new file mode 100644
index 00000000000..3d19a2923b9
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'User edits a merge request', :js do
+ include Select2Helper
+
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(edit_project_merge_request_path(project, merge_request))
+ end
+
+ it 'changes the target branch' do
+ expect(page).to have_content('Target branch')
+
+ select2('merge-test', from: '#merge_request_target_branch')
+ click_button('Save changes')
+
+ expect(page).to have_content("Request to merge #{merge_request.source_branch} into merge-test")
+ expect(page).to have_content("changed target branch from #{merge_request.target_branch} to merge-test")
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_manages_subscription_spec.rb b/spec/features/projects/merge_requests/user_manages_subscription_spec.rb
new file mode 100644
index 00000000000..4ca435491cb
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_manages_subscription_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'User manages subscription', :js do
+ let(:project) { create(:project, :public, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'toggles subscription' do
+ subscribe_button = find('.js-issuable-subscribe-button')
+
+ expect(subscribe_button).to have_content('Subscribe')
+
+ click_on('Subscribe')
+
+ wait_for_requests
+
+ expect(subscribe_button).to have_content('Unsubscribe')
+
+ click_on('Unsubscribe')
+
+ wait_for_requests
+
+ expect(subscribe_button).to have_content('Subscribe')
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_reopens_merge_request_spec.rb b/spec/features/projects/merge_requests/user_reopens_merge_request_spec.rb
new file mode 100644
index 00000000000..ba3c9789da1
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_reopens_merge_request_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'User reopens a merge requests', :js do
+ let(:project) { create(:project, :public, :repository) }
+ let!(:merge_request) { create(:closed_merge_request, source_project: project, target_project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'reopens a merge request' do
+ click_link('Reopen merge request', match: :first)
+
+ page.within('.status-box') do
+ expect(page).to have_content('Open')
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_reverts_merge_request_spec.rb b/spec/features/projects/merge_requests/user_reverts_merge_request_spec.rb
new file mode 100644
index 00000000000..a41d683dbbb
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_reverts_merge_request_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+
+describe 'User reverts a merge request', :js do
+ let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+
+ click_button('Merge')
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'reverts a merge request' do
+ find("a[href='#modal-revert-commit']").click
+
+ page.within('#modal-revert-commit') do
+ uncheck('create_merge_request')
+ click_button('Revert')
+ end
+
+ expect(page).to have_content('The merge request has been successfully reverted.')
+
+ wait_for_requests
+ end
+
+ it 'does not revert a merge request that was previously reverted' do
+ find("a[href='#modal-revert-commit']").click
+
+ page.within('#modal-revert-commit') do
+ uncheck('create_merge_request')
+ click_button('Revert')
+ end
+
+ find("a[href='#modal-revert-commit']").click
+
+ page.within('#modal-revert-commit') do
+ uncheck('create_merge_request')
+ click_button('Revert')
+ end
+
+ expect(page).to have_content('Sorry, we cannot revert this merge request automatically.')
+ end
+
+ it 'reverts a merge request in a new merge request' do
+ find("a[href='#modal-revert-commit']").click
+
+ page.within('#modal-revert-commit') do
+ click_button('Revert')
+ end
+
+ expect(page).to have_content('The merge request has been successfully reverted. You can now submit a merge request to get this change into the original branch.')
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/projects/merge_requests/user_sorts_merge_requests_spec.rb
new file mode 100644
index 00000000000..d8d9f7e2a8c
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_sorts_merge_requests_spec.rb
@@ -0,0 +1,63 @@
+require 'spec_helper'
+
+describe 'User sorts merge requests' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let!(:merge_request2) do
+ create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test')
+ end
+ let(:project) { create(:project, :public, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_merge_requests_path(project))
+ end
+
+ it 'keeps the sort option' do
+ find('button.dropdown-toggle').click
+
+ page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ click_link('Last updated')
+ end
+
+ visit(merge_requests_dashboard_path(assignee_id: user.id))
+
+ expect(find('.issues-filters')).to have_content('Last updated')
+
+ visit(project_merge_requests_path(project))
+
+ expect(find('.issues-filters')).to have_content('Last updated')
+ end
+
+ context 'when merge requests have awards' do
+ before do
+ create_list(:award_emoji, 2, awardable: merge_request)
+ create(:award_emoji, :downvote, awardable: merge_request)
+
+ create(:award_emoji, awardable: merge_request2)
+ create_list(:award_emoji, 2, :downvote, awardable: merge_request2)
+ end
+
+ it 'sorts by popularity' do
+ find('button.dropdown-toggle').click
+
+ page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ click_link('Popularity')
+ end
+
+ page.within('.mr-list') do
+ page.within('li.merge-request:nth-child(1)') do
+ expect(page).to have_content(merge_request.title)
+ expect(page).to have_content('2 1')
+ end
+
+ page.within('li.merge-request:nth-child(2)') do
+ expect(page).to have_content(merge_request2.title)
+ expect(page).to have_content('1 2')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_all_merge_requests_spec.rb b/spec/features/projects/merge_requests/user_views_all_merge_requests_spec.rb
new file mode 100644
index 00000000000..6c695bd7aa9
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_all_merge_requests_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'User views all merge requests' do
+ let!(:closed_merge_request) { create(:closed_merge_request, source_project: project, target_project: project) }
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:project) { create(:project, :public) }
+
+ before do
+ visit(project_merge_requests_path(project, state: :all))
+ end
+
+ it 'shows all merge requests' do
+ expect(page).to have_content(merge_request.title).and have_content(closed_merge_request.title)
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_closed_merge_requests_spec.rb b/spec/features/projects/merge_requests/user_views_closed_merge_requests_spec.rb
new file mode 100644
index 00000000000..853809fe87a
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_closed_merge_requests_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'User views closed merge requests' do
+ let!(:closed_merge_request) { create(:closed_merge_request, source_project: project, target_project: project) }
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:project) { create(:project, :public) }
+
+ before do
+ visit(project_merge_requests_path(project, state: :closed))
+ end
+
+ it 'shows closed merge requests' do
+ expect(page).to have_content(closed_merge_request.title).and have_no_content(merge_request.title)
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_diffs_spec.rb b/spec/features/projects/merge_requests/user_views_diffs_spec.rb
new file mode 100644
index 00000000000..295eb02b625
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_diffs_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe 'User views diffs', :js do
+ let(:merge_request) do
+ create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test')
+ end
+ let(:project) { create(:project, :public, :repository) }
+
+ before do
+ visit(diffs_project_merge_request_path(project, merge_request))
+
+ wait_for_requests
+ end
+
+ shared_examples 'unfold diffs' do
+ it 'unfolds diffs' do
+ first('.js-unfold').click
+
+ expect(first('.text-file')).to have_content('.bundle')
+ end
+ end
+
+ it 'shows diffs' do
+ expect(page).to have_css('.tab-content #diffs.active')
+ expect(page).to have_css('#parallel-diff-btn', count: 1)
+ expect(page).to have_css('#inline-diff-btn', count: 1)
+ end
+
+ context 'when in the inline view' do
+ include_examples 'unfold diffs'
+ end
+
+ context 'when in the side-by-side view' do
+ before do
+ click_link('Side-by-side')
+
+ wait_for_requests
+ end
+
+ it 'shows diffs in parallel' do
+ expect(page).to have_css('.parallel')
+ end
+
+ include_examples 'unfold diffs'
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_merged_merge_requests_spec.rb b/spec/features/projects/merge_requests/user_views_merged_merge_requests_spec.rb
new file mode 100644
index 00000000000..eb012694f1e
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_merged_merge_requests_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'User views merged merge requests' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let!(:merged_merge_request) { create(:merged_merge_request, source_project: project, target_project: project) }
+ let(:project) { create(:project, :public) }
+
+ before do
+ visit(project_merge_requests_path(project, state: :merged))
+ end
+
+ it 'shows merged merge requests' do
+ expect(page).to have_content(merged_merge_request.title).and have_no_content(merge_request.title)
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_open_merge_request_spec.rb b/spec/features/projects/merge_requests/user_views_open_merge_request_spec.rb
new file mode 100644
index 00000000000..3aac93eaf7c
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_open_merge_request_spec.rb
@@ -0,0 +1,92 @@
+require 'spec_helper'
+
+describe 'User views an open merge request' do
+ let(:merge_request) do
+ create(:merge_request, source_project: project, target_project: project, description: '# Description header')
+ end
+
+ context 'when a merge request does not have repository' do
+ let(:project) { create(:project, :public, :repository) }
+
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'renders both the title and the description' do
+ node = find('.wiki h1 a#user-content-description-header')
+ expect(node[:href]).to end_with('#description-header')
+
+ # Work around a weird Capybara behavior where calling `parent` on a node
+ # returns the whole document, not the node's actual parent element
+ expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..-1])
+
+ expect(page).to have_content(merge_request.title).and have_content(merge_request.description)
+ end
+ end
+
+ context 'when a merge request has repository', :js do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when rendering description preview' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(edit_project_merge_request_path(project, merge_request))
+ end
+
+ it 'renders empty description preview' do
+ find('.gfm-form').fill_in(:merge_request_description, with: '')
+
+ page.within('.gfm-form') do
+ click_link('Preview')
+
+ expect(find('.js-md-preview')).to have_content('Nothing to preview.')
+ end
+ end
+
+ it 'renders description preview' do
+ find('.gfm-form').fill_in(:merge_request_description, with: ':+1: Nice')
+
+ page.within('.gfm-form') do
+ click_link('Preview')
+
+ expect(find('.js-md-preview')).to have_css('gl-emoji')
+ end
+
+ expect(find('.gfm-form')).to have_css('.js-md-preview').and have_link('Write')
+ expect(find('#merge_request_description', visible: false)).not_to be_visible
+ end
+ end
+
+ context 'when the branch is rebased on the target' do
+ let(:merge_request) { create(:merge_request, :rebased, source_project: project, target_project: project) }
+
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'does not show diverged commits count' do
+ page.within('.mr-source-target') do
+ expect(page).not_to have_content(/([0-9]+ commit[s]? behind)/)
+ end
+ end
+ end
+
+ context 'when the branch is diverged on the target' do
+ let(:merge_request) { create(:merge_request, :diverged, source_project: project, target_project: project) }
+
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'shows diverged commits count' do
+ page.within('.mr-source-target') do
+ expect(page).to have_content(/([0-9]+ commits behind)/)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_views_open_merge_requests_spec.rb b/spec/features/projects/merge_requests/user_views_open_merge_requests_spec.rb
new file mode 100644
index 00000000000..bf95dbb7d09
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_views_open_merge_requests_spec.rb
@@ -0,0 +1,115 @@
+require 'spec_helper'
+
+describe 'User views open merge requests' do
+ set(:user) { create(:user) }
+
+ shared_examples_for 'shows merge requests' do
+ it 'shows merge requests' do
+ expect(page).to have_content(project.name).and have_content(merge_request.source_project.name)
+ end
+ end
+
+ context 'when project is public' do
+ set(:project) { create(:project, :public, :repository) }
+
+ context 'when not signed in' do
+ context "when the target branch is the project's default branch" do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let!(:closed_merge_request) { create(:closed_merge_request, source_project: project, target_project: project) }
+
+ before do
+ visit(project_merge_requests_path(project))
+ end
+
+ include_examples 'shows merge requests'
+
+ it 'shows open merge requests' do
+ expect(page).to have_content(merge_request.title).and have_no_content(closed_merge_request.title)
+ end
+
+ it 'does not show target branch name' do
+ expect(page).to have_content(merge_request.title)
+ expect(find('.issuable-info')).not_to have_content(project.default_branch)
+ end
+ end
+
+ context "when the target branch is different from the project's default branch" do
+ let!(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ target_project: project,
+ source_branch: 'fix',
+ target_branch: 'feature_conflict')
+ end
+
+ before do
+ visit(project_merge_requests_path(project))
+ end
+
+ it 'shows target branch name' do
+ expect(page).to have_content(merge_request.target_branch)
+ end
+ end
+
+ context 'when a merge request has pipelines' do
+ let!(:build) { create :ci_build, pipeline: pipeline }
+
+ let(:merge_request) do
+ create(:merge_request_with_diffs,
+ source_project: project,
+ target_project: project,
+ source_branch: 'merge-test')
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch,
+ head_pipeline_of: merge_request)
+ end
+
+ before do
+ project.enable_ci
+
+ visit(project_merge_requests_path(project))
+ end
+
+ it 'shows pipeline status' do
+ page.within('.mr-list') do
+ expect(page).to have_link('Pipeline: pending')
+ end
+ end
+ end
+ end
+
+ context 'when signed in' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(project_merge_requests_path(project))
+ end
+
+ include_examples 'shows merge requests'
+ end
+ end
+
+ context 'when project is internal' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ set(:project) { create(:project, :internal, :repository) }
+
+ context 'when signed in' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+
+ visit(project_merge_requests_path(project))
+ end
+
+ include_examples 'shows merge requests'
+ end
+ end
+end
diff --git a/spec/features/projects/milestones/user_interacts_with_labels_spec.rb b/spec/features/projects/milestones/user_interacts_with_labels_spec.rb
new file mode 100644
index 00000000000..f6a82f80d65
--- /dev/null
+++ b/spec/features/projects/milestones/user_interacts_with_labels_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'User interacts with labels' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:milestone) { create(:milestone, project: project, title: 'v2.2', description: '# Description header') }
+ let(:issue1) { create(:issue, project: project, title: 'Bugfix1', milestone: milestone) }
+ let(:issue2) { create(:issue, project: project, title: 'Bugfix2', milestone: milestone) }
+ let(:label_bug) { create(:label, project: project, title: 'bug') }
+ let(:label_feature) { create(:label, project: project, title: 'feature') }
+ let(:label_enhancement) { create(:label, project: project, title: 'enhancement') }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ issue1.labels << [label_bug, label_feature]
+ issue2.labels << [label_bug, label_enhancement]
+
+ visit(project_milestones_path(project))
+ end
+
+ it 'shows the list of labels', :js do
+ click_link('v2.2')
+
+ page.within('.nav-sidebar') do
+ page.find(:xpath, "//a[@href='#tab-labels']").click
+ end
+
+ expect(page).to have_selector('ul.manage-labels-list')
+
+ wait_for_requests
+
+ page.within('#tab-labels') do
+ expect(page).to have_content(label_bug.title)
+ expect(page).to have_content(label_enhancement.title)
+ expect(page).to have_content(label_feature.title)
+ end
+ end
+end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index cd3dc72d3c6..6f097ad16c7 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -9,12 +9,14 @@ feature 'New project' do
sign_in(user)
end
- it 'shows "New project" page' do
+ it 'shows "New project" page', :js do
visit new_project_path
expect(page).to have_content('Project path')
expect(page).to have_content('Project name')
+ find('#import-project-tab').click
+
expect(page).to have_link('GitHub')
expect(page).to have_link('Bitbucket')
expect(page).to have_link('GitLab.com')
@@ -23,14 +25,15 @@ feature 'New project' do
expect(page).to have_link('GitLab export')
end
- context 'Visibility level selector' do
+ context 'Visibility level selector', :js do
Gitlab::VisibilityLevel.options.each do |key, level|
it "sets selector to #{key}" do
stub_application_setting(default_project_visibility: level)
visit new_project_path
-
- expect(find_field("project_visibility_level_#{level}")).to be_checked
+ page.within('#blank-project-pane') do
+ expect(find_field("project_visibility_level_#{level}")).to be_checked
+ end
end
it "saves visibility level #{level} on validation error" do
@@ -38,8 +41,9 @@ feature 'New project' do
choose(s_(key))
click_button('Create project')
-
- expect(find_field("project_visibility_level_#{level}")).to be_checked
+ page.within('#blank-project-pane') do
+ expect(find_field("project_visibility_level_#{level}")).to be_checked
+ end
end
end
end
@@ -51,9 +55,11 @@ feature 'New project' do
end
it 'selects the user namespace' do
- namespace = find('#project_namespace_id')
+ page.within('#blank-project-pane') do
+ namespace = find('#project_namespace_id')
- expect(namespace.text).to eq user.username
+ expect(namespace.text).to eq user.username
+ end
end
end
@@ -66,9 +72,11 @@ feature 'New project' do
end
it 'selects the group namespace' do
- namespace = find('#project_namespace_id option[selected]')
+ page.within('#blank-project-pane') do
+ namespace = find('#project_namespace_id option[selected]')
- expect(namespace.text).to eq group.name
+ expect(namespace.text).to eq group.name
+ end
end
end
@@ -82,9 +90,11 @@ feature 'New project' do
end
it 'selects the group namespace' do
- namespace = find('#project_namespace_id option[selected]')
+ page.within('#blank-project-pane') do
+ namespace = find('#project_namespace_id option[selected]')
- expect(namespace.text).to eq subgroup.full_path
+ expect(namespace.text).to eq subgroup.full_path
+ end
end
end
@@ -124,9 +134,10 @@ feature 'New project' do
end
end
- context 'Import project options' do
+ context 'Import project options', :js do
before do
visit new_project_path
+ find('#import-project-tab').click
end
context 'from git repository url' do
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 24b335a7068..fa2f7a1fd78 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -54,7 +54,7 @@ feature 'Pipeline Schedules', :js do
end
it 'deletes the pipeline' do
- click_link 'Delete'
+ accept_confirm { click_link 'Delete' }
expect(page).not_to have_css(".pipeline-schedule-table-row")
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index acbc5b046e6..b8fa1a54c24 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -67,13 +67,13 @@ describe 'Pipeline', :js do
it 'shows a running icon and a cancel action for the running build' do
page.within('#ci-badge-deploy') do
expect(page).to have_selector('.js-ci-status-icon-running')
- expect(page).to have_selector('.js-icon-action-cancel')
+ expect(page).to have_selector('.js-icon-cancel')
expect(page).to have_content('deploy')
end
end
it 'should be possible to cancel the running build' do
- find('#ci-badge-deploy .ci-action-icon-container').trigger('click')
+ find('#ci-badge-deploy .ci-action-icon-container').click
expect(page).not_to have_content('Cancel running')
end
@@ -86,13 +86,13 @@ describe 'Pipeline', :js do
expect(page).to have_content('build')
end
- page.within('#ci-badge-build .ci-action-icon-container') do
- expect(page).to have_selector('.js-icon-action-retry')
+ page.within('#ci-badge-build .ci-action-icon-container.js-icon-retry') do
+ expect(page).to have_selector('svg')
end
end
it 'should be possible to retry the success job' do
- find('#ci-badge-build .ci-action-icon-container').trigger('click')
+ find('#ci-badge-build .ci-action-icon-container').click
expect(page).not_to have_content('Retry job')
end
@@ -105,13 +105,13 @@ describe 'Pipeline', :js do
expect(page).to have_content('test')
end
- page.within('#ci-badge-test .ci-action-icon-container') do
- expect(page).to have_selector('.js-icon-action-retry')
+ page.within('#ci-badge-test .ci-action-icon-container.js-icon-retry') do
+ expect(page).to have_selector('svg')
end
end
it 'should be possible to retry the failed build' do
- find('#ci-badge-test .ci-action-icon-container').trigger('click')
+ find('#ci-badge-test .ci-action-icon-container').click
expect(page).not_to have_content('Retry job')
end
@@ -124,13 +124,13 @@ describe 'Pipeline', :js do
expect(page).to have_content('manual')
end
- page.within('#ci-badge-manual-build .ci-action-icon-container') do
- expect(page).to have_selector('.js-icon-action-play')
+ page.within('#ci-badge-manual-build .ci-action-icon-container.js-icon-play') do
+ expect(page).to have_selector('svg')
end
end
it 'should be possible to play the manual job' do
- find('#ci-badge-manual-build .ci-action-icon-container').trigger('click')
+ find('#ci-badge-manual-build .ci-action-icon-container').click
expect(page).not_to have_content('Play job')
end
@@ -165,7 +165,7 @@ describe 'Pipeline', :js do
context 'when retrying' do
before do
- find('.js-retry-button').trigger('click')
+ find('.js-retry-button').click
end
it { expect(page).not_to have_content('Retry') }
@@ -231,7 +231,7 @@ describe 'Pipeline', :js do
context 'when retrying' do
before do
- find('.js-retry-button').trigger('click')
+ find('.js-retry-button').click
end
it { expect(page).not_to have_content('Retry') }
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index f7b40cb1820..fc689bbb486 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -103,7 +103,7 @@ describe 'Pipelines', :js do
context 'when canceling' do
before do
- find('.js-pipelines-cancel-button').click
+ accept_confirm { find('.js-pipelines-cancel-button').click }
wait_for_requests
end
@@ -162,6 +162,16 @@ describe 'Pipelines', :js do
expect(page).to have_selector(
%Q{span[data-original-title="#{pipeline.yaml_errors}"]})
end
+
+ it 'contains badge that indicates failure reason' do
+ expect(page).to have_content 'error'
+ end
+
+ it 'contains badge with tooltip which contains failure reason' do
+ expect(pipeline.failure_reason?).to eq true
+ expect(page).to have_selector(
+ %Q{span[data-original-title="#{pipeline.present.failure_reason}"]})
+ end
end
context 'with manual actions' do
@@ -222,7 +232,7 @@ describe 'Pipelines', :js do
context 'when canceling' do
before do
- find('.js-pipelines-cancel-button').trigger('click')
+ accept_alert { find('.js-pipelines-cancel-button').click }
end
it 'indicates that pipeline was canceled' do
@@ -335,14 +345,14 @@ describe 'Pipelines', :js do
context 'when clicking a stage badge' do
it 'should open a dropdown' do
- find('.js-builds-dropdown-button').trigger('click')
+ find('.js-builds-dropdown-button').click
expect(page).to have_link build.name
end
it 'should be possible to cancel pending build' do
- find('.js-builds-dropdown-button').trigger('click')
- find('a.js-ci-action-icon').trigger('click')
+ find('.js-builds-dropdown-button').click
+ find('a.js-ci-action-icon').click
expect(page).to have_content('canceled')
expect(build.reload).to be_canceled
@@ -351,11 +361,16 @@ describe 'Pipelines', :js do
context 'dropdown jobs list' do
it 'should keep the dropdown open when the user ctr/cmd + clicks in the job name' do
- find('.js-builds-dropdown-button').trigger('click')
-
- execute_script('var e = $.Event("keydown", { keyCode: 64 }); $("body").trigger(e);')
-
- find('.mini-pipeline-graph-dropdown-item').trigger('click')
+ find('.js-builds-dropdown-button').click
+ dropdown_item = find('.mini-pipeline-graph-dropdown-item').native
+
+ %i(alt control).each do |meta_key|
+ page.driver.browser.action
+ .key_down(meta_key)
+ .click(dropdown_item)
+ .key_up(meta_key)
+ .perform
+ end
expect(page).to have_selector('.js-ci-action-icon')
end
@@ -443,7 +458,7 @@ describe 'Pipelines', :js do
visit new_project_pipeline_path(project)
end
- context 'for valid commit', js: true do
+ context 'for valid commit', :js do
before do
click_button project.default_branch
@@ -491,7 +506,7 @@ describe 'Pipelines', :js do
end
describe 'find pipelines' do
- it 'shows filtered pipelines', js: true do
+ it 'shows filtered pipelines', :js do
click_button project.default_branch
page.within '.dropdown-menu' do
@@ -515,7 +530,6 @@ describe 'Pipelines', :js do
let(:project) { create(:project, :public, :repository) }
it { expect(page).to have_content 'Build with confidence' }
- it { expect(page).to have_http_status(:success) }
end
context 'when project is private' do
diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb
index 5d77cd1ccd5..15a5cd9990b 100644
--- a/spec/features/projects/project_settings_spec.rb
+++ b/spec/features/projects/project_settings_spec.rb
@@ -10,7 +10,7 @@ describe 'Edit Project Settings' do
sign_in(user)
end
- describe 'Project settings section', js: true do
+ describe 'Project settings section', :js do
it 'shows errors for invalid project name' do
visit edit_project_path(project)
fill_in 'project_name_edit', with: 'foo&bar'
@@ -32,6 +32,32 @@ describe 'Edit Project Settings' do
end
end
+ describe 'Merge request settings section' do
+ it 'shows "Merge commit" strategy' do
+ visit edit_project_path(project)
+
+ page.within '.merge-requests-feature' do
+ expect(page).to have_content 'Merge commit'
+ end
+ end
+
+ it 'shows "Merge commit with semi-linear history " strategy' do
+ visit edit_project_path(project)
+
+ page.within '.merge-requests-feature' do
+ expect(page).to have_content 'Merge commit with semi-linear history'
+ end
+ end
+
+ it 'shows "Fast-forward merge" strategy' do
+ visit edit_project_path(project)
+
+ page.within '.merge-requests-feature' do
+ expect(page).to have_content 'Fast-forward merge'
+ end
+ end
+ end
+
describe 'Rename repository section' do
context 'with invalid characters' do
it 'shows errors for invalid project path/name' do
@@ -99,7 +125,7 @@ describe 'Edit Project Settings' do
end
end
- describe 'Transfer project section', js: true do
+ describe 'Transfer project section', :js do
let!(:project) { create(:project, :repository, namespace: user.namespace, name: 'gitlabhq') }
let!(:group) { create(:group) }
diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb
index f0a23729220..33ccbc1a29f 100644
--- a/spec/features/projects/ref_switcher_spec.rb
+++ b/spec/features/projects/ref_switcher_spec.rb
@@ -1,11 +1,12 @@
require 'rails_helper'
-feature 'Ref switcher', js: true do
+feature 'Ref switcher', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
before do
project.team << [user, :master]
+ set_cookie('new_repo', 'true')
sign_in(user)
visit project_tree_path(project, 'master')
end
@@ -40,4 +41,38 @@ feature 'Ref switcher', js: true do
expect(page).to have_title "'test'"
end
+
+ context "create branch" do
+ let(:input) { find('.js-new-branch-name') }
+
+ before do
+ click_button 'master'
+ wait_for_requests
+
+ page.within '.project-refs-form' do
+ find(".dropdown-footer-list a").click
+ end
+ end
+
+ it "shows error message for the invalid branch name" do
+ input.set 'foo bar'
+ click_button('Create')
+ wait_for_requests
+ expect(page).to have_content 'Branch name is invalid'
+ end
+
+ it "should create new branch properly" do
+ input.set 'new-branch-name'
+ click_button('Create')
+ wait_for_requests
+ expect(find('.js-project-refs-dropdown')).to have_content 'new-branch-name'
+ end
+
+ it "should create new branch by Enter key" do
+ input.set 'new-branch-name-2'
+ input.native.send_keys :enter
+ wait_for_requests
+ expect(find('.js-project-refs-dropdown')).to have_content 'new-branch-name-2'
+ end
+ end
end
diff --git a/spec/features/projects/services/slack_service_spec.rb b/spec/features/projects/services/slack_service_spec.rb
deleted file mode 100644
index c10ec5e2987..00000000000
--- a/spec/features/projects/services/slack_service_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'spec_helper'
-
-feature 'Projects > Slack service > Setup events' 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, pipeline_channel: 6, wiki_page_channel: 7)
- project.team << [user, :master]
- sign_in(user)
- end
-
- scenario 'user can filter events by channel' do
- visit edit_project_service_path(project, service)
-
- expect(page.find_field("service_push_channel").value).to have_content '1'
- expect(page.find_field("service_issue_channel").value).to have_content '2'
- 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_pipeline_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/services/user_activates_asana_spec.rb b/spec/features/projects/services/user_activates_asana_spec.rb
new file mode 100644
index 00000000000..db836d2985c
--- /dev/null
+++ b/spec/features/projects/services/user_activates_asana_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'User activates Asana' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Asana')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Api key', with: 'verySecret')
+ fill_in('Restrict to branch', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('Asana activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_assembla_spec.rb b/spec/features/projects/services/user_activates_assembla_spec.rb
new file mode 100644
index 00000000000..f099b332785
--- /dev/null
+++ b/spec/features/projects/services/user_activates_assembla_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'User activates Assembla' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Assembla')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Token', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('Assembla activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
new file mode 100644
index 00000000000..a00c2e0ad99
--- /dev/null
+++ b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe 'User activates Atlassian Bamboo CI' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Atlassian Bamboo CI')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Bamboo url', with: 'http://bamboo.example.com')
+ fill_in('Build key', with: 'KEY')
+ fill_in('Username', with: 'user')
+ fill_in('Password', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('Atlassian Bamboo CI activated.')
+
+ # Password field should not be filled in.
+ click_link('Atlassian Bamboo CI')
+
+ expect(find_field('Enter new password').value).to be_nil
+ end
+end
diff --git a/spec/features/projects/services/user_activates_emails_on_push_spec.rb b/spec/features/projects/services/user_activates_emails_on_push_spec.rb
new file mode 100644
index 00000000000..3769875b29c
--- /dev/null
+++ b/spec/features/projects/services/user_activates_emails_on_push_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'User activates Emails on push' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Emails on push')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Recipients', with: 'qa@company.name')
+ click_button('Save')
+
+ expect(page).to have_content('Emails on push activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_flowdock_spec.rb b/spec/features/projects/services/user_activates_flowdock_spec.rb
new file mode 100644
index 00000000000..5298d8acaf5
--- /dev/null
+++ b/spec/features/projects/services/user_activates_flowdock_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'User activates Flowdock' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Flowdock')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Token', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('Flowdock activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb
new file mode 100644
index 00000000000..a9bf16642c7
--- /dev/null
+++ b/spec/features/projects/services/user_activates_hipchat_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'User activates HipChat' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('HipChat')
+ end
+
+ context 'with standart settings' do
+ it 'activates service' do
+ check('Active')
+ fill_in('Room', with: 'gitlab')
+ fill_in('Token', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('HipChat activated.')
+ end
+ end
+
+ context 'with custom settings' do
+ it 'activates service' do
+ check('Active')
+ fill_in('Room', with: 'gitlab_custom')
+ fill_in('Token', with: 'secretCustom')
+ fill_in('Server', with: 'https://chat.example.com')
+ click_button('Save')
+
+ expect(page).to have_content('HipChat activated.')
+ end
+ end
+end
diff --git a/spec/features/projects/services/user_activates_irker_spec.rb b/spec/features/projects/services/user_activates_irker_spec.rb
new file mode 100644
index 00000000000..435663c818f
--- /dev/null
+++ b/spec/features/projects/services/user_activates_irker_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'User activates Irker (IRC gateway)' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Irker (IRC gateway)')
+ end
+
+ it 'activates service' do
+ check('Active')
+ check('Colorize messages')
+ fill_in('Recipients', with: 'irc://chat.freenode.net/#commits')
+ click_button('Save')
+
+ expect(page).to have_content('Irker (IRC gateway) activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
new file mode 100644
index 00000000000..1048803fde8
--- /dev/null
+++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'User activates JetBrains TeamCity CI' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('JetBrains TeamCity CI')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Teamcity url', with: 'http://teamcity.example.com')
+ fill_in('Build type', with: 'GitlabTest_Build')
+ fill_in('Username', with: 'user')
+ fill_in('Password', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('JetBrains TeamCity CI activated.')
+ end
+end
diff --git a/spec/features/projects/services/jira_service_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb
index 65e3a487d4b..ac78b1dfb1c 100644
--- a/spec/features/projects/services/jira_service_spec.rb
+++ b/spec/features/projects/services/user_activates_jira_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Setup Jira service', :js do
+describe 'User activates Jira', :js do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:service) { project.create_jira_service }
@@ -65,7 +65,7 @@ feature 'Setup Jira service', :js do
expect(find('.flash-container-page')).to have_content 'Test failed. message'
expect(find('.flash-container-page')).to have_content 'Save anyway'
- find('.flash-alert .flash-action').trigger('click')
+ find('.flash-alert .flash-action').click
wait_for_requests
expect(page).to have_content('JIRA activated.')
diff --git a/spec/features/projects/services/mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index 95d5e8b14b9..6f057137867 100644
--- a/spec/features/projects/services/mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -76,7 +76,7 @@ feature 'Setup Mattermost slash commands', :js do
select_element = find('#mattermost_team_id')
selected_option = select_element.find('option[selected]')
- expect(select_element['disabled']).to be(true)
+ expect(select_element['disabled']).to eq("true")
expect(selected_option).to have_content(team_name.to_s)
end
@@ -104,7 +104,7 @@ feature 'Setup Mattermost slash commands', :js do
select_element = find('#mattermost_team_id')
- expect(select_element['disabled']).to be(false)
+ expect(select_element['disabled']).to be_falsey
expect(select_element.all('option').count).to eq(3)
end
@@ -122,7 +122,7 @@ feature 'Setup Mattermost slash commands', :js do
click_link 'Add to Mattermost'
- expect(find('input[type="submit"]')['disabled']).not_to be(true)
+ expect(find('input[type="submit"]')['disabled']).not_to eq("true")
end
it 'disables the submit button if the required fields are not provided', :js do
@@ -132,7 +132,7 @@ feature 'Setup Mattermost slash commands', :js do
fill_in('mattermost_trigger', with: '')
- expect(find('input[type="submit"]')['disabled']).to be(true)
+ expect(find('input[type="submit"]')['disabled']).to eq("true")
end
def stub_teams(count: 0)
diff --git a/spec/features/projects/services/user_activates_packagist_spec.rb b/spec/features/projects/services/user_activates_packagist_spec.rb
new file mode 100644
index 00000000000..b0cc818f093
--- /dev/null
+++ b/spec/features/projects/services/user_activates_packagist_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'User activates Packagist' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Packagist')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Username', with: 'theUser')
+ fill_in('Token', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('Packagist activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
new file mode 100644
index 00000000000..d5d109ba48b
--- /dev/null
+++ b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'User activates PivotalTracker' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('PivotalTracker')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Token', with: 'verySecret')
+ click_button('Save')
+
+ expect(page).to have_content('PivotalTracker activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/services/user_activates_pushover_spec.rb
new file mode 100644
index 00000000000..9b7e8d62792
--- /dev/null
+++ b/spec/features/projects/services/user_activates_pushover_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe 'User activates Pushover' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+
+ click_link('Pushover')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Api key', with: 'verySecret')
+ fill_in('User key', with: 'verySecret')
+ fill_in('Device', with: 'myDevice')
+ select('High Priority', from: 'Priority')
+ select('Bike', from: 'Sound')
+ click_button('Save')
+
+ expect(page).to have_content('Pushover activated.')
+ end
+end
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
new file mode 100644
index 00000000000..fae9ebd1bd6
--- /dev/null
+++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe 'User activates Slack notifications' do
+ let(:user) { create(:user) }
+ let(:service) { SlackService.new }
+ let(:project) { create(:project, slack_service: service) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'when service is not configured yet' do
+ before do
+ visit(project_settings_integrations_path(project))
+
+ click_link('Slack notifications')
+ end
+
+ it 'activates service' do
+ check('Active')
+ fill_in('Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685')
+ click_button('Save')
+
+ expect(page).to have_content('Slack notifications activated.')
+ end
+ end
+
+ context 'when service is already configured' do
+ before do
+ service.fields
+ service.update_attributes(
+ push_channel: 1,
+ issue_channel: 2,
+ merge_request_channel: 3,
+ note_channel: 4,
+ tag_push_channel: 5,
+ pipeline_channel: 6,
+ wiki_page_channel: 7)
+
+ visit(edit_project_service_path(project, service))
+ end
+
+ it 'filters events by channel' do
+ 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_pipeline_channel').value).to have_content('6')
+ expect(page.find_field('service_wiki_page_channel').value).to have_content('7')
+ end
+ end
+end
diff --git a/spec/features/projects/services/slack_slash_command_spec.rb b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
index a8baf126269..a8baf126269 100644
--- a/spec/features/projects/services/slack_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/services/user_views_services_spec.rb
new file mode 100644
index 00000000000..5c5e8b66642
--- /dev/null
+++ b/spec/features/projects/services/user_views_services_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'User views services' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_settings_integrations_path(project))
+ end
+
+ it 'shows the list of available services' do
+ expect(page).to have_content('Project services')
+ expect(page).to have_content('Campfire')
+ expect(page).to have_content('HipChat')
+ expect(page).to have_content('Assembla')
+ expect(page).to have_content('Pushover')
+ expect(page).to have_content('Atlassian Bamboo')
+ expect(page).to have_content('JetBrains TeamCity')
+ expect(page).to have_content('Asana')
+ expect(page).to have_content('Irker (IRC gateway)')
+ expect(page).to have_content('Packagist')
+ end
+end
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
new file mode 100644
index 00000000000..28954a4fb40
--- /dev/null
+++ b/spec/features/projects/settings/forked_project_settings_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+feature 'Settings for a forked project', :js do
+ include ProjectForksHelper
+ let(:user) { create(:user) }
+ let(:original_project) { create(:project) }
+ let(:forked_project) { fork_project(original_project, user) }
+
+ before do
+ original_project.add_master(user)
+ forked_project.add_master(user)
+ sign_in(user)
+ end
+
+ shared_examples 'project settings for a forked projects' do
+ it 'allows deleting the link to the forked project' do
+ visit edit_project_path(forked_project)
+
+ click_button 'Remove fork relationship'
+
+ wait_for_requests
+
+ fill_in('confirm_name_input', with: forked_project.name)
+ click_button('Confirm')
+
+ expect(page).to have_content('The fork relationship has been removed.')
+ expect(forked_project.reload.forked?).to be_falsy
+ end
+ end
+
+ it_behaves_like 'project settings for a forked projects'
+
+ context 'when the original project is deleted' do
+ before do
+ original_project.destroy!
+ end
+
+ it_behaves_like 'project settings for a forked projects'
+ end
+end
diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb
index d932c4e4d9a..cbdb7973ac8 100644
--- a/spec/features/projects/settings/integration_settings_spec.rb
+++ b/spec/features/projects/settings/integration_settings_spec.rb
@@ -76,7 +76,7 @@ feature 'Integration settings' do
expect(page).to have_content(url)
end
- scenario 'test existing webhook', js: true do
+ scenario 'test existing webhook', :js do
WebMock.stub_request(:post, hook.url)
visit integrations_path
diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb
index 104ce08d9f3..ac76c30cc7c 100644
--- a/spec/features/projects/settings/merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/merge_requests_settings_spec.rb
@@ -19,9 +19,9 @@ feature 'Project settings > Merge Requests', :js do
expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
- select 'Disabled', from: "project_project_feature_attributes_merge_requests_access_level"
within('.sharing-permissions-form') do
- click_on('Save changes')
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
+ find('input[value="Save changes"]').send_keys(:return)
end
expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
@@ -39,9 +39,9 @@ feature 'Project settings > Merge Requests', :js do
expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
- select 'Everyone with access', from: "project_project_feature_attributes_builds_access_level"
within('.sharing-permissions-form') do
- click_on('Save changes')
+ find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
+ find('input[value="Save changes"]').send_keys(:return)
end
expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
@@ -60,9 +60,9 @@ feature 'Project settings > Merge Requests', :js do
expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved')
- select 'Everyone with access', from: "project_project_feature_attributes_merge_requests_access_level"
within('.sharing-permissions-form') do
- click_on('Save changes')
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
+ find('input[value="Save changes"]').send_keys(:return)
end
expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index 232d796a200..ea8f997409d 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -22,7 +22,7 @@ feature "Pipelines settings" do
context 'for master' do
given(:role) { :master }
- scenario 'be allowed to change', js: true do
+ scenario 'be allowed to change' do
fill_in('Test coverage parsing', with: 'coverage_regex')
click_on 'Save changes'
@@ -41,5 +41,15 @@ feature "Pipelines settings" do
checkbox = find_field('project_auto_cancel_pending_pipelines')
expect(checkbox).to be_checked
end
+
+ scenario 'update auto devops settings' do
+ fill_in('project_auto_devops_attributes_domain', with: 'test.com')
+ page.choose('project_auto_devops_attributes_enabled_false')
+ click_on 'Save changes'
+
+ expect(page.status_code).to eq(200)
+ expect(project.auto_devops).to be_present
+ expect(project.auto_devops).not_to be_enabled
+ end
end
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 15180d4b498..e2a5619c22b 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -23,7 +23,7 @@ feature 'Repository settings' do
context 'for master' do
given(:role) { :master }
- context 'Deploy Keys', js: true do
+ context 'Deploy Keys', :js do
let(:private_deploy_key) { create(:deploy_key, title: 'private_deploy_key', public: false) }
let(:public_deploy_key) { create(:another_deploy_key, title: 'public_deploy_key', public: true) }
let(:new_ssh_key) { attributes_for(:key)[:key] }
@@ -34,7 +34,6 @@ feature 'Repository settings' do
visit project_settings_repository_path(project)
- expect(page.status_code).to eq(200)
expect(page).to have_content('private_deploy_key')
expect(page).to have_content('public_deploy_key')
end
@@ -86,7 +85,7 @@ feature 'Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- find('li', text: private_deploy_key.title).click_button('Remove')
+ accept_confirm { find('li', text: private_deploy_key.title).click_button('Remove') }
expect(page).not_to have_content(private_deploy_key.title)
end
diff --git a/spec/features/projects/settings/user_manages_group_links_spec.rb b/spec/features/projects/settings/user_manages_group_links_spec.rb
new file mode 100644
index 00000000000..91e8059865c
--- /dev/null
+++ b/spec/features/projects/settings/user_manages_group_links_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe 'User manages group links' do
+ include Select2Helper
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:group_ops) { create(:group, name: 'Ops') }
+ let(:group_market) { create(:group, name: 'Market', path: 'market') }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ share_link = project.project_group_links.new(group_access: Gitlab::Access::MASTER)
+ share_link.group_id = group_ops.id
+ share_link.save!
+
+ visit(project_group_links_path(project))
+ end
+
+ it 'shows a list of groups' do
+ page.within('.project-members-groups') do
+ expect(page).to have_content('Ops')
+ expect(page).not_to have_content('Market')
+ end
+ end
+
+ it 'shares a project with a group', :js do
+ click_link('Share with group')
+
+ select2(group_market.id, from: '#link_group_id')
+ select('Master', from: 'link_group_access')
+
+ click_button('Share')
+
+ page.within('.project-members-groups') do
+ expect(page).to have_content('Market')
+ end
+ end
+end
diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb
new file mode 100644
index 00000000000..2709047b8de
--- /dev/null
+++ b/spec/features/projects/settings/user_manages_project_members_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe 'User manages project members' do
+ let(:group) { create(:group, name: 'OpenSource') }
+ let(:project) { create(:project) }
+ let(:project2) { create(:project) }
+ let(:user) { create(:user) }
+ let(:user_dmitriy) { create(:user, name: 'Dmitriy') }
+ let(:user_mike) { create(:user, name: 'Mike') }
+
+ before do
+ project.add_master(user)
+ project.add_developer(user_dmitriy)
+ sign_in(user)
+ end
+
+ it 'cancels a team member' do
+ visit(project_project_members_path(project))
+
+ project_member = project.project_members.find_by(user_id: user_dmitriy.id)
+
+ page.within("#project_member_#{project_member.id}") do
+ click_link('Remove user from project')
+ end
+
+ visit(project_project_members_path(project))
+
+ expect(page).not_to have_content(user_dmitriy.name)
+ expect(page).not_to have_content(user_dmitriy.username)
+ end
+
+ it 'imports a team from another project' do
+ project2.add_master(user)
+ project2.add_reporter(user_mike)
+
+ visit(project_project_members_path(project))
+
+ page.within('.users-project-form') do
+ click_link('Import')
+ end
+
+ select(project2.name_with_namespace, from: 'source_project_id')
+ click_button('Import')
+
+ project_member = project.project_members.find_by(user_id: user_mike.id)
+
+ page.within("#project_member_#{project_member.id}") do
+ expect(page).to have_content('Mike')
+ expect(page).to have_content('Reporter')
+ end
+ end
+
+ it 'shows all members of project shared group' do
+ group.add_owner(user)
+ group.add_developer(user_dmitriy)
+
+ share_link = project.project_group_links.new(group_access: Gitlab::Access::MASTER)
+ share_link.group_id = group.id
+ share_link.save!
+
+ visit(project_project_members_path(project))
+
+ page.within('.project-members-groups') do
+ expect(page).to have_content('OpenSource')
+ expect(first('.group_member')).to have_content('Master')
+ end
+ end
+end
diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb
index 1756c7d00fe..1c3b84d0114 100644
--- a/spec/features/projects/settings/visibility_settings_spec.rb
+++ b/spec/features/projects/settings/visibility_settings_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Visibility settings', js: true do
+feature 'Visibility settings', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace, visibility_level: 20) }
@@ -11,19 +11,19 @@ feature 'Visibility settings', js: true do
end
scenario 'project visibility select is available' do
- visibility_select_container = find('.js-visibility-select')
+ visibility_select_container = find('.project-visibility-setting')
- expect(visibility_select_container.find('.visibility-select').value).to eq project.visibility_level.to_s
- expect(visibility_select_container).to have_content 'The project can be accessed without any authentication.'
+ expect(visibility_select_container.find('select').value).to eq project.visibility_level.to_s
+ expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
end
scenario 'project visibility description updates on change' do
- visibility_select_container = find('.js-visibility-select')
- visibility_select = visibility_select_container.find('.visibility-select')
+ visibility_select_container = find('.project-visibility-setting')
+ visibility_select = visibility_select_container.find('select')
visibility_select.select('Private')
expect(visibility_select.value).to eq '0'
- expect(visibility_select_container).to have_content 'Project access must be granted explicitly to each user.'
+ expect(visibility_select_container).to have_content 'Access must be granted explicitly to each user.'
end
end
@@ -37,11 +37,10 @@ feature 'Visibility settings', js: true do
end
scenario 'project visibility is locked' do
- visibility_select_container = find('.js-visibility-select')
+ visibility_select_container = find('.project-visibility-setting')
- expect(visibility_select_container).not_to have_select '.visibility-select'
- expect(visibility_select_container).to have_content 'Public'
- expect(visibility_select_container).to have_content 'The project can be accessed without any authentication.'
+ expect(visibility_select_container).to have_selector 'select[name="project[visibility_level]"]:disabled'
+ expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
end
end
end
diff --git a/spec/features/projects/shortcuts_spec.rb b/spec/features/projects/shortcuts_spec.rb
deleted file mode 100644
index bf18c444c3d..00000000000
--- a/spec/features/projects/shortcuts_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-feature 'Project shortcuts' do
- let(:project) { create(:project, name: 'Victorialand') }
- let(:user) { create(:user) }
-
- describe 'On a project', js: true do
- before do
- project.team << [user, :master]
- sign_in user
- visit project_path(project)
- end
-
- describe 'pressing "i"' do
- it 'redirects to new issue page' do
- find('body').native.send_key('i')
- expect(page).to have_content('Victorialand')
- end
- end
- end
-end
diff --git a/spec/features/projects/show_project_spec.rb b/spec/features/projects/show_project_spec.rb
index 1bc6fae9e7f..0b94c9eae5d 100644
--- a/spec/features/projects/show_project_spec.rb
+++ b/spec/features/projects/show_project_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Project show page', feature: true do
+describe 'Project show page', :feature do
context 'when project pending delete' do
let(:project) { create(:project, :empty_repo, pending_delete: true) }
diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb
index 3e79dba3f19..e4215291f99 100644
--- a/spec/features/projects/snippets/create_snippet_spec.rb
+++ b/spec/features/projects/snippets/create_snippet_spec.rb
@@ -10,7 +10,7 @@ feature 'Create Snippet', :js do
fill_in 'project_snippet_title', with: 'My Snippet Title'
fill_in 'project_snippet_description', with: 'My Snippet **Description**'
page.within('.file-editor') do
- find('.ace_editor').native.send_keys('Hello World!')
+ find('.ace_text-input', visible: false).send_keys('Hello World!')
end
end
@@ -59,7 +59,7 @@ feature 'Create Snippet', :js do
fill_form
dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- click_button('Create snippet')
+ find("input[value='Create snippet']").send_keys(:return)
wait_for_requests
expect(page).to have_content('My Snippet Title')
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
new file mode 100644
index 00000000000..1bd2098af6d
--- /dev/null
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'User comments on a snippet', :js do
+ let(:project) { create(:project) }
+ let!(:snippet) { create(:project_snippet, project: project, author: user) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_snippet_path(project, snippet))
+ end
+
+ it 'leaves a comment on a snippet' do
+ page.within('.js-main-target-form') do
+ fill_in('note_note', with: 'Good snippet!')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ expect(page).to have_content('Good snippet!')
+ end
+end
diff --git a/spec/features/projects/snippets/user_deletes_snippet_spec.rb b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
new file mode 100644
index 00000000000..ca5f7981c33
--- /dev/null
+++ b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'User deletes a snippet' do
+ let(:project) { create(:project) }
+ let!(:snippet) { create(:project_snippet, project: project, author: user) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_snippet_path(project, snippet))
+ end
+
+ it 'deletes a snippet' do
+ first(:link, 'Delete').click
+
+ expect(page).not_to have_content(snippet.title)
+ end
+end
diff --git a/spec/features/projects/snippets/user_updates_snippet_spec.rb b/spec/features/projects/snippets/user_updates_snippet_spec.rb
new file mode 100644
index 00000000000..09a390443cf
--- /dev/null
+++ b/spec/features/projects/snippets/user_updates_snippet_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'User updates a snippet' do
+ let(:project) { create(:project) }
+ let!(:snippet) { create(:project_snippet, project: project, author: user) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_snippet_path(project, snippet))
+ end
+
+ it 'updates a snippet' do
+ page.within('.detail-page-header') do
+ first(:link, 'Edit').click
+ end
+
+ fill_in('project_snippet_title', with: 'Snippet new title')
+ click_button('Save')
+
+ expect(page).to have_content('Snippet new title')
+ end
+end
diff --git a/spec/features/projects/snippets/user_views_snippets_spec.rb b/spec/features/projects/snippets/user_views_snippets_spec.rb
new file mode 100644
index 00000000000..e9992e00ca8
--- /dev/null
+++ b/spec/features/projects/snippets/user_views_snippets_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'User views snippets' do
+ let(:project) { create(:project) }
+ let!(:project_snippet) { create(:project_snippet, project: project, author: user) }
+ let!(:snippet) { create(:snippet, author: user) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_snippets_path(project))
+ end
+
+ it 'shows snippets' do
+ expect(page).to have_content(project_snippet.title)
+ expect(page).not_to have_content(snippet.title)
+ end
+end
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
new file mode 100644
index 00000000000..8ee7b9cf015
--- /dev/null
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+feature 'Multi-file editor new directory', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ set_cookie('new_repo', 'true')
+
+ visit project_tree_path(project, :master)
+
+ wait_for_requests
+ end
+
+ it 'creates directory in current directory' do
+ find('.add-to-tree').click
+
+ click_link('New directory')
+
+ page.within('.popup-dialog') do
+ find('.form-control').set('foldername')
+
+ click_button('Create directory')
+ end
+
+ fill_in('commit-message', with: 'commit message')
+
+ click_button('Commit 1 file')
+
+ expect(page).to have_selector('td', text: 'commit message')
+
+ click_link('foldername')
+
+ expect(page).to have_selector('td', text: 'commit message', count: 2)
+ expect(page).to have_selector('td', text: '.gitkeep')
+ end
+end
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
new file mode 100644
index 00000000000..1e2de0711b8
--- /dev/null
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+feature 'Multi-file editor new file', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ set_cookie('new_repo', 'true')
+
+ visit project_tree_path(project, :master)
+
+ wait_for_requests
+ end
+
+ it 'creates file in current directory' do
+ find('.add-to-tree').click
+
+ click_link('New file')
+
+ page.within('.popup-dialog') do
+ find('.form-control').set('filename')
+
+ click_button('Create file')
+ end
+
+ fill_in('commit-message', with: 'commit message')
+
+ click_button('Commit 1 file')
+
+ expect(page).to have_selector('td', text: 'commit message')
+ end
+end
diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb
new file mode 100644
index 00000000000..8439bb5a69e
--- /dev/null
+++ b/spec/features/projects/tree/upload_file_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+feature 'Multi-file editor upload file', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:txt_file) { File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt') }
+ let(:img_file) { File.join(Rails.root, 'spec', 'fixtures', 'dk.png') }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ set_cookie('new_repo', 'true')
+
+ visit project_tree_path(project, :master)
+
+ wait_for_requests
+ end
+
+ it 'uploads text file' do
+ find('.add-to-tree').click
+
+ # make the field visible so capybara can use it
+ execute_script('document.querySelector("#file-upload").classList.remove("hidden")')
+ attach_file('file-upload', txt_file)
+
+ find('.add-to-tree').click
+
+ expect(page).to have_selector('.repo-tab', text: 'doc_sample.txt')
+ expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
+ end
+
+ it 'uploads image file' do
+ find('.add-to-tree').click
+
+ # make the field visible so capybara can use it
+ execute_script('document.querySelector("#file-upload").classList.remove("hidden")')
+ attach_file('file-upload', img_file)
+
+ find('.add-to-tree').click
+
+ expect(page).to have_selector('.repo-tab', text: 'dk.png')
+ expect(page).not_to have_selector('.monaco-editor')
+ expect(page).to have_content('The source could not be displayed for this temporary file.')
+ end
+end
diff --git a/spec/features/projects/user_archives_project_spec.rb b/spec/features/projects/user_archives_project_spec.rb
new file mode 100644
index 00000000000..72063d13c2a
--- /dev/null
+++ b/spec/features/projects/user_archives_project_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'User archives a project' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+
+ sign_in(user)
+ end
+
+ context 'when a project is archived' do
+ let(:project) { create(:project, :archived, namespace: user.namespace) }
+
+ before do
+ visit(edit_project_path(project))
+ end
+
+ it 'unarchives a project' do
+ expect(page).to have_content('Unarchive project')
+
+ click_link('Unarchive')
+
+ expect(page).not_to have_content('Archived project')
+ end
+ end
+
+ context 'when a project is unarchived' do
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+
+ before do
+ visit(edit_project_path(project))
+ end
+
+ it 'archives a project' do
+ expect(page).to have_content('Archive project')
+
+ click_link('Archive')
+
+ expect(page).to have_content('Archived')
+ end
+ end
+end
diff --git a/spec/features/projects/user_browses_a_tree_with_a_folder_containing_only_a_folder.rb b/spec/features/projects/user_browses_a_tree_with_a_folder_containing_only_a_folder.rb
new file mode 100644
index 00000000000..a17e65cc5b9
--- /dev/null
+++ b/spec/features/projects/user_browses_a_tree_with_a_folder_containing_only_a_folder.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+# This is a regression test for https://gitlab.com/gitlab-org/gitlab-ce/issues/37569
+describe 'User browses a tree with a folder containing only a folder' do
+ let(:project) { create(:project, :empty_repo) }
+ let(:user) { project.creator }
+
+ before do
+ # We need to disable the tree.flat_path provided by Gitaly to reproduce the issue
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false)
+
+ project.repository.create_dir(user, 'foo/bar', branch_name: 'master', message: 'Add the foo/bar folder')
+ sign_in(user)
+ visit(project_tree_path(project, project.repository.root_ref))
+ end
+
+ it 'shows the nested folder on a single row' do
+ expect(page).to have_content('foo/bar')
+ end
+end
diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb
index b7a0b72db50..f5e4d7f5130 100644
--- a/spec/features/projects/user_browses_files_spec.rb
+++ b/spec/features/projects/user_browses_files_spec.rb
@@ -76,7 +76,7 @@ describe 'User browses files' do
expect(page).to have_content('LICENSE')
end
- it 'shows files from a repository with apostroph in its name', js: true do
+ 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
@@ -91,7 +91,7 @@ describe 'User browses files' do
expect(page).not_to have_content('Loading commit data...')
end
- it 'shows the code with a leading dot in the directory', js: true do
+ 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
@@ -117,7 +117,7 @@ describe 'User browses files' do
click_link('.gitignore')
end
- it 'shows a file content', js: true do
+ it 'shows a file content', :js do
wait_for_requests
expect(page).to have_content('*.rbc')
end
@@ -168,17 +168,18 @@ describe 'User browses files' do
visit(tree_path_root_ref)
end
- it 'shows a preview of a file content', js: true do
+ it 'shows a preview of a file content', :js do
find('.add-to-tree').click
click_link('Upload file')
drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'))
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
+ fill_in(:branch_name, with: 'new_branch_name', visible: true)
+ click_button('Upload file')
end
- fill_in(:branch_name, with: 'new_branch_name', visible: true)
- click_button('Upload file')
+ wait_for_all_requests
visit(project_blob_path(project, 'new_branch_name/logo_sample.svg'))
diff --git a/spec/features/projects/user_creates_directory_spec.rb b/spec/features/projects/user_creates_directory_spec.rb
index 1ba5d83eadf..052cb3188c5 100644
--- a/spec/features/projects/user_creates_directory_spec.rb
+++ b/spec/features/projects/user_creates_directory_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'User creates a directory', js: true do
+feature 'User creates a directory', :js 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."
@@ -79,7 +79,7 @@ feature 'User creates a directory', js: true do
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Create directory')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
end
diff --git a/spec/features/projects/user_creates_files_spec.rb b/spec/features/projects/user_creates_files_spec.rb
index 3d335687510..d84b91ddc32 100644
--- a/spec/features/projects/user_creates_files_spec.rb
+++ b/spec/features/projects/user_creates_files_spec.rb
@@ -59,7 +59,8 @@ describe 'User creates files' do
expect(page).to have_selector('.file-editor')
end
- it 'creates and commit a new file', js: true do
+ it 'creates and commit a new file', :js do
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
@@ -74,7 +75,8 @@ describe 'User creates files' do
expect(page).to have_content('*.rbca')
end
- it 'creates and commit a new file with new lines at the end of file', js: true do
+ it 'creates and commit a new file with new lines at the end of file', :js do
+ find('#editor')
execute_script('ace.edit("editor").setValue("Sample\n\n\n")')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
@@ -86,14 +88,16 @@ describe 'User creates files' do
find('.js-edit-blob').click
+ find('#editor')
expect(evaluate_script('ace.edit("editor").getValue()')).to eq("Sample\n\n\n")
end
- it 'creates and commit a new file with a directory name', js: true do
+ it 'creates and commit a new file with a directory name', :js do
fill_in(:file_name, with: 'foo/bar/baz.txt')
expect(page).to have_selector('.file-editor')
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -105,9 +109,10 @@ describe 'User creates files' do
expect(page).to have_content('*.rbca')
end
- it 'creates and commit a new file specifying a new branch', js: true do
+ it 'creates and commit a new file specifying a new branch', :js do
expect(page).to have_selector('.file-editor')
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
@@ -130,19 +135,20 @@ describe 'User creates files' do
visit(project2_tree_path_root_ref)
end
- it 'creates and commit new file in forked project', js: true do
+ it 'creates and commit new file in forked project', :js do
find('.add-to-tree').click
click_link('New file')
expect(page).to have_selector('.file-editor')
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
expect(page).to have_content('New commit message')
diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb
index 1c3791f63ac..4a152572502 100644
--- a/spec/features/projects/user_creates_project_spec.rb
+++ b/spec/features/projects/user_creates_project_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'User creates a project', js: true do
+feature 'User creates a project', :js do
let(:user) { create(:user) }
before do
diff --git a/spec/features/projects/user_deletes_files_spec.rb b/spec/features/projects/user_deletes_files_spec.rb
index 95cd316be0e..9e4e92ec076 100644
--- a/spec/features/projects/user_deletes_files_spec.rb
+++ b/spec/features/projects/user_deletes_files_spec.rb
@@ -21,7 +21,7 @@ describe 'User deletes files' do
visit(project_tree_path_root_ref)
end
- it 'deletes the file', js: true do
+ it 'deletes the file', :js do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
@@ -41,7 +41,7 @@ describe 'User deletes files' do
visit(project2_tree_path_root_ref)
end
- it 'deletes the file in a forked project', js: true do
+ it 'deletes the file in a forked project', :js do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
@@ -59,7 +59,7 @@ describe 'User deletes files' do
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Delete file')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
expect(page).to have_content('New commit message')
diff --git a/spec/features/projects/user_edits_files_spec.rb b/spec/features/projects/user_edits_files_spec.rb
index 3129aad8473..d26ee653415 100644
--- a/spec/features/projects/user_edits_files_spec.rb
+++ b/spec/features/projects/user_edits_files_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
describe 'User edits files' do
+ include ProjectForksHelper
let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
@@ -17,12 +18,12 @@ describe 'User edits files' do
visit(project_tree_path_root_ref)
end
- it 'inserts a content of a file', js: true do
+ it 'inserts a content of a file', :js do
click_link('.gitignore')
find('.js-edit-blob').click
+ find('.file-editor', match: :first)
- wait_for_requests
-
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca')
@@ -35,12 +36,12 @@ describe 'User edits files' do
expect(page).not_to have_link('edit')
end
- it 'commits an edited file', js: true do
+ it 'commits an edited file', :js do
click_link('.gitignore')
find('.js-edit-blob').click
+ find('.file-editor', match: :first)
- wait_for_requests
-
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -52,12 +53,13 @@ describe 'User edits files' do
expect(page).to have_content('*.rbca')
end
- it 'commits an edited file to a new branch', js: true do
+ it 'commits an edited file to a new branch', :js do
click_link('.gitignore')
find('.js-edit-blob').click
- wait_for_requests
+ find('.file-editor', match: :first)
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
@@ -67,16 +69,15 @@ describe 'User edits files' do
click_link('Changes')
- wait_for_requests
expect(page).to have_content('*.rbca')
end
- it 'shows the diff of an edited file', js: true do
+ it 'shows the diff of an edited file', :js do
click_link('.gitignore')
find('.js-edit-blob').click
+ find('.file-editor', match: :first)
- wait_for_requests
-
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
click_link('Preview changes')
@@ -90,7 +91,7 @@ describe 'User edits files' do
visit(project2_tree_path_root_ref)
end
- it 'inserts a content of a file in a forked project', js: true do
+ it 'inserts a content of a file in a forked project', :js do
click_link('.gitignore')
find('.js-edit-blob').click
@@ -104,14 +105,15 @@ describe 'User edits files' do
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
)
- wait_for_requests
+ find('.file-editor', match: :first)
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca')
end
- it 'commits an edited file in a forked project', js: true do
+ it 'commits an edited file in a forked project', :js do
click_link('.gitignore')
find('.js-edit-blob').click
@@ -120,13 +122,14 @@ describe 'User edits files' do
click_link('Fork')
- wait_for_requests
+ find('.file-editor', match: :first)
+ find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
@@ -134,5 +137,35 @@ describe 'User edits files' do
expect(page).to have_content('New commit message')
end
+
+ context 'when the user already had a fork of the project', :js do
+ let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) }
+ before do
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'links to the forked project for editing' do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+
+ expect(page).not_to have_link('Fork')
+ expect(page).not_to have_button('Cancel')
+
+ find('#editor')
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:commit_message, with: 'Another commit', visible: true)
+ click_button('Commit changes')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+
+ wait_for_requests
+
+ expect(page).to have_content('Another commit')
+ expect(page).to have_content("From #{forked_project.full_path}")
+ expect(page).to have_content("into #{project2.full_path}")
+ end
+ end
end
end
diff --git a/spec/features/projects/user_interacts_with_stars_spec.rb b/spec/features/projects/user_interacts_with_stars_spec.rb
index 0ac3f8181fa..d9d2e0ab171 100644
--- a/spec/features/projects/user_interacts_with_stars_spec.rb
+++ b/spec/features/projects/user_interacts_with_stars_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'User interacts with project stars' do
let(:project) { create(:project, :public, :repository) }
- context 'when user is signed in', js: true do
+ context 'when user is signed in', :js do
let(:user) { create(:user) }
before do
diff --git a/spec/features/projects/user_replaces_files_spec.rb b/spec/features/projects/user_replaces_files_spec.rb
index e284fdefd4f..245b6aa285b 100644
--- a/spec/features/projects/user_replaces_files_spec.rb
+++ b/spec/features/projects/user_replaces_files_spec.rb
@@ -23,7 +23,7 @@ describe 'User replaces files' do
visit(project_tree_path_root_ref)
end
- it 'replaces an existed file with a new one', js: true do
+ it 'replaces an existed file with a new one', :js do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
@@ -49,7 +49,7 @@ describe 'User replaces files' do
visit(project2_tree_path_root_ref)
end
- it 'replaces an existed file with a new one in a forked project', js: true do
+ it 'replaces an existed file with a new one in a forked project', :js do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
@@ -74,7 +74,7 @@ describe 'User replaces files' do
expect(page).to have_content('Replacement file commit message')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
diff --git a/spec/features/projects/user_uploads_files_spec.rb b/spec/features/projects/user_uploads_files_spec.rb
index 98871317ca3..ae51901adc6 100644
--- a/spec/features/projects/user_uploads_files_spec.rb
+++ b/spec/features/projects/user_uploads_files_spec.rb
@@ -23,7 +23,7 @@ describe 'User uploads files' do
visit(project_tree_path_root_ref)
end
- it 'uploads and commit a new file', js: true do
+ it 'uploads and commit a new file', :js do
find('.add-to-tree').click
click_link('Upload file')
drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
@@ -39,6 +39,9 @@ describe 'User uploads files' do
expect(current_path).to eq(project_new_merge_request_path(project))
click_link('Changes')
+ find("a[data-action='diffs']", text: 'Changes').click
+
+ wait_for_requests
expect(page).to have_content('Lorem ipsum dolor sit amet')
expect(page).to have_content('Sed ut perspiciatis unde omnis')
@@ -51,7 +54,7 @@ describe 'User uploads files' do
visit(project2_tree_path_root_ref)
end
- it 'uploads and commit a new fileto a forked project', js: true do
+ it 'uploads and commit a new file to a forked project', :js do
find('.add-to-tree').click
click_link('Upload file')
@@ -69,11 +72,13 @@ describe 'User uploads files' do
expect(page).to have_content('New commit message')
- fork = user.fork_of(project2)
+ fork = user.fork_of(project2.reload)
expect(current_path).to eq(project_new_merge_request_path(fork))
- click_link('Changes')
+ find("a[data-action='diffs']", text: 'Changes').click
+
+ wait_for_requests
expect(page).to have_content('Lorem ipsum dolor sit amet')
expect(page).to have_content('Sed ut perspiciatis unde omnis')
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
new file mode 100644
index 00000000000..fb0d8c766fe
--- /dev/null
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -0,0 +1,108 @@
+require 'spec_helper'
+
+describe 'User uses shortcuts', :js do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+
+ visit(project_path(project))
+ end
+
+ context 'when navigating to the Overview pages' do
+ it 'redirects to the details page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('p')
+
+ expect(page).to have_active_navigation('Overview')
+ expect(page).to have_active_sub_navigation('Details')
+ end
+
+ it 'redirects to the activity page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('e')
+
+ expect(page).to have_active_navigation('Overview')
+ expect(page).to have_active_sub_navigation('Activity')
+ end
+ end
+
+ context 'when navigating to the Repository pages' do
+ it 'redirects to the repository files page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('f')
+
+ expect(page).to have_active_navigation('Repository')
+ expect(page).to have_active_sub_navigation('Files')
+ end
+
+ it 'redirects to the repository commits page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('c')
+
+ expect(page).to have_active_navigation('Repository')
+ expect(page).to have_active_sub_navigation('Commits')
+ end
+
+ it 'redirects to the repository graph page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('n')
+
+ expect(page).to have_active_navigation('Repository')
+ expect(page).to have_active_sub_navigation('Graph')
+ end
+
+ it 'redirects to the repository charts page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('d')
+
+ expect(page).to have_active_navigation('Repository')
+ expect(page).to have_active_sub_navigation('Charts')
+ end
+ end
+
+ context 'when navigating to the Issues pages' do
+ it 'redirects to the issues list page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('i')
+
+ expect(page).to have_active_navigation('Issues')
+ expect(page).to have_active_sub_navigation('List')
+ end
+
+ it 'redirects to the new issue page' do
+ find('body').native.send_key('i')
+
+ expect(page).to have_content(project.title)
+ end
+ end
+
+ context 'when navigating to the Merge Requests pages' do
+ it 'redirects to the merge requests page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('m')
+
+ expect(page).to have_active_navigation('Merge Requests')
+ end
+ end
+
+ context 'when navigating to the Snippets pages' do
+ it 'redirects to the snippets page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('s')
+
+ expect(page).to have_active_navigation('Snippets')
+ end
+ end
+
+ context 'when navigating to the Wiki pages' do
+ it 'redirects to the wiki page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('w')
+
+ expect(page).to have_active_navigation('Wiki')
+ end
+ end
+end
diff --git a/spec/features/projects/user_views_details_spec.rb b/spec/features/projects/user_views_details_spec.rb
new file mode 100644
index 00000000000..ffc063654cd
--- /dev/null
+++ b/spec/features/projects/user_views_details_spec.rb
@@ -0,0 +1,151 @@
+require 'spec_helper'
+
+describe 'User views details' do
+ set(:user) { create(:user) }
+
+ shared_examples_for 'redirects to the sign in page' do
+ it 'redirects to the sign in page' do
+ expect(current_path).to eq(new_user_session_path)
+ end
+ end
+
+ shared_examples_for 'shows details of empty project' do
+ let(:user_has_ssh_key) { false }
+
+ it 'shows details' do
+ expect(page).not_to have_content('Git global setup')
+
+ page.all(:css, '.git-empty .clone').each do |element|
+ expect(element.text).to include(project.http_url_to_repo)
+ end
+
+ expect(page).to have_field('project_clone', with: project.http_url_to_repo) unless user_has_ssh_key
+ end
+ end
+
+ shared_examples_for 'shows details of non empty project' do
+ let(:user_has_ssh_key) { false }
+
+ it 'shows details' do
+ page.within('.breadcrumbs .breadcrumb-item-text') do
+ expect(page).to have_content(project.title)
+ end
+
+ expect(page).to have_field('project_clone', with: project.http_url_to_repo) unless user_has_ssh_key
+ end
+ end
+
+ context 'when project is public' do
+ context 'when project is empty' do
+ set(:project) { create(:project_empty_repo, :public) }
+
+ context 'when not signed in' do
+ before do
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of empty project'
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when user does not have ssh keys' do
+ before do
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of empty project'
+ end
+
+ context 'when user has ssh keys' do
+ before do
+ create(:personal_key, user: user)
+
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of empty project' do
+ let(:user_has_ssh_key) { true }
+ end
+ end
+ end
+ end
+
+ context 'when project is not empty' do
+ set(:project) { create(:project, :public, :repository) }
+
+ before do
+ visit(project_path(project))
+ end
+
+ context 'when not signed in' do
+ before do
+ allow(Gitlab.config.gitlab).to receive(:host).and_return('www.example.com')
+ end
+
+ include_examples 'shows details of non empty project'
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ context 'when user does not have ssh keys' do
+ before do
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of non empty project'
+ end
+
+ context 'when user has ssh keys' do
+ before do
+ create(:personal_key, user: user)
+
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of non empty project' do
+ let(:user_has_ssh_key) { true }
+ end
+ end
+ end
+ end
+ end
+
+ context 'when project is internal' do
+ set(:project) { create(:project, :internal, :repository) }
+
+ context 'when not signed in' do
+ before do
+ visit(project_path(project))
+ end
+
+ include_examples 'redirects to the sign in page'
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+
+ visit(project_path(project))
+ end
+
+ include_examples 'shows details of non empty project'
+ end
+ end
+
+ context 'when project is private' do
+ set(:project) { create(:project, :private) }
+
+ before do
+ visit(project_path(project))
+ end
+
+ include_examples 'redirects to the sign in page'
+ end
+end
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index 2a316a0d0db..7f547a4ca1f 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'View on environment', js: true do
+describe 'View on environment', :js do
let(:branch_name) { 'feature' }
let(:file_path) { 'files/ruby/feature.rb' }
let(:project) { create(:project, :repository) }
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
index 9a4ccf3c54d..337baaf4dcd 100644
--- a/spec/features/projects/wiki/markdown_preview_spec.rb
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Projects > Wiki > User previews markdown changes', js: true do
+feature 'Projects > Wiki > User previews markdown changes', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
let(:wiki_content) do
@@ -14,18 +14,17 @@ feature 'Projects > Wiki > User previews markdown changes', js: true do
background do
project.team << [user, :master]
- WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
sign_in(user)
visit project_path(project)
- find('.shortcuts-wiki').trigger('click')
+ find('.shortcuts-wiki').click
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
- find('.add-new-wiki').trigger('click')
+ find('.add-new-wiki').click
page.within '#modal-new-wiki' do
fill_in :new_wiki_path, with: 'a/b/c/d'
click_button 'Create page'
@@ -92,7 +91,7 @@ feature 'Projects > Wiki > User previews markdown changes', js: true do
context "while editing a wiki page" do
def create_wiki_page(path)
- find('.add-new-wiki').trigger('click')
+ find('.add-new-wiki').click
page.within '#modal-new-wiki' do
fill_in :new_wiki_path, with: path
diff --git a/spec/features/projects/wiki/shortcuts_spec.rb b/spec/features/projects/wiki/shortcuts_spec.rb
index eaff5f876b6..f70d1e710dd 100644
--- a/spec/features/projects/wiki/shortcuts_spec.rb
+++ b/spec/features/projects/wiki/shortcuts_spec.rb
@@ -3,9 +3,7 @@ require 'spec_helper'
feature 'Wiki shortcuts', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
- let(:wiki_page) do
- WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
- end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: 'Home page' }) }
before do
sign_in(user)
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 9d66f482c8d..4a9d1cb87e1 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -1,38 +1,75 @@
require 'spec_helper'
-feature 'Projects > Wiki > User creates wiki page', :js do
+describe 'User creates wiki page' do
let(:user) { create(:user) }
- background do
- project.team << [user, :master]
+ before do
+ project.add_master(user)
sign_in(user)
- visit project_path(project)
+ visit(project_wikis_path(project))
end
- context 'in the 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, namespace: user.namespace) }
- context 'when wiki is empty' do
- before do
- find('.shortcuts-wiki').trigger('click')
+ 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")
+
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: '[link test](test)')
+ click_on('Create page')
+ end
+
+ expect(page).to have_content('Home')
+ expect(page).to have_content('link test')
+
+ click_link('link test')
+
+ expect(page).to have_content('Create Page')
+ end
+
+ 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')
+ end
+
+ 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(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']")
end
- scenario 'commit message field has value "Create home"' do
+ it 'has "Create home" as a commit message' do
expect(page).to have_field('wiki[message]', with: 'Create home')
end
- scenario 'directly from the wiki home page' do
- fill_in :wiki_content, with: 'My awesome wiki!'
- page.within '.wiki-form' do
- click_button 'Create page'
+ it 'creates a page from the home page' do
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+
+ page.within('.wiki-form') do
+ 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!')
end
- scenario 'creates ASCII wiki with LaTeX blocks' do
+ it 'creates ASCII wiki with LaTeX blocks', :js do
stub_application_setting(plantuml_url: 'http://localhost', plantuml_enabled: true)
ascii_content = <<~MD
@@ -40,24 +77,24 @@ feature 'Projects > Wiki > User creates wiki page', :js do
[stem]
++++
- \sqrt{4} = 2
+ \\sqrt{4} = 2
++++
another part
[latexmath]
++++
- \beta_x \gamma
+ \\beta_x \\gamma
++++
stem:[2+2] is 4
MD
find('#wiki_format option[value=asciidoc]').select_option
- fill_in :wiki_content, with: ascii_content
+ 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
@@ -67,27 +104,49 @@ feature 'Projects > Wiki > User creates wiki page', :js do
end
end
- context 'when wiki is not empty' do
- before do
- WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
- find('.shortcuts-wiki').trigger('click')
+ context 'in a group namespace', :js do
+ let(:project) { create(:project, namespace: create(:group, :public)) }
+
+ it 'has "Create home" as a commit message' do
+ expect(page).to have_field('wiki[message]', with: 'Create home')
+ 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')
+ 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!')
end
+ end
+ end
+
+ 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' })
+ end
+
+ context 'in a user namespace' do
+ let(:project) { create(:project, namespace: user.namespace) }
context 'via the "new wiki page" page' do
- scenario 'when the wiki page has a single word name' do
- click_link 'New page'
+ 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')
- page.within '.wiki-form' do
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Create page')
end
expect(page).to have_content('Foo')
@@ -95,20 +154,20 @@ feature 'Projects > Wiki > User creates wiki page', :js do
expect(page).to have_content('My awesome wiki!')
end
- scenario 'when the wiki page has 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')
- page.within '.wiki-form' do
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Create page')
end
expect(page).to have_content('Spaces in the name')
@@ -116,20 +175,20 @@ feature 'Projects > Wiki > User creates wiki page', :js do
expect(page).to have_content('My awesome wiki!')
end
- scenario 'when the wiki page has 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')
- page.within '.wiki-form' do
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Create page')
end
expect(page).to have_content('Hyphens in the name')
@@ -138,73 +197,47 @@ feature 'Projects > Wiki > User creates wiki page', :js do
end
end
- scenario 'content has autocomplete' 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
+ page.within('.wiki-form') do
find('#wiki_content').native.send_keys('')
- fill_in :wiki_content, with: '@'
+ fill_in(:wiki_content, with: '@')
end
expect(page).to have_selector('.atwho-view')
end
end
- end
-
- context 'in a group namespace' do
- let(:project) { create(:project, namespace: create(:group, :public)) }
- context 'when wiki is empty' do
- before do
- find('.shortcuts-wiki').trigger('click')
- end
-
- scenario 'commit message field has value "Create home"' do
- expect(page).to have_field('wiki[message]', with: 'Create home')
- end
+ context 'in a group namespace' do
+ let(:project) { create(:project, namespace: create(:group, :public)) }
- scenario 'directly from the wiki home page' do
- fill_in :wiki_content, with: 'My awesome wiki!'
- page.within '.wiki-form' do
- 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!')
- end
- end
-
- context 'when wiki is not empty' do
- before do
- WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
- find('.shortcuts-wiki').trigger('click')
- end
+ context 'via the "new wiki page" page' do
+ it 'creates a page' do
+ click_link('New page')
- scenario 'via the "new wiki page" page' do
- click_link 'New page'
+ page.within('#modal-new-wiki') do
+ fill_in(:new_wiki_path, with: 'foo')
+ click_button('Create page')
+ end
- 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')
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Create foo')
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Create page')
+ end
- page.within '.wiki-form' do
- 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!')
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!')
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
new file mode 100644
index 00000000000..605e332196b
--- /dev/null
+++ b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+feature 'User deletes wiki page' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki) }
+
+ before do
+ sign_in(user)
+ visit(project_wiki_path(project, wiki_page))
+ end
+
+ it 'deletes a page' do
+ click_on('Edit')
+ click_on('Delete')
+
+ expect(page).to have_content('Page was successfully deleted')
+ end
+end
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 9a92622ba2b..37a118c34ab 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
@@ -3,14 +3,7 @@ require 'spec_helper'
describe 'Projects > Wiki > User views Git access wiki page' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
- let(:wiki_page) do
- WikiPages::CreateService.new(
- project,
- user,
- title: 'home',
- content: '[some link](other-page)'
- ).execute
- end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) }
before do
sign_in(user)
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 64a80aec205..949d90a50ff 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -1,83 +1,154 @@
require 'spec_helper'
-feature 'Projects > Wiki > User updates wiki page' do
+describe 'User updates wiki page' do
let(:user) { create(:user) }
- let!(:wiki_page) { WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute }
- background do
- project.team << [user, :master]
+ before do
+ project.add_master(user)
sign_in(user)
+ end
+
+ context 'when wiki is empty' do
+ before do
+ visit(project_wikis_path(project))
+ end
+
+ context 'in a user namespace' do
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ it 'redirects back to the home edit page' do
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
+ end
+
+ expect(current_path).to eq project_wiki_path(project, :home)
+ end
+
+ it 'updates a page that has a path', :js do
+ click_on('New 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')
+ end
- visit project_wikis_path(project)
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('Three')
+
+ first(:link, text: 'Three').click
+
+ expect(find('.nav-text')).to have_content('Three')
+
+ click_on('Edit')
+
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
+
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
+
+ expect(page).to have_content('Updated Wiki Content')
+ end
+ end
end
- context 'in the user namespace' do
- let(:project) { create(:project, namespace: user.namespace) }
+ context 'when wiki is not empty' do
+ let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
+ let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
- context 'the home page' do
- scenario 'success when the wiki content is not empty' do
- click_link 'Edit'
+ before do
+ visit(project_wikis_path(project))
+ end
+
+ context 'in a user namespace' do
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ it 'updates a page' do
+ click_link('Edit')
# Commit message field should have correct value.
expect(page).to have_field('wiki[message]', with: 'Update home')
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Save changes'
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Save changes')
expect(page).to have_content('Home')
expect(page).to have_content("Last edited by #{user.name}")
expect(page).to have_content('My awesome wiki!')
end
- scenario 'failure when the wiki content is empty' do
- click_link 'Edit'
+ it 'shows a validation error message' do
+ click_link('Edit')
- fill_in :wiki_content, with: ''
- click_button 'Save changes'
+ fill_in(:wiki_content, with: '')
+ click_button('Save changes')
expect(page).to have_selector('.wiki-form')
expect(page).to have_content('Edit Page')
expect(page).to have_content('The form contains the following error:')
- expect(page).to have_content('Content can\'t be blank')
- expect(find('textarea#wiki_content').value).to eq ''
+ expect(page).to have_content("Content can't be blank")
+ expect(find('textarea#wiki_content').value).to eq('')
end
- scenario 'content has autocomplete', :js do
- click_link 'Edit'
+ it 'shows the autocompletion dropdown', :js do
+ click_link('Edit')
find('#wiki_content').native.send_keys('')
- fill_in :wiki_content, with: '@'
+ fill_in(:wiki_content, with: '@')
expect(page).to have_selector('.atwho-view')
end
- end
- scenario 'page has been updated since the user opened the edit page' do
- click_link 'Edit'
+ it 'shows the error message' do
+ click_link('Edit')
+
+ wiki_page.update(content: 'Update')
- wiki_page.update(content: 'Update')
+ click_button('Save changes')
+
+ expect(page).to have_content('Someone edited the page the same time you did.')
+ end
+
+ it 'updates a page' do
+ click_on('Edit')
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
+
+ expect(page).to have_content('Updated Wiki Content')
+ end
- click_button 'Save changes'
+ it 'cancels edititng of a page' do
+ click_on('Edit')
- expect(page).to have_content 'Someone edited the page the same time you did.'
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
+ end
+
+ expect(current_path).to eq(project_wiki_path(project, wiki_page))
+ end
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, namespace: create(:group, :public)) }
- scenario 'the home page' do
- click_link 'Edit'
+ it 'updates a page' do
+ click_link('Edit')
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Save changes'
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Save changes')
- 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')
+ 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/projects/wiki/user_views_project_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb
deleted file mode 100644
index 92e96f11219..00000000000
--- a/spec/features/projects/wiki/user_views_project_wiki_page_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'spec_helper'
-
-feature 'Projects > Wiki > User views the wiki page' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :public) }
- let(:old_page_version_id) { wiki_page.versions.last.id }
- let(:wiki_page) do
- WikiPages::CreateService.new(
- project,
- user,
- title: 'home',
- content: '[some link](other-page)'
- ).execute
- end
-
- background do
- project.team << [user, :master]
- sign_in(user)
- WikiPages::UpdateService.new(
- project,
- user,
- message: 'updated home',
- content: 'updated [some link](other-page)',
- format: :markdown
- ).execute(wiki_page)
- end
-
- scenario 'Visit Wiki Page Current Commit' do
- visit project_wiki_path(project, wiki_page)
-
- expect(page).to have_selector('a.btn', text: 'Edit')
- end
-
- scenario 'Visit Wiki Page Historical Commit' do
- visit project_wiki_path(project, wiki_page, version_id: old_page_version_id)
-
- expect(page).not_to have_selector('a.btn', text: 'Edit')
- end
-end
diff --git a/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_in_project_page_spec.rb
index cf9fe4c1ad1..ebb3bd044c1 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
@@ -18,12 +18,7 @@ describe 'Projects > Wiki > User views wiki in project page' do
context 'when wiki homepage contains a link' do
before do
- WikiPages::CreateService.new(
- project,
- user,
- title: 'home',
- content: '[some link](other-page)'
- ).execute
+ create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' })
end
it 'displays the correct URL for the link' do
diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
new file mode 100644
index 00000000000..ff325aeadd3
--- /dev/null
+++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
@@ -0,0 +1,145 @@
+require 'spec_helper'
+
+describe 'User views a wiki page' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:wiki_page) do
+ create(:wiki_page,
+ wiki: project.wiki,
+ attrs: { title: 'home', content: 'Look at this [image](image.jpg)\n\n ![alt text](image.jpg)' })
+ end
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'when wiki is empty' do
+ before do
+ visit(project_wikis_path(project))
+
+ click_on('New 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')
+ end
+ end
+
+ it 'shows the history of a page that has a path', :js do
+ expect(current_path).to include('one/two/three-test')
+
+ first(:link, text: 'Three').click
+ click_on('Page history')
+
+ expect(current_path).to include('one/two/three-test')
+
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
+ end
+ end
+
+ it 'shows an old version of a page', :js do
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('Three')
+
+ first(:link, text: 'Three').click
+
+ expect(find('.nav-text')).to have_content('Three')
+
+ click_on('Edit')
+
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
+
+ fill_in('Content', with: 'Updated Wiki Content')
+
+ click_on('Save changes')
+ click_on('Page history')
+
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
+ end
+
+ find('a[href*="?version_id"]')
+ end
+ end
+
+ context 'when a page does not have history' do
+ before do
+ visit(project_wiki_path(project, wiki_page))
+ end
+
+ it 'shows all the pages' do
+ expect(page).to have_content(user.name)
+ expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize)
+ end
+
+ it 'shows a file stored in a page' do
+ gollum_file_double = double('Gollum::File',
+ mime_type: 'image/jpeg',
+ name: 'images/image.jpg',
+ path: 'images/image.jpg',
+ raw_data: '')
+ wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
+
+ allow(wiki_file).to receive(:mime_type).and_return('image/jpeg')
+ allow_any_instance_of(ProjectWiki).to receive(:find_file).with('image.jpg', nil).and_return(wiki_file)
+
+ expect(page).to have_xpath('//img[@data-src="image.jpg"]')
+ expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/image.jpg")
+
+ click_on('image')
+
+ expect(current_path).to match('wikis/image.jpg')
+ expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved
+ end
+
+ it 'shows the creation page if file does not exist' do
+ expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/image.jpg")
+
+ click_on('image')
+
+ expect(current_path).to match('wikis/image.jpg')
+ expect(page).to have_content('New Wiki Page')
+ expect(page).to have_content('Create page')
+ end
+ end
+
+ context 'when a page has history' do
+ before do
+ wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)')
+ end
+
+ it 'shows the page history' do
+ visit(project_wiki_path(project, wiki_page))
+
+ expect(page).to have_selector('a.btn', text: 'Edit')
+
+ click_on('Page history')
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content("#{user.username} created page: home")
+ expect(page).to have_content('updated home')
+ end
+
+ it 'does not show the "Edit" button' do
+ visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id))
+
+ expect(page).not_to have_selector('a.btn', text: 'Edit')
+ end
+ end
+
+ it 'opens a default wiki page', :js do
+ visit(project_path(project))
+
+ find('.shortcuts-wiki').click
+
+ expect(page).to have_content('Home ยท Create Page')
+ end
+end