Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
commitb595cb0c1dec83de5bdee18284abe86614bed33b (patch)
tree8c3d4540f193c5ff98019352f554e921b3a41a72 /spec/features
parent2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff)
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/admin/admin_groups_spec.rb28
-rw-r--r--spec/features/admin/admin_projects_spec.rb28
-rw-r--r--spec/features/admin/admin_runners_spec.rb52
-rw-r--r--spec/features/admin/admin_sees_background_migrations_spec.rb4
-rw-r--r--spec/features/admin/admin_system_info_spec.rb6
-rw-r--r--spec/features/admin/users/user_spec.rb4
-rw-r--r--spec/features/dashboard/todos/todos_spec.rb19
-rw-r--r--spec/features/file_uploads/multipart_invalid_uploads_spec.rb2
-rw-r--r--spec/features/groups/group_runners_spec.rb44
-rw-r--r--spec/features/groups/group_settings_spec.rb4
-rw-r--r--spec/features/groups/import_export/import_file_spec.rb24
-rw-r--r--spec/features/groups/merge_requests_spec.rb2
-rw-r--r--spec/features/groups/settings/packages_and_registries_spec.rb22
-rw-r--r--spec/features/groups/settings/user_searches_in_settings_spec.rb2
-rw-r--r--spec/features/groups/show_spec.rb25
-rw-r--r--spec/features/groups_spec.rb18
-rw-r--r--spec/features/incidents/incident_details_spec.rb77
-rw-r--r--spec/features/incidents/incident_timeline_events_spec.rb70
-rw-r--r--spec/features/invites_spec.rb5
-rw-r--r--spec/features/issuables/issuable_list_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/visual_tokens_spec.rb4
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb16
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb14
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb2
-rw-r--r--spec/features/merge_request/user_creates_merge_request_spec.rb38
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb28
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb36
-rw-r--r--spec/features/milestone_spec.rb2
-rw-r--r--spec/features/monitor_sidebar_link_spec.rb5
-rw-r--r--spec/features/nav/top_nav_responsive_spec.rb2
-rw-r--r--spec/features/nav/top_nav_tooltip_spec.rb4
-rw-r--r--spec/features/profiles/account_spec.rb2
-rw-r--r--spec/features/profiles/oauth_applications_spec.rb55
-rw-r--r--spec/features/profiles/password_spec.rb2
-rw-r--r--spec/features/projects/blobs/blame_spec.rb39
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb1551
-rw-r--r--spec/features/projects/branches_spec.rb2
-rw-r--r--spec/features/projects/ci/secure_files_spec.rb4
-rw-r--r--spec/features/projects/commits/multi_view_diff_spec.rb26
-rw-r--r--spec/features/projects/deploy_keys_spec.rb26
-rw-r--r--spec/features/projects/diffs/diff_show_spec.rb4
-rw-r--r--spec/features/projects/environments_pod_logs_spec.rb68
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb2
-rw-r--r--spec/features/projects/files/gitignore_dropdown_spec.rb4
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb12
-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/jobs/permissions_spec.rb6
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb23
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb59
-rw-r--r--spec/features/projects/jobs_spec.rb76
-rw-r--r--spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb4
-rw-r--r--spec/features/projects/navbar_spec.rb18
-rw-r--r--spec/features/projects/new_project_spec.rb57
-rw-r--r--spec/features/projects/pipelines/legacy_pipelines_spec.rb4
-rw-r--r--spec/features/projects/releases/user_creates_release_spec.rb21
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb20
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb1
-rw-r--r--spec/features/projects/settings/secure_files_settings_spec.rb46
-rw-r--r--spec/features/projects/settings/secure_files_spec.rb101
-rw-r--r--spec/features/projects/settings/visibility_settings_spec.rb6
-rw-r--r--spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb2
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb47
-rw-r--r--spec/features/projects/tracings_spec.rb60
-rw-r--r--spec/features/projects_spec.rb93
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_line_permalink_updater_spec.rb103
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_show_spec.rb1201
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/edit_spec.rb213
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/shortcuts_blob_spec.rb45
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/user_creates_new_blob_in_new_project_spec.rb63
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb80
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/blobs/user_views_pipeline_editor_button_spec.rb46
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/editing_a_file_spec.rb34
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/find_file_keyboard_spec.rb42
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/project_owner_creates_license_file_spec.rb72
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_files_spec.rb377
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_lfs_files_spec.rb86
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/user_deletes_files_spec.rb74
-rw-r--r--spec/features/refactor_blob_viewer_disabled/projects/files/user_edits_files_spec.rb226
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb4
-rw-r--r--spec/features/tags/developer_updates_tag_spec.rb2
-rw-r--r--spec/features/unsubscribe_links_spec.rb2
-rw-r--r--spec/features/users/email_verification_on_login_spec.rb357
-rw-r--r--spec/features/users/google_analytics_csp_spec.rb15
-rw-r--r--spec/features/users/login_spec.rb4
-rw-r--r--spec/features/users/show_spec.rb6
91 files changed, 2067 insertions, 4037 deletions
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 2d541a34f62..040c6a65b7c 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin Groups' do
let_it_be(:user) { create :user }
let_it_be(:group) { create :group }
- let_it_be(:current_user) { create(:admin) }
+ let_it_be_with_reload(:current_user) { create(:admin) }
before do
sign_in(current_user)
@@ -231,11 +231,33 @@ RSpec.describe 'Admin Groups' do
it_behaves_like 'adds user into a group' do
let(:user_selector) { user.email }
end
+
+ context 'when membership is set to expire' do
+ it 'renders relative time' do
+ expire_time = Time.current + 2.days
+ current_user.update!(time_display_relative: true)
+ group.add_member(user, Gitlab::Access::REPORTER, expires_at: expire_time)
+
+ visit admin_group_path(group)
+
+ expect(page).to have_content(/Expires in \d day/)
+ end
+
+ it 'renders absolute time' do
+ expire_time = Time.current.tomorrow.middle_of_day
+ current_user.update!(time_display_relative: false)
+ group.add_member(user, Gitlab::Access::REPORTER, expires_at: expire_time)
+
+ visit admin_group_path(group)
+
+ expect(page).to have_content("Expires on #{expire_time.strftime('%b %-d')}")
+ end
+ end
end
describe 'add admin himself to a group' do
before do
- group.add_user(:user, Gitlab::Access::OWNER)
+ group.add_member(:user, Gitlab::Access::OWNER)
end
it 'adds admin a to a group as developer', :js do
@@ -252,7 +274,7 @@ RSpec.describe 'Admin Groups' do
describe 'admin removes themself from a group', :js do
it 'removes admin from the group' do
- group.add_user(current_user, Gitlab::Access::DEVELOPER)
+ group.add_member(current_user, Gitlab::Access::DEVELOPER)
visit group_group_members_path(group)
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index 2166edf65ff..6b147b01991 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -7,15 +7,37 @@ RSpec.describe "Admin::Projects" do
include Spec::Support::Helpers::Features::InviteMembersModalHelper
include Spec::Support::Helpers::ModalHelpers
- let(:user) { create :user }
- let(:project) { create(:project, :with_namespace_settings) }
- let(:current_user) { create(:admin) }
+ let_it_be_with_reload(:user) { create :user }
+ let_it_be_with_reload(:project) { create(:project, :with_namespace_settings) }
+ let_it_be_with_reload(:current_user) { create(:admin) }
before do
sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user)
end
+ describe 'when membership is set to expire', :js do
+ it 'renders relative time' do
+ expire_time = Time.current + 2.days
+ current_user.update!(time_display_relative: true)
+ project.add_member(user, Gitlab::Access::REPORTER, expires_at: expire_time)
+
+ visit admin_project_path(project)
+
+ expect(page).to have_content(/Expires in \d day/)
+ end
+
+ it 'renders absolute time' do
+ expire_time = Time.current.tomorrow.middle_of_day
+ current_user.update!(time_display_relative: false)
+ project.add_member(user, Gitlab::Access::REPORTER, expires_at: expire_time)
+
+ visit admin_project_path(project)
+
+ expect(page).to have_content("Expires on #{expire_time.strftime('%b %-d')}")
+ end
+ end
+
describe "GET /admin/projects" do
let!(:archived_project) { create :project, :public, :archived }
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index d312965f6cf..44fd21e510a 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "Admin Runners" do
let_it_be(:namespace) { create(:namespace) }
let_it_be(:project) { create(:project, namespace: namespace, creator: user) }
- context "runners registration" do
+ describe "runners registration" do
before do
visit admin_runners_path
end
@@ -164,7 +164,9 @@ RSpec.describe "Admin Runners" do
end
describe 'filter by status' do
- let!(:never_contacted) { create(:ci_runner, :instance, description: 'runner-never-contacted', contacted_at: nil) }
+ let!(:never_contacted) do
+ create(:ci_runner, :instance, description: 'runner-never-contacted', contacted_at: nil)
+ end
before do
create(:ci_runner, :instance, description: 'runner-1', contacted_at: Time.zone.now)
@@ -326,13 +328,15 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
page.within('[data-testid="runner-type-tabs"]') do
click_on 'Instance'
-
- expect(page).to have_link('Instance', class: 'active')
end
end
it_behaves_like 'shows no runners found'
+ it 'shows active tab' do
+ expect(page).to have_link('Instance', class: 'active')
+ end
+
it 'shows no runner' do
expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
@@ -402,8 +406,8 @@ RSpec.describe "Admin Runners" do
end
it 'sorts by last contact date' do
- create(:ci_runner, :instance, description: 'runner-1', created_at: '2018-07-12 15:37', contacted_at: '2018-07-12 15:37')
- create(:ci_runner, :instance, description: 'runner-2', created_at: '2018-07-12 16:37', contacted_at: '2018-07-12 16:37')
+ create(:ci_runner, :instance, description: 'runner-1', contacted_at: '2018-07-12')
+ create(:ci_runner, :instance, description: 'runner-2', contacted_at: '2018-07-13')
visit admin_runners_path
@@ -448,13 +452,13 @@ RSpec.describe "Admin Runners" do
it 'updates ACTIVE runner status to paused=false' do
visit admin_runners_path('status[]': 'ACTIVE')
- expect(page).to have_current_path(admin_runners_path('paused[]': 'false') )
+ expect(page).to have_current_path(admin_runners_path('paused[]': 'false'))
end
it 'updates PAUSED runner status to paused=true' do
visit admin_runners_path('status[]': 'PAUSED')
- expect(page).to have_current_path(admin_runners_path('paused[]': 'true') )
+ expect(page).to have_current_path(admin_runners_path('paused[]': 'true'))
end
end
end
@@ -477,7 +481,9 @@ RSpec.describe "Admin Runners" do
describe 'runner show page breadcrumbs' do
it 'contains the current runner id and token' do
page.within '[data-testid="breadcrumb-links"]' do
- expect(page.find('[data-testid="breadcrumb-current-link"]')).to have_link("##{runner.id} (#{runner.short_sha})")
+ expect(page.find('[data-testid="breadcrumb-current-link"]')).to have_link(
+ "##{runner.id} (#{runner.short_sha})"
+ )
end
end
end
@@ -515,16 +521,16 @@ RSpec.describe "Admin Runners" do
describe "Runner edit page" do
let(:runner) { create(:ci_runner, :project) }
+ let!(:project1) { create(:project) }
+ let!(:project2) { create(:project) }
before do
- @project1 = create(:project)
- @project2 = create(:project)
visit edit_admin_runner_path(runner)
wait_for_requests
end
- describe 'runner edit page breadcrumbs' do
+ describe 'breadcrumbs' do
it 'contains the current runner id and token' do
page.within '[data-testid="breadcrumb-links"]' do
expect(page).to have_link("##{runner.id} (#{runner.short_sha})")
@@ -539,7 +545,7 @@ RSpec.describe "Admin Runners" do
end
end
- describe 'when a runner is updated', :js do
+ context 'when a runner is updated', :js do
before do
click_on _('Save changes')
wait_for_requests
@@ -556,21 +562,21 @@ RSpec.describe "Admin Runners" do
describe 'projects' do
it 'contains project names' do
- expect(page).to have_content(@project1.full_name)
- expect(page).to have_content(@project2.full_name)
+ expect(page).to have_content(project1.full_name)
+ expect(page).to have_content(project2.full_name)
end
end
describe 'search' do
before do
search_form = find('#runner-projects-search')
- search_form.fill_in 'search', with: @project1.name
+ search_form.fill_in 'search', with: project1.name
search_form.click_button 'Search'
end
it 'contains name of correct project' do
- expect(page).to have_content(@project1.full_name)
- expect(page).not_to have_content(@project2.full_name)
+ expect(page).to have_content(project1.full_name)
+ expect(page).not_to have_content(project2.full_name)
end
end
@@ -584,12 +590,12 @@ RSpec.describe "Admin Runners" do
assigned_project = page.find('[data-testid="assigned-projects"]')
expect(page).to have_content('Runner assigned to project.')
- expect(assigned_project).to have_content(@project2.path)
+ expect(assigned_project).to have_content(project2.path)
end
end
context 'with specific runner' do
- let(:runner) { create(:ci_runner, :project, projects: [@project1]) }
+ let(:runner) { create(:ci_runner, :project, projects: [project1]) }
before do
visit edit_admin_runner_path(runner)
@@ -599,7 +605,7 @@ RSpec.describe "Admin Runners" do
end
context 'with locked runner' do
- let(:runner) { create(:ci_runner, :project, projects: [@project1], locked: true) }
+ let(:runner) { create(:ci_runner, :project, projects: [project1], locked: true) }
before do
visit edit_admin_runner_path(runner)
@@ -610,7 +616,7 @@ RSpec.describe "Admin Runners" do
end
describe 'disable/destroy' do
- let(:runner) { create(:ci_runner, :project, projects: [@project1]) }
+ let(:runner) { create(:ci_runner, :project, projects: [project1]) }
before do
visit edit_admin_runner_path(runner)
@@ -624,7 +630,7 @@ RSpec.describe "Admin Runners" do
new_runner_project = page.find('[data-testid="unassigned-projects"]')
expect(page).to have_content('Runner unassigned from project.')
- expect(new_runner_project).to have_content(@project1.path)
+ expect(new_runner_project).to have_content(project1.path)
end
end
end
diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb
index 8edddcf9a9b..faf13374719 100644
--- a/spec/features/admin/admin_sees_background_migrations_spec.rb
+++ b/spec/features/admin/admin_sees_background_migrations_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe "Admin > Admin sees background migrations" do
let_it_be(:admin) { create(:admin) }
+ let(:job_class) { Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob }
let_it_be(:active_migration) { create(:batched_background_migration, :active, table_name: 'active') }
let_it_be(:failed_migration) { create(:batched_background_migration, :failed, table_name: 'failed', total_tuple_count: 100) }
@@ -107,7 +108,8 @@ RSpec.describe "Admin > Admin sees background migrations" do
anything,
batch_min_value: 6,
batch_size: 5,
- job_arguments: failed_migration.job_arguments
+ job_arguments: failed_migration.job_arguments,
+ job_class: job_class
).and_return([6, 10])
end
end
diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb
index 2225f25aa1e..8ff31dfded7 100644
--- a/spec/features/admin/admin_system_info_spec.rb
+++ b/spec/features/admin/admin_system_info_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Admin System Info' do
expect(page).to have_content 'CPU 2 cores'
expect(page).to have_content 'Memory Usage 4 GB / 16 GB'
expect(page).to have_content 'Disk Usage'
- expect(page).to have_content 'Uptime'
+ expect(page).to have_content 'System started'
end
end
@@ -39,7 +39,7 @@ RSpec.describe 'Admin System Info' do
expect(page).to have_content 'CPU Unable to collect CPU info'
expect(page).to have_content 'Memory Usage 4 GB / 16 GB'
expect(page).to have_content 'Disk Usage'
- expect(page).to have_content 'Uptime'
+ expect(page).to have_content 'System started'
end
end
@@ -54,7 +54,7 @@ RSpec.describe 'Admin System Info' do
expect(page).to have_content 'CPU 2 cores'
expect(page).to have_content 'Memory Usage Unable to collect memory info'
expect(page).to have_content 'Disk Usage'
- expect(page).to have_content 'Uptime'
+ expect(page).to have_content 'System started'
end
end
end
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
index 18bb03f4617..bc88b90a2dd 100644
--- a/spec/features/admin/users/user_spec.rb
+++ b/spec/features/admin/users/user_spec.rb
@@ -372,8 +372,8 @@ RSpec.describe 'Admin::Users::User' do
describe 'show user keys', :js do
it do
- key1 = create(:key, user: user, title: 'ssh-rsa Key1', key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4FIEBXGi4bPU8kzxMefudPIJ08/gNprdNTaO9BR/ndy3+58s2HCTw2xCHcsuBmq+TsAqgEidVq4skpqoTMB+Uot5Uzp9z4764rc48dZiI661izoREoKnuRQSsRqUTHg5wrLzwxlQbl1MVfRWQpqiz/5KjBC7yLEb9AbusjnWBk8wvC1bQPQ1uLAauEA7d836tgaIsym9BrLsMVnR4P1boWD3Xp1B1T/ImJwAGHvRmP/ycIqmKdSpMdJXwxcb40efWVj0Ibbe7ii9eeoLdHACqevUZi6fwfbymdow+FeqlkPoHyGg3Cu4vD/D8+8cRc7mE/zGCWcQ15Var83Tczour Key1')
- key2 = create(:key, user: user, title: 'ssh-rsa Key2', key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQSTWXhJAX/He+nG78MiRRRn7m0Pb0XbcgTxE0etArgoFoh9WtvDf36HG6tOSg/0UUNcp0dICsNAmhBKdncp6cIyPaXJTURPRAGvhI0/VDk4bi27bRnccGbJ/hDaUxZMLhhrzY0r22mjVf8PF6dvv5QUIQVm1/LeaWYsHHvLgiIjwrXirUZPnFrZw6VLREoBKG8uWvfSXw1L5eapmstqfsME8099oi+vWLR8MgEysZQmD28M73fgW4zek6LDQzKQyJx9nB+hJkKUDvcuziZjGmRFlNgSA2mguERwL1OXonD8WYUrBDGKroIvBT39zS5d9tQDnidEJZ9Y8gv5ViYP7x Key2')
+ key1 = create(:key, user: user, title: 'ssh-rsa Key1')
+ key2 = create(:key, user: user, title: 'ssh-rsa Key2')
visit admin_user_path(user)
diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb
index adb43d60306..e02cd182b2c 100644
--- a/spec/features/dashboard/todos/todos_spec.rb
+++ b/spec/features/dashboard/todos/todos_spec.rb
@@ -60,6 +60,21 @@ RSpec.describe 'Dashboard Todos' do
end
end
+ context 'when todo references an issue of type task' do
+ let(:task) { create(:issue, :task, project: project) }
+ let!(:task_todo) { create(:todo, :mentioned, user: user, project: project, target: task, author: author) }
+
+ before do
+ sign_in(user)
+
+ visit dashboard_todos_path
+ end
+
+ it 'displays the correct issue type name' do
+ expect(page).to have_content('mentioned you on task')
+ end
+ end
+
context 'user has an unauthorized todo' do
before do
sign_in(user)
@@ -85,6 +100,10 @@ RSpec.describe 'Dashboard Todos' do
visit dashboard_todos_path
end
+ it 'displays the correct issue type name' do
+ expect(page).to have_content('mentioned you on issue')
+ end
+
it 'has todo present' do
expect(page).to have_selector('.todos-list .todo', count: 1)
end
diff --git a/spec/features/file_uploads/multipart_invalid_uploads_spec.rb b/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
index 91c8e100e6a..cff8b4e61a5 100644
--- a/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
+++ b/spec/features/file_uploads/multipart_invalid_uploads_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Invalid uploads that must be rejected', :api, :js do
# These keys are rejected directly by rack itself.
# The request will not be received by multipart.rb (can't use the 'handling file uploads' shared example)
- it_behaves_like 'rejecting invalid keys', key_name: 'x' * 11000, message: 'Puma caught this error: exceeded available parameter key space (RangeError)'
+ it_behaves_like 'rejecting invalid keys', key_name: 'x' * 11000, message: 'Puma caught this error: exceeded available parameter key space (Rack::QueryParser::ParamsTooDeepError)'
it_behaves_like 'rejecting invalid keys', key_name: 'package[]test', status: 400, message: 'Bad Request'
it_behaves_like 'handling file uploads', 'by rejecting uploads with an invalid key'
diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb
index a60b8a60da0..a129db6cb6f 100644
--- a/spec/features/groups/group_runners_spec.rb
+++ b/spec/features/groups/group_runners_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe "Group Runners" do
describe "Group runners page", :js do
let!(:group_registration_token) { group.runners_token }
- context "runners registration" do
+ describe "runners registration" do
before do
visit group_runners_path(group)
end
@@ -128,7 +128,7 @@ RSpec.describe "Group Runners" do
end
end
- context 'filtered search' do
+ describe 'filtered search' do
before do
visit group_runners_path(group)
end
@@ -182,5 +182,45 @@ RSpec.describe "Group Runners" do
end
end
end
+
+ context 'when group_runner_view_ui is enabled' do
+ before do
+ stub_feature_flags(group_runner_view_ui: true)
+ end
+
+ it 'user views runner details' do
+ visit group_runner_path(group, runner)
+
+ expect(page).to have_content "#{s_('Runners|Description')} runner-foo"
+ end
+
+ it 'user edits the runner to be protected' do
+ visit edit_group_runner_path(group, runner)
+
+ expect(page.find_field('runner[access_level]')).not_to be_checked
+
+ check 'runner_access_level'
+ click_button _('Save changes')
+
+ expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}"
+ end
+
+ context 'when a runner has a tag' do
+ before do
+ runner.update!(tag_list: ['tag'])
+ end
+
+ it 'user edits runner not to run untagged jobs' do
+ visit edit_group_runner_path(group, runner)
+
+ page.find_field('runner[tag_list]').set('tag, tag2')
+
+ uncheck 'runner_run_untagged'
+ click_button _('Save changes')
+
+ expect(page).to have_content "#{s_('Runners|Tags')} tag tag2"
+ end
+ end
+ end
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 019b094ccb5..2f599d24b01 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'Edit group settings' do
it 'shows the selection menu' do
visit edit_group_path(group)
- expect(page).to have_content('Allowed to create projects')
+ expect(page).to have_content('Roles allowed to create projects')
end
end
@@ -97,7 +97,7 @@ RSpec.describe 'Edit group settings' do
it 'shows the selection menu' do
visit edit_group_path(group)
- expect(page).to have_content('Allowed to create subgroups')
+ expect(page).to have_content('Roles allowed to create subgroups')
end
end
diff --git a/spec/features/groups/import_export/import_file_spec.rb b/spec/features/groups/import_export/import_file_spec.rb
index 3d23451feef..b69b8bf2c19 100644
--- a/spec/features/groups/import_export/import_file_spec.rb
+++ b/spec/features/groups/import_export/import_file_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Import/Export - Group Import', :js do
visit new_group_path
click_link 'Import group'
- fill_in :import_group_name, with: group_name
+ fill_in s_('Groups|Group name'), with: group_name
expect(page).to have_content 'Import group from file'
attach_file(file) do
@@ -41,10 +41,12 @@ RSpec.describe 'Import/Export - Group Import', :js do
group = Group.find_by(name: group_name)
- expect(group).not_to be_nil
- expect(group.description).to eq 'A voluptate non sequi temporibus quam at.'
- expect(group.path).to eq 'test-group-import'
- expect(group.import_state.status).to eq GroupImportState.state_machine.states[:finished].value
+ aggregate_failures do
+ expect(group).not_to be_nil
+ expect(group.description).to eq 'A voluptate non sequi temporibus quam at.'
+ expect(group.path).to eq 'test-group-import'
+ expect(group.import_state.status).to eq GroupImportState.state_machine.states[:finished].value
+ end
end
end
@@ -53,9 +55,9 @@ RSpec.describe 'Import/Export - Group Import', :js do
visit new_group_path
click_link 'Import group'
- fill_in :import_group_name, with: 'Test Group Import'
+ fill_in s_('Groups|Group name'), with: 'Test Group Import'
- fill_in :import_group_path, with: 'custom-path'
+ fill_in s_('Groups|Group URL'), with: 'custom-path'
attach_file(file) do
find('.js-filepicker-button').click
end
@@ -76,8 +78,10 @@ RSpec.describe 'Import/Export - Group Import', :js do
visit new_group_path
click_link 'Import group'
- fill_in :import_group_path, with: 'test-group-import'
- expect(page).to have_content "Group path is already taken. We've suggested one that is available."
+ fill_in s_('Groups|Group URL'), with: 'test-group-import'
+ expect(page).to have_content s_(
+ 'Groups|Group path is unavailable. Path has been replaced with a suggested available path.'
+ )
end
end
end
@@ -89,7 +93,7 @@ RSpec.describe 'Import/Export - Group Import', :js do
visit new_group_path
click_link 'Import group'
- fill_in :import_group_name, with: 'Test Group Import'
+ fill_in s_('Groups|Group name'), with: 'Test Group Import'
attach_file(file) do
find('.js-filepicker-button').click
end
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index 7541e54f014..be1db970e9d 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Group merge requests page' do
expect(page).to have_selector('.empty-state')
expect(page).to have_link('Select project to create merge request')
- expect(page).not_to have_selector('.issues-filters')
+ expect(page).to have_selector('.issues-filters')
end
context 'with no open merge requests' do
diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb
index d3141da9160..98dc534f54e 100644
--- a/spec/features/groups/settings/packages_and_registries_spec.rb
+++ b/spec/features/groups/settings/packages_and_registries_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Group Packages & Registries settings' do
sign_in(user)
end
- context 'when packges feature is disabled on the group' do
+ context 'when packages feature is disabled on the group' do
before do
stub_packages_setting(enabled: false)
end
@@ -56,26 +56,26 @@ RSpec.describe 'Group Packages & Registries settings' do
expect(sidebar).to have_link _('Packages & Registries')
end
- it 'has a Package Registry section', :js do
+ it 'has a Duplicate packages section', :js do
visit_settings_page
- expect(page).to have_content('Package Registry')
- expect(page).to have_button('Collapse')
+ expect(page).to have_content('Duplicate packages')
end
it 'automatically saves changes to the server', :js do
visit_settings_page
within '[data-testid="maven-settings"]' do
- expect(page).to have_content('Allow duplicates')
+ expect(page).to have_content('Reject packages with the same name and version')
+ expect(page).not_to have_content('Exceptions')
find('.gl-toggle').click
- expect(page).to have_content('Do not allow duplicates')
+ expect(page).to have_content('Exceptions')
visit_settings_page
- expect(page).to have_content('Do not allow duplicates')
+ expect(page).to have_content('Exceptions')
end
end
@@ -83,12 +83,10 @@ RSpec.describe 'Group Packages & Registries settings' do
visit_settings_page
within '[data-testid="maven-settings"]' do
- expect(page).to have_content('Allow duplicates')
+ expect(page).to have_content('Reject packages with the same name and version')
find('.gl-toggle').click
- expect(page).to have_content('Do not allow duplicates')
-
fill_in 'Exceptions', with: ')'
# simulate blur event
@@ -103,11 +101,11 @@ RSpec.describe 'Group Packages & Registries settings' do
visit_sub_group_settings_page
within '[data-testid="maven-settings"]' do
- expect(page).to have_content('Allow duplicates')
+ expect(page).to have_content('Reject packages with the same name and version')
find('.gl-toggle').click
- expect(page).to have_content('Do not allow duplicates')
+ expect(page).to have_content('Exceptions')
end
end
end
diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb
index c7b7b25caa7..998c3d2ca3f 100644
--- a/spec/features/groups/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb
@@ -48,6 +48,6 @@ RSpec.describe 'User searches group settings', :js do
visit group_settings_packages_and_registries_path(group)
end
- it_behaves_like 'can highlight results', 'Use GitLab as a private registry'
+ it_behaves_like 'can highlight results', 'Allow packages with the same name and version'
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index fa8db1befb5..9a1e216c6d2 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -97,6 +97,31 @@ RSpec.describe 'Group show page' do
end
end
+ context 'when a public project is shared with a private group' do
+ let_it_be(:private_group) { create(:group, :private) }
+ let_it_be(:public_project) { create(:project, :public) }
+ let_it_be(:project_group_link) { create(:project_group_link, group: private_group, project: public_project) }
+
+ before do
+ private_group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'shows warning popover', :js do
+ visit group_path(private_group)
+
+ click_link _('Shared projects')
+
+ wait_for_requests
+
+ page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
+ click_button _('Less restrictive visibility')
+ end
+
+ expect(page).to have_content _('Project visibility level is less restrictive than the group settings.')
+ end
+ end
+
context 'when user does not have permissions to create new subgroups or projects', :js do
before do
group.add_reporter(user)
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 31390b110e7..ece6167b193 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'Group' do
end
describe 'as a non-admin' do
- it 'creates a group and persists visibility radio selection', :js, :saas do
+ it 'creates a group and persists visibility radio selection', :js do
stub_application_setting(default_group_visibility: :private)
fill_in 'Group name', with: 'test-group'
@@ -499,8 +499,6 @@ RSpec.describe 'Group' do
let_it_be_with_refind(:user) { create(:user) }
before do
- stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
-
group.add_owner(user)
sign_in(user)
end
@@ -509,8 +507,8 @@ RSpec.describe 'Group' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Group) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -520,8 +518,8 @@ RSpec.describe 'Group' do
end
it 'does not display the banner in a paid group page' do
- allow_next_found_instance_of(Group) do |g|
- allow(g).to receive(:paid?).and_return(true)
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:paid?).and_return(true)
end
visit group_path(group)
expect_page_not_to_have_storage_enforcement_banner
@@ -531,12 +529,13 @@ RSpec.describe 'Group' do
visit group_path(group)
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
find('.js-storage-enforcement-banner [data-testid="close-icon"]').click
+ wait_for_requests
page.refresh
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Group) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -547,6 +546,7 @@ RSpec.describe 'Group' do
# This test should break and be rewritten after the implementation of the storage_enforcement_date
# TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
it 'does not display the banner in the group page' do
+ stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
visit group_path(group)
expect_page_not_to_have_storage_enforcement_banner
end
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index dad3dfd3440..7c24943eb6f 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Incident details', :js do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
let_it_be(:incident) { create(:incident, project: project, author: developer, description: 'description') }
+ let_it_be(:issue) { create(:issue, project: project, author: developer, description: 'Issue description') }
let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: incident) }
before_all do
@@ -14,23 +15,24 @@ RSpec.describe 'Incident details', :js do
before do
sign_in(developer)
-
- visit project_issues_incident_path(project, incident)
- wait_for_requests
end
context 'when a developer+ displays the incident' do
- it 'shows the incident' do
+ before do
+ visit project_issues_incident_path(project, incident)
+ wait_for_requests
+ end
+
+ it 'shows correct elements on the page', :aggregate_failures do
+ # shows the incident
page.within('.issuable-details') do
expect(find('h1')).to have_content(incident.title)
end
- end
- it 'does not show design management' do
+ # does not show design management
expect(page).not_to have_selector('.js-design-management')
- end
- it 'shows the incident tabs' do
+ # shows the incident tabs
page.within('.issuable-details') do
incident_tabs = find('[data-testid="incident-tabs"]')
@@ -38,9 +40,8 @@ RSpec.describe 'Incident details', :js do
expect(incident_tabs).to have_content('Summary')
expect(incident_tabs).to have_content(incident.description)
end
- end
- it 'shows the right sidebar mounted with type issue' do
+ # shows the right sidebar mounted with type issue
page.within('.layout-page') do
sidebar = find('.right-sidebar')
@@ -51,12 +52,12 @@ RSpec.describe 'Incident details', :js do
end
end
- context 'escalation status' do
+ describe 'escalation status' do
let(:sidebar) { page.find('.right-sidebar') }
let(:widget) { sidebar.find('[data-testid="escalation_status_container"]') }
let(:expected_dropdown_options) { escalation_status.class::STATUSES.keys.take(3).map { |key| key.to_s.titleize } }
- it 'has an interactable escalation status widget' do
+ it 'has an interactable escalation status widget', :aggregate_failures do
expect(current_status).to have_text(escalation_status.status_name.to_s.titleize)
# list the available statuses
@@ -87,41 +88,41 @@ RSpec.describe 'Incident details', :js do
end
end
- context 'when an incident `issue_type` is edited by a signed in user' do
- it 'routes the user to the incident details page when the `issue_type` is set to incident' do
- wait_for_requests
- project_path = "/#{project.full_path}"
- click_button 'Edit title and description'
- wait_for_requests
+ it 'routes the user to the incident details page when the `issue_type` is set to incident' do
+ visit project_issue_path(project, issue)
+ wait_for_requests
+
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
- page.within('[data-testid="issuable-form"]') do
- click_button 'Incident'
- click_button 'Issue'
- click_button 'Save changes'
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Issue'
+ click_button 'Incident'
+ click_button 'Save changes'
- wait_for_requests
+ wait_for_requests
- expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
- end
+ expect(page).to have_current_path("#{project_path}/-/issues/incident/#{issue.iid}")
end
end
- context 'when incident details are edited by a signed in user' do
- it 'routes the user to the incident details page when the `issue_type` is set to incident' do
- wait_for_requests
- project_path = "/#{project.full_path}"
- click_button 'Edit title and description'
- wait_for_requests
+ it 'routes the user to the issue details page when the `issue_type` is set to issue' do
+ visit project_issues_incident_path(project, incident)
+ wait_for_requests
- page.within('[data-testid="issuable-form"]') do
- click_button 'Incident'
- click_button 'Issue'
- click_button 'Save changes'
+ project_path = "/#{project.full_path}"
+ click_button 'Edit title and description'
+ wait_for_requests
- wait_for_requests
+ page.within('[data-testid="issuable-form"]') do
+ click_button 'Incident'
+ click_button 'Issue'
+ click_button 'Save changes'
- expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
- end
+ wait_for_requests
+
+ expect(page).to have_current_path("#{project_path}/-/issues/#{incident.iid}")
end
end
end
diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb
new file mode 100644
index 00000000000..e39f348013c
--- /dev/null
+++ b/spec/features/incidents/incident_timeline_events_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Incident timeline events', :js do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:incident) { create(:incident, project: project) }
+
+ before_all do
+ project.add_developer(developer)
+ end
+
+ before do
+ stub_feature_flags(incident_timeline: true)
+ sign_in(developer)
+
+ visit project_issues_incident_path(project, incident)
+ wait_for_requests
+ click_link 'Timeline'
+ end
+
+ context 'when add event is clicked' do
+ it 'submits event data when save is clicked' do
+ click_button 'Add new timeline event'
+
+ expect(page).to have_selector('.common-note-form')
+
+ fill_in 'Description', with: 'Event note goes here'
+ fill_in 'timeline-input-hours', with: '07'
+ fill_in 'timeline-input-minutes', with: '25'
+
+ click_button 'Save'
+
+ expect(page).to have_selector('.incident-timeline-events')
+
+ page.within '.timeline-event-note' do
+ expect(page).to have_content('Event note goes here')
+ expect(page).to have_content('07:25')
+ end
+ end
+ end
+
+ context 'when delete event is clicked' do
+ before do
+ click_button 'Add new timeline event'
+ fill_in 'Description', with: 'Event note to delete'
+ click_button 'Save'
+ end
+
+ it 'shows the confirmation modal and deletes the event' do
+ click_button 'More actions'
+
+ page.within '.gl-new-dropdown-item-text-wrapper' do
+ expect(page).to have_content('Delete')
+ page.find('.gl-new-dropdown-item-text-primary', text: 'Delete').click
+ end
+
+ page.within '.modal' do
+ expect(page).to have_content('Delete event')
+ end
+
+ click_button 'Delete event'
+
+ wait_for_requests
+
+ expect(page).to have_content('No timeline items have been added yet.')
+ end
+ end
+end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 965e97baadd..fe804dc52d7 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- context 'when invite is sent before account is created - ldap or social sign in for manual acceptance edge case' do
+ context 'when invite is sent before account is created - ldap or service sign in for manual acceptance edge case' do
let(:user) { create(:user, email: 'user@example.com') }
context 'when invite clicked and not signed in' do
@@ -221,7 +221,8 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
category: 'RegistrationsController',
action: 'accepted',
label: 'invite_email',
- property: group_invite.id.to_s
+ property: group_invite.id.to_s,
+ user: group_invite.reload.user
)
end
end
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 0fa2d238b0a..a1e80586c05 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'issuable list', :js do
issuable_types = [:issue, :merge_request]
before do
- project.add_user(user, :developer)
+ project.add_member(user, :developer)
sign_in(user)
issuable_types.each { |type| create_issuables(type) }
end
diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb
index 7a367723609..c44181a60e4 100644
--- a/spec/features/issues/filtered_search/visual_tokens_spec.rb
+++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe 'Visual tokens', :js do
let_it_be(:issue) { create(:issue, project: project) }
before do
- project.add_user(user, :maintainer)
- project.add_user(user_rock, :maintainer)
+ project.add_member(user, :maintainer)
+ project.add_member(user_rock, :maintainer)
sign_in(user)
visit project_issues_path(project)
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index 1c707466b51..5ba09703852 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -20,25 +20,11 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
context 'when signed in' do
before do
- project.add_user(user, membership_level)
+ project.add_member(user, membership_level)
sign_in(user)
end
- context 'when ’Create merge request’ button is clicked' do
- before do
- visit project_issue_path(project, issue)
-
- wait_for_requests
-
- click_button('Create merge request')
-
- wait_for_requests
- end
-
- it_behaves_like 'merge request author auto assign'
- end
-
context 'when interacting with the dropdown' do
before do
visit project_issue_path(project, issue)
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index f03c812ebb5..fafaea8ac68 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -45,25 +45,13 @@ RSpec.describe 'Merge request > Batch comments', :js do
expect(page).to have_selector('.note:not(.draft-note)', text: 'Line is wrong')
end
- it 'publishes single comment' do
- write_diff_comment
-
- click_button 'Add comment now'
-
- wait_for_requests
-
- expect(page).not_to have_selector('.draft-note-component', text: 'Line is wrong')
-
- expect(page).to have_selector('.note:not(.draft-note)', text: 'Line is wrong')
- end
-
it 'deletes draft note' do
write_diff_comment
find('.js-note-delete').click
page.within('.modal') do
- click_button('Delete Comment', match: :first)
+ click_button('Delete comment', match: :first)
end
wait_for_requests
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index 06b29969775..f21929e5275 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -253,7 +253,7 @@ RSpec.describe 'User comments on a diff', :js do
end
page.within('.modal') do
- click_button('Delete Comment', match: :first)
+ click_button('Delete comment', match: :first)
end
page.within('.merge-request-tabs') do
diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb
index 2bf8e9ba6a4..c8b22bb3125 100644
--- a/spec/features/merge_request/user_creates_merge_request_spec.rb
+++ b/spec/features/merge_request/user_creates_merge_request_spec.rb
@@ -15,39 +15,27 @@ RSpec.describe "User creates a merge request", :js do
sign_in(user)
end
- context 'when completed the compare branches form' do
- before do
- visit(project_new_merge_request_path(project))
+ it "creates a merge request" do
+ visit(project_new_merge_request_path(project))
- find(".js-source-branch").click
- click_link("fix")
+ find(".js-source-branch").click
+ click_link("fix")
- find(".js-target-branch").click
- click_link("feature")
+ find(".js-target-branch").click
+ click_link("feature")
- click_button("Compare branches")
- end
+ click_button("Compare branches")
- it "shows merge request form" do
- page.within('.merge-request-form') do
- expect(page.find('#merge_request_description')['placeholder']).to eq 'Describe the goal of the changes and what reviewers should be aware of.'
- end
+ page.within('.merge-request-form') do
+ expect(page.find('#merge_request_description')['placeholder']).to eq 'Describe the goal of the changes and what reviewers should be aware of.'
end
- context "when completed the merge request form" do
- before do
- fill_in("Title", with: title)
- click_button("Create merge request")
- end
+ fill_in("Title", with: title)
+ click_button("Create merge request")
- it "creates a merge request" do
- page.within(".merge-request") do
- expect(page).to have_content(title)
- end
- end
+ page.within(".merge-request") do
+ expect(page).to have_content(title)
end
-
- it_behaves_like 'merge request author auto assign'
end
context "XSS branch name exists" do
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index 8a310aba77b..d461170c990 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
it 'allows commenting' do
should_allow_commenting(find_by_scrolling('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'))
- accept_gl_confirm(button_text: 'Delete Comment') do
+ accept_gl_confirm(button_text: 'Delete comment') do
first('button.more-actions-toggle').click
first('.js-note-delete').click
end
diff --git a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
index 56517a97716..60ea168940a 100644
--- a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
+++ b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe 'Merge request > User scrolls to note on load', :js do
note_element = find(collapsed_fragment_id)
expect(note_element.visible?).to eq(true)
- expect(note_element.sibling('.replies-toggle')[:class]).to include('expanded')
+ expect(note_element.sibling('li:nth-child(2)')).to have_button s_('Notes|Collapse replies')
end
end
end
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 0e9ff98c3e1..8225fcbfd89 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -124,7 +124,7 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
it 'removes avatar when note is deleted' do
open_more_actions_dropdown(note)
- accept_gl_confirm(button_text: 'Delete Comment') do
+ accept_gl_confirm(button_text: 'Delete comment') do
find(".note-row-#{note.id} .js-note-delete").click
end
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 81034caaee2..e045f11c0d8 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
before do
merge_request.update!(merge_commit_sha: sha)
- project.add_user(user, role)
+ project.add_member(user, role)
sign_in(user)
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 2dafd66b406..1d3effd4a2a 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -591,14 +591,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when a new failures exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_failed)
end
@@ -639,14 +639,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when an existing failure exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_failed)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_failed)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
@@ -686,14 +686,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when a resolved failure exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_failed)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
@@ -732,14 +732,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when a new error exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_error)
end
@@ -779,14 +779,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when an existing error exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_error)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_error)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
@@ -825,14 +825,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'when a resolved error exists' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_error)
end
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
reports.get_suite('junit').add_test_case(create_test_case_java_success)
end
@@ -871,7 +871,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
context 'properly truncates the report' do
let(:base_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
10.times do |index|
reports.get_suite('rspec').add_test_case(
create_test_case_rspec_failed(index))
@@ -882,7 +882,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
let(:head_reports) do
- Gitlab::Ci::Reports::TestReports.new.tap do |reports|
+ Gitlab::Ci::Reports::TestReport.new.tap do |reports|
10.times do |index|
reports.get_suite('rspec').add_test_case(
create_test_case_rspec_failed(index))
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 9696b1ff551..16b1de0393f 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -123,10 +123,6 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
context 'when actor is a developer in parent project' do
let(:actor) { developer_in_parent }
- before do
- stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
- end
-
it 'creates a pipeline in the parent project when user proceeds with the warning' do
visit project_merge_request_path(parent_project, merge_request)
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 4465d7e29be..2c2a2dfd4a8 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -24,23 +24,21 @@ RSpec.describe 'Merge request > User sees versions', :js do
visit diffs_project_merge_request_path(project, merge_request, params)
end
- shared_examples 'allows commenting' do |file_id:, line_code:, comment:|
+ shared_examples 'allows commenting' do |file_name:, line_text:, comment:|
it do
- diff_file_selector = ".diff-file[id='#{file_id}']"
- line_code = "#{file_id}_#{line_code}"
+ page.within find_by_scrolling('.diff-file', text: file_name) do
+ line_code_element = page.find('.diff-grid-row', text: line_text)
- page.within find_by_scrolling(diff_file_selector) do
- line_code_element = first("[id='#{line_code}']")
# scrolling to element's bottom is required in order for .hover action to work
# otherwise, the element could be hidden underneath a sticky header
scroll_to_elements_bottom(line_code_element)
line_code_element.hover
- first("[id='#{line_code}'] [role='button']").click
+ page.find("[data-testid='left-comment-button']", visible: true).click
- page.within("form[data-line-code='#{line_code}']") do
- fill_in "note[note]", with: comment
- click_button('Add comment now')
- end
+ expect(page).to have_selector("form", count: 1)
+
+ fill_in("note[note]", with: comment)
+ click_button('Add comment now')
wait_for_requests
@@ -59,8 +57,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
- file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
- line_code: '1_1',
+ file_name: '.gitmodules',
+ line_text: '[submodule "six"]',
comment: 'Typo, please fix.'
end
@@ -107,8 +105,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
- file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
- line_code: '2_2',
+ file_name: '.gitmodules',
+ line_text: 'path = six',
comment: 'Typo, please fix.'
end
@@ -174,9 +172,9 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
- file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
- line_code: '4_4',
- comment: 'Typo, please fix.'
+ file_name: '.gitmodules',
+ line_text: '[submodule "gitlab-shell"]',
+ comment: 'Typo, please fix.'
end
describe 'compare with same version' do
@@ -241,8 +239,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
- file_id: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd',
- line_code: '6_6',
+ file_name: 'files/ruby/popen.rb',
+ line_text: 'RuntimeError',
comment: 'Typo, please fix.'
end
end
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index 5bbd89f1b88..2a1ea1a4e73 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe 'Milestone' do
end
find('input[name="commit"]').click
- expect(find('.alert-danger')).to have_content('already being used for another group or project milestone.')
+ expect(find('.gl-alert-danger')).to have_content('already being used for another group or project milestone.')
end
it 'displays validation message when there is a group milestone with same title' do
diff --git a/spec/features/monitor_sidebar_link_spec.rb b/spec/features/monitor_sidebar_link_spec.rb
index 3c59cd65cdb..b888e2f4171 100644
--- a/spec/features/monitor_sidebar_link_spec.rb
+++ b/spec/features/monitor_sidebar_link_spec.rb
@@ -45,7 +45,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project))
expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project))
expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project))
- expect(page).not_to have_link('Logs', href: project_logs_path(project))
expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project))
end
@@ -78,7 +77,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project))
expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project))
expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project))
- expect(page).not_to have_link('Logs', href: project_logs_path(project))
expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project))
end
@@ -96,7 +94,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project))
expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project))
- expect(page).not_to have_link('Logs', href: project_logs_path(project))
expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project))
end
@@ -113,7 +110,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).to have_link('Environments', href: project_environments_path(project))
expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project))
expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project))
- expect(page).to have_link('Logs', href: project_logs_path(project))
expect(page).to have_link('Kubernetes', href: project_clusters_path(project))
end
@@ -130,7 +126,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do
expect(page).to have_link('Environments', href: project_environments_path(project))
expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project))
expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project))
- expect(page).to have_link('Logs', href: project_logs_path(project))
expect(page).to have_link('Kubernetes', href: project_clusters_path(project))
end
diff --git a/spec/features/nav/top_nav_responsive_spec.rb b/spec/features/nav/top_nav_responsive_spec.rb
index d571327e4b5..4f8e47b5068 100644
--- a/spec/features/nav/top_nav_responsive_spec.rb
+++ b/spec/features/nav/top_nav_responsive_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'top nav responsive', :js do
end
it 'has new dropdown', :aggregate_failures do
- click_button('Create new')
+ click_button('Create new...')
expect(page).to have_link('New project', href: new_project_path)
expect(page).to have_link('New group', href: new_group_path)
diff --git a/spec/features/nav/top_nav_tooltip_spec.rb b/spec/features/nav/top_nav_tooltip_spec.rb
index 58bfe1caf65..73e4571e7a2 100644
--- a/spec/features/nav/top_nav_tooltip_spec.rb
+++ b/spec/features/nav/top_nav_tooltip_spec.rb
@@ -15,10 +15,10 @@ RSpec.describe 'top nav tooltips', :js do
page.find(btn).hover
- expect(page).to have_content('Create new')
+ expect(page).to have_content('Create new...')
page.find(btn).click
- expect(page).not_to have_content('Create new')
+ expect(page).not_to have_content('Create new...')
end
end
diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb
index 6a4a1fca008..4fe0c3d035e 100644
--- a/spec/features/profiles/account_spec.rb
+++ b/spec/features/profiles/account_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Profile > Account', :js do
sign_in(user)
end
- describe 'Social sign-in' do
+ describe 'Service sign-in' do
context 'when an identity does not exist' do
before do
allow(Devise).to receive_messages(omniauth_configs: { google_oauth2: {} })
diff --git a/spec/features/profiles/oauth_applications_spec.rb b/spec/features/profiles/oauth_applications_spec.rb
index ee1daf69f62..7d8cd2dc6ca 100644
--- a/spec/features/profiles/oauth_applications_spec.rb
+++ b/spec/features/profiles/oauth_applications_spec.rb
@@ -35,9 +35,61 @@ RSpec.describe 'Profile > Applications' do
expect(page).to have_content('Your applications (0)')
expect(page).to have_content('Authorized applications (0)')
end
+ end
+
+ describe 'Authorized applications', :js do
+ let(:other_user) { create(:user) }
+ let(:application) { create(:oauth_application, owner: user) }
+ let(:created_at) { 2.days.ago }
+ let(:token) { create(:oauth_access_token, application: application, resource_owner: user) }
+ let(:anonymous_token) { create(:oauth_access_token, resource_owner: user) }
+
+ context 'with multiple access token types and multiple owners' do
+ let!(:token2) { create(:oauth_access_token, application: application, resource_owner: user) }
+ let!(:other_user_token) { create(:oauth_access_token, application: application, resource_owner: other_user) }
+
+ before do
+ token.update_column(:created_at, created_at)
+ token2.update_column(:created_at, created_at - 1.day)
+ anonymous_token.update_columns(application_id: nil, created_at: 1.day.ago)
+ end
+
+ it 'displays the correct authorized applications' do
+ visit oauth_applications_path
+
+ expect(page).to have_content('Authorized applications (2)')
+
+ page.within('div.oauth-authorized-applications') do
+ # Ensure the correct user's token details are displayed
+ # when the application has more than one token
+ page.within("tr#application_#{application.id}") do
+ expect(page).to have_content(created_at)
+ end
+
+ expect(page).to have_content('Anonymous')
+ expect(page).not_to have_content(other_user_token.created_at)
+ end
+ end
+ end
it 'deletes an authorized application' do
- create(:oauth_access_token, resource_owner: user)
+ token
+ visit oauth_applications_path
+
+ page.within('div.oauth-authorized-applications') do
+ page.within("tr#application_#{application.id}") do
+ click_button 'Revoke'
+ end
+ end
+
+ accept_gl_confirm(button_text: 'Revoke application')
+
+ expect(page).to have_content('The application was revoked access.')
+ expect(page).to have_content('Authorized applications (0)')
+ end
+
+ it 'deletes an anonymous authorized application' do
+ anonymous_token
visit oauth_applications_path
page.within('.oauth-authorized-applications') do
@@ -48,7 +100,6 @@ RSpec.describe 'Profile > Applications' do
accept_gl_confirm(button_text: 'Revoke application')
expect(page).to have_content('The application was revoked access.')
- expect(page).to have_content('Your applications (0)')
expect(page).to have_content('Authorized applications (0)')
end
end
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 7eadb74d2d4..07dfbca8cbd 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Profile > Password' do
it 'shows an error message' do
fill_passwords('mypassword', 'mypassword2')
- page.within('.alert-danger') do
+ page.within('.gl-alert-danger') do
expect(page).to have_content("Password confirmation doesn't match Password")
end
end
diff --git a/spec/features/projects/blobs/blame_spec.rb b/spec/features/projects/blobs/blame_spec.rb
index bb3b5cd931c..3b2b74b469e 100644
--- a/spec/features/projects/blobs/blame_spec.rb
+++ b/spec/features/projects/blobs/blame_spec.rb
@@ -49,6 +49,12 @@ RSpec.describe 'File blame', :js do
expect(page).to have_css('#L3')
expect(find('.page-link.active')).to have_text('2')
end
+
+ it 'correctly redirects to the prior blame page' do
+ find('.version-link').click
+
+ expect(find('.page-link.active')).to have_text('2')
+ end
end
context 'when feature flag disabled' do
@@ -64,4 +70,37 @@ RSpec.describe 'File blame', :js do
end
end
end
+
+ context 'when blob length is over global max page limit' do
+ before do
+ stub_const('Projects::BlameService::PER_PAGE', 200)
+ end
+
+ let(:path) { 'files/markdown/ruby-style-guide.md' }
+
+ it 'displays two hundred lines of the file with pagination' do
+ visit_blob_blame(path)
+
+ expect(page).to have_css('.blame-commit')
+ expect(page).to have_css('.gl-pagination')
+
+ expect(page).to have_css('#L1')
+ expect(page).not_to have_css('#L201')
+ expect(find('.page-link.active')).to have_text('1')
+ end
+
+ context 'when user clicks on the next button' do
+ before do
+ visit_blob_blame(path)
+
+ find('.js-next-button').click
+ end
+
+ it 'displays next two hundred lines of the file with pagination' do
+ expect(page).not_to have_css('#L1')
+ expect(page).to have_css('#L201')
+ expect(find('.page-link.active')).to have_text('2')
+ end
+ end
+ end
end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 76baad63cc2..f5cafa2b2ec 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -29,176 +29,162 @@ RSpec.describe 'File blob', :js do
).execute
end
- context 'with refactor_blob_viewer feature flag enabled' do
- context 'Ruby file' do
+ context 'Ruby file' do
+ before do
+ visit_blob('files/ruby/popen.rb')
+
+ wait_for_requests
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ 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
+
+ it 'displays file actions on all screen sizes' do
+ file_actions_selector = '.file-actions'
+
+ resize_screen_sm
+ expect(page).to have_selector(file_actions_selector, visible: true)
+
+ resize_screen_xs
+ expect(page).to have_selector(file_actions_selector, visible: true)
+ end
+ end
+
+ context 'Markdown file' do
+ context 'visiting directly' do
before do
- visit_blob('files/ruby/popen.rb')
+ visit_blob('files/markdown/ruby-style-guide.md')
wait_for_requests
end
- it 'displays the blob' do
+ it 'displays the blob using the rich viewer' do
aggregate_failures do
- # shows highlighted Ruby code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("require 'fileutils'")
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ # 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
- it 'displays file actions on all screen sizes' do
- file_actions_selector = '.file-actions'
-
- resize_screen_sm
- expect(page).to have_selector(file_actions_selector, visible: true)
-
- resize_screen_xs
- expect(page).to have_selector(file_actions_selector, visible: true)
- end
- end
-
- context 'Markdown file' do
- context 'visiting directly' do
+ context 'switching to the simple viewer' do
before do
- visit_blob('files/markdown/ruby-style-guide.md')
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
wait_for_requests
end
- it 'displays the blob using the rich viewer' do
+ it 'displays the blob using the simple viewer' do
aggregate_failures do
- # hides the simple viewer
- expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
- 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')
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
- # shows a disabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ # shows highlighted Markdown code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
- # shows a raw button
- expect(page).to have_link('Open raw')
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
- context 'switching to the simple viewer' do
+ context 'switching to the rich viewer again' do
before do
- find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
wait_for_requests
end
- it 'displays the blob using the simple viewer' do
+ it 'displays the blob using the rich viewer' do
aggregate_failures do
- # hides the rich viewer
- expect(page).to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
- # shows highlighted Markdown code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
-
- # shows an enabled copy button
- 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_requests
- end
-
- it 'displays the blob using the rich viewer' do
- aggregate_failures do
- # hides the simple viewer
- expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).to have_selector('.blob-viewer[data-type="rich"]')
-
- # shows a disabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
- end
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
end
end
end
end
+ end
- context 'when ref switch' do
- def switch_ref_to(ref_name)
- first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
+ context 'when ref switch' do
+ def switch_ref_to(ref_name)
+ first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
- page.within '.project-refs-form' do
- click_link ref_name
- wait_for_requests
- end
+ page.within '.project-refs-form' do
+ click_link ref_name
+ wait_for_requests
end
+ end
- it 'displays no highlighted number of different ref' do
- Files::UpdateService.new(
- project,
- project.first_owner,
- commit_message: 'Update',
- start_branch: 'feature',
- branch_name: 'feature',
- file_path: 'files/js/application.js',
- file_content: 'new content'
- ).execute
+ it 'displays no highlighted number of different ref' do
+ Files::UpdateService.new(
+ project,
+ project.first_owner,
+ commit_message: 'Update',
+ start_branch: 'feature',
+ branch_name: 'feature',
+ file_path: 'files/js/application.js',
+ file_content: 'new content'
+ ).execute
- project.commit('feature').diffs.diff_files.first
+ project.commit('feature').diffs.diff_files.first
- visit_blob('files/js/application.js', anchor: 'L3')
- switch_ref_to('feature')
+ visit_blob('files/js/application.js', anchor: 'L3')
+ switch_ref_to('feature')
- page.within '.blob-content' do
- expect(page).not_to have_css('.hll')
- end
+ page.within '.blob-content' do
+ expect(page).not_to have_css('.hll')
end
+ end
- context 'successfully change ref of similar name' do
- before do
- project.repository.create_branch('dev')
- project.repository.create_branch('development')
- end
-
- it 'switch ref from longer to shorter ref name' do
- visit_blob('files/js/application.js', ref: 'development')
- switch_ref_to('dev')
-
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
- end
- end
+ context 'successfully change ref of similar name' do
+ before do
+ project.repository.create_branch('dev')
+ project.repository.create_branch('development')
+ end
- it 'switch ref from shorter to longer ref name' do
- visit_blob('files/js/application.js', ref: 'dev')
- switch_ref_to('development')
+ it 'switch ref from longer to shorter ref name' do
+ visit_blob('files/js/application.js', ref: 'development')
+ switch_ref_to('dev')
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
- end
+ aggregate_failures do
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ expect(page).not_to have_css('flash-container')
end
end
- it 'successfully changes ref when the ref name matches the project name' do
- project.repository.create_branch(project.name)
-
- visit_blob('files/js/application.js', ref: project.name)
- switch_ref_to('master')
+ it 'switch ref from shorter to longer ref name' do
+ visit_blob('files/js/application.js', ref: 'dev')
+ switch_ref_to('development')
aggregate_failures do
expect(page.find('.file-title-name').text).to eq('application.js')
@@ -206,133 +192,216 @@ RSpec.describe 'File blob', :js do
end
end
end
+
+ it 'successfully changes ref when the ref name matches the project name' do
+ project.repository.create_branch(project.name)
+
+ visit_blob('files/js/application.js', ref: project.name)
+ switch_ref_to('master')
+
+ aggregate_failures do
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ expect(page).not_to have_css('flash-container')
+ end
+ end
+ end
+ end
+
+ context 'Markdown rendering' do
+ before do
+ project.add_maintainer(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add RedCarpet and CommonMark Markdown ",
+ file_path: 'files/commonmark/file.md',
+ file_content: "1. one\n - sublist\n"
+ ).execute
end
- context 'Markdown rendering' do
+ context 'when rendering default markdown' do
before do
- project.add_maintainer(project.creator)
+ visit_blob('files/commonmark/file.md')
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add RedCarpet and CommonMark Markdown ",
- file_path: 'files/commonmark/file.md',
- file_content: "1. one\n - sublist\n"
- ).execute
+ wait_for_requests
end
- context 'when rendering default markdown' do
- before do
- visit_blob('files/commonmark/file.md')
-
- wait_for_requests
+ it 'renders using CommonMark' do
+ aggregate_failures do
+ expect(page).to have_content("sublist")
+ expect(page).not_to have_xpath("//ol//li//ul")
end
+ end
+ end
+ end
- it 'renders using CommonMark' do
- aggregate_failures do
- expect(page).to have_content("sublist")
- expect(page).not_to have_xpath("//ol//li//ul")
- end
+ context 'Markdown file (stored in LFS)' do
+ before do
+ project.add_maintainer(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')
+
+ wait_for_requests
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an error message
+ expect(page).to have_content('This content could not be displayed because it is stored in LFS. 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 'Markdown file (stored in LFS)' do
+ context 'when LFS is disabled on the project' do
before do
- project.add_maintainer(project.creator)
+ visit_blob('files/lfs/file.md')
- 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
+ wait_for_requests
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)
+ 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')
- visit_blob('files/lfs/file.md')
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
- wait_for_requests
+ # shows a raw button
+ expect(page).to have_link('Open raw')
end
+ end
+ end
+ end
- it 'displays an error' do
- aggregate_failures do
- # hides the simple viewer
- expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
- expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+ context 'PDF file' do
+ before do
+ project.add_maintainer(project.creator)
- # shows an error message
- expect(page).to have_content('This content could not be displayed because it is stored in LFS. You can download it instead.')
+ 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
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ visit_blob('files/test.pdf')
- # does not show a copy button
- expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ wait_for_requests
+ end
- # shows a download button
- expect(page).to have_link('Download')
- end
- 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 'when LFS is disabled on the project' do
- before do
- visit_blob('files/lfs/file.md')
+ context 'Jupiter Notebook file' do
+ before do
+ project.add_maintainer(project.creator)
- wait_for_requests
- end
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add Jupiter Notebook",
+ file_path: 'files/basic.ipynb',
+ file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
+ ).execute
- it 'displays the blob' do
- aggregate_failures do
- # shows text
- expect(page).to have_content('size 1575078')
+ visit_blob('files/basic.ipynb')
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ wait_for_requests
+ end
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows rendered notebook
+ expect(page).to have_selector('.js-notebook-viewer-mounted')
- # shows a raw button
- expect(page).to have_link('Open raw')
- end
- end
+ # does show a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # show 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')
+
+ # shows the rendered notebook
+ expect(page).to have_content('test')
end
end
+ end
- context 'PDF file' do
+ context 'ISO file (stored in LFS)' do
+ context 'when LFS is enabled on the project' do
before do
- project.add_maintainer(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
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
- visit_blob('files/test.pdf')
+ visit_blob('files/lfs/lfs_object.iso')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
- # shows rendered PDF
- expect(page).to have_selector('.js-pdf-viewer')
+ # shows a download link
+ expect(page).to have_link('Download (1.50 MiB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
@@ -346,126 +415,108 @@ RSpec.describe 'File blob', :js do
end
end
- context 'Jupiter Notebook file' do
+ context 'when LFS is disabled on the project' do
before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add Jupiter Notebook",
- file_path: 'files/basic.ipynb',
- file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
- ).execute
-
- visit_blob('files/basic.ipynb')
+ visit_blob('files/lfs/lfs_object.iso')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
- # shows rendered notebook
- expect(page).to have_selector('.js-notebook-viewer-mounted')
+ # shows text
+ expect(page).to have_content('size 1575078')
- # does show a viewer switcher
- expect(page).to have_selector('.js-blob-viewer-switcher')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # show a disabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+ # 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')
-
- # shows the rendered notebook
- expect(page).to have_content('test')
end
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')
+ context 'ZIP file' do
+ before do
+ visit_blob('Gemfile.zip')
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'displays the blob' do
- aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (1.50 MiB)')
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (2.11 KiB)')
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ # 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 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
+ # 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')
+ context 'binary file that appears to be text in the first 1024 bytes' do
+ before do
+ visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
+ end
- wait_for_requests
- end
+ it 'displays the blob' do
+ expect(page).to have_link('Download (23.81 KiB)')
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ expect(page).not_to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ expect(page).not_to have_link('Open raw')
+ end
+ end
- it 'displays the blob' do
- aggregate_failures do
- # shows text
- expect(page).to have_content('size 1575078')
+ context 'empty file' do
+ before do
+ project.add_maintainer(project.creator)
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ 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
- # shows an enabled copy button
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ visit_blob('files/empty.md')
- # shows a raw button
- expect(page).to have_link('Open raw')
- end
- end
- end
+ wait_for_requests
end
- context 'ZIP file' do
- before do
- visit_blob('Gemfile.zip')
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('Empty file')
- wait_for_requests
- end
-
- it 'displays the blob' do
- aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (2.11 KiB)')
-
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
+ # 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 copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
- # shows a download button
- expect(page).to have_link('Download')
- end
+ # 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 'empty file' do
+ context 'files with auxiliary viewers' do
+ describe '.gitlab-ci.yml' do
before do
project.add_maintainer(project.creator)
@@ -474,660 +525,586 @@ RSpec.describe 'File blob', :js do
project.creator,
start_branch: 'master',
branch_name: 'master',
- commit_message: "Add empty file",
- file_path: 'files/empty.md',
- file_content: ''
+ 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('files/empty.md')
-
- wait_for_requests
+ visit_blob('.gitlab-ci.yml')
end
- it 'displays an error' do
+ it 'displays an auxiliary viewer' do
aggregate_failures do
- # shows an error message
- expect(page).to have_content('Empty file')
+ # shows that configuration is valid
+ expect(page).to have_content('This GitLab CI configuration is valid.')
- # 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')
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
end
end
end
- context 'files with auxiliary viewers' do
- describe '.gitlab-ci.yml' do
- before do
- project.add_maintainer(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
+ describe '.gitlab/route-map.yml' do
+ before do
+ project.add_maintainer(project.creator)
- 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.')
+ 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
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
+ visit_blob('.gitlab/route-map.yml')
end
- describe '.gitlab/route-map.yml' do
- before do
- project.add_maintainer(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')
+ 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
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that map is valid
- expect(page).to have_content('This Route Map is valid.')
+ describe '.gitlab/dashboards/custom-dashboard.yml' do
+ before do
+ project.add_maintainer(project.creator)
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
+ file_path: '.gitlab/dashboards/custom-dashboard.yml',
+ file_content: file_content
+ ).execute
end
- describe '.gitlab/dashboards/custom-dashboard.yml' do
+ context 'with metrics_dashboard_exhaustive_validations feature flag off' do
before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
- file_path: '.gitlab/dashboards/custom-dashboard.yml',
- file_content: file_content
- ).execute
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
- context 'with metrics_dashboard_exhaustive_validations feature flag off' do
- before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
- end
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
end
end
+ end
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
end
end
end
+ end
- context 'with metrics_dashboard_exhaustive_validations feature flag on' do
- before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
- end
+ context 'with metrics_dashboard_exhaustive_validations feature flag on' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ end
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
end
end
+ end
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("root is missing required keys: panel_groups")
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("root is missing required keys: panel_groups")
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
end
end
end
end
+ end
- context 'LICENSE' do
- before do
- visit_blob('LICENSE')
- 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.')
+ 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', href: 'http://choosealicense.com/licenses/mit/')
- end
+ # shows a learn more link
+ expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
end
end
+ end
- context '*.gemspec' do
- before do
- project.add_maintainer(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
+ context '*.gemspec' do
+ before do
+ project.add_maintainer(project.creator)
- 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.')
+ 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
- # shows a learn more link
- expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
- end
- end
+ visit_blob('activerecord.gemspec')
end
- context 'CONTRIBUTING.md' do
- before do
- file_name = 'CONTRIBUTING.md'
+ 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.')
- create_file(file_name, '## Contribution guidelines')
- visit_blob(file_name)
+ # shows a learn more link
+ expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
end
+ end
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
- end
+ context 'CONTRIBUTING.md' do
+ before do
+ file_name = 'CONTRIBUTING.md'
+
+ create_file(file_name, '## Contribution guidelines')
+ visit_blob(file_name)
+ end
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
end
end
+ end
- context 'CHANGELOG.md' do
- before do
- file_name = 'CHANGELOG.md'
+ context 'CHANGELOG.md' do
+ before do
+ file_name = 'CHANGELOG.md'
- create_file(file_name, '## Changelog for v1.0.0')
- visit_blob(file_name)
- end
+ create_file(file_name, '## Changelog for v1.0.0')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
end
end
+ end
- context 'Cargo.toml' do
- before do
- file_name = 'Cargo.toml'
-
- create_file(file_name, '
- [package]
- name = "hello_world" # the name of the package
- version = "0.1.0" # the current version, obeying semver
- authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
- ')
- visit_blob(file_name)
- end
+ context 'Cargo.toml' do
+ before do
+ file_name = 'Cargo.toml'
+
+ create_file(file_name, '
+ [package]
+ name = "hello_world" # the name of the package
+ version = "0.1.0" # the current version, obeying semver
+ authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Cargo.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Cargo.")
end
end
+ end
- context 'Cartfile' do
- before do
- file_name = 'Cartfile'
+ context 'Cartfile' do
+ before do
+ file_name = 'Cartfile'
- create_file(file_name, '
- gitlab "Alamofire/Alamofire" == 4.9.0
- gitlab "Alamofire/AlamofireImage" ~> 3.4
- ')
- visit_blob(file_name)
- end
+ create_file(file_name, '
+ gitlab "Alamofire/Alamofire" == 4.9.0
+ gitlab "Alamofire/AlamofireImage" ~> 3.4
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Carthage.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Carthage.")
end
end
+ end
- context 'composer.json' do
- before do
- file_name = 'composer.json'
-
- create_file(file_name, '
- {
- "license": "MIT"
- }
- ')
- visit_blob(file_name)
- end
+ context 'composer.json' do
+ before do
+ file_name = 'composer.json'
+
+ create_file(file_name, '
+ {
+ "license": "MIT"
+ }
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Composer.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Composer.")
end
end
+ end
- context 'Gemfile' do
- before do
- file_name = 'Gemfile'
+ context 'Gemfile' do
+ before do
+ file_name = 'Gemfile'
- create_file(file_name, '
- source "https://rubygems.org"
+ create_file(file_name, '
+ source "https://rubygems.org"
- # Gems here
- ')
- visit_blob(file_name)
- end
+ # Gems here
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Bundler.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Bundler.")
end
end
+ end
- context 'Godeps.json' do
- before do
- file_name = 'Godeps.json'
-
- create_file(file_name, '
- {
- "GoVersion": "go1.6"
- }
- ')
- visit_blob(file_name)
- end
+ context 'Godeps.json' do
+ before do
+ file_name = 'Godeps.json'
+
+ create_file(file_name, '
+ {
+ "GoVersion": "go1.6"
+ }
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using godep.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using godep.")
end
end
+ end
- context 'go.mod' do
- before do
- file_name = 'go.mod'
+ context 'go.mod' do
+ before do
+ file_name = 'go.mod'
- create_file(file_name, '
- module example.com/mymodule
+ create_file(file_name, '
+ module example.com/mymodule
- go 1.14
- ')
- visit_blob(file_name)
- end
+ go 1.14
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Go Modules.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Go Modules.")
end
end
+ end
- context 'package.json' do
- before do
- file_name = 'package.json'
-
- create_file(file_name, '
- {
- "name": "my-awesome-package",
- "version": "1.0.0"
- }
- ')
- visit_blob(file_name)
- end
+ context 'package.json' do
+ before do
+ file_name = 'package.json'
+
+ create_file(file_name, '
+ {
+ "name": "my-awesome-package",
+ "version": "1.0.0"
+ }
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using npm.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using npm.")
end
end
+ end
- context 'podfile' do
- before do
- file_name = 'podfile'
+ context 'podfile' do
+ before do
+ file_name = 'podfile'
- create_file(file_name, 'platform :ios, "8.0"')
- visit_blob(file_name)
- end
+ create_file(file_name, 'platform :ios, "8.0"')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
+ end
- context 'test.podspec' do
- before do
- file_name = 'test.podspec'
-
- create_file(file_name, '
- Pod::Spec.new do |s|
- s.name = "TensorFlowLiteC"
- ')
- visit_blob(file_name)
- end
+ context 'test.podspec' do
+ before do
+ file_name = 'test.podspec'
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
- end
+ create_file(file_name, '
+ Pod::Spec.new do |s|
+ s.name = "TensorFlowLiteC"
+ ')
+ visit_blob(file_name)
end
- context 'JSON.podspec.json' do
- before do
- file_name = 'JSON.podspec.json'
-
- create_file(file_name, '
- {
- "name": "JSON"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
+ end
- context 'requirements.txt' do
- before do
- file_name = 'requirements.txt'
-
- create_file(file_name, 'Project requirements')
- visit_blob(file_name)
- end
+ context 'JSON.podspec.json' do
+ before do
+ file_name = 'JSON.podspec.json'
+
+ create_file(file_name, '
+ {
+ "name": "JSON"
+ }
+ ')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using pip.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
+ end
- context 'yarn.lock' do
- before do
- file_name = 'yarn.lock'
+ context 'requirements.txt' do
+ before do
+ file_name = 'requirements.txt'
- create_file(file_name, '
- # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
- # yarn lockfile v1
- ')
- visit_blob(file_name)
- end
+ create_file(file_name, 'Project requirements')
+ visit_blob(file_name)
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Yarn.")
- end
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using pip.")
end
end
+ end
- context 'openapi.yml' do
- before do
- file_name = 'openapi.yml'
-
- create_file(file_name, '
- swagger: \'2.0\'
- info:
- title: Classic API Resource Documentation
- description: |
- <div class="foo-bar" style="background-color: red;" data-foo-bar="baz">
- <h1>Swagger API documentation</h1>
- </div>
- version: production
- basePath: /JSSResource/
- produces:
- - application/xml
- - application/json
- consumes:
- - application/xml
- - application/json
- security:
- - basicAuth: []
- paths:
- /accounts:
- get:
- responses:
- \'200\':
- description: No response was specified
- tags:
- - accounts
- operationId: findAccounts
- summary: Finds all accounts
- ')
- visit_blob(file_name, useUnsafeMarkdown: '1')
- click_button('Display rendered file')
+ context 'yarn.lock' do
+ before do
+ file_name = 'yarn.lock'
- wait_for_requests
- end
+ create_file(file_name, '
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+ # yarn lockfile v1
+ ')
+ visit_blob(file_name)
+ end
- it 'removes `style`, `class`, and `data-*`` attributes from HTML' do
- expect(page).to have_css('h1', text: 'Swagger API documentation')
- expect(page).not_to have_css('.foo-bar')
- expect(page).not_to have_css('[style="background-color: red;"]')
- expect(page).not_to have_css('[data-foo-bar="baz"]')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ expect(page).to have_content("This project manages its dependencies using Yarn.")
end
end
end
- context 'realtime pipelines' do
+ context 'openapi.yml' do
before do
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'feature',
- branch_name: 'feature',
- commit_message: "Add ruby file",
- file_path: 'files/ruby/test.rb',
- file_content: "# Awesome content"
- ).execute
+ file_name = 'openapi.yml'
+
+ create_file(file_name, '
+ swagger: \'2.0\'
+ info:
+ title: Classic API Resource Documentation
+ description: |
+ <div class="foo-bar" style="background-color: red;" data-foo-bar="baz">
+ <h1>Swagger API documentation</h1>
+ </div>
+ version: production
+ basePath: /JSSResource/
+ produces:
+ - application/xml
+ - application/json
+ consumes:
+ - application/xml
+ - application/json
+ security:
+ - basicAuth: []
+ paths:
+ /accounts:
+ get:
+ responses:
+ \'200\':
+ description: No response was specified
+ tags:
+ - accounts
+ operationId: findAccounts
+ summary: Finds all accounts
+ ')
+ visit_blob(file_name, useUnsafeMarkdown: '1')
+ click_button('Display rendered file')
- create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
- visit_blob('files/ruby/test.rb', ref: 'feature')
+ wait_for_requests
end
- it 'shows the realtime pipeline status' do
- page.within('.commit-actions') do
- expect(page).to have_css('.ci-status-icon')
- expect(page).to have_css('.ci-status-icon-running')
- expect(page).to have_css('.js-ci-status-icon-running')
- end
+ it 'removes `style`, `class`, and `data-*`` attributes from HTML' do
+ expect(page).to have_css('h1', text: 'Swagger API documentation')
+ expect(page).not_to have_css('.foo-bar')
+ expect(page).not_to have_css('[style="background-color: red;"]')
+ expect(page).not_to have_css('[data-foo-bar="baz"]')
end
end
+ end
- context 'for subgroups' do
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:project) { create(:project, :public, :repository, group: subgroup) }
-
- it 'renders tree table without errors' do
- visit_blob('README.md')
+ context 'realtime pipelines' do
+ before do
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'feature',
+ branch_name: 'feature',
+ commit_message: "Add ruby file",
+ file_path: 'files/ruby/test.rb',
+ file_content: "# Awesome content"
+ ).execute
+
+ create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
+ visit_blob('files/ruby/test.rb', ref: 'feature')
+ end
- expect(page).to have_selector('.file-content')
- expect(page).not_to have_selector('[data-testid="alert-danger"]')
+ it 'shows the realtime pipeline status' do
+ page.within('.commit-actions') do
+ expect(page).to have_css('.ci-status-icon')
+ expect(page).to have_css('.ci-status-icon-running')
+ expect(page).to have_css('.js-ci-status-icon-running')
end
+ end
+ end
- it 'displays a GPG badge' do
- visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
+ context 'for subgroups' do
+ let(:group) { create(:group) }
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project) { create(:project, :public, :repository, group: subgroup) }
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
+ it 'renders tree table without errors' do
+ visit_blob('README.md')
+
+ expect(page).to have_selector('.file-content')
+ expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
- context 'on signed merge commit' do
- it 'displays a GPG badge' do
- visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
+ it 'displays a GPG badge' do
+ visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
+ expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
+ expect(page).to have_selector '.gpg-status-box.invalid'
end
+ end
- context 'when static objects external storage is enabled' do
- before do
- stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
- end
+ context 'on signed merge commit' do
+ it 'displays a GPG badge' do
+ visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
- context 'private project' do
- let_it_be(:project) { create(:project, :repository, :private) }
- let_it_be(:user) { create(:user, static_object_token: 'ABCD1234') }
+ expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
+ expect(page).to have_selector '.gpg-status-box.invalid'
+ end
+ end
- before do
- project.add_developer(user)
+ context 'when static objects external storage is enabled' do
+ before do
+ stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
+ end
- sign_in(user)
- visit_blob('README.md')
- end
+ context 'private project' do
+ let_it_be(:project) { create(:project, :repository, :private) }
+ let_it_be(:user) { create(:user, static_object_token: 'ABCD1234') }
- it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
- download_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}&inline=false"
+ before do
+ project.add_developer(user)
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
- end
+ sign_in(user)
+ visit_blob('README.md')
end
- context 'public project' do
- before do
- visit_blob('README.md')
- end
+ it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
+ path = project_raw_path(project, 'master/README.md')
+ raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
+ download_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}&inline=false"
- it 'shows open raw and download buttons with external storage URL prepended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}"
- download_uri = "https://cdn.gitlab.com#{path}?inline=false"
-
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
+ aggregate_failures do
+ expect(page).to have_link 'Open raw', href: raw_uri
+ expect(page).to have_link 'Download', href: download_uri
end
end
end
- end
-
- context 'with refactor_blob_viewer feature flag disabled' do
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- context 'binary file that appears to be text in the first 1024 bytes' do
- # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
- # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559
+ context 'public project' do
before do
- visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
+ visit_blob('README.md')
end
- it 'displays the blob' do
+
+ it 'shows open raw and download buttons with external storage URL prepended to their href' do
+ path = project_raw_path(project, 'master/README.md')
+ raw_uri = "https://cdn.gitlab.com#{path}"
+ download_uri = "https://cdn.gitlab.com#{path}?inline=false"
+
aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (23.8 KB)')
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
- # The specs below verify an arguably incorrect result, but since we only
- # learn that the file is not actually text once the text viewer content
- # is loaded asynchronously, there is no straightforward way to get these
- # synchronously loaded elements to display correctly.
- #
- # Clicking the copy button will result in nothing being copied.
- # Clicking the raw button will result in the binary file being downloaded,
- # as expected.
- # shows an enabled copy button, incorrectly
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
- # shows a raw button, incorrectly
- expect(page).to have_link('Open raw')
+ expect(page).to have_link 'Open raw', href: raw_uri
+ expect(page).to have_link 'Download', href: download_uri
end
end
end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index d906bb396be..727f9aa486e 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -233,6 +233,8 @@ RSpec.describe 'Branches' do
end
context 'with one or more pipeline', :js do
+ let(:project) { create(:project, :public, :empty_repo) }
+
before do
sha = create_file(branch_name: "branch")
create(:ci_pipeline,
diff --git a/spec/features/projects/ci/secure_files_spec.rb b/spec/features/projects/ci/secure_files_spec.rb
index a0e9d663d35..412330eb5d6 100644
--- a/spec/features/projects/ci/secure_files_spec.rb
+++ b/spec/features/projects/ci/secure_files_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Secure Files', :js do
it 'user sees the Secure Files list component' do
visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no records to show')
+ expect(page).to have_content('There are no secure files yet.')
end
it 'prompts the user to confirm before deleting a file' do
@@ -37,7 +37,7 @@ RSpec.describe 'Secure Files', :js do
it 'displays an uploaded file in the file list' do
visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no records to show')
+ expect(page).to have_content('There are no secure files yet.')
page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
click_button 'Upload File'
diff --git a/spec/features/projects/commits/multi_view_diff_spec.rb b/spec/features/projects/commits/multi_view_diff_spec.rb
index 282112a3767..5af2e367aed 100644
--- a/spec/features/projects/commits/multi_view_diff_spec.rb
+++ b/spec/features/projects/commits/multi_view_diff_spec.rb
@@ -46,28 +46,28 @@ RSpec.describe 'Multiple view Diffs', :js do
end
context 'opening a diff with ipynb' do
- it 'loads the rendered diff as hidden' do
+ it 'loads the raw diff as hidden' do
diff = page.find('.diff-file, .file-holder', match: :first)
- expect(diff).not_to have_selector '[data-diff-toggle-entity="toHide"]'
- expect(diff).to have_selector '[data-diff-toggle-entity="toShow"]'
+ expect(diff).not_to have_selector '[data-diff-toggle-entity="rawViewer"]'
+ expect(diff).to have_selector '[data-diff-toggle-entity="renderedViewer"]'
- expect(classes_for_element(diff, 'toHide', visible: false)).to include('hidden')
- expect(classes_for_element(diff, 'toShow')).not_to include('hidden')
+ expect(classes_for_element(diff, 'rawViewer', visible: false)).to include('hidden')
+ expect(classes_for_element(diff, 'renderedViewer')).not_to include('hidden')
- expect(classes_for_element(diff, 'toShowBtn')).to include('selected')
- expect(classes_for_element(diff, 'toHideBtn')).not_to include('selected')
+ expect(classes_for_element(diff, 'renderedButton')).to include('selected')
+ expect(classes_for_element(diff, 'rawButton')).not_to include('selected')
end
- it 'displays the rendered diff and hides after selection changes' do
+ it 'displays the raw diff and hides after selection changes' do
diff = page.find('.diff-file, .file-holder', match: :first)
- diff.find('[data-diff-toggle-entity="toShowBtn"]').click
+ diff.find('[data-diff-toggle-entity="rawButton"]').click
- expect(diff).to have_selector '[data-diff-toggle-entity="toShow"]'
- expect(diff).not_to have_selector '[data-diff-toggle-entity="toHide"]'
+ expect(diff).to have_selector '[data-diff-toggle-entity="rawViewer"]'
+ expect(diff).not_to have_selector '[data-diff-toggle-entity="renderedViewer"]'
- expect(classes_for_element(diff, 'toHideBtn')).not_to include('selected')
- expect(classes_for_element(diff, 'toShowBtn')).to include('selected')
+ expect(classes_for_element(diff, 'renderedButton')).not_to include('selected')
+ expect(classes_for_element(diff, 'rawButton')).to include('selected')
end
it 'transforms the diff' do
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index bf705cf875b..06462263f5a 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -3,22 +3,38 @@
require 'spec_helper'
RSpec.describe 'Project deploy keys', :js do
- let(:user) { create(:user) }
- let(:project) { create(:project_empty_repo) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project_empty_repo) }
+ let_it_be(:deploy_keys_project) { create(:deploy_keys_project, project: project) }
+ let_it_be(:deploy_key) { deploy_keys_project.deploy_key }
before do
project.add_maintainer(user)
sign_in(user)
end
+ context 'editing key' do
+ it 'shows fingerprints' do
+ visit edit_project_deploy_key_path(project, deploy_key)
+
+ expect(page).to have_content('Fingerprint (SHA256)')
+ expect(find('#deploy_key_fingerprint_sha256').value).to eq(deploy_key.fingerprint_sha256)
+
+ if Gitlab::FIPS.enabled?
+ expect(page).not_to have_content('Fingerprint (MD5)')
+ else
+ expect(page).to have_content('Fingerprint (MD5)')
+ expect(find('#deploy_key_fingerprint').value).to eq(deploy_key.fingerprint)
+ end
+ end
+ end
+
describe 'removing key' do
before do
- create(:deploy_keys_project, project: project)
+ visit project_settings_repository_path(project)
end
it 'removes association between project and deploy key' do
- visit project_settings_repository_path(project)
-
page.within(find('.rspec-deploy-keys-settings')) do
expect(page).to have_selector('.deploy-key', count: 1)
diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb
index 56506ada3ce..dcd6f1239bb 100644
--- a/spec/features/projects/diffs/diff_show_spec.rb
+++ b/spec/features/projects/diffs/diff_show_spec.rb
@@ -169,8 +169,8 @@ RSpec.describe 'Diff file viewer', :js, :with_clean_rails_cache do
wait_for_requests
end
- it 'shows there is no preview' do
- expect(page).to have_content('No preview for this file type')
+ it 'shows that file was added' do
+ expect(page).to have_content('File added')
end
end
end
diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb
deleted file mode 100644
index 531eae1d638..00000000000
--- a/spec/features/projects/environments_pod_logs_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do
- include KubernetesHelpers
-
- let(:pod_names) { %w(kube-pod) }
- let(:pod_name) { pod_names.first }
- let(:project) { create(:project, :repository) }
- let(:environment) { create(:environment, project: project) }
- let(:service) { create(:cluster_platform_kubernetes, :configured) }
-
- before do
- cluster = create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project])
- create(:deployment, :success, environment: environment)
-
- stub_kubeclient_pods(environment.deployment_namespace)
- stub_kubeclient_logs(pod_name, environment.deployment_namespace, container: 'container-0')
- stub_kubeclient_deployments(environment.deployment_namespace)
- stub_kubeclient_ingresses(environment.deployment_namespace)
- stub_kubeclient_nodes_and_nodes_metrics(cluster.platform.api_url)
-
- sign_in(project.first_owner)
- end
-
- it "shows environments in dropdown" do
- create(:environment, project: project)
-
- visit project_logs_path(environment.project, environment_name: environment.name, pod_name: pod_name)
-
- wait_for_requests
-
- page.within('.js-environments-dropdown') do
- toggle = find(".dropdown-toggle:not([disabled])")
-
- expect(toggle).to have_content(environment.name)
-
- toggle.click
-
- dropdown_items = find(".dropdown-menu").all(".dropdown-item")
- expect(dropdown_items.first).to have_content(environment.name)
- expect(dropdown_items.size).to eq(2)
- end
- end
-
- context 'with logs', :use_clean_rails_memory_store_caching do
- it "shows pod logs", :sidekiq_might_not_need_inline do
- visit project_logs_path(environment.project, environment_name: environment.name, pod_name: pod_name)
-
- wait_for_requests
-
- page.within('.qa-pods-dropdown') do # rubocop:disable QA/SelectorUsage
- find(".dropdown-toggle:not([disabled])").click
-
- dropdown_items = find(".dropdown-menu").all(".dropdown-item:not([disabled])")
- expect(dropdown_items.size).to eq(1)
-
- dropdown_items.each_with_index do |item, i|
- expect(item.text).to eq(pod_names[i])
- end
- end
- expect(page).to have_content("kube-pod | Log 1")
- expect(page).to have_content("kube-pod | Log 2")
- expect(page).to have_content("kube-pod | Log 3")
- end
- end
-end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index 3a0cc61d9c6..dd1635c900e 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -26,6 +26,6 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do
wait_for_requests
expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(editor_get_value).to have_content('COPY ./ /usr/local/apache2/htdocs/')
+ expect(find('.monaco-editor')).to have_content('COPY ./ /usr/local/apache2/htdocs/')
end
end
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index 4a92216f46c..a86adf951d8 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do
wait_for_requests
expect(page).to have_css('.gitignore-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(editor_get_value).to have_content('/.bundle')
- expect(editor_get_value).to have_content('config/initializers/secret_token.rb')
+ expect(find('.monaco-editor')).to have_content('/.bundle')
+ expect(find('.monaco-editor')).to have_content('config/initializers/secret_token.rb')
end
end
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 cdf6c219ea5..46ac0dee7eb 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -30,8 +30,8 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
wait_for_requests
expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
- expect(editor_get_value).to have_content('jekyll build -d test')
+ expect(find('.monaco-editor')).to have_content('This file is a template, and might need editing before it works on your project')
+ expect(find('.monaco-editor')).to have_content('jekyll build -d test')
end
context 'when template param is provided' do
@@ -41,8 +41,8 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
wait_for_requests
expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
- expect(editor_get_value).to have_content('jekyll build -d test')
+ expect(find('.monaco-editor')).to have_content('This file is a template, and might need editing before it works on your project')
+ expect(find('.monaco-editor')).to have_content('jekyll build -d test')
end
end
@@ -53,7 +53,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
wait_for_requests
expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(editor_get_value).to have_content('')
+ expect(find('.monaco-editor')).to have_content('')
end
end
@@ -64,7 +64,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
it 'leaves the editor empty' do
wait_for_requests
- expect(editor_get_value).to have_content('')
+ expect(find('.monaco-editor')).to have_content('')
end
end
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 0e87622d3c2..6b1e60db5b1 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
@@ -22,8 +22,10 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
select_template('MIT License')
- expect(ide_editor_value).to have_content('MIT License')
- expect(ide_editor_value).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
+ file_content = "Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}"
+
+ expect(find('.monaco-editor')).to have_content('MIT License')
+ expect(find('.monaco-editor')).to have_content(file_content)
ide_commit
@@ -33,7 +35,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
license_file = project.repository.blob_at('master', 'LICENSE').data
expect(license_file).to have_content('MIT License')
- expect(license_file).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
+ expect(license_file).to have_content(file_content)
end
def select_template(template)
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index a904ba770dd..b6019944071 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -12,8 +12,6 @@ RSpec.describe 'Project Jobs Permissions' do
let_it_be(:job) { create(:ci_build, :running, :coverage, :trace_artifact, pipeline: pipeline) }
before do
- stub_feature_flags(jobs_table_vue: false)
-
sign_in(user)
project.enable_ci
@@ -96,8 +94,8 @@ RSpec.describe 'Project Jobs Permissions' do
end
it_behaves_like 'project jobs page responds with status', 200 do
- it 'renders job' do
- page.within('.build') do
+ it 'renders job', :js do
+ page.within('[data-testid="jobs-table"]') do
expect(page).to have_content("##{job.id}")
.and have_content(job.sha[0..7])
.and have_content(job.ref)
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 6a2d2c36521..6a0cfcde812 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -90,4 +90,27 @@ RSpec.describe 'User browses a job', :js do
end
end
end
+
+ context 'job log search' do
+ before do
+ visit(project_job_path(project, build))
+ wait_for_all_requests
+ end
+
+ it 'searches for supplied substring' do
+ find('[data-testid="job-log-search-box"] input').set('GroupsHelper')
+
+ find('[data-testid="search-button"]').click
+
+ expect(page).to have_content('26 results found for GroupsHelper')
+ end
+
+ it 'shows no results for supplied substring' do
+ find('[data-testid="job-log-search-box"] input').set('YouWontFindMe')
+
+ find('[data-testid="search-button"]').click
+
+ expect(page).to have_content('No search results found')
+ end
+ end
end
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index 07b7a54974a..bb44b70bb3a 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -9,48 +9,11 @@ def visit_jobs_page
end
RSpec.describe 'User browses jobs' do
- describe 'with jobs_table_vue feature flag turned off' do
- let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
- let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
- let(:user) { create(:user) }
-
- before do
- stub_feature_flags(jobs_table_vue: false)
- project.add_maintainer(user)
- project.enable_ci
- build.update!(coverage_regex: '/Coverage (\d+)%/')
-
- sign_in(user)
-
- visit(project_jobs_path(project))
- end
-
- it 'shows the coverage' do
- page.within('td.coverage') do
- expect(page).to have_content('99.9%')
- end
- end
-
- context 'with a failed job' do
- let!(:build) { create(:ci_build, :coverage, :failed, pipeline: pipeline) }
-
- it 'displays a tooltip with the failure reason' do
- page.within('.ci-table') do
- failed_job_link = page.find('.ci-failed')
- expect(failed_job_link[:title]).to eq('Failed - (unknown failure)')
- end
- end
- end
- end
-
- describe 'with jobs_table_vue feature flag turned on', :js do
+ describe 'Jobs', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
before do
- stub_feature_flags(jobs_table_vue: true)
-
project.add_maintainer(user)
project.enable_ci
@@ -135,6 +98,26 @@ RSpec.describe 'User browses jobs' do
end
end
+ context 'with a coverage job' do
+ let!(:job) do
+ create(:ci_build, :coverage, pipeline: pipeline)
+ end
+
+ before do
+ job.update!(coverage_regex: '/Coverage (\d+)%/')
+
+ visit_jobs_page
+
+ wait_for_requests
+ end
+
+ it 'shows the coverage' do
+ page.within('[data-testid="job-coverage"]') do
+ expect(page).to have_content('99.9%')
+ end
+ end
+ end
+
context 'with a scheduled job' do
let!(:scheduled_job) { create(:ci_build, :scheduled, pipeline: pipeline, name: 'build') }
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index f0d41c1dd11..84c75752bc1 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -20,7 +20,6 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end
before do
- stub_feature_flags(jobs_table_vue: false)
project.add_role(user, user_access_level)
sign_in(user)
end
@@ -29,9 +28,11 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'with no jobs' do
before do
visit project_jobs_path(project)
+
+ wait_for_requests
end
- it 'shows the empty state page' do
+ it 'shows the empty state page', :js do
expect(page).to have_content('Use jobs to automate your tasks')
expect(page).to have_link('Create CI/CD configuration file', href: project_ci_pipeline_editor_path(project))
end
@@ -40,59 +41,6 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'with a job' do
let!(:job) { create(:ci_build, pipeline: pipeline) }
- context "Pending scope" do
- before do
- visit project_jobs_path(project, scope: :pending)
- end
-
- it "shows Pending tab jobs" do
- expect(page).to have_selector('[data-testid="jobs-tabs"] a.active', text: 'Pending')
- expect(page).to have_content job.short_sha
- expect(page).to have_content job.ref
- expect(page).to have_content job.name
- end
- end
-
- context "Running scope" do
- before do
- job.run!
- visit project_jobs_path(project, scope: :running)
- end
-
- it "shows Running tab jobs" do
- expect(page).to have_selector('[data-testid="jobs-tabs"] a.active', text: 'Running')
- expect(page).to have_content job.short_sha
- expect(page).to have_content job.ref
- expect(page).to have_content job.name
- end
- end
-
- context "Finished scope" do
- before do
- job.run!
- visit project_jobs_path(project, scope: :finished)
- end
-
- it "shows Finished tab jobs" do
- expect(page).to have_selector('[data-testid="jobs-tabs"] a.active', text: 'Finished')
- expect(page).to have_content('Use jobs to automate your tasks')
- end
- end
-
- context "All jobs" do
- before do
- project.builds.running_or_pending.each(&:success)
- visit project_jobs_path(project)
- end
-
- it "shows All tab jobs" do
- expect(page).to have_selector('[data-testid="jobs-tabs"] a.active', text: 'All')
- expect(page).to have_content job.short_sha
- expect(page).to have_content job.ref
- expect(page).to have_content job.name
- end
- end
-
context "when visiting old URL" do
let(:jobs_url) do
project_jobs_path(project)
@@ -1207,22 +1155,4 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
it { expect(page.status_code).to eq(404) }
end
end
-
- describe "GET /:project/jobs/:id/status" do
- context "Job from project" do
- before do
- visit status_project_job_path(project, job)
- end
-
- it { expect(page.status_code).to eq(200) }
- end
-
- context "Job from other project" do
- before do
- visit status_project_job_path(project, job2)
- end
-
- it { expect(page.status_code).to eq(404) }
- end
- 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 bd0874316ac..c92e8bc2954 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
@@ -32,7 +32,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
end
it 'changes expiration date' do
- project.team.add_users([new_member.id], :developer, expires_at: three_days_from_now)
+ project.team.add_members([new_member.id], :developer, expires_at: three_days_from_now)
visit project_project_members_path(project)
page.within find_member_row(new_member) do
@@ -46,7 +46,7 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
end
it 'clears expiration date' do
- project.team.add_users([new_member.id], :developer, expires_at: five_days_from_now)
+ project.team.add_members([new_member.id], :developer, expires_at: five_days_from_now)
visit project_project_members_path(project)
page.within find_member_row(new_member) do
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 023601b0b1e..e07a5d09405 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'Project navbar' do
stub_config(pages: { enabled: true })
insert_after_sub_nav_item(
- _('CI/CD'),
+ _('Packages & Registries'),
within: _('Settings'),
new_sub_nav_item_name: _('Pages')
)
@@ -60,18 +60,22 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar'
end
+ context 'when package registry is available' do
+ before do
+ stub_config(packages: { enabled: true })
+
+ visit project_path(project)
+ end
+
+ it_behaves_like 'verified navigation bar'
+ end
+
context 'when container registry is available' do
before do
stub_config(registry: { enabled: true })
insert_container_nav
- insert_after_sub_nav_item(
- _('CI/CD'),
- within: _('Settings'),
- new_sub_nav_item_name: _('Packages & Registries')
- )
-
visit project_path(project)
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index a1e92a79516..9d2d1454d77 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -61,15 +61,15 @@ RSpec.describe 'New project', :js do
expect(page).to have_link('GitLab export')
end
- describe 'github import option' do
+ shared_examples 'renders importer link' do |params|
context 'with user namespace' do
before do
visit new_project_path
click_link 'Import project'
end
- it 'renders link to github importer' do
- expect(page).to have_link(href: new_import_github_path)
+ it "renders link to #{params[:name]} importer" do
+ expect(page).to have_link(href: Rails.application.routes.url_helpers.send(params[:route]))
end
end
@@ -82,21 +82,56 @@ RSpec.describe 'New project', :js do
click_link 'Import project'
end
- it 'renders link to github importer including namespace id' do
- expect(page).to have_link(href: new_import_github_path(namespace_id: group.id))
+ it "renders link to #{params[:name]} importer including namespace id" do
+ expect(page).to have_link(href: Rails.application.routes.url_helpers.send(params[:route], namespace_id: group.id))
end
end
end
- describe 'manifest import option' do
- before do
- visit new_project_path
+ describe 'importer links' do
+ shared_examples 'link to importers' do
+ let(:importer_routes) do
+ {
+ 'github': :new_import_github_path,
+ 'bitbucket': :status_import_bitbucket_path,
+ 'bitbucket server': :status_import_bitbucket_server_path,
+ 'gitlab.com': :status_import_gitlab_path,
+ 'fogbugz': :new_import_fogbugz_path,
+ 'gitea': :new_import_gitea_path,
+ 'manifest': :new_import_manifest_path,
+ 'phabricator': :new_import_phabricator_path
+ }
+ end
+
+ it 'renders links to several importers', :aggregate_failures do
+ importer_routes.each_value do |route|
+ expect(page).to have_link(href: Rails.application.routes.url_helpers.send(route, link_params))
+ end
+ end
+ end
- click_link 'Import project'
+ context 'with user namespace' do
+ let(:link_params) { {} }
+
+ before do
+ visit new_project_path
+ click_link 'Import project'
+ end
+
+ include_examples 'link to importers'
end
- it 'has Manifest file' do
- expect(page).to have_link('Manifest file')
+ context 'with group namespace' do
+ let(:group) { create(:group, :private) }
+ let(:link_params) { { namespace_id: group.id } }
+
+ before do
+ group.add_owner(user)
+ visit new_project_path(namespace_id: group.id)
+ click_link 'Import project'
+ end
+
+ include_examples 'link to importers'
end
end
diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
index 3f89e344c51..15d889933bf 100644
--- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
@@ -357,6 +357,10 @@ RSpec.describe 'Pipelines', :js do
end
it 'enqueues the delayed job', :js do
+ find('[data-testid="mini-pipeline-graph-dropdown"]').click
+
+ within('[data-testid="mini-pipeline-graph-dropdown"]') { find('.ci-status-icon-pending') }
+
expect(delayed_job.reload).to be_pending
end
end
diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb
index 9e428a0623d..10c4395da81 100644
--- a/spec/features/projects/releases/user_creates_release_spec.rb
+++ b/spec/features/projects/releases/user_creates_release_spec.rb
@@ -111,6 +111,27 @@ RSpec.describe 'User creates release', :js do
end
end
+ context 'when tag name supplied in the parameters' do
+ let(:new_page_url) { new_project_release_path(project, tag_name: 'v1.1.0') }
+
+ it 'creates release with preselected tag' do
+ page.within '[data-testid="tag-name-field"]' do
+ expect(page).to have_text('v1.1.0')
+ end
+
+ expect(page).not_to have_selector('[data-testid="create-from-field"]')
+
+ fill_release_title("test release")
+ click_button('Create release')
+
+ wait_for_all_requests
+
+ release = project.releases.last
+
+ expect(release.tag).to eq('v1.1.0')
+ end
+ end
+
def fill_out_form_and_submit
select_new_tag_name(tag_name)
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index ff28d59ed08..9468540736f 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration policy', :js do
+RSpec.describe 'Project > Settings > Packages & Registries > Container registry tag expiration policy', :js do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) }
@@ -23,14 +23,15 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'shows available section' do
subject
- settings_block = find('[data-testid="registry-settings-app"]')
+ settings_block = find('[data-testid="container-expiration-policy-project-settings"]')
expect(settings_block).to have_text 'Clean up image tags'
end
it 'saves cleanup policy submit the form' do
subject
- within '[data-testid="registry-settings-app"]' do
+ within '[data-testid="container-expiration-policy-project-settings"]' do
+ click_button('Expand')
select('Every day', from: 'Run cleanup')
select('50 tags per image name', from: 'Keep the most recent:')
fill_in('Keep tags matching:', with: 'stable')
@@ -48,7 +49,8 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not save cleanup policy submit form with invalid regex' do
subject
- within '[data-testid="registry-settings-app"]' do
+ within '[data-testid="container-expiration-policy-project-settings"]' do
+ click_button('Expand')
fill_in('Remove tags matching:', with: '*-production')
submit_button = find('[data-testid="save-button"')
@@ -73,7 +75,8 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'displays the related section' do
subject
- within '[data-testid="registry-settings-app"]' do
+ within '[data-testid="container-expiration-policy-project-settings"]' do
+ click_button('Expand')
expect(find('[data-testid="enable-toggle"]')).to have_content('Disabled - Tags will not be automatically deleted.')
end
end
@@ -87,7 +90,8 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not display the related section' do
subject
- within '[data-testid="registry-settings-app"]' do
+ within '[data-testid="container-expiration-policy-project-settings"]' do
+ click_button('Expand')
expect(find('.gl-alert-title')).to have_content('Cleanup policy for tags is disabled')
end
end
@@ -100,7 +104,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not exists' do
subject
- expect(page).not_to have_selector('[data-testid="registry-settings-app"]')
+ expect(page).not_to have_selector('[data-testid="container-expiration-policy-project-settings"]')
end
end
@@ -110,7 +114,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
it 'does not exists' do
subject
- expect(page).not_to have_selector('[data-testid="registry-settings-app"]')
+ expect(page).not_to have_selector('[data-testid="container-expiration-policy-project-settings"]')
end
end
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 72ada356225..ddfed73e2ca 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -179,7 +179,6 @@ RSpec.describe 'Projects > Settings > Repository settings' do
expect(page).to have_css(".js-mirror-url-hidden[value=\"#{ssh_url}\"]", visible: false)
select 'SSH public key', from: 'Authentication method'
-
select_direction
Sidekiq::Testing.fake! do
diff --git a/spec/features/projects/settings/secure_files_settings_spec.rb b/spec/features/projects/settings/secure_files_settings_spec.rb
deleted file mode 100644
index c7c9cafc420..00000000000
--- a/spec/features/projects/settings/secure_files_settings_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Secure Files Settings' do
- let_it_be(:maintainer) { create(:user) }
- let_it_be(:project) { create(:project, creator_id: maintainer.id) }
-
- before_all do
- project.add_maintainer(maintainer)
- end
-
- context 'when the :ci_secure_files feature flag is enabled' do
- before do
- stub_feature_flags(ci_secure_files: true)
-
- sign_in(user)
- visit project_settings_ci_cd_path(project)
- end
-
- context 'authenticated user with admin permissions' do
- let(:user) { maintainer }
-
- it 'shows the secure files settings' do
- expect(page).to have_content('Secure Files')
- end
- end
- end
-
- context 'when the :ci_secure_files feature flag is disabled' do
- before do
- stub_feature_flags(ci_secure_files: false)
-
- sign_in(user)
- visit project_settings_ci_cd_path(project)
- end
-
- context 'authenticated user with admin permissions' do
- let(:user) { maintainer }
-
- it 'does not shows the secure files settings' do
- expect(page).not_to have_content('Secure Files')
- end
- end
- end
-end
diff --git a/spec/features/projects/settings/secure_files_spec.rb b/spec/features/projects/settings/secure_files_spec.rb
new file mode 100644
index 00000000000..ee38acf1953
--- /dev/null
+++ b/spec/features/projects/settings/secure_files_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Secure Files', :js do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(ci_secure_files_read_only: false)
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'when the :ci_secure_files feature flag is enabled' do
+ before do
+ stub_feature_flags(ci_secure_files: true)
+
+ visit project_settings_ci_cd_path(project)
+ end
+
+ context 'authenticated user with admin permissions' do
+ it 'shows the secure files settings' do
+ expect(page).to have_content('Secure Files')
+ end
+ end
+ end
+
+ context 'when the :ci_secure_files feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_secure_files: false)
+
+ visit project_settings_ci_cd_path(project)
+ end
+
+ context 'authenticated user with admin permissions' do
+ it 'does not shows the secure files settings' do
+ expect(page).not_to have_content('Secure Files')
+ end
+ end
+ end
+
+ it 'user sees the Secure Files list component' do
+ visit project_settings_ci_cd_path(project)
+
+ within '#js-secure-files' do
+ expect(page).to have_content('There are no secure files yet.')
+ end
+ end
+
+ it 'prompts the user to confirm before deleting a file' do
+ file = create(:ci_secure_file, project: project)
+
+ visit project_settings_ci_cd_path(project)
+
+ within '#js-secure-files' do
+ expect(page).to have_content(file.name)
+
+ find('button.btn-danger-secondary').click
+ end
+
+ expect(page).to have_content("Delete #{file.name}?")
+
+ click_on('Delete secure file')
+
+ visit project_settings_ci_cd_path(project)
+
+ within '#js-secure-files' do
+ expect(page).not_to have_content(file.name)
+ end
+ end
+
+ it 'displays an uploaded file in the file list' do
+ visit project_settings_ci_cd_path(project)
+
+ within '#js-secure-files' do
+ expect(page).to have_content('There are no secure files yet.')
+
+ page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
+ click_button 'Upload File'
+ end
+
+ expect(page).to have_content('upload-keystore.jks')
+ end
+ end
+
+ it 'displays an error when a duplicate file upload is attempted' do
+ create(:ci_secure_file, project: project, name: 'upload-keystore.jks')
+ visit project_settings_ci_cd_path(project)
+
+ within '#js-secure-files' do
+ expect(page).to have_content('upload-keystore.jks')
+
+ page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
+ click_button 'Upload File'
+ end
+
+ expect(page).to have_content('A file with this name already exists.')
+ end
+ end
+end
diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb
index becb30c02b7..fc78b5b5769 100644
--- a/spec/features/projects/settings/visibility_settings_spec.rb
+++ b/spec/features/projects/settings/visibility_settings_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
visibility_select_container = find('.project-visibility-setting')
expect(visibility_select_container.find('select').value).to eq project.visibility_level.to_s
- expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
+ expect(visibility_select_container).to have_content 'Accessible by anyone, regardless of authentication.'
end
it 'project visibility description updates on change' do
@@ -25,7 +25,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
visibility_select.select('Private')
expect(visibility_select.value).to eq '0'
- expect(visibility_select_container).to have_content 'Access must be granted explicitly to each user.'
+ expect(visibility_select_container).to have_content 'Only accessible by project members. Membership must be explicitly granted to each user.'
end
context 'merge requests select' do
@@ -86,7 +86,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
visibility_select_container = find('.project-visibility-setting')
expect(visibility_select_container).to have_selector 'select[name="project[visibility_level]"]:disabled'
- expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
+ expect(visibility_select_container).to have_content 'Accessible by anyone, regardless of authentication.'
end
context 'disable email notifications' do
diff --git a/spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb b/spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb
index 59f1bc94226..262885e09b3 100644
--- a/spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb
+++ b/spec/features/projects/show/user_interacts_with_auto_devops_banner_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Project > Show > User interacts with auto devops implicitly enab
let(:user) { create(:user) }
before do
- project.add_user(user, role)
+ project.add_member(user, role)
sign_in(user)
end
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index 552f068ecc7..fb2f0539558 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
with_them do
before do
project.project_feature.update!({ merge_requests_access_level: merge_requests_access_level })
- project.add_user(user, user_level)
+ project.add_member(user, user_level)
visit project_path(project)
end
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
index 17080043b6d..c8438b73dc3 100644
--- a/spec/features/projects/tags/user_edits_tags_spec.rb
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -5,17 +5,58 @@ require 'spec_helper'
RSpec.describe 'Project > Tags', :js do
include DropzoneHelper
- let(:user) { create(:user) }
- let(:role) { :developer }
- let(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:role) { :developer }
+ let_it_be(:project) { create(:project, :repository) }
before do
sign_in(user)
project.add_role(user, role)
end
+ shared_examples "can create and update release" do
+ it 'can create new release' do
+ visit page_url
+ page.find("a[href=\"#{new_project_release_path(project, tag_name: 'v1.1.0')}\"]").click
+
+ fill_in "Release notes", with: "new release from tag"
+ expect(page).not_to have_field("Create from")
+ click_button "Create release"
+
+ expect(page).to have_current_path(project_release_path(project, 'v1.1.0'))
+ expect(Release.last.description).to eq("new release from tag")
+ end
+
+ it 'can edit existing release' do
+ release = create(:release, project: project, tag: 'v1.1.0')
+
+ visit page_url
+ page.find("a[href=\"#{edit_project_release_path(project, release)}\"]").click
+
+ fill_in "Release notes", with: "updated release desc"
+ click_button "Save changes"
+
+ expect(page).to have_current_path(project_release_path(project, 'v1.1.0'))
+ expect(release.reload.description).to eq("updated release desc")
+ end
+ end
+
+ context 'when visiting tags index page' do
+ let(:page_url) { project_tags_path(project) }
+
+ include_examples "can create and update release"
+ end
+
+ context 'when visiting individual tag page' do
+ let(:page_url) { project_tag_path(project, 'v1.1.0') }
+
+ include_examples "can create and update release"
+ end
+
+ # TODO: remove most of these together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
describe 'when opening project tags' do
before do
+ stub_feature_flags(edit_tag_release_notes_via_release_page: false)
visit project_tags_path(project)
end
diff --git a/spec/features/projects/tracings_spec.rb b/spec/features/projects/tracings_spec.rb
deleted file mode 100644
index b79a0427ef6..00000000000
--- a/spec/features/projects/tracings_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Tracings Content Security Policy' do
- include ContentSecurityPolicyHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- subject { response_headers['Content-Security-Policy'] }
-
- before_all do
- project.add_maintainer(user)
- end
-
- before do
- sign_in(user)
- end
-
- context 'when there is no global config' do
- before do
- setup_csp_for_controller(Projects::TracingsController)
- end
-
- it 'does not add CSP directives' do
- visit project_tracing_path(project)
-
- is_expected.to be_blank
- end
- end
-
- context 'when a global CSP config exists' do
- before do
- csp = ActionDispatch::ContentSecurityPolicy.new do |p|
- p.frame_src 'https://global-policy.com'
- end
-
- setup_existing_csp_for_controller(Projects::TracingsController, csp)
- end
-
- context 'when external_url is set' do
- let!(:project_tracing_setting) { create(:project_tracing_setting, project: project) }
-
- it 'overwrites frame-src' do
- visit project_tracing_path(project)
-
- is_expected.to eq("frame-src https://example.com")
- end
- end
-
- context 'when external_url is not set' do
- it 'uses global policy' do
- visit project_tracing_path(project)
-
- is_expected.to eq("frame-src https://global-policy.com")
- end
- end
- end
-end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index db64f84aa76..f6f9c7f0d3c 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -440,6 +440,99 @@ RSpec.describe 'Project' do
end
end
+ describe 'storage_enforcement_banner', :js do
+ let_it_be(:group) { create(:group) }
+ let_it_be_with_refind(:user) { create(:user) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'with storage_enforcement_date set' do
+ let_it_be(:storage_enforcement_date) { Date.today + 30 }
+
+ before do
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ end
+ end
+
+ it 'displays the banner in the project page' do
+ visit project_path(project)
+ expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ end
+
+ context 'when in a subgroup project page' do
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, namespace: subgroup) }
+
+ it 'displays the banner' do
+ visit project_path(project)
+ expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ end
+ end
+
+ context 'when in a user namespace project page' do
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
+
+ before do
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |namspace|
+ allow(namspace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ end
+ end
+
+ it 'displays the banner' do
+ visit project_path(project)
+ expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ end
+ end
+
+ it 'does not display the banner in a paid group project page' do
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:paid?).and_return(true)
+ end
+ visit project_path(project)
+ expect_page_not_to_have_storage_enforcement_banner
+ end
+
+ it 'does not display the banner if user has previously closed unless threshold has changed' do
+ visit project_path(project)
+ expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ find('.js-storage-enforcement-banner [data-testid="close-icon"]').click
+ wait_for_requests
+ page.refresh
+ expect_page_not_to_have_storage_enforcement_banner
+
+ storage_enforcement_date = Date.today + 13
+ allow_next_found_instance_of(Group) do |grp|
+ allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ end
+ page.refresh
+ expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ end
+ end
+
+ context 'with storage_enforcement_date not set' do
+ # This test should break and be rewritten after the implementation of the storage_enforcement_date
+ # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ it 'does not display the banner in the group page' do
+ stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
+ visit project_path(project)
+ expect_page_not_to_have_storage_enforcement_banner
+ end
+ end
+ end
+
+ def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
+ expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ end
+
+ def expect_page_not_to_have_storage_enforcement_banner
+ expect(page).not_to have_text "storage limits will apply to this namespace"
+ end
+
def remove_with_confirm(button_text, confirm_with, confirm_button_text = 'Confirm')
click_button button_text
fill_in 'confirm_name_input', with: confirm_with
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_line_permalink_updater_spec.rb
deleted file mode 100644
index e8c026a254e..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_line_permalink_updater_spec.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
- include TreeHelper
-
- let(:project) { create(:project, :public, :repository) }
- let(:path) { 'CHANGELOG' }
- let(:sha) { project.repository.commit.sha }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- describe 'On a file(blob)' do
- def get_absolute_url(path = "")
- "http://#{page.server.host}:#{page.server.port}#{path}"
- end
-
- def visit_blob(fragment = nil)
- visit project_blob_path(project, tree_join('master', path), anchor: fragment)
- end
-
- describe 'Click "Permalink" button' do
- it 'works with no initial line number fragment hash' do
- visit_blob
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path))))
- end
-
- it 'maintains intitial fragment hash' do
- fragment = "L3"
-
- visit_blob(fragment)
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment)))
- end
-
- it 'changes fragment hash if line number clicked' do
- ending_fragment = "L5"
-
- visit_blob
-
- find('#L3').click
- find("##{ending_fragment}").click
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
- end
-
- it 'with initial fragment hash, changes fragment hash if line number clicked' do
- fragment = "L1"
- ending_fragment = "L5"
-
- visit_blob(fragment)
-
- find('#L3').click
- find("##{ending_fragment}").click
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
- end
- end
-
- describe 'Click "Blame" button' do
- it 'works with no initial line number fragment hash' do
- visit_blob
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path))))
- end
-
- it 'maintains intitial fragment hash' do
- fragment = "L3"
-
- visit_blob(fragment)
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: fragment)))
- end
-
- it 'changes fragment hash if line number clicked' do
- ending_fragment = "L5"
-
- visit_blob
-
- find('#L3').click
- find("##{ending_fragment}").click
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
- end
-
- it 'with initial fragment hash, changes fragment hash if line number clicked' do
- fragment = "L1"
- ending_fragment = "L5"
-
- visit_blob(fragment)
-
- find('#L3').click
- find("##{ending_fragment}").click
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_show_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_show_spec.rb
deleted file mode 100644
index 5574b4da383..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/blob_show_spec.rb
+++ /dev/null
@@ -1,1201 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'File blob', :js do
- include MobileHelpers
-
- let(:project) { create(:project, :public, :repository) }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- def visit_blob(path, anchor: nil, ref: 'master', **additional_args)
- visit project_blob_path(project, File.join(ref, path), anchor: anchor, **additional_args)
-
- wait_for_requests
- end
-
- def create_file(file_name, content)
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add #{file_name}",
- file_path: file_name,
- file_content: <<-SPEC.strip_heredoc
- #{content}
- SPEC
- ).execute
- end
-
- context 'Ruby file' do
- before do
- visit_blob('files/ruby/popen.rb')
-
- wait_for_requests
- end
-
- it 'displays the blob' do
- aggregate_failures do
- # shows highlighted Ruby code
- expect(page).to have_css(".js-syntax-highlight")
- expect(page).to have_content("require 'fileutils'")
-
- # does not show a viewer switcher
- 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
-
- it 'displays file actions on all screen sizes' do
- file_actions_selector = '.file-actions'
-
- resize_screen_sm
- expect(page).to have_selector(file_actions_selector, visible: true)
-
- resize_screen_xs
- expect(page).to have_selector(file_actions_selector, visible: true)
- end
- end
-
- context 'Markdown file' do
- context 'visiting directly' do
- before do
- visit_blob('files/markdown/ruby-style-guide.md')
-
- wait_for_requests
- 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_requests
- 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_css(".js-syntax-highlight")
- 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_requests
- 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 'when ref switch' do
- def switch_ref_to(ref_name)
- first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
-
- page.within '.project-refs-form' do
- click_link ref_name
- wait_for_requests
- end
- end
-
- it 'displays single highlighted line number of different ref' do
- visit_blob('files/js/application.js', anchor: 'L1')
-
- switch_ref_to('feature')
-
- page.within '.blob-content' do
- expect(find_by_id('LC1')[:class]).to include("hll")
- end
- end
-
- it 'displays multiple highlighted line numbers of different ref' do
- visit_blob('files/js/application.js', anchor: 'L1-3')
-
- switch_ref_to('feature')
-
- page.within '.blob-content' do
- expect(find_by_id('LC1')[:class]).to include("hll")
- expect(find_by_id('LC2')[:class]).to include("hll")
- expect(find_by_id('LC3')[:class]).to include("hll")
- end
- end
-
- it 'displays no highlighted number of different ref' do
- Files::UpdateService.new(
- project,
- project.first_owner,
- commit_message: 'Update',
- start_branch: 'feature',
- branch_name: 'feature',
- file_path: 'files/js/application.js',
- file_content: 'new content'
- ).execute
-
- project.commit('feature').diffs.diff_files.first
-
- visit_blob('files/js/application.js', anchor: 'L3')
- switch_ref_to('feature')
-
- page.within '.blob-content' do
- expect(page).not_to have_css('.hll')
- end
- end
-
- context 'successfully change ref of similar name' do
- before do
- project.repository.create_branch('dev')
- project.repository.create_branch('development')
- end
-
- it 'switch ref from longer to shorter ref name' do
- visit_blob('files/js/application.js', ref: 'development')
- switch_ref_to('dev')
-
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
- end
- end
-
- it 'switch ref from shorter to longer ref name' do
- visit_blob('files/js/application.js', ref: 'dev')
- switch_ref_to('development')
-
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
- end
- end
- end
-
- it 'successfully changes ref when the ref name matches the project name' do
- project.repository.create_branch(project.name)
-
- visit_blob('files/js/application.js', ref: project.name)
- switch_ref_to('master')
-
- aggregate_failures do
- expect(page.find('.file-title-name').text).to eq('application.js')
- expect(page).not_to have_css('flash-container')
- end
- end
- end
-
- context 'visiting with a line number anchor' do
- before do
- visit_blob('files/markdown/ruby-style-guide.md', anchor: '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_css(".js-syntax-highlight")
- 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 rendering' do
- before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add RedCarpet and CommonMark Markdown ",
- file_path: 'files/commonmark/file.md',
- file_content: "1. one\n - sublist\n"
- ).execute
- end
-
- context 'when rendering default markdown' do
- before do
- visit_blob('files/commonmark/file.md')
-
- wait_for_requests
- end
-
- it 'renders using CommonMark' do
- aggregate_failures do
- expect(page).to have_content("sublist")
- expect(page).not_to have_xpath("//ol//li//ul")
- end
- end
- end
- end
-
- context 'Markdown file (stored in LFS)' do
- before do
- project.add_maintainer(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')
-
- wait_for_requests
- 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_requests
- 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')
-
- wait_for_requests
- 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_maintainer(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')
-
- wait_for_requests
- 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 'Jupiter Notebook file' do
- before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add Jupiter Notebook",
- file_path: 'files/basic.ipynb',
- file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
- ).execute
-
- visit_blob('files/basic.ipynb')
-
- wait_for_requests
- end
-
- it 'displays the blob' do
- aggregate_failures do
- # shows rendered notebook
- expect(page).to have_selector('.js-notebook-viewer-mounted')
-
- # does show a viewer switcher
- expect(page).to have_selector('.js-blob-viewer-switcher')
-
- # show 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')
-
- # shows the rendered notebook
- expect(page).to have_content('test')
- 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')
-
- wait_for_requests
- 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')
-
- wait_for_requests
- 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')
-
- wait_for_requests
- 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_maintainer(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')
-
- wait_for_requests
- 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 'binary file that appears to be text in the first 1024 bytes' do
- before do
- visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
- end
-
- it 'displays the blob' do
- aggregate_failures do
- # shows a download link
- expect(page).to have_link('Download (23.8 KB)')
-
- # does not show a viewer switcher
- expect(page).not_to have_selector('.js-blob-viewer-switcher')
-
- # The specs below verify an arguably incorrect result, but since we only
- # learn that the file is not actually text once the text viewer content
- # is loaded asynchronously, there is no straightforward way to get these
- # synchronously loaded elements to display correctly.
- #
- # Clicking the copy button will result in nothing being copied.
- # Clicking the raw button will result in the binary file being downloaded,
- # as expected.
-
- # shows an enabled copy button, incorrectly
- expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
-
- # shows a raw button, incorrectly
- expect(page).to have_link('Open raw')
- end
- end
- end
-
- context 'files with auxiliary viewers' do
- describe '.gitlab-ci.yml' do
- before do
- project.add_maintainer(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
-
- describe '.gitlab/route-map.yml' do
- before do
- project.add_maintainer(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
-
- describe '.gitlab/dashboards/custom-dashboard.yml' do
- before do
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
- file_path: '.gitlab/dashboards/custom-dashboard.yml',
- file_content: file_content
- ).execute
- end
-
- context 'with metrics_dashboard_exhaustive_validations feature flag off' do
- before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
- end
-
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
- end
-
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
- end
- end
-
- context 'with metrics_dashboard_exhaustive_validations feature flag on' do
- before do
- stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
- end
-
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
- end
-
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("root is missing required keys: panel_groups")
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
- 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', href: 'http://choosealicense.com/licenses/mit/')
- end
- end
- end
-
- context '*.gemspec' do
- before do
- project.add_maintainer(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.')
-
- # shows a learn more link
- expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
- end
- end
- end
-
- context 'CONTRIBUTING.md' do
- before do
- file_name = 'CONTRIBUTING.md'
-
- create_file(file_name, '## Contribution guidelines')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
- end
- end
- end
-
- context 'CHANGELOG.md' do
- before do
- file_name = 'CHANGELOG.md'
-
- create_file(file_name, '## Changelog for v1.0.0')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
- end
- end
- end
-
- context 'Cargo.toml' do
- before do
- file_name = 'Cargo.toml'
-
- create_file(file_name, '
- [package]
- name = "hello_world" # the name of the package
- version = "0.1.0" # the current version, obeying semver
- authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Cargo.")
- end
- end
- end
-
- context 'Cartfile' do
- before do
- file_name = 'Cartfile'
-
- create_file(file_name, '
- gitlab "Alamofire/Alamofire" == 4.9.0
- gitlab "Alamofire/AlamofireImage" ~> 3.4
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Carthage.")
- end
- end
- end
-
- context 'composer.json' do
- before do
- file_name = 'composer.json'
-
- create_file(file_name, '
- {
- "license": "MIT"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Composer.")
- end
- end
- end
-
- context 'Gemfile' do
- before do
- file_name = 'Gemfile'
-
- create_file(file_name, '
- source "https://rubygems.org"
-
- # Gems here
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Bundler.")
- end
- end
- end
-
- context 'Godeps.json' do
- before do
- file_name = 'Godeps.json'
-
- create_file(file_name, '
- {
- "GoVersion": "go1.6"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using godep.")
- end
- end
- end
-
- context 'go.mod' do
- before do
- file_name = 'go.mod'
-
- create_file(file_name, '
- module example.com/mymodule
-
- go 1.14
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Go Modules.")
- end
- end
- end
-
- context 'package.json' do
- before do
- file_name = 'package.json'
-
- create_file(file_name, '
- {
- "name": "my-awesome-package",
- "version": "1.0.0"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using npm.")
- end
- end
- end
-
- context 'podfile' do
- before do
- file_name = 'podfile'
-
- create_file(file_name, 'platform :ios, "8.0"')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
- end
- end
-
- context 'test.podspec' do
- before do
- file_name = 'test.podspec'
-
- create_file(file_name, '
- Pod::Spec.new do |s|
- s.name = "TensorFlowLiteC"
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
- end
- end
-
- context 'JSON.podspec.json' do
- before do
- file_name = 'JSON.podspec.json'
-
- create_file(file_name, '
- {
- "name": "JSON"
- }
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using CocoaPods.")
- end
- end
- end
-
- context 'requirements.txt' do
- before do
- file_name = 'requirements.txt'
-
- create_file(file_name, 'Project requirements')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using pip.")
- end
- end
- end
-
- context 'yarn.lock' do
- before do
- file_name = 'yarn.lock'
-
- create_file(file_name, '
- # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
- # yarn lockfile v1
- ')
- visit_blob(file_name)
- end
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- expect(page).to have_content("This project manages its dependencies using Yarn.")
- end
- end
- end
-
- context 'openapi.yml' do
- before do
- file_name = 'openapi.yml'
-
- create_file(file_name, '
- swagger: \'2.0\'
- info:
- title: Classic API Resource Documentation
- description: |
- <div class="foo-bar" style="background-color: red;" data-foo-bar="baz">
- <h1>Swagger API documentation</h1>
- </div>
- version: production
- basePath: /JSSResource/
- produces:
- - application/xml
- - application/json
- consumes:
- - application/xml
- - application/json
- security:
- - basicAuth: []
- paths:
- /accounts:
- get:
- responses:
- \'200\':
- description: No response was specified
- tags:
- - accounts
- operationId: findAccounts
- summary: Finds all accounts
- ')
- visit_blob(file_name, useUnsafeMarkdown: '1')
- click_button('Display rendered file')
-
- wait_for_requests
- end
-
- it 'removes `style`, `class`, and `data-*`` attributes from HTML' do
- expect(page).to have_css('h1', text: 'Swagger API documentation')
- expect(page).not_to have_css('.foo-bar')
- expect(page).not_to have_css('[style="background-color: red;"]')
- expect(page).not_to have_css('[data-foo-bar="baz"]')
- end
- end
- end
-
- context 'realtime pipelines' do
- before do
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'feature',
- branch_name: 'feature',
- commit_message: "Add ruby file",
- file_path: 'files/ruby/test.rb',
- file_content: "# Awesome content"
- ).execute
-
- create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
- visit_blob('files/ruby/test.rb', ref: 'feature')
- end
-
- it 'shows the realtime pipeline status' do
- page.within('.commit-actions') do
- expect(page).to have_css('.ci-status-icon')
- expect(page).to have_css('.ci-status-icon-running')
- expect(page).to have_css('.js-ci-status-icon-running')
- end
- end
- end
-
- context 'for subgroups' do
- let(:group) { create(:group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:project) { create(:project, :public, :repository, group: subgroup) }
-
- it 'renders tree table without errors' do
- visit_blob('README.md')
-
- expect(page).to have_selector('.file-content')
- expect(page).not_to have_selector('[data-testid="alert-danger"]')
- end
-
- it 'displays a GPG badge' do
- visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
-
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
- end
-
- context 'on signed merge commit' do
- it 'displays a GPG badge' do
- visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
-
- expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
- expect(page).to have_selector '.gpg-status-box.invalid'
- end
- end
-
- context 'when static objects external storage is enabled' do
- before do
- stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
- end
-
- context 'private project' do
- let_it_be(:project) { create(:project, :repository, :private) }
- let_it_be(:user) { create(:user) }
-
- before do
- project.add_developer(user)
-
- sign_in(user)
- visit_blob('README.md')
- end
-
- it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
- download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
-
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
- end
- end
-
- context 'public project' do
- before do
- visit_blob('README.md')
- end
-
- it 'shows open raw and download buttons with external storage URL prepended to their href' do
- path = project_raw_path(project, 'master/README.md')
- raw_uri = "https://cdn.gitlab.com#{path}"
- download_uri = "https://cdn.gitlab.com#{path}?inline=false"
-
- aggregate_failures do
- expect(page).to have_link 'Open raw', href: raw_uri
- expect(page).to have_link 'Download', href: download_uri
- end
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/edit_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/edit_spec.rb
deleted file mode 100644
index f5b9947b29e..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/edit_spec.rb
+++ /dev/null
@@ -1,213 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Editing file blob', :js do
- include TreeHelper
- include BlobSpecHelpers
-
- let(:project) { create(:project, :public, :repository) }
- let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
- let(:branch) { 'master' }
- let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
- let(:readme_file_path) { 'README.md' }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- context 'as a developer' do
- let(:user) { create(:user) }
- let(:role) { :developer }
-
- before do
- project.add_role(user, role)
- sign_in(user)
- end
-
- def edit_and_commit(commit_changes: true, is_diff: false)
- set_default_button('edit')
- refresh
- wait_for_requests
-
- if is_diff
- first('.js-diff-more-actions').click
- click_link('Edit in single-file editor')
- else
- click_link('Edit')
- end
-
- fill_editor(content: 'class NextFeature\\nend\\n')
-
- if commit_changes
- click_button 'Commit changes'
- end
- end
-
- def fill_editor(content: 'class NextFeature\\nend\\n')
- wait_for_requests
- execute_script("monaco.editor.getModels()[0].setValue('#{content}')")
- end
-
- context 'from MR diff' do
- before do
- visit diffs_project_merge_request_path(project, merge_request)
- edit_and_commit(is_diff: true)
- end
-
- it 'returns me to the mr' do
- expect(page).to have_content(merge_request.title)
- end
- end
-
- it 'updates the content of file with a number as file path' do
- project.repository.create_file(user, '1', 'test', message: 'testing', branch_name: branch)
- visit project_blob_path(project, tree_join(branch, '1'))
-
- edit_and_commit
-
- expect(page).to have_content 'NextFeature'
- end
-
- it 'editing a template file in a sub directory does not change path' do
- project.repository.create_file(user, 'ci/.gitlab-ci.yml', 'test', message: 'testing', branch_name: branch)
- visit project_edit_blob_path(project, tree_join(branch, 'ci/.gitlab-ci.yml'))
-
- expect(find_by_id('file_path').value).to eq('ci/.gitlab-ci.yml')
- end
-
- it 'updating file path updates syntax highlighting' do
- visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
- expect(find('#editor')['data-mode-id']).to eq('markdown')
-
- find('#file_path').send_keys('foo.txt') do
- expect(find('#editor')['data-mode-id']).to eq('plaintext')
- end
- end
-
- context 'from blob file path' do
- before do
- visit project_blob_path(project, tree_join(branch, file_path))
- end
-
- it 'updates content' do
- edit_and_commit
-
- expect(page).to have_content 'successfully committed'
- expect(page).to have_content 'NextFeature'
- end
-
- it 'previews content' do
- edit_and_commit(commit_changes: false)
- click_link 'Preview changes'
- wait_for_requests
-
- old_line_count = page.all('.line_holder.old').size
- new_line_count = page.all('.line_holder.new').size
-
- expect(old_line_count).to be > 0
- expect(new_line_count).to be > 0
- end
- end
-
- context 'when rendering the preview' do
- it 'renders content with CommonMark' do
- visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
- fill_editor(content: '1. one\\n - sublist\\n')
- click_link 'Preview'
- wait_for_requests
-
- # the above generates two separate lists (not embedded) in CommonMark
- expect(page).to have_content('sublist')
- expect(page).not_to have_xpath('//ol//li//ul')
- end
- end
- end
-
- context 'visit blob edit' do
- context 'redirects to sign in and returns' do
- context 'as developer' do
- let(:user) { create(:user) }
-
- before do
- project.add_developer(user)
- visit project_edit_blob_path(project, tree_join(branch, file_path))
- end
-
- it 'redirects to sign in and returns' do
- expect(page).to have_current_path(new_user_session_path)
-
- gitlab_sign_in(user)
-
- expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
- end
- end
-
- context 'as guest' do
- let(:user) { create(:user) }
-
- before do
- visit project_edit_blob_path(project, tree_join(branch, file_path))
- end
-
- it 'redirects to sign in and returns' do
- expect(page).to have_current_path(new_user_session_path)
-
- gitlab_sign_in(user)
-
- expect(page).to have_current_path(project_blob_path(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.add_developer(user)
- project.repository.add_branch(user, protected_branch, 'master')
- create(:protected_branch, project: project, name: protected_branch)
- sign_in(user)
- end
-
- context 'on some branch' do
- before do
- visit project_edit_blob_path(project, tree_join(branch, file_path))
- end
-
- it 'shows blob editor with same branch' do
- expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
- expect(find('.js-branch-name').value).to eq(branch)
- end
- end
-
- context 'with protected branch' do
- it 'shows blob editor with patch branch' do
- freeze_time do
- visit project_edit_blob_path(project, tree_join(protected_branch, file_path))
-
- epoch = Time.zone.now.strftime('%s%L').last(5)
-
- expect(find('.js-branch-name').value).to eq "#{user.username}-protected-branch-patch-#{epoch}"
- end
- end
- end
- end
-
- context 'as maintainer' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- visit project_edit_blob_path(project, tree_join(branch, file_path))
- end
-
- it 'shows blob editor with same branch' do
- expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
- expect(find('.js-branch-name').value).to eq(branch)
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/shortcuts_blob_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/shortcuts_blob_spec.rb
deleted file mode 100644
index fe0b217992e..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/shortcuts_blob_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Blob shortcuts', :js do
- include TreeHelper
- let(:project) { create(:project, :public, :repository) }
- let(:path) { project.repository.ls_files(project.repository.root_ref)[0] }
- let(:sha) { project.repository.commit.sha }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- describe 'On a file(blob)', :js do
- def get_absolute_url(path = "")
- "http://#{page.server.host}:#{page.server.port}#{path}"
- end
-
- def visit_blob(fragment = nil)
- visit project_blob_path(project, tree_join('master', path), anchor: fragment)
- end
-
- describe 'pressing "y"' do
- it 'redirects to permalink with commit sha' do
- visit_blob
- wait_for_requests
-
- find('body').native.send_key('y')
-
- expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path))), url: true)
- end
-
- it 'maintains fragment hash when redirecting' do
- fragment = "L1"
- visit_blob(fragment)
- wait_for_requests
-
- find('body').native.send_key('y')
-
- expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment)), url: true)
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
deleted file mode 100644
index fe38659f60b..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User creates new blob', :js do
- include WebIdeSpecHelpers
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :empty_repo) }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- shared_examples 'creating a file' do
- it 'allows the user to add a new file in Web IDE' do
- visit project_path(project)
-
- click_link 'New file'
-
- wait_for_requests
-
- ide_create_new_file('dummy-file', content: "Hello world\n")
-
- ide_commit
-
- expect(page).to have_content('All changes are committed')
- expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
- end
- end
-
- describe 'as a maintainer' do
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- it_behaves_like 'creating a file'
- end
-
- describe 'as an admin' do
- let(:user) { create(:user, :admin) }
-
- before do
- sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
- end
-
- it_behaves_like 'creating a file'
- end
-
- describe 'as a developer' do
- before do
- project.add_developer(user)
- sign_in(user)
- visit project_path(project)
- end
-
- it 'does not allow pushing to the default branch' do
- expect(page).not_to have_content('New file')
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
deleted file mode 100644
index 4290df08e66..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled', :js do
- include CookieHelper
-
- let(:project) { create(:project, :empty_repo) }
- let(:user) { project.first_owner }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- describe 'viewing the new blob page' do
- before do
- sign_in(user)
- end
-
- context 'when the page is loaded from the link using the suggest_gitlab_ci_yml param' do
- before do
- visit namespace_project_new_blob_path(namespace_id: project.namespace, project_id: project, id: 'master', suggest_gitlab_ci_yml: 'true')
- end
-
- it 'pre-fills .gitlab-ci.yml for file name' do
- file_name = page.find_by_id('file_name')
-
- expect(file_name.value).to have_content('.gitlab-ci.yml')
- end
-
- it 'chooses the .gitlab-ci.yml Template Type' do
- template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
-
- expect(template_type.text).to have_content('.gitlab-ci.yml')
- end
-
- it 'displays suggest_gitlab_ci_yml popover' do
- page.find(:css, '.gitlab-ci-yml-selector').click
-
- popover_selector = '.suggest-gitlab-ci-yml'
-
- expect(page).to have_css(popover_selector, visible: true)
-
- page.within(popover_selector) do
- expect(page).to have_content('1/2: Choose a template')
- end
- end
-
- it 'sets the commit cookie when the Commit button is clicked' do
- click_button 'Commit changes'
-
- expect(get_cookie("suggest_gitlab_ci_yml_commit_#{project.id}")).to be_present
- end
- end
-
- context 'when the page is visited without the param' do
- before do
- visit namespace_project_new_blob_path(namespace_id: project.namespace, project_id: project, id: 'master')
- end
-
- it 'does not pre-fill .gitlab-ci.yml for file name' do
- file_name = page.find_by_id('file_name')
-
- expect(file_name.value).not_to have_content('.gitlab-ci.yml')
- end
-
- it 'does not choose the .gitlab-ci.yml Template Type' do
- template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
-
- expect(template_type.text).to have_content('Select a template type')
- end
-
- it 'does not display suggest_gitlab_ci_yml popover' do
- popover_selector = '.b-popover.suggest-gitlab-ci-yml'
-
- expect(page).not_to have_css(popover_selector, visible: true)
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_views_pipeline_editor_button_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_views_pipeline_editor_button_spec.rb
deleted file mode 100644
index a00e1eaa551..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/blobs/user_views_pipeline_editor_button_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User views pipeline editor button on root ci config file', :js do
- include BlobSpecHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :public, :repository) }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- end
-
- context "when the ci config is the root file" do
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- it 'shows the button to the Pipeline Editor' do
- project.update!(ci_config_path: '.my-config.yml')
- project.repository.create_file(user, project.ci_config_path_or_default, 'test', message: 'testing', branch_name: 'master')
- visit project_blob_path(project, File.join('master', '.my-config.yml'))
-
- expect(page).to have_content('Edit in pipeline editor')
- end
-
- it 'does not shows the Pipeline Editor button' do
- project.repository.create_file(user, '.my-sub-config.yml', 'test', message: 'testing', branch_name: 'master')
- visit project_blob_path(project, File.join('master', '.my-sub-config.yml'))
-
- expect(page).not_to have_content('Edit in pipeline editor')
- end
- end
-
- context "when user cannot collaborate" do
- before do
- sign_in(user)
- end
- it 'does not shows the Pipeline Editor button' do
- visit project_blob_path(project, File.join('master', '.my-config.yml'))
- expect(page).not_to have_content('Edit in pipeline editor')
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/editing_a_file_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/editing_a_file_spec.rb
deleted file mode 100644
index c32fb1aa4d3..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/editing_a_file_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > User wants to edit a file' do
- let(:project) { create(:project, :repository) }
- let(:user) { project.first_owner }
- let(:commit_params) do
- {
- start_branch: project.default_branch,
- branch_name: project.default_branch,
- commit_message: "Committing First Update",
- file_path: ".gitignore",
- file_content: "First Update",
- last_commit_sha: Gitlab::Git::Commit.last_for_path(project.repository, project.default_branch,
- ".gitignore").sha
- }
- end
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in user
- visit project_edit_blob_path(project,
- File.join(project.default_branch, '.gitignore'))
- end
-
- it 'file has been updated since the user opened the edit page' do
- Files::UpdateService.new(project, user, commit_params).execute
-
- click_button 'Commit changes'
-
- expect(page).to have_content 'Someone edited the file the same time you did.'
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/find_file_keyboard_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/find_file_keyboard_spec.rb
deleted file mode 100644
index 9ba5f5a9b57..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/find_file_keyboard_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > Find file keyboard shortcuts', :js do
- let(:project) { create(:project, :repository) }
- let(:user) { project.first_owner }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in user
-
- visit project_find_file_path(project, project.repository.root_ref)
-
- wait_for_requests
- end
-
- it 'opens file when pressing enter key' do
- fill_in 'file_find', with: 'CHANGELOG'
-
- find('#file_find').native.send_keys(:enter)
-
- expect(page).to have_selector('.blob-content-holder')
-
- page.within('.js-file-title') do
- expect(page).to have_content('CHANGELOG')
- end
- end
-
- it 'navigates files with arrow keys' do
- fill_in 'file_find', with: 'application.'
-
- find('#file_find').native.send_keys(:down)
- find('#file_find').native.send_keys(:enter)
-
- expect(page).to have_selector('.blob-content-holder')
-
- page.within('.js-file-title') do
- expect(page).to have_content('application.js')
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/project_owner_creates_license_file_spec.rb
deleted file mode 100644
index ab920504100..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/project_owner_creates_license_file_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > Project owner creates a license file', :js do
- let(:project) { create(:project, :repository) }
- let(:project_maintainer) { project.first_owner }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- project.repository.delete_file(project_maintainer, 'LICENSE',
- message: 'Remove LICENSE', branch_name: 'master')
- sign_in(project_maintainer)
- visit project_path(project)
- end
-
- it 'project maintainer creates a license file manually from a template' do
- visit project_tree_path(project, project.repository.root_ref)
- find('.add-to-tree').click
- click_link 'New file'
-
- fill_in :file_name, with: 'LICENSE'
-
- expect(page).to have_selector('.license-selector')
-
- select_template('MIT License')
-
- file_content = first('.file-editor')
- expect(file_content).to have_content('MIT License')
- expect(file_content).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
-
- fill_in :commit_message, with: 'Add a LICENSE file', visible: true
- click_button 'Commit changes'
-
- expect(page).to have_current_path(
- project_blob_path(project, 'master/LICENSE'), ignore_query: true)
- expect(page).to have_content('MIT License')
- expect(page).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
- end
-
- it 'project maintainer 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_current_path(
- project_new_blob_path(project, 'master'), ignore_query: true)
- expect(find('#file_name').value).to eq('LICENSE')
- expect(page).to have_selector('.license-selector')
-
- select_template('MIT License')
-
- file_content = first('.file-editor')
- expect(file_content).to have_content('MIT License')
- expect(file_content).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
-
- fill_in :commit_message, with: 'Add a LICENSE file', visible: true
- click_button 'Commit changes'
-
- expect(page).to have_current_path(
- project_blob_path(project, 'master/LICENSE'), ignore_query: true)
- expect(page).to have_content('MIT License')
- expect(page).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
- end
-
- def select_template(template)
- page.within('.js-license-selector-wrap') do
- click_button 'Apply a template'
- click_link template
- wait_for_requests
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_files_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_files_spec.rb
deleted file mode 100644
index 5abdad905fd..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_files_spec.rb
+++ /dev/null
@@ -1,377 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe "User browses files", :js do
- include RepoHelpers
-
- let(:fork_message) do
- "You're not allowed to make changes to this project directly. "\
- "A fork of this project has been created that you can make changes in, so you can submit a merge request."
- end
-
- let(:project) { create(:project, :repository, name: "Shop") }
- let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") }
- let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
- let(:user) { project.first_owner }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in(user)
- end
-
- it "shows last commit for current directory", :js do
- visit(tree_path_root_ref)
-
- click_link("files")
-
- last_commit = project.repository.last_commit_for_path(project.default_branch, "files")
-
- page.within(".commit-detail") do
- expect(page).to have_content(last_commit.short_id).and have_content(last_commit.author_name)
- end
- end
-
- context "when browsing the master branch", :js do
- before do
- visit(tree_path_root_ref)
- end
-
- it "shows files from a repository" do
- expect(page).to have_content("VERSION")
- .and have_content(".gitignore")
- .and have_content("LICENSE")
- end
-
- it "shows the `Browse Directory` link" do
- click_link("files")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link("History")
-
- expect(page).to have_link("Browse Directory").and have_no_link("Browse Code")
- end
-
- it "shows the `Browse File` link" do
- page.within(".tree-table") do
- click_link("README.md")
- end
-
- click_link("History")
-
- expect(page).to have_link("Browse File").and have_no_link("Browse Files")
- end
-
- it "shows the `Browse Files` link" do
- click_link("History")
-
- expect(page).to have_link("Browse Files").and have_no_link("Browse Directory")
- end
-
- it "redirects to the permalink URL" do
- click_link(".gitignore")
- click_link("Permalink")
-
- permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore")
-
- expect(page).to have_current_path(permalink_path, ignore_query: true)
- end
- end
-
- context "when browsing the `markdown` branch", :js do
- context "when browsing the root" do
- before do
- visit(project_tree_path(project, "markdown"))
- end
-
- it "shows correct files and links" do
- expect(page).to have_current_path(project_tree_path(project, "markdown"), ignore_query: true)
- expect(page).to have_content("README.md")
- .and have_content("CHANGELOG")
- .and have_content("Welcome to GitLab GitLab is a free project and repository management application")
- .and have_link("GitLab API doc")
- .and have_link("GitLab API website")
- .and have_link("Rake tasks")
- .and have_link("backup and restore procedure")
- .and have_link("GitLab API doc directory")
- .and have_link("Maintenance")
- .and have_header_with_correct_id_and_link(2, "Application details", "application-details")
- .and have_link("empty", href: "")
- .and have_link("#id", href: "#id")
- .and have_link("/#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
- .and have_link("README.md#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
- .and have_link("d/README.md#id", href: project_blob_path(project, "markdown/db/README.md", anchor: "id"))
- end
-
- it "shows correct content of file" do
- click_link("GitLab API doc")
-
- expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/README.md"), ignore_query: true)
- expect(page).to have_content("All API requests require authentication")
- .and have_content("Contents")
- .and have_link("Users")
- .and have_link("Rake tasks")
- .and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api")
-
- click_link("Users")
-
- expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/users.md"), ignore_query: true)
- expect(page).to have_content("Get a list of users.")
-
- page.go_back
-
- click_link("Rake tasks")
-
- expect(page).to have_current_path(project_tree_path(project, "markdown/doc/raketasks"), ignore_query: true)
- expect(page).to have_content("backup_restore.md").and have_content("maintenance.md")
-
- click_link("maintenance.md")
-
- expect(page).to have_current_path(project_blob_path(project, "markdown/doc/raketasks/maintenance.md"), ignore_query: true)
- expect(page).to have_content("bundle exec rake gitlab:env:info RAILS_ENV=production")
-
- click_link("shop")
-
- page.within(".tree-table") do
- click_link("README.md")
- end
-
- page.go_back
-
- page.within(".tree-table") do
- click_link("d")
- end
-
- expect(page).to have_link("..", href: project_tree_path(project, "markdown/"))
-
- page.within(".tree-table") do
- click_link("README.md")
- end
-
- expect(page).to have_link("empty", href: "")
- end
-
- it "shows correct content of directory" do
- click_link("GitLab API doc directory")
-
- expect(page).to have_current_path(project_tree_path(project, "markdown/doc/api"), ignore_query: true)
- expect(page).to have_content("README.md").and have_content("users.md")
-
- click_link("Users")
-
- expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/users.md"), ignore_query: true)
- expect(page).to have_content("List users").and have_content("Get a list of users.")
- end
- end
- end
-
- context 'when commit message has markdown', :js do
- before do
- project.repository.create_file(user, 'index', 'test', message: ':star: testing', branch_name: 'master')
-
- visit(project_tree_path(project, "master"))
- end
-
- it 'renders emojis' do
- expect(page).to have_selector('gl-emoji', count: 2)
- end
- end
-
- context "when browsing a `improve/awesome` branch", :js do
- before do
- visit(project_tree_path(project, "improve/awesome"))
- end
-
- it "shows files from a repository" do
- expect(page).to have_content("VERSION")
- .and have_content(".gitignore")
- .and have_content("LICENSE")
-
- click_link("files")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link("html")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('html')
- end
-
- expect(page).to have_link('500.html')
- end
- end
-
- context "when browsing a `Ääh-test-utf-8` branch", :js do
- before do
- project.repository.create_branch('Ääh-test-utf-8', project.repository.root_ref)
- visit(project_tree_path(project, "Ääh-test-utf-8"))
- end
-
- it "shows files from a repository" do
- expect(page).to have_content("VERSION")
- .and have_content(".gitignore")
- .and have_content("LICENSE")
-
- click_link("files")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link("html")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('html')
- end
-
- expect(page).to have_link('500.html')
- end
- end
-
- context "when browsing a `test-#` branch", :js do
- before do
- project.repository.create_branch('test-#', project.repository.root_ref)
- visit(project_tree_path(project, "test-#"))
- end
-
- it "shows files from a repository" do
- expect(page).to have_content("VERSION")
- .and have_content(".gitignore")
- .and have_content("LICENSE")
-
- click_link("files")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link("html")
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('html')
- end
-
- expect(page).to have_link('500.html')
- end
- end
-
- context "when browsing a specific ref", :js do
- let(:ref) { project_tree_path(project, "6d39438") }
-
- before do
- visit(ref)
- end
-
- it "shows files from a repository for `6d39438`" do
- expect(page).to have_current_path(ref, ignore_query: true)
- expect(page).to have_content(".gitignore").and have_content("LICENSE")
- end
-
- it "shows files from a repository with apostroph in its name" do
- first(".js-project-refs-dropdown").click
-
- page.within(".project-refs-form") do
- click_link("'test'")
- end
-
- expect(page).to have_selector(".dropdown-toggle-text", text: "'test'")
-
- visit(project_tree_path(project, "'test'"))
-
- expect(page).not_to have_selector(".tree-commit .animation-container")
- end
-
- it "shows the code with a leading dot in the directory" do
- first(".js-project-refs-dropdown").click
-
- page.within(".project-refs-form") do
- click_link("fix")
- end
-
- visit(project_tree_path(project, "fix/.testdir"))
-
- expect(page).not_to have_selector(".tree-commit .animation-container")
- end
-
- it "does not show the permalink link" do
- click_link(".gitignore")
-
- expect(page).not_to have_link("permalink")
- end
- end
-
- context "when browsing a file content", :js do
- before do
- visit(tree_path_root_ref)
- wait_for_requests
-
- click_link(".gitignore")
- end
-
- it "shows a file content" do
- expect(page).to have_content("*.rbc")
- end
-
- it "is possible to blame" do
- click_link("Blame")
-
- expect(page).to have_content("*.rb")
- .and have_content("Dmitriy Zaporozhets")
- .and have_content("Initial commit")
- .and have_content("Ignore DS files")
-
- previous_commit_anchor = "//a[@title='Ignore DS files']/parent::span/following-sibling::span/a"
- find(:xpath, previous_commit_anchor).click
-
- expect(page).to have_content("*.rb")
- .and have_content("Dmitriy Zaporozhets")
- .and have_content("Initial commit")
-
- expect(page).not_to have_content("Ignore DS files")
- end
- end
-
- context "when browsing a file with pathspec characters" do
- let(:filename) { ':wq' }
- let(:newrev) { project.repository.commit('master').sha }
-
- before do
- create_file_in_repo(project, 'master', 'master', filename, 'Test file')
- path = File.join('master', filename)
-
- visit(project_blob_path(project, path))
- wait_for_requests
- end
-
- it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
-
- within_window new_tab do
- expect(page).to have_content("Test file")
- end
- end
- end
-
- context "when browsing a raw file" do
- before do
- visit(tree_path_root_ref)
- wait_for_requests
-
- click_link(".gitignore")
- wait_for_requests
- end
-
- it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
-
- within_window new_tab do
- expect(page).to have_content("*.rbc")
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_lfs_files_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_lfs_files_spec.rb
deleted file mode 100644
index 2d9b6b3a903..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/user_browses_lfs_files_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > User browses LFS files' do
- let(:project) { create(:project, :repository) }
- let(:user) { project.first_owner }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in(user)
- end
-
- context 'when LFS is disabled', :js do
- before do
- allow_next_found_instance_of(Project) do |project|
- allow(project).to receive(:lfs_enabled?).and_return(false)
- end
-
- visit project_tree_path(project, 'lfs')
- wait_for_requests
- end
-
- it 'is possible to see raw content of LFS pointer' do
- click_link 'files'
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link 'lfs'
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('lfs')
- end
-
- click_link 'lfs_object.iso'
-
- 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'
- expect(page).not_to have_content 'Download (1.5 MB)'
- end
- end
-
- context 'when LFS is enabled', :js do
- before do
- allow_next_found_instance_of(Project) do |project|
- allow(project).to receive(:lfs_enabled?).and_return(true)
- end
-
- visit project_tree_path(project, 'lfs')
- wait_for_requests
- end
-
- it 'shows an LFS object' do
- click_link('files')
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_link('files')
- end
-
- click_link('lfs')
- click_link('lfs_object.iso')
-
- expect(page).to have_content('Download (1.5 MB)')
- expect(page).not_to have_content('version https://git-lfs.github.com/spec/v1')
- expect(page).not_to have_content('oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897')
- expect(page).not_to have_content('size 1575078')
-
- page.within('.content') do
- expect(page).to have_content('Delete')
- expect(page).to have_content('History')
- expect(page).to have_content('Permalink')
- expect(page).to have_content('Replace')
- expect(page).to have_link('Download')
-
- expect(page).not_to have_content('Annotate')
- expect(page).not_to have_content('Blame')
-
- expect(page).not_to have_selector(:link_or_button, text: /^Edit$/)
- expect(page).to have_selector(:link_or_button, 'Open in Web IDE')
- end
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/user_deletes_files_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/user_deletes_files_spec.rb
deleted file mode 100644
index d503c9b1192..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/user_deletes_files_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > User deletes files', :js do
- let(:fork_message) do
- "You're not allowed to make changes to this project directly. "\
- "A fork of this project has been created that you can make changes in, so you can submit a merge request."
- end
-
- let(:project) { create(:project, :repository, name: 'Shop') }
- let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
- let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
- let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
- let(:user) { create(:user) }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in(user)
- end
-
- context 'when an user has write access' do
- before do
- project.add_maintainer(user)
- visit(project_tree_path_root_ref)
- wait_for_requests
- end
-
- it 'deletes the file', :js do
- click_link('.gitignore')
-
- expect(page).to have_content('.gitignore')
-
- click_on('Delete')
- fill_in(:commit_message, with: 'New commit message', visible: true)
- click_button('Delete file')
-
- expect(page).to have_current_path(project_tree_path(project, 'master/'), ignore_query: true)
- expect(page).not_to have_content('.gitignore')
- end
- end
-
- context 'when an user does not have write access', :js do
- before do
- project2.add_reporter(user)
- visit(project2_tree_path_root_ref)
- wait_for_requests
- end
-
- it 'deletes the file in a forked project', :js, :sidekiq_might_not_need_inline do
- click_link('.gitignore')
-
- expect(page).to have_content('.gitignore')
-
- click_on('Delete')
-
- expect(page).to have_link('Fork')
- expect(page).to have_button('Cancel')
-
- click_link('Fork')
-
- expect(page).to have_content(fork_message)
-
- click_on('Delete')
- fill_in(:commit_message, with: 'New commit message', visible: true)
- click_button('Delete file')
-
- fork = user.fork_of(project2.reload)
-
- expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
- expect(page).to have_content('New commit message')
- end
- end
-end
diff --git a/spec/features/refactor_blob_viewer_disabled/projects/files/user_edits_files_spec.rb b/spec/features/refactor_blob_viewer_disabled/projects/files/user_edits_files_spec.rb
deleted file mode 100644
index 7a70d67d8ca..00000000000
--- a/spec/features/refactor_blob_viewer_disabled/projects/files/user_edits_files_spec.rb
+++ /dev/null
@@ -1,226 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Projects > Files > User edits files', :js do
- include ProjectForksHelper
- include BlobSpecHelpers
-
- let(:project) { create(:project, :repository, name: 'Shop') }
- let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
- let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
- let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
- let(:user) { create(:user) }
-
- before do
- stub_feature_flags(refactor_blob_viewer: false)
- sign_in(user)
- end
-
- after do
- unset_default_button
- end
-
- shared_examples 'unavailable for an archived project' do
- it 'does not show the edit link for an archived project', :js do
- project.update!(archived: true)
- visit project_tree_path(project, project.repository.root_ref)
-
- click_link('.gitignore')
-
- aggregate_failures 'available edit buttons' do
- expect(page).not_to have_text('Edit')
- expect(page).not_to have_text('Web IDE')
-
- expect(page).not_to have_text('Replace')
- expect(page).not_to have_text('Delete')
- end
- end
- end
-
- context 'when an user has write access', :js do
- before do
- project.add_maintainer(user)
- visit(project_tree_path_root_ref)
- wait_for_requests
- end
-
- it 'inserts a content of a file' do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
-
- expect(editor_value).to eq('*.rbca')
- end
-
- it 'does not show the edit link if a file is binary' do
- binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png')
- visit(project_blob_path(project, binary_file))
- wait_for_requests
-
- page.within '.content' do
- expect(page).not_to have_link('edit')
- end
- end
-
- it 'commits an edited file' do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
- fill_in(:commit_message, with: 'New commit message', visible: true)
- click_button('Commit changes')
-
- expect(page).to have_current_path(project_blob_path(project, 'master/.gitignore'), ignore_query: true)
-
- wait_for_requests
-
- expect(page).to have_content('*.rbca')
- end
-
- it 'commits an edited file to a new branch' do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
-
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
- fill_in(:commit_message, with: 'New commit message', visible: true)
- fill_in(:branch_name, with: 'new_branch_name', visible: true)
- click_button('Commit changes')
-
- expect(page).to have_current_path(project_new_merge_request_path(project), ignore_query: true)
-
- click_link('Changes')
-
- expect(page).to have_content('*.rbca')
- end
-
- it 'shows the diff of an edited file' do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
- click_link('Preview changes')
-
- expect(page).to have_css('.line_holder.new')
- end
-
- it_behaves_like 'unavailable for an archived project'
- end
-
- context 'when an user does not have write access', :js do
- before do
- project2.add_reporter(user)
- visit(project2_tree_path_root_ref)
- wait_for_requests
- end
-
- def expect_fork_prompt
- expect(page).to have_selector(:link_or_button, 'Fork')
- expect(page).to have_selector(:link_or_button, 'Cancel')
- expect(page).to have_content(
- "You can’t edit files directly in this project. "\
- "Fork this project and submit a merge request with your changes."
- )
- end
-
- def expect_fork_status
- expect(page).to have_content(
- "You're not allowed to make changes to this project directly. "\
- "A fork of this project has been created that you can make changes in, so you can submit a merge request."
- )
- end
-
- it 'inserts a content of a file in a forked project', :sidekiq_might_not_need_inline do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
-
- expect_fork_prompt
-
- click_link_or_button('Fork project')
-
- expect_fork_status
-
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
-
- expect(editor_value).to eq('*.rbca')
- end
-
- it 'commits an edited file in a forked project', :sidekiq_might_not_need_inline do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
-
- expect_fork_prompt
- click_link_or_button('Fork project')
-
- find('.file-editor', match: :first)
-
- find('#editor')
- set_editor_value('*.rbca')
- fill_in(:commit_message, with: 'New commit message', visible: true)
- click_button('Commit changes')
-
- fork = user.fork_of(project2.reload)
-
- expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
-
- wait_for_requests
-
- expect(page).to have_content('New commit message')
- end
-
- context 'when the user already had a fork of the project', :js do
- let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) }
-
- before do
- visit(project2_tree_path_root_ref)
- wait_for_requests
- end
-
- it 'links to the forked project for editing', :sidekiq_might_not_need_inline do
- set_default_button('edit')
- click_link('.gitignore')
- click_link_or_button('Edit')
-
- expect(page).not_to have_link('Fork project')
-
- find('#editor')
- set_editor_value('*.rbca')
- fill_in(:commit_message, with: 'Another commit', visible: true)
- click_button('Commit changes')
-
- fork = user.fork_of(project2)
-
- expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
-
- wait_for_requests
-
- expect(page).to have_content('Another commit')
- expect(page).to have_content("From #{forked_project.full_path}")
- expect(page).to have_content("into #{project2.full_path}")
- end
-
- it_behaves_like 'unavailable for an archived project' do
- let(:project) { project2 }
- end
- end
- end
-end
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 7350a54e8df..1523586ab26 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -153,6 +153,7 @@ RSpec.describe 'User uses header search field', :js do
it 'displays search options' do
fill_in_search('test')
+
expect(page).to have_selector(scoped_search_link('test', search_code: true))
expect(page).to have_selector(scoped_search_link('test', group_id: group.id, search_code: true))
expect(page).to have_selector(scoped_search_link('test', project_id: project.id, group_id: group.id, search_code: true))
@@ -167,6 +168,7 @@ RSpec.describe 'User uses header search field', :js do
it 'displays search options' do
fill_in_search('test')
+ sleep 0.5
expect(page).to have_selector(scoped_search_link('test', search_code: true, repository_ref: 'master'))
expect(page).not_to have_selector(scoped_search_link('test', search_code: true, group_id: project.namespace_id, repository_ref: 'master'))
expect(page).to have_selector(scoped_search_link('test', search_code: true, project_id: project.id, repository_ref: 'master'))
@@ -184,7 +186,7 @@ RSpec.describe 'User uses header search field', :js do
fill_in_search('Feature')
within(dashboard_search_options_popup_menu) do
- expect(page).to have_text('"Feature" in all GitLab')
+ expect(page).to have_text('Feature in all GitLab')
expect(page).to have_no_text('Feature Flags')
end
end
diff --git a/spec/features/tags/developer_updates_tag_spec.rb b/spec/features/tags/developer_updates_tag_spec.rb
index b2fc28b8493..531ed91c057 100644
--- a/spec/features/tags/developer_updates_tag_spec.rb
+++ b/spec/features/tags/developer_updates_tag_spec.rb
@@ -2,6 +2,7 @@
require 'spec_helper'
+# TODO: remove this file together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
RSpec.describe 'Developer updates tag' do
let(:user) { create(:user) }
let(:group) { create(:group) }
@@ -10,6 +11,7 @@ RSpec.describe 'Developer updates tag' do
before do
project.add_developer(user)
sign_in(user)
+ stub_feature_flags(edit_tag_release_notes_via_release_page: false)
visit project_tags_path(project)
end
diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb
index 3fe276ce162..5317f586390 100644
--- a/spec/features/unsubscribe_links_spec.rb
+++ b/spec/features/unsubscribe_links_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Unsubscribe links', :sidekiq_might_not_need_inline do
let(:mail) { ActionMailer::Base.deliveries.last }
let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) }
let(:header_link) { mail.header['List-Unsubscribe'].to_s[1..-2] } # Strip angle brackets
- let(:body_link) { body.find_link('unsubscribe')['href'] }
+ let(:body_link) { body.find_link('Unsubscribe')['href'] }
before do
perform_enqueued_jobs { issue }
diff --git a/spec/features/users/email_verification_on_login_spec.rb b/spec/features/users/email_verification_on_login_spec.rb
new file mode 100644
index 00000000000..0833f7f6f8e
--- /dev/null
+++ b/spec/features/users/email_verification_on_login_spec.rb
@@ -0,0 +1,357 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting do
+ include EmailHelpers
+
+ let_it_be(:user) { create(:user) }
+
+ let(:require_email_verification_enabled) { user }
+
+ before do
+ stub_feature_flags(require_email_verification: require_email_verification_enabled)
+ end
+
+ shared_examples 'email verification required' do
+ before do
+ allow(Gitlab::AppLogger).to receive(:info)
+ end
+
+ it 'requires email verification before being able to access GitLab' do
+ perform_enqueued_jobs do
+ # When logging in
+ gitlab_sign_in(user)
+ expect_log_message(message: "Account Locked: username=#{user.username}")
+ expect_log_message('Instructions Sent')
+
+ # Expect the user to be locked and the unlock_token to be set
+ user.reload
+ expect(user.locked_at).not_to be_nil
+ expect(user.unlock_token).not_to be_nil
+
+ # Expect to see the verification form on the login page
+ expect(page).to have_current_path(new_user_session_path)
+ expect(page).to have_content('Help us protect your account')
+
+ # Expect an instructions email to be sent with a code
+ code = expect_instructions_email_and_extract_code
+
+ # Signing in again prompts for the code and doesn't send a new one
+ gitlab_sign_in(user)
+ expect(page).to have_current_path(new_user_session_path)
+ expect(page).to have_content('Help us protect your account')
+
+ # Verify the code
+ verify_code(code)
+ expect_log_message('Successful')
+ expect_log_message(message: "Successful Login: username=#{user.username} "\
+ "ip=127.0.0.1 method=standard admin=false")
+
+ # Expect the user to be unlocked
+ expect_user_to_be_unlocked
+
+ # Expect a confirmation page with a meta refresh tag for 3 seconds to the root
+ expect(page).to have_current_path(users_successful_verification_path)
+ expect(page).to have_content('Verification successful')
+ expect(page).to have_selector("meta[http-equiv='refresh'][content='3; url=#{root_path}']", visible: false)
+ end
+ end
+
+ describe 'resending a new code' do
+ it 'resends a new code' do
+ perform_enqueued_jobs do
+ # When logging in
+ gitlab_sign_in(user)
+
+ # Expect an instructions email to be sent with a code
+ code = expect_instructions_email_and_extract_code
+
+ # Request a new code
+ click_link 'Resend code'
+ expect_log_message('Instructions Sent', 2)
+ new_code = expect_instructions_email_and_extract_code
+
+ # Verify the old code is different from the new code
+ expect(code).not_to eq(new_code)
+ end
+ end
+
+ it 'rate limits resends' do
+ # When logging in
+ gitlab_sign_in(user)
+
+ # It shows a resend button
+ expect(page).to have_link 'Resend code'
+
+ # Resend more than the rate limited amount of times
+ 10.times do
+ click_link 'Resend code'
+ end
+
+ # Expect the link to be gone
+ expect(page).not_to have_link 'Resend code'
+
+ # Wait for 1 hour
+ travel 1.hour
+
+ # Now it's visible again
+ gitlab_sign_in(user)
+ expect(page).to have_link 'Resend code'
+ end
+ end
+
+ describe 'verification errors' do
+ it 'rate limits verifications' do
+ perform_enqueued_jobs do
+ # When logging in
+ gitlab_sign_in(user)
+
+ # Expect an instructions email to be sent with a code
+ code = expect_instructions_email_and_extract_code
+
+ # Verify an invalid token more than the rate limited amount of times
+ 11.times do
+ verify_code('123456')
+ end
+
+ # Expect an error message
+ expect_log_message('Failed Attempt', reason: 'rate_limited')
+ expect(page).to have_content("You've reached the maximum amount of tries. "\
+ 'Wait 10 minutes or resend a new code and try again.')
+
+ # Wait for 10 minutes
+ travel 10.minutes
+
+ # Now it works again
+ verify_code(code)
+ expect_log_message('Successful')
+ end
+ end
+
+ it 'verifies invalid codes' do
+ # When logging in
+ gitlab_sign_in(user)
+
+ # Verify an invalid code
+ verify_code('123456')
+
+ # Expect an error message
+ expect_log_message('Failed Attempt', reason: 'invalid')
+ expect(page).to have_content('The code is incorrect. Enter it again, or resend a new code.')
+ end
+
+ it 'verifies expired codes' do
+ perform_enqueued_jobs do
+ # When logging in
+ gitlab_sign_in(user)
+
+ # Expect an instructions email to be sent with a code
+ code = expect_instructions_email_and_extract_code
+
+ # Wait for the code to expire before verifying
+ travel VerifiesWithEmail::TOKEN_VALID_FOR_MINUTES.minutes + 1.second
+ verify_code(code)
+
+ # Expect an error message
+ expect_log_message('Failed Attempt', reason: 'expired')
+ expect(page).to have_content('The code has expired. Resend a new code and try again.')
+ end
+ end
+ end
+ end
+
+ shared_examples 'no email verification required' do |**login_args|
+ it 'does not lock the user and redirects to the root page after logging in' do
+ gitlab_sign_in(user, **login_args)
+
+ expect_user_to_be_unlocked
+
+ expect(page).to have_current_path(root_path)
+ end
+ end
+
+ shared_examples 'no email verification required when 2fa enabled or ff disabled' do
+ context 'when 2FA is enabled' do
+ let_it_be(:user) { create(:user, :two_factor) }
+
+ it_behaves_like 'no email verification required', two_factor_auth: true
+ end
+
+ context 'when the feature flag is disabled' do
+ let(:require_email_verification_enabled) { false }
+
+ it_behaves_like 'no email verification required'
+ end
+ end
+
+ describe 'when failing to login the maximum allowed number of times' do
+ before do
+ # See comment in RequireEmailVerification::MAXIMUM_ATTEMPTS on why this is divided by 2
+ (RequireEmailVerification::MAXIMUM_ATTEMPTS / 2).times do
+ gitlab_sign_in(user, password: 'wrong_password')
+ end
+ end
+
+ it 'locks the user, but does not set the unlock token', :aggregate_failures do
+ user.reload
+ expect(user.locked_at).not_to be_nil
+ expect(user.unlock_token).to be_nil # The unlock token is only set after logging in with valid credentials
+ expect(user.failed_attempts).to eq(RequireEmailVerification::MAXIMUM_ATTEMPTS)
+ end
+
+ it_behaves_like 'email verification required'
+ it_behaves_like 'no email verification required when 2fa enabled or ff disabled'
+
+ describe 'when waiting for the auto unlock time' do
+ before do
+ travel User::UNLOCK_IN + 1.second
+ end
+
+ it_behaves_like 'no email verification required'
+ end
+ end
+
+ describe 'when no previous authentication event exists' do
+ it_behaves_like 'no email verification required'
+ end
+
+ describe 'when a previous authentication event exists for another ip address' do
+ before do
+ create(:authentication_event, :successful, user: user, ip_address: '1.2.3.4')
+ end
+
+ it_behaves_like 'email verification required'
+ it_behaves_like 'no email verification required when 2fa enabled or ff disabled'
+ end
+
+ describe 'when a previous authentication event exists for the same ip address' do
+ before do
+ create(:authentication_event, :successful, user: user)
+ end
+
+ it_behaves_like 'no email verification required'
+ end
+
+ describe 'rate limiting password guessing' do
+ before do
+ 5.times { gitlab_sign_in(user, password: 'wrong_password') }
+ gitlab_sign_in(user)
+ end
+
+ it 'shows an error message on on the login page' do
+ expect(page).to have_current_path(new_user_session_path)
+ expect(page).to have_content('Maximum login attempts exceeded. Wait 10 minutes and try again.')
+ end
+ end
+
+ describe 'inconsistent states' do
+ context 'when the feature flag is toggled off after being prompted for a verification token' do
+ before do
+ create(:authentication_event, :successful, user: user, ip_address: '1.2.3.4')
+ end
+
+ it 'still accepts the token' do
+ perform_enqueued_jobs do
+ # The user is prompted for a verification code
+ gitlab_sign_in(user)
+ expect(page).to have_content('Help us protect your account')
+ code = expect_instructions_email_and_extract_code
+
+ # We toggle the feature flag off
+ stub_feature_flags(require_email_verification: false)
+
+ # Resending and veryfying the code work as expected
+ click_link 'Resend code'
+ new_code = expect_instructions_email_and_extract_code
+
+ verify_code(code)
+ expect(page).to have_content('The code is incorrect. Enter it again, or resend a new code.')
+
+ travel VerifiesWithEmail::TOKEN_VALID_FOR_MINUTES.minutes + 1.second
+
+ verify_code(new_code)
+ expect(page).to have_content('The code has expired. Resend a new code and try again.')
+
+ click_link 'Resend code'
+ another_code = expect_instructions_email_and_extract_code
+
+ verify_code(another_code)
+ expect_user_to_be_unlocked
+ expect(page).to have_current_path(users_successful_verification_path)
+ end
+ end
+ end
+
+ context 'when the feature flag is toggled on after Devise sent unlock instructions' do
+ let(:require_email_verification_enabled) { false }
+
+ before do
+ perform_enqueued_jobs do
+ (User.maximum_attempts / 2).times do
+ gitlab_sign_in(user, password: 'wrong_password')
+ end
+ end
+ end
+
+ it 'the unlock link still works' do
+ # The user is locked and unlock instructions are sent
+ expect(page).to have_content('Invalid login or password.')
+ user.reload
+ expect(user.locked_at).not_to be_nil
+ expect(user.unlock_token).not_to be_nil
+ mail = find_email_for(user)
+
+ expect(mail.to).to match_array([user.email])
+ expect(mail.subject).to eq('Unlock instructions')
+ unlock_url = mail.body.parts.first.to_s[/http.*/]
+
+ # We toggle the feature flag on
+ stub_feature_flags(require_email_verification: true)
+
+ # Unlocking works as expected
+ visit unlock_url
+ expect_user_to_be_unlocked
+ expect(page).to have_current_path(new_user_session_path)
+ expect(page).to have_content('Your account has been unlocked successfully')
+
+ gitlab_sign_in(user)
+ expect(page).to have_current_path(root_path)
+ end
+ end
+ end
+
+ def expect_user_to_be_unlocked
+ user.reload
+
+ aggregate_failures do
+ expect(user.locked_at).to be_nil
+ expect(user.unlock_token).to be_nil
+ expect(user.failed_attempts).to eq(0)
+ end
+ end
+
+ def expect_instructions_email_and_extract_code
+ mail = find_email_for(user)
+ expect(mail.to).to match_array([user.email])
+ expect(mail.subject).to eq('Verify your identity')
+ code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/]
+ reset_delivered_emails!
+ code
+ end
+
+ def verify_code(code)
+ fill_in 'Verification code', with: code
+ click_button 'Verify code'
+ end
+
+ def expect_log_message(event = nil, times = 1, reason: '', message: nil)
+ expect(Gitlab::AppLogger).to have_received(:info)
+ .exactly(times).times
+ .with(message || hash_including(message: 'Email Verification',
+ event: event,
+ username: user.username,
+ ip: '127.0.0.1',
+ reason: reason))
+ end
+end
diff --git a/spec/features/users/google_analytics_csp_spec.rb b/spec/features/users/google_analytics_csp_spec.rb
new file mode 100644
index 00000000000..46a9b3be22f
--- /dev/null
+++ b/spec/features/users/google_analytics_csp_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Google Analytics 4 content security policy' do
+ it 'includes the GA4 content security policy headers' do
+ visit root_path
+
+ expect(response_headers['Content-Security-Policy']).to include(
+ '*.googletagmanager.com',
+ '*.google-analytics.com',
+ '*.analytics.google.com'
+ )
+ end
+end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index efb7c98d63a..3ba3650b608 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -579,9 +579,9 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
context 'group setting' do
before do
group1 = create :group, name: 'Group 1', require_two_factor_authentication: true
- group1.add_user(user, GroupMember::DEVELOPER)
+ group1.add_member(user, GroupMember::DEVELOPER)
group2 = create :group, name: 'Group 2', require_two_factor_authentication: true
- group2.add_user(user, GroupMember::DEVELOPER)
+ group2.add_member(user, GroupMember::DEVELOPER)
end
context 'with grace period defined' do
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index cb395846b96..2a444dad486 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -9,6 +9,12 @@ RSpec.describe 'User page' do
subject(:visit_profile) { visit(user_path(user)) }
+ it 'shows user id' do
+ subject
+
+ expect(page).to have_content("User ID: #{user.id}")
+ end
+
context 'with public profile' do
it 'shows all the tabs' do
subject