summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb55
-rw-r--r--spec/db/production/settings.rb16
-rw-r--r--spec/factories/ci/builds.rb13
-rw-r--r--spec/factories/groups.rb4
-rw-r--r--spec/factories/projects.rb13
-rw-r--r--spec/features/admin/admin_groups_spec.rb2
-rw-r--r--spec/features/admin/admin_projects_spec.rb6
-rw-r--r--spec/features/admin/admin_settings_spec.rb53
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb67
-rw-r--r--spec/features/projects/builds_spec.rb37
-rw-r--r--spec/features/projects/files/creating_a_file_spec.rb44
-rw-r--r--spec/features/security/admin_access_spec.rb2
-rw-r--r--spec/finders/snippets_finder_spec.rb25
-rw-r--r--spec/javascripts/abuse_reports_spec.js.es64
-rw-r--r--spec/javascripts/activities_spec.js.es63
-rw-r--r--spec/javascripts/awards_handler_spec.js13
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js2
-rw-r--r--spec/javascripts/boards/boards_store_spec.js.es69
-rw-r--r--spec/javascripts/boards/issue_spec.js.es65
-rw-r--r--spec/javascripts/boards/list_spec.js.es68
-rw-r--r--spec/javascripts/boards/mock_data.js.es63
-rw-r--r--spec/javascripts/dashboard_spec.js.es63
-rw-r--r--spec/javascripts/datetime_utility_spec.js.es62
-rw-r--r--spec/javascripts/diff_comments_store_spec.js.es65
-rw-r--r--spec/javascripts/fixtures/awards_handler.html.haml52
-rw-r--r--spec/javascripts/fixtures/pipeline_graph.html.haml15
-rw-r--r--spec/javascripts/gl_dropdown_spec.js.es64
-rw-r--r--spec/javascripts/gl_field_errors_spec.js.es63
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_graph_spec.js6
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_util_spec.js4
-rw-r--r--spec/javascripts/graphs/stat_graph_spec.js4
-rw-r--r--spec/javascripts/issue_spec.js5
-rw-r--r--spec/javascripts/labels_issue_sidebar_spec.js.es65
-rw-r--r--spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es643
-rw-r--r--spec/javascripts/line_highlighter_spec.js3
-rw-r--r--spec/javascripts/merge_request_spec.js3
-rw-r--r--spec/javascripts/new_branch_spec.js3
-rw-r--r--spec/javascripts/notes_spec.js4
-rw-r--r--spec/javascripts/pipelines_spec.js.es625
-rw-r--r--spec/javascripts/project_title_spec.js20
-rw-r--r--spec/javascripts/right_sidebar_spec.js3
-rw-r--r--spec/javascripts/shortcuts_issuable_spec.js3
-rw-r--r--spec/javascripts/smart_interval_spec.js.es635
-rw-r--r--spec/javascripts/subbable_resource_spec.js.es63
-rw-r--r--spec/javascripts/u2f/authenticate_spec.js4
-rw-r--r--spec/javascripts/u2f/register_spec.js4
-rw-r--r--spec/javascripts/zen_mode_spec.js5
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb2
-rw-r--r--spec/lib/gitlab/allowable_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/status/build/cancelable_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/status/build/common_spec.rb37
-rw-r--r--spec/lib/gitlab/ci/status/build/factory_spec.rb141
-rw-r--r--spec/lib/gitlab/ci/status/build/play_spec.rb82
-rw-r--r--spec/lib/gitlab/ci/status/build/retryable_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/status/build/stop_spec.rb84
-rw-r--r--spec/lib/gitlab/ci/status/canceled_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/created_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/extended_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/status/factory_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/status/failed_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/pending_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/common_spec.rb33
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/factory_spec.rb9
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/running_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/skipped_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/status/stage/common_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/status/stage/factory_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/status/success_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/routing_spec.rb23
-rw-r--r--spec/lib/mattermost/team_spec.rb19
-rw-r--r--spec/migrations/migrate_process_commit_worker_jobs_spec.rb27
-rw-r--r--spec/models/build_spec.rb110
-rw-r--r--spec/models/ci/pipeline_spec.rb20
-rw-r--r--spec/models/ci/stage_spec.rb4
-rw-r--r--spec/models/commit_status_spec.rb9
-rw-r--r--spec/models/concerns/routable_spec.rb14
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb7
-rw-r--r--spec/models/generic_commit_status_spec.rb16
-rw-r--r--spec/models/group_spec.rb10
-rw-r--r--spec/models/namespace_spec.rb6
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb126
-rw-r--r--spec/models/project_services/slack_service/pipeline_message_spec.rb30
-rw-r--r--spec/models/user_spec.rb11
-rw-r--r--spec/requests/api/branches_spec.rb31
-rw-r--r--spec/requests/api/commits_spec.rb70
-rw-r--r--spec/requests/api/groups_spec.rb22
-rw-r--r--spec/requests/api/helpers_spec.rb (renamed from spec/requests/api/api_helpers_spec.rb)85
-rw-r--r--spec/requests/api/merge_requests_spec.rb16
-rw-r--r--spec/requests/api/services_spec.rb5
-rw-r--r--spec/requests/api/users_spec.rb27
-rw-r--r--spec/routing/admin_routing_spec.rb14
-rw-r--r--spec/serializers/analytics_build_entity_spec.rb8
-rw-r--r--spec/services/system_note_service_spec.rb2
-rw-r--r--spec/support/login_helpers.rb3
-rw-r--r--spec/support/services_shared_context.rb6
-rw-r--r--spec/views/projects/commit/_commit_box.html.haml_spec.rb2
-rw-r--r--spec/views/projects/pipelines/show.html.haml_spec.rb2
100 files changed, 1795 insertions, 290 deletions
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
new file mode 100644
index 00000000000..9fd5c3b85f6
--- /dev/null
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Projects::ReleasesController do
+ let!(:project) { create(:project) }
+ let!(:user) { create(:user) }
+ let!(:release) { create(:release, project: project) }
+ let!(:tag) { release.tag }
+
+ before do
+ project.team << [user, :developer]
+ sign_in(user)
+ end
+
+ describe 'GET #edit' do
+ it 'initializes a new release' do
+ tag_id = release.tag
+ project.releases.destroy_all
+
+ get :edit, namespace_id: project.namespace.path, project_id: project.path, tag_id: tag_id
+
+ release = assigns(:release)
+ expect(release).not_to be_nil
+ expect(release).not_to be_persisted
+ end
+
+ it 'retrieves an existing release' do
+ get :edit, namespace_id: project.namespace.path, project_id: project.path, tag_id: release.tag
+
+ release = assigns(:release)
+ expect(release).not_to be_nil
+ expect(release).to be_persisted
+ end
+ end
+
+ describe 'PUT #update' do
+ it 'updates release note description' do
+ update_release('description updated')
+
+ release = project.releases.find_by_tag(tag)
+ expect(release.description).to eq("description updated")
+ end
+
+ it 'deletes release note when description is null' do
+ expect { update_release('') }.to change(project.releases, :count).by(-1)
+ end
+ end
+
+ def update_release(description)
+ put :update,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ tag_id: release.tag,
+ release: { description: description }
+ end
+end
diff --git a/spec/db/production/settings.rb b/spec/db/production/settings.rb
new file mode 100644
index 00000000000..a7c5283df94
--- /dev/null
+++ b/spec/db/production/settings.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+require 'rainbow/ext/string'
+
+describe 'seed production settings', lib: true do
+ context 'GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN is set in the environment' do
+ before do
+ allow(ENV).to receive(:[]).and_call_original
+ allow(ENV).to receive(:[]).with('GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN').and_return('013456789')
+ end
+
+ it 'writes the token to the database' do
+ load(File.join(__dir__, '../../../db/fixtures/production/010_settings.rb'))
+ expect(ApplicationSetting.current.runners_registration_token).to eq('013456789')
+ end
+ end
+end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index c443af09075..62466c06194 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -12,12 +12,14 @@ FactoryGirl.define do
started_at 'Di 29. Okt 09:51:28 CET 2013'
finished_at 'Di 29. Okt 09:53:28 CET 2013'
commands 'ls -a'
+
options do
{
image: "ruby:2.1",
services: ["postgres"]
}
end
+
yaml_variables do
[
{ key: :DB_NAME, value: 'postgres', public: true }
@@ -60,15 +62,20 @@ FactoryGirl.define do
end
trait :teardown_environment do
- options do
- { environment: { action: 'stop' } }
- end
+ environment 'staging'
+ options environment: { name: 'staging',
+ action: 'stop' }
end
trait :allowed_to_fail do
allow_failure true
end
+ trait :playable do
+ skipped
+ manual
+ end
+
after(:build) do |build, evaluator|
build.project = build.pipeline.project
end
diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb
index ebd3595ea64..ece6beb9fa9 100644
--- a/spec/factories/groups.rb
+++ b/spec/factories/groups.rb
@@ -19,5 +19,9 @@ FactoryGirl.define do
trait :access_requestable do
request_access_enabled true
end
+
+ trait :nested do
+ parent factory: :group
+ end
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 1166498ddff..0d072d6a690 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -133,4 +133,17 @@ FactoryGirl.define do
)
end
end
+
+ factory :kubernetes_project, parent: :empty_project do
+ after :create do |project|
+ project.create_kubernetes_service(
+ active: true,
+ properties: {
+ namespace: project.path,
+ api_url: 'https://kubernetes.example.com/api',
+ token: 'a' * 40,
+ }
+ )
+ end
+ end
end
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index f6d625fa7f6..0aa01fc499a 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -21,7 +21,7 @@ feature 'Admin Groups', feature: true do
scenario 'shows the visibility level radio populated with the group visibility_level value' do
group = create(:group, :private)
- visit edit_admin_group_path(group)
+ visit admin_group_edit_path(group)
expect_selected_visibility(group.visibility_level)
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index 30ded9202a4..a36bfd574cb 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -8,11 +8,11 @@ describe "Admin::Projects", feature: true do
describe "GET /admin/projects" do
before do
- visit admin_namespaces_projects_path
+ visit admin_projects_path
end
it "is ok" do
- expect(current_path).to eq(admin_namespaces_projects_path)
+ expect(current_path).to eq(admin_projects_path)
end
it "has projects list" do
@@ -22,7 +22,7 @@ describe "Admin::Projects", feature: true do
describe "GET /admin/projects/:id" do
before do
- visit admin_namespaces_projects_path
+ visit admin_projects_path
click_link "#{@project.name}"
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
new file mode 100644
index 00000000000..8cd66f189be
--- /dev/null
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+feature 'Admin updates settings', feature: true do
+ before(:each) do
+ login_as :admin
+ visit admin_application_settings_path
+ end
+
+ scenario 'Change application settings' do
+ uncheck 'Gravatar enabled'
+ fill_in 'Home page URL', with: 'https://about.gitlab.com/'
+ fill_in 'Help page text', with: 'Example text'
+ click_button 'Save'
+
+ expect(current_application_settings.gravatar_enabled).to be_falsey
+ expect(current_application_settings.home_page_url).to eq "https://about.gitlab.com/"
+ expect(page).to have_content "Application settings saved successfully"
+ end
+
+ scenario 'Change Slack Service template settings' do
+ click_link 'Service Templates'
+ click_link 'Slack'
+ fill_in 'Webhook', with: 'http://localhost'
+ fill_in 'Username', with: 'test_user'
+ fill_in 'service_push_channel', with: '#test_channel'
+ page.check('Notify only broken builds')
+
+ check_all_events
+ click_on 'Save'
+
+ expect(page).to have_content 'Application settings saved successfully'
+
+ click_link 'Slack'
+
+ page.all('input[type=checkbox]').each do |checkbox|
+ expect(checkbox).to be_checked
+ end
+ expect(find_field('Webhook').value).to eq 'http://localhost'
+ expect(find_field('Username').value).to eq 'test_user'
+ expect(find('#service_push_channel').value).to eq '#test_channel'
+ end
+
+ def check_all_events
+ page.check('Active')
+ page.check('Push')
+ page.check('Tag push')
+ page.check('Note')
+ page.check('Issue')
+ page.check('Merge request')
+ page.check('Build')
+ page.check('Pipeline')
+ end
+end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index 365cb445df1..44dfc2dff45 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -36,7 +36,7 @@ feature 'Tooltips on .timeago dates', feature: true, js: true do
visit user_snippets_path(user)
wait_for_ajax()
- page.find('.js-timeago').hover
+ page.find('.js-timeago.snippet-created-ago').hover
end
it 'has the datetime formated correctly' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index c421da97d76..cd0512a37e6 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -2,8 +2,9 @@ require 'rails_helper'
feature 'GFM autocomplete', feature: true, js: true do
include WaitForAjax
- let(:user) { create(:user) }
+ let(:user) { create(:user, username: 'someone.special') }
let(:project) { create(:project) }
+ let(:label) { create(:label, project: project, title: 'special+') }
let(:issue) { create(:issue, project: project) }
before do
@@ -23,21 +24,69 @@ feature 'GFM autocomplete', feature: true, js: true do
expect(page).to have_selector('.atwho-container')
end
- it 'opens autocomplete menu when field is prefixed with non-text character' do
+ it 'doesnt open autocomplete menu character is prefixed with text' do
page.within '.timeline-content-form' do
- find('#note_note').native.send_keys('')
+ find('#note_note').native.send_keys('testing')
find('#note_note').native.send_keys('@')
end
- expect(page).to have_selector('.atwho-container')
+ expect(page).not_to have_selector('.atwho-view')
end
- it 'doesnt open autocomplete menu character is prefixed with text' do
- page.within '.timeline-content-form' do
- find('#note_note').native.send_keys('testing')
- find('#note_note').native.send_keys('@')
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ note = find('#note_note')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('')
+ note.native.send_keys("~#{label.title[0]}")
+ sleep 1
+ note.click
+ end
+
+ label_item = find('.atwho-view li', text: label.title)
+
+ expect_to_wrap(true, label_item, note, label.title)
end
- expect(page).not_to have_selector('.atwho-view')
+ it 'doesn\'t wrap for assignee values' do
+ note = find('#note_note')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('')
+ note.native.send_keys("@#{user.username[0]}")
+ sleep 1
+ note.click
+ end
+
+ user_item = find('.atwho-view li', text: user.username)
+
+ expect_to_wrap(false, user_item, note, user.username)
+ end
+
+ it 'doesn\'t wrap for emoji values' do
+ note = find('#note_note')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('')
+ note.native.send_keys(":cartwheel")
+ sleep 1
+ note.click
+ end
+
+ emoji_item = find('.atwho-view li', text: 'cartwheel_tone1')
+
+ expect_to_wrap(false, emoji_item, note, 'cartwheel_tone1')
+ end
+
+ def expect_to_wrap(should_wrap, item, note, value)
+ expect(item).to have_content(value)
+ expect(item).not_to have_content("\"#{value}\"")
+
+ item.click
+
+ if should_wrap
+ expect(note.value).to include("\"#{value}\"")
+ else
+ expect(note.value).not_to include("\"#{value}\"")
+ end
+ end
end
end
diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb
index a0ccc472d11..8c4d4320dc5 100644
--- a/spec/features/projects/builds_spec.rb
+++ b/spec/features/projects/builds_spec.rb
@@ -227,6 +227,43 @@ feature 'Builds', :feature do
expect(page).to have_selector('.js-build-value', text: 'TRIGGER_VALUE_1')
end
end
+
+ context 'when build starts environment' do
+ let(:environment) { create(:environment, project: project) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ context 'build is successfull and has deployment' do
+ let(:deployment) { create(:deployment) }
+ let(:build) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) }
+
+ it 'shows a link for the build' do
+ visit namespace_project_build_path(project.namespace, project, build)
+
+ expect(page).to have_link environment.name
+ end
+ end
+
+ context 'build is complete and not successfull' do
+ let(:build) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) }
+
+ it 'shows a link for the build' do
+ visit namespace_project_build_path(project.namespace, project, build)
+
+ expect(page).to have_link environment.name
+ end
+ end
+
+ context 'build creates a new deployment' do
+ let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) }
+ let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) }
+
+ it 'shows a link to lastest deployment' do
+ visit namespace_project_build_path(project.namespace, project, build)
+
+ expect(page).to have_link('latest deployment')
+ end
+ end
+ end
end
describe "POST /:project/builds/:id/cancel" do
diff --git a/spec/features/projects/files/creating_a_file_spec.rb b/spec/features/projects/files/creating_a_file_spec.rb
new file mode 100644
index 00000000000..ae448706130
--- /dev/null
+++ b/spec/features/projects/files/creating_a_file_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+feature 'User wants to create a file', feature: true do
+ include WaitForAjax
+
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ background do
+ project.team << [user, :master]
+ login_as user
+ visit namespace_project_new_blob_path(project.namespace, project, project.default_branch)
+ end
+
+ def submit_new_file(options)
+ file_name = find('#file_name')
+ file_name.set options[:file_name] || 'README.md'
+
+ file_content = find('#file-content')
+ file_content.set options[:file_content] || 'Some content'
+
+ click_button 'Commit Changes'
+ end
+
+ scenario 'file name contains Chinese characters' do
+ submit_new_file(file_name: '测试.md')
+ expect(page).to have_content 'The file has been successfully created.'
+ end
+
+ scenario 'directory name contains Chinese characters' do
+ submit_new_file(file_name: '中文/测试.md')
+ expect(page).to have_content 'The file has been successfully created.'
+ end
+
+ scenario 'file name contains invalid characters' do
+ submit_new_file(file_name: '\\')
+ expect(page).to have_content 'Your changes could not be committed, because the file name can contain only'
+ end
+
+ scenario 'file name contains directory traversal' do
+ submit_new_file(file_name: '../README.md')
+ expect(page).to have_content 'Your changes could not be committed, because the file name cannot include directory traversal.'
+ end
+end
diff --git a/spec/features/security/admin_access_spec.rb b/spec/features/security/admin_access_spec.rb
index fe8cd7b7602..e180ca53eb5 100644
--- a/spec/features/security/admin_access_spec.rb
+++ b/spec/features/security/admin_access_spec.rb
@@ -4,7 +4,7 @@ describe "Admin::Projects", feature: true do
include AccessMatchers
describe "GET /admin/projects" do
- subject { admin_namespaces_projects_path }
+ subject { admin_projects_path }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for :user }
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index 4427443208a..975e99c5807 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -93,16 +93,39 @@ describe SnippetsFinder do
expect(snippets).not_to include(@snippet1, @snippet2)
end
- it "returns public and internal snippets for none project members" do
+ it "returns public and internal snippets for non project members" do
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet2, @snippet3)
expect(snippets).not_to include(@snippet1)
end
+ it "returns public snippets for non project members" do
+ snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_public")
+ expect(snippets).to include(@snippet3)
+ expect(snippets).not_to include(@snippet1, @snippet2)
+ end
+
+ it "returns internal snippets for non project members" do
+ snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_internal")
+ expect(snippets).to include(@snippet2)
+ expect(snippets).not_to include(@snippet1, @snippet3)
+ end
+
+ it "does not return private snippets for non project members" do
+ snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
+ expect(snippets).not_to include(@snippet1, @snippet2, @snippet3)
+ end
+
it "returns all snippets for project members" do
project1.team << [user, :developer]
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet1, @snippet2, @snippet3)
end
+
+ it "returns private snippets for project members" do
+ project1.team << [user, :developer]
+ snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
+ expect(snippets).to include(@snippet1)
+ end
end
end
diff --git a/spec/javascripts/abuse_reports_spec.js.es6 b/spec/javascripts/abuse_reports_spec.js.es6
index a3171353bfb..9e94c9d1d74 100644
--- a/spec/javascripts/abuse_reports_spec.js.es6
+++ b/spec/javascripts/abuse_reports_spec.js.es6
@@ -1,6 +1,6 @@
-/* eslint-disable */
-/*= require abuse_reports */
+/* eslint-disable space-before-function-paren, no-new, padded-blocks */
+/*= require abuse_reports */
/*= require jquery */
((global) => {
diff --git a/spec/javascripts/activities_spec.js.es6 b/spec/javascripts/activities_spec.js.es6
index 8640cd44085..192da4ee8d9 100644
--- a/spec/javascripts/activities_spec.js.es6
+++ b/spec/javascripts/activities_spec.js.es6
@@ -1,4 +1,5 @@
-/* eslint-disable */
+/* eslint-disable no-unused-expressions, comma-spacing, prefer-const, no-prototype-builtins, semi, no-new, keyword-spacing, no-plusplus, no-shadow, max-len */
+
/*= require js.cookie.js */
/*= require jquery.endless-scroll.js */
/*= require pager */
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index ac1404f6e1c..89201c8cb8b 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, no-undef, new-parens, no-unused-vars, quotes, jasmine/no-spec-dupes, prefer-template, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, new-parens, no-unused-vars, quotes, jasmine/no-spec-dupes, prefer-template, padded-blocks, max-len */
+/* global AwardsHandler */
/*= require awards_handler */
/*= require jquery */
@@ -33,9 +34,9 @@
};
describe('AwardsHandler', function() {
- fixture.preload('awards_handler.html');
+ fixture.preload('issues/open-issue.html.raw');
beforeEach(function() {
- fixture.load('awards_handler.html');
+ fixture.load('issues/open-issue.html.raw');
awardsHandler = new AwardsHandler;
spyOn(awardsHandler, 'postEmoji').and.callFake((function(_this) {
return function(url, emoji, cb) {
@@ -113,7 +114,7 @@
});
describe('::getAwardUrl', function() {
return it('should return the url for request', function() {
- return expect(awardsHandler.getAwardUrl()).toBe('/gitlab-org/gitlab-test/issues/8/toggle_award_emoji');
+ return expect(awardsHandler.getAwardUrl()).toBe('http://test.host/frontend-fixtures/issues-project/issues/1/toggle_award_emoji');
});
});
describe('::addAward and ::checkMutuality', function() {
@@ -209,7 +210,7 @@
$('.js-add-award').eq(0).click();
$menu = $('.emoji-menu');
$block = $('.js-awards-block');
- $emoji = $menu.find(".emoji-menu-list-item " + selector);
+ $emoji = $menu.find('.emoji-menu-list:not(.frequent-emojis) ' + selector);
expect($emoji.length).toBe(1);
expect($block.find(selector).length).toBe(0);
$emoji.click();
@@ -224,7 +225,7 @@
openEmojiMenuAndAddEmoji();
$('.js-add-award').eq(0).click();
$block = $('.js-awards-block');
- $emoji = $('.emoji-menu').find(".emoji-menu-list-item " + selector);
+ $emoji = $('.emoji-menu').find(".emoji-menu-list:not(.frequent-emojis) " + selector);
$emoji.click();
return expect($block.find(selector).length).toBe(0);
});
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index efb1203eb2f..0f61000bc37 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable space-before-function-paren, no-var, no-return-assign, comma-dangle, no-undef, jasmine/no-spec-dupes, new-cap, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, no-return-assign, comma-dangle, jasmine/no-spec-dupes, new-cap, padded-blocks, max-len */
/*= require behaviors/quick_submit */
diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6
index b84dfc8197b..b3a1afa28a5 100644
--- a/spec/javascripts/boards/boards_store_spec.js.es6
+++ b/spec/javascripts/boards/boards_store_spec.js.es6
@@ -1,4 +1,11 @@
-/* eslint-disable */
+/* eslint-disable comma-dangle, one-var, no-unused-vars, indent */
+/* global Vue */
+/* global BoardService */
+/* global boardsMockInterceptor */
+/* global Cookies */
+/* global listObj */
+/* global listObjDuplicate */
+
//= require jquery
//= require jquery_ujs
//= require js.cookie
diff --git a/spec/javascripts/boards/issue_spec.js.es6 b/spec/javascripts/boards/issue_spec.js.es6
index 90cb8926545..c8a61a0a9b5 100644
--- a/spec/javascripts/boards/issue_spec.js.es6
+++ b/spec/javascripts/boards/issue_spec.js.es6
@@ -1,4 +1,7 @@
-/* eslint-disable */
+/* eslint-disable comma-dangle */
+/* global BoardService */
+/* global ListIssue */
+
//= require jquery
//= require jquery_ujs
//= require js.cookie
diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6
index dfbcbe3a7c1..7d942ec3d65 100644
--- a/spec/javascripts/boards/list_spec.js.es6
+++ b/spec/javascripts/boards/list_spec.js.es6
@@ -1,4 +1,10 @@
-/* eslint-disable */
+/* eslint-disable comma-dangle */
+/* global Vue */
+/* global boardsMockInterceptor */
+/* global BoardService */
+/* global List */
+/* global listObj */
+
//= require jquery
//= require jquery_ujs
//= require js.cookie
diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6
index fcb3d8f17d8..8d3e2237fda 100644
--- a/spec/javascripts/boards/mock_data.js.es6
+++ b/spec/javascripts/boards/mock_data.js.es6
@@ -1,4 +1,5 @@
-/* eslint-disable */
+/* eslint-disable comma-dangle, no-unused-vars, quote-props */
+
const listObj = {
id: 1,
position: 0,
diff --git a/spec/javascripts/dashboard_spec.js.es6 b/spec/javascripts/dashboard_spec.js.es6
index 93f73fa0e9a..aadf6f518a8 100644
--- a/spec/javascripts/dashboard_spec.js.es6
+++ b/spec/javascripts/dashboard_spec.js.es6
@@ -1,4 +1,5 @@
-/* eslint-disable */
+/* eslint-disable no-new, padded-blocks */
+
/*= require sidebar */
/*= require jquery */
/*= require js.cookie */
diff --git a/spec/javascripts/datetime_utility_spec.js.es6 b/spec/javascripts/datetime_utility_spec.js.es6
index 9fdbab3a9e9..8ece24555c5 100644
--- a/spec/javascripts/datetime_utility_spec.js.es6
+++ b/spec/javascripts/datetime_utility_spec.js.es6
@@ -1,5 +1,5 @@
-/* eslint-disable */
//= require lib/utils/datetime_utility
+
(() => {
describe('Date time utils', () => {
describe('get day name', () => {
diff --git a/spec/javascripts/diff_comments_store_spec.js.es6 b/spec/javascripts/diff_comments_store_spec.js.es6
index 9b2845af608..18805d26ac0 100644
--- a/spec/javascripts/diff_comments_store_spec.js.es6
+++ b/spec/javascripts/diff_comments_store_spec.js.es6
@@ -1,8 +1,11 @@
-/* eslint-disable */
+/* eslint-disable no-extra-semi, jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown, max-len */
+/* global CommentsStore */
+
//= require vue
//= require diff_notes/models/discussion
//= require diff_notes/models/note
//= require diff_notes/stores/comments
+
(() => {
function createDiscussion(noteId = 1, resolved = true) {
CommentsStore.create('a', noteId, true, resolved, 'test');
diff --git a/spec/javascripts/fixtures/awards_handler.html.haml b/spec/javascripts/fixtures/awards_handler.html.haml
deleted file mode 100644
index 1ef2e8f8624..00000000000
--- a/spec/javascripts/fixtures/awards_handler.html.haml
+++ /dev/null
@@ -1,52 +0,0 @@
-.issue-details.issuable-details
- .detail-page-description.content-block
- %h2.title Quibusdam sint officiis earum molestiae ipsa autem voluptatem nisi rem.
- .description.js-task-list-container.is-task-list-enabled
- .wiki
- %p Qui exercitationem magnam optio quae fuga earum odio.
- %textarea.hidden.js-task-list-field Qui exercitationem magnam optio quae fuga earum odio.
- %small.edited-text
- .content-block.content-block-small
- .awards.js-awards-block{"data-award-url" => "/gitlab-org/gitlab-test/issues/8/toggle_award_emoji"}
- %button.award-control.btn.js-emoji-btn{"data-placement" => "bottom", "data-title" => "", :type => "button"}
- .icon.emoji-icon.emoji-1F44D{"data-aliases" => "", "data-emoji" => "thumbsup", "data-unicode-name" => "1F44D", :title => "thumbsup"}
- %span.award-control-text.js-counter 0
- %button.award-control.btn.js-emoji-btn{"data-placement" => "bottom", "data-title" => "", :type => "button"}
- .icon.emoji-icon.emoji-1F44E{"data-aliases" => "", "data-emoji" => "thumbsdown", "data-unicode-name" => "1F44E", :title => "thumbsdown"}
- %span.award-control-text.js-counter 0
- .award-menu-holder.js-award-holder
- %button.btn.award-control.js-add-award{:type => "button"}
- %i.fa.fa-smile-o.award-control-icon.award-control-icon-normal
- %i.fa.fa-spinner.fa-spin.award-control-icon.award-control-icon-loading
- %span.award-control-text Add
- %section.issuable-discussion
- #notes
- %ul#notes-list.notes.main-notes-list.timeline
- %li#note_348.note.note-row-348.timeline-entry{"data-author-id" => "18", "data-editable" => ""}
- .timeline-entry-inner
- .timeline-icon
- %a{:href => "/u/agustin"}
- %img.avatar.s40{:alt => "", :src => "#"}/
- .timeline-content
- .note-header
- %a.author_link{:href => "/u/agustin"}
- %span.author Brenna Stokes
- .inline.note-headline-light
- @agustin commented
- %a{:href => "#note_348"}
- %time 11 days ago
- .note-actions
- %span.note-role Reporter
- %a.note-action-button.note-emoji-button.js-add-award.js-note-emoji{"data-position" => "right", :href => "#", :title => "Award Emoji"}
- %i.fa.fa-spinner.fa-spin
- %i.fa.fa-smile-o.link-highlight
- .js-task-list-container.note-body.is-task-list-enabled
- .note-text
- %p Suscipit sunt quia quisquam sed eveniet ipsam.
- .note-awards
- .awards.hidden.js-awards-block{"data-award-url" => "/gitlab-org/gitlab-test/notes/348/toggle_award_emoji"}
- .award-menu-holder.js-award-holder
- %button.btn.award-control.js-add-award{:type => "button"}
- %i.fa.fa-smile-o.award-control-icon.award-control-icon-normal
- %i.fa.fa-spinner.fa-spin.award-control-icon.award-control-icon-loading
- %span.award-control-text Add
diff --git a/spec/javascripts/fixtures/pipeline_graph.html.haml b/spec/javascripts/fixtures/pipeline_graph.html.haml
new file mode 100644
index 00000000000..deca50ceaa7
--- /dev/null
+++ b/spec/javascripts/fixtures/pipeline_graph.html.haml
@@ -0,0 +1,15 @@
+%div.pipeline-visualization.js-pipeline-graph
+ %ul.stage-column-list
+ %li.stage-column
+ .stage-name
+ %a{:href => "/"}
+ Test
+ .builds-container
+ %ul
+ %li.build
+ .curve
+ .build-content
+ %a
+ %svg
+ .ci-status-text
+ stop_review
diff --git a/spec/javascripts/gl_dropdown_spec.js.es6 b/spec/javascripts/gl_dropdown_spec.js.es6
index 8ba238018cd..bfaf90e2aee 100644
--- a/spec/javascripts/gl_dropdown_spec.js.es6
+++ b/spec/javascripts/gl_dropdown_spec.js.es6
@@ -1,4 +1,6 @@
-/* eslint-disable */
+/* eslint-disable comma-dangle, prefer-const, no-param-reassign, no-plusplus, semi, no-unused-expressions, arrow-spacing, max-len */
+/* global Turbolinks */
+
/*= require jquery */
/*= require gl_dropdown */
/*= require turbolinks */
diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6
index 0713e30e485..5018e87ad6c 100644
--- a/spec/javascripts/gl_field_errors_spec.js.es6
+++ b/spec/javascripts/gl_field_errors_spec.js.es6
@@ -1,4 +1,5 @@
-/* eslint-disable */
+/* eslint-disable space-before-function-paren, arrow-body-style, indent, padded-blocks */
+
//= require jquery
//= require gl_field_errors
diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
index a406e6cc36a..bc5cbeb6a40 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
@@ -1,4 +1,8 @@
-/* eslint-disable quotes, no-undef, indent, semi, object-curly-spacing, jasmine/no-suite-dupes, vars-on-top, no-var, padded-blocks, spaced-comment, max-len */
+/* eslint-disable quotes, indent, semi, object-curly-spacing, jasmine/no-suite-dupes, vars-on-top, no-var, padded-blocks, spaced-comment, max-len */
+/* global d3 */
+/* global ContributorsGraph */
+/* global ContributorsMasterGraph */
+
//= require graphs/stat_graph_contributors_graph
describe("ContributorsGraph", function () {
diff --git a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
index 96f39abe13e..751f3d175e2 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable quotes, padded-blocks, no-var, camelcase, object-curly-spacing, semi, indent, object-property-newline, comma-dangle, comma-spacing, no-undef, spaced-comment, max-len, key-spacing, vars-on-top, quote-props, no-multi-spaces, max-len */
+/* eslint-disable quotes, padded-blocks, no-var, camelcase, object-curly-spacing, semi, indent, object-property-newline, comma-dangle, comma-spacing, spaced-comment, max-len, key-spacing, vars-on-top, quote-props, no-multi-spaces */
+/* global ContributorsStatGraphUtil */
+
//= require graphs/stat_graph_contributors_util
describe("ContributorsStatGraphUtil", function () {
diff --git a/spec/javascripts/graphs/stat_graph_spec.js b/spec/javascripts/graphs/stat_graph_spec.js
index f78573b992b..0da124632ae 100644
--- a/spec/javascripts/graphs/stat_graph_spec.js
+++ b/spec/javascripts/graphs/stat_graph_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable quotes, padded-blocks, no-undef, semi */
+/* eslint-disable quotes, padded-blocks, semi */
+/* global StatGraph */
+
//= require graphs/stat_graph
describe("StatGraph", function () {
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index 14af6644de1..faab5ae00c2 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-use-before-define, indent, no-undef, no-trailing-spaces, comma-dangle, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-use-before-define, indent, no-trailing-spaces, comma-dangle, padded-blocks, max-len */
+/* global Issue */
/*= require lib/utils/text_utility */
/*= require issue */
@@ -70,7 +71,7 @@
$('input[type=checkbox]').attr('checked', true).trigger('change');
expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
});
-
+
it('submits an ajax request on tasklist:changed', function() {
spyOn(jQuery, 'ajax').and.callFake(function(req) {
expect(req.type).toBe('PATCH');
diff --git a/spec/javascripts/labels_issue_sidebar_spec.js.es6 b/spec/javascripts/labels_issue_sidebar_spec.js.es6
index 49687048eb5..0c48d04776f 100644
--- a/spec/javascripts/labels_issue_sidebar_spec.js.es6
+++ b/spec/javascripts/labels_issue_sidebar_spec.js.es6
@@ -1,4 +1,7 @@
-/* eslint-disable */
+/* eslint-disable no-new, no-plusplus, object-curly-spacing, prefer-const, semi */
+/* global IssuableContext */
+/* global LabelsSelect */
+
//= require lib/utils/type_utility
//= require jquery
//= require bootstrap
diff --git a/spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es6 b/spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es6
new file mode 100644
index 00000000000..3645dd70c55
--- /dev/null
+++ b/spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es6
@@ -0,0 +1,43 @@
+//= require lib/utils/custom_event_polyfill
+
+describe('Custom Event Polyfill', () => {
+ it('should be defined', () => {
+ expect(window.CustomEvent).toBeDefined();
+ });
+
+ it('should create a `CustomEvent` instance', () => {
+ const e = new window.CustomEvent('foo');
+
+ expect(e.type).toEqual('foo');
+ expect(e.bubbles).toBe(false);
+ expect(e.cancelable).toBe(false);
+ expect(e.detail).toBeFalsy();
+ });
+
+ it('should create a `CustomEvent` instance with a `details` object', () => {
+ const e = new window.CustomEvent('bar', { detail: { foo: 'bar' } });
+
+ expect(e.type).toEqual('bar');
+ expect(e.bubbles).toBe(false);
+ expect(e.cancelable).toBe(false);
+ expect(e.detail.foo).toEqual('bar');
+ });
+
+ it('should create a `CustomEvent` instance with a `bubbles` boolean', () => {
+ const e = new window.CustomEvent('bar', { bubbles: true });
+
+ expect(e.type).toEqual('bar');
+ expect(e.bubbles).toBe(true);
+ expect(e.cancelable).toBe(false);
+ expect(e.detail).toBeFalsy();
+ });
+
+ it('should create a `CustomEvent` instance with a `cancelable` boolean', () => {
+ const e = new window.CustomEvent('bar', { cancelable: true });
+
+ expect(e.type).toEqual('bar');
+ expect(e.bubbles).toBe(false);
+ expect(e.cancelable).toBe(true);
+ expect(e.detail).toBeFalsy();
+ });
+});
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index b8b174a2e53..decdf583410 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-undef, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, no-plusplus, jasmine/no-spec-dupes, no-underscore-dangle, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, no-plusplus, jasmine/no-spec-dupes, no-underscore-dangle, padded-blocks, max-len */
+/* global LineHighlighter */
/*= require line_highlighter */
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index cbe2634d3a4..4cf1693af1b 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-return-assign, no-undef, padded-blocks */
+/* eslint-disable space-before-function-paren, no-return-assign, padded-blocks */
+/* global MergeRequest */
/*= require merge_request */
diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js
index 8828970d984..a6cb9e47744 100644
--- a/spec/javascripts/new_branch_spec.js
+++ b/spec/javascripts/new_branch_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, no-undef, quotes, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, padded-blocks, max-len */
+/* global NewBranchForm */
/*= require jquery-ui/autocomplete */
/*= require new_branch_form */
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index 2db182d702b..d3bfa7730fa 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable space-before-function-paren, no-unused-expressions, no-undef, no-var, object-shorthand, comma-dangle, semi, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, semi, padded-blocks, max-len */
+/* global Notes */
+
/*= require notes */
/*= require autosize */
/*= require gl_form */
diff --git a/spec/javascripts/pipelines_spec.js.es6 b/spec/javascripts/pipelines_spec.js.es6
new file mode 100644
index 00000000000..85c9cf4b4f1
--- /dev/null
+++ b/spec/javascripts/pipelines_spec.js.es6
@@ -0,0 +1,25 @@
+//= require pipelines
+
+(() => {
+ describe('Pipelines', () => {
+ fixture.preload('pipeline_graph');
+
+ beforeEach(() => {
+ fixture.load('pipeline_graph');
+ });
+
+ it('should be defined', () => {
+ expect(window.gl.Pipelines).toBeDefined();
+ });
+
+ it('should create a `Pipelines` instance without options', () => {
+ expect(() => { new window.gl.Pipelines(); }).not.toThrow(); //eslint-disable-line
+ });
+
+ it('should create a `Pipelines` instance with options', () => {
+ const pipelines = new window.gl.Pipelines({ foo: 'bar' });
+
+ expect(pipelines.pipelineGraph).toBeDefined();
+ });
+ });
+})();
diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js
index 49211a6b852..bb802a4b5e3 100644
--- a/spec/javascripts/project_title_spec.js
+++ b/spec/javascripts/project_title_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-undef, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, jasmine/no-expect-in-setup-teardown, padded-blocks, max-len */
+
+/* global Project */
/*= require bootstrap */
/*= require select2 */
@@ -21,16 +23,18 @@
return this.project = new Project();
});
return describe('project list', function() {
+ var fakeAjaxResponse = function fakeAjaxResponse(req) {
+ var d;
+ expect(req.url).toBe('/api/v3/projects.json?simple=true');
+ d = $.Deferred();
+ d.resolve(this.projects_data);
+ return d.promise();
+ };
+
beforeEach((function(_this) {
return function() {
_this.projects_data = fixture.load('projects.json')[0];
- return spyOn(jQuery, 'ajax').and.callFake(function(req) {
- var d;
- expect(req.url).toBe('/api/v3/projects.json?simple=true');
- d = $.Deferred();
- d.resolve(_this.projects_data);
- return d.promise();
- });
+ return spyOn(jQuery, 'ajax').and.callFake(fakeAjaxResponse.bind(_this));
};
})(this));
it('to show on toggle click', (function(_this) {
diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js
index 0a9bc546144..a083dbf033a 100644
--- a/spec/javascripts/right_sidebar_spec.js
+++ b/spec/javascripts/right_sidebar_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-undef, no-return-assign, new-cap, vars-on-top, semi, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, semi, padded-blocks, max-len */
+/* global Sidebar */
/*= require right_sidebar */
/*= require jquery */
diff --git a/spec/javascripts/shortcuts_issuable_spec.js b/spec/javascripts/shortcuts_issuable_spec.js
index e37816b0a8c..7bc898aed5d 100644
--- a/spec/javascripts/shortcuts_issuable_spec.js
+++ b/spec/javascripts/shortcuts_issuable_spec.js
@@ -1,4 +1,5 @@
-/* eslint-disable space-before-function-paren, no-return-assign, no-undef, no-var, quotes, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-return-assign, no-var, quotes, padded-blocks */
+/* global ShortcutsIssuable */
/*= require shortcuts_issuable */
diff --git a/spec/javascripts/smart_interval_spec.js.es6 b/spec/javascripts/smart_interval_spec.js.es6
index ed6166a25a8..1b7ca97cde4 100644
--- a/spec/javascripts/smart_interval_spec.js.es6
+++ b/spec/javascripts/smart_interval_spec.js.es6
@@ -14,8 +14,9 @@
startingInterval: DEFAULT_STARTING_INTERVAL,
maxInterval: DEFAULT_MAX_INTERVAL,
incrementByFactorOf: DEFAULT_INCREMENT_FACTOR,
- delayStartBy: 0,
lazyStart: false,
+ immediateExecution: false,
+ hiddenInterval: null,
};
if (config) {
@@ -114,14 +115,31 @@
expect(interval.state.intervalId).toBeTruthy();
// simulates triggering of visibilitychange event
- interval.state.pageVisibility = 'hidden';
- interval.handleVisibilityChange();
+ interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
expect(interval.state.intervalId).toBeUndefined();
done();
}, DEFAULT_SHORT_TIMEOUT);
});
+ it('should change to the hidden interval when page is not visible', function (done) {
+ const HIDDEN_INTERVAL = 1500;
+ const interval = createDefaultSmartInterval({ hiddenInterval: HIDDEN_INTERVAL });
+
+ setTimeout(() => {
+ expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
+ interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL).toBeTruthy();
+
+ // simulates triggering of visibilitychange event
+ interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
+
+ expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.getCurrentInterval()).toBe(HIDDEN_INTERVAL);
+ done();
+ }, DEFAULT_SHORT_TIMEOUT);
+ });
+
it('should resume when page is becomes visible at the previous interval', function (done) {
const interval = this.smartInterval;
@@ -129,14 +147,12 @@
expect(interval.state.intervalId).toBeTruthy();
// simulates triggering of visibilitychange event
- interval.state.pageVisibility = 'hidden';
- interval.handleVisibilityChange();
+ interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
expect(interval.state.intervalId).toBeUndefined();
// simulates triggering of visibilitychange event
- interval.state.pageVisibility = 'visible';
- interval.handleVisibilityChange();
+ interval.handleVisibilityChange({ target: { visibilityState: 'visible' } });
expect(interval.state.intervalId).toBeTruthy();
@@ -154,6 +170,11 @@
done();
}, DEFAULT_SHORT_TIMEOUT);
});
+
+ it('should execute callback before first interval', function () {
+ const interval = createDefaultSmartInterval({ immediateExecution: true });
+ expect(interval.cfg.immediateExecution).toBeFalsy();
+ });
});
});
})(window.gl || (window.gl = {}));
diff --git a/spec/javascripts/subbable_resource_spec.js.es6 b/spec/javascripts/subbable_resource_spec.js.es6
index df395296791..6a70dd856a7 100644
--- a/spec/javascripts/subbable_resource_spec.js.es6
+++ b/spec/javascripts/subbable_resource_spec.js.es6
@@ -1,4 +1,5 @@
-/* eslint-disable */
+/* eslint-disable max-len, arrow-parens, comma-dangle, no-plusplus */
+
//= vue
//= vue-resource
//= require jquery
diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js
index 944df6d23f7..a8874ab12d3 100644
--- a/spec/javascripts/u2f/authenticate_spec.js
+++ b/spec/javascripts/u2f/authenticate_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable space-before-function-paren, new-parens, no-undef, quotes, comma-dangle, no-var, one-var, one-var-declaration-per-line, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, new-parens, quotes, comma-dangle, no-var, one-var, one-var-declaration-per-line, padded-blocks, max-len */
+/* global MockU2FDevice */
+/* global U2FAuthenticate */
/*= require u2f/authenticate */
/*= require u2f/util */
diff --git a/spec/javascripts/u2f/register_spec.js b/spec/javascripts/u2f/register_spec.js
index 0c73c5772bd..189592ea87a 100644
--- a/spec/javascripts/u2f/register_spec.js
+++ b/spec/javascripts/u2f/register_spec.js
@@ -1,4 +1,6 @@
-/* eslint-disable space-before-function-paren, new-parens, no-undef, quotes, no-var, one-var, one-var-declaration-per-line, comma-dangle, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, new-parens, quotes, no-var, one-var, one-var-declaration-per-line, comma-dangle, padded-blocks, max-len */
+/* global MockU2FDevice */
+/* global U2FRegister */
/*= require u2f/register */
/*= require u2f/util */
diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js
index b9acaaa5a0d..d80ce5a7f7e 100644
--- a/spec/javascripts/zen_mode_spec.js
+++ b/spec/javascripts/zen_mode_spec.js
@@ -1,4 +1,7 @@
-/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-undef, object-shorthand, comma-dangle, no-return-assign, new-cap, padded-blocks, max-len */
+/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, object-shorthand, comma-dangle, no-return-assign, new-cap, padded-blocks, max-len */
+/* global Dropzone */
+/* global Mousetrap */
+/* global ZenMode */
/*= require zen_mode */
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index 2bfa51deb20..df2dd173b57 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -175,7 +175,7 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
allow_any_instance_of(described_class).to receive(:uri_type).and_return(:raw)
doc = filter(image(escaped))
- expect(doc.at_css('img')['src']).to match '/raw/'
+ expect(doc.at_css('img')['src']).to eq "/#{project_path}/raw/#{Addressable::URI.escape(ref)}/#{escaped}"
end
context 'when requested path is a file in the repo' do
diff --git a/spec/lib/gitlab/allowable_spec.rb b/spec/lib/gitlab/allowable_spec.rb
new file mode 100644
index 00000000000..87733d53e92
--- /dev/null
+++ b/spec/lib/gitlab/allowable_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe Gitlab::Allowable do
+ subject do
+ Class.new.include(described_class).new
+ end
+
+ describe '#can?' do
+ let(:user) { create(:user) }
+
+ context 'when user is allowed to do something' do
+ let(:project) { create(:empty_project, :public) }
+
+ it 'reports correct ability to perform action' do
+ expect(subject.can?(user, :read_project, project)).to be true
+ end
+ end
+
+ context 'when user is not allowed to do something' do
+ let(:project) { create(:empty_project, :private) }
+
+ it 'reports correct ability to perform action' do
+ expect(subject.can?(user, :read_project, project)).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/cancelable_spec.rb b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb
new file mode 100644
index 00000000000..9376bce17a1
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Cancelable do
+ let(:status) { double('core status') }
+ let(:user) { double('user') }
+
+ subject do
+ described_class.new(status)
+ end
+
+ describe '#text' do
+ it 'does not override status text' do
+ expect(status).to receive(:text)
+
+ subject.text
+ end
+ end
+
+ describe '#icon' do
+ it 'does not override status icon' do
+ expect(status).to receive(:icon)
+
+ subject.icon
+ end
+ end
+
+ describe '#label' do
+ it 'does not override status label' do
+ expect(status).to receive(:label)
+
+ subject.label
+ end
+ end
+
+ describe 'action details' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ describe '#has_action?' do
+ context 'when user is allowed to update build' do
+ before { build.project.team << [user, :developer] }
+
+ it { is_expected.to have_action }
+ end
+
+ context 'when user is not allowed to update build' do
+ it { is_expected.not_to have_action }
+ end
+ end
+
+ describe '#action_path' do
+ it { expect(subject.action_path).to include "#{build.id}/cancel" }
+ end
+
+ describe '#action_icon' do
+ it { expect(subject.action_icon).to eq 'ban' }
+ end
+
+ describe '#action_title' do
+ it { expect(subject.action_title).to eq 'Cancel' }
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is cancelable' do
+ let(:build) do
+ create(:ci_build, :running)
+ end
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when build is not cancelable' do
+ let(:build) { create(:ci_build, :success) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/common_spec.rb b/spec/lib/gitlab/ci/status/build/common_spec.rb
new file mode 100644
index 00000000000..40b96b1807b
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/common_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Common do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:project) { build.project }
+
+ subject do
+ Gitlab::Ci::Status::Core
+ .new(build, user)
+ .extend(described_class)
+ end
+
+ describe '#has_action?' do
+ it { is_expected.not_to have_action }
+ end
+
+ describe '#has_details?' do
+ context 'when user has access to read build' do
+ before { project.team << [user, :developer] }
+
+ it { is_expected.to have_details }
+ end
+
+ context 'when user does not have access to read build' do
+ before { project.update(public_builds: false) }
+
+ it { is_expected.not_to have_details }
+ end
+ end
+
+ describe '#details_path' do
+ it 'links to the build details page' do
+ expect(subject.details_path).to include "builds/#{build.id}"
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb
new file mode 100644
index 00000000000..dccb29b5ef6
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb
@@ -0,0 +1,141 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Factory do
+ let(:user) { create(:user) }
+ let(:project) { build.project }
+
+ subject { described_class.new(build, user) }
+ let(:status) { subject.fabricate! }
+
+ before { project.team << [user, :developer] }
+
+ context 'when build is successful' do
+ let(:build) { create(:ci_build, :success) }
+
+ it 'fabricates a retryable build status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'passed'
+ expect(status.icon).to eq 'icon_status_success'
+ expect(status.label).to eq 'passed'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is failed' do
+ let(:build) { create(:ci_build, :failed) }
+
+ it 'fabricates a retryable build status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'failed'
+ expect(status.icon).to eq 'icon_status_failed'
+ expect(status.label).to eq 'failed'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is a canceled' do
+ let(:build) { create(:ci_build, :canceled) }
+
+ it 'fabricates a retryable build status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'canceled'
+ expect(status.icon).to eq 'icon_status_canceled'
+ expect(status.label).to eq 'canceled'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is running' do
+ let(:build) { create(:ci_build, :running) }
+
+ it 'fabricates a canceable build status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'running'
+ expect(status.icon).to eq 'icon_status_running'
+ expect(status.label).to eq 'running'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is pending' do
+ let(:build) { create(:ci_build, :pending) }
+
+ it 'fabricates a cancelable build status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'pending'
+ expect(status.icon).to eq 'icon_status_pending'
+ expect(status.label).to eq 'pending'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is skipped' do
+ let(:build) { create(:ci_build, :skipped) }
+
+ it 'fabricates a core skipped status' do
+ expect(status).to be_a Gitlab::Ci::Status::Skipped
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'skipped'
+ expect(status.icon).to eq 'icon_status_skipped'
+ expect(status.label).to eq 'skipped'
+ expect(status).to have_details
+ expect(status).not_to have_action
+ end
+ end
+
+ context 'when build is a manual action' do
+ context 'when build is a play action' do
+ let(:build) { create(:ci_build, :playable) }
+
+ it 'fabricates a core skipped status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Play
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'manual'
+ expect(status.icon).to eq 'icon_status_manual'
+ expect(status.label).to eq 'manual play action'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+
+ context 'when build is an environment stop action' do
+ let(:build) { create(:ci_build, :playable, :teardown_environment) }
+
+ it 'fabricates a core skipped status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Stop
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'manual'
+ expect(status.icon).to eq 'icon_status_manual'
+ expect(status.label).to eq 'manual stop action'
+ expect(status).to have_details
+ expect(status).to have_action
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/play_spec.rb b/spec/lib/gitlab/ci/status/build/play_spec.rb
new file mode 100644
index 00000000000..4ddf04a8e11
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/play_spec.rb
@@ -0,0 +1,82 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Play do
+ let(:status) { double('core') }
+ let(:user) { double('user') }
+
+ subject { described_class.new(status) }
+
+ describe '#text' do
+ it { expect(subject.text).to eq 'manual' }
+ end
+
+ describe '#label' do
+ it { expect(subject.label).to eq 'manual play action' }
+ end
+
+ describe '#icon' do
+ it { expect(subject.icon).to eq 'icon_status_manual' }
+ end
+
+ describe 'action details' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ describe '#has_action?' do
+ context 'when user is allowed to update build' do
+ before { build.project.team << [user, :developer] }
+
+ it { is_expected.to have_action }
+ end
+
+ context 'when user is not allowed to update build' do
+ it { is_expected.not_to have_action }
+ end
+ end
+
+ describe '#action_path' do
+ it { expect(subject.action_path).to include "#{build.id}/play" }
+ end
+
+ describe '#action_icon' do
+ it { expect(subject.action_icon).to eq 'play' }
+ end
+
+ describe '#action_title' do
+ it { expect(subject.action_title).to eq 'Play' }
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is playable' do
+ context 'when build stops an environment' do
+ let(:build) do
+ create(:ci_build, :playable, :teardown_environment)
+ end
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+
+ context 'when build does not stop an environment' do
+ let(:build) { create(:ci_build, :playable) }
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+ end
+
+ context 'when build is not playable' do
+ let(:build) { create(:ci_build) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/retryable_spec.rb b/spec/lib/gitlab/ci/status/build/retryable_spec.rb
new file mode 100644
index 00000000000..d61e5bbaa6b
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/retryable_spec.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Retryable do
+ let(:status) { double('core status') }
+ let(:user) { double('user') }
+
+ subject do
+ described_class.new(status)
+ end
+
+ describe '#text' do
+ it 'does not override status text' do
+ expect(status).to receive(:text)
+
+ subject.text
+ end
+ end
+
+ describe '#icon' do
+ it 'does not override status icon' do
+ expect(status).to receive(:icon)
+
+ subject.icon
+ end
+ end
+
+ describe '#label' do
+ it 'does not override status label' do
+ expect(status).to receive(:label)
+
+ subject.label
+ end
+ end
+
+ describe 'action details' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ describe '#has_action?' do
+ context 'when user is allowed to update build' do
+ before { build.project.team << [user, :developer] }
+
+ it { is_expected.to have_action }
+ end
+
+ context 'when user is not allowed to update build' do
+ it { is_expected.not_to have_action }
+ end
+ end
+
+ describe '#action_path' do
+ it { expect(subject.action_path).to include "#{build.id}/retry" }
+ end
+
+ describe '#action_icon' do
+ it { expect(subject.action_icon).to eq 'refresh' }
+ end
+
+ describe '#action_title' do
+ it { expect(subject.action_title).to eq 'Retry' }
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is retryable' do
+ let(:build) do
+ create(:ci_build, :success)
+ end
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when build is not retryable' do
+ let(:build) { create(:ci_build, :running) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/stop_spec.rb b/spec/lib/gitlab/ci/status/build/stop_spec.rb
new file mode 100644
index 00000000000..59a85b55f90
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/stop_spec.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Stop do
+ let(:status) { double('core status') }
+ let(:user) { double('user') }
+
+ subject do
+ described_class.new(status)
+ end
+
+ describe '#text' do
+ it { expect(subject.text).to eq 'manual' }
+ end
+
+ describe '#label' do
+ it { expect(subject.label).to eq 'manual stop action' }
+ end
+
+ describe '#icon' do
+ it { expect(subject.icon).to eq 'icon_status_manual' }
+ end
+
+ describe 'action details' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ describe '#has_action?' do
+ context 'when user is allowed to update build' do
+ before { build.project.team << [user, :developer] }
+
+ it { is_expected.to have_action }
+ end
+
+ context 'when user is not allowed to update build' do
+ it { is_expected.not_to have_action }
+ end
+ end
+
+ describe '#action_path' do
+ it { expect(subject.action_path).to include "#{build.id}/play" }
+ end
+
+ describe '#action_icon' do
+ it { expect(subject.action_icon).to eq 'stop' }
+ end
+
+ describe '#action_title' do
+ it { expect(subject.action_title).to eq 'Stop' }
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is playable' do
+ context 'when build stops an environment' do
+ let(:build) do
+ create(:ci_build, :playable, :teardown_environment)
+ end
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when build does not stop an environment' do
+ let(:build) { create(:ci_build, :playable) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+
+ context 'when build is not playable' do
+ let(:build) { create(:ci_build) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/canceled_spec.rb b/spec/lib/gitlab/ci/status/canceled_spec.rb
index 619ecbcba67..4639278ad45 100644
--- a/spec/lib/gitlab/ci/status/canceled_spec.rb
+++ b/spec/lib/gitlab/ci/status/canceled_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Canceled do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'canceled' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Canceled do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_canceled' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: canceled' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/created_spec.rb b/spec/lib/gitlab/ci/status/created_spec.rb
index 157302c65a8..2ce176a29d6 100644
--- a/spec/lib/gitlab/ci/status/created_spec.rb
+++ b/spec/lib/gitlab/ci/status/created_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Created do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'created' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Created do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_created' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: created' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/extended_spec.rb b/spec/lib/gitlab/ci/status/extended_spec.rb
index 120e121aae5..c2d74ca5cde 100644
--- a/spec/lib/gitlab/ci/status/extended_spec.rb
+++ b/spec/lib/gitlab/ci/status/extended_spec.rb
@@ -2,11 +2,11 @@ require 'spec_helper'
describe Gitlab::Ci::Status::Extended do
subject do
- Class.new.extend(described_class)
+ Class.new.include(described_class)
end
it 'requires subclass to implement matcher' do
- expect { subject.matches?(double) }
+ expect { subject.matches?(double, double) }
.to raise_error(NotImplementedError)
end
end
diff --git a/spec/lib/gitlab/ci/status/factory_spec.rb b/spec/lib/gitlab/ci/status/factory_spec.rb
index d5bd7f7102b..f92a1c149bf 100644
--- a/spec/lib/gitlab/ci/status/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/factory_spec.rb
@@ -2,15 +2,17 @@ require 'spec_helper'
describe Gitlab::Ci::Status::Factory do
subject do
- described_class.new(object)
+ described_class.new(resource, user)
end
+ let(:user) { create(:user) }
+
let(:status) { subject.fabricate! }
context 'when object has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
- let(:object) { double(status: core_status) }
+ let(:resource) { double(status: core_status) }
it "fabricates a core status #{core_status}" do
expect(status).to be_a(
diff --git a/spec/lib/gitlab/ci/status/failed_spec.rb b/spec/lib/gitlab/ci/status/failed_spec.rb
index 0b3cb8168e6..9d527e6a7ef 100644
--- a/spec/lib/gitlab/ci/status/failed_spec.rb
+++ b/spec/lib/gitlab/ci/status/failed_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Failed do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'failed' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Failed do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_failed' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: failed' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/pending_spec.rb b/spec/lib/gitlab/ci/status/pending_spec.rb
index 57c901c1202..d03f595d3c7 100644
--- a/spec/lib/gitlab/ci/status/pending_spec.rb
+++ b/spec/lib/gitlab/ci/status/pending_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Pending do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'pending' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Pending do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_pending' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: pending' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/pipeline/common_spec.rb b/spec/lib/gitlab/ci/status/pipeline/common_spec.rb
index 21adee3f8e7..d665674bf70 100644
--- a/spec/lib/gitlab/ci/status/pipeline/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/pipeline/common_spec.rb
@@ -1,23 +1,36 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Pipeline::Common do
- let(:pipeline) { create(:ci_pipeline) }
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project, :private) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
subject do
- Class.new(Gitlab::Ci::Status::Core)
- .new(pipeline).extend(described_class)
+ Gitlab::Ci::Status::Core
+ .new(pipeline, user)
+ .extend(described_class)
end
- it 'does not have action' do
- expect(subject).not_to have_action
+ describe '#has_action?' do
+ it { is_expected.not_to have_action }
end
- it 'has details' do
- expect(subject).to have_details
+ describe '#has_details?' do
+ context 'when user has access to read pipeline' do
+ before { project.team << [user, :developer] }
+
+ it { is_expected.to have_details }
+ end
+
+ context 'when user does not have access to read pipeline' do
+ it { is_expected.not_to have_details }
+ end
end
- it 'links to the pipeline details page' do
- expect(subject.details_path)
- .to include "pipelines/#{pipeline.id}"
+ describe '#details_path' do
+ it 'links to the pipeline details page' do
+ expect(subject.details_path)
+ .to include "pipelines/#{pipeline.id}"
+ end
end
end
diff --git a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
index d6243940f2e..d4a2dc7fcc1 100644
--- a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
@@ -1,14 +1,21 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Pipeline::Factory do
+ let(:user) { create(:user) }
+ let(:project) { pipeline.project }
+
subject do
- described_class.new(pipeline)
+ described_class.new(pipeline, user)
end
let(:status) do
subject.fabricate!
end
+ before do
+ project.team << [user, :developer]
+ end
+
context 'when pipeline has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
diff --git a/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb b/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb
index 02e526e3de2..7e3383c307f 100644
--- a/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb
+++ b/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb
@@ -29,13 +29,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
end
it 'is a correct match' do
- expect(described_class.matches?(pipeline)).to eq true
+ expect(described_class.matches?(pipeline, double)).to eq true
end
end
context 'when pipeline does not have warnings' do
it 'does not match' do
- expect(described_class.matches?(pipeline)).to eq false
+ expect(described_class.matches?(pipeline, double)).to eq false
end
end
end
@@ -51,13 +51,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
end
it 'does not match' do
- expect(described_class.matches?(pipeline)).to eq false
+ expect(described_class.matches?(pipeline, double)).to eq false
end
end
context 'when pipeline does not have warnings' do
it 'does not match' do
- expect(described_class.matches?(pipeline)).to eq false
+ expect(described_class.matches?(pipeline, double)).to eq false
end
end
end
diff --git a/spec/lib/gitlab/ci/status/running_spec.rb b/spec/lib/gitlab/ci/status/running_spec.rb
index c023f1872cc..9f47090d396 100644
--- a/spec/lib/gitlab/ci/status/running_spec.rb
+++ b/spec/lib/gitlab/ci/status/running_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Running do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'running' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Running do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_running' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: running' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/skipped_spec.rb b/spec/lib/gitlab/ci/status/skipped_spec.rb
index d4f7f4b3b70..94601648a8d 100644
--- a/spec/lib/gitlab/ci/status/skipped_spec.rb
+++ b/spec/lib/gitlab/ci/status/skipped_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Skipped do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'skipped' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Skipped do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_skipped' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: skipped' }
- end
end
diff --git a/spec/lib/gitlab/ci/status/stage/common_spec.rb b/spec/lib/gitlab/ci/status/stage/common_spec.rb
index f3259c6f23e..8814a7614a0 100644
--- a/spec/lib/gitlab/ci/status/stage/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/stage/common_spec.rb
@@ -1,26 +1,43 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Stage::Common do
- let(:pipeline) { create(:ci_empty_pipeline) }
- let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+
+ let(:stage) do
+ build(:ci_stage, pipeline: pipeline, name: 'test')
+ end
subject do
Class.new(Gitlab::Ci::Status::Core)
- .new(stage).extend(described_class)
+ .new(stage, user).extend(described_class)
end
it 'does not have action' do
expect(subject).not_to have_action
end
- it 'has details' do
- expect(subject).to have_details
- end
-
it 'links to the pipeline details page' do
expect(subject.details_path)
.to include "pipelines/#{pipeline.id}"
expect(subject.details_path)
.to include "##{stage.name}"
end
+
+ context 'when user has permission to read pipeline' do
+ before do
+ project.team << [user, :master]
+ end
+
+ it 'has details' do
+ expect(subject).to have_details
+ end
+ end
+
+ context 'when user does not have permission to read pipeline' do
+ it 'does not have details' do
+ expect(subject).not_to have_details
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/status/stage/factory_spec.rb b/spec/lib/gitlab/ci/status/stage/factory_spec.rb
index 17929665c83..6f8721d30c2 100644
--- a/spec/lib/gitlab/ci/status/stage/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/stage/factory_spec.rb
@@ -1,17 +1,26 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Stage::Factory do
- let(:pipeline) { create(:ci_empty_pipeline) }
- let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+
+ let(:stage) do
+ build(:ci_stage, pipeline: pipeline, name: 'test')
+ end
subject do
- described_class.new(stage)
+ described_class.new(stage, user)
end
let(:status) do
subject.fabricate!
end
+ before do
+ project.team << [user, :developer]
+ end
+
context 'when stage has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
diff --git a/spec/lib/gitlab/ci/status/success_spec.rb b/spec/lib/gitlab/ci/status/success_spec.rb
index 9e261a3aa5f..90f9f615e0d 100644
--- a/spec/lib/gitlab/ci/status/success_spec.rb
+++ b/spec/lib/gitlab/ci/status/success_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Success do
- subject { described_class.new(double('subject')) }
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
describe '#text' do
it { expect(subject.label).to eq 'passed' }
@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Success do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_success' }
end
-
- describe '#title' do
- it { expect(subject.title).to eq 'Double: passed' }
- end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 8e1a28f2723..c4ee838b7c9 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -147,6 +147,7 @@ project:
- bugzilla_service
- gitlab_issue_tracker_service
- external_wiki_service
+- kubernetes_service
- forked_project_link
- forked_from_project
- forked_project_links
diff --git a/spec/lib/gitlab/routing_spec.rb b/spec/lib/gitlab/routing_spec.rb
new file mode 100644
index 00000000000..01d5acfc15b
--- /dev/null
+++ b/spec/lib/gitlab/routing_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::Routing do
+ context 'when module is included' do
+ subject do
+ Class.new.include(described_class).new
+ end
+
+ it 'makes it possible to access url helpers' do
+ expect(subject).to respond_to(:namespace_project_path)
+ end
+ end
+
+ context 'when module is not included' do
+ subject do
+ Class.new.include(described_class.url_helpers).new
+ end
+
+ it 'exposes url helpers module through a method' do
+ expect(subject).to respond_to(:namespace_project_path)
+ end
+ end
+end
diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb
new file mode 100644
index 00000000000..a3b0831659f
--- /dev/null
+++ b/spec/lib/mattermost/team_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe Mattermost::Team do
+ let(:session) { Mattermost::Session.new('http://localhost:8065/', nil) }
+
+ describe '.all' do
+ let(:result) { {id: 'abc', display_name: 'team'} }
+ before do
+ WebMock.stub_request(:get, 'http://localhost:8065/api/v3/teams/all').
+ and_return({ abc: result }.to_json)
+ end
+
+ xit 'gets the teams' do
+ allow(session).to receive(:with_session) { yield }
+
+ expect(described_class.all).to eq(result)
+ end
+ end
+end
diff --git a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
index 52428547a9f..6a93deb5412 100644
--- a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
+++ b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
@@ -1,3 +1,5 @@
+# encoding: utf-8
+
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_worker_jobs.rb')
@@ -59,6 +61,10 @@ describe MigrateProcessCommitWorkerJobs do
Sidekiq.redis { |r| r.llen('queue:process_commit') }
end
+ def pop_job
+ JSON.load(Sidekiq.redis { |r| r.lpop('queue:process_commit') })
+ end
+
before do
Sidekiq.redis do |redis|
job = JSON.dump(args: [project.id, user.id, commit.oid])
@@ -92,11 +98,28 @@ describe MigrateProcessCommitWorkerJobs do
expect(job_count).to eq(1)
end
+ it 'encodes data to UTF-8' do
+ allow_any_instance_of(Rugged::Repository).to receive(:lookup).
+ with(commit.oid).
+ and_return(commit)
+
+ allow(commit).to receive(:message).
+ and_return('김치'.force_encoding('BINARY'))
+
+ migration.up
+
+ job = pop_job
+
+ # We don't care so much about what is being stored, instead we just want
+ # to make sure the encoding is right so that JSON encoding the data
+ # doesn't produce any errors.
+ expect(job['args'][2]['message'].encoding).to eq(Encoding::UTF_8)
+ end
+
context 'a migrated job' do
let(:job) do
migration.up
-
- JSON.load(Sidekiq.redis { |r| r.lpop('queue:process_commit') })
+ pop_job
end
let(:commit_hash) do
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index d4970e38f7c..ea60c17a58a 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -254,6 +254,24 @@ describe Ci::Build, models: true do
end
end
+ describe '#ref_slug' do
+ {
+ 'master' => 'master',
+ '1-foo' => '1-foo',
+ 'fix/1-foo' => 'fix-1-foo',
+ 'fix-1-foo' => 'fix-1-foo',
+ 'a' * 63 => 'a' * 63,
+ 'a' * 64 => 'a' * 63,
+ 'FOO' => 'foo',
+ }.each do |ref, slug|
+ it "transforms #{ref} to #{slug}" do
+ build.ref = ref
+
+ expect(build.ref_slug).to eq(slug)
+ end
+ end
+ end
+
describe '#variables' do
let(:container_registry_enabled) { false }
let(:predefined_variables) do
@@ -265,6 +283,7 @@ describe Ci::Build, models: true do
{ key: 'CI_BUILD_REF', value: build.sha, public: true },
{ key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
{ key: 'CI_BUILD_REF_NAME', value: 'master', public: true },
+ { key: 'CI_BUILD_REF_SLUG', value: 'master', public: true },
{ key: 'CI_BUILD_NAME', value: 'test', public: true },
{ key: 'CI_BUILD_STAGE', value: 'test', public: true },
{ key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
@@ -899,21 +918,87 @@ describe Ci::Build, models: true do
end
end
+ describe '#cancelable?' do
+ subject { build }
+
+ context 'when build is cancelable' do
+ context 'when build is pending' do
+ it { is_expected.to be_cancelable }
+ end
+
+ context 'when build is running' do
+ before do
+ build.run!
+ end
+
+ it { is_expected.to be_cancelable }
+ end
+ end
+
+ context 'when build is not cancelable' do
+ context 'when build is successful' do
+ before do
+ build.success!
+ end
+
+ it { is_expected.not_to be_cancelable }
+ end
+
+ context 'when build is failed' do
+ before do
+ build.drop!
+ end
+
+ it { is_expected.not_to be_cancelable }
+ end
+ end
+ end
+
describe '#retryable?' do
- context 'when build is running' do
- before do
- build.run!
+ subject { build }
+
+ context 'when build is retryable' do
+ context 'when build is successful' do
+ before do
+ build.success!
+ end
+
+ it { is_expected.to be_retryable }
+ end
+
+ context 'when build is failed' do
+ before do
+ build.drop!
+ end
+
+ it { is_expected.to be_retryable }
end
- it { expect(build).not_to be_retryable }
+ context 'when build is canceled' do
+ before do
+ build.cancel!
+ end
+
+ it { is_expected.to be_retryable }
+ end
end
- context 'when build is finished' do
- before do
- build.success!
+ context 'when build is not retryable' do
+ context 'when build is running' do
+ before do
+ build.run!
+ end
+
+ it { is_expected.not_to be_retryable }
end
- it { expect(build).to be_retryable }
+ context 'when build is skipped' do
+ before do
+ build.skip!
+ end
+
+ it { is_expected.not_to be_retryable }
+ end
end
end
@@ -1180,4 +1265,13 @@ describe Ci::Build, models: true do
it { is_expected.to eq('review/master') }
end
end
+
+ describe '#detailed_status' do
+ let(:user) { create(:user) }
+
+ it 'returns a detailed status' do
+ expect(build.detailed_status(user))
+ .to be_a Gitlab::Ci::Status::Build::Cancelable
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 8158e71dd55..e78ae14b737 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -442,11 +442,15 @@ describe Ci::Pipeline, models: true do
end
describe '#detailed_status' do
+ let(:user) { create(:user) }
+
+ subject { pipeline.detailed_status(user) }
+
context 'when pipeline is created' do
let(:pipeline) { create(:ci_pipeline, status: :created) }
it 'returns detailed status for created pipeline' do
- expect(pipeline.detailed_status.text).to eq 'created'
+ expect(subject.text).to eq 'created'
end
end
@@ -454,7 +458,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :pending) }
it 'returns detailed status for pending pipeline' do
- expect(pipeline.detailed_status.text).to eq 'pending'
+ expect(subject.text).to eq 'pending'
end
end
@@ -462,7 +466,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :running) }
it 'returns detailed status for running pipeline' do
- expect(pipeline.detailed_status.text).to eq 'running'
+ expect(subject.text).to eq 'running'
end
end
@@ -470,7 +474,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :success) }
it 'returns detailed status for successful pipeline' do
- expect(pipeline.detailed_status.text).to eq 'passed'
+ expect(subject.text).to eq 'passed'
end
end
@@ -478,7 +482,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :failed) }
it 'returns detailed status for failed pipeline' do
- expect(pipeline.detailed_status.text).to eq 'failed'
+ expect(subject.text).to eq 'failed'
end
end
@@ -486,7 +490,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :canceled) }
it 'returns detailed status for canceled pipeline' do
- expect(pipeline.detailed_status.text).to eq 'canceled'
+ expect(subject.text).to eq 'canceled'
end
end
@@ -494,7 +498,7 @@ describe Ci::Pipeline, models: true do
let(:pipeline) { create(:ci_pipeline, status: :skipped) }
it 'returns detailed status for skipped pipeline' do
- expect(pipeline.detailed_status.text).to eq 'skipped'
+ expect(subject.text).to eq 'skipped'
end
end
@@ -506,7 +510,7 @@ describe Ci::Pipeline, models: true do
end
it 'retruns detailed status for successful pipeline with warnings' do
- expect(pipeline.detailed_status.label).to eq 'passed with warnings'
+ expect(subject.label).to eq 'passed with warnings'
end
end
end
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index f232761dba2..8fff38f7cda 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -68,7 +68,9 @@ describe Ci::Stage, models: true do
end
describe '#detailed_status' do
- subject { stage.detailed_status }
+ let(:user) { create(:user) }
+
+ subject { stage.detailed_status(user) }
context 'when build is created' do
let!(:stage_build) { create_job(:ci_build, status: :created) }
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 1ec08c2a9d0..701f3323c0f 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -234,4 +234,13 @@ describe CommitStatus, models: true do
end
end
end
+
+ describe '#detailed_status' do
+ let(:user) { create(:user) }
+
+ it 'returns a detailed status' do
+ expect(commit_status.detailed_status(user))
+ .to be_a Gitlab::Ci::Status::Success
+ end
+ end
end
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index 0acefc0c1d5..b556135532f 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -3,6 +3,10 @@ require 'spec_helper'
describe Group, 'Routable' do
let!(:group) { create(:group) }
+ describe 'Validations' do
+ it { is_expected.to validate_presence_of(:route) }
+ end
+
describe 'Associations' do
it { is_expected.to have_one(:route).dependent(:destroy) }
end
@@ -35,16 +39,16 @@ describe Group, 'Routable' do
it { expect(described_class.find_by_full_path('unknown')).to eq(nil) }
end
- describe '.where_paths_in' do
+ describe '.where_full_path_in' do
context 'without any paths' do
it 'returns an empty relation' do
- expect(described_class.where_paths_in([])).to eq([])
+ expect(described_class.where_full_path_in([])).to eq([])
end
end
context 'without any valid paths' do
it 'returns an empty relation' do
- expect(described_class.where_paths_in(%w[unknown])).to eq([])
+ expect(described_class.where_full_path_in(%w[unknown])).to eq([])
end
end
@@ -52,13 +56,13 @@ describe Group, 'Routable' do
let!(:nested_group) { create(:group, parent: group) }
it 'returns the projects matching the paths' do
- result = described_class.where_paths_in([group.to_param, nested_group.to_param])
+ result = described_class.where_full_path_in([group.to_param, nested_group.to_param])
expect(result).to contain_exactly(group, nested_group)
end
it 'returns projects regardless of the casing of paths' do
- result = described_class.where_paths_in([group.to_param.upcase, nested_group.to_param.upcase])
+ result = described_class.where_full_path_in([group.to_param.upcase, nested_group.to_param.upcase])
expect(result).to contain_exactly(group, nested_group)
end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index eb64f3d0c83..4b0bfa43abf 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -6,6 +6,7 @@ shared_examples 'TokenAuthenticatable' do
it { expect(described_class).to be_private_method_defined(:write_new_token) }
it { expect(described_class).to respond_to("find_by_#{token_field}") }
it { is_expected.to respond_to("ensure_#{token_field}") }
+ it { is_expected.to respond_to("set_#{token_field}") }
it { is_expected.to respond_to("reset_#{token_field}!") }
end
end
@@ -55,6 +56,12 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
end
end
+ describe 'setting new token' do
+ subject { described_class.new.send("set_#{token_field}", '0123456789') }
+
+ it { is_expected.to eq '0123456789' }
+ end
+
describe 'multiple token fields' do
before do
described_class.send(:add_authentication_token_field, :yet_another_token)
diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb
index 615cfe3142b..6004bfdb7b7 100644
--- a/spec/models/generic_commit_status_spec.rb
+++ b/spec/models/generic_commit_status_spec.rb
@@ -1,8 +1,11 @@
require 'spec_helper'
describe GenericCommitStatus, models: true do
- let(:pipeline) { FactoryGirl.create :ci_pipeline }
- let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, pipeline: pipeline }
+ let(:pipeline) { create(:ci_pipeline) }
+
+ let(:generic_commit_status) do
+ create(:generic_commit_status, pipeline: pipeline)
+ end
describe '#context' do
subject { generic_commit_status.context }
@@ -17,6 +20,15 @@ describe GenericCommitStatus, models: true do
it { is_expected.to eq([:external]) }
end
+ describe '#detailed_status' do
+ let(:user) { create(:user) }
+
+ it 'returns detailed status object' do
+ expect(generic_commit_status.detailed_status(user))
+ .to be_a Gitlab::Ci::Status::Success
+ end
+ end
+
describe 'set_default_values' do
before do
generic_commit_status.context = nil
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 1613a586a2c..893c6827a91 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -50,9 +50,8 @@ describe Group, models: true do
describe 'validations' do
it { is_expected.to validate_presence_of :name }
- it { is_expected.to validate_uniqueness_of(:name) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_id) }
it { is_expected.to validate_presence_of :path }
- it { is_expected.to validate_uniqueness_of(:path) }
it { is_expected.not_to validate_presence_of :owner }
end
@@ -271,4 +270,11 @@ describe Group, models: true do
expect(group.web_url).to include("groups/#{group.name}")
end
end
+
+ describe 'nested group' do
+ subject { create(:group, :nested) }
+
+ it { is_expected.to be_valid }
+ it { expect(subject.parent).to be_kind_of(Group) }
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 7f82e85563b..069c59fb5ca 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -6,20 +6,16 @@ describe Namespace, models: true do
it { is_expected.to have_many :projects }
it { is_expected.to validate_presence_of(:name) }
- it { is_expected.to validate_uniqueness_of(:name) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_id) }
it { is_expected.to validate_length_of(:name).is_at_most(255) }
it { is_expected.to validate_length_of(:description).is_at_most(255) }
it { is_expected.to validate_presence_of(:path) }
- it { is_expected.to validate_uniqueness_of(:path) }
it { is_expected.to validate_length_of(:path).is_at_most(255) }
it { is_expected.to validate_presence_of(:owner) }
- describe "Mass assignment" do
- end
-
describe "Respond to" do
it { is_expected.to respond_to(:human_name) }
it { is_expected.to respond_to(:to_param) }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
new file mode 100644
index 00000000000..ffb92012b89
--- /dev/null
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -0,0 +1,126 @@
+require 'spec_helper'
+
+describe KubernetesService, models: true do
+ let(:project) { create(:empty_project) }
+
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before { subject.active = true }
+ it { is_expected.to validate_presence_of(:namespace) }
+ it { is_expected.to validate_presence_of(:api_url) }
+ it { is_expected.to validate_presence_of(:token) }
+
+ context 'namespace format' do
+ before do
+ subject.project = project
+ subject.api_url = "http://example.com"
+ subject.token = "test"
+ end
+
+ {
+ 'foo' => true,
+ '1foo' => true,
+ 'foo1' => true,
+ 'foo-bar' => true,
+ '-foo' => false,
+ 'foo-' => false,
+ 'a' * 63 => true,
+ 'a' * 64 => false,
+ 'a.b' => false,
+ 'a*b' => false,
+ }.each do |namespace, validity|
+ it "should validate #{namespace} as #{validity ? 'valid' : 'invalid'}" do
+ subject.namespace = namespace
+
+ expect(subject.valid?).to eq(validity)
+ end
+ end
+ end
+ end
+
+ context 'when service is inactive' do
+ before { subject.active = false }
+ it { is_expected.not_to validate_presence_of(:namespace) }
+ it { is_expected.not_to validate_presence_of(:api_url) }
+ it { is_expected.not_to validate_presence_of(:token) }
+ end
+ end
+
+ describe '#initialize_properties' do
+ context 'with a project' do
+ it 'defaults to the project name' do
+ expect(described_class.new(project: project).namespace).to eq(project.name)
+ end
+ end
+
+ context 'without a project' do
+ it 'leaves the namespace unset' do
+ expect(described_class.new.namespace).to be_nil
+ end
+ end
+ end
+
+ describe '#test' do
+ let(:project) { create(:kubernetes_project) }
+ let(:service) { project.kubernetes_service }
+ let(:discovery_url) { service.api_url + '/api/v1' }
+
+ # JSON response body from Kubernetes GET /api/v1 request
+ let(:discovery_response) { { "kind" => "APIResourceList", "groupVersion" => "v1", "resources" => [] }.to_json }
+
+ context 'with path prefix in api_url' do
+ let(:discovery_url) { 'https://kubernetes.example.com/prefix/api/v1' }
+
+ before do
+ service.api_url = 'https://kubernetes.example.com/prefix/'
+ end
+
+ it 'tests with the prefix' do
+ WebMock.stub_request(:get, discovery_url).to_return(body: discovery_response)
+
+ expect(service.test[:success]).to be_truthy
+ expect(WebMock).to have_requested(:get, discovery_url).once
+ end
+ end
+
+ context 'with custom CA certificate' do
+ let(:certificate) { "CA PEM DATA" }
+ before do
+ service.update_attributes!(ca_pem: certificate)
+ end
+
+ it 'is added to the certificate store' do
+ cert = double("certificate")
+
+ expect(OpenSSL::X509::Certificate).to receive(:new).with(certificate).and_return(cert)
+ expect_any_instance_of(OpenSSL::X509::Store).to receive(:add_cert).with(cert)
+ WebMock.stub_request(:get, discovery_url).to_return(body: discovery_response)
+
+ expect(service.test[:success]).to be_truthy
+ expect(WebMock).to have_requested(:get, discovery_url).once
+ end
+ end
+
+ context 'success' do
+ it 'reads the discovery endpoint' do
+ WebMock.stub_request(:get, discovery_url).to_return(body: discovery_response)
+
+ expect(service.test[:success]).to be_truthy
+ expect(WebMock).to have_requested(:get, discovery_url).once
+ end
+ end
+
+ context 'failure' do
+ it 'fails to read the discovery endpoint' do
+ WebMock.stub_request(:get, discovery_url).to_return(status: 404)
+
+ expect(service.test[:success]).to be_falsy
+ expect(WebMock).to have_requested(:get, discovery_url).once
+ end
+ end
+ end
+end
diff --git a/spec/models/project_services/slack_service/pipeline_message_spec.rb b/spec/models/project_services/slack_service/pipeline_message_spec.rb
index 363138a9454..4098500122f 100644
--- a/spec/models/project_services/slack_service/pipeline_message_spec.rb
+++ b/spec/models/project_services/slack_service/pipeline_message_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe SlackService::PipelineMessage do
subject { SlackService::PipelineMessage.new(args) }
+ let(:user) { { name: 'hacker' } }
let(:args) do
{
@@ -15,7 +16,7 @@ describe SlackService::PipelineMessage do
},
project: { path_with_namespace: 'project_name',
web_url: 'example.gitlab.com' },
- user: { name: 'hacker' }
+ user: user
}
end
@@ -28,9 +29,7 @@ describe SlackService::PipelineMessage do
let(:message) { build_message('passed') }
it 'returns a message with information about succeeded build' do
- expect(subject.pretext).to be_empty
- expect(subject.fallback).to eq(message)
- expect(subject.attachments).to eq([text: message, color: color])
+ verify_message
end
end
@@ -40,16 +39,29 @@ describe SlackService::PipelineMessage do
let(:duration) { 10 }
it 'returns a message with information about failed build' do
- expect(subject.pretext).to be_empty
- expect(subject.fallback).to eq(message)
- expect(subject.attachments).to eq([text: message, color: color])
+ verify_message
end
+
+ context 'when triggered by API therefore lacking user' do
+ let(:user) { nil }
+ let(:message) { build_message(status, 'API') }
+
+ it 'returns a message stating it is by API' do
+ verify_message
+ end
+ end
+ end
+
+ def verify_message
+ expect(subject.pretext).to be_empty
+ expect(subject.fallback).to eq(message)
+ expect(subject.attachments).to eq([text: message, color: color])
end
- def build_message(status_text = status)
+ def build_message(status_text = status, name = user[:name])
"<example.gitlab.com|project_name>:" \
" Pipeline <example.gitlab.com/pipelines/123|#123>" \
" of <example.gitlab.com/commits/develop|develop> branch" \
- " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}"
+ " by #{name} #{status_text} in #{duration} #{'second'.pluralize(duration)}"
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index bad6ed9e146..8b20ee81614 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -727,17 +727,6 @@ describe User, models: true do
end
end
- describe 'by_username_or_id' do
- let(:user1) { create(:user, username: 'foo') }
-
- it "gets the correct user" do
- expect(User.by_username_or_id(user1.id)).to eq(user1)
- expect(User.by_username_or_id('foo')).to eq(user1)
- expect(User.by_username_or_id(-1)).to be_nil
- expect(User.by_username_or_id('bar')).to be_nil
- end
- end
-
describe '.find_by_ssh_key_id' do
context 'using an existing SSH key ID' do
let(:user) { create(:user) }
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 55b8c8c0c69..2878e0cb59b 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -11,6 +11,7 @@ describe API::Branches, api: true do
let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
let!(:branch_name) { 'feature' }
let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
+ let!(:branch_with_dot) { CreateBranchService.new(project, user).execute("with.1.2.3", "master") }
describe "GET /projects/:id/repository/branches" do
it "returns an array of project branches" do
@@ -37,6 +38,13 @@ describe API::Branches, api: true do
expect(json_response['developers_can_merge']).to eq(false)
end
+ it "returns the branch information for a single branch with dots in the name" do
+ get api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq("with.1.2.3")
+ end
+
context 'on a merged branch' do
it "returns the branch information for a single branch" do
get api("/projects/#{project.id}/repository/branches/merge-test", user)
@@ -71,6 +79,14 @@ describe API::Branches, api: true do
expect(json_response['developers_can_merge']).to eq(false)
end
+ it "protects a single branch with dots in the name" do
+ put api("/projects/#{project.id}/repository/branches/with.1.2.3/protect", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq("with.1.2.3")
+ expect(json_response['protected']).to eq(true)
+ end
+
it 'protects a single branch and developers can push' do
put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user),
developers_can_push: true
@@ -220,6 +236,14 @@ describe API::Branches, api: true do
expect(json_response['protected']).to eq(false)
end
+ it "update branches with dots in branch name" do
+ put api("/projects/#{project.id}/repository/branches/with.1.2.3/unprotect", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['name']).to eq("with.1.2.3")
+ expect(json_response['protected']).to eq(false)
+ end
+
it "returns success when unprotect branch" do
put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user)
expect(response).to have_http_status(404)
@@ -292,6 +316,13 @@ describe API::Branches, api: true do
expect(json_response['branch_name']).to eq(branch_name)
end
+ it "removes a branch with dots in the branch name" do
+ delete api("/projects/#{project.id}/repository/branches/with.1.2.3", user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response['branch_name']).to eq("with.1.2.3")
+ end
+
it 'returns 404 if branch not exists' do
delete api("/projects/#{project.id}/repository/branches/foobar", user)
expect(response).to have_http_status(404)
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index e497bce6943..964cded917c 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -456,6 +456,76 @@ describe API::Commits, api: true do
end
end
+ describe 'POST :id/repository/commits/:sha/cherry_pick' do
+ let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
+
+ context 'authorized user' do
+ it 'cherry picks a commit' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'master'
+
+ expect(response).to have_http_status(201)
+ expect(json_response['title']).to eq(master_pickable_commit.title)
+ expect(json_response['message']).to eq(master_pickable_commit.message)
+ expect(json_response['author_name']).to eq(master_pickable_commit.author_name)
+ expect(json_response['committer_name']).to eq(user.name)
+ end
+
+ it 'returns 400 if commit is already included in the target branch' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'markdown'
+
+ expect(response).to have_http_status(400)
+ expect(json_response['message']).to eq('Sorry, we cannot cherry-pick this commit automatically.
+ A cherry-pick may have already been performed with this commit, or a more recent commit may have updated some of its content.')
+ end
+
+ it 'returns 400 if you are not allowed to push to the target branch' do
+ project.team << [user2, :developer]
+ protected_branch = create(:protected_branch, project: project, name: 'feature')
+
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user2), branch: protected_branch.name
+
+ expect(response).to have_http_status(400)
+ expect(json_response['message']).to eq('You are not allowed to push into this branch')
+ end
+
+ it 'returns 400 for missing parameters' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
+
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq('branch is missing')
+ end
+
+ it 'returns 404 if commit is not found' do
+ post api("/projects/#{project.id}/repository/commits/abcd0123/cherry_pick", user), branch: 'master'
+
+ expect(response).to have_http_status(404)
+ expect(json_response['message']).to eq('404 Commit Not Found')
+ end
+
+ it 'returns 404 if branch is not found' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user), branch: 'foo'
+
+ expect(response).to have_http_status(404)
+ expect(json_response['message']).to eq('404 Branch Not Found')
+ end
+
+ it 'returns 400 for missing parameters' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick", user)
+
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq('branch is missing')
+ end
+ end
+
+ context 'unauthorized user' do
+ it 'does not cherry pick the commit' do
+ post api("/projects/#{project.id}/repository/commits/#{master_pickable_commit.id}/cherry_pick"), branch: 'master'
+
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+
describe 'Post comment to commit' do
context 'authorized user' do
it 'returns comment' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 548ed8e1892..a75ba824e85 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -243,6 +243,28 @@ describe API::Groups, api: true do
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name' ] }
expect(project_names).to match_array([project1.name, project3.name])
+ expect(json_response.first['default_branch']).to be_present
+ end
+
+ it "returns the group's projects with simple representation" do
+ get api("/groups/#{group1.id}/projects", user1), simple: true
+
+ expect(response).to have_http_status(200)
+ expect(json_response.length).to eq(2)
+ project_names = json_response.map { |proj| proj['name' ] }
+ expect(project_names).to match_array([project1.name, project3.name])
+ expect(json_response.first['default_branch']).not_to be_present
+ end
+
+ it 'filters the groups projects' do
+ public_project = create(:project, :public, path: 'test1', group: group1)
+
+ get api("/groups/#{group1.id}/projects", user1), visibility: 'public'
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['name']).to eq(public_project.name)
end
it "does not return a non existing group" do
diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index 3f34309f419..4035fd97af5 100644
--- a/spec/requests/api/api_helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -2,7 +2,6 @@ require 'spec_helper'
describe API::Helpers, api: true do
include API::Helpers
- include ApiHelpers
include SentryHelper
let(:user) { create(:user) }
@@ -13,18 +12,18 @@ describe API::Helpers, api: true do
let(:env) { { 'REQUEST_METHOD' => 'GET' } }
let(:request) { Rack::Request.new(env) }
- def set_env(token_usr, identifier)
+ def set_env(user_or_token, identifier)
clear_env
clear_param
- env[API::Helpers::PRIVATE_TOKEN_HEADER] = token_usr.private_token
- env[API::Helpers::SUDO_HEADER] = identifier
+ env[API::Helpers::PRIVATE_TOKEN_HEADER] = user_or_token.respond_to?(:private_token) ? user_or_token.private_token : user_or_token
+ env[API::Helpers::SUDO_HEADER] = identifier.to_s
end
- def set_param(token_usr, identifier)
+ def set_param(user_or_token, identifier)
clear_env
clear_param
- params[API::Helpers::PRIVATE_TOKEN_PARAM] = token_usr.private_token
- params[API::Helpers::SUDO_PARAM] = identifier
+ params[API::Helpers::PRIVATE_TOKEN_PARAM] = user_or_token.respond_to?(:private_token) ? user_or_token.private_token : user_or_token
+ params[API::Helpers::SUDO_PARAM] = identifier.to_s
end
def clear_env
@@ -163,6 +162,13 @@ describe API::Helpers, api: true do
expect(current_user).to eq(user)
end
+ it 'memoize the current_user: sudo permissions are not run against the sudoed user' do
+ set_env(admin, user.id)
+
+ expect(current_user).to eq(user)
+ expect(current_user).to eq(user)
+ end
+
it 'handles sudo to oneself' do
set_env(admin, admin.id)
@@ -294,33 +300,48 @@ describe API::Helpers, api: true do
end
end
- describe '.sudo_identifier' do
- it "returns integers when input is an int" do
- set_env(admin, '123')
- expect(sudo_identifier).to eq(123)
- set_env(admin, '0001234567890')
- expect(sudo_identifier).to eq(1234567890)
-
- set_param(admin, '123')
- expect(sudo_identifier).to eq(123)
- set_param(admin, '0001234567890')
- expect(sudo_identifier).to eq(1234567890)
+ describe '.sudo?' do
+ context 'when no sudo env or param is passed' do
+ before do
+ doorkeeper_guard_returns(nil)
+ end
+
+ it 'returns false' do
+ expect(sudo?).to be_falsy
+ end
end
- it "returns string when input is an is not an int" do
- set_env(admin, '12.30')
- expect(sudo_identifier).to eq("12.30")
- set_env(admin, 'hello')
- expect(sudo_identifier).to eq('hello')
- set_env(admin, ' 123')
- expect(sudo_identifier).to eq(' 123')
-
- set_param(admin, '12.30')
- expect(sudo_identifier).to eq("12.30")
- set_param(admin, 'hello')
- expect(sudo_identifier).to eq('hello')
- set_param(admin, ' 123')
- expect(sudo_identifier).to eq(' 123')
+ context 'when sudo env or param is passed', 'user is not an admin' do
+ before do
+ set_env(user, '123')
+ end
+
+ it 'returns an 403 Forbidden' do
+ expect { sudo? }.to raise_error '403 - {"message"=>"403 Forbidden - Must be admin to use sudo"}'
+ end
+ end
+
+ context 'when sudo env or param is passed', 'user is admin' do
+ context 'personal access token is used' do
+ before do
+ personal_access_token = create(:personal_access_token, user: admin)
+ set_env(personal_access_token.token, user.id)
+ end
+
+ it 'returns an 403 Forbidden' do
+ expect { sudo? }.to raise_error '403 - {"message"=>"403 Forbidden - Private token must be specified in order to use sudo"}'
+ end
+ end
+
+ context 'private access token is used' do
+ before do
+ set_env(admin.private_token, user.id)
+ end
+
+ it 'returns true' do
+ expect(sudo?).to be_truthy
+ end
+ end
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 75b270aa93c..f032d1b683d 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -533,6 +533,22 @@ describe API::MergeRequests, api: true do
expect(json_response['labels']).to include '?'
expect(json_response['labels']).to include '&'
end
+
+ it 'does not update state when title is empty' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: 'close', title: nil
+
+ merge_request.reload
+ expect(response).to have_http_status(400)
+ expect(merge_request.state).to eq('opened')
+ end
+
+ it 'does not update state when target_branch is empty' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: 'close', target_branch: nil
+
+ merge_request.reload
+ expect(response).to have_http_status(400)
+ expect(merge_request.state).to eq('opened')
+ end
end
describe "POST /projects/:id/merge_requests/:merge_request_id/comments" do
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index d30361f53d4..668e39f9dba 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -2,6 +2,7 @@ require "spec_helper"
describe API::Services, api: true do
include ApiHelpers
+
let(:user) { create(:user) }
let(:admin) { create(:admin) }
let(:user2) { create(:user) }
@@ -98,7 +99,7 @@ describe API::Services, api: true do
post api("/projects/#{project.id}/services/idonotexist/trigger")
expect(response).to have_http_status(404)
- expect(json_response["message"]).to eq("404 Service Not Found")
+ expect(json_response["error"]).to eq("404 Not Found")
end
end
@@ -114,7 +115,7 @@ describe API::Services, api: true do
end
it 'when the service is inactive' do
- post api("/projects/#{project.id}/services/mattermost_slash_commands/trigger")
+ post api("/projects/#{project.id}/services/mattermost_slash_commands/trigger"), params
expect(response).to have_http_status(404)
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index c37dbfa0a33..9e317f3a7e9 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -651,13 +651,12 @@ describe API::Users, api: true do
end
describe "GET /user" do
- let(:personal_access_token) { create(:personal_access_token, user: user) }
- let(:private_token) { user.private_token }
+ let(:personal_access_token) { create(:personal_access_token, user: user).token }
context 'with regular user' do
context 'with personal access token' do
it 'returns 403 without private token when sudo is defined' do
- get api("/user?private_token=#{personal_access_token.token}&sudo=#{user.id}")
+ get api("/user?private_token=#{personal_access_token}&sudo=123")
expect(response).to have_http_status(403)
end
@@ -665,7 +664,7 @@ describe API::Users, api: true do
context 'with private token' do
it 'returns 403 without private token when sudo defined' do
- get api("/user?private_token=#{private_token}&sudo=#{user.id}")
+ get api("/user?private_token=#{user.private_token}&sudo=123")
expect(response).to have_http_status(403)
end
@@ -676,40 +675,44 @@ describe API::Users, api: true do
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
+ expect(json_response['id']).to eq(user.id)
end
end
context 'with admin' do
- let(:user) { create(:admin) }
+ let(:admin_personal_access_token) { create(:personal_access_token, user: admin).token }
context 'with personal access token' do
it 'returns 403 without private token when sudo defined' do
- get api("/user?private_token=#{personal_access_token.token}&sudo=#{user.id}")
+ get api("/user?private_token=#{admin_personal_access_token}&sudo=#{user.id}")
expect(response).to have_http_status(403)
end
- it 'returns current user without private token when sudo not defined' do
- get api("/user?private_token=#{personal_access_token.token}")
+ it 'returns initial current user without private token when sudo not defined' do
+ get api("/user?private_token=#{admin_personal_access_token}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
+ expect(json_response['id']).to eq(admin.id)
end
end
context 'with private token' do
- it 'returns current user with private token when sudo defined' do
- get api("/user?private_token=#{private_token}&sudo=#{user.id}")
+ it 'returns sudoed user with private token when sudo defined' do
+ get api("/user?private_token=#{admin.private_token}&sudo=#{user.id}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/login')
+ expect(json_response['id']).to eq(user.id)
end
- it 'returns current user without private token when sudo not defined' do
- get api("/user?private_token=#{private_token}")
+ it 'returns initial current user without private token when sudo not defined' do
+ get api("/user?private_token=#{admin.private_token}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
+ expect(json_response['id']).to eq(admin.id)
end
end
end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index 69eeb45ed71..661b671301e 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -66,7 +66,8 @@ describe Admin::ProjectsController, "routing" do
end
it "to #show" do
- expect(get("/admin/projects/gitlab")).to route_to('admin/projects#show', namespace_id: 'gitlab')
+ expect(get("/admin/projects/gitlab/gitlab-ce")).to route_to('admin/projects#show', namespace_id: 'gitlab', id: 'gitlab-ce')
+ expect(get("/admin/projects/gitlab/subgroup/gitlab-ce")).to route_to('admin/projects#show', namespace_id: 'gitlab/subgroup', id: 'gitlab-ce')
end
end
@@ -119,3 +120,14 @@ describe Admin::HealthCheckController, "routing" do
expect(get("/admin/health_check")).to route_to('admin/health_check#show')
end
end
+
+describe Admin::GroupsController, "routing" do
+ it "to #index" do
+ expect(get("/admin/groups")).to route_to('admin/groups#index')
+ end
+
+ it "to #show" do
+ expect(get("/admin/groups/gitlab")).to route_to('admin/groups#show', id: 'gitlab')
+ expect(get("/admin/groups/gitlab/subgroup")).to route_to('admin/groups#show', id: 'gitlab/subgroup')
+ end
+end
diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb
index 6b33fe66a63..86e703a6448 100644
--- a/spec/serializers/analytics_build_entity_spec.rb
+++ b/spec/serializers/analytics_build_entity_spec.rb
@@ -13,6 +13,14 @@ describe AnalyticsBuildEntity do
subject { entity.as_json }
+ before do
+ Timecop.freeze
+ end
+
+ after do
+ Timecop.return
+ end
+
it 'contains the URL' do
expect(subject).to include(:url)
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 90b7e62bc6f..0e8adb68721 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -694,7 +694,7 @@ describe SystemNoteService, services: true do
describe "existing reference" do
before do
- message = "[#{author.name}|http://localhost/#{author.username}] mentioned this issue in [a commit of #{project.path_with_namespace}|http://localhost/#{project.path_with_namespace}/commit/#{commit.id}]:\n'#{commit.title}'"
+ message = "[#{author.name}|http://localhost/#{author.username}] mentioned this issue in [a commit of #{project.path_with_namespace}|http://localhost/#{project.path_with_namespace}/commit/#{commit.id}]:\n'#{commit.title.chomp}'"
allow_any_instance_of(JIRA::Resource::Issue).to receive(:comments).and_return([OpenStruct.new(body: message)])
end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index c0b3e83244d..ad1eed5b369 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -75,7 +75,8 @@ module LoginHelpers
def logout
find(".header-user-dropdown-toggle").click
click_link "Sign out"
- expect(page).to have_content('Signed out successfully')
+ # check the sign_in button
+ expect(page).to have_button('Sign in')
end
# Logout without JavaScript driver
diff --git a/spec/support/services_shared_context.rb b/spec/support/services_shared_context.rb
index d1c999cad4d..66c93890e31 100644
--- a/spec/support/services_shared_context.rb
+++ b/spec/support/services_shared_context.rb
@@ -16,8 +16,14 @@ Service.available_services_names.each do |service|
hash.merge!(k => 'secrettoken')
elsif k =~ /^(.*_url|url|webhook)/
hash.merge!(k => "http://example.com")
+ elsif service_klass.method_defined?("#{k}?")
+ hash.merge!(k => true)
elsif service == 'irker' && k == :recipients
hash.merge!(k => 'irc://irc.network.net:666/#channel')
+ elsif service == 'irker' && k == :server_port
+ hash.merge!(k => 1234)
+ elsif service == 'jira' && k == :jira_issue_transition_id
+ hash.merge!(k => 1234)
else
hash.merge!(k => "someword")
end
diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
index 16bf0698c4b..e741e3cf9b6 100644
--- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb
+++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
@@ -13,7 +13,7 @@ describe 'projects/commit/_commit_box.html.haml' do
it 'shows the commit SHA' do
render
- expect(rendered).to have_text("Commit #{Commit.truncate_sha(project.commit.sha)}")
+ expect(rendered).to have_text("#{Commit.truncate_sha(project.commit.sha)}")
end
it 'shows the last pipeline that ran for the commit' do
diff --git a/spec/views/projects/pipelines/show.html.haml_spec.rb b/spec/views/projects/pipelines/show.html.haml_spec.rb
index bf027499c94..a066ea078e6 100644
--- a/spec/views/projects/pipelines/show.html.haml_spec.rb
+++ b/spec/views/projects/pipelines/show.html.haml_spec.rb
@@ -28,7 +28,7 @@ describe 'projects/pipelines/show' do
it 'shows a graph with grouped stages' do
render
- expect(rendered).to have_css('.pipeline-graph')
+ expect(rendered).to have_css('.js-pipeline-graph')
expect(rendered).to have_css('.grouped-pipeline-dropdown')
# stages