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
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb18
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb14
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb13
-rw-r--r--spec/factories/broadcast_messages.rb12
-rw-r--r--spec/factories/ci/builds.rb6
-rw-r--r--spec/factories/ci/runners.rb2
-rw-r--r--spec/factories/clusters/applications/helm.rb2
-rw-r--r--spec/factories/clusters/platforms/kubernetes.rb3
-rw-r--r--spec/factories/emails.rb2
-rw-r--r--spec/factories/gpg_keys.rb4
-rw-r--r--spec/factories/group_members.rb2
-rw-r--r--spec/factories/merge_requests.rb2
-rw-r--r--spec/factories/notes.rb2
-rw-r--r--spec/factories/oauth_access_grants.rb2
-rw-r--r--spec/factories/project_members.rb2
-rw-r--r--spec/factories/todos.rb2
-rw-r--r--spec/factories/uploads.rb10
-rw-r--r--spec/features/calendar_spec.rb21
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/groups/labels/subscription_spec.rb50
-rw-r--r--spec/features/groups/settings/ci_cd_spec.rb39
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb254
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb4
-rw-r--r--spec/features/projects/clusters/user_spec.rb4
-rw-r--r--spec/features/projects/jobs_spec.rb12
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb24
-rw-r--r--spec/features/search/user_uses_search_filters_spec.rb4
-rw-r--r--spec/features/u2f_spec.rb4
-rw-r--r--spec/features/users/overview_spec.rb123
-rw-r--r--spec/features/users/show_spec.rb2
-rw-r--r--spec/finders/group_labels_finder_spec.rb19
-rw-r--r--spec/finders/labels_finder_spec.rb10
-rw-r--r--spec/finders/merge_requests_finder_spec.rb32
-rw-r--r--spec/fixtures/api/schemas/job/runners.json3
-rw-r--r--spec/fixtures/ssh_host_example_key.pub2
-rw-r--r--spec/javascripts/diffs/components/commit_item_spec.js35
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js16
-rw-r--r--spec/javascripts/diffs/store/actions_spec.js9
-rw-r--r--spec/javascripts/diffs/store/mutations_spec.js16
-rw-r--r--spec/javascripts/diffs/store/utils_spec.js16
-rw-r--r--spec/javascripts/jobs/components/commit_block_spec.js2
-rw-r--r--spec/javascripts/jobs/components/empty_state_spec.js2
-rw-r--r--spec/javascripts/jobs/components/job_app_spec.js139
-rw-r--r--spec/javascripts/jobs/store/getters_spec.js92
-rw-r--r--spec/javascripts/notes/mock_data.js24
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb88
-rw-r--r--spec/lib/gitlab/import_export/relation_factory_spec.rb4
-rw-r--r--spec/models/ci/pipeline_spec.rb30
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb5
-rw-r--r--spec/models/instance_configuration_spec.rb6
-rw-r--r--spec/models/label_spec.rb36
-rw-r--r--spec/requests/api/commits_spec.rb14
-rw-r--r--spec/routing/project_routing_spec.rb8
-rw-r--r--spec/serializers/commit_entity_spec.rb28
-rw-r--r--spec/services/notification_recipient_service_spec.rb47
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb4
-rw-r--r--spec/services/system_note_service_spec.rb2
-rw-r--r--spec/support/services/clusters/create_service_shared.rb4
58 files changed, 1084 insertions, 250 deletions
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 10e1bfc30f9..2e0f79cd313 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -86,4 +86,22 @@ describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.receive_max_input_size).to eq(1024)
end
end
+
+ describe 'PUT #reset_registration_token' do
+ before do
+ sign_in(admin)
+ end
+
+ subject { put :reset_registration_token }
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { ApplicationSetting.current.runners_registration_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(admin_runners_path)
+ end
+ end
end
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index ea18122e0c3..06ccace8242 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -17,4 +17,18 @@ describe Groups::Settings::CiCdController do
expect(response).to render_template(:show)
end
end
+
+ describe 'PUT #reset_registration_token' do
+ subject { put :reset_registration_token, group_id: group }
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { group.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(group_settings_ci_cd_path)
+ end
+ end
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 1f14a0cc381..4629929f9af 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -74,6 +74,19 @@ describe Projects::Settings::CiCdController do
end
end
+ describe 'PUT #reset_registration_token' do
+ subject { put :reset_registration_token, namespace_id: project.namespace, project_id: project }
+ it 'resets runner registration token' do
+ expect { subject }.to change { project.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(namespace_project_settings_ci_cd_path)
+ end
+ end
+
describe 'PATCH update' do
let(:params) { { ci_config_path: '' } }
diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb
index 9a65e7f8a3f..1a2be5e9552 100644
--- a/spec/factories/broadcast_messages.rb
+++ b/spec/factories/broadcast_messages.rb
@@ -1,17 +1,17 @@
FactoryBot.define do
factory :broadcast_message do
message "MyText"
- starts_at 1.day.ago
- ends_at 1.day.from_now
+ starts_at { 1.day.ago }
+ ends_at { 1.day.from_now }
trait :expired do
- starts_at 5.days.ago
- ends_at 3.days.ago
+ starts_at { 5.days.ago }
+ ends_at { 3.days.ago }
end
trait :future do
- starts_at 5.days.from_now
- ends_at 6.days.from_now
+ starts_at { 5.days.from_now }
+ ends_at { 6.days.from_now }
end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 7a4b1dfafac..85ba7d4097d 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -180,12 +180,12 @@ FactoryBot.define do
end
trait :erased do
- erased_at Time.now
+ erased_at { Time.now }
erased_by factory: :user
end
trait :queued do
- queued_at Time.now
+ queued_at { Time.now }
runner factory: :ci_runner
end
@@ -215,7 +215,7 @@ FactoryBot.define do
end
trait :expired do
- artifacts_expire_at 1.minute.ago
+ artifacts_expire_at { 1.minute.ago }
end
trait :with_commit do
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index 347e4f433e2..f564e7bee47 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
runner_type :instance_type
trait :online do
- contacted_at Time.now
+ contacted_at { Time.now }
end
trait :instance do
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 5756486df27..3c9ca22a051 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -42,7 +42,7 @@ FactoryBot.define do
trait :timeouted do
installing
- updated_at ClusterWaitForAppInstallationWorker::TIMEOUT.ago
+ updated_at { ClusterWaitForAppInstallationWorker::TIMEOUT.ago }
end
factory :clusters_applications_ingress, class: Clusters::Applications::Ingress do
diff --git a/spec/factories/clusters/platforms/kubernetes.rb b/spec/factories/clusters/platforms/kubernetes.rb
index 36ac2372204..4a0d1b181ea 100644
--- a/spec/factories/clusters/platforms/kubernetes.rb
+++ b/spec/factories/clusters/platforms/kubernetes.rb
@@ -3,11 +3,10 @@ FactoryBot.define do
cluster
namespace nil
api_url 'https://kubernetes.example.com'
- token 'a' * 40
+ token { 'a' * 40 }
trait :configured do
api_url 'https://kubernetes.example.com'
- token 'a' * 40
username 'xxxxxx'
password 'xxxxxx'
diff --git a/spec/factories/emails.rb b/spec/factories/emails.rb
index d23ddf9d79b..feacd5ccf15 100644
--- a/spec/factories/emails.rb
+++ b/spec/factories/emails.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
user
email { generate(:email_alias) }
- trait(:confirmed) { confirmed_at Time.now }
+ trait(:confirmed) { confirmed_at { Time.now } }
trait(:skip_validate) { to_create {|instance| instance.save(validate: false) } }
end
end
diff --git a/spec/factories/gpg_keys.rb b/spec/factories/gpg_keys.rb
index 51b8ddc9934..3c0f43cc1b6 100644
--- a/spec/factories/gpg_keys.rb
+++ b/spec/factories/gpg_keys.rb
@@ -2,11 +2,11 @@ require_relative '../support/helpers/gpg_helpers'
FactoryBot.define do
factory :gpg_key do
- key GpgHelpers::User1.public_key
+ key { GpgHelpers::User1.public_key }
user
factory :gpg_key_with_subkeys do
- key GpgHelpers::User1.public_key_with_extra_signing_key
+ key { GpgHelpers::User1.public_key_with_extra_signing_key }
end
end
end
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 47036560b9d..12be63e5d92 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
trait(:developer) { access_level GroupMember::DEVELOPER }
trait(:maintainer) { access_level GroupMember::MAINTAINER }
trait(:owner) { access_level GroupMember::OWNER }
- trait(:access_request) { requested_at Time.now }
+ trait(:access_request) { requested_at { Time.now } }
trait(:invited) do
user_id nil
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index b8b089b069b..8094c43b065 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -80,7 +80,7 @@ FactoryBot.define do
trait :merge_when_pipeline_succeeds do
merge_when_pipeline_succeeds true
- merge_user author
+ merge_user { author }
end
trait :remove_source_branch do
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 6844ed8aa4a..2d1f48bf249 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -90,7 +90,7 @@ FactoryBot.define do
noteable nil
noteable_type 'Commit'
noteable_id nil
- commit_id RepoHelpers.sample_commit.id
+ commit_id { RepoHelpers.sample_commit.id }
end
trait :legacy_diff_note do
diff --git a/spec/factories/oauth_access_grants.rb b/spec/factories/oauth_access_grants.rb
index 9e6af24c4eb..02c51cd9899 100644
--- a/spec/factories/oauth_access_grants.rb
+++ b/spec/factories/oauth_access_grants.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
resource_owner_id { create(:user).id }
application
token { Doorkeeper::OAuth::Helpers::UniqueToken.generate }
- expires_in 2.hours
+ expires_in { 2.hours }
redirect_uri { application.redirect_uri }
scopes { application.scopes }
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index 22a8085ea45..c72e0487895 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -8,7 +8,7 @@ FactoryBot.define do
trait(:reporter) { access_level ProjectMember::REPORTER }
trait(:developer) { access_level ProjectMember::DEVELOPER }
trait(:maintainer) { access_level ProjectMember::MAINTAINER }
- trait(:access_request) { requested_at Time.now }
+ trait(:access_request) { requested_at { Time.now } }
trait(:invited) do
user_id nil
diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb
index 14486c80341..ed3d87eb76b 100644
--- a/spec/factories/todos.rb
+++ b/spec/factories/todos.rb
@@ -49,7 +49,7 @@ FactoryBot.define do
author
user
action { Todo::ASSIGNED }
- commit_id RepoHelpers.sample_commit.id
+ commit_id { RepoHelpers.sample_commit.id }
target_type "Commit"
end
end
diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb
index 81c485fba1a..7256f785e1f 100644
--- a/spec/factories/uploads.rb
+++ b/spec/factories/uploads.rb
@@ -1,7 +1,7 @@
FactoryBot.define do
factory :upload do
model { build(:project) }
- size 100.kilobytes
+ size { 100.kilobytes }
uploader "AvatarUploader"
mount_point :avatar
secret nil
@@ -19,13 +19,13 @@ FactoryBot.define do
uploader "PersonalFileUploader"
path { File.join(secret, filename) }
model { build(:personal_snippet) }
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :issuable_upload do
uploader "FileUploader"
path { File.join(secret, filename) }
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :with_file do
@@ -43,14 +43,14 @@ FactoryBot.define do
model { build(:group) }
path { File.join(secret, filename) }
uploader "NamespaceFileUploader"
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :favicon_upload do
model { build(:appearance) }
path { File.join(secret, filename) }
uploader "FaviconUploader"
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :attachment_upload do
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index f08946b0593..aa3ca8923ff 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -64,7 +64,7 @@ describe 'Contributions Calendar', :js do
end
def selected_day_activities(visible: true)
- find('.user-calendar-activities', visible: visible).text
+ find('.tab-pane#activity .user-calendar-activities', visible: visible).text
end
before do
@@ -74,15 +74,16 @@ describe 'Contributions Calendar', :js do
describe 'calendar day selection' do
before do
visit user.username
+ page.find('.js-activity-tab a').click
wait_for_requests
end
it 'displays calendar' do
- expect(page).to have_css('.js-contrib-calendar')
+ expect(find('.tab-pane#activity')).to have_css('.js-contrib-calendar')
end
describe 'select calendar day' do
- let(:cells) { page.all('.user-contrib-cell') }
+ let(:cells) { page.all('.tab-pane#activity .user-contrib-cell') }
before do
cells[0].click
@@ -108,6 +109,7 @@ describe 'Contributions Calendar', :js do
describe 'deselect calendar day' do
before do
cells[0].click
+ page.find('.js-activity-tab a').click
wait_for_requests
end
@@ -122,6 +124,7 @@ describe 'Contributions Calendar', :js do
shared_context 'visit user page' do
before do
visit user.username
+ page.find('.js-activity-tab a').click
wait_for_requests
end
end
@@ -130,12 +133,12 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity square color for 1 contribution' do
- expect(page).to have_selector(get_cell_color_selector(contribution_count), count: 1)
+ expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(contribution_count), count: 1)
end
it 'displays calendar activity square on the correct date' do
today = Date.today.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
+ expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
end
end
@@ -150,7 +153,7 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity log' do
- expect(find('.content_list .event-note')).to have_content issue_title
+ expect(find('.tab-pane#activity .content_list .event-note')).to have_content issue_title
end
end
end
@@ -182,17 +185,17 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity squares for both days' do
- expect(page).to have_selector(get_cell_color_selector(1), count: 2)
+ expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(1), count: 2)
end
it 'displays calendar activity square for yesterday' do
yesterday = Date.yesterday.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
+ expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
end
it 'displays calendar activity square for today' do
today = Date.today.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(1, today), count: 1)
+ expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, today), count: 1)
end
end
end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index d7234158fa1..0db8093411b 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -14,7 +14,7 @@ describe 'Tooltips on .timeago dates', :js do
updated_at: created_date, created_at: created_date)
sign_in user
- visit user_path(user)
+ visit user_activity_path(user)
wait_for_requests()
page.find('.js-timeago').hover
diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb
index d9543bfa97f..22b51b297a6 100644
--- a/spec/features/groups/labels/subscription_spec.rb
+++ b/spec/features/groups/labels/subscription_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
describe 'Labels subscription' do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let!(:feature) { create(:group_label, group: group, title: 'feature') }
+ let!(:label1) { create(:group_label, group: group, title: 'foo') }
+ let!(:label2) { create(:group_label, group: group, title: 'bar') }
context 'when signed in' do
before do
@@ -14,9 +15,9 @@ describe 'Labels subscription' do
it 'users can subscribe/unsubscribe to group labels', :js do
visit group_labels_path(group)
- expect(page).to have_content('feature')
+ expect(page).to have_content(label1.title)
- within "#group_label_#{feature.id}" do
+ within "#group_label_#{label1.id}" do
expect(page).not_to have_button 'Unsubscribe'
click_button 'Subscribe'
@@ -30,15 +31,48 @@ describe 'Labels subscription' do
expect(page).not_to have_button 'Unsubscribe'
end
end
+
+ context 'subscription filter' do
+ before do
+ visit group_labels_path(group)
+ end
+
+ it 'shows only subscribed labels' do
+ label1.subscribe(user)
+
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).to have_content label1.title
+ end
+ end
+
+ it 'shows no subscribed labels message' do
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).not_to have_content label1.title
+ expect(page).to have_content('You do not have any subscriptions yet')
+ end
+ end
+ end
end
context 'when not signed in' do
- it 'users can not subscribe/unsubscribe to labels' do
+ before do
visit group_labels_path(group)
+ end
- expect(page).to have_content 'feature'
+ it 'users can not subscribe/unsubscribe to labels' do
+ expect(page).to have_content label1.title
expect(page).not_to have_button('Subscribe')
end
+
+ it 'does not show subscribed tab' do
+ page.within('.nav-tabs') do
+ expect(page).not_to have_link 'Subscribed'
+ end
+ end
end
def click_link_on_dropdown(text)
@@ -48,4 +82,10 @@ describe 'Labels subscription' do
find('a.js-subscribe-button', text: text).click
end
end
+
+ def click_subscribed_tab
+ page.within('.nav-tabs') do
+ click_link 'Subscribed'
+ end
+ end
end
diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb
new file mode 100644
index 00000000000..d422fd18346
--- /dev/null
+++ b/spec/features/groups/settings/ci_cd_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Group CI/CD settings' do
+ include WaitForRequests
+
+ let(:user) {create(:user)}
+ let(:group) {create(:group)}
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ describe 'runners registration token' do
+ let!(:token) { group.runners_token }
+
+ before do
+ visit group_settings_ci_cd_path(group)
+ end
+
+ it 'has a registration token' do
+ expect(page.find('#registration_token')).to have_content(token)
+ end
+
+ describe 'reload registration token' do
+ let(:page_token) { find('#registration_token').text }
+
+ before do
+ click_button 'Reset runners registration token'
+ end
+
+ it 'changes registration token' do
+ expect(page_token).not_to eq token
+ end
+ end
+ end
+end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 206a3a4fe9a..e168bb0fc89 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -61,83 +61,229 @@ describe 'User edit profile' do
end
context 'user status', :js do
- def select_emoji(emoji_name)
+ def select_emoji(emoji_name, is_modal = false)
+ emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu'
toggle_button = find('.js-toggle-emoji-menu')
toggle_button.click
- emoji_button = find(%Q{.js-status-emoji-menu .js-emoji-btn gl-emoji[data-name="#{emoji_name}"]})
+ emoji_button = find(%Q{#{emoji_menu_class} .js-emoji-btn gl-emoji[data-name="#{emoji_name}"]})
emoji_button.click
end
- it 'shows the user status form' do
- visit(profile_path)
+ context 'profile edit form' do
+ it 'shows the user status form' do
+ visit(profile_path)
- expect(page).to have_content('Current status')
- end
+ expect(page).to have_content('Current status')
+ end
- it 'adds emoji to user status' do
- emoji = 'biohazard'
- visit(profile_path)
- select_emoji(emoji)
- submit_settings
+ it 'adds emoji to user status' do
+ emoji = 'biohazard'
+ visit(profile_path)
+ select_emoji(emoji)
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(emoji)
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ end
end
- end
- it 'adds message to user status' do
- message = 'I have something to say'
- visit(profile_path)
- fill_in 'js-status-message-field', with: message
- submit_settings
+ it 'adds message to user status' do
+ message = 'I have something to say'
+ visit(profile_path)
+ fill_in 'js-status-message-field', with: message
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji('speech_balloon')
- expect(page).to have_content message
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji('speech_balloon')
+ expect(page).to have_content message
+ end
end
- end
- it 'adds message and emoji to user status' do
- emoji = 'tanabata_tree'
- message = 'Playing outside'
- visit(profile_path)
- select_emoji(emoji)
- fill_in 'js-status-message-field', with: message
- submit_settings
+ it 'adds message and emoji to user status' do
+ emoji = 'tanabata_tree'
+ message = 'Playing outside'
+ visit(profile_path)
+ select_emoji(emoji)
+ fill_in 'js-status-message-field', with: message
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(emoji)
- expect(page).to have_content message
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ expect(page).to have_content message
+ end
end
- end
- it 'clears the user status' do
- user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+ it 'clears the user status' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ visit(profile_path)
+ click_button 'js-clear-user-status-button'
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(user_status.emoji)
- expect(page).to have_content user_status.message
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
end
- visit(profile_path)
- click_button 'js-clear-user-status-button'
- submit_settings
+ it 'displays a default emoji if only message is entered' do
+ message = 'a status without emoji'
+ visit(profile_path)
+ fill_in 'js-status-message-field', with: message
- visit user_path(user)
- expect(page).not_to have_selector '.cover-status'
+ within('.js-toggle-emoji-menu') do
+ expect(page).to have_emoji('speech_balloon')
+ end
+ end
end
- it 'displays a default emoji if only message is entered' do
- message = 'a status without emoji'
- visit(profile_path)
- fill_in 'js-status-message-field', with: message
+ context 'user menu' do
+ def open_user_status_modal
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Set status'
+ end
+ end
+
+ def set_user_status_in_modal
+ page.within "#set-user-status-modal" do
+ click_button 'Set status'
+ end
+ end
+
+ before do
+ visit root_path(user)
+ end
+
+ it 'shows the "Set status" menu item in the user menu' do
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ expect(page).to have_content('Set status')
+ end
+ end
+
+ it 'shows the "Edit status" menu item in the user menu' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+ visit root_path(user)
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ expect(page).to have_content('Edit status')
+ end
+ end
+
+ it 'shows user status modal' do
+ open_user_status_modal
+
+ expect(page.find('#set-user-status-modal')).to be_visible
+ expect(page).to have_content('Set a status')
+ end
+
+ it 'adds emoji to user status' do
+ emoji = 'biohazard'
+ open_user_status_modal
+ select_emoji(emoji, true)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ end
+ end
+
+ it 'adds message to user status' do
+ message = 'I have something to say'
+ open_user_status_modal
+ find('.js-status-message-field').native.send_keys(message)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji('speech_balloon')
+ expect(page).to have_content message
+ end
+ end
+
+ it 'adds message and emoji to user status' do
+ emoji = 'tanabata_tree'
+ message = 'Playing outside'
+ open_user_status_modal
+ select_emoji(emoji, true)
+ find('.js-status-message-field').native.send_keys(message)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ expect(page).to have_content message
+ end
+ end
+
+ it 'clears the user status with the "X" button' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Edit status'
+ end
+
+ find('.js-clear-user-status-button').click
+ set_user_status_in_modal
+
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
+ end
+
+ it 'clears the user status with the "Remove status" button' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Edit status'
+ end
+
+ page.within "#set-user-status-modal" do
+ click_button 'Remove status'
+ end
+
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
+ end
+
+ it 'displays a default emoji if only message is entered' do
+ message = 'a status without emoji'
+ open_user_status_modal
+ find('.js-status-message-field').native.send_keys(message)
- within('.js-toggle-emoji-menu') do
- expect(page).to have_emoji('speech_balloon')
+ within('.js-toggle-emoji-menu') do
+ expect(page).to have_emoji('speech_balloon')
+ end
end
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index edc763ad0ad..8b92b9fc869 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -84,10 +84,8 @@ describe 'Gcp Cluster', :js do
it_behaves_like 'valid cluster gcp form'
- context 'rbac_clusters feature flag is enabled' do
+ context 'RBAC is enabled for the cluster' do
before do
- stub_feature_flags(rbac_clusters: true)
-
check 'cluster_provider_gcp_attributes_legacy_abac'
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 2b4998ed5ac..9ae1dba60b5 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -44,10 +44,8 @@ describe 'User Cluster', :js do
it_behaves_like 'valid cluster user form'
- context 'rbac_clusters feature flag is enabled' do
+ context 'RBAC is enabled for the cluster' do
before do
- stub_feature_flags(rbac_clusters: true)
-
check 'cluster_platform_kubernetes_attributes_authorization_type'
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 6a7bf0860e9..7bebd066b80 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -542,7 +542,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
end
- it 'shows manual action empty state' do
+ it 'shows manual action empty state', :js do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job requires a manual action')
expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
@@ -591,14 +591,14 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
end
- it 'shows empty state' do
+ it 'shows empty state', :js do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job has not been triggered yet')
expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered')
end
end
- context 'Pending job' do
+ context 'Pending job', :js do
let(:job) { create(:ci_build, :pending, pipeline: pipeline) }
before do
@@ -625,7 +625,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'without log' do
+ context 'without log', :js do
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
before do
@@ -640,7 +640,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'Skipped job' do
+ context 'Skipped job', :js do
let(:job) { create(:ci_build, :skipped, pipeline: pipeline) }
before do
@@ -654,7 +654,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'when job is failed but has no trace' do
+ context 'when job is failed but has no trace', :js do
let(:job) { create(:ci_build, :failed, pipeline: pipeline) }
it 'renders empty state' do
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index 30b0a5578ea..6f8ec0015ad 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -137,5 +137,29 @@ describe "Projects > Settings > Pipelines settings" do
end
end
end
+
+ describe 'runners registration token' do
+ let!(:token) { project.runners_token }
+
+ before do
+ visit project_settings_ci_cd_path(project)
+ end
+
+ it 'has a registration token' do
+ expect(page.find('#registration_token')).to have_content(token)
+ end
+
+ describe 'reload registration token' do
+ let(:page_token) { find('#registration_token').text }
+
+ before do
+ click_button 'Reset runners registration token'
+ end
+
+ it 'changes registration token' do
+ expect(page_token).not_to eq token
+ end
+ end
+ end
end
end
diff --git a/spec/features/search/user_uses_search_filters_spec.rb b/spec/features/search/user_uses_search_filters_spec.rb
index 66afe163447..0725ff178ac 100644
--- a/spec/features/search/user_uses_search_filters_spec.rb
+++ b/spec/features/search/user_uses_search_filters_spec.rb
@@ -14,7 +14,7 @@ describe 'User uses search filters', :js do
visit(search_path)
end
- context' when filtering by group' do
+ context 'when filtering by group' do
it 'shows group projects' do
find('.js-search-group-dropdown').click
@@ -36,7 +36,7 @@ describe 'User uses search filters', :js do
end
end
- context' when filtering by project' do
+ context 'when filtering by project' do
it 'shows a project' do
page.within('.project-filter') do
find('.js-search-project-dropdown').click
diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb
index f1192f48b86..ae9b65d1a39 100644
--- a/spec/features/u2f_spec.rb
+++ b/spec/features/u2f_spec.rb
@@ -42,7 +42,7 @@ describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
it 'allows registering a new device with a name' do
visit profile_account_path
manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using mobile")
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
u2f_device = register_u2f_device
@@ -70,7 +70,7 @@ describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
it 'allows deleting a device' do
visit profile_account_path
manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using mobile")
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
first_u2f_device = register_u2f_device
second_u2f_device = register_u2f_device(name: 'My other device')
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
new file mode 100644
index 00000000000..11f357cbaa5
--- /dev/null
+++ b/spec/features/users/overview_spec.rb
@@ -0,0 +1,123 @@
+require 'spec_helper'
+
+describe 'Overview tab on a user profile', :js do
+ let(:user) { create(:user) }
+ let(:contributed_project) { create(:project, :public, :repository) }
+
+ def push_code_contribution
+ event = create(:push_event, project: contributed_project, author: user)
+
+ create(:push_event_payload,
+ event: event,
+ commit_from: '11f9ac0a48b62cef25eedede4c1819964f08d5ce',
+ commit_to: '1cf19a015df3523caf0a1f9d40c98a267d6a2fc2',
+ commit_count: 3,
+ ref: 'master')
+ end
+
+ before do
+ sign_in user
+ end
+
+ describe 'activities section' do
+ shared_context 'visit overview tab' do
+ before do
+ visit user.username
+ page.find('.js-overview-tab a').click
+ wait_for_requests
+ end
+ end
+
+ describe 'user has no activities' do
+ include_context 'visit overview tab'
+
+ it 'does not show any entries in the list of activities' do
+ page.within('.activities-block') do
+ expect(page).not_to have_selector('.event-item')
+ end
+ end
+
+ it 'does not show a link to the activity list' do
+ expect(find('#js-overview .activities-block')).to have_selector('.js-view-all', visible: false)
+ end
+ end
+
+ describe 'user has 3 activities' do
+ before do
+ 3.times { push_code_contribution }
+ end
+
+ include_context 'visit overview tab'
+
+ it 'display 3 entries in the list of activities' do
+ expect(find('#js-overview')).to have_selector('.event-item', count: 3)
+ end
+ end
+
+ describe 'user has 10 activities' do
+ before do
+ 10.times { push_code_contribution }
+ end
+
+ include_context 'visit overview tab'
+
+ it 'displays 5 entries in the list of activities' do
+ expect(find('#js-overview')).to have_selector('.event-item', count: 5)
+ end
+
+ it 'shows a link to the activity list' do
+ expect(find('#js-overview .activities-block')).to have_selector('.js-view-all', visible: true)
+ end
+
+ it 'links to the activity tab' do
+ page.within('.activities-block') do
+ find('.js-view-all').click
+ wait_for_requests
+ expect(URI.parse(current_url).path).to eq("/users/#{user.username}/activity")
+ end
+ end
+ end
+ end
+
+ describe 'projects section' do
+ shared_context 'visit overview tab' do
+ before do
+ visit user.username
+ page.find('.js-overview-tab a').click
+ wait_for_requests
+ end
+ end
+
+ describe 'user has no personal projects' do
+ include_context 'visit overview tab'
+
+ it 'it shows an empty project list with an info message' do
+ page.within('.projects-block') do
+ expect(page).to have_content('No projects found')
+ expect(page).not_to have_selector('.project-row')
+ end
+ end
+
+ it 'does not show a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: false)
+ end
+ end
+
+ describe 'user has a personal project' do
+ let(:private_project) { create(:project, :private, namespace: user.namespace, creator: user) { |p| p.add_maintainer(user) } }
+ let!(:private_event) { create(:event, project: private_project, author: user) }
+
+ include_context 'visit overview tab'
+
+ it 'it shows one entry in the list of projects' do
+ page.within('.projects-block') do
+ expect(page).to have_selector('.project-row', count: 1)
+ end
+ end
+
+ it 'shows a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
+ end
+ end
+ end
+end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index bc07ab48c39..86379164cf0 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -8,6 +8,7 @@ describe 'User page' do
visit(user_path(user))
page.within '.nav-links' do
+ expect(page).to have_link('Overview')
expect(page).to have_link('Activity')
expect(page).to have_link('Groups')
expect(page).to have_link('Contributed projects')
@@ -44,6 +45,7 @@ describe 'User page' do
visit(user_path(user))
page.within '.nav-links' do
+ expect(page).to have_link('Overview')
expect(page).to have_link('Activity')
expect(page).to have_link('Groups')
expect(page).to have_link('Contributed projects')
diff --git a/spec/finders/group_labels_finder_spec.rb b/spec/finders/group_labels_finder_spec.rb
index ef68fc105e4..7bdd312eff0 100644
--- a/spec/finders/group_labels_finder_spec.rb
+++ b/spec/finders/group_labels_finder_spec.rb
@@ -4,29 +4,38 @@ require 'spec_helper'
describe GroupLabelsFinder, '#execute' do
let!(:group) { create(:group) }
+ let!(:user) { create(:user) }
let!(:label1) { create(:group_label, title: 'Foo', description: 'Lorem ipsum', group: group) }
let!(:label2) { create(:group_label, title: 'Bar', description: 'Fusce consequat', group: group) }
it 'returns all group labels sorted by name if no params' do
- result = described_class.new(group).execute
+ result = described_class.new(user, group).execute
expect(result.to_a).to match_array([label2, label1])
end
it 'returns all group labels sorted by name desc' do
- result = described_class.new(group, sort: 'name_desc').execute
+ result = described_class.new(user, group, sort: 'name_desc').execute
expect(result.to_a).to match_array([label2, label1])
end
- it 'returns group labels that march search' do
- result = described_class.new(group, search: 'Foo').execute
+ it 'returns group labels that match search' do
+ result = described_class.new(user, group, search: 'Foo').execute
expect(result.to_a).to match_array([label1])
end
+ it 'returns group labels user subscribed to' do
+ label2.subscribe(user)
+
+ result = described_class.new(user, group, subscribed: 'true').execute
+
+ expect(result.to_a).to match_array([label2])
+ end
+
it 'returns second page of labels' do
- result = described_class.new(group, page: '2').execute
+ result = described_class.new(user, group, page: '2').execute
expect(result.to_a).to match_array([])
end
diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb
index f5cec8e349a..9abc52aa664 100644
--- a/spec/finders/labels_finder_spec.rb
+++ b/spec/finders/labels_finder_spec.rb
@@ -210,5 +210,15 @@ describe LabelsFinder do
expect(finder.execute).to eq [project_label_1]
end
end
+
+ context 'filter by subscription' do
+ it 'returns labels user subscribed to' do
+ project_label_1.subscribe(user)
+
+ finder = described_class.new(user, subscribed: 'true')
+
+ expect(finder.execute).to eq [project_label_1]
+ end
+ end
end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 33d01697c75..ff4c6b8dd42 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -3,21 +3,37 @@ require 'spec_helper'
describe MergeRequestsFinder do
include ProjectForksHelper
+ # We need to explicitly permit Gitaly N+1s because of the specs that use
+ # :request_store. Gitaly N+1 detection is only enabled when :request_store is,
+ # but we don't care about potential N+1s when we're just creating several
+ # projects in the setup phase.
+ def create_project_without_n_plus_1(*args)
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ create(:project, :public, *args)
+ end
+ end
+
let(:user) { create :user }
let(:user2) { create :user }
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
- let(:project1) { create(:project, :public, group: group) }
- let(:project2) { fork_project(project1, user) }
+ let(:project1) { create_project_without_n_plus_1(group: group) }
+ let(:project2) do
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ fork_project(project1, user)
+ end
+ end
let(:project3) do
- p = fork_project(project1, user)
- p.update!(archived: true)
- p
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ p = fork_project(project1, user)
+ p.update!(archived: true)
+ p
+ end
end
- let(:project4) { create(:project, :public, group: subgroup) }
- let(:project5) { create(:project, :public, group: subgroup) }
- let(:project6) { create(:project, :public, group: subgroup) }
+ let(:project4) { create_project_without_n_plus_1(group: subgroup) }
+ let(:project5) { create_project_without_n_plus_1(group: subgroup) }
+ let(:project6) { create_project_without_n_plus_1(group: subgroup) }
let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) }
let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') }
diff --git a/spec/fixtures/api/schemas/job/runners.json b/spec/fixtures/api/schemas/job/runners.json
index bebb0c88652..646bfd3a82d 100644
--- a/spec/fixtures/api/schemas/job/runners.json
+++ b/spec/fixtures/api/schemas/job/runners.json
@@ -8,6 +8,5 @@
"online": { "type": "boolean" },
"available": { "type": "boolean" },
"settings_path": { "type": "string" }
- },
- "additionalProperties": false
+ }
}
diff --git a/spec/fixtures/ssh_host_example_key.pub b/spec/fixtures/ssh_host_example_key.pub
index 6bac42b3ad0..d43315ddae8 100644
--- a/spec/fixtures/ssh_host_example_key.pub
+++ b/spec/fixtures/ssh_host_example_key.pub
@@ -1 +1 @@
-random content
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuRkAgwaap/pXThwCpjX8Wd5tR36Tqx3sW2sVVHs3UKB7kd+xNknw7e4qpuEATv56xHrhKm2+ye/JidTuQ/1EwFhjaz7I5wTslfVawQpeH1ZqAGmvdO/xTw+l7fgEFVlGVx9y0HV3m52y2C9yw82qmg+BohbTVgPtjjutpFc+CwLQxLTnTrRhZf5udQgz+YlwLv+Y0kDx6+DWWOl8N9+TWuGyFKBln79CyBgFcK5NFmF48kYn8W+r7rmawfw9XbuF1aa+6JF+6cNR1mCEonyrRLdXP+vWcxpLKYfejB0NmA1y+W9M/K53AcIHA5zlRQ49tFh0P22eh/Gl8JQ6yyuin foo@bar.mynet
diff --git a/spec/javascripts/diffs/components/commit_item_spec.js b/spec/javascripts/diffs/components/commit_item_spec.js
index 627fb8c490a..8c3376c0eb3 100644
--- a/spec/javascripts/diffs/components/commit_item_spec.js
+++ b/spec/javascripts/diffs/components/commit_item_spec.js
@@ -9,6 +9,8 @@ import getDiffWithCommit from '../mock_data/diff_with_commit';
const TEST_AUTHOR_NAME = 'test';
const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=36`;
+const TEST_SIGNATURE_HTML = '<a>Legit commit</a>';
+const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`;
const getTitleElement = vm => vm.$el.querySelector('.commit-row-message.item-title');
const getDescElement = vm => vm.$el.querySelector('pre.commit-row-description');
@@ -16,6 +18,7 @@ const getDescExpandElement = vm => vm.$el.querySelector('.commit-content .text-e
const getShaElement = vm => vm.$el.querySelector('.commit-sha-group');
const getAvatarElement = vm => vm.$el.querySelector('.user-avatar-link');
const getCommitterElement = vm => vm.$el.querySelector('.commiter');
+const getCommitActionsElement = vm => vm.$el.querySelector('.commit-actions');
describe('diffs/components/commit_widget', () => {
const Component = Vue.extend(CommitItem);
@@ -125,4 +128,36 @@ describe('diffs/components/commit_widget', () => {
expect(nameElement).toHaveText(TEST_AUTHOR_NAME);
});
});
+
+ describe('with signature', () => {
+ beforeEach(done => {
+ vm.commit.signatureHtml = TEST_SIGNATURE_HTML;
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders signature html', () => {
+ const actionsElement = getCommitActionsElement(vm);
+
+ expect(actionsElement).toContainHtml(TEST_SIGNATURE_HTML);
+ });
+ });
+
+ describe('with pipeline status', () => {
+ beforeEach(done => {
+ vm.commit.pipelineStatusPath = TEST_PIPELINE_STATUS_PATH;
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders pipeline status', () => {
+ const actionsElement = getCommitActionsElement(vm);
+
+ expect(actionsElement).toContainElement('.ci-status-link');
+ });
+ });
});
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
index b29a22da7c2..0ad214ea4a4 100644
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ b/spec/javascripts/diffs/mock_data/diff_discussions.js
@@ -2,15 +2,13 @@ export default {
id: '6b232e05bea388c6b043ccc243ba505faac04ea8',
reply_id: '6b232e05bea388c6b043ccc243ba505faac04ea8',
position: {
- formatter: {
- old_line: null,
- new_line: 2,
- old_path: 'CHANGELOG',
- new_path: 'CHANGELOG',
- base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
- start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
- head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
- },
+ old_line: null,
+ new_line: 2,
+ old_path: 'CHANGELOG',
+ new_path: 'CHANGELOG',
+ base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
+ start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
+ head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
},
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
expanded: true,
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index aacad7a479b..85c1926fcb1 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -148,12 +148,8 @@ describe('DiffsStoreActions', () => {
},
fileHash: 'ABC',
resolvable: true,
- position: {
- formatter: diffPosition,
- },
- original_position: {
- formatter: diffPosition,
- },
+ position: diffPosition,
+ original_position: diffPosition,
};
const discussions = reduceDiscussionsToLineCodes([singleDiscussion]);
@@ -178,6 +174,7 @@ describe('DiffsStoreActions', () => {
oldLine: 5,
oldPath: 'file2',
lineCode: 'ABC_1_1',
+ positionType: 'text',
},
},
},
diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js
index cc8d5dc4bac..0b712055956 100644
--- a/spec/javascripts/diffs/store/mutations_spec.js
+++ b/spec/javascripts/diffs/store/mutations_spec.js
@@ -194,24 +194,16 @@ describe('DiffsStoreMutations', () => {
line_code: 'ABC_1',
diff_discussion: true,
resolvable: true,
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: diffPosition,
- },
+ original_position: diffPosition,
+ position: diffPosition,
},
{
id: 2,
line_code: 'ABC_1',
diff_discussion: true,
resolvable: true,
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: diffPosition,
- },
+ original_position: diffPosition,
+ position: diffPosition,
},
];
diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js
index e660f94c72e..257270a91ec 100644
--- a/spec/javascripts/diffs/store/utils_spec.js
+++ b/spec/javascripts/diffs/store/utils_spec.js
@@ -333,20 +333,12 @@ describe('DiffsStoreUtils', () => {
const discussions = {
upToDateDiscussion1: {
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: wrongDiffPosition,
- },
+ original_position: diffPosition,
+ position: wrongDiffPosition,
},
outDatedDiscussion1: {
- original_position: {
- formatter: wrongDiffPosition,
- },
- position: {
- formatter: wrongDiffPosition,
- },
+ original_position: wrongDiffPosition,
+ position: wrongDiffPosition,
},
};
diff --git a/spec/javascripts/jobs/components/commit_block_spec.js b/spec/javascripts/jobs/components/commit_block_spec.js
index 61ee993f46a..0bcc4ff940f 100644
--- a/spec/javascripts/jobs/components/commit_block_spec.js
+++ b/spec/javascripts/jobs/components/commit_block_spec.js
@@ -56,7 +56,7 @@ describe('Commit block', () => {
props.mergeRequest.path,
);
expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(
- props.mergeRequest.iid,
+ `!${props.mergeRequest.iid}`,
);
});
});
diff --git a/spec/javascripts/jobs/components/empty_state_spec.js b/spec/javascripts/jobs/components/empty_state_spec.js
index 872cc1e3864..73488eaab9b 100644
--- a/spec/javascripts/jobs/components/empty_state_spec.js
+++ b/spec/javascripts/jobs/components/empty_state_spec.js
@@ -67,7 +67,7 @@ describe('Empty State', () => {
content,
action: {
path: 'runner',
- title: 'Check runner',
+ button_title: 'Check runner',
method: 'post',
},
});
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
index c31fa6f9887..e02eb9723fe 100644
--- a/spec/javascripts/jobs/components/job_app_spec.js
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -37,6 +37,7 @@ describe('Job App ', () => {
available: false,
},
tags: ['docker'],
+ has_trace: true,
};
const props = {
@@ -182,4 +183,142 @@ describe('Job App ', () => {
expect(vm.$el.querySelector('.js-job-stuck')).toBeNull();
});
});
+
+ describe('environments block', () => {
+ it('renders environment block when job has environment', () => {
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, {
+ deployment_status: {
+ environment: {
+ environment_path: '/path',
+ name: 'foo',
+ },
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-environment')).not.toBeNull();
+ });
+
+ it('does not render environment block when job has environment', () => {
+ store.dispatch('receiveJobSuccess', job);
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-environment')).toBeNull();
+ });
+ });
+
+ describe('erased block', () => {
+ it('renders erased block when `erased` is true', () => {
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, {
+ erased: true,
+ erased_by: {
+ username: 'root',
+ web_url: 'gitlab.com/root',
+ },
+ erased_at: '2016-11-07T11:11:16.525Z',
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-erased')).not.toBeNull();
+ });
+
+ it('does not render erased block when `erased` is false', () => {
+ store.dispatch('receiveJobSuccess', Object.assign({}, job, { erased: false }));
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-erased')).toBeNull();
+ });
+ });
+
+ describe('empty states block', () => {
+ it('renders empty state when job does not have trace and is not running', () => {
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ illustration: {
+ image: 'path',
+ size: '340',
+ title: 'Empty State',
+ content: 'This is an empty state',
+ },
+ action: {
+ button_title: 'Retry job',
+ method: 'post',
+ path: '/path',
+ },
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull();
+ });
+
+ it('does not render empty state when job does not have trace but it is running', () => {
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'running',
+ icon: 'status_running',
+ label: 'running',
+ text: 'running',
+ details_path: 'path',
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+ });
+
+ it('does not render empty state when job has trace but it is not running', () => {
+ store.dispatch('receiveJobSuccess', Object.assign({}, job, { has_trace: true }));
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+ });
+ });
});
diff --git a/spec/javascripts/jobs/store/getters_spec.js b/spec/javascripts/jobs/store/getters_spec.js
index 63ef4135d83..160b2f4b34a 100644
--- a/spec/javascripts/jobs/store/getters_spec.js
+++ b/spec/javascripts/jobs/store/getters_spec.js
@@ -99,12 +99,14 @@ describe('Job Store Getters', () => {
expect(getters.hasEnvironment(localState)).toEqual(false);
});
});
+
describe('with an empty object for `deployment_status`', () => {
it('returns false', () => {
localState.job.deployment_status = {};
expect(getters.hasEnvironment(localState)).toEqual(false);
});
});
+
describe('when `deployment_status` is defined and not empty', () => {
it('returns true', () => {
localState.job.deployment_status = {
@@ -118,4 +120,94 @@ describe('Job Store Getters', () => {
});
});
});
+
+ describe('hasTrace', () => {
+ describe('when has_trace is true', () => {
+ it('returns true', () => {
+ localState.job.has_trace = true;
+ localState.job.status = {};
+
+ expect(getters.hasTrace(localState)).toEqual(true);
+ });
+ });
+
+ describe('when job is running', () => {
+ it('returns true', () => {
+ localState.job.has_trace = false;
+ localState.job.status = { group: 'running' };
+
+ expect(getters.hasTrace(localState)).toEqual(true);
+ });
+ });
+
+ describe('when has_trace is false and job is not running', () => {
+ it('returns false', () => {
+ localState.job.has_trace = false;
+ localState.job.status = { group: 'pending' };
+
+ expect(getters.hasTrace(localState)).toEqual(false);
+ });
+ });
+ });
+
+ describe('emptyStateIllustration', () => {
+ describe('with defined illustration', () => {
+ it('returns the state illustration object', () => {
+ localState.job.status = {
+ illustration: {
+ path: 'foo',
+ },
+ };
+
+ expect(getters.emptyStateIllustration(localState)).toEqual({ path: 'foo' });
+ });
+ });
+
+ describe('when illustration is not defined', () => {
+ it('returns an empty object', () => {
+ expect(getters.emptyStateIllustration(localState)).toEqual({});
+ });
+ });
+ });
+
+ describe('isJobStuck', () => {
+ describe('when job is pending and runners are not available', () => {
+ it('returns true', () => {
+ localState.job.status = {
+ group: 'pending',
+ };
+ localState.job.runners = {
+ available: false,
+ };
+
+ expect(getters.isJobStuck(localState)).toEqual(true);
+ });
+ });
+
+ describe('when job is not pending', () => {
+ it('returns false', () => {
+ localState.job.status = {
+ group: 'running',
+ };
+ localState.job.runners = {
+ available: false,
+ };
+
+ expect(getters.isJobStuck(localState)).toEqual(false);
+ });
+ });
+
+ describe('when runners are available', () => {
+ it('returns false', () => {
+ localState.job.status = {
+ group: 'pending',
+ };
+ localState.job.runners = {
+ available: true,
+ };
+
+ expect(getters.isJobStuck(localState)).toEqual(false);
+ });
+ });
+ });
});
diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js
index 1f030e5af28..9a0e7f34a9c 100644
--- a/spec/javascripts/notes/mock_data.js
+++ b/spec/javascripts/notes/mock_data.js
@@ -1177,10 +1177,8 @@ export const discussion1 = {
file_path: 'about.md',
},
position: {
- formatter: {
- new_line: 50,
- old_line: null,
- },
+ new_line: 50,
+ old_line: null,
},
notes: [
{
@@ -1197,10 +1195,8 @@ export const resolvedDiscussion1 = {
file_path: 'about.md',
},
position: {
- formatter: {
- new_line: 50,
- old_line: null,
- },
+ new_line: 50,
+ old_line: null,
},
notes: [
{
@@ -1217,10 +1213,8 @@ export const discussion2 = {
file_path: 'README.md',
},
position: {
- formatter: {
- new_line: null,
- old_line: 20,
- },
+ new_line: null,
+ old_line: 20,
},
notes: [
{
@@ -1237,10 +1231,8 @@ export const discussion3 = {
file_path: 'README.md',
},
position: {
- formatter: {
- new_line: 21,
- old_line: null,
- },
+ new_line: 21,
+ old_line: null,
},
notes: [
{
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
index 677eb373d22..2d94356f386 100644
--- a/spec/lib/gitlab/diff/position_spec.rb
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -5,6 +5,34 @@ describe Gitlab::Diff::Position do
let(:project) { create(:project, :repository) }
+ let(:args_for_img) do
+ {
+ old_path: "files/any.img",
+ new_path: "files/any.img",
+ base_sha: nil,
+ head_sha: nil,
+ start_sha: nil,
+ width: 100,
+ height: 100,
+ x: 1,
+ y: 100,
+ position_type: "image"
+ }
+ end
+
+ let(:args_for_text) do
+ {
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ base_sha: nil,
+ head_sha: nil,
+ start_sha: nil,
+ position_type: "text"
+ }
+ end
+
describe "position for an added text file" do
let(:commit) { project.commit("2ea1f3dec713d940208fb5ce4a38765ecb5d3f73") }
@@ -529,53 +557,49 @@ describe Gitlab::Diff::Position do
end
end
+ describe "#as_json" do
+ shared_examples "diff position json" do
+ let(:diff_position) { described_class.new(args) }
+
+ it "returns the position as JSON" do
+ expect(diff_position.as_json).to eq(args.stringify_keys)
+ end
+ end
+
+ context "for text positon" do
+ let(:args) { args_for_text }
+
+ it_behaves_like "diff position json"
+ end
+
+ context "for image positon" do
+ let(:args) { args_for_img }
+
+ it_behaves_like "diff position json"
+ end
+ end
+
describe "#to_json" do
shared_examples "diff position json" do
+ let(:diff_position) { described_class.new(args) }
+
it "returns the position as JSON" do
- expect(JSON.parse(diff_position.to_json)).to eq(hash.stringify_keys)
+ expect(JSON.parse(diff_position.to_json)).to eq(args.stringify_keys)
end
it "works when nested under another hash" do
- expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => hash.stringify_keys)
+ expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => args.stringify_keys)
end
end
context "for text positon" do
- let(:hash) do
- {
- old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 14,
- base_sha: nil,
- head_sha: nil,
- start_sha: nil,
- position_type: "text"
- }
- end
-
- let(:diff_position) { described_class.new(hash) }
+ let(:args) { args_for_text }
it_behaves_like "diff position json"
end
context "for image positon" do
- let(:hash) do
- {
- old_path: "files/any.img",
- new_path: "files/any.img",
- base_sha: nil,
- head_sha: nil,
- start_sha: nil,
- width: 100,
- height: 100,
- x: 1,
- y: 100,
- position_type: "image"
- }
- end
-
- let(:diff_position) { described_class.new(hash) }
+ let(:args) { args_for_img }
it_behaves_like "diff position json"
end
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb
index cf9e0f71910..a31f77484d8 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb
@@ -191,9 +191,7 @@ describe Gitlab::ImportExport::RelationFactory do
"author" => {
"name" => "Administrator"
},
- "events" => [
-
- ]
+ "events" => []
}
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index b19e75a956d..5ca140879c3 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1993,4 +1993,34 @@ describe Ci::Pipeline, :mailer do
end
end
end
+
+ describe '#default_branch?' do
+ let(:default_branch) { 'master'}
+
+ subject { pipeline.default_branch? }
+
+ before do
+ allow(project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ context 'when pipeline ref is the default branch of the project' do
+ let(:pipeline) do
+ build(:ci_empty_pipeline, status: :created, project: project, ref: default_branch)
+ end
+
+ it "returns true" do
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when pipeline ref is not the default branch of the project' do
+ let(:pipeline) do
+ build(:ci_empty_pipeline, status: :created, project: project, ref: 'another_branch')
+ end
+
+ it "returns false" do
+ expect(subject).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index da26d802688..f8d50e89d40 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -331,11 +331,12 @@ describe CacheMarkdownField do
end
context 'with a project' do
- let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: :project_value) }
+ let(:project) { create(:project, group: create(:group)) }
+ let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: project) }
it 'sets the project in the context' do
is_expected.to have_key(:project)
- expect(context[:project]).to eq(:project_value)
+ expect(context[:project]).to eq(project)
end
it 'invalidates the cache when project changes' do
diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb
index 34db94920f3..cb3d6c7cda2 100644
--- a/spec/models/instance_configuration_spec.rb
+++ b/spec/models/instance_configuration_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
-RSpec.describe InstanceConfiguration do
+describe InstanceConfiguration do
context 'without cache' do
describe '#settings' do
describe '#ssh_algorithms_hashes' do
- let(:md5) { '54:e0:f8:70:d6:4f:4c:b1:b3:02:44:77:cf:cd:0d:fc' }
- let(:sha256) { '9327f0d15a48c4d9f6a3aee65a1825baf9a3412001c98169c5fd022ac27762fc' }
+ let(:md5) { '5a:65:6c:4d:d4:4c:6d:e6:59:25:b8:cf:ba:34:e7:64' }
+ let(:sha256) { 'SHA256:2KJDT7xf2i68mBgJ3TVsjISntg4droLbXYLfQj0VvSY' }
it 'does not return anything if file does not exist' do
stub_pub_file(exist: false)
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index 99670af786a..3fc6c06b7fa 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -155,4 +155,40 @@ describe Label do
expect(described_class.search('feature')).to be_empty
end
end
+
+ describe '.subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns nothing' do
+ expect(described_class.subscribed_by(0)).to be_empty
+ end
+ end
+
+ describe '.optionally_subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.optionally_subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns all labels if user_id is nil' do
+ expect(described_class.optionally_subscribed_by(nil)).to match_array([label, label2])
+ end
+ end
end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 06ccf383362..98399471f9a 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -572,6 +572,20 @@ describe API::Commits do
expect(json_response['title']).to eq(message)
end
+ it 'includes the commit stats' do
+ post api(url, user), valid_mo_params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to include 'stats'
+ end
+
+ it "doesn't include the commit stats when stats is false" do
+ post api(url, user), valid_mo_params.merge(stats: false)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).not_to include 'stats'
+ end
+
it 'return a 400 bad request if there are any issues' do
post api(url, user), invalid_mo_params
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 5abc6d81958..56df8dddbc1 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -258,10 +258,10 @@ describe 'project routing' do
end
it 'to #logs_tree' do
- expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable')
- expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
- expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
- expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+ expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable')
+ expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+ expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+ expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb
index 35215e06f5f..b9995818e98 100644
--- a/spec/serializers/commit_entity_spec.rb
+++ b/spec/serializers/commit_entity_spec.rb
@@ -1,10 +1,11 @@
require 'spec_helper'
describe CommitEntity do
+ SIGNATURE_HTML = 'TEST'.freeze
+
let(:entity) do
described_class.new(commit, request: request)
end
-
let(:request) { double('request') }
let(:project) { create(:project, :repository) }
let(:commit) { project.commit }
@@ -12,7 +13,11 @@ describe CommitEntity do
subject { entity.as_json }
before do
+ render = double('render')
+ allow(render).to receive(:call).and_return(SIGNATURE_HTML)
+
allow(request).to receive(:project).and_return(project)
+ allow(request).to receive(:render).and_return(render)
end
context 'when commit author is a user' do
@@ -61,7 +66,7 @@ describe CommitEntity do
context 'when type is "full"' do
let(:entity) do
- described_class.new(commit, request: request, type: :full)
+ described_class.new(commit, request: request, type: :full, pipeline_ref: project.default_branch, pipeline_project: project)
end
it 'exposes extra properties' do
@@ -70,6 +75,25 @@ describe CommitEntity do
expect(subject.fetch(:description_html)).not_to be_nil
expect(subject.fetch(:title_html)).not_to be_nil
end
+
+ context 'when commit has signature' do
+ let(:commit) { project.commit(TestEnv::BRANCH_SHA['signed-commits']) }
+
+ it 'exposes "signature_html"' do
+ expect(request.render).to receive(:call)
+ expect(subject.fetch(:signature_html)).to be SIGNATURE_HTML
+ end
+ end
+
+ context 'when commit has pipeline' do
+ before do
+ create(:ci_pipeline, project: project, sha: commit.id)
+ end
+
+ it 'exposes "pipeline_status_path"' do
+ expect(subject.fetch(:pipeline_status_path)).not_to be_nil
+ end
+ end
end
context 'when commit_url_params is set' do
diff --git a/spec/services/notification_recipient_service_spec.rb b/spec/services/notification_recipient_service_spec.rb
index 14ba6b7bed2..cea5ea125b9 100644
--- a/spec/services/notification_recipient_service_spec.rb
+++ b/spec/services/notification_recipient_service_spec.rb
@@ -10,27 +10,50 @@ describe NotificationRecipientService do
let(:issue) { create(:issue, project: project, assignees: [assignee]) }
let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) }
- def create_watcher
- watcher = create(:user)
- create(:notification_setting, source: project, user: watcher, level: :watch)
+ shared_examples 'no N+1 queries' do
+ it 'avoids N+1 queries', :request_store do
+ create_user
- other_projects.each do |other_project|
- create(:notification_setting, source: other_project, user: watcher, level: :watch)
+ service.build_new_note_recipients(note)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ service.build_new_note_recipients(note)
+ end
+
+ create_user
+
+ expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count)
end
end
- it 'avoids N+1 queries', :request_store do
- create_watcher
+ context 'when there are multiple watchers' do
+ def create_user
+ watcher = create(:user)
+ create(:notification_setting, source: project, user: watcher, level: :watch)
+
+ other_projects.each do |other_project|
+ create(:notification_setting, source: other_project, user: watcher, level: :watch)
+ end
+ end
- service.build_new_note_recipients(note)
+ include_examples 'no N+1 queries'
+ end
- control_count = ActiveRecord::QueryRecorder.new do
- service.build_new_note_recipients(note)
+ context 'when there are multiple subscribers' do
+ def create_user
+ subscriber = create(:user)
+ issue.subscriptions.create(user: subscriber, project: project, subscribed: true)
end
- create_watcher
+ include_examples 'no N+1 queries'
- expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count)
+ context 'when the project is private' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ include_examples 'no N+1 queries'
+ end
end
end
end
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index e98df375d48..373fe7cb7dd 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -148,7 +148,7 @@ describe Projects::AutocompleteService do
let!(:label1) { create(:label, project: project) }
let!(:label2) { create(:label, project: project) }
let!(:sub_group_label) { create(:group_label, group: sub_group) }
- let!(:parent_group_label) { create(:group_label, group: group.parent) }
+ let!(:parent_group_label) { create(:group_label, group: group.parent, group_id: group.id) }
before do
create(:group_member, group: group, user: user)
@@ -156,7 +156,7 @@ describe Projects::AutocompleteService do
it 'returns labels from project and ancestor groups' do
service = described_class.new(project, user)
- results = service.labels_as_hash
+ results = service.labels_as_hash(nil)
expected_labels = [label1, label2, parent_group_label]
expect_labels_to_equal(results, expected_labels)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index f4b7cb8c90a..a18126ee339 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -324,7 +324,7 @@ describe SystemNoteService do
end
it "posts the 'merge when pipeline succeeds' system note" do
- expect(subject.note).to eq "canceled the automatic merge"
+ expect(subject.note).to eq "canceled the automatic merge"
end
end
diff --git a/spec/support/services/clusters/create_service_shared.rb b/spec/support/services/clusters/create_service_shared.rb
index 22f712f3fcf..b0bf942aa09 100644
--- a/spec/support/services/clusters/create_service_shared.rb
+++ b/spec/support/services/clusters/create_service_shared.rb
@@ -30,10 +30,6 @@ shared_context 'invalid cluster create params' do
end
shared_examples 'create cluster service success' do
- before do
- stub_feature_flags(rbac_clusters: false)
- end
-
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)