summaryrefslogtreecommitdiff
path: root/spec/features/projects
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2017-05-23 02:10:29 +0800
committerLin Jen-Shin <godfat@godfat.org>2017-05-23 02:10:29 +0800
commit1a4130d3a6cfb4956f8bb1186cc499ea549d8e18 (patch)
tree076adcb3e6f3800a1a7bbc6809839d5cb3b3f372 /spec/features/projects
parent3c8a6fba67998eb17240b15db85f8d1c8aff338e (diff)
parent18a6d9c5326bc2b90a1f0cc8664d638a39885924 (diff)
downloadgitlab-ce-27377-preload-pipeline-entity.tar.gz
Merge remote-tracking branch 'upstream/master' into 27377-preload-pipeline-entity27377-preload-pipeline-entity
* upstream/master: (2534 commits) Update VERSION to 9.3.0-pre Update CHANGELOG.md for 9.2.0 removes unnecessary redundacy in usage ping doc Respect the typo as rubocop said Add a test to ensure this works on MySQL Change pipelines schedules help page path change domain to hostname in usage ping doc Fixes broken MySQL migration for retried Show password field mask while editing service settings Add notes for supported schedulers and cloud providers Move environment monitoring to environments doc Add docs for change of Cache/Artifact restore order" Avoid resource intensive login checks if password is not provided Change translation for 'coding' by 'desarrollo' for Spanish Add to docs: issues multiple assignees rename "Add emoji" and "Award emoji" to "Add reaction" where appropriate Add project and group notification settings info 32570 Fix border-bottom for project activity tab Add users endpoint to frontend API class Rename users on mysql ...
Diffstat (limited to 'spec/features/projects')
-rw-r--r--spec/features/projects/artifacts/file_spec.rb59
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb466
-rw-r--r--spec/features/projects/blobs/edit_spec.rb146
-rw-r--r--spec/features/projects/blobs/user_create_spec.rb9
-rw-r--r--spec/features/projects/branches/new_branch_ref_dropdown_spec.rb48
-rw-r--r--spec/features/projects/branches_spec.rb85
-rw-r--r--spec/features/projects/builds_spec.rb71
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb7
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb2
-rw-r--r--spec/features/projects/deploy_keys_spec.rb12
-rw-r--r--spec/features/projects/edit_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb6
-rw-r--r--spec/features/projects/environments/environments_spec.rb40
-rw-r--r--spec/features/projects/features_visibility_spec.rb38
-rw-r--r--spec/features/projects/files/browse_files_spec.rb17
-rw-r--r--spec/features/projects/files/creating_a_file_spec.rb10
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb8
-rw-r--r--spec/features/projects/files/editing_a_file_spec.rb6
-rw-r--r--spec/features/projects/files/files_sort_submodules_with_folders_spec.rb2
-rw-r--r--spec/features/projects/files/find_file_keyboard_spec.rb2
-rw-r--r--spec/features/projects/files/find_files_spec.rb30
-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.rb10
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb8
-rw-r--r--spec/features/projects/files/template_type_dropdown_spec.rb135
-rw-r--r--spec/features/projects/files/undo_template_spec.rb66
-rw-r--r--spec/features/projects/gfm_autocomplete_load_spec.rb2
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb8
-rw-r--r--spec/features/projects/import_export/test_project_export.tar.gzbin679892 -> 681478 bytes
-rw-r--r--spec/features/projects/issuable_templates_spec.rb16
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb1
-rw-r--r--spec/features/projects/members/group_links_spec.rb2
-rw-r--r--spec/features/projects/members/list_spec.rb90
-rw-r--r--spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb1
-rw-r--r--spec/features/projects/members/sorting_spec.rb4
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb11
-rw-r--r--spec/features/projects/merge_request_button_spec.rb28
-rw-r--r--spec/features/projects/merge_requests/list_spec.rb24
-rw-r--r--spec/features/projects/milestones/milestone_spec.rb23
-rw-r--r--spec/features/projects/new_project_spec.rb16
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb146
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb53
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb54
-rw-r--r--spec/features/projects/project_settings_spec.rb152
-rw-r--r--spec/features/projects/ref_switcher_spec.rb1
-rw-r--r--spec/features/projects/settings/integration_settings_spec.rb96
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb11
-rw-r--r--spec/features/projects/snippets/show_spec.rb144
-rw-r--r--spec/features/projects/snippets_spec.rb24
-rw-r--r--spec/features/projects/user_create_dir_spec.rb1
-rw-r--r--spec/features/projects/view_on_env_spec.rb6
-rw-r--r--spec/features/projects/wiki/markdown_preview_spec.rb60
-rw-r--r--spec/features/projects/wiki/shortcuts_spec.rb20
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb89
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb6
56 files changed, 2105 insertions, 273 deletions
diff --git a/spec/features/projects/artifacts/file_spec.rb b/spec/features/projects/artifacts/file_spec.rb
new file mode 100644
index 00000000000..74308a7e8dd
--- /dev/null
+++ b/spec/features/projects/artifacts/file_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+
+feature 'Artifact file', :js, feature: true do
+ let(:project) { create(:project, :public) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
+ let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ def visit_file(path)
+ visit file_namespace_project_build_artifacts_path(project.namespace, project, build, path)
+ end
+
+ context 'Text file' do
+ before do
+ visit_file('other_artifacts_0.1.2/doc_sample.txt')
+
+ wait_for_ajax
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('The source could not be displayed because it is stored as a job artifact. You can download it instead.')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'JPG file' do
+ before do
+ visit_file('rails_sample.jpg')
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows rendered image
+ expect(page).to have_selector('.image_file img')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
new file mode 100644
index 00000000000..fc242082278
--- /dev/null
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -0,0 +1,466 @@
+require 'spec_helper'
+
+feature 'File blob', :js, feature: true do
+ let(:project) { create(:project, :public) }
+
+ def visit_blob(path, fragment = nil)
+ visit namespace_project_blob_path(project.namespace, project, File.join('master', path), anchor: fragment)
+
+ wait_for_ajax
+ end
+
+ context 'Ruby file' do
+ before do
+ visit_blob('files/ruby/popen.rb')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+ end
+ end
+ end
+
+ context 'Markdown file' do
+ context 'visiting directly' do
+ before do
+ visit_blob('files/markdown/ruby-style-guide.md')
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+ end
+
+ context 'visiting with a line number anchor' do
+ before do
+ visit_blob('files/markdown/ruby-style-guide.md', 'L1')
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # highlights the line in question
+ expect(page).to have_selector('#LC1.hll')
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+
+ context 'Markdown file (stored in LFS)' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add Markdown in LFS",
+ file_path: 'files/lfs/file.md',
+ file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data
+ ).execute
+ end
+
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+
+ visit_blob('files/lfs/file.md')
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an error message
+ expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS. You can download it instead.')
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switcher .js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # shows an error message
+ expect(page).to have_content('The source could not be displayed because it is stored in LFS. You can download it instead.')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ end
+ end
+ end
+ end
+
+ context 'when LFS is disabled on the project' do
+ before do
+ visit_blob('files/lfs/file.md')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows text
+ expect(page).to have_content('size 1575078')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+ end
+ end
+ end
+ end
+
+ context 'PDF file' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add PDF",
+ file_path: 'files/test.pdf',
+ file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data
+ ).execute
+
+ visit_blob('files/test.pdf')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows rendered PDF
+ expect(page).to have_selector('.js-pdf-viewer')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'ISO file (stored in LFS)' do
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+
+ visit_blob('files/lfs/lfs_object.iso')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (1.5 MB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'when LFS is disabled on the project' do
+ before do
+ visit_blob('files/lfs/lfs_object.iso')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows text
+ expect(page).to have_content('size 1575078')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+ end
+ end
+ end
+ end
+
+ context 'ZIP file' do
+ before do
+ visit_blob('Gemfile.zip')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (2.11 KB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'empty file' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add empty file",
+ file_path: 'files/empty.md',
+ file_content: ''
+ ).execute
+
+ visit_blob('files/empty.md')
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('Empty file')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # does not show a download or raw button
+ expect(page).not_to have_link('Download')
+ expect(page).not_to have_link('Open raw')
+ end
+ end
+ end
+
+ context '.gitlab-ci.yml' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab-ci.yml",
+ file_path: '.gitlab-ci.yml',
+ file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ ).execute
+
+ visit_blob('.gitlab-ci.yml')
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that configuration is valid
+ expect(page).to have_content('This GitLab CI configuration is valid.')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
+
+ context '.gitlab/route-map.yml' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab/route-map.yml",
+ file_path: '.gitlab/route-map.yml',
+ file_content: <<-MAP.strip_heredoc
+ # Team data
+ - source: 'data/team.yml'
+ public: 'team/'
+ MAP
+ ).execute
+
+ visit_blob('.gitlab/route-map.yml')
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that map is valid
+ expect(page).to have_content('This Route Map is valid.')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
+
+ context 'LICENSE' do
+ before do
+ visit_blob('LICENSE')
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows license
+ expect(page).to have_content('This project is licensed under the MIT License.')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more', 'http://choosealicense.com/licenses/mit/')
+ end
+ end
+ end
+
+ context '*.gemspec' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add activerecord.gemspec",
+ file_path: 'activerecord.gemspec',
+ file_content: <<-SPEC.strip_heredoc
+ Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "activerecord"
+ end
+ SPEC
+ ).execute
+
+ visit_blob('activerecord.gemspec')
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows names of dependency manager and package
+ expect(page).to have_content('This project manages its dependencies using RubyGems and defines a gem named activerecord.')
+
+ # shows a link to the gem
+ expect(page).to have_link('activerecord', 'https://rubygems.org/gems/activerecord')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more', 'http://choosealicense.com/licenses/mit/')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index a820d07ab3b..cc5b1a7e734 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -1,45 +1,135 @@
require 'spec_helper'
feature 'Editing file blob', feature: true, js: true do
- include WaitForAjax
+ include TreeHelper
- given(:user) { create(:user) }
- given(:role) { :developer }
- given(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') }
- given(:project) { merge_request.target_project }
+ let(:project) { create(:project, :public, :test_repo) }
+ let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
+ let(:branch) { 'master' }
+ let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
- background do
- login_as(user)
- project.team << [user, role]
- end
-
- def edit_and_commit
- wait_for_ajax
- first('.file-actions').click_link 'Edit'
- execute_script('ace.edit("editor").setValue("class NextFeature\nend\n")')
- click_button 'Commit Changes'
- end
+ context 'as a developer' do
+ let(:user) { create(:user) }
+ let(:role) { :developer }
- context 'from MR diff' do
before do
- visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
- edit_and_commit
+ project.team << [user, role]
+ login_as(user)
+ end
+
+ def edit_and_commit
+ wait_for_ajax
+ find('.js-edit-blob').click
+ execute_script('ace.edit("editor").setValue("class NextFeature\nend\n")')
+ click_button 'Commit changes'
+ end
+
+ context 'from MR diff' do
+ before do
+ visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
+ edit_and_commit
+ end
+
+ it 'returns me to the mr' do
+ expect(page).to have_content(merge_request.title)
+ end
end
- scenario 'returns me to the mr' do
- expect(page).to have_content(merge_request.title)
+ context 'from blob file path' do
+ before do
+ visit namespace_project_blob_path(project.namespace, project, tree_join(branch, file_path))
+ edit_and_commit
+ end
+
+ it 'updates content' do
+ expect(page).to have_content 'successfully committed'
+ expect(page).to have_content 'NextFeature'
+ end
end
end
- context 'from blob file path' do
- before do
- visit namespace_project_blob_path(project.namespace, project, '/feature/files/ruby/feature.rb')
- edit_and_commit
+ context 'visit blob edit' do
+ context 'redirects to sign in and returns' do
+ context 'as developer' do
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :developer]
+ visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))
+ end
+
+ it 'redirects to sign in and returns' do
+ expect(page).to have_current_path(new_user_session_path)
+
+ login_as(user)
+
+ expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)))
+ end
+ end
+
+ context 'as guest' do
+ let(:user) { create(:user) }
+
+ before do
+ visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))
+ end
+
+ it 'redirects to sign in and returns' do
+ expect(page).to have_current_path(new_user_session_path)
+
+ login_as(user)
+
+ expect(page).to have_current_path(namespace_project_blob_path(project.namespace, project, tree_join(branch, file_path)))
+ end
+ end
+ end
+
+ context 'as developer' do
+ let(:user) { create(:user) }
+ let(:protected_branch) { 'protected-branch' }
+
+ before do
+ project.team << [user, :developer]
+ project.repository.add_branch(user, protected_branch, 'master')
+ create(:protected_branch, project: project, name: protected_branch)
+ login_as(user)
+ end
+
+ context 'on some branch' do
+ before do
+ visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))
+ end
+
+ it 'shows blob editor with same branch' do
+ expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)))
+ expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch)
+ end
+ end
+
+ context 'with protected branch' do
+ before do
+ visit namespace_project_edit_blob_path(project.namespace, project, tree_join(protected_branch, file_path))
+ end
+
+ it 'shows blob editor with patch branch' do
+ expect(find('.js-target-branch .dropdown-toggle-text').text).to eq('patch-1')
+ end
+ end
end
- scenario 'updates content' do
- expect(page).to have_content 'successfully committed'
- expect(page).to have_content 'NextFeature'
+ context 'as master' do
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ visit namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path))
+ end
+
+ it 'shows blob editor with same branch' do
+ expect(page).to have_current_path(namespace_project_edit_blob_path(project.namespace, project, tree_join(branch, file_path)))
+ expect(find('.js-target-branch .dropdown-toggle-text').text).to eq(branch)
+ end
end
end
end
diff --git a/spec/features/projects/blobs/user_create_spec.rb b/spec/features/projects/blobs/user_create_spec.rb
index 5686868a0c4..d805450e095 100644
--- a/spec/features/projects/blobs/user_create_spec.rb
+++ b/spec/features/projects/blobs/user_create_spec.rb
@@ -1,7 +1,6 @@
require 'spec_helper'
feature 'New blob creation', feature: true, js: true do
- include WaitForAjax
include TargetBranchHelpers
given(:user) { create(:user) }
@@ -22,7 +21,7 @@ feature 'New blob creation', feature: true, js: true do
end
def commit_file
- click_button 'Commit Changes'
+ click_button 'Commit changes'
end
context 'with default target branch' do
@@ -77,7 +76,7 @@ feature 'New blob creation', feature: true, js: true do
project,
user,
start_branch: 'master',
- target_branch: 'master',
+ branch_name: 'master',
commit_message: 'Create file',
file_path: 'feature.rb',
file_content: content
@@ -87,8 +86,8 @@ feature 'New blob creation', feature: true, js: true do
end
scenario 'shows error message' do
- expect(page).to have_content('Your changes could not be committed because a file with the same name already exists')
- expect(page).to have_content('New File')
+ expect(page).to have_content('A file with this name already exists')
+ expect(page).to have_content('New file')
expect(page).to have_content('NextFeature')
end
end
diff --git a/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb
new file mode 100644
index 00000000000..c5e0a0f0517
--- /dev/null
+++ b/spec/features/projects/branches/new_branch_ref_dropdown_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe 'New Branch Ref Dropdown', :js, :feature do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:toggle) { find('.create-from .dropdown-menu-toggle') }
+
+ before do
+ project.add_master(user)
+
+ login_as(user)
+ visit new_namespace_project_branch_path(project.namespace, project)
+ end
+
+ it 'filters a list of branches and tags' do
+ toggle.click
+
+ filter_by('v1.0.0')
+
+ expect(items_count).to be(1)
+
+ filter_by('video')
+
+ expect(items_count).to be(1)
+
+ find('.create-from .dropdown-content li').click
+
+ expect(toggle).to have_content 'video'
+ end
+
+ it 'accepts a manually entered commit SHA' do
+ toggle.click
+
+ filter_by('somecommitsha')
+
+ find('.create-from input[type=search]').send_keys(:enter)
+
+ expect(toggle).to have_content 'somecommitsha'
+ end
+
+ def items_count
+ all('.create-from .dropdown-content li').length
+ end
+
+ def filter_by(filter_text)
+ fill_in 'Filter by Git revision', with: filter_text
+ end
+end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 8e0306ce83b..7668ce5f8be 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -4,7 +4,13 @@ describe 'Branches', feature: true do
let(:project) { create(:project, :public) }
let(:repository) { project.repository }
- context 'logged in' do
+ 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
login_as :user
project.team << [@user, :developer]
@@ -38,6 +44,83 @@ describe 'Branches', feature: true do
expect(find('.all-branches')).to have_selector('li', count: 1)
end
end
+
+ describe 'Delete unprotected branch' do
+ it 'removes branch after confirmation', js: true do
+ visit namespace_project_branches_path(project.namespace, 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)
+ find('.js-branch-fix .btn-remove').trigger(: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 namespace_project_protected_branches_path(project.namespace, 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 namespace_project_branches_path(project.namespace, 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
+ before do
+ login_as :user
+ project.team << [@user, :master]
+ end
+
+ describe 'Delete protected branch' do
+ before do
+ visit namespace_project_protected_branches_path(project.namespace, 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 namespace_project_branches_path(project.namespace, 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
diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb
index 2116721b224..ab10434e10c 100644
--- a/spec/features/projects/builds_spec.rb
+++ b/spec/features/projects/builds_spec.rb
@@ -205,21 +205,13 @@ feature 'Builds', :feature do
it 'loads job trace' do
expect(page).to have_content 'BUILD TRACE'
- build.append_trace(' and more trace', 11)
+ build.trace.write do |stream|
+ stream.append(' and more trace', 11)
+ end
expect(page).to have_content 'BUILD TRACE and more trace'
end
end
-
- context 'when build does not have an initial trace' do
- let(:build) { create(:ci_build, pipeline: pipeline) }
-
- it 'loads new trace' do
- build.append_trace('build trace', 0)
-
- expect(page).to have_content 'build trace'
- end
- end
end
feature 'Variables' do
@@ -390,7 +382,7 @@ feature 'Builds', :feature do
it 'sends the right headers' do
expect(page.status_code).to eq(200)
expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(page.response_headers['X-Sendfile']).to eq(build.path_to_trace)
+ expect(page.response_headers['X-Sendfile']).to eq(build.trace.send(:current_path))
end
end
@@ -409,43 +401,24 @@ feature 'Builds', :feature do
context 'storage form' do
let(:existing_file) { Tempfile.new('existing-trace-file').path }
- let(:non_existing_file) do
- file = Tempfile.new('non-existing-trace-file')
- path = file.path
- file.unlink
- path
- end
- context 'when build has trace in file' do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- build.run!
- visit namespace_project_build_path(project.namespace, project, build)
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- allow_any_instance_of(Project).to receive(:ci_id).and_return(nil)
- allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(existing_file)
- allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(non_existing_file)
+ build.run!
- page.within('.js-build-sidebar') { click_link 'Raw' }
- end
+ allow_any_instance_of(Gitlab::Ci::Trace).to receive(:paths)
+ .and_return(paths)
- 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)
- end
+ visit namespace_project_build_path(project.namespace, project, build)
end
- context 'when build has trace in old file' do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- build.run!
- visit namespace_project_build_path(project.namespace, project, build)
-
- allow_any_instance_of(Project).to receive(:ci_id).and_return(999)
- allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file)
- allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(existing_file)
+ context 'when build has trace in file' do
+ let(:paths) do
+ [existing_file]
+ end
+ before do
page.within('.js-build-sidebar') { click_link 'Raw' }
end
@@ -457,20 +430,10 @@ feature 'Builds', :feature do
end
context 'when build has trace in DB' do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- build.run!
- visit namespace_project_build_path(project.namespace, project, build)
-
- allow_any_instance_of(Project).to receive(:ci_id).and_return(nil)
- allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file)
- allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(non_existing_file)
-
- page.within('.js-build-sidebar') { click_link 'Raw' }
- end
+ let(:paths) { [] }
it 'sends the right headers' do
- expect(page.status_code).to eq(404)
+ expect(page.status_code).not_to have_link('Raw')
end
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index 0b972d2a439..fa67d390c47 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -1,5 +1,4 @@
require 'spec_helper'
-include WaitForAjax
describe 'Cherry-pick Commits' do
let(:group) { create(:group) }
@@ -75,8 +74,10 @@ describe 'Cherry-pick Commits' do
wait_for_ajax
- page.within('#modal-cherry-pick-commit .dropdown-menu .dropdown-content') do
- click_link 'feature'
+ page.within('#modal-cherry-pick-commit .dropdown-menu') do
+ find('.dropdown-input input').set('feature')
+ wait_for_ajax
+ click_link "feature"
end
page.within('#modal-cherry-pick-commit') do
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 30a2b2bcf8c..98c0f2c63b0 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -1,8 +1,6 @@
require 'rails_helper'
feature 'Mini Pipeline Graph in Commit View', :js, :feature do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index 0b997f130ea..06abfbbc86b 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Project deploy keys', feature: true do
+describe 'Project deploy keys', :js, :feature do
let(:user) { create(:user) }
let(:project) { create(:project_empty_repo) }
@@ -17,9 +17,13 @@ describe 'Project deploy keys', feature: true do
it 'removes association between project and deploy key' do
visit namespace_project_settings_repository_path(project.namespace, project)
- page.within '.deploy-keys' do
- expect { click_on 'Remove' }
- .to change { project.deploy_keys.count }.by(-1)
+ page.within(find('.deploy-keys')) do
+ expect(page).to have_selector('.deploy-keys li', count: 1)
+
+ click_on 'Remove'
+
+ expect(page).not_to have_selector('.fa-spinner', count: 0)
+ expect(page).to have_selector('.deploy-keys li', count: 0)
end
end
end
diff --git a/spec/features/projects/edit_spec.rb b/spec/features/projects/edit_spec.rb
index 7c319af893b..a263781c43c 100644
--- a/spec/features/projects/edit_spec.rb
+++ b/spec/features/projects/edit_spec.rb
@@ -1,8 +1,6 @@
require 'rails_helper'
feature 'Project edit', feature: true, js: true do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:project) { create(:project) }
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index acc3efe04e6..86ce50c976f 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -62,6 +62,8 @@ feature 'Environment', :feature do
name: 'deploy to production')
end
+ given(:role) { :master }
+
scenario 'does show a play button' do
expect(page).to have_link(action.name.humanize)
end
@@ -132,6 +134,8 @@ feature 'Environment', :feature do
on_stop: 'close_app')
end
+ given(:role) { :master }
+
scenario 'does allow to stop environment' do
click_link('Stop')
@@ -200,7 +204,7 @@ feature 'Environment', :feature do
end
scenario 'user deletes the branch with running environment' do
- visit namespace_project_branches_path(project.namespace, project)
+ visit namespace_project_branches_path(project.namespace, project, search: 'feature')
remove_branch_with_hooks(project, user, 'feature') do
page.within('.js-branch-feature') { find('a.btn-remove').click }
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 641e2cf7402..cf393afccbb 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -23,6 +23,46 @@ feature 'Environments page', :feature, :js do
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) }
+
+ describe 'in available tab page' do
+ it 'should show one environment' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'available')
+ expect(page).to have_css('.environments-container')
+ expect(page.all('tbody > tr').length).to eq(1)
+ end
+ end
+
+ describe 'in stopped tab page' do
+ it 'should show no environments' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'stopped')
+ expect(page).to have_css('.environments-container')
+ expect(page).to have_content('You don\'t have any environments right now')
+ end
+ end
+ end
+
+ describe 'with one stopped environment' do
+ given(:environment) { create(:environment, project: project, state: :stopped) }
+
+ describe 'in available tab page' do
+ it 'should show no environments' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'available')
+ expect(page).to have_css('.environments-container')
+ expect(page).to have_content('You don\'t have any environments right now')
+ end
+ end
+
+ describe 'in stopped tab page' do
+ it 'should show one environment' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'stopped')
+ expect(page).to have_css('.environments-container')
+ expect(page.all('tbody > tr').length).to eq(1)
+ end
+ end
+ end
end
context 'without environments' do
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 9079350186d..4533a6fb144 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -1,9 +1,6 @@
require 'spec_helper'
-include WaitForAjax
describe 'Edit Project Settings', feature: true do
- include WaitForAjax
-
let(:member) { create(:user) }
let!(:project) { create(:project, :public, path: 'gitlab', name: 'sample') }
let!(:issue) { create(:issue, project: project) }
@@ -71,20 +68,23 @@ describe 'Edit Project Settings', feature: true do
end
describe 'project features visibility pages' do
- before do
- @tools =
- {
- builds: namespace_project_pipelines_path(project.namespace, project),
- issues: namespace_project_issues_path(project.namespace, project),
- wiki: namespace_project_wiki_path(project.namespace, project, :home),
- snippets: namespace_project_snippets_path(project.namespace, project),
- merge_requests: namespace_project_merge_requests_path(project.namespace, project),
- }
+ let(:tools) do
+ {
+ builds: namespace_project_pipelines_path(project.namespace, project),
+ issues: namespace_project_issues_path(project.namespace, project),
+ wiki: namespace_project_wiki_path(project.namespace, project, :home),
+ snippets: namespace_project_snippets_path(project.namespace, project),
+ merge_requests: namespace_project_merge_requests_path(project.namespace, project)
+ }
end
context 'normal user' do
+ before do
+ login_as(member)
+ end
+
it 'renders 200 if tool is enabled' do
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::ENABLED)
visit url
expect(page.status_code).to eq(200)
@@ -92,7 +92,7 @@ describe 'Edit Project Settings', feature: true do
end
it 'renders 404 if feature is disabled' do
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED)
visit url
expect(page.status_code).to eq(404)
@@ -102,21 +102,21 @@ describe 'Edit Project Settings', feature: true do
it 'renders 404 if feature is enabled only for team members' do
project.team.truncate
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
visit url
expect(page.status_code).to eq(404)
end
end
- it 'renders 200 if users is member of group' do
+ it 'renders 200 if user is member of group' do
group = create(:group)
project.group = group
project.save
group.add_owner(member)
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
visit url
expect(page.status_code).to eq(200)
@@ -131,7 +131,7 @@ describe 'Edit Project Settings', feature: true do
end
it 'renders 404 if feature is disabled' do
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED)
visit url
expect(page.status_code).to eq(404)
@@ -141,7 +141,7 @@ describe 'Edit Project Settings', feature: true do
it 'renders 200 if feature is enabled only for team members' do
project.team.truncate
- @tools.each do |method_name, url|
+ tools.each do |method_name, url|
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
visit url
expect(page.status_code).to eq(200)
diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb
index d281043caa3..4166aec1956 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', feature: true do
+feature 'user browses project', feature: true, js: true do
let(:project) { create(:project) }
let(:user) { create(:user) }
@@ -13,7 +13,7 @@ feature 'user browses project', feature: true do
scenario "can see blame of '.gitignore'" do
click_link ".gitignore"
click_link 'Blame'
-
+
expect(page).to have_content "*.rb"
expect(page).to have_content "Dmitriy Zaporozhets"
expect(page).to have_content "Initial commit"
@@ -24,10 +24,23 @@ feature 'user browses project', feature: true do
click_link 'files'
click_link 'lfs'
click_link 'lfs_object.iso'
+ wait_for_ajax
expect(page).not_to have_content 'Download (1.5 MB)'
expect(page).to have_content 'version https://git-lfs.github.com/spec/v1'
expect(page).to have_content 'oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897'
expect(page).to have_content 'size 1575078'
end
+
+ scenario 'can see last commit for current directory' do
+ last_commit = project.repository.last_commit_for_path(project.default_branch, 'files')
+
+ click_link 'files'
+ wait_for_ajax
+
+ page.within('.blob-commit-info') do
+ expect(page).to have_content last_commit.short_id
+ expect(page).to have_content last_commit.author_name
+ end
+ end
end
diff --git a/spec/features/projects/files/creating_a_file_spec.rb b/spec/features/projects/files/creating_a_file_spec.rb
index ae448706130..69744ac3948 100644
--- a/spec/features/projects/files/creating_a_file_spec.rb
+++ b/spec/features/projects/files/creating_a_file_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'User wants to create a file', feature: true do
- include WaitForAjax
-
let(:project) { create(:project) }
let(:user) { create(:user) }
@@ -19,7 +17,7 @@ feature 'User wants to create a file', feature: true do
file_content = find('#file-content')
file_content.set options[:file_content] || 'Some content'
- click_button 'Commit Changes'
+ click_button 'Commit changes'
end
scenario 'file name contains Chinese characters' do
@@ -29,16 +27,16 @@ feature 'User wants to create a file', feature: true do
scenario 'directory name contains Chinese characters' do
submit_new_file(file_name: '中文/测试.md')
- expect(page).to have_content 'The file has been successfully created.'
+ expect(page).to have_content 'The file has been successfully created'
end
scenario 'file name contains invalid characters' do
submit_new_file(file_name: '\\')
- expect(page).to have_content 'Your changes could not be committed, because the file name can contain only'
+ expect(page).to have_content 'Path can contain only'
end
scenario 'file name contains directory traversal' do
submit_new_file(file_name: '../README.md')
- expect(page).to have_content 'Your changes could not be committed, because the file name cannot include directory traversal.'
+ expect(page).to have_content 'Path cannot include directory traversal'
end
end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index 32f33a3ca97..548131c7cd4 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -1,13 +1,14 @@
require 'spec_helper'
+require 'fileutils'
feature 'User wants to add a Dockerfile file', feature: true do
- include WaitForAjax
-
before do
user = create(:user)
project = create(:project)
project.team << [user, :master]
+
login_as user
+
visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'Dockerfile')
end
@@ -17,11 +18,14 @@ feature 'User wants to add a Dockerfile file', feature: true do
scenario 'user can pick a Dockerfile file from the dropdown', js: true do
find('.js-dockerfile-selector').click
+
wait_for_ajax
+
within '.dockerfile-selector' do
find('.dropdown-input-field').set('HTTPd')
find('.dropdown-content li', text: 'HTTPd').click
end
+
wait_for_ajax
expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'HTTPd')
diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb
index 36a80d7575d..7a3afafec29 100644
--- a/spec/features/projects/files/editing_a_file_spec.rb
+++ b/spec/features/projects/files/editing_a_file_spec.rb
@@ -1,14 +1,12 @@
require 'spec_helper'
feature 'User wants to edit a file', feature: true do
- include WaitForAjax
-
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:commit_params) do
{
start_branch: project.default_branch,
- target_branch: project.default_branch,
+ branch_name: project.default_branch,
commit_message: "Committing First Update",
file_path: ".gitignore",
file_content: "First Update",
@@ -27,7 +25,7 @@ feature 'User wants to edit a file', feature: true do
scenario 'file has been updated since the user opened the edit page' do
Files::UpdateService.new(project, user, commit_params).execute
- click_button 'Commit Changes'
+ click_button 'Commit changes'
expect(page).to have_content 'Someone edited the file the same time you did.'
end
diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
index 10b91d8990b..5c8105de4cb 100644
--- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
+++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'User views files page', feature: true do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:project) { create(:forked_project_with_submodules) }
diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb
index 582349d8d5b..e7a6749d8ac 100644
--- a/spec/features/projects/files/find_file_keyboard_spec.rb
+++ b/spec/features/projects/files/find_file_keyboard_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'Find file keyboard shortcuts', feature: true, js: true do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:project) { create(:project) }
diff --git a/spec/features/projects/files/find_files_spec.rb b/spec/features/projects/files/find_files_spec.rb
new file mode 100644
index 00000000000..716b7591b95
--- /dev/null
+++ b/spec/features/projects/files/find_files_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+feature 'Find files button in the tree header', feature: true do
+ given(:user) { create(:user) }
+ given(:project) { create(:project) }
+
+ background do
+ login_as(user)
+ project.team << [user, :developer]
+ end
+
+ scenario 'project main screen' do
+ visit namespace_project_path(
+ project.namespace,
+ project
+ )
+
+ expect(page).to have_selector('.tree-controls .shortcuts-find-file')
+ end
+
+ scenario 'project tree screen' do
+ visit namespace_project_tree_path(
+ project.namespace,
+ project,
+ project.default_branch
+ )
+
+ expect(page).to have_selector('.tree-controls .shortcuts-find-file')
+ end
+end
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index 9ebef505b92..e59428f8b24 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'User wants to add a .gitignore file', feature: true do
- include WaitForAjax
-
before do
user = create(:user)
project = create(:project)
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 fca40f68b01..85b66b93fba 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'User wants to add a .gitlab-ci.yml file', feature: true do
- include WaitForAjax
-
before do
user = create(:user)
project = create(:project)
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 ccadc936567..249830921ac 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,8 +1,6 @@
require 'spec_helper'
feature 'project owner creates a license file', feature: true, js: true do
- include WaitForAjax
-
let(:project_master) { create(:user) }
let(:project) { create(:project) }
background do
@@ -29,7 +27,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
- click_button 'Commit Changes'
+ click_button 'Commit changes'
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
@@ -40,7 +38,7 @@ feature 'project owner creates a license file', feature: true, js: true do
scenario 'project master creates a license file from the "Add license" link' do
click_link 'Add License'
- expect(page).to have_content('New File')
+ expect(page).to have_content('New file')
expect(current_path).to eq(
namespace_project_new_blob_path(project.namespace, project, 'master'))
expect(find('#file_name').value).to eq('LICENSE')
@@ -53,7 +51,7 @@ feature 'project owner creates a license file', feature: true, js: true do
expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
- click_button 'Commit Changes'
+ click_button 'Commit changes'
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
@@ -63,7 +61,7 @@ feature 'project owner creates a license file', feature: true, js: true do
def select_template(template)
page.within('.js-license-selector-wrap') do
- click_button 'Choose a License template'
+ click_button 'Apply a license template'
click_link template
wait_for_ajax
end
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 420db962318..70a41886985 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,8 +1,6 @@
require 'spec_helper'
feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do
- include WaitForAjax
-
let(:project_master) { create(:user) }
let(:project) { create(:empty_project) }
background do
@@ -14,7 +12,7 @@ feature 'project owner sees a link to create a license file in empty project', f
visit namespace_project_path(project.namespace, project)
click_link 'Create empty bare repository'
click_on 'LICENSE'
- expect(page).to have_content('New File')
+ expect(page).to have_content('New file')
expect(current_path).to eq(
namespace_project_new_blob_path(project.namespace, project, 'master'))
@@ -30,7 +28,7 @@ feature 'project owner sees a link to create a license file in empty project', f
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
# Remove pre-receive hook so we can push without auth
FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
- click_button 'Commit Changes'
+ click_button 'Commit changes'
expect(current_path).to eq(
namespace_project_blob_path(project.namespace, project, 'master/LICENSE'))
@@ -40,7 +38,7 @@ feature 'project owner sees a link to create a license file in empty project', f
def select_template(template)
page.within('.js-license-selector-wrap') do
- click_button 'Choose a License template'
+ click_button 'Apply a license template'
click_link template
wait_for_ajax
end
diff --git a/spec/features/projects/files/template_type_dropdown_spec.rb b/spec/features/projects/files/template_type_dropdown_spec.rb
new file mode 100644
index 00000000000..9fcf12e6cb9
--- /dev/null
+++ b/spec/features/projects/files/template_type_dropdown_spec.rb
@@ -0,0 +1,135 @@
+require 'spec_helper'
+
+feature 'Template type dropdown selector', js: true do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ login_as user
+ end
+
+ context 'editing a non-matching file' do
+ before do
+ create_and_edit_file('.random-file.js')
+ end
+
+ scenario 'not displayed' do
+ check_type_selector_display(false)
+ end
+
+ scenario 'selects every template type correctly' do
+ fill_in 'file_path', with: '.gitignore'
+ try_selecting_all_types
+ end
+
+ scenario 'updates toggle value when input matches' do
+ fill_in 'file_path', with: '.gitignore'
+ check_type_selector_toggle_text('.gitignore')
+ end
+ end
+
+ context 'editing a matching file' do
+ before do
+ visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, 'LICENSE'))
+ end
+
+ scenario 'displayed' do
+ check_type_selector_display(true)
+ end
+
+ scenario 'is displayed when input matches' do
+ check_type_selector_display(true)
+ end
+
+ scenario 'selects every template type correctly' do
+ try_selecting_all_types
+ end
+
+ context 'user previews changes' do
+ before do
+ click_link 'Preview changes'
+ end
+
+ scenario 'type selector is hidden and shown correctly' do
+ check_type_selector_display(false)
+ click_link 'Write'
+ check_type_selector_display(true)
+ end
+ end
+ end
+
+ context 'creating a matching file' do
+ before do
+ visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: '.gitignore')
+ end
+
+ scenario 'is displayed' do
+ check_type_selector_display(true)
+ end
+
+ scenario 'toggle is set to the correct value' do
+ check_type_selector_toggle_text('.gitignore')
+ end
+
+ scenario 'selects every template type correctly' do
+ try_selecting_all_types
+ end
+ end
+
+ context 'creating a file' do
+ before do
+ visit namespace_project_new_blob_path(project.namespace, project, project.default_branch)
+ end
+
+ scenario 'type selector is shown' do
+ check_type_selector_display(true)
+ end
+
+ scenario 'toggle is set to the proper value' do
+ check_type_selector_toggle_text('Choose type')
+ end
+
+ scenario 'selects every template type correctly' do
+ try_selecting_all_types
+ end
+ end
+end
+
+def check_type_selector_display(is_visible)
+ count = is_visible ? 1 : 0
+ expect(page).to have_css('.js-template-type-selector', count: count)
+end
+
+def try_selecting_all_types
+ try_selecting_template_type('LICENSE', 'Apply a license template')
+ try_selecting_template_type('Dockerfile', 'Apply a Dockerfile template')
+ try_selecting_template_type('.gitlab-ci.yml', 'Apply a GitLab CI Yaml template')
+ try_selecting_template_type('.gitignore', 'Apply a .gitignore template')
+end
+
+def try_selecting_template_type(template_type, selector_label)
+ select_template_type(template_type)
+ check_template_selector_display(selector_label)
+ check_type_selector_toggle_text(template_type)
+end
+
+def select_template_type(template_type)
+ find('.js-template-type-selector').click
+ find('.dropdown-content li', text: template_type).click
+end
+
+def check_template_selector_display(content)
+ expect(page).to have_content(content)
+end
+
+def check_type_selector_toggle_text(template_type)
+ dropdown_toggle_button = find('.template-type-selector .dropdown-toggle-text')
+ expect(dropdown_toggle_button).to have_content(template_type)
+end
+
+def create_and_edit_file(file_name)
+ visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: file_name)
+ click_button "Commit changes"
+ visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, file_name))
+end
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
new file mode 100644
index 00000000000..cd3af0b7d29
--- /dev/null
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -0,0 +1,66 @@
+require 'spec_helper'
+
+feature 'Template Undo Button', js: true do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ login_as user
+ end
+
+ context 'editing a matching file and applying a template' do
+ before do
+ visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, "LICENSE"))
+ select_file_template('.js-license-selector', 'Apache License 2.0')
+ end
+
+ scenario 'reverts template application' do
+ try_template_undo('http://www.apache.org/licenses/', 'Apply a license template')
+ end
+ end
+
+ context 'creating a non-matching file' do
+ before do
+ visit namespace_project_new_blob_path(project.namespace, project, 'master')
+ select_file_template_type('LICENSE')
+ select_file_template('.js-license-selector', 'Apache License 2.0')
+ end
+
+ scenario 'reverts template application' do
+ try_template_undo('http://www.apache.org/licenses/', 'Apply a license template')
+ end
+ end
+end
+
+def try_template_undo(template_content, toggle_text)
+ check_undo_button_display
+ check_content_reverted(template_content)
+ check_toggle_text_set(toggle_text)
+end
+
+def check_toggle_text_set(neutral_toggle_text)
+ expect(page).to have_content(neutral_toggle_text)
+end
+
+def check_undo_button_display
+ expect(page).to have_content('Template applied')
+ expect(page).to have_css('.template-selectors-undo-menu .btn-info')
+end
+
+def check_content_reverted(template_content)
+ find('.template-selectors-undo-menu .btn-info').click
+ expect(page).not_to have_content(template_content)
+ expect(find('.template-type-selector .dropdown-toggle-text')).to have_content()
+end
+
+def select_file_template(template_selector_selector, template_name)
+ find(template_selector_selector).click
+ find('.dropdown-content li', text: template_name).click
+ wait_for_ajax
+end
+
+def select_file_template_type(template_type)
+ find('.js-template-type-selector').click
+ find('.dropdown-content li', text: template_type).click
+end
diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb
index dd9622f16a0..67bc9142356 100644
--- a/spec/features/projects/gfm_autocomplete_load_spec.rb
+++ b/spec/features/projects/gfm_autocomplete_load_spec.rb
@@ -10,7 +10,7 @@ describe 'GFM autocomplete loading', feature: true, js: true do
end
it 'does not load on project#show' do
- expect(evaluate_script('gl.GfmAutoComplete.dataSources')).to eq({})
+ expect(evaluate_script('gl.GfmAutoComplete')).to eq(nil)
end
it 'loads on new issue page' do
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 2d1106ea3e8..583f479ec18 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -69,12 +69,8 @@ feature 'Import/Export - project import integration test', feature: true, js: tr
select2(namespace.id, from: '#project_namespace_id')
- # click on disabled element
- find(:link, 'GitLab export').trigger('click')
-
- page.within('.flash-container') do
- expect(page).to have_content('Please enter path and name')
- end
+ # Check for tooltip disabled import button
+ expect(find('.import_gitlab_project')['title']).to eq('Please enter a valid project name.')
end
end
diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz
index 399c1d478c5..4efd5a26a82 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 62d0aedda48..fa5e30075e3 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'issuable templates', feature: true, js: true do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
@@ -14,7 +12,7 @@ feature 'issuable templates', feature: true, js: true do
context 'user creates an issue using templates' do
let(:template_content) { 'this is a test "bug" template' }
let(:longtemplate_content) { %Q(this\n\n\n\n\nis\n\n\n\n\na\n\n\n\n\nbug\n\n\n\n\ntemplate) }
- let(:issue) { create(:issue, author: user, assignee: user, project: project) }
+ let(:issue) { create(:issue, author: user, assignees: [user], project: project) }
let(:description_addition) { ' appending to description' }
background do
@@ -74,7 +72,7 @@ feature 'issuable templates', feature: true, js: true do
context 'user creates an issue using templates, with a prior description' do
let(:prior_description) { 'test issue description' }
let(:template_content) { 'this is a test "bug" template' }
- let(:issue) { create(:issue, author: user, assignee: user, project: project) }
+ let(:issue) { create(:issue, author: user, assignees: [user], project: project) }
background do
project.repository.create_file(
@@ -163,12 +161,14 @@ feature 'issuable templates', feature: true, js: true do
end
def select_template(name)
- first('.js-issuable-selector').click
- first('.js-issuable-selector-wrap .dropdown-content a', text: name).click
+ find('.js-issuable-selector').click
+
+ find('.js-issuable-selector-wrap .dropdown-content a', text: name, match: :first).click
end
def select_option(name)
- first('.js-issuable-selector').click
- first('.js-issuable-selector-wrap .dropdown-footer-list a', text: name).click
+ find('.js-issuable-selector').click
+
+ find('.js-issuable-selector-wrap .dropdown-footer-list a', text: name, match: :first).click
end
end
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index 1e900d7e660..836f81fb16d 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -1,7 +1,6 @@
require 'spec_helper'
feature 'Prioritize labels', feature: true do
- include WaitForAjax
include DragTo
let(:user) { create(:user) }
diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb
index cffb935ad5a..ab2b089db2e 100644
--- a/spec/features/projects/members/group_links_spec.rb
+++ b/spec/features/projects/members/group_links_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
feature 'Projects > Members > Anonymous user sees members', feature: true, js: true do
- include WaitForAjax
-
let(:user) { create(:user) }
let(:group) { create(:group, :public) }
let(:project) { create(:empty_project, :public) }
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
new file mode 100644
index 00000000000..deea34214fb
--- /dev/null
+++ b/spec/features/projects/members/list_spec.rb
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+feature 'Project members list', feature: true do
+ include Select2Helper
+
+ let(:user1) { create(:user, name: 'John Doe') }
+ let(:user2) { create(:user, name: 'Mary Jane') }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, namespace: group) }
+
+ background do
+ login_as(user1)
+ group.add_owner(user1)
+ end
+
+ scenario 'show members from project and group' do
+ project.add_developer(user2)
+
+ visit_members_page
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row.text).to include(user2.name)
+ end
+
+ scenario 'show user once if member of both group and project' do
+ project.add_developer(user1)
+
+ visit_members_page
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row).to be_blank
+ end
+
+ scenario 'update user acess level', :js do
+ project.add_developer(user2)
+
+ visit_members_page
+
+ page.within(second_row) do
+ click_button('Developer')
+ click_link('Reporter')
+
+ expect(page).to have_button('Reporter')
+ end
+ end
+
+ scenario 'add user to project', :js do
+ visit_members_page
+
+ add_user(user2.id, 'Reporter')
+
+ page.within(second_row) do
+ expect(page).to have_content(user2.name)
+ expect(page).to have_button('Reporter')
+ end
+ end
+
+ scenario 'invite user to project', :js do
+ visit_members_page
+
+ add_user('test@example.com', 'Reporter')
+
+ page.within(second_row) do
+ expect(page).to have_content('test@example.com')
+ expect(page).to have_content('Invited')
+ expect(page).to have_button('Reporter')
+ end
+ end
+
+ def first_row
+ page.all('ul.content-list > li')[0]
+ end
+
+ def second_row
+ page.all('ul.content-list > li')[1]
+ end
+
+ def add_user(id, role)
+ page.within ".users-project-form" do
+ select2(id, from: "#user_ids", multiple: true)
+ select(role, from: "access_level")
+ end
+
+ click_button "Add to project"
+ end
+
+ def visit_members_page
+ visit namespace_project_settings_members_path(project.namespace, project)
+ end
+end
diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
index c3f45be6e4b..19d14ad9af4 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,7 +1,6 @@
require 'spec_helper'
feature 'Projects > Members > Master adds member with expiration date', feature: true, js: true do
- include WaitForAjax
include Select2Helper
include ActiveSupport::Testing::TimeHelpers
diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb
index c7a32a65e49..b7ae5f0b925 100644
--- a/spec/features/projects/members/sorting_spec.rb
+++ b/spec/features/projects/members/sorting_spec.rb
@@ -68,7 +68,7 @@ feature 'Projects > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
end
- scenario 'sorts by recent sign in' do
+ scenario 'sorts by recent sign in', :redis do
visit_members_list(sort: :recent_sign_in)
expect(first_member).to include(master.name)
@@ -76,7 +76,7 @@ feature 'Projects > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
end
- scenario 'sorts by oldest sign in' do
+ scenario 'sorts by oldest sign in', :redis do
visit_members_list(sort: :oldest_sign_in)
expect(first_member).to include(developer.name)
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index de25d45f447..1bf8f710b9f 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -31,6 +31,17 @@ feature 'Projects > Members > User requests access', feature: true do
expect(page).not_to have_content 'Leave Project'
end
+ context 'code access is restricted' do
+ scenario 'user can request access' do
+ project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE,
+ builds_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE)
+ visit namespace_project_path(project.namespace, project)
+
+ expect(page).to have_content 'Request Access'
+ end
+ end
+
scenario 'user is not listed in the project members page' do
click_link 'Request Access'
diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb
index b6728960fb8..1370ab1c521 100644
--- a/spec/features/projects/merge_request_button_spec.rb
+++ b/spec/features/projects/merge_request_button_spec.rb
@@ -1,13 +1,13 @@
require 'spec_helper'
feature 'Merge Request button', feature: true do
- shared_examples 'Merge Request button only shown when allowed' do
+ shared_examples 'Merge request button only shown when allowed' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
let(:forked_project) { create(:project, :public, forked_from_project: project) }
context 'not logged in' do
- it 'does not show Create Merge Request button' do
+ it 'does not show Create merge request button' do
visit url
within("#content-body") do
@@ -22,7 +22,7 @@ feature 'Merge Request button', feature: true do
project.team << [user, :developer]
end
- it 'shows Create Merge Request button' do
+ it 'shows Create merge request button' do
href = new_namespace_project_merge_request_path(project.namespace,
project,
merge_request: { source_branch: 'feature',
@@ -40,7 +40,7 @@ feature 'Merge Request button', feature: true do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
end
- it 'does not show Create Merge Request button' do
+ it 'does not show Create merge request button' do
visit url
within("#content-body") do
@@ -55,7 +55,7 @@ feature 'Merge Request button', feature: true do
login_as(user)
end
- it 'does not show Create Merge Request button' do
+ it 'does not show Create merge request button' do
visit url
within("#content-body") do
@@ -66,7 +66,7 @@ feature 'Merge Request button', feature: true do
context 'on own fork of project' do
let(:user) { forked_project.owner }
- it 'shows Create Merge Request button' do
+ it 'shows Create merge request button' do
href = new_namespace_project_merge_request_path(forked_project.namespace,
forked_project,
merge_request: { source_branch: 'feature',
@@ -83,24 +83,24 @@ feature 'Merge Request button', feature: true do
end
context 'on branches page' do
- it_behaves_like 'Merge Request button only shown when allowed' do
- let(:label) { 'Merge Request' }
- let(:url) { namespace_project_branches_path(project.namespace, project) }
- let(:fork_url) { namespace_project_branches_path(forked_project.namespace, forked_project) }
+ it_behaves_like 'Merge request button only shown when allowed' do
+ let(:label) { 'Merge request' }
+ let(:url) { namespace_project_branches_path(project.namespace, project, search: 'feature') }
+ let(:fork_url) { namespace_project_branches_path(forked_project.namespace, forked_project, search: 'feature') }
end
end
context 'on compare page' do
- it_behaves_like 'Merge Request button only shown when allowed' do
- let(:label) { 'Create Merge Request' }
+ it_behaves_like 'Merge request button only shown when allowed' do
+ let(:label) { 'Create merge request' }
let(:url) { namespace_project_compare_path(project.namespace, project, from: 'master', to: 'feature') }
let(:fork_url) { namespace_project_compare_path(forked_project.namespace, forked_project, from: 'master', to: 'feature') }
end
end
context 'on commits page' do
- it_behaves_like 'Merge Request button only shown when allowed' do
- let(:label) { 'Create Merge Request' }
+ it_behaves_like 'Merge request button only shown when allowed' do
+ let(:label) { 'Create merge request' }
let(:url) { namespace_project_commits_path(project.namespace, project, 'feature') }
let(:fork_url) { namespace_project_commits_path(forked_project.namespace, forked_project, 'feature') }
end
diff --git a/spec/features/projects/merge_requests/list_spec.rb b/spec/features/projects/merge_requests/list_spec.rb
index 5dd58ad66a7..7e8a796c55d 100644
--- a/spec/features/projects/merge_requests/list_spec.rb
+++ b/spec/features/projects/merge_requests/list_spec.rb
@@ -17,4 +17,28 @@ feature 'Merge Requests List' do
expect(page).not_to have_selector('.js-new-board-list')
end
+
+ it 'should show an empty state' do
+ visit namespace_project_merge_requests_path(project.namespace, project)
+
+ expect(page).to have_selector('.empty-state')
+ end
+
+ it 'empty state should have a create merge request button' do
+ visit namespace_project_merge_requests_path(project.namespace, project)
+
+ expect(page).to have_link 'New merge request', href: new_namespace_project_merge_request_path(project.namespace, project)
+ end
+
+ context 'if there are merge requests' do
+ before do
+ create(:merge_request, assignee: user, source_project: project)
+
+ visit namespace_project_merge_requests_path(project.namespace, project)
+ end
+
+ it 'should not show an empty state' do
+ expect(page).not_to have_selector('.empty-state')
+ end
+ end
end
diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb
index dab78fd3571..b4fc0edbde8 100644
--- a/spec/features/projects/milestones/milestone_spec.rb
+++ b/spec/features/projects/milestones/milestone_spec.rb
@@ -63,4 +63,27 @@ feature 'Project milestone', :feature do
expect(page).not_to have_content('Assign some issues to this milestone.')
end
end
+
+ context 'when project has an issue' do
+ before do
+ create(:issue, project: project, milestone: milestone)
+
+ visit namespace_project_milestone_path(project.namespace, project, milestone)
+ end
+
+ describe 'the collapsed sidebar' do
+ before do
+ find('.milestone-sidebar .gutter-toggle').click
+ end
+
+ it 'shows the total MR and issue counts' do
+ find('.milestone-sidebar .block', match: :first)
+
+ aggregate_failures 'MR and issue blocks' do
+ expect(find('.milestone-sidebar .block.issues')).to have_content 1
+ expect(find('.milestone-sidebar .block.merge-requests')).to have_content 0
+ end
+ end
+ end
+ end
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index 52196ce49bd..c66b9a34b86 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -71,6 +71,22 @@ feature "New project", feature: true do
end
end
end
+
+ context "with subgroup namespace" do
+ let(:group) { create(:group, :private, owner: user) }
+ let(:subgroup) { create(:group, parent: group) }
+
+ before do
+ group.add_master(user)
+ visit new_project_path(namespace_id: subgroup.id)
+ end
+
+ it "selects the group namespace" do
+ namespace = find("#project_namespace_id option[selected]")
+
+ expect(namespace.text).to eq subgroup.full_path
+ end
+ end
end
context 'Import project options' do
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
new file mode 100644
index 00000000000..1211b17b3d8
--- /dev/null
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -0,0 +1,146 @@
+require 'spec_helper'
+
+feature 'Pipeline Schedules', :feature do
+ include PipelineSchedulesHelper
+ include WaitForAjax
+
+ let!(:project) { create(:project) }
+ let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
+ let!(:pipeline) { create(:ci_pipeline, pipeline_schedule: pipeline_schedule) }
+ let(:scope) { nil }
+ let!(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+
+ login_as(user)
+ visit_page
+ end
+
+ describe 'GET /projects/pipeline_schedules' do
+ let(:visit_page) { visit_pipelines_schedules }
+
+ it 'avoids N + 1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count
+
+ create_list(:ci_pipeline_schedule, 2, project: project)
+
+ expect { visit_pipelines_schedules }.not_to exceed_query_limit(control_count)
+ end
+
+ describe 'The view' do
+ it 'displays the required information description' do
+ page.within('.pipeline-schedule-table-row') do
+ expect(page).to have_content('pipeline schedule')
+ expect(page).to have_link('master')
+ expect(page).to have_link("##{pipeline.id}")
+ end
+ end
+
+ it 'creates a new scheduled pipeline' do
+ click_link 'New schedule'
+
+ expect(page).to have_content('Schedule a new pipeline')
+ end
+
+ it 'changes ownership of the pipeline' do
+ click_link 'Take ownership'
+ page.within('.pipeline-schedule-table-row') do
+ expect(page).not_to have_content('No owner')
+ expect(page).to have_link('John Doe')
+ end
+ end
+
+ it 'edits the pipeline' do
+ page.within('.pipeline-schedule-table-row') do
+ click_link 'Edit'
+ end
+
+ expect(page).to have_content('Edit Pipeline Schedule')
+ end
+
+ it 'deletes the pipeline' do
+ click_link 'Delete'
+
+ expect(page).not_to have_content('pipeline schedule')
+ end
+ end
+ end
+
+ describe 'POST /projects/pipeline_schedules/new', js: true do
+ let(:visit_page) { visit_new_pipeline_schedule }
+
+ it 'sets defaults for timezone and target branch' do
+ expect(page).to have_button('master')
+ expect(page).to have_button('UTC')
+ end
+
+ it 'it creates a new scheduled pipeline' do
+ fill_in_schedule_form
+ save_pipeline_schedule
+
+ expect(page).to have_content('my fancy description')
+ end
+
+ it 'it prevents an invalid form from being submitted' do
+ save_pipeline_schedule
+
+ expect(page).to have_content('This field is required')
+ end
+ end
+
+ describe 'PATCH /projects/pipelines_schedules/:id/edit', js: true do
+ let(:visit_page) do
+ edit_pipeline_schedule
+ end
+
+ it 'it displays existing properties' do
+ description = find_field('schedule_description').value
+ expect(description).to eq('pipeline schedule')
+ expect(page).to have_button('master')
+ expect(page).to have_button('UTC')
+ end
+
+ it 'edits the scheduled pipeline' do
+ fill_in 'schedule_description', with: 'my brand new description'
+
+ save_pipeline_schedule
+
+ expect(page).to have_content('my brand new description')
+ end
+ end
+
+ def visit_new_pipeline_schedule
+ visit new_namespace_project_pipeline_schedule_path(project.namespace, project, pipeline_schedule)
+ end
+
+ def edit_pipeline_schedule
+ visit edit_namespace_project_pipeline_schedule_path(project.namespace, project, pipeline_schedule)
+ end
+
+ def visit_pipelines_schedules
+ visit namespace_project_pipeline_schedules_path(project.namespace, project, scope: scope)
+ end
+
+ def select_timezone
+ find('.js-timezone-dropdown').click
+ click_link 'American Samoa'
+ end
+
+ def select_target_branch
+ find('.js-target-branch-dropdown').click
+ click_link 'master'
+ end
+
+ def save_pipeline_schedule
+ click_button 'Save pipeline schedule'
+ end
+
+ def fill_in_schedule_form
+ fill_in 'schedule_description', with: 'my fancy description'
+ fill_in 'schedule_cron', with: '* 1 2 3 4'
+
+ select_timezone
+ select_target_branch
+ end
+end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 5a53e48f5f8..cfac54ef259 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -254,4 +254,57 @@ describe 'Pipeline', :feature, :js do
it { expect(build_manual.reload).to be_pending }
end
end
+
+ describe 'GET /:project/pipelines/:id/failures' do
+ let(:project) { create(:project) }
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
+ let(:pipeline_failures_page) { failures_namespace_project_pipeline_path(project.namespace, project, pipeline) }
+ let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) }
+
+ context 'with failed build' do
+ before do
+ failed_build.trace.set('4 examples, 1 failure')
+
+ visit pipeline_failures_page
+ end
+
+ it 'shows jobs tab pane as active' do
+ expect(page).to have_content('Failed Jobs')
+ expect(page).to have_css('#js-tab-failures.active')
+ end
+
+ it 'lists failed builds' do
+ expect(page).to have_content(failed_build.name)
+ expect(page).to have_content(failed_build.stage)
+ end
+
+ it 'shows build failure logs' do
+ expect(page).to have_content('4 examples, 1 failure')
+ end
+ end
+
+ context 'when missing build logs' do
+ before do
+ visit pipeline_failures_page
+ end
+
+ it 'includes failed jobs' do
+ expect(page).to have_content('No job trace')
+ end
+ end
+
+ context 'without failures' do
+ before do
+ failed_build.update!(status: :success)
+
+ visit pipeline_failures_page
+ end
+
+ it 'displays the pipeline graph' do
+ expect(current_path).to eq(pipeline_path(pipeline))
+ expect(page).not_to have_content('Failed Jobs')
+ expect(page).to have_selector('.pipeline-visualization')
+ end
+ end
+ end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 2272b19bc8f..5f82cf2f5e5 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -22,7 +22,7 @@ describe 'Pipelines', :feature, :js do
project: project,
ref: 'master',
status: 'running',
- sha: project.commit.id,
+ sha: project.commit.id
)
end
@@ -370,6 +370,58 @@ describe 'Pipelines', :feature, :js do
end
end
+ describe 'GET /:project/pipelines/show' do
+ let(:project) { create(:project) }
+
+ let(:pipeline) do
+ create(:ci_empty_pipeline,
+ project: project,
+ sha: project.commit.id,
+ user: user)
+ end
+
+ before do
+ create_build('build', 0, 'build', :success)
+ create_build('test', 1, 'rspec 0:2', :pending)
+ create_build('test', 1, 'rspec 1:2', :running)
+ create_build('test', 1, 'spinach 0:2', :created)
+ create_build('test', 1, 'spinach 1:2', :created)
+ create_build('test', 1, 'audit', :created)
+ create_build('deploy', 2, 'production', :created)
+
+ create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3)
+
+ visit namespace_project_pipeline_path(project.namespace, project, pipeline)
+ wait_for_vue_resource
+ end
+
+ it 'shows a graph with grouped stages' do
+ expect(page).to have_css('.js-pipeline-graph')
+
+ # header
+ expect(page).to have_text("##{pipeline.id}")
+ expect(page).to have_selector(%Q(img[alt$="#{pipeline.user.name}'s avatar"]))
+ expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user))
+
+ # stages
+ expect(page).to have_text('Build')
+ expect(page).to have_text('Test')
+ expect(page).to have_text('Deploy')
+ expect(page).to have_text('External')
+
+ # builds
+ expect(page).to have_text('rspec')
+ expect(page).to have_text('spinach')
+ expect(page).to have_text('rspec')
+ expect(page).to have_text('production')
+ expect(page).to have_text('jenkins')
+ end
+
+ def create_build(stage, stage_idx, name, status)
+ create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name, status: status)
+ end
+ end
+
describe 'POST /:project/pipelines' do
let(:project) { create(:project) }
diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb
index 5d0314d5c09..11dcab4d737 100644
--- a/spec/features/projects/project_settings_spec.rb
+++ b/spec/features/projects/project_settings_spec.rb
@@ -1,64 +1,158 @@
require 'spec_helper'
describe 'Edit Project Settings', feature: true do
+ include Select2Helper
+
let(:user) { create(:user) }
- let(:project) { create(:empty_project, path: 'gitlab', name: 'sample') }
+ let(:project) { create(:empty_project, namespace: user.namespace, path: 'gitlab', name: 'sample') }
before do
login_as(user)
- project.team << [user, :master]
end
- describe 'Project settings', js: true do
+ describe 'Project settings section', js: true do
it 'shows errors for invalid project name' do
visit edit_namespace_project_path(project.namespace, project)
-
fill_in 'project_name_edit', with: 'foo&bar'
-
click_button 'Save changes'
-
expect(page).to have_field 'project_name_edit', with: 'foo&bar'
expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'."
expect(page).to have_button 'Save changes'
end
- scenario 'shows a successful notice when the project is updated' do
+ it 'shows a successful notice when the project is updated' do
visit edit_namespace_project_path(project.namespace, project)
-
fill_in 'project_name_edit', with: 'hello world'
-
click_button 'Save changes'
-
expect(page).to have_content "Project 'hello world' was successfully updated."
end
end
- describe 'Rename repository' do
- it 'shows errors for invalid project path/name' do
- visit edit_namespace_project_path(project.namespace, project)
-
- fill_in 'project_name', with: 'foo&bar'
- fill_in 'Path', with: 'foo&bar'
+ describe 'Rename repository section' do
+ context 'with invalid characters' do
+ it 'shows errors for invalid project path/name' do
+ rename_project(project, name: 'foo&bar', path: 'foo&bar')
+ expect(page).to have_field 'Project name', with: 'foo&bar'
+ expect(page).to have_field 'Path', with: 'foo&bar'
+ expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'."
+ expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"
+ end
+ end
- click_button 'Rename project'
+ context 'when changing project name' do
+ it 'renames the repository' do
+ rename_project(project, name: 'bar')
+ expect(find('h1.title')).to have_content(project.name)
+ end
+
+ context 'with emojis' do
+ it 'shows error for invalid project name' do
+ rename_project(project, name: '🚀 foo bar ☁️')
+ expect(page).to have_field 'Project name', with: '🚀 foo bar ☁️'
+ expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'."
+ end
+ end
+ end
- expect(page).to have_field 'Project name', with: 'foo&bar'
- expect(page).to have_field 'Path', with: 'foo&bar'
- expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'."
- expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"
+ context 'when changing project path' do
+ # Not using empty project because we need a repo to exist
+ let(:project) { create(:project, namespace: user.namespace, name: 'gitlabhq') }
+
+ before(:context) { TestEnv.clean_test_path }
+ after(:example) { TestEnv.clean_test_path }
+
+ specify 'the project is accessible via the new path' do
+ rename_project(project, path: 'bar')
+ new_path = namespace_project_path(project.namespace, 'bar')
+ visit new_path
+ expect(current_path).to eq(new_path)
+ expect(find('h1.title')).to have_content(project.name)
+ end
+
+ specify 'the project is accessible via a redirect from the old path' do
+ old_path = namespace_project_path(project.namespace, project)
+ rename_project(project, path: 'bar')
+ new_path = namespace_project_path(project.namespace, 'bar')
+ visit old_path
+ expect(current_path).to eq(new_path)
+ expect(find('h1.title')).to have_content(project.name)
+ end
+
+ context 'and a new project is added with the same path' do
+ it 'overrides the redirect' do
+ old_path = namespace_project_path(project.namespace, project)
+ rename_project(project, path: 'bar')
+ new_project = create(:empty_project, namespace: user.namespace, path: 'gitlabhq', name: 'quz')
+ visit old_path
+ expect(current_path).to eq(old_path)
+ expect(find('h1.title')).to have_content(new_project.name)
+ end
+ end
end
end
- describe 'Rename repository name with emojis' do
- it 'shows error for invalid project name' do
- visit edit_namespace_project_path(project.namespace, project)
-
- fill_in 'project_name', with: '🚀 foo bar ☁️'
+ describe 'Transfer project section', js: true do
+ # Not using empty project because we need a repo to exist
+ let!(:project) { create(:project, namespace: user.namespace, name: 'gitlabhq') }
+ let!(:group) { create(:group) }
+
+ before(:context) { TestEnv.clean_test_path }
+ before(:example) { group.add_owner(user) }
+ after(:example) { TestEnv.clean_test_path }
+
+ specify 'the project is accessible via the new path' do
+ transfer_project(project, group)
+ new_path = namespace_project_path(group, project)
+ visit new_path
+ expect(current_path).to eq(new_path)
+ expect(find('h1.title')).to have_content(project.name)
+ end
- click_button 'Rename project'
+ specify 'the project is accessible via a redirect from the old path' do
+ old_path = namespace_project_path(project.namespace, project)
+ transfer_project(project, group)
+ new_path = namespace_project_path(group, project)
+ visit old_path
+ expect(current_path).to eq(new_path)
+ expect(find('h1.title')).to have_content(project.name)
+ end
- expect(page).to have_field 'Project name', with: '🚀 foo bar ☁️'
- expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'."
+ context 'and a new project is added with the same path' do
+ it 'overrides the redirect' do
+ old_path = namespace_project_path(project.namespace, project)
+ transfer_project(project, group)
+ new_project = create(:empty_project, namespace: user.namespace, path: 'gitlabhq', name: 'quz')
+ visit old_path
+ expect(current_path).to eq(old_path)
+ expect(find('h1.title')).to have_content(new_project.name)
+ end
end
end
end
+
+def rename_project(project, name: nil, path: nil)
+ visit edit_namespace_project_path(project.namespace, project)
+ fill_in('project_name', with: name) if name
+ fill_in('Path', with: path) if path
+ click_button('Rename project')
+ wait_for_edit_project_page_reload
+ project.reload
+end
+
+def transfer_project(project, namespace)
+ visit edit_namespace_project_path(project.namespace, project)
+ select2(namespace.id, from: '#new_namespace_id')
+ click_button('Transfer project')
+ confirm_transfer_modal
+ wait_for_edit_project_page_reload
+ project.reload
+end
+
+def confirm_transfer_modal
+ fill_in('confirm_name_input', with: project.path)
+ click_button 'Confirm'
+end
+
+def wait_for_edit_project_page_reload
+ expect(find('.project-edit-container')).to have_content('Rename repository')
+end
diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb
index 3b8f0b2d3f8..881ad7910dd 100644
--- a/spec/features/projects/ref_switcher_spec.rb
+++ b/spec/features/projects/ref_switcher_spec.rb
@@ -1,7 +1,6 @@
require 'rails_helper'
feature 'Ref switcher', feature: true, js: true do
- include WaitForAjax
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb
new file mode 100644
index 00000000000..d3232f0cc16
--- /dev/null
+++ b/spec/features/projects/settings/integration_settings_spec.rb
@@ -0,0 +1,96 @@
+require 'spec_helper'
+
+feature 'Integration settings', feature: true do
+ let(:project) { create(:empty_project) }
+ let(:user) { create(:user) }
+ let(:role) { :developer }
+ let(:integrations_path) { namespace_project_settings_integrations_path(project.namespace, project) }
+
+ background do
+ login_as(user)
+ project.team << [user, role]
+ end
+
+ context 'for developer' do
+ given(:role) { :developer }
+
+ scenario 'to be disallowed to view' do
+ visit integrations_path
+
+ expect(page.status_code).to eq(404)
+ end
+ end
+
+ context 'for master' do
+ given(:role) { :master }
+
+ context 'Webhooks' do
+ let(:hook) { create(:project_hook, :all_events_enabled, enable_ssl_verification: true, project: project) }
+ let(:url) { generate(:url) }
+
+ scenario 'show list of webhooks' do
+ hook
+
+ visit integrations_path
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_content(hook.url)
+ expect(page).to have_content('SSL Verification: enabled')
+ expect(page).to have_content('Push Events')
+ expect(page).to have_content('Tag Push Events')
+ expect(page).to have_content('Issues Events')
+ expect(page).to have_content('Confidential Issues Events')
+ expect(page).to have_content('Note Events')
+ expect(page).to have_content('Merge Requests Events')
+ expect(page).to have_content('Pipeline Events')
+ expect(page).to have_content('Wiki Page Events')
+ end
+
+ scenario 'create webhook' do
+ visit integrations_path
+
+ fill_in 'hook_url', with: url
+ check 'Tag push events'
+ check 'Enable SSL verification'
+ check 'Job events'
+
+ click_button 'Add webhook'
+
+ expect(page).to have_content(url)
+ expect(page).to have_content('SSL Verification: enabled')
+ expect(page).to have_content('Push Events')
+ expect(page).to have_content('Tag Push Events')
+ expect(page).to have_content('Job events')
+ end
+
+ scenario 'edit existing webhook' do
+ hook
+ visit integrations_path
+
+ click_link 'Edit'
+ fill_in 'hook_url', with: url
+ check 'Enable SSL verification'
+ click_button 'Save changes'
+
+ expect(page).to have_content 'SSL Verification: enabled'
+ expect(page).to have_content(url)
+ end
+
+ scenario 'test existing webhook' do
+ WebMock.stub_request(:post, hook.url)
+ visit integrations_path
+
+ click_link 'Test'
+
+ expect(current_path).to eq(integrations_path)
+ end
+
+ scenario 'remove existing webhook' do
+ hook
+ visit integrations_path
+
+ expect { click_link 'Remove' }.to change(ProjectHook, :count).by(-1)
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index 76cb240ea98..035c57eaa47 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -32,5 +32,16 @@ feature "Pipelines settings", feature: true do
expect(page).to have_button('Save changes', disabled: false)
expect(page).to have_field('Test coverage parsing', with: 'coverage_regex')
end
+
+ scenario 'updates auto_cancel_pending_pipelines' do
+ page.check('Auto-cancel redundant, pending pipelines')
+ click_on 'Save changes'
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_button('Save changes', disabled: false)
+
+ checkbox = find_field('project_auto_cancel_pending_pipelines')
+ expect(checkbox).to be_checked
+ end
end
end
diff --git a/spec/features/projects/snippets/show_spec.rb b/spec/features/projects/snippets/show_spec.rb
new file mode 100644
index 00000000000..cedf3778c7e
--- /dev/null
+++ b/spec/features/projects/snippets/show_spec.rb
@@ -0,0 +1,144 @@
+require 'spec_helper'
+
+feature 'Project snippet', :js, feature: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:snippet) { create(:project_snippet, project: project, file_name: file_name, content: content) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+ end
+
+ context 'Ruby file' do
+ let(:file_name) { 'popen.rb' }
+ let(:content) { project.repository.blob_at('master', 'files/ruby/popen.rb').data }
+
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'Markdown file' do
+ let(:file_name) { 'ruby-style-guide.md' }
+ let(:content) { project.repository.blob_at('master', 'files/markdown/ruby-style-guide.md').data }
+
+ context 'visiting directly' do
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet)
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+
+ # shows a raw button
+ expect(page).to have_link('Open raw')
+
+ # shows a download button
+ expect(page).to have_link('Download')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+ end
+
+ context 'visiting with a line number anchor' do
+ before do
+ visit namespace_project_snippet_path(project.namespace, project, snippet, anchor: 'L1')
+
+ wait_for_ajax
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
+
+ # highlights the line in question
+ expect(page).to have_selector('#LC1.hll')
+
+ # shows highlighted Markdown code
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/snippets_spec.rb b/spec/features/projects/snippets_spec.rb
index d37e8ed4699..18689c17fe9 100644
--- a/spec/features/projects/snippets_spec.rb
+++ b/spec/features/projects/snippets_spec.rb
@@ -4,11 +4,27 @@ describe 'Project snippets', feature: true do
context 'when the project has snippets' do
let(:project) { create(:empty_project, :public) }
let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) }
- before do
- allow(Snippet).to receive(:default_per_page).and_return(1)
- visit namespace_project_snippets_path(project.namespace, project)
+ let!(:other_snippet) { create(:project_snippet) }
+
+ context 'pagination' do
+ before do
+ allow(Snippet).to receive(:default_per_page).and_return(1)
+
+ visit namespace_project_snippets_path(project.namespace, project)
+ end
+
+ it_behaves_like 'paginated snippets'
end
- it_behaves_like 'paginated snippets'
+ context 'list content' do
+ it 'contains all project snippets' do
+ visit namespace_project_snippets_path(project.namespace, project)
+
+ expect(page).to have_selector('.snippet-row', count: 2)
+
+ expect(page).to have_content(snippets[0].title)
+ expect(page).to have_content(snippets[1].title)
+ end
+ end
end
end
diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb
index 2065abfb248..5dfdc465d7d 100644
--- a/spec/features/projects/user_create_dir_spec.rb
+++ b/spec/features/projects/user_create_dir_spec.rb
@@ -1,7 +1,6 @@
require 'spec_helper'
feature 'New directory creation', feature: true, js: true do
- include WaitForAjax
include TargetBranchHelpers
given(:user) { create(:user) }
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index ce5c5f21167..b7a41ca54e6 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
describe 'View on environment', js: true do
- include WaitForAjax
-
let(:branch_name) { 'feature' }
let(:file_path) { 'files/ruby/feature.rb' }
let(:project) { create(:project, :repository) }
@@ -25,7 +23,7 @@ describe 'View on environment', js: true do
project,
user,
start_branch: branch_name,
- target_branch: branch_name,
+ branch_name: branch_name,
commit_message: "Add .gitlab/route-map.yml",
file_path: '.gitlab/route-map.yml',
file_content: route_map
@@ -36,7 +34,7 @@ describe 'View on environment', js: true do
project,
user,
start_branch: branch_name,
- target_branch: branch_name,
+ branch_name: branch_name,
commit_message: "Update feature",
file_path: file_path,
file_content: "# Noop"
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
index a1c386ddc18..49d7ef09e64 100644
--- a/spec/features/projects/wiki/markdown_preview_spec.rb
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -17,19 +17,23 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t
login_as(user)
visit namespace_project_path(project.namespace, project)
- click_link 'Wiki'
+ find('.shortcuts-wiki').trigger('click')
WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
end
context "while creating a new wiki page" do
context "when there are no spaces or hyphens in the page name" do
it "rewrites relative links as expected" do
- click_link 'New Page'
- fill_in :new_wiki_path, with: 'a/b/c/d'
- click_button 'Create Page'
+ find('.add-new-wiki').trigger('click')
+ page.within '#modal-new-wiki' do
+ fill_in :new_wiki_path, with: 'a/b/c/d'
+ click_button 'Create page'
+ end
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
+ page.within '.wiki-form' do
+ fill_in :wiki_content, with: wiki_content
+ click_on "Preview"
+ end
expect(page).to have_content("regular link")
@@ -42,12 +46,16 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t
context "when there are spaces in the page name" do
it "rewrites relative links as expected" do
- click_link 'New Page'
- fill_in :new_wiki_path, with: 'a page/b page/c page/d page'
- click_button 'Create Page'
+ click_link 'New page'
+ page.within '#modal-new-wiki' do
+ fill_in :new_wiki_path, with: 'a page/b page/c page/d page'
+ click_button 'Create page'
+ end
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
+ page.within '.wiki-form' do
+ fill_in :wiki_content, with: wiki_content
+ click_on "Preview"
+ end
expect(page).to have_content("regular link")
@@ -60,12 +68,16 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t
context "when there are hyphens in the page name" do
it "rewrites relative links as expected" do
- click_link 'New Page'
- fill_in :new_wiki_path, with: 'a-page/b-page/c-page/d-page'
- click_button 'Create Page'
+ click_link 'New page'
+ page.within '#modal-new-wiki' do
+ fill_in :new_wiki_path, with: 'a-page/b-page/c-page/d-page'
+ click_button 'Create page'
+ end
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
+ page.within '.wiki-form' do
+ fill_in :wiki_content, with: wiki_content
+ click_on "Preview"
+ end
expect(page).to have_content("regular link")
@@ -79,11 +91,17 @@ feature 'Projects > Wiki > User previews markdown changes', feature: true, js: t
context "while editing a wiki page" do
def create_wiki_page(path)
- click_link 'New Page'
- fill_in :new_wiki_path, with: path
- click_button 'Create Page'
- fill_in :wiki_content, with: 'content'
- click_on "Create page"
+ find('.add-new-wiki').trigger('click')
+
+ page.within '#modal-new-wiki' do
+ fill_in :new_wiki_path, with: path
+ click_button 'Create page'
+ end
+
+ page.within '.wiki-form' do
+ fill_in :wiki_content, with: 'content'
+ click_on "Create page"
+ end
end
context "when there are no spaces or hyphens in the page name" do
diff --git a/spec/features/projects/wiki/shortcuts_spec.rb b/spec/features/projects/wiki/shortcuts_spec.rb
new file mode 100644
index 00000000000..c1f6b0cce3b
--- /dev/null
+++ b/spec/features/projects/wiki/shortcuts_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+feature 'Wiki shortcuts', :feature, :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project, namespace: user.namespace) }
+ let(:wiki_page) do
+ WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
+ end
+
+ before do
+ login_as(user)
+ visit namespace_project_wiki_path(project.namespace, project, wiki_page)
+ end
+
+ scenario 'Visit edit wiki page using "e" keyboard shortcut' do
+ find('body').native.send_key('e')
+
+ expect(find('.wiki-page-title')).to have_content('Edit Page')
+ end
+end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index fff8b9f3447..5c502ce4fb5 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Projects > Wiki > User creates wiki page', feature: true do
+feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
let(:user) { create(:user) }
background do
@@ -8,17 +8,22 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
login_as(user)
visit namespace_project_path(project.namespace, project)
- click_link 'Wiki'
+ find('.shortcuts-wiki').trigger('click')
end
context 'in the user namespace' do
let(:project) { create(:project, namespace: user.namespace) }
context 'when wiki is empty' do
+ scenario 'commit message field has value "Create home"' 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!'
- click_button 'Create page'
-
+ 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!')
@@ -32,13 +37,20 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
context 'via the "new wiki page" page' do
scenario 'when the wiki page has a single word name', js: true do
- click_link 'New Page'
+ click_link 'New page'
- 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
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ # 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
expect(page).to have_content('Foo')
expect(page).to have_content("Last edited by #{user.name}")
@@ -46,13 +58,20 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
end
scenario 'when the wiki page has spaces in the name', js: true do
- click_link 'New Page'
+ click_link 'New page'
- 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
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ # 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'
+ end
expect(page).to have_content('Spaces in the name')
expect(page).to have_content("Last edited by #{user.name}")
@@ -60,13 +79,20 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
end
scenario 'when the wiki page has hyphens in the name', js: true do
- click_link 'New Page'
+ click_link 'New page'
- 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
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ # 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'
+ end
expect(page).to have_content('Hyphens in the name')
expect(page).to have_content("Last edited by #{user.name}")
@@ -80,9 +106,15 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
let(:project) { create(:project, namespace: create(:group, :public)) }
context 'when wiki is empty' do
+ scenario 'commit message field has value "Create home"' 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!'
- click_button 'Create page'
+ 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}")
@@ -96,13 +128,20 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
end
scenario 'via the "new wiki page" page', js: true do
- click_link 'New Page'
+ click_link 'New page'
- 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
- fill_in :wiki_content, with: 'My awesome wiki!'
- click_button 'Create page'
+ # 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
expect(page).to have_content('Foo')
expect(page).to have_content("Last edited by #{user.name}")
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 aedc0333cb9..86cf520ea80 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -19,6 +19,9 @@ feature 'Projects > Wiki > User updates wiki page', feature: true do
scenario 'success when the wiki content is not empty' 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'
@@ -48,6 +51,9 @@ feature 'Projects > Wiki > User updates wiki page', feature: true do
scenario 'the home 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'