summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/application_controller_spec.rb36
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb21
-rw-r--r--spec/controllers/import/gitlab_controller_spec.rb21
-rw-r--r--spec/factories/services.rb1
-rw-r--r--spec/factories/users.rb4
-rw-r--r--spec/factories/web_hook_log.rb14
-rw-r--r--spec/features/admin/admin_hook_logs_spec.rb40
-rw-r--r--spec/features/admin/admin_hooks_spec.rb15
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb15
-rw-r--r--spec/features/atom/dashboard_spec.rb9
-rw-r--r--spec/features/atom/issues_spec.rb23
-rw-r--r--spec/features/atom/users_spec.rb9
-rw-r--r--spec/features/copy_as_gfm_spec.rb35
-rw-r--r--spec/features/dashboard/activity_spec.rb6
-rw-r--r--spec/features/dashboard/issues_spec.rb4
-rw-r--r--spec/features/dashboard/projects_spec.rb2
-rw-r--r--spec/features/dashboard_issues_spec.rb4
-rw-r--r--spec/features/groups/activity_spec.rb8
-rw-r--r--spec/features/groups/issues_spec.rb8
-rw-r--r--spec/features/groups/show_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb8
-rw-r--r--spec/features/merge_requests/discussion_spec.rb2
-rw-r--r--spec/features/merge_requests/versions_spec.rb2
-rw-r--r--spec/features/profile_spec.rb15
-rw-r--r--spec/features/projects/activity/rss_spec.rb4
-rw-r--r--spec/features/projects/commit/rss_spec.rb8
-rw-r--r--spec/features/projects/compare_spec.rb6
-rw-r--r--spec/features/projects/issues/rss_spec.rb8
-rw-r--r--spec/features/projects/main/rss_spec.rb4
-rw-r--r--spec/features/projects/settings/integration_settings_spec.rb52
-rw-r--r--spec/features/projects/sub_group_issuables_spec.rb32
-rw-r--r--spec/features/projects/tree/rss_spec.rb4
-rw-r--r--spec/features/users/rss_spec.rb4
-rw-r--r--spec/helpers/notes_helper_spec.rb8
-rw-r--r--spec/helpers/rss_helper_spec.rb8
-rw-r--r--spec/javascripts/copy_as_gfm_spec.js2
-rw-r--r--spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js2
-rw-r--r--spec/javascripts/raven/raven_config_spec.js18
-rw-r--r--spec/javascripts/sidebar/sidebar_assignees_spec.js12
-rw-r--r--spec/javascripts/sidebar/sidebar_store_spec.js5
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb52
-rw-r--r--spec/lib/gitlab/diff/position_tracer_spec.rb315
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb384
-rw-r--r--spec/lib/gitlab/regex_spec.rb392
-rw-r--r--spec/models/ci/pipeline_spec.rb2
-rw-r--r--spec/models/concerns/discussion_on_diff_spec.rb26
-rw-r--r--spec/models/diff_discussion_spec.rb7
-rw-r--r--spec/models/hooks/service_hook_spec.rb35
-rw-r--r--spec/models/hooks/system_hook_spec.rb22
-rw-r--r--spec/models/hooks/web_hook_log_spec.rb30
-rw-r--r--spec/models/hooks/web_hook_spec.rb93
-rw-r--r--spec/models/merge_request_spec.rb36
-rw-r--r--spec/models/namespace_spec.rb4
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb35
-rw-r--r--spec/models/user_spec.rb16
-rw-r--r--spec/requests/api/users_spec.rb4
-rw-r--r--spec/routing/admin_routing_spec.rb12
-rw-r--r--spec/routing/project_routing_spec.rb12
-rw-r--r--spec/routing/routing_spec.rb4
-rw-r--r--spec/services/notes/diff_position_update_service_spec.rb20
-rw-r--r--spec/services/system_note_service_spec.rb31
-rw-r--r--spec/services/web_hook_service_spec.rb137
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb16
-rw-r--r--spec/support/features/rss_shared_examples.rb24
-rw-r--r--spec/support/kubernetes_helpers.rb2
-rw-r--r--spec/tasks/tokens_spec.rb6
-rw-r--r--spec/validators/dynamic_path_validator_spec.rb14
-rw-r--r--spec/workers/remove_old_web_hook_logs_worker_spec.rb18
70 files changed, 1497 insertions, 737 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index d40aae04fc3..3f99e2ff596 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -99,6 +99,42 @@ describe ApplicationController do
end
end
+ describe '#authenticate_user_from_rss_token' do
+ describe "authenticating a user from an RSS token" do
+ controller(described_class) do
+ def index
+ render text: 'authenticated'
+ end
+ end
+
+ context "when the 'rss_token' param is populated with the RSS token" do
+ context 'when the request format is atom' do
+ it "logs the user in" do
+ get :index, rss_token: user.rss_token, format: :atom
+ expect(response).to have_http_status 200
+ expect(response.body).to eq 'authenticated'
+ end
+ end
+
+ context 'when the request format is not atom' do
+ it "doesn't log the user in" do
+ get :index, rss_token: user.rss_token
+ expect(response.status).not_to have_http_status 200
+ expect(response.body).not_to eq 'authenticated'
+ end
+ end
+ end
+
+ context "when the 'rss_token' param is populated with an invalid RSS token" do
+ it "doesn't log the user" do
+ get :index, rss_token: "token"
+ expect(response.status).not_to eq 200
+ expect(response.body).not_to eq 'authenticated'
+ end
+ end
+ end
+ end
+
describe '#route_not_found' do
it 'renders 404 if authenticated' do
allow(controller).to receive(:current_user).and_return(user)
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index 010e3180ea4..0be7bc6a045 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -133,9 +133,13 @@ describe Import::BitbucketController do
end
context "when a namespace with the Bitbucket user's username already exists" do
- let!(:existing_namespace) { create(:namespace, name: other_username, owner: user) }
+ let!(:existing_namespace) { create(:group, name: other_username) }
context "when the namespace is owned by the GitLab user" do
+ before do
+ existing_namespace.add_owner(user)
+ end
+
it "takes the existing namespace" do
expect(Gitlab::BitbucketImport::ProjectCreator).
to receive(:new).with(bitbucket_repo, bitbucket_repo.name, existing_namespace, user, access_params).
@@ -146,11 +150,6 @@ describe Import::BitbucketController do
end
context "when the namespace is not owned by the GitLab user" do
- before do
- existing_namespace.owner = create(:user)
- existing_namespace.save
- end
-
it "doesn't create a project" do
expect(Gitlab::BitbucketImport::ProjectCreator).
not_to receive(:new)
@@ -202,10 +201,14 @@ describe Import::BitbucketController do
end
context 'user has chosen an existing nested namespace and name for the project' do
- let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
- let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
let(:test_name) { 'test_name' }
+ before do
+ nested_namespace.add_owner(user)
+ end
+
it 'takes the selected namespace and name' do
expect(Gitlab::BitbucketImport::ProjectCreator).
to receive(:new).with(bitbucket_repo, test_name, nested_namespace, user, access_params).
@@ -248,7 +251,7 @@ describe Import::BitbucketController do
context 'user has chosen existent and non-existent nested namespaces and name for the project' do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
it 'takes the selected namespace and name' do
expect(Gitlab::BitbucketImport::ProjectCreator).
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
index 3270ea059fa..3afd09063d7 100644
--- a/spec/controllers/import/gitlab_controller_spec.rb
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -108,9 +108,13 @@ describe Import::GitlabController do
end
context "when a namespace with the GitLab.com user's username already exists" do
- let!(:existing_namespace) { create(:namespace, name: other_username, owner: user) }
+ let!(:existing_namespace) { create(:group, name: other_username) }
context "when the namespace is owned by the GitLab server user" do
+ before do
+ existing_namespace.add_owner(user)
+ end
+
it "takes the existing namespace" do
expect(Gitlab::GitlabImport::ProjectCreator).
to receive(:new).with(gitlab_repo, existing_namespace, user, access_params).
@@ -121,11 +125,6 @@ describe Import::GitlabController do
end
context "when the namespace is not owned by the GitLab server user" do
- before do
- existing_namespace.owner = create(:user)
- existing_namespace.save
- end
-
it "doesn't create a project" do
expect(Gitlab::GitlabImport::ProjectCreator).
not_to receive(:new)
@@ -176,8 +175,12 @@ describe Import::GitlabController do
end
context 'user has chosen an existing nested namespace for the project' do
- let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
- let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
+
+ before do
+ nested_namespace.add_owner(user)
+ end
it 'takes the selected namespace and name' do
expect(Gitlab::GitlabImport::ProjectCreator).
@@ -221,7 +224,7 @@ describe Import::GitlabController do
context 'user has chosen existent and non-existent nested namespaces and name for the project' do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
it 'takes the selected namespace and name' do
expect(Gitlab::GitlabImport::ProjectCreator).
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 28ddd0da753..3fad4d2d658 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -20,7 +20,6 @@ FactoryGirl.define do
project factory: :empty_project
active true
properties({
- namespace: 'somepath',
api_url: 'https://kubernetes.example.com',
token: 'a' * 40
})
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 33fa80772ff..e60fe713bc3 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -8,6 +8,10 @@ FactoryGirl.define do
confirmation_token { nil }
can_create_group true
+ before(:create) do |user|
+ user.ensure_rss_token
+ end
+
trait :admin do
admin true
end
diff --git a/spec/factories/web_hook_log.rb b/spec/factories/web_hook_log.rb
new file mode 100644
index 00000000000..230b3f6b26e
--- /dev/null
+++ b/spec/factories/web_hook_log.rb
@@ -0,0 +1,14 @@
+FactoryGirl.define do
+ factory :web_hook_log do
+ web_hook factory: :project_hook
+ trigger 'push_hooks'
+ url { generate(:url) }
+ request_headers {}
+ request_data {}
+ response_headers {}
+ response_body ''
+ response_status '200'
+ execution_duration 2.0
+ internal_error_message nil
+ end
+end
diff --git a/spec/features/admin/admin_hook_logs_spec.rb b/spec/features/admin/admin_hook_logs_spec.rb
new file mode 100644
index 00000000000..5b67f4de6ac
--- /dev/null
+++ b/spec/features/admin/admin_hook_logs_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+feature 'Admin::HookLogs', feature: true do
+ let(:project) { create(:project) }
+ let(:system_hook) { create(:system_hook) }
+ let(:hook_log) { create(:web_hook_log, web_hook: system_hook, internal_error_message: 'some error') }
+
+ before do
+ login_as :admin
+ end
+
+ scenario 'show list of hook logs' do
+ hook_log
+ visit edit_admin_hook_path(system_hook)
+
+ expect(page).to have_content('Recent Deliveries')
+ expect(page).to have_content(hook_log.url)
+ end
+
+ scenario 'show hook log details' do
+ hook_log
+ visit edit_admin_hook_path(system_hook)
+ click_link 'View details'
+
+ expect(page).to have_content("POST #{hook_log.url}")
+ expect(page).to have_content(hook_log.internal_error_message)
+ expect(page).to have_content('Resend Request')
+ end
+
+ scenario 'retry hook log' do
+ WebMock.stub_request(:post, system_hook.url)
+
+ hook_log
+ visit edit_admin_hook_path(system_hook)
+ click_link 'View details'
+ click_link 'Resend Request'
+
+ expect(current_path).to eq(edit_admin_hook_path(system_hook))
+ end
+end
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index c5f24d412d7..80f7ec43c06 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -58,10 +58,19 @@ describe 'Admin::Hooks', feature: true do
end
describe 'Remove existing hook' do
- it 'remove existing hook' do
- visit admin_hooks_path
+ context 'removes existing hook' do
+ it 'from hooks list page' do
+ visit admin_hooks_path
+
+ expect { click_link 'Remove' }.to change(SystemHook, :count).by(-1)
+ end
- expect { click_link 'Remove' }.to change(SystemHook, :count).by(-1)
+ it 'from hook edit page' do
+ visit admin_hooks_path
+ click_link 'Edit'
+
+ expect { click_link 'Remove' }.to change(SystemHook, :count).by(-1)
+ end
end
end
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index 9ea325ab41b..711c8a710f3 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -20,13 +20,20 @@ describe "Dashboard Issues Feed", feature: true do
expect(body).to have_selector('title', text: "#{user.name} issues")
end
+ it "renders atom feed via RSS token" do
+ visit issues_dashboard_path(:atom, rss_token: user.rss_token)
+
+ expect(response_headers['Content-Type']).to have_content('application/atom+xml')
+ expect(body).to have_selector('title', text: "#{user.name} issues")
+ end
+
it "renders atom feed with url parameters" do
- visit issues_dashboard_path(:atom, private_token: user.private_token, state: 'opened', assignee_id: user.id)
+ visit issues_dashboard_path(:atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
@@ -35,7 +42,7 @@ describe "Dashboard Issues Feed", feature: true do
let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') }
it "renders issue fields" do
- visit issues_dashboard_path(:atom, private_token: user.private_token)
+ visit issues_dashboard_path(:atom, rss_token: user.rss_token)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
@@ -58,7 +65,7 @@ describe "Dashboard Issues Feed", feature: true do
end
it "renders issue label and milestone info" do
- visit issues_dashboard_path(:atom, private_token: user.private_token)
+ visit issues_dashboard_path(:atom, rss_token: user.rss_token)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb
index 746df36bb25..1df058b023c 100644
--- a/spec/features/atom/dashboard_spec.rb
+++ b/spec/features/atom/dashboard_spec.rb
@@ -11,6 +11,13 @@ describe "Dashboard Feed", feature: true do
end
end
+ context "projects atom feed via RSS token" do
+ it "renders projects atom feed" do
+ visit dashboard_projects_path(:atom, rss_token: user.rss_token)
+ expect(body).to have_selector('feed title')
+ end
+ end
+
context 'feed content' do
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project, author: user, description: '') }
@@ -20,7 +27,7 @@ describe "Dashboard Feed", feature: true do
project.team << [user, :master]
issue_event(issue, user)
note_event(note, user)
- visit dashboard_projects_path(:atom, private_token: user.private_token)
+ visit dashboard_projects_path(:atom, rss_token: user.rss_token)
end
it "has issue opened event" do
diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb
index 4f6754ad541..a61231ea254 100644
--- a/spec/features/atom/issues_spec.rb
+++ b/spec/features/atom/issues_spec.rb
@@ -43,25 +43,40 @@ describe 'Issues Feed', feature: true do
end
end
+ context 'when authenticated via RSS token' do
+ it 'renders atom feed' do
+ visit namespace_project_issues_path(project.namespace, project, :atom,
+ rss_token: user.rss_token)
+
+ expect(response_headers['Content-Type']).
+ to have_content('application/atom+xml')
+ expect(body).to have_selector('title', text: "#{project.name} issues")
+ expect(body).to have_selector('author email', text: issue.author_public_email)
+ expect(body).to have_selector('assignees assignee email', text: issue.assignees.first.public_email)
+ expect(body).to have_selector('assignee email', text: issue.assignees.first.public_email)
+ expect(body).to have_selector('entry summary', text: issue.title)
+ end
+ end
+
it "renders atom feed with url parameters for project issues" do
visit namespace_project_issues_path(project.namespace, project,
- :atom, private_token: user.private_token, state: 'opened', assignee_id: user.id)
+ :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
it "renders atom feed with url parameters for group issues" do
- visit issues_group_path(group, :atom, private_token: user.private_token, state: 'opened', assignee_id: user.id)
+ visit issues_group_path(group, :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s])
end
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
index 7a2987e815d..fae5aaa52bd 100644
--- a/spec/features/atom/users_spec.rb
+++ b/spec/features/atom/users_spec.rb
@@ -11,6 +11,13 @@ describe "User Feed", feature: true do
end
end
+ context 'user atom feed via RSS token' do
+ it "renders user atom feed" do
+ visit user_path(user, :atom, rss_token: user.rss_token)
+ expect(body).to have_selector('feed title')
+ end
+ end
+
context 'feed content' do
let(:project) { create(:project) }
let(:issue) do
@@ -40,7 +47,7 @@ describe "User Feed", feature: true do
issue_event(issue, user)
note_event(note, user)
merge_request_event(merge_request, user)
- visit user_path(user, :atom, private_token: user.private_token)
+ visit user_path(user, :atom, rss_token: user.rss_token)
end
it 'has issue opened event' do
diff --git a/spec/features/copy_as_gfm_spec.rb b/spec/features/copy_as_gfm_spec.rb
index 43ea36c3cdd..740f60c05cc 100644
--- a/spec/features/copy_as_gfm_spec.rb
+++ b/spec/features/copy_as_gfm_spec.rb
@@ -51,7 +51,6 @@ describe 'Copy as GFM', feature: true, js: true do
To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/).
-
- Manage Git repositories with fine grained access controls that keep your code secure
- Perform code reviews and enhance collaboration with merge requests
@@ -66,6 +65,38 @@ describe 'Copy as GFM', feature: true, js: true do
GFM
)
+ aggregate_failures('an accidentally selected empty element') do
+ gfm = '# Heading1'
+
+ html = <<-HTML.strip_heredoc
+ <h1>Heading1</h1>
+
+ <h2></h2>
+ HTML
+
+ output_gfm = html_to_gfm(html)
+ expect(output_gfm.strip).to eq(gfm.strip)
+ end
+
+ aggregate_failures('an accidentally selected other element') do
+ gfm = 'Test comment with **Markdown!**'
+
+ html = <<-HTML.strip_heredoc
+ <li class="note">
+ <div class="md">
+ <p>
+ Test comment with <strong>Markdown!</strong>
+ </p>
+ </div>
+ </li>
+
+ <li class="note"></li>
+ HTML
+
+ output_gfm = html_to_gfm(html)
+ expect(output_gfm.strip).to eq(gfm.strip)
+ end
+
verify(
'InlineDiffFilter',
@@ -352,7 +383,6 @@ describe 'Copy as GFM', feature: true, js: true do
<<-GFM.strip_heredoc,
- Nested
-
- Lists
GFM
@@ -375,7 +405,6 @@ describe 'Copy as GFM', feature: true, js: true do
<<-GFM.strip_heredoc,
1. Nested
-
1. Numbered lists
GFM
diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb
index c977f266296..0764044260e 100644
--- a/spec/features/dashboard/activity_spec.rb
+++ b/spec/features/dashboard/activity_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'Dashboard Activity', feature: true do
login_as(create :user)
visit activity_dashboard_path
end
-
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index 7a132dba1e9..2346a9ec2ed 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -62,6 +62,6 @@ RSpec.describe 'Dashboard Issues', feature: true do
expect(page).to have_content(other_issue.title)
end
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index f1789fc9d43..01351548a99 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -31,5 +31,5 @@ RSpec.describe 'Dashboard Projects', feature: true do
end
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb
index ad60fb2c74f..1c53f6dff06 100644
--- a/spec/features/dashboard_issues_spec.rb
+++ b/spec/features/dashboard_issues_spec.rb
@@ -53,10 +53,10 @@ describe "Dashboard Issues filtering", feature: true, js: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => [''])
expect(params).to include('assignee_id' => [user.id.to_s])
- expect(auto_discovery_params).to include('private_token' => [user.private_token])
+ expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => [''])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end
diff --git a/spec/features/groups/activity_spec.rb b/spec/features/groups/activity_spec.rb
index 3b481cba424..81f9c103e95 100644
--- a/spec/features/groups/activity_spec.rb
+++ b/spec/features/groups/activity_spec.rb
@@ -11,8 +11,8 @@ feature 'Group activity page', feature: true do
visit path
end
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -20,7 +20,7 @@ feature 'Group activity page', feature: true do
visit path
end
- it_behaves_like "it has an RSS button without a private token"
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index aa2e9632d6c..d6b88542ef7 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -12,15 +12,15 @@ feature 'Group issues page', feature: true do
context 'when signed in' do
let(:user) { user_in_group }
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
let(:user) { nil }
- it_behaves_like "it has an RSS button without a private token"
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index fb39693e8ca..d3c49c37374 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -11,7 +11,7 @@ feature 'Group show page', feature: true do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -19,6 +19,6 @@ feature 'Group show page', feature: true do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 03ff1cffb3f..7958ad7e24f 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -810,10 +810,10 @@ describe 'Filter issues', js: true, feature: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => [milestone.title])
expect(params).to include('assignee_id' => [user.id.to_s])
- expect(auto_discovery_params).to include('private_token' => [user.private_token])
+ expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => [milestone.title])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end
@@ -825,10 +825,10 @@ describe 'Filter issues', js: true, feature: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
- expect(params).to include('private_token' => [user.private_token])
+ expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => [milestone.title])
expect(params).to include('assignee_id' => [user.id.to_s])
- expect(auto_discovery_params).to include('private_token' => [user.private_token])
+ expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => [milestone.title])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end
diff --git a/spec/features/merge_requests/discussion_spec.rb b/spec/features/merge_requests/discussion_spec.rb
index f59d0faa274..1a09cc54c2e 100644
--- a/spec/features/merge_requests/discussion_spec.rb
+++ b/spec/features/merge_requests/discussion_spec.rb
@@ -43,7 +43,7 @@ feature 'Merge Request Discussions', feature: true do
it 'shows a link to the outdated diff' do
within(".discussion[data-discussion-id='#{outdated_discussion.id}']") do
path = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, diff_id: old_merge_request_diff.id, anchor: outdated_discussion.line_code)
- expect(page).to have_link('an outdated diff', href: path)
+ expect(page).to have_link('an old version of the diff', href: path)
end
end
end
diff --git a/spec/features/merge_requests/versions_spec.rb b/spec/features/merge_requests/versions_spec.rb
index aef8ef20938..aad522ee26e 100644
--- a/spec/features/merge_requests/versions_spec.rb
+++ b/spec/features/merge_requests/versions_spec.rb
@@ -124,6 +124,8 @@ feature 'Merge Request versions', js: true, feature: true do
diff_refs: merge_request_diff3.compare_with(merge_request_diff1.head_commit_sha).diff_refs
)
outdated_diff_note = create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position)
+ outdated_diff_note.position = outdated_diff_note.original_position
+ outdated_diff_note.save!
visit current_url
wait_for_requests
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index e63feb14b7e..7df628fd7a0 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -47,6 +47,21 @@ describe 'Profile account page', feature: true do
end
end
+ describe 'when I reset RSS token' do
+ before do
+ visit profile_account_path
+ end
+
+ it 'resets RSS token' do
+ previous_token = find("#rss-token").value
+
+ click_link('Reset RSS token')
+
+ expect(page).to have_content 'RSS token was successfully reset'
+ expect(find('#rss-token').value).not_to eq(previous_token)
+ end
+ end
+
describe 'when I reset incoming email token' do
before do
allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true)
diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb
index b47c6d431eb..3c1de5c09b2 100644
--- a/spec/features/projects/activity/rss_spec.rb
+++ b/spec/features/projects/activity/rss_spec.rb
@@ -16,7 +16,7 @@ feature 'Project Activity RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
end
context 'when signed out' do
@@ -24,6 +24,6 @@ feature 'Project Activity RSS' do
visit path
end
- it_behaves_like "it has an RSS button without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
end
end
diff --git a/spec/features/projects/commit/rss_spec.rb b/spec/features/projects/commit/rss_spec.rb
index 6e0e1916f87..03b6d560c96 100644
--- a/spec/features/projects/commit/rss_spec.rb
+++ b/spec/features/projects/commit/rss_spec.rb
@@ -12,8 +12,8 @@ feature 'Project Commits RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -21,7 +21,7 @@ feature 'Project Commits RSS' do
visit path
end
- it_behaves_like "it has an RSS button without a private token"
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index 294a63a5c6d..4162f2579d1 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -52,8 +52,12 @@ describe "Compare", js: true do
def select_using_dropdown(dropdown_type, selection)
dropdown = find(".js-compare-#{dropdown_type}-dropdown")
dropdown.find(".compare-dropdown-toggle").click
+ # find input before using to wait for the inputs visiblity
+ dropdown.find('.dropdown-menu')
dropdown.fill_in("Filter by Git revision", with: selection)
wait_for_requests
- dropdown.find_all("a[data-ref=\"#{selection}\"]", visible: true).last.click
+ # find before all to wait for the items visiblity
+ dropdown.find("a[data-ref=\"#{selection}\"]", match: :first)
+ dropdown.all("a[data-ref=\"#{selection}\"]").last.click
end
end
diff --git a/spec/features/projects/issues/rss_spec.rb b/spec/features/projects/issues/rss_spec.rb
index 71429f00095..f6852192aef 100644
--- a/spec/features/projects/issues/rss_spec.rb
+++ b/spec/features/projects/issues/rss_spec.rb
@@ -16,8 +16,8 @@ feature 'Project Issues RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's private token"
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -25,7 +25,7 @@ feature 'Project Issues RSS' do
visit path
end
- it_behaves_like "it has an RSS button without a private token"
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/projects/main/rss_spec.rb b/spec/features/projects/main/rss_spec.rb
index b1a3af612a1..53966229a2a 100644
--- a/spec/features/projects/main/rss_spec.rb
+++ b/spec/features/projects/main/rss_spec.rb
@@ -12,7 +12,7 @@ feature 'Project RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -20,6 +20,6 @@ feature 'Project RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb
index d3232f0cc16..fbaea14a2be 100644
--- a/spec/features/projects/settings/integration_settings_spec.rb
+++ b/spec/features/projects/settings/integration_settings_spec.rb
@@ -85,11 +85,55 @@ feature 'Integration settings', feature: true do
expect(current_path).to eq(integrations_path)
end
- scenario 'remove existing webhook' do
- hook
- visit integrations_path
+ context 'remove existing webhook' do
+ scenario 'from webhooks list page' do
+ hook
+ visit integrations_path
+
+ expect { click_link 'Remove' }.to change(ProjectHook, :count).by(-1)
+ end
+
+ scenario 'from webhook edit page' do
+ hook
+ visit integrations_path
+ click_link 'Edit'
+
+ expect { click_link 'Remove' }.to change(ProjectHook, :count).by(-1)
+ end
+ end
+ end
+
+ context 'Webhook logs' do
+ let(:hook) { create(:project_hook, project: project) }
+ let(:hook_log) { create(:web_hook_log, web_hook: hook, internal_error_message: 'some error') }
+
+ scenario 'show list of hook logs' do
+ hook_log
+ visit edit_namespace_project_hook_path(project.namespace, project, hook)
+
+ expect(page).to have_content('Recent Deliveries')
+ expect(page).to have_content(hook_log.url)
+ end
+
+ scenario 'show hook log details' do
+ hook_log
+ visit edit_namespace_project_hook_path(project.namespace, project, hook)
+ click_link 'View details'
+
+ expect(page).to have_content("POST #{hook_log.url}")
+ expect(page).to have_content(hook_log.internal_error_message)
+ expect(page).to have_content('Resend Request')
+ end
+
+ scenario 'retry hook log' do
+ WebMock.stub_request(:post, hook.url)
+
+ hook_log
+ visit edit_namespace_project_hook_path(project.namespace, project, hook)
+ click_link 'View details'
+ click_link 'Resend Request'
- expect { click_link 'Remove' }.to change(ProjectHook, :count).by(-1)
+ expect(current_path).to eq(edit_namespace_project_hook_path(project.namespace, project, hook))
end
end
end
diff --git a/spec/features/projects/sub_group_issuables_spec.rb b/spec/features/projects/sub_group_issuables_spec.rb
new file mode 100644
index 00000000000..cf21b208f65
--- /dev/null
+++ b/spec/features/projects/sub_group_issuables_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'Subgroup Issuables', :feature, :js do
+ let!(:group) { create(:group, name: 'group') }
+ let!(:subgroup) { create(:group, parent: group, name: 'subgroup') }
+ let!(:project) { create(:empty_project, namespace: subgroup, name: 'project') }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ login_as user
+ end
+
+ it 'shows the full subgroup title when issues index page is empty' do
+ visit namespace_project_issues_path(project.namespace.to_param, project.to_param)
+
+ expect_to_have_full_subgroup_title
+ end
+
+ it 'shows the full subgroup title when merge requests index page is empty' do
+ visit namespace_project_merge_requests_path(project.namespace.to_param, project.to_param)
+
+ expect_to_have_full_subgroup_title
+ end
+
+ def expect_to_have_full_subgroup_title
+ title = find('.title-container')
+
+ expect(title).not_to have_selector '.initializing'
+ expect(title).to have_content 'group / subgroup / project'
+ end
+end
diff --git a/spec/features/projects/tree/rss_spec.rb b/spec/features/projects/tree/rss_spec.rb
index 9ac51997d65..9bf59c4139c 100644
--- a/spec/features/projects/tree/rss_spec.rb
+++ b/spec/features/projects/tree/rss_spec.rb
@@ -12,7 +12,7 @@ feature 'Project Tree RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed with current_user's private token"
+ it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end
context 'when signed out' do
@@ -20,6 +20,6 @@ feature 'Project Tree RSS' do
visit path
end
- it_behaves_like "an autodiscoverable RSS feed without a private token"
+ it_behaves_like "an autodiscoverable RSS feed without an RSS token"
end
end
diff --git a/spec/features/users/rss_spec.rb b/spec/features/users/rss_spec.rb
index 14564abb16d..dbd5f66b55e 100644
--- a/spec/features/users/rss_spec.rb
+++ b/spec/features/users/rss_spec.rb
@@ -9,7 +9,7 @@ feature 'User RSS' do
visit path
end
- it_behaves_like "it has an RSS button with current_user's private token"
+ it_behaves_like "it has an RSS button with current_user's RSS token"
end
context 'when signed out' do
@@ -17,6 +17,6 @@ feature 'User RSS' do
visit path
end
- it_behaves_like "it has an RSS button without a private token"
+ it_behaves_like "it has an RSS button without an RSS token"
end
end
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index 099146678ae..355a4845afb 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -92,7 +92,13 @@ describe NotesHelper do
)
end
- let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, position: position).to_discussion }
+ let(:diff_note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, position: position) }
+ let(:discussion) { diff_note.to_discussion }
+
+ before do
+ diff_note.position = diff_note.original_position
+ diff_note.save!
+ end
it 'returns the diff version comparison path with the line code' do
expect(helper.discussion_path(discussion)).to eq(diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, diff_id: merge_request_diff3, start_sha: merge_request_diff1.head_commit_sha, anchor: discussion.line_code))
diff --git a/spec/helpers/rss_helper_spec.rb b/spec/helpers/rss_helper_spec.rb
index f3f174f3d14..269e1057e8d 100644
--- a/spec/helpers/rss_helper_spec.rb
+++ b/spec/helpers/rss_helper_spec.rb
@@ -3,17 +3,17 @@ require 'spec_helper'
describe RssHelper do
describe '#rss_url_options' do
context 'when signed in' do
- it "includes the current_user's private_token" do
+ it "includes the current_user's rss_token" do
current_user = create(:user)
allow(helper).to receive(:current_user).and_return(current_user)
- expect(helper.rss_url_options).to include private_token: current_user.private_token
+ expect(helper.rss_url_options).to include rss_token: current_user.rss_token
end
end
context 'when signed out' do
- it "does not have a private_token" do
+ it "does not have an rss_token" do
allow(helper).to receive(:current_user).and_return(nil)
- expect(helper.rss_url_options[:private_token]).to be_nil
+ expect(helper.rss_url_options[:rss_token]).to be_nil
end
end
end
diff --git a/spec/javascripts/copy_as_gfm_spec.js b/spec/javascripts/copy_as_gfm_spec.js
index 1a850bb56ab..ded450749d3 100644
--- a/spec/javascripts/copy_as_gfm_spec.js
+++ b/spec/javascripts/copy_as_gfm_spec.js
@@ -1,4 +1,4 @@
-require('~/copy_as_gfm');
+import '~/copy_as_gfm';
(() => {
describe('gl.CopyAsGFM', () => {
diff --git a/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js b/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
index 0ebb867b851..79447787fc9 100644
--- a/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
+++ b/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import eventHub from '~/filtered_search/event_hub';
import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content';
-require('~/filtered_search/filtered_search_token_keys');
+import '~/filtered_search/filtered_search_token_keys';
const createComponent = (propsData) => {
const Component = Vue.extend(RecentSearchesDropdownContent);
diff --git a/spec/javascripts/raven/raven_config_spec.js b/spec/javascripts/raven/raven_config_spec.js
index b31a7c28ebe..c82658b9262 100644
--- a/spec/javascripts/raven/raven_config_spec.js
+++ b/spec/javascripts/raven/raven_config_spec.js
@@ -140,24 +140,6 @@ describe('RavenConfig', () => {
});
});
- describe('bindRavenErrors', () => {
- let $document;
- let $;
-
- beforeEach(() => {
- $document = jasmine.createSpyObj('$document', ['on']);
- $ = jasmine.createSpy('$').and.returnValue($document);
-
- window.$ = $;
-
- RavenConfig.bindRavenErrors();
- });
-
- it('should call .on', function () {
- expect($document.on).toHaveBeenCalledWith('ajaxError.raven', RavenConfig.handleRavenErrors);
- });
- });
-
describe('handleRavenErrors', () => {
let event;
let req;
diff --git a/spec/javascripts/sidebar/sidebar_assignees_spec.js b/spec/javascripts/sidebar/sidebar_assignees_spec.js
index 865951b2ad7..929ba75e67d 100644
--- a/spec/javascripts/sidebar/sidebar_assignees_spec.js
+++ b/spec/javascripts/sidebar/sidebar_assignees_spec.js
@@ -43,4 +43,16 @@ describe('sidebar assignees', () => {
expect(SidebarMediator.prototype.assignYourself).toHaveBeenCalled();
expect(this.mediator.store.assignees.length).toEqual(1);
});
+
+ it('hides assignees until fetched', (done) => {
+ component = new SidebarAssigneeComponent().$mount(this.sidebarAssigneesEl);
+ const currentAssignee = this.sidebarAssigneesEl.querySelector('.value');
+ expect(currentAssignee).toBe(null);
+
+ component.store.isFetching.assignees = false;
+ Vue.nextTick(() => {
+ expect(component.$el.querySelector('.value')).toBeVisible();
+ done();
+ });
+ });
});
diff --git a/spec/javascripts/sidebar/sidebar_store_spec.js b/spec/javascripts/sidebar/sidebar_store_spec.js
index 29facf483b5..b3fa156eb64 100644
--- a/spec/javascripts/sidebar/sidebar_store_spec.js
+++ b/spec/javascripts/sidebar/sidebar_store_spec.js
@@ -35,6 +35,10 @@ describe('Sidebar store', () => {
SidebarStore.singleton = null;
});
+ it('has default isFetching values', () => {
+ expect(this.store.isFetching.assignees).toBe(true);
+ });
+
it('adds a new assignee', () => {
this.store.addAssignee(assignee);
expect(this.store.assignees.length).toEqual(1);
@@ -67,6 +71,7 @@ describe('Sidebar store', () => {
};
this.store.setAssigneeData(users);
+ expect(this.store.isFetching.assignees).toBe(false);
expect(this.store.assignees.length).toEqual(3);
});
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
index c56fded7516..ce2b5d620fd 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
@@ -18,8 +18,8 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
let(:subject) { described_class.new(['parent/the-Path'], migration) }
it 'includes the namespace' do
- parent = create(:namespace, path: 'parent')
- child = create(:namespace, path: 'the-path', parent: parent)
+ parent = create(:group, path: 'parent')
+ child = create(:group, path: 'the-path', parent: parent)
found_ids = subject.namespaces_for_paths(type: :child).
map(&:id)
@@ -30,13 +30,13 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
context 'for child namespaces' do
it 'only returns child namespaces with the correct path' do
- _root_namespace = create(:namespace, path: 'THE-path')
- _other_path = create(:namespace,
+ _root_namespace = create(:group, path: 'THE-path')
+ _other_path = create(:group,
path: 'other',
- parent: create(:namespace))
- namespace = create(:namespace,
+ parent: create(:group))
+ namespace = create(:group,
path: 'the-path',
- parent: create(:namespace))
+ parent: create(:group))
found_ids = subject.namespaces_for_paths(type: :child).
map(&:id)
@@ -45,13 +45,13 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
end
it 'has no namespaces that look the same' do
- _root_namespace = create(:namespace, path: 'THE-path')
- _similar_path = create(:namespace,
+ _root_namespace = create(:group, path: 'THE-path')
+ _similar_path = create(:group,
path: 'not-really-the-path',
- parent: create(:namespace))
- namespace = create(:namespace,
+ parent: create(:group))
+ namespace = create(:group,
path: 'the-path',
- parent: create(:namespace))
+ parent: create(:group))
found_ids = subject.namespaces_for_paths(type: :child).
map(&:id)
@@ -62,11 +62,11 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
context 'for top levelnamespaces' do
it 'only returns child namespaces with the correct path' do
- root_namespace = create(:namespace, path: 'the-path')
- _other_path = create(:namespace, path: 'other')
- _child_namespace = create(:namespace,
+ root_namespace = create(:group, path: 'the-path')
+ _other_path = create(:group, path: 'other')
+ _child_namespace = create(:group,
path: 'the-path',
- parent: create(:namespace))
+ parent: create(:group))
found_ids = subject.namespaces_for_paths(type: :top_level).
map(&:id)
@@ -75,11 +75,11 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
end
it 'has no namespaces that just look the same' do
- root_namespace = create(:namespace, path: 'the-path')
- _similar_path = create(:namespace, path: 'not-really-the-path')
- _child_namespace = create(:namespace,
+ root_namespace = create(:group, path: 'the-path')
+ _similar_path = create(:group, path: 'not-really-the-path')
+ _child_namespace = create(:group,
path: 'the-path',
- parent: create(:namespace))
+ parent: create(:group))
found_ids = subject.namespaces_for_paths(type: :top_level).
map(&:id)
@@ -124,10 +124,10 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
describe "#child_ids_for_parent" do
it "collects child ids for all levels" do
- parent = create(:namespace)
- first_child = create(:namespace, parent: parent)
- second_child = create(:namespace, parent: parent)
- third_child = create(:namespace, parent: second_child)
+ parent = create(:group)
+ first_child = create(:group, parent: parent)
+ second_child = create(:group, parent: parent)
+ third_child = create(:group, parent: second_child)
all_ids = [parent.id, first_child.id, second_child.id, third_child.id]
collected_ids = subject.child_ids_for_parent(parent, ids: [parent.id])
@@ -205,9 +205,9 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces do
end
describe '#rename_namespaces' do
- let!(:top_level_namespace) { create(:namespace, path: 'the-path') }
+ let!(:top_level_namespace) { create(:group, path: 'the-path') }
let!(:child_namespace) do
- create(:namespace, path: 'the-path', parent: create(:namespace))
+ create(:group, path: 'the-path', parent: create(:group))
end
it 'renames top level namespaces the namespace' do
diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb
index 4d202a76e1b..93d30b90937 100644
--- a/spec/lib/gitlab/diff/position_tracer_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer_spec.rb
@@ -61,9 +61,10 @@ describe Gitlab::Diff::PositionTracer, lib: true do
let(:old_diff_refs) { raise NotImplementedError }
let(:new_diff_refs) { raise NotImplementedError }
+ let(:change_diff_refs) { raise NotImplementedError }
let(:old_position) { raise NotImplementedError }
- let(:position_tracer) { described_class.new(repository: project.repository, old_diff_refs: old_diff_refs, new_diff_refs: new_diff_refs) }
+ let(:position_tracer) { described_class.new(project: project, old_diff_refs: old_diff_refs, new_diff_refs: new_diff_refs) }
subject { position_tracer.trace(old_position) }
def diff_refs(base_commit, head_commit)
@@ -77,16 +78,40 @@ describe Gitlab::Diff::PositionTracer, lib: true do
Gitlab::Diff::Position.new(attrs)
end
- def expect_new_position(attrs, new_position = subject)
- if attrs.nil?
- expect(new_position).to be_nil
- else
- expect(new_position).not_to be_nil
+ def expect_new_position(attrs, result = subject)
+ aggregate_failures("expect new position #{attrs.inspect}") do
+ if attrs.nil?
+ expect(result[:outdated]).to be_truthy
+ else
+ expect(result[:outdated]).to be_falsey
- expect(new_position.diff_refs).to eq(new_diff_refs)
+ new_position = result[:position]
+ expect(new_position).not_to be_nil
- attrs.each do |attr, value|
- expect(new_position.send(attr)).to eq(value)
+ expect(new_position.diff_refs).to eq(new_diff_refs)
+
+ attrs.each do |attr, value|
+ expect(new_position.send(attr)).to eq(value)
+ end
+ end
+ end
+ end
+
+ def expect_change_position(attrs, result = subject)
+ aggregate_failures("expect change position #{attrs.inspect}") do
+ expect(result[:outdated]).to be_truthy
+
+ change_position = result[:position]
+ if attrs.nil? || attrs.empty?
+ expect(change_position).to be_nil
+ else
+ expect(change_position).not_to be_nil
+
+ expect(change_position.diff_refs).to eq(change_diff_refs)
+
+ attrs.each do |attr, value|
+ expect(change_position.send(attr)).to eq(value)
+ end
end
end
end
@@ -395,6 +420,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -407,14 +433,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 + BB
# 3 + C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:change_diff_refs) { diff_refs(update_line_commit, delete_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 3) }
# old diff:
@@ -426,8 +458,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 + A
# 2 + BB
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 3,
+ new_line: nil
+ )
end
end
end
@@ -512,6 +549,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -525,14 +563,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 + BB
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 3) }
# old diff:
@@ -545,8 +589,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 2 A
# 3 - C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 3,
+ new_line: nil
+ )
end
end
end
@@ -558,6 +607,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when the file's content was unchanged between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, rename_file_commit) }
+ let(:change_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -569,8 +619,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 1 BB
# 2 2 A
- it "returns nil since the line doesn't exist in the new diffs anymore" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: nil,
+ new_line: 2
+ )
end
end
@@ -628,6 +683,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
+ let(:change_diff_refs) { diff_refs(delete_line_commit, update_line_again_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -640,28 +696,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 - A
# 2 + AA
- it "returns nil" do
- expect(subject).to be_nil
- end
- end
-
- context "when that line was deleted between the old and the new diff" do
- let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
- let(:new_diff_refs) { diff_refs(delete_line_commit, delete_line_again_commit) }
- let(:old_position) { position(new_path: file_name, new_line: 1) }
-
- # old diff:
- # 1 + BB
- # 2 + A
- #
- # new diff:
- # file_name -> new_file_name
- # 1 - BB
- # 2 - A
- # 1 + AA
-
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: new_file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
end
@@ -673,6 +714,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when the file's content was unchanged between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:change_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -683,8 +725,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 - BB
# 2 - A
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
@@ -692,6 +739,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was unchanged between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -703,14 +751,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 - BB
# 2 - A
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was moved between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
let(:new_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
+ let(:change_diff_refs) { diff_refs(update_line_commit, delete_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -723,14 +777,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 - A
# 3 - C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was changed between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(update_line_commit, delete_file_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, delete_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -743,14 +803,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 - BB
# 3 - C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_file_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, delete_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 3) }
# old diff:
@@ -762,8 +828,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 - BB
# 2 - A
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 3,
+ new_line: nil
+ )
end
end
end
@@ -775,6 +846,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when the file's content was unchanged between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, create_second_file_commit) }
+ let(:change_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -787,8 +859,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 2 B
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: nil,
+ new_line: 2
+ )
end
end
@@ -796,6 +873,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was unchanged between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
+ let(:change_diff_refs) { diff_refs(initial_commit, update_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 1) }
# old diff:
@@ -808,14 +886,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 2 BB
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: nil,
+ new_line: 1
+ )
end
end
context "when that line was moved between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, update_line_commit) }
let(:new_diff_refs) { diff_refs(move_line_commit, move_second_file_line_commit) }
+ let(:change_diff_refs) { diff_refs(initial_commit, move_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -828,14 +912,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 2 A
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: nil,
+ new_line: 1
+ )
end
end
context "when that line was changed between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, create_file_commit) }
let(:new_diff_refs) { diff_refs(update_line_commit, update_second_file_line_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, update_second_file_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 2) }
# old diff:
@@ -848,14 +938,20 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 2 BB
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
context "when that line was deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(initial_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(delete_line_commit, delete_second_file_line_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, delete_second_file_line_commit) }
let(:old_position) { position(new_path: file_name, new_line: 3) }
# old diff:
@@ -867,8 +963,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 1 BB
# 2 2 A
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 3,
+ new_line: nil
+ )
end
end
end
@@ -957,6 +1058,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed or deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(initial_commit, create_file_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, create_file_commit) }
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
# old diff:
@@ -970,8 +1072,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 + B
# 3 + C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 1,
+ new_line: nil
+ )
end
end
end
@@ -980,6 +1087,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when the position pointed at a deleted line in the old diff" do
let(:old_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
let(:new_diff_refs) { diff_refs(initial_commit, update_line_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, initial_commit) }
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 2) }
# old diff:
@@ -993,8 +1101,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 + BB
# 3 + C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 2,
+ new_line: nil
+ )
end
end
@@ -1076,6 +1189,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed or deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(initial_commit, delete_line_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, delete_line_commit) }
let(:old_position) { position(old_path: file_name, new_path: file_name, old_line: 3, new_line: 3) }
# old diff:
@@ -1088,8 +1202,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 1 + A
# 2 + B
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 3,
+ new_line: nil
+ )
end
end
end
@@ -1182,6 +1301,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
context "when that line was changed or deleted between the old and the new diff" do
let(:old_diff_refs) { diff_refs(create_file_commit, move_line_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, update_line_commit) }
+ let(:change_diff_refs) { diff_refs(move_line_commit, update_line_commit) }
let(:old_position) { position(old_path: file_name, new_path: file_name, new_line: 1) }
# old diff:
@@ -1196,8 +1316,13 @@ describe Gitlab::Diff::PositionTracer, lib: true do
# 2 + BB
# 3 3 C
- it "returns nil" do
- expect(subject).to be_nil
+ it "returns the position of the change" do
+ expect_change_position(
+ old_path: file_name,
+ new_path: file_name,
+ old_line: 1,
+ new_line: nil
+ )
end
end
end
@@ -1239,7 +1364,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
describe "typical use scenarios" do
let(:second_branch_name) { "#{branch_name}-2" }
- def expect_positions(old_attrs, new_attrs)
+ def expect_new_positions(old_attrs, new_attrs)
old_positions = old_attrs.map do |old_attrs|
position(old_attrs)
end
@@ -1248,8 +1373,14 @@ describe Gitlab::Diff::PositionTracer, lib: true do
position_tracer.trace(old_position)
end
- new_positions.zip(new_attrs).each do |new_position, new_attrs|
- expect_new_position(new_attrs, new_position)
+ aggregate_failures do
+ new_positions.zip(new_attrs).each do |new_position, new_attrs|
+ if new_attrs&.delete(:change)
+ expect_change_position(new_attrs, new_position)
+ else
+ expect_new_position(new_attrs, new_position)
+ end
+ end
end
end
@@ -1330,6 +1461,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
describe "simple push of new commit" do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
+ let(:change_diff_refs) { diff_refs(update_file_commit, update_file_again_commit) }
# old diff:
# 1 1 A
@@ -1368,14 +1500,14 @@ describe Gitlab::Diff::PositionTracer, lib: true do
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
{ old_path: file_name, old_line: 2 },
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
- { old_path: file_name, old_line: 4, new_line: 4 },
- nil,
+ { new_path: file_name, new_line: 4, change: true },
+ { new_path: file_name, old_line: 3, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
- { old_path: file_name, old_line: 6 },
+ { new_path: file_name, old_line: 5, change: true },
{ new_path: file_name, new_line: 7 }
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
@@ -1402,6 +1534,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, second_create_file_commit) }
+ let(:change_diff_refs) { diff_refs(update_file_commit, second_create_file_commit) }
# old diff:
# 1 1 A
@@ -1440,20 +1573,21 @@ describe Gitlab::Diff::PositionTracer, lib: true do
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
{ old_path: file_name, old_line: 2 },
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 3 },
- { old_path: file_name, old_line: 4, new_line: 4 },
- nil,
+ { new_path: file_name, new_line: 4, change: true },
+ { old_path: file_name, old_line: 3, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 },
- { old_path: file_name, old_line: 6 },
+ { old_path: file_name, old_line: 5, change: true },
{ new_path: file_name, new_line: 7 }
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
describe "force push to delete last commit" do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
+ let(:change_diff_refs) { diff_refs(update_file_again_commit, update_file_commit) }
# old diff:
# 1 1 A
@@ -1492,16 +1626,16 @@ describe Gitlab::Diff::PositionTracer, lib: true do
new_position_attrs = [
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
{ old_path: file_name, old_line: 2 },
- nil,
+ { old_path: file_name, old_line: 2, change: true },
{ old_path: file_name, new_path: file_name, old_line: 3, new_line: 2 },
- { old_path: file_name, old_line: 4 },
+ { old_path: file_name, old_line: 4, change: true },
{ old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 },
- { old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 },
- nil,
+ { new_path: file_name, new_line: 5, change: true },
+ { old_path: file_name, old_line: 6, change: true },
{ new_path: file_name, new_line: 6 }
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
@@ -1567,6 +1701,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, overwrite_update_file_again_commit) }
+ let(:change_diff_refs) { diff_refs(update_file_again_commit, overwrite_update_file_again_commit) }
# old diff:
# 1 1 A
@@ -1618,7 +1753,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
{ new_path: file_name, new_line: 10 }, # + G
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
@@ -1643,6 +1778,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
let(:new_diff_refs) { diff_refs(create_file_commit, merge_commit) }
+ let(:change_diff_refs) { diff_refs(update_file_again_commit, merge_commit) }
# old diff:
# 1 1 A
@@ -1694,13 +1830,14 @@ describe Gitlab::Diff::PositionTracer, lib: true do
{ new_path: file_name, new_line: 10 }, # + G
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
describe "changing target branch" do
let(:old_diff_refs) { diff_refs(create_file_commit, update_file_again_commit) }
let(:new_diff_refs) { diff_refs(update_file_commit, update_file_again_commit) }
+ let(:change_diff_refs) { diff_refs(create_file_commit, update_file_commit) }
# old diff:
# 1 1 A
@@ -1739,7 +1876,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
new_position_attrs = [
{ old_path: file_name, new_path: file_name, old_line: 1, new_line: 1 },
- nil,
+ { old_path: file_name, old_line: 2, change: true },
{ new_path: file_name, new_line: 2 },
{ old_path: file_name, new_path: file_name, old_line: 2, new_line: 3 },
{ new_path: file_name, new_line: 4 },
@@ -1749,7 +1886,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do
{ new_path: file_name, new_line: 7 }
]
- expect_positions(old_position_attrs, new_position_attrs)
+ expect_new_positions(old_position_attrs, new_position_attrs)
end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 34f617e23a5..2e9646286df 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -131,6 +131,7 @@ services:
- service_hook
hooks:
- project
+- web_hook_logs
protected_branches:
- project
- merge_access_levels
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index c22fba11225..96054c996fd 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -54,6 +54,7 @@ Note:
- type
- position
- original_position
+- change_position
- resolved_at
- resolved_by_id
- discussion_id
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
new file mode 100644
index 00000000000..1eea710c80b
--- /dev/null
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -0,0 +1,384 @@
+# coding: utf-8
+require 'spec_helper'
+
+describe Gitlab::PathRegex, lib: true do
+ # Pass in a full path to remove the format segment:
+ # `/ci/lint(.:format)` -> `/ci/lint`
+ def without_format(path)
+ path.split('(', 2)[0]
+ end
+
+ # Pass in a full path and get the last segment before a wildcard
+ # That's not a parameter
+ # `/*namespace_id/:project_id/builds/artifacts/*ref_name_and_path`
+ # -> 'builds/artifacts'
+ def path_before_wildcard(path)
+ path = path.gsub(STARTING_WITH_NAMESPACE, "")
+ path_segments = path.split('/').reject(&:empty?)
+ wildcard_index = path_segments.index { |segment| parameter?(segment) }
+
+ segments_before_wildcard = path_segments[0..wildcard_index - 1]
+
+ segments_before_wildcard.join('/')
+ end
+
+ def parameter?(segment)
+ segment =~ /[*:]/
+ end
+
+ # If the path is reserved. Then no conflicting paths can# be created for any
+ # route using this reserved word.
+ #
+ # Both `builds/artifacts` & `build` are covered by reserving the word
+ # `build`
+ def wildcards_include?(path)
+ described_class::PROJECT_WILDCARD_ROUTES.include?(path) ||
+ described_class::PROJECT_WILDCARD_ROUTES.include?(path.split('/').first)
+ end
+
+ def failure_message(missing_words, constant_name, migration_helper)
+ missing_words = Array(missing_words)
+ <<-MSG
+ Found new routes that could cause conflicts with existing namespaced routes
+ for groups or projects.
+
+ Add <#{missing_words.join(', ')}> to `Gitlab::PathRegex::#{constant_name}
+ to make sure no projects or namespaces can be created with those paths.
+
+ To rename any existing records with those paths you can use the
+ `Gitlab::Database::RenameReservedpathsMigration::<VERSION>.#{migration_helper}`
+ migration helper.
+
+ Make sure to make a note of the renamed records in the release blog post.
+
+ MSG
+ end
+
+ let(:all_routes) do
+ route_set = Rails.application.routes
+ routes_collection = route_set.routes
+ routes_array = routes_collection.routes
+ routes_array.map { |route| route.path.spec.to_s }
+ end
+
+ let(:routes_without_format) { all_routes.map { |path| without_format(path) } }
+
+ # Routes not starting with `/:` or `/*`
+ # all routes not starting with a param
+ let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } }
+
+ let(:top_level_words) do
+ routes_not_starting_in_wildcard.map do |route|
+ route.split('/')[1]
+ end.compact.uniq
+ end
+
+ # All routes that start with a namespaced path, that have 1 or more
+ # path-segments before having another wildcard parameter.
+ # - Starting with paths:
+ # - `/*namespace_id/:project_id/`
+ # - `/*namespace_id/:id/`
+ # - Followed by one or more path-parts not starting with `:` or `*`
+ # - Followed by a path-part that includes a wildcard parameter `*`
+ # At the time of writing these routes match: http://rubular.com/r/Rv2pDE5Dvw
+ STARTING_WITH_NAMESPACE = %r{^/\*namespace_id/:(project_)?id}
+ NON_PARAM_PARTS = %r{[^:*][a-z\-_/]*}
+ ANY_OTHER_PATH_PART = %r{[a-z\-_/:]*}
+ WILDCARD_SEGMENT = %r{\*}
+ let(:namespaced_wildcard_routes) do
+ routes_without_format.select do |p|
+ p =~ %r{#{STARTING_WITH_NAMESPACE}/#{NON_PARAM_PARTS}/#{ANY_OTHER_PATH_PART}#{WILDCARD_SEGMENT}}
+ end
+ end
+
+ # This will return all paths that are used in a namespaced route
+ # before another wildcard path:
+ #
+ # /*namespace_id/:project_id/builds/artifacts/*ref_name_and_path
+ # /*namespace_id/:project_id/info/lfs/objects/*oid
+ # /*namespace_id/:project_id/commits/*id
+ # /*namespace_id/:project_id/builds/:build_id/artifacts/file/*path
+ # -> ['builds/artifacts', 'info/lfs/objects', 'commits', 'artifacts/file']
+ let(:all_wildcard_paths) do
+ namespaced_wildcard_routes.map do |route|
+ path_before_wildcard(route)
+ end.uniq
+ end
+
+ STARTING_WITH_GROUP = %r{^/groups/\*(group_)?id/}
+ let(:group_routes) do
+ routes_without_format.select do |path|
+ path =~ STARTING_WITH_GROUP
+ end
+ end
+
+ let(:paths_after_group_id) do
+ group_routes.map do |route|
+ route.gsub(STARTING_WITH_GROUP, '').split('/').first
+ end.uniq
+ end
+
+ describe 'TOP_LEVEL_ROUTES' do
+ it 'includes all the top level namespaces' do
+ failure_block = lambda do
+ missing_words = top_level_words - described_class::TOP_LEVEL_ROUTES
+ failure_message(missing_words, 'TOP_LEVEL_ROUTES', 'rename_root_paths')
+ end
+
+ expect(described_class::TOP_LEVEL_ROUTES)
+ .to include(*top_level_words), failure_block
+ end
+ end
+
+ describe 'GROUP_ROUTES' do
+ it "don't contain a second wildcard" do
+ failure_block = lambda do
+ missing_words = paths_after_group_id - described_class::GROUP_ROUTES
+ failure_message(missing_words, 'GROUP_ROUTES', 'rename_child_paths')
+ end
+
+ expect(described_class::GROUP_ROUTES)
+ .to include(*paths_after_group_id), failure_block
+ end
+ end
+
+ describe 'PROJECT_WILDCARD_ROUTES' do
+ it 'includes all paths that can be used after a namespace/project path' do
+ aggregate_failures do
+ all_wildcard_paths.each do |path|
+ expect(wildcards_include?(path))
+ .to be(true), failure_message(path, 'PROJECT_WILDCARD_ROUTES', 'rename_wildcard_paths')
+ end
+ end
+ end
+ end
+
+ describe '.root_namespace_path_regex' do
+ subject { described_class.root_namespace_path_regex }
+
+ it 'rejects top level routes' do
+ expect(subject).not_to match('admin/')
+ expect(subject).not_to match('api/')
+ expect(subject).not_to match('.well-known/')
+ end
+
+ it 'accepts project wildcard routes' do
+ expect(subject).to match('blob/')
+ expect(subject).to match('edit/')
+ expect(subject).to match('wikis/')
+ end
+
+ it 'accepts group routes' do
+ expect(subject).to match('activity/')
+ expect(subject).to match('group_members/')
+ expect(subject).to match('subgroups/')
+ end
+
+ it 'is not case sensitive' do
+ expect(subject).not_to match('Users/')
+ end
+
+ it 'does not allow extra slashes' do
+ expect(subject).not_to match('/blob/')
+ expect(subject).not_to match('blob//')
+ end
+ end
+
+ describe '.full_namespace_path_regex' do
+ subject { described_class.full_namespace_path_regex }
+
+ context 'at the top level' do
+ context 'when the final level' do
+ it 'rejects top level routes' do
+ expect(subject).not_to match('admin/')
+ expect(subject).not_to match('api/')
+ expect(subject).not_to match('.well-known/')
+ end
+
+ it 'accepts project wildcard routes' do
+ expect(subject).to match('blob/')
+ expect(subject).to match('edit/')
+ expect(subject).to match('wikis/')
+ end
+
+ it 'accepts group routes' do
+ expect(subject).to match('activity/')
+ expect(subject).to match('group_members/')
+ expect(subject).to match('subgroups/')
+ end
+ end
+
+ context 'when more levels follow' do
+ it 'rejects top level routes' do
+ expect(subject).not_to match('admin/more/')
+ expect(subject).not_to match('api/more/')
+ expect(subject).not_to match('.well-known/more/')
+ end
+
+ it 'accepts project wildcard routes' do
+ expect(subject).to match('blob/more/')
+ expect(subject).to match('edit/more/')
+ expect(subject).to match('wikis/more/')
+ expect(subject).to match('environments/folders/')
+ expect(subject).to match('info/lfs/objects/')
+ end
+
+ it 'accepts group routes' do
+ expect(subject).to match('activity/more/')
+ expect(subject).to match('group_members/more/')
+ expect(subject).to match('subgroups/more/')
+ end
+ end
+ end
+
+ context 'at the second level' do
+ context 'when the final level' do
+ it 'accepts top level routes' do
+ expect(subject).to match('root/admin/')
+ expect(subject).to match('root/api/')
+ expect(subject).to match('root/.well-known/')
+ end
+
+ it 'rejects project wildcard routes' do
+ expect(subject).not_to match('root/blob/')
+ expect(subject).not_to match('root/edit/')
+ expect(subject).not_to match('root/wikis/')
+ expect(subject).not_to match('root/environments/folders/')
+ expect(subject).not_to match('root/info/lfs/objects/')
+ end
+
+ it 'rejects group routes' do
+ expect(subject).not_to match('root/activity/')
+ expect(subject).not_to match('root/group_members/')
+ expect(subject).not_to match('root/subgroups/')
+ end
+ end
+
+ context 'when more levels follow' do
+ it 'accepts top level routes' do
+ expect(subject).to match('root/admin/more/')
+ expect(subject).to match('root/api/more/')
+ expect(subject).to match('root/.well-known/more/')
+ end
+
+ it 'rejects project wildcard routes' do
+ expect(subject).not_to match('root/blob/more/')
+ expect(subject).not_to match('root/edit/more/')
+ expect(subject).not_to match('root/wikis/more/')
+ expect(subject).not_to match('root/environments/folders/more/')
+ expect(subject).not_to match('root/info/lfs/objects/more/')
+ end
+
+ it 'rejects group routes' do
+ expect(subject).not_to match('root/activity/more/')
+ expect(subject).not_to match('root/group_members/more/')
+ expect(subject).not_to match('root/subgroups/more/')
+ end
+ end
+ end
+
+ it 'is not case sensitive' do
+ expect(subject).not_to match('root/Blob/')
+ end
+
+ it 'does not allow extra slashes' do
+ expect(subject).not_to match('/root/admin/')
+ expect(subject).not_to match('root/admin//')
+ end
+ end
+
+ describe '.project_path_regex' do
+ subject { described_class.project_path_regex }
+
+ it 'accepts top level routes' do
+ expect(subject).to match('admin/')
+ expect(subject).to match('api/')
+ expect(subject).to match('.well-known/')
+ end
+
+ it 'rejects project wildcard routes' do
+ expect(subject).not_to match('blob/')
+ expect(subject).not_to match('edit/')
+ expect(subject).not_to match('wikis/')
+ expect(subject).not_to match('environments/folders/')
+ expect(subject).not_to match('info/lfs/objects/')
+ end
+
+ it 'accepts group routes' do
+ expect(subject).to match('activity/')
+ expect(subject).to match('group_members/')
+ expect(subject).to match('subgroups/')
+ end
+
+ it 'is not case sensitive' do
+ expect(subject).not_to match('Blob/')
+ end
+
+ it 'does not allow extra slashes' do
+ expect(subject).not_to match('/admin/')
+ expect(subject).not_to match('admin//')
+ end
+ end
+
+ describe '.full_project_path_regex' do
+ subject { described_class.full_project_path_regex }
+
+ it 'accepts top level routes' do
+ expect(subject).to match('root/admin/')
+ expect(subject).to match('root/api/')
+ expect(subject).to match('root/.well-known/')
+ end
+
+ it 'rejects project wildcard routes' do
+ expect(subject).not_to match('root/blob/')
+ expect(subject).not_to match('root/edit/')
+ expect(subject).not_to match('root/wikis/')
+ expect(subject).not_to match('root/environments/folders/')
+ expect(subject).not_to match('root/info/lfs/objects/')
+ end
+
+ it 'accepts group routes' do
+ expect(subject).to match('root/activity/')
+ expect(subject).to match('root/group_members/')
+ expect(subject).to match('root/subgroups/')
+ end
+
+ it 'is not case sensitive' do
+ expect(subject).not_to match('root/Blob/')
+ end
+
+ it 'does not allow extra slashes' do
+ expect(subject).not_to match('/root/admin/')
+ expect(subject).not_to match('root/admin//')
+ end
+ end
+
+ describe '.namespace_format_regex' do
+ subject { described_class.namespace_format_regex }
+
+ it { is_expected.to match('gitlab-ce') }
+ it { is_expected.to match('gitlab_git') }
+ it { is_expected.to match('_underscore.js') }
+ it { is_expected.to match('100px.com') }
+ it { is_expected.to match('gitlab.org') }
+ it { is_expected.not_to match('?gitlab') }
+ it { is_expected.not_to match('git lab') }
+ it { is_expected.not_to match('gitlab.git') }
+ it { is_expected.not_to match('gitlab.org.') }
+ it { is_expected.not_to match('gitlab.org/') }
+ it { is_expected.not_to match('/gitlab.org') }
+ it { is_expected.not_to match('gitlab git') }
+ end
+
+ describe '.project_path_format_regex' do
+ subject { described_class.project_path_format_regex }
+
+ it { is_expected.to match('gitlab-ce') }
+ it { is_expected.to match('gitlab_git') }
+ it { is_expected.to match('_underscore.js') }
+ it { is_expected.to match('100px.com') }
+ it { is_expected.not_to match('?gitlab') }
+ it { is_expected.not_to match('git lab') }
+ it { is_expected.not_to match('gitlab.git') }
+ end
+end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index a7d1283acb8..0bee892fe0c 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -2,386 +2,6 @@
require 'spec_helper'
describe Gitlab::Regex, lib: true do
- # Pass in a full path to remove the format segment:
- # `/ci/lint(.:format)` -> `/ci/lint`
- def without_format(path)
- path.split('(', 2)[0]
- end
-
- # Pass in a full path and get the last segment before a wildcard
- # That's not a parameter
- # `/*namespace_id/:project_id/builds/artifacts/*ref_name_and_path`
- # -> 'builds/artifacts'
- def path_before_wildcard(path)
- path = path.gsub(STARTING_WITH_NAMESPACE, "")
- path_segments = path.split('/').reject(&:empty?)
- wildcard_index = path_segments.index { |segment| parameter?(segment) }
-
- segments_before_wildcard = path_segments[0..wildcard_index - 1]
-
- segments_before_wildcard.join('/')
- end
-
- def parameter?(segment)
- segment =~ /[*:]/
- end
-
- # If the path is reserved. Then no conflicting paths can# be created for any
- # route using this reserved word.
- #
- # Both `builds/artifacts` & `build` are covered by reserving the word
- # `build`
- def wildcards_include?(path)
- described_class::PROJECT_WILDCARD_ROUTES.include?(path) ||
- described_class::PROJECT_WILDCARD_ROUTES.include?(path.split('/').first)
- end
-
- def failure_message(missing_words, constant_name, migration_helper)
- missing_words = Array(missing_words)
- <<-MSG
- Found new routes that could cause conflicts with existing namespaced routes
- for groups or projects.
-
- Add <#{missing_words.join(', ')}> to `Gitlab::Regex::#{constant_name}
- to make sure no projects or namespaces can be created with those paths.
-
- To rename any existing records with those paths you can use the
- `Gitlab::Database::RenameReservedpathsMigration::<VERSION>.#{migration_helper}`
- migration helper.
-
- Make sure to make a note of the renamed records in the release blog post.
-
- MSG
- end
-
- let(:all_routes) do
- route_set = Rails.application.routes
- routes_collection = route_set.routes
- routes_array = routes_collection.routes
- routes_array.map { |route| route.path.spec.to_s }
- end
-
- let(:routes_without_format) { all_routes.map { |path| without_format(path) } }
-
- # Routes not starting with `/:` or `/*`
- # all routes not starting with a param
- let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } }
-
- let(:top_level_words) do
- routes_not_starting_in_wildcard.map do |route|
- route.split('/')[1]
- end.compact.uniq
- end
-
- # All routes that start with a namespaced path, that have 1 or more
- # path-segments before having another wildcard parameter.
- # - Starting with paths:
- # - `/*namespace_id/:project_id/`
- # - `/*namespace_id/:id/`
- # - Followed by one or more path-parts not starting with `:` or `*`
- # - Followed by a path-part that includes a wildcard parameter `*`
- # At the time of writing these routes match: http://rubular.com/r/Rv2pDE5Dvw
- STARTING_WITH_NAMESPACE = %r{^/\*namespace_id/:(project_)?id}
- NON_PARAM_PARTS = %r{[^:*][a-z\-_/]*}
- ANY_OTHER_PATH_PART = %r{[a-z\-_/:]*}
- WILDCARD_SEGMENT = %r{\*}
- let(:namespaced_wildcard_routes) do
- routes_without_format.select do |p|
- p =~ %r{#{STARTING_WITH_NAMESPACE}/#{NON_PARAM_PARTS}/#{ANY_OTHER_PATH_PART}#{WILDCARD_SEGMENT}}
- end
- end
-
- # This will return all paths that are used in a namespaced route
- # before another wildcard path:
- #
- # /*namespace_id/:project_id/builds/artifacts/*ref_name_and_path
- # /*namespace_id/:project_id/info/lfs/objects/*oid
- # /*namespace_id/:project_id/commits/*id
- # /*namespace_id/:project_id/builds/:build_id/artifacts/file/*path
- # -> ['builds/artifacts', 'info/lfs/objects', 'commits', 'artifacts/file']
- let(:all_wildcard_paths) do
- namespaced_wildcard_routes.map do |route|
- path_before_wildcard(route)
- end.uniq
- end
-
- STARTING_WITH_GROUP = %r{^/groups/\*(group_)?id/}
- let(:group_routes) do
- routes_without_format.select do |path|
- path =~ STARTING_WITH_GROUP
- end
- end
-
- let(:paths_after_group_id) do
- group_routes.map do |route|
- route.gsub(STARTING_WITH_GROUP, '').split('/').first
- end.uniq
- end
-
- describe 'TOP_LEVEL_ROUTES' do
- it 'includes all the top level namespaces' do
- failure_block = lambda do
- missing_words = top_level_words - described_class::TOP_LEVEL_ROUTES
- failure_message(missing_words, 'TOP_LEVEL_ROUTES', 'rename_root_paths')
- end
-
- expect(described_class::TOP_LEVEL_ROUTES)
- .to include(*top_level_words), failure_block
- end
- end
-
- describe 'GROUP_ROUTES' do
- it "don't contain a second wildcard" do
- failure_block = lambda do
- missing_words = paths_after_group_id - described_class::GROUP_ROUTES
- failure_message(missing_words, 'GROUP_ROUTES', 'rename_child_paths')
- end
-
- expect(described_class::GROUP_ROUTES)
- .to include(*paths_after_group_id), failure_block
- end
- end
-
- describe 'PROJECT_WILDCARD_ROUTES' do
- it 'includes all paths that can be used after a namespace/project path' do
- aggregate_failures do
- all_wildcard_paths.each do |path|
- expect(wildcards_include?(path))
- .to be(true), failure_message(path, 'PROJECT_WILDCARD_ROUTES', 'rename_wildcard_paths')
- end
- end
- end
- end
-
- describe '.root_namespace_path_regex' do
- subject { described_class.root_namespace_path_regex }
-
- it 'rejects top level routes' do
- expect(subject).not_to match('admin/')
- expect(subject).not_to match('api/')
- expect(subject).not_to match('.well-known/')
- end
-
- it 'accepts project wildcard routes' do
- expect(subject).to match('blob/')
- expect(subject).to match('edit/')
- expect(subject).to match('wikis/')
- end
-
- it 'accepts group routes' do
- expect(subject).to match('activity/')
- expect(subject).to match('group_members/')
- expect(subject).to match('subgroups/')
- end
-
- it 'is not case sensitive' do
- expect(subject).not_to match('Users/')
- end
-
- it 'does not allow extra slashes' do
- expect(subject).not_to match('/blob/')
- expect(subject).not_to match('blob//')
- end
- end
-
- describe '.full_namespace_path_regex' do
- subject { described_class.full_namespace_path_regex }
-
- context 'at the top level' do
- context 'when the final level' do
- it 'rejects top level routes' do
- expect(subject).not_to match('admin/')
- expect(subject).not_to match('api/')
- expect(subject).not_to match('.well-known/')
- end
-
- it 'accepts project wildcard routes' do
- expect(subject).to match('blob/')
- expect(subject).to match('edit/')
- expect(subject).to match('wikis/')
- end
-
- it 'accepts group routes' do
- expect(subject).to match('activity/')
- expect(subject).to match('group_members/')
- expect(subject).to match('subgroups/')
- end
- end
-
- context 'when more levels follow' do
- it 'rejects top level routes' do
- expect(subject).not_to match('admin/more/')
- expect(subject).not_to match('api/more/')
- expect(subject).not_to match('.well-known/more/')
- end
-
- it 'accepts project wildcard routes' do
- expect(subject).to match('blob/more/')
- expect(subject).to match('edit/more/')
- expect(subject).to match('wikis/more/')
- expect(subject).to match('environments/folders/')
- expect(subject).to match('info/lfs/objects/')
- end
-
- it 'accepts group routes' do
- expect(subject).to match('activity/more/')
- expect(subject).to match('group_members/more/')
- expect(subject).to match('subgroups/more/')
- end
- end
- end
-
- context 'at the second level' do
- context 'when the final level' do
- it 'accepts top level routes' do
- expect(subject).to match('root/admin/')
- expect(subject).to match('root/api/')
- expect(subject).to match('root/.well-known/')
- end
-
- it 'rejects project wildcard routes' do
- expect(subject).not_to match('root/blob/')
- expect(subject).not_to match('root/edit/')
- expect(subject).not_to match('root/wikis/')
- expect(subject).not_to match('root/environments/folders/')
- expect(subject).not_to match('root/info/lfs/objects/')
- end
-
- it 'rejects group routes' do
- expect(subject).not_to match('root/activity/')
- expect(subject).not_to match('root/group_members/')
- expect(subject).not_to match('root/subgroups/')
- end
- end
-
- context 'when more levels follow' do
- it 'accepts top level routes' do
- expect(subject).to match('root/admin/more/')
- expect(subject).to match('root/api/more/')
- expect(subject).to match('root/.well-known/more/')
- end
-
- it 'rejects project wildcard routes' do
- expect(subject).not_to match('root/blob/more/')
- expect(subject).not_to match('root/edit/more/')
- expect(subject).not_to match('root/wikis/more/')
- expect(subject).not_to match('root/environments/folders/more/')
- expect(subject).not_to match('root/info/lfs/objects/more/')
- end
-
- it 'rejects group routes' do
- expect(subject).not_to match('root/activity/more/')
- expect(subject).not_to match('root/group_members/more/')
- expect(subject).not_to match('root/subgroups/more/')
- end
- end
- end
-
- it 'is not case sensitive' do
- expect(subject).not_to match('root/Blob/')
- end
-
- it 'does not allow extra slashes' do
- expect(subject).not_to match('/root/admin/')
- expect(subject).not_to match('root/admin//')
- end
- end
-
- describe '.project_path_regex' do
- subject { described_class.project_path_regex }
-
- it 'accepts top level routes' do
- expect(subject).to match('admin/')
- expect(subject).to match('api/')
- expect(subject).to match('.well-known/')
- end
-
- it 'rejects project wildcard routes' do
- expect(subject).not_to match('blob/')
- expect(subject).not_to match('edit/')
- expect(subject).not_to match('wikis/')
- expect(subject).not_to match('environments/folders/')
- expect(subject).not_to match('info/lfs/objects/')
- end
-
- it 'accepts group routes' do
- expect(subject).to match('activity/')
- expect(subject).to match('group_members/')
- expect(subject).to match('subgroups/')
- end
-
- it 'is not case sensitive' do
- expect(subject).not_to match('Blob/')
- end
-
- it 'does not allow extra slashes' do
- expect(subject).not_to match('/admin/')
- expect(subject).not_to match('admin//')
- end
- end
-
- describe '.full_project_path_regex' do
- subject { described_class.full_project_path_regex }
-
- it 'accepts top level routes' do
- expect(subject).to match('root/admin/')
- expect(subject).to match('root/api/')
- expect(subject).to match('root/.well-known/')
- end
-
- it 'rejects project wildcard routes' do
- expect(subject).not_to match('root/blob/')
- expect(subject).not_to match('root/edit/')
- expect(subject).not_to match('root/wikis/')
- expect(subject).not_to match('root/environments/folders/')
- expect(subject).not_to match('root/info/lfs/objects/')
- end
-
- it 'accepts group routes' do
- expect(subject).to match('root/activity/')
- expect(subject).to match('root/group_members/')
- expect(subject).to match('root/subgroups/')
- end
-
- it 'is not case sensitive' do
- expect(subject).not_to match('root/Blob/')
- end
-
- it 'does not allow extra slashes' do
- expect(subject).not_to match('/root/admin/')
- expect(subject).not_to match('root/admin//')
- end
- end
-
- describe '.namespace_regex' do
- subject { described_class.namespace_regex }
-
- it { is_expected.to match('gitlab-ce') }
- it { is_expected.to match('gitlab_git') }
- it { is_expected.to match('_underscore.js') }
- it { is_expected.to match('100px.com') }
- it { is_expected.to match('gitlab.org') }
- it { is_expected.not_to match('?gitlab') }
- it { is_expected.not_to match('git lab') }
- it { is_expected.not_to match('gitlab.git') }
- it { is_expected.not_to match('gitlab.org.') }
- it { is_expected.not_to match('gitlab.org/') }
- it { is_expected.not_to match('/gitlab.org') }
- it { is_expected.not_to match('gitlab git') }
- end
-
- describe '.project_path_format_regex' do
- subject { described_class.project_path_format_regex }
-
- it { is_expected.to match('gitlab-ce') }
- it { is_expected.to match('gitlab_git') }
- it { is_expected.to match('_underscore.js') }
- it { is_expected.to match('100px.com') }
- it { is_expected.not_to match('?gitlab') }
- it { is_expected.not_to match('git lab') }
- it { is_expected.not_to match('gitlab.git') }
- end
-
describe '.project_name_regex' do
subject { described_class.project_name_regex }
@@ -412,16 +32,4 @@ describe Gitlab::Regex, lib: true do
it { is_expected.not_to match('9foo') }
it { is_expected.not_to match('foo-') }
end
-
- describe '.full_namespace_regex' do
- subject { described_class.full_namespace_regex }
-
- it { is_expected.to match('gitlab.org') }
- it { is_expected.to match('gitlab.org/gitlab-git') }
- it { is_expected.not_to match('gitlab.org.') }
- it { is_expected.not_to match('gitlab.org/') }
- it { is_expected.not_to match('/gitlab.org') }
- it { is_expected.not_to match('gitlab.git') }
- it { is_expected.not_to match('gitlab git') }
- end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 2515fc3b00a..00e3b8e5689 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -965,7 +965,7 @@ describe Ci::Pipeline, models: true do
end
before do
- ProjectWebHookWorker.drain
+ WebHookWorker.drain
end
context 'with pipeline hooks enabled' do
diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb
index 8571e85627c..f3e148f95f0 100644
--- a/spec/models/concerns/discussion_on_diff_spec.rb
+++ b/spec/models/concerns/discussion_on_diff_spec.rb
@@ -21,4 +21,30 @@ describe DiscussionOnDiff, model: true do
end
end
end
+
+ describe '#line_code_in_diffs' do
+ context 'when the discussion is active in the diff' do
+ let(:diff_refs) { subject.position.diff_refs }
+
+ it 'returns the current line code' do
+ expect(subject.line_code_in_diffs(diff_refs)).to eq(subject.line_code)
+ end
+ end
+
+ context 'when the discussion was created in the diff' do
+ let(:diff_refs) { subject.original_position.diff_refs }
+
+ it 'returns the original line code' do
+ expect(subject.line_code_in_diffs(diff_refs)).to eq(subject.original_line_code)
+ end
+ end
+
+ context 'when the discussion is unrelated to the diff' do
+ let(:diff_refs) { subject.project.commit(RepoHelpers.sample_commit.id).diff_refs }
+
+ it 'returns nil' do
+ expect(subject.line_code_in_diffs(diff_refs)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/diff_discussion_spec.rb b/spec/models/diff_discussion_spec.rb
index 81f338745b1..45b2f6e4beb 100644
--- a/spec/models/diff_discussion_spec.rb
+++ b/spec/models/diff_discussion_spec.rb
@@ -48,7 +48,7 @@ describe DiffDiscussion, model: true do
end
it 'returns the diff ID for the version to show' do
- expect(diff_id: merge_request_diff1.id)
+ expect(subject.merge_request_version_params).to eq(diff_id: merge_request_diff1.id)
end
end
@@ -65,6 +65,11 @@ describe DiffDiscussion, model: true do
let(:diff_note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, position: position) }
+ before do
+ diff_note.position = diff_note.original_position
+ diff_note.save!
+ end
+
it 'returns the diff ID and start sha of the versions to compare' do
expect(subject.merge_request_version_params).to eq(diff_id: merge_request_diff3.id, start_sha: merge_request_diff1.head_commit_sha)
end
diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb
index 1a83c836652..57454d2a773 100644
--- a/spec/models/hooks/service_hook_spec.rb
+++ b/spec/models/hooks/service_hook_spec.rb
@@ -1,36 +1,19 @@
-require "spec_helper"
+require 'spec_helper'
describe ServiceHook, models: true do
- describe "Associations" do
+ describe 'associations' do
it { is_expected.to belong_to :service }
end
- describe "execute" do
- before(:each) do
- @service_hook = create(:service_hook)
- @data = { project_id: 1, data: {} }
+ describe 'execute' do
+ let(:hook) { build(:service_hook) }
+ let(:data) { { key: 'value' } }
- WebMock.stub_request(:post, @service_hook.url)
- end
-
- it "POSTs to the webhook URL" do
- @service_hook.execute(@data)
- expect(WebMock).to have_requested(:post, @service_hook.url).with(
- headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Service Hook' }
- ).once
- end
-
- it "POSTs the data as JSON" do
- @service_hook.execute(@data)
- expect(WebMock).to have_requested(:post, @service_hook.url).with(
- headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Service Hook' }
- ).once
- end
-
- it "catches exceptions" do
- expect(WebHook).to receive(:post).and_raise("Some HTTP Post error")
+ it '#execute' do
+ expect(WebHookService).to receive(:new).with(hook, data, 'service_hook').and_call_original
+ expect_any_instance_of(WebHookService).to receive(:execute)
- expect { @service_hook.execute(@data) }.to raise_error(RuntimeError)
+ hook.execute(data)
end
end
end
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index 4340170888d..0d2b622132e 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -126,4 +126,26 @@ describe SystemHook, models: true do
expect(SystemHook.repository_update_hooks).to eq([hook])
end
end
+
+ describe 'execute WebHookService' do
+ let(:hook) { build(:system_hook) }
+ let(:data) { { key: 'value' } }
+ let(:hook_name) { 'system_hook' }
+
+ before do
+ expect(WebHookService).to receive(:new).with(hook, data, hook_name).and_call_original
+ end
+
+ it '#execute' do
+ expect_any_instance_of(WebHookService).to receive(:execute)
+
+ hook.execute(data, hook_name)
+ end
+
+ it '#async_execute' do
+ expect_any_instance_of(WebHookService).to receive(:async_execute)
+
+ hook.async_execute(data, hook_name)
+ end
+ end
end
diff --git a/spec/models/hooks/web_hook_log_spec.rb b/spec/models/hooks/web_hook_log_spec.rb
new file mode 100644
index 00000000000..c649cf3b589
--- /dev/null
+++ b/spec/models/hooks/web_hook_log_spec.rb
@@ -0,0 +1,30 @@
+require 'rails_helper'
+
+describe WebHookLog, models: true do
+ it { is_expected.to belong_to(:web_hook) }
+
+ it { is_expected.to serialize(:request_headers).as(Hash) }
+ it { is_expected.to serialize(:request_data).as(Hash) }
+ it { is_expected.to serialize(:response_headers).as(Hash) }
+
+ it { is_expected.to validate_presence_of(:web_hook) }
+
+ describe '#success?' do
+ let(:web_hook_log) { build(:web_hook_log, response_status: status) }
+
+ describe '2xx' do
+ let(:status) { '200' }
+ it { expect(web_hook_log.success?).to be_truthy }
+ end
+
+ describe 'not 2xx' do
+ let(:status) { '500' }
+ it { expect(web_hook_log.success?).to be_falsey }
+ end
+
+ describe 'internal erorr' do
+ let(:status) { 'internal error' }
+ it { expect(web_hook_log.success?).to be_falsey }
+ end
+ end
+end
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 9d4db1bfb52..53157c24477 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -1,89 +1,54 @@
require 'spec_helper'
describe WebHook, models: true do
- describe "Validations" do
+ let(:hook) { build(:project_hook) }
+
+ describe 'associations' do
+ it { is_expected.to have_many(:web_hook_logs).dependent(:destroy) }
+ end
+
+ describe 'validations' do
it { is_expected.to validate_presence_of(:url) }
describe 'url' do
- it { is_expected.to allow_value("http://example.com").for(:url) }
- it { is_expected.to allow_value("https://example.com").for(:url) }
- it { is_expected.to allow_value(" https://example.com ").for(:url) }
- it { is_expected.to allow_value("http://test.com/api").for(:url) }
- it { is_expected.to allow_value("http://test.com/api?key=abc").for(:url) }
- it { is_expected.to allow_value("http://test.com/api?key=abc&type=def").for(:url) }
+ it { is_expected.to allow_value('http://example.com').for(:url) }
+ it { is_expected.to allow_value('https://example.com').for(:url) }
+ it { is_expected.to allow_value(' https://example.com ').for(:url) }
+ it { is_expected.to allow_value('http://test.com/api').for(:url) }
+ it { is_expected.to allow_value('http://test.com/api?key=abc').for(:url) }
+ it { is_expected.to allow_value('http://test.com/api?key=abc&type=def').for(:url) }
- it { is_expected.not_to allow_value("example.com").for(:url) }
- it { is_expected.not_to allow_value("ftp://example.com").for(:url) }
- it { is_expected.not_to allow_value("herp-and-derp").for(:url) }
+ it { is_expected.not_to allow_value('example.com').for(:url) }
+ it { is_expected.not_to allow_value('ftp://example.com').for(:url) }
+ it { is_expected.not_to allow_value('herp-and-derp').for(:url) }
it 'strips :url before saving it' do
- hook = create(:project_hook, url: ' https://example.com ')
+ hook.url = ' https://example.com '
+ hook.save
expect(hook.url).to eq('https://example.com')
end
end
end
- describe "execute" do
- let(:project) { create(:empty_project) }
- let(:project_hook) { create(:project_hook) }
-
- before(:each) do
- project.hooks << [project_hook]
- @data = { before: 'oldrev', after: 'newrev', ref: 'ref' }
-
- WebMock.stub_request(:post, project_hook.url)
- end
-
- context 'when token is defined' do
- let(:project_hook) { create(:project_hook, :token) }
-
- it 'POSTs to the webhook URL' do
- project_hook.execute(@data, 'push_hooks')
- expect(WebMock).to have_requested(:post, project_hook.url).with(
- headers: { 'Content-Type' => 'application/json',
- 'X-Gitlab-Event' => 'Push Hook',
- 'X-Gitlab-Token' => project_hook.token }
- ).once
- end
- end
-
- it "POSTs to the webhook URL" do
- project_hook.execute(@data, 'push_hooks')
- expect(WebMock).to have_requested(:post, project_hook.url).with(
- headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Push Hook' }
- ).once
- end
-
- it "POSTs the data as JSON" do
- project_hook.execute(@data, 'push_hooks')
- expect(WebMock).to have_requested(:post, project_hook.url).with(
- headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Push Hook' }
- ).once
- end
-
- it "catches exceptions" do
- expect(WebHook).to receive(:post).and_raise("Some HTTP Post error")
-
- expect { project_hook.execute(@data, 'push_hooks') }.to raise_error(RuntimeError)
- end
-
- it "handles SSL exceptions" do
- expect(WebHook).to receive(:post).and_raise(OpenSSL::SSL::SSLError.new('SSL error'))
+ describe 'execute' do
+ let(:data) { { key: 'value' } }
+ let(:hook_name) { 'project hook' }
- expect(project_hook.execute(@data, 'push_hooks')).to eq([false, 'SSL error'])
+ before do
+ expect(WebHookService).to receive(:new).with(hook, data, hook_name).and_call_original
end
- it "handles 200 status code" do
- WebMock.stub_request(:post, project_hook.url).to_return(status: 200, body: "Success")
+ it '#execute' do
+ expect_any_instance_of(WebHookService).to receive(:execute)
- expect(project_hook.execute(@data, 'push_hooks')).to eq([200, 'Success'])
+ hook.execute(data, hook_name)
end
- it "handles 2xx status codes" do
- WebMock.stub_request(:post, project_hook.url).to_return(status: 201, body: "Success")
+ it '#async_execute' do
+ expect_any_instance_of(WebHookService).to receive(:async_execute)
- expect(project_hook.execute(@data, 'push_hooks')).to eq([201, 'Success'])
+ hook.async_execute(data, hook_name)
end
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index e89b707fae7..3645964b09c 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1213,7 +1213,7 @@ describe MergeRequest, models: true do
expect(Notes::DiffPositionUpdateService).to receive(:new).with(
subject.project,
- nil,
+ subject.author,
old_diff_refs: old_diff_refs,
new_diff_refs: commit.diff_refs,
paths: note.position.paths
@@ -1222,7 +1222,7 @@ describe MergeRequest, models: true do
expect_any_instance_of(Notes::DiffPositionUpdateService).to receive(:execute).with(note)
expect_any_instance_of(DiffNote).to receive(:save).once
- subject.reload_diff
+ subject.reload_diff(subject.author)
end
end
@@ -1540,4 +1540,36 @@ describe MergeRequest, models: true do
it { expect(subject.base_pipeline).to eq(pipeline) }
end
+
+ describe '#version_params_for' do
+ subject { create(:merge_request, importing: true) }
+ let(:project) { subject.project }
+ let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+ let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
+ let!(:merge_request_diff3) { subject.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
+
+ context 'when the diff refs are for an older merge request version' do
+ let(:diff_refs) { merge_request_diff1.diff_refs }
+
+ it 'returns the diff ID for the version to show' do
+ expect(subject.version_params_for(diff_refs)).to eq(diff_id: merge_request_diff1.id)
+ end
+ end
+
+ context 'when the diff refs are for a comparison between merge request versions' do
+ let(:diff_refs) { merge_request_diff3.compare_with(merge_request_diff1.head_commit_sha).diff_refs }
+
+ it 'returns the diff ID and start sha of the versions to compare' do
+ expect(subject.version_params_for(diff_refs)).to eq(diff_id: merge_request_diff3.id, start_sha: merge_request_diff1.head_commit_sha)
+ end
+ end
+
+ context 'when the diff refs are not for a merge request version' do
+ let(:diff_refs) { project.commit(sample_commit.id).diff_refs }
+
+ it 'returns nil' do
+ expect(subject.version_params_for(diff_refs)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 312302afdbb..ff5e7c350aa 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -238,8 +238,8 @@ describe Namespace, models: true do
end
context 'in sub-groups' do
- let(:parent) { create(:namespace, path: 'parent') }
- let(:child) { create(:namespace, parent: parent, path: 'child') }
+ let(:parent) { create(:group, path: 'parent') }
+ let(:child) { create(:group, parent: parent, path: 'child') }
let!(:project) { create(:project_empty_repo, namespace: child) }
let(:path_in_dir) { File.join(repository_storage_path, 'parent', 'child') }
let(:deleted_path) { File.join('parent', "child+#{child.id}+deleted") }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index c1c2f2a7219..0dcf4a4b5d6 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -13,7 +13,7 @@ describe KubernetesService, models: true, caching: true do
let(:discovery_url) { service.api_url + '/api/v1' }
let(:discovery_response) { { body: kube_discovery_body.to_json } }
- let(:pods_url) { service.api_url + "/api/v1/namespaces/#{service.namespace}/pods" }
+ let(:pods_url) { service.api_url + "/api/v1/namespaces/#{service.actual_namespace}/pods" }
let(:pods_response) { { body: kube_pods_body(kube_pod).to_json } }
def stub_kubeclient_discover
@@ -100,7 +100,35 @@ describe KubernetesService, models: true, caching: true do
it 'sets the namespace to the default' do
expect(kube_namespace).not_to be_nil
- expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
+ expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
+ end
+ end
+ end
+
+ describe '#actual_namespace' do
+ subject { service.actual_namespace }
+
+ it "returns the default namespace" do
+ is_expected.to eq(service.send(:default_namespace))
+ end
+
+ context 'when namespace is specified' do
+ before do
+ service.namespace = 'my-namespace'
+ end
+
+ it "returns the user-namespace" do
+ is_expected.to eq('my-namespace')
+ end
+ end
+
+ context 'when service is not assigned to project' do
+ before do
+ service.project = nil
+ end
+
+ it "does not return namespace" do
+ is_expected.to be_nil
end
end
end
@@ -187,13 +215,14 @@ describe KubernetesService, models: true, caching: true do
kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
expect(kube_namespace).not_to be_nil
- expect(kube_namespace[:value]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
+ expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
end
end
end
describe '#terminals' do
let(:environment) { build(:environment, project: project, name: "env", slug: "env-000000") }
+
subject { service.terminals(environment) }
context 'with invalid pods' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 6a15830a15c..aabdac4bb75 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -440,6 +440,22 @@ describe User, models: true do
end
end
+ describe 'ensure incoming email token' do
+ it 'has incoming email token' do
+ user = create(:user)
+ expect(user.incoming_email_token).not_to be_blank
+ end
+ end
+
+ describe 'rss token' do
+ it 'ensures an rss token on read' do
+ user = create(:user, rss_token: nil)
+ rss_token = user.rss_token
+ expect(rss_token).not_to be_blank
+ expect(user.reload.rss_token).to eq rss_token
+ end
+ end
+
describe '#recently_sent_password_reset?' do
it 'is false when reset_password_sent_at is nil' do
user = build_stubbed(:user, reset_password_sent_at: nil)
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 4919ad19833..a2503dbeb69 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -287,7 +287,7 @@ describe API::Users do
expect(json_response['message']['projects_limit']).
to eq(['must be greater than or equal to 0'])
expect(json_response['message']['username']).
- to eq([Gitlab::Regex.namespace_regex_message])
+ to eq([Gitlab::PathRegex.namespace_format_message])
end
it "is not available for non admin users" do
@@ -459,7 +459,7 @@ describe API::Users do
expect(json_response['message']['projects_limit']).
to eq(['must be greater than or equal to 0'])
expect(json_response['message']['username']).
- to eq([Gitlab::Regex.namespace_regex_message])
+ to eq([Gitlab::PathRegex.namespace_format_message])
end
it 'returns 400 if provider is missing for identity update' do
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index e5fc0b676af..179fc9733ad 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -103,6 +103,18 @@ describe Admin::HooksController, "routing" do
end
end
+# admin_hook_hook_log_retry GET /admin/hooks/:hook_id/hook_logs/:id/retry(.:format) admin/hook_logs#retry
+# admin_hook_hook_log GET /admin/hooks/:hook_id/hook_logs/:id(.:format) admin/hook_logs#show
+describe Admin::HookLogsController, 'routing' do
+ it 'to #retry' do
+ expect(get('/admin/hooks/1/hook_logs/1/retry')).to route_to('admin/hook_logs#retry', hook_id: '1', id: '1')
+ end
+
+ it 'to #show' do
+ expect(get('/admin/hooks/1/hook_logs/1')).to route_to('admin/hook_logs#show', hook_id: '1', id: '1')
+ end
+end
+
# admin_logs GET /admin/logs(.:format) admin/logs#show
describe Admin::LogsController, "routing" do
it "to #show" do
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index a391c046f92..54417f6b3e1 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -349,6 +349,18 @@ describe 'project routing' do
end
end
+ # retry_namespace_project_hook_hook_log GET /:project_id/hooks/:hook_id/hook_logs/:id/retry(.:format) projects/hook_logs#retry
+ # namespace_project_hook_hook_log GET /:project_id/hooks/:hook_id/hook_logs/:id(.:format) projects/hook_logs#show
+ describe Projects::HookLogsController, 'routing' do
+ it 'to #retry' do
+ expect(get('/gitlab/gitlabhq/hooks/1/hook_logs/1/retry')).to route_to('projects/hook_logs#retry', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
+ end
+
+ it 'to #show' do
+ expect(get('/gitlab/gitlabhq/hooks/1/hook_logs/1')).to route_to('projects/hook_logs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
+ end
+ end
+
# project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /\h{7,40}/, project_id: /[^\/]+/}
describe Projects::CommitController, 'routing' do
it 'to #show' do
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index abacc50a371..a62af13cf0c 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -151,6 +151,10 @@ describe ProfilesController, "routing" do
expect(put("/profile/reset_private_token")).to route_to('profiles#reset_private_token')
end
+ it "to #reset_rss_token" do
+ expect(put("/profile/reset_rss_token")).to route_to('profiles#reset_rss_token')
+ end
+
it "to #show" do
expect(get("/profile")).to route_to('profiles#show')
end
diff --git a/spec/services/notes/diff_position_update_service_spec.rb b/spec/services/notes/diff_position_update_service_spec.rb
index d73ae51fbc3..380c296fd3a 100644
--- a/spec/services/notes/diff_position_update_service_spec.rb
+++ b/spec/services/notes/diff_position_update_service_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Notes::DiffPositionUpdateService, services: true do
let(:project) { create(:project, :repository) }
+ let(:current_user) { project.owner }
let(:create_commit) { project.commit("913c66a37b4a45b9769037c55c2d238bd0942d2e") }
let(:modify_commit) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
let(:edit_commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") }
@@ -25,7 +26,7 @@ describe Notes::DiffPositionUpdateService, services: true do
subject do
described_class.new(
project,
- nil,
+ current_user,
old_diff_refs: old_diff_refs,
new_diff_refs: new_diff_refs,
paths: [path]
@@ -170,6 +171,23 @@ describe Notes::DiffPositionUpdateService, services: true do
expect(note.original_position).to eq(old_position)
expect(note.position).to eq(old_position)
end
+
+ it 'sets the change position' do
+ subject.execute(note)
+
+ change_position = note.change_position
+ expect(change_position.start_sha).to eq(old_diff_refs.head_sha)
+ expect(change_position.head_sha).to eq(new_diff_refs.head_sha)
+ expect(change_position.old_line).to eq(9)
+ expect(change_position.new_line).to be_nil
+ end
+
+ it 'creates a system note' do
+ expect(SystemNoteService).to receive(:diff_discussion_outdated).with(
+ note.to_discussion, project, current_user, instance_of(Gitlab::Diff::Position))
+
+ subject.execute(note)
+ end
end
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 7a9cd7553b1..5a7cfaff7fb 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -1034,4 +1034,35 @@ describe SystemNoteService, services: true do
expect(subject.note).to eq 'resolved all discussions'
end
end
+
+ describe '.diff_discussion_outdated' do
+ let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let(:merge_request) { discussion.noteable }
+ let(:project) { merge_request.source_project }
+ let(:change_position) { discussion.position }
+
+ def reloaded_merge_request
+ MergeRequest.find(merge_request.id)
+ end
+
+ subject { described_class.diff_discussion_outdated(discussion, project, author, change_position) }
+
+ it_behaves_like 'a system note' do
+ let(:expected_noteable) { discussion.first_note.noteable }
+ let(:action) { 'outdated' }
+ end
+
+ it 'creates a new note in the discussion' do
+ # we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded.
+ expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1)
+ end
+
+ it 'links to the diff in the system note' do
+ expect(subject.note).to include('version 1')
+
+ diff_id = merge_request.merge_request_diff.id
+ line_code = change_position.line_code(project.repository)
+ expect(subject.note).to include(diffs_namespace_project_merge_request_url(project.namespace, project, merge_request, diff_id: diff_id, anchor: line_code))
+ end
+ end
end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
new file mode 100644
index 00000000000..b5abc46e80c
--- /dev/null
+++ b/spec/services/web_hook_service_spec.rb
@@ -0,0 +1,137 @@
+require 'spec_helper'
+
+describe WebHookService, services: true do
+ let(:project) { create(:empty_project) }
+ let(:project_hook) { create(:project_hook) }
+ let(:headers) do
+ {
+ 'Content-Type' => 'application/json',
+ 'X-Gitlab-Event' => 'Push Hook'
+ }
+ end
+ let(:data) do
+ { before: 'oldrev', after: 'newrev', ref: 'ref' }
+ end
+ let(:service_instance) { WebHookService.new(project_hook, data, 'push_hooks') }
+
+ describe '#execute' do
+ before(:each) do
+ project.hooks << [project_hook]
+
+ WebMock.stub_request(:post, project_hook.url)
+ end
+
+ context 'when token is defined' do
+ let(:project_hook) { create(:project_hook, :token) }
+
+ it 'POSTs to the webhook URL' do
+ service_instance.execute
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: headers.merge({ 'X-Gitlab-Token' => project_hook.token })
+ ).once
+ end
+ end
+
+ it 'POSTs to the webhook URL' do
+ service_instance.execute
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: headers
+ ).once
+ end
+
+ it 'POSTs the data as JSON' do
+ service_instance.execute
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: headers
+ ).once
+ end
+
+ it 'catches exceptions' do
+ WebMock.stub_request(:post, project_hook.url).to_raise(StandardError.new('Some error'))
+
+ expect { service_instance.execute }.to raise_error(StandardError)
+ end
+
+ it 'handles exceptions' do
+ exceptions = [SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout]
+ exceptions.each do |exception_class|
+ exception = exception_class.new('Exception message')
+
+ WebMock.stub_request(:post, project_hook.url).to_raise(exception)
+ expect(service_instance.execute).to eq([nil, exception.message])
+ expect { service_instance.execute }.not_to raise_error
+ end
+ end
+
+ it 'handles 200 status code' do
+ WebMock.stub_request(:post, project_hook.url).to_return(status: 200, body: 'Success')
+
+ expect(service_instance.execute).to eq([200, 'Success'])
+ end
+
+ it 'handles 2xx status codes' do
+ WebMock.stub_request(:post, project_hook.url).to_return(status: 201, body: 'Success')
+
+ expect(service_instance.execute).to eq([201, 'Success'])
+ end
+
+ context 'execution logging' do
+ let(:hook_log) { project_hook.web_hook_logs.last }
+
+ context 'with success' do
+ before do
+ WebMock.stub_request(:post, project_hook.url).to_return(status: 200, body: 'Success')
+ service_instance.execute
+ end
+
+ it 'log successful execution' do
+ expect(hook_log.trigger).to eq('push_hooks')
+ expect(hook_log.url).to eq(project_hook.url)
+ expect(hook_log.request_headers).to eq(headers)
+ expect(hook_log.response_body).to eq('Success')
+ expect(hook_log.response_status).to eq('200')
+ expect(hook_log.execution_duration).to be > 0
+ expect(hook_log.internal_error_message).to be_nil
+ end
+ end
+
+ context 'with exception' do
+ before do
+ WebMock.stub_request(:post, project_hook.url).to_raise(SocketError.new('Some HTTP Post error'))
+ service_instance.execute
+ end
+
+ it 'log failed execution' do
+ expect(hook_log.trigger).to eq('push_hooks')
+ expect(hook_log.url).to eq(project_hook.url)
+ expect(hook_log.request_headers).to eq(headers)
+ expect(hook_log.response_body).to eq('')
+ expect(hook_log.response_status).to eq('internal error')
+ expect(hook_log.execution_duration).to be > 0
+ expect(hook_log.internal_error_message).to eq('Some HTTP Post error')
+ end
+ end
+
+ context 'should not log ServiceHooks' do
+ let(:service_hook) { create(:service_hook) }
+ let(:service_instance) { WebHookService.new(service_hook, data, 'service_hook') }
+
+ before do
+ WebMock.stub_request(:post, service_hook.url).to_return(status: 200, body: 'Success')
+ end
+
+ it { expect { service_instance.execute }.not_to change(WebHookLog, :count) }
+ end
+ end
+ end
+
+ describe '#async_execute' do
+ let(:system_hook) { create(:system_hook) }
+
+ it 'enqueue WebHookWorker' do
+ expect(Sidekiq::Client).to receive(:enqueue).with(WebHookWorker, project_hook.id, data, 'push_hooks')
+
+ WebHookService.new(project_hook, data, 'push_hooks').async_execute
+ end
+ end
+end
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index c59b30c772d..d6b40db09ce 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -209,9 +209,13 @@ shared_examples 'a GitHub-ish import controller: POST create' do
end
context 'user has chosen a namespace and name for the project' do
- let(:test_namespace) { create(:namespace, name: 'test_namespace', owner: user) }
+ let(:test_namespace) { create(:group, name: 'test_namespace') }
let(:test_name) { 'test_name' }
+ before do
+ test_namespace.add_owner(user)
+ end
+
it 'takes the selected namespace and name' do
expect(Gitlab::GithubImport::ProjectCreator).
to receive(:new).with(provider_repo, test_name, test_namespace, user, access_params, type: provider).
@@ -230,10 +234,14 @@ shared_examples 'a GitHub-ish import controller: POST create' do
end
context 'user has chosen an existing nested namespace and name for the project' do
- let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
- let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
let(:test_name) { 'test_name' }
+ before do
+ nested_namespace.add_owner(user)
+ end
+
it 'takes the selected namespace and name' do
expect(Gitlab::GithubImport::ProjectCreator).
to receive(:new).with(provider_repo, test_name, nested_namespace, user, access_params, type: provider).
@@ -276,7 +284,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
context 'user has chosen existent and non-existent nested namespaces and name for the project' do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
it 'takes the selected namespace and name' do
expect(Gitlab::GithubImport::ProjectCreator).
diff --git a/spec/support/features/rss_shared_examples.rb b/spec/support/features/rss_shared_examples.rb
index 9a3b0a731ad..1cbb4134995 100644
--- a/spec/support/features/rss_shared_examples.rb
+++ b/spec/support/features/rss_shared_examples.rb
@@ -1,23 +1,23 @@
-shared_examples "an autodiscoverable RSS feed with current_user's private token" do
- it "has an RSS autodiscovery link tag with current_user's private token" do
- expect(page).to have_css("link[type*='atom+xml'][href*='private_token=#{Thread.current[:current_user].private_token}']", visible: false)
+shared_examples "an autodiscoverable RSS feed with current_user's RSS token" do
+ it "has an RSS autodiscovery link tag with current_user's RSS token" do
+ expect(page).to have_css("link[type*='atom+xml'][href*='rss_token=#{Thread.current[:current_user].rss_token}']", visible: false)
end
end
-shared_examples "it has an RSS button with current_user's private token" do
- it "shows the RSS button with current_user's private token" do
- expect(page).to have_css("a:has(.fa-rss)[href*='private_token=#{Thread.current[:current_user].private_token}']")
+shared_examples "it has an RSS button with current_user's RSS token" do
+ it "shows the RSS button with current_user's RSS token" do
+ expect(page).to have_css("a:has(.fa-rss)[href*='rss_token=#{Thread.current[:current_user].rss_token}']")
end
end
-shared_examples "an autodiscoverable RSS feed without a private token" do
- it "has an RSS autodiscovery link tag without a private token" do
- expect(page).to have_css("link[type*='atom+xml']:not([href*='private_token'])", visible: false)
+shared_examples "an autodiscoverable RSS feed without an RSS token" do
+ it "has an RSS autodiscovery link tag without an RSS token" do
+ expect(page).to have_css("link[type*='atom+xml']:not([href*='rss_token'])", visible: false)
end
end
-shared_examples "it has an RSS button without a private token" do
- it "shows the RSS button without a private token" do
- expect(page).to have_css("a:has(.fa-rss):not([href*='private_token'])")
+shared_examples "it has an RSS button without an RSS token" do
+ it "shows the RSS button without an RSS token" do
+ expect(page).to have_css("a:has(.fa-rss):not([href*='rss_token'])")
end
end
diff --git a/spec/support/kubernetes_helpers.rb b/spec/support/kubernetes_helpers.rb
index d2a1ded57ff..9280fad4ace 100644
--- a/spec/support/kubernetes_helpers.rb
+++ b/spec/support/kubernetes_helpers.rb
@@ -41,7 +41,7 @@ module KubernetesHelpers
containers.map do |container|
terminal = {
selectors: { pod: pod_name, container: container['name'] },
- url: container_exec_url(service.api_url, service.namespace, pod_name, container['name']),
+ url: container_exec_url(service.api_url, service.actual_namespace, pod_name, container['name']),
subprotocols: ['channel.k8s.io'],
headers: { 'Authorization' => ["Bearer #{service.token}"] },
created_at: DateTime.parse(pod['metadata']['creationTimestamp']),
diff --git a/spec/tasks/tokens_spec.rb b/spec/tasks/tokens_spec.rb
index 19036c7677c..b84137eb365 100644
--- a/spec/tasks/tokens_spec.rb
+++ b/spec/tasks/tokens_spec.rb
@@ -18,4 +18,10 @@ describe 'tokens rake tasks' do
expect { run_rake_task('tokens:reset_all_email') }.to change { user.reload.incoming_email_token }
end
end
+
+ describe 'reset_all_rss task' do
+ it 'invokes create_hooks task' do
+ expect { run_rake_task('tokens:reset_all_rss') }.to change { user.reload.rss_token }
+ end
+ end
end
diff --git a/spec/validators/dynamic_path_validator_spec.rb b/spec/validators/dynamic_path_validator_spec.rb
index 03e23781d1b..5f998e78f07 100644
--- a/spec/validators/dynamic_path_validator_spec.rb
+++ b/spec/validators/dynamic_path_validator_spec.rb
@@ -15,31 +15,31 @@ describe DynamicPathValidator do
end
context 'for group' do
- it 'calls valid_namespace_path?' do
+ it 'calls valid_group_path?' do
group = build(:group, :nested, path: 'activity')
- expect(described_class).to receive(:valid_namespace_path?).with(group.full_path).and_call_original
+ expect(described_class).to receive(:valid_group_path?).with(group.full_path).and_call_original
expect(validator.path_valid_for_record?(group, 'activity')).to be_falsey
end
end
context 'for user' do
- it 'calls valid_namespace_path?' do
+ it 'calls valid_user_path?' do
user = build(:user, username: 'activity')
- expect(described_class).to receive(:valid_namespace_path?).with(user.full_path).and_call_original
+ expect(described_class).to receive(:valid_user_path?).with(user.full_path).and_call_original
expect(validator.path_valid_for_record?(user, 'activity')).to be_truthy
end
end
context 'for user namespace' do
- it 'calls valid_namespace_path?' do
+ it 'calls valid_user_path?' do
user = create(:user, username: 'activity')
namespace = user.namespace
- expect(described_class).to receive(:valid_namespace_path?).with(namespace.full_path).and_call_original
+ expect(described_class).to receive(:valid_user_path?).with(namespace.full_path).and_call_original
expect(validator.path_valid_for_record?(namespace, 'activity')).to be_truthy
end
@@ -52,7 +52,7 @@ describe DynamicPathValidator do
validator.validate_each(group, :path, "Path with spaces, and comma's!")
- expect(group.errors[:path]).to include(Gitlab::Regex.namespace_regex_message)
+ expect(group.errors[:path]).to include(Gitlab::PathRegex.namespace_format_message)
end
it 'adds a message when the path is not in the correct format' do
diff --git a/spec/workers/remove_old_web_hook_logs_worker_spec.rb b/spec/workers/remove_old_web_hook_logs_worker_spec.rb
new file mode 100644
index 00000000000..6d26ba5dfa0
--- /dev/null
+++ b/spec/workers/remove_old_web_hook_logs_worker_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe RemoveOldWebHookLogsWorker do
+ subject { described_class.new }
+
+ describe '#perform' do
+ let!(:week_old_record) { create(:web_hook_log, created_at: Time.now - 1.week) }
+ let!(:three_days_old_record) { create(:web_hook_log, created_at: Time.now - 3.days) }
+ let!(:one_day_old_record) { create(:web_hook_log, created_at: Time.now - 1.day) }
+
+ it 'removes web hook logs older than 2 days' do
+ subject.perform
+
+ expect(WebHookLog.all).to include(one_day_old_record)
+ expect(WebHookLog.all).not_to include(week_old_record, three_days_old_record)
+ end
+ end
+end