summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/dashboard/todos_controller_spec.rb7
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb67
-rw-r--r--spec/controllers/import/gitlab_controller_spec.rb66
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb9
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb11
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb12
-rw-r--r--spec/factories/ci/builds.rb5
-rw-r--r--spec/factories/environments.rb5
-rw-r--r--spec/features/admin/admin_health_check_spec.rb6
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb32
-rw-r--r--spec/features/gitlab_flavored_markdown_spec.rb12
-rw-r--r--spec/features/groups/empty_states_spec.rb70
-rw-r--r--spec/features/issues/award_emoji_spec.rb5
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb20
-rw-r--r--spec/features/issues/move_spec.rb4
-rw-r--r--spec/features/issues/spam_issues_spec.rb2
-rw-r--r--spec/features/issues_spec.rb17
-rw-r--r--spec/features/merge_requests/create_new_mr_spec.rb20
-rw-r--r--spec/features/milestones/milestones_spec.rb6
-rw-r--r--spec/features/projects/environments/environments_spec.rb40
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb8
-rw-r--r--spec/features/projects/merge_requests/list_spec.rb24
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb20
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb6
-rw-r--r--spec/features/search_spec.rb6
-rw-r--r--spec/fixtures/metrics.json1
-rw-r--r--spec/helpers/events_helper_spec.rb27
-rw-r--r--spec/helpers/projects_helper_spec.rb8
-rw-r--r--spec/javascripts/blob/pdf/index_spec.js72
-rw-r--r--spec/javascripts/blob/pdf/test.pdfbin0 -> 11956 bytes
-rw-r--r--spec/javascripts/blob/sketch/index_spec.js118
-rw-r--r--spec/javascripts/boards/board_list_spec.js201
-rw-r--r--spec/javascripts/environments/environment_actions_spec.js15
-rw-r--r--spec/javascripts/environments/environment_spec.js99
-rw-r--r--spec/javascripts/environments/environments_store_spec.js110
-rw-r--r--spec/javascripts/environments/mock_data.js16
-rw-r--r--spec/javascripts/fixtures/pdf_viewer.html.haml1
-rw-r--r--spec/javascripts/fixtures/sketch_viewer.html.haml2
-rw-r--r--spec/javascripts/issue_show/issue_title_spec.js22
-rw-r--r--spec/javascripts/lib/utils/number_utility_spec.js41
-rw-r--r--spec/javascripts/monitoring/prometheus_graph_spec.js10
-rw-r--r--spec/javascripts/test_bundle.js1
-rw-r--r--spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js15
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb19
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb7
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb6
-rw-r--r--spec/lib/gitlab/backend/shell_spec.rb9
-rw-r--r--spec/lib/gitlab/git/attributes_spec.rb4
-rw-r--r--spec/lib/gitlab/git/blame_spec.rb2
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb2
-rw-r--r--spec/lib/gitlab/git/branch_spec.rb2
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb8
-rw-r--r--spec/lib/gitlab/git/compare_spec.rb2
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb2
-rw-r--r--spec/lib/gitlab/git/encoding_helper_spec.rb2
-rw-r--r--spec/lib/gitlab/git/index_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb111
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb2
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb2
-rw-r--r--spec/lib/gitlab/gitaly_client/notifications_spec.rb9
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_spec.rb41
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/import_export/fork_spec.rb49
-rw-r--r--spec/lib/gitlab/import_export/hash_util_spec.rb28
-rw-r--r--spec/lib/gitlab/import_export/merge_request_parser_spec.rb31
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/relation_factory_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/repo_saver_spec.rb (renamed from spec/lib/gitlab/import_export/repo_bundler_spec.rb)0
-rw-r--r--spec/lib/gitlab/o_auth/user_spec.rb9
-rw-r--r--spec/lib/gitlab/polling_interval_spec.rb4
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb8
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb36
-rw-r--r--spec/models/blob_spec.rb42
-rw-r--r--spec/models/issue_spec.rb8
-rw-r--r--spec/models/namespace_spec.rb51
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb89
-rw-r--r--spec/requests/api/issues_spec.rb376
-rw-r--r--spec/requests/api/milestones_spec.rb2
-rw-r--r--spec/requests/api/runner_spec.rb23
-rw-r--r--spec/serializers/build_action_entity_spec.rb4
-rw-r--r--spec/serializers/build_entity_spec.rb4
-rw-r--r--spec/services/merge_requests/build_service_spec.rb42
-rw-r--r--spec/services/system_note_service_spec.rb35
-rw-r--r--spec/services/users/create_service_spec.rb26
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb59
-rw-r--r--spec/support/drag_to_helper.rb4
-rw-r--r--spec/support/issuables_list_metadata_shared_examples.rb15
-rw-r--r--spec/support/matchers/gitaly_matchers.rb2
-rw-r--r--spec/support/matchers/query_matcher.rb33
-rw-r--r--spec/support/seed_helper.rb36
-rw-r--r--spec/workers/process_commit_worker_spec.rb7
92 files changed, 2046 insertions, 462 deletions
diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb
index 71a4a2c43c7..6075259ea99 100644
--- a/spec/controllers/dashboard/todos_controller_spec.rb
+++ b/spec/controllers/dashboard/todos_controller_spec.rb
@@ -35,6 +35,13 @@ describe Dashboard::TodosController do
expect(assigns(:todos).current_page).to eq(last_page)
expect(response).to have_http_status(200)
end
+
+ it 'does not redirect to external sites when provided a host field' do
+ external_host = "www.example.com"
+ get :index, page: (last_page + 1).to_param, host: external_host
+
+ expect(response).to redirect_to(dashboard_todos_path(page: last_page))
+ end
end
end
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index 51f23e4eeb9..010e3180ea4 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -200,5 +200,72 @@ describe Import::BitbucketController do
end
end
end
+
+ context 'user has chosen an existing nested namespace and name for the project' do
+ let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+ let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
+ let(:test_name) { 'test_name' }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, nested_namespace, user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: nested_namespace.full_path, new_name: test_name, format: :js }
+ end
+ end
+
+ context 'user has chosen a non-existent nested namespaces and name for the project' do
+ let(:test_name) { 'test_name' }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+
+ it 'new namespace has the right parent' do
+ allow(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js }
+
+ expect(Namespace.find_by_path_or_name('bar').parent.path).to eq('foo')
+ end
+ end
+
+ context 'user has chosen existent and non-existent nested namespaces and name for the project' do
+ let(:test_name) { 'test_name' }
+ let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(bitbucket_repo, test_name, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+ end
end
end
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
index 3f73ea000ae..2dbb89219d0 100644
--- a/spec/controllers/import/gitlab_controller_spec.rb
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -174,6 +174,72 @@ describe Import::GitlabController do
end
end
end
+
+ context 'user has chosen an existing nested namespace for the project' do
+ let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+ let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, nested_namespace, user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: nested_namespace.full_path, format: :js }
+ end
+ end
+
+ context 'user has chosen a non-existent nested namespaces for the project' do
+ let(:test_name) { 'test_name' }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/bar', format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+
+ it 'new namespace has the right parent' do
+ allow(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', format: :js }
+
+ expect(Namespace.find_by_path_or_name('bar').parent.path).to eq('foo')
+ end
+ end
+
+ context 'user has chosen existent and non-existent nested namespaces and name for the project' do
+ let(:test_name) { 'test_name' }
+ let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/foobar/bar', format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::GitlabImport::ProjectCreator).
+ to receive(:new).with(gitlab_repo, kind_of(Namespace), user, access_params).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/foobar/bar', format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index 7c75815f3c4..6724b474179 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -96,12 +96,19 @@ describe Projects::ImportsController do
}
end
- it 'redirects to params[:to]' do
+ it 'redirects to internal params[:to]' do
get :show, namespace_id: project.namespace.to_param, project_id: project, continue: params
expect(flash[:notice]).to eq params[:notice]
expect(response).to redirect_to params[:to]
end
+
+ it 'does not redirect to external params[:to]' do
+ params[:to] = "//google.com"
+
+ get :show, namespace_id: project.namespace.to_param, project_id: project, continue: params
+ expect(response).not_to redirect_to params[:to]
+ end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 734966d50b2..d5f1d46bf7f 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -83,6 +83,17 @@ describe Projects::IssuesController do
expect(assigns(:issues).current_page).to eq(last_page)
expect(response).to have_http_status(200)
end
+
+ it 'does not redirect to external sites when provided a host field' do
+ external_host = "www.example.com"
+ get :index,
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ page: (last_page + 1).to_param,
+ host: external_host
+
+ expect(response).to redirect_to(namespace_project_issues_path(page: last_page, state: controller.params[:state], scope: controller.params[:scope]))
+ end
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 72f41f7209a..99d5583e683 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -176,6 +176,18 @@ describe Projects::MergeRequestsController do
expect(assigns(:merge_requests).current_page).to eq(last_page)
expect(response).to have_http_status(200)
end
+
+ it 'does not redirect to external sites when provided a host field' do
+ external_host = "www.example.com"
+ get :index,
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ state: 'opened',
+ page: (last_page + 1).to_param,
+ host: external_host
+
+ expect(response).to redirect_to(namespace_project_merge_requests_path(page: last_page, state: controller.params[:state], scope: controller.params[:scope]))
+ end
end
context 'when filtering by opened state' do
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index f78086211f7..87a0c95c4dc 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -192,5 +192,10 @@ FactoryGirl.define do
trait :no_options do
options { {} }
end
+
+ trait :non_playable do
+ status 'created'
+ self.when 'manual'
+ end
end
end
diff --git a/spec/factories/environments.rb b/spec/factories/environments.rb
index 0852dda6b29..3fbf24b5c7d 100644
--- a/spec/factories/environments.rb
+++ b/spec/factories/environments.rb
@@ -32,5 +32,10 @@ FactoryGirl.define do
environment.update_attribute(:deployments, [deployment])
end
end
+
+ trait :non_playable do
+ status 'created'
+ self.when 'manual'
+ end
end
end
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
index f7e49a56deb..523afa2318f 100644
--- a/spec/features/admin/admin_health_check_spec.rb
+++ b/spec/features/admin/admin_health_check_spec.rb
@@ -2,7 +2,6 @@ require 'spec_helper'
feature "Admin Health Check", feature: true do
include StubENV
- include WaitForAjax
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
@@ -24,11 +23,12 @@ feature "Admin Health Check", feature: true do
expect(page).to have_selector('#health-check-token', text: token)
end
- describe 'reload access token', js: true do
+ describe 'reload access token' do
it 'changes the access token' do
orig_token = current_application_settings.health_check_access_token
click_button 'Reset health check access token'
- wait_for_ajax
+
+ expect(page).to have_content('New health check access token has been generated!')
expect(find('#health-check-token').text).not_to eq orig_token
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
new file mode 100644
index 00000000000..508ca38d7e5
--- /dev/null
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'Dashboard Merge Requests' do
+ let(:current_user) { create :user }
+ let(:project) do
+ create(:empty_project) do |project|
+ project.add_master(current_user)
+ end
+ end
+
+ before do
+ login_as(current_user)
+ end
+
+ it 'should show an empty state' do
+ visit merge_requests_dashboard_path(assignee_id: current_user.id)
+
+ expect(page).to have_selector('.empty-state')
+ end
+
+ context 'if there are merge requests' do
+ before do
+ create(:merge_request, assignee: current_user, source_project: project)
+
+ visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ end
+
+ it 'should not show an empty state' do
+ expect(page).not_to have_selector('.empty-state')
+ end
+ end
+end
diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb
index 84d73d693bc..876f33dd03e 100644
--- a/spec/features/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/gitlab_flavored_markdown_spec.rb
@@ -48,7 +48,9 @@ describe "GitLab Flavored Markdown", feature: true do
end
end
- describe "for issues" do
+ describe "for issues", feature: true, js: true do
+ include WaitForVueResource
+
before do
@other_issue = create(:issue,
author: @user,
@@ -79,6 +81,14 @@ describe "GitLab Flavored Markdown", feature: true do
expect(page).to have_link(fred.to_reference)
end
+
+ it "renders updated subject once edited somewhere else in issues#show" do
+ visit namespace_project_issue_path(project.namespace, project, @issue)
+ @issue.update(title: "fix #{@other_issue.to_reference} and update")
+
+ wait_for_vue_resource
+ expect(page).to have_text("fix #{@other_issue.to_reference} and update")
+ end
end
describe "for merge requests" do
diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb
new file mode 100644
index 00000000000..fef8e41bffe
--- /dev/null
+++ b/spec/features/groups/empty_states_spec.rb
@@ -0,0 +1,70 @@
+require 'spec_helper'
+
+feature 'Groups Merge Requests Empty States' do
+ let(:group) { create(:group) }
+ let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user }
+
+ before do
+ login_as(user)
+ end
+
+ context 'group has a project' do
+ let(:project) { create(:empty_project, namespace: group) }
+
+ before do
+ project.add_master(user)
+ end
+
+ context 'the project has a merge request' do
+ before do
+ create(:merge_request, source_project: project)
+
+ visit merge_requests_group_path(group)
+ end
+
+ it 'should not display an empty state' do
+ expect(page).not_to have_selector('.empty-state')
+ end
+ end
+
+ context 'the project has no merge requests', :js do
+ before do
+ visit merge_requests_group_path(group)
+ end
+
+ it 'should display an empty state' do
+ expect(page).to have_selector('.empty-state')
+ end
+
+ it 'should show a new merge request button' do
+ within '.empty-state' do
+ expect(page).to have_content('New merge request')
+ end
+ end
+
+ it 'the new merge request button opens a project dropdown' do
+ within '.empty-state' do
+ find('.new-project-item-select-button').click
+ end
+
+ expect(page).to have_selector('.ajax-project-dropdown')
+ end
+ end
+ end
+
+ context 'group without a project' do
+ before do
+ visit merge_requests_group_path(group)
+ end
+
+ it 'should display an empty state' do
+ expect(page).to have_selector('.empty-state')
+ end
+
+ it 'should not show a new merge request button' do
+ within '.empty-state' do
+ expect(page).not_to have_link('New merge request')
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb
index 16e453bc328..8e67ab028d7 100644
--- a/spec/features/issues/award_emoji_spec.rb
+++ b/spec/features/issues/award_emoji_spec.rb
@@ -2,6 +2,7 @@ require 'rails_helper'
describe 'Awards Emoji', feature: true do
include WaitForAjax
+ include WaitForVueResource
let!(:project) { create(:project, :public) }
let!(:user) { create(:user) }
@@ -22,10 +23,11 @@ describe 'Awards Emoji', feature: true do
# The `heart_tip` emoji is not valid anymore so we need to skip validation
issue.award_emoji.build(user: user, name: 'heart_tip').save!(validate: false)
visit namespace_project_issue_path(project.namespace, project, issue)
+ wait_for_vue_resource
end
# Regression test: https://gitlab.com/gitlab-org/gitlab-ce/issues/29529
- it 'does not shows a 500 page' do
+ it 'does not shows a 500 page', js: true do
expect(page).to have_text(issue.title)
end
end
@@ -35,6 +37,7 @@ describe 'Awards Emoji', feature: true do
before do
visit namespace_project_issue_path(project.namespace, project, issue)
+ wait_for_vue_resource
end
it 'increments the thumbsdown emoji', js: true do
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 004e335dd38..2f880c926e7 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
describe 'Filter issues', js: true, feature: true do
+ include Devise::Test::IntegrationHelpers
include FilteredSearchHelpers
include WaitForAjax
@@ -42,16 +43,17 @@ describe 'Filter issues', js: true, feature: true do
project.team << [user2, :master]
group.add_developer(user)
group.add_developer(user2)
- login_as(user)
- create(:issue, project: project)
- create(:issue, title: "Bug report 1", project: project)
- create(:issue, title: "Bug report 2", project: project)
- create(:issue, title: "issue with 'single quotes'", project: project)
- create(:issue, title: "issue with \"double quotes\"", project: project)
- create(:issue, title: "issue with !@\#{$%^&*()-+", project: project)
- create(:issue, title: "issue by assignee", project: project, milestone: milestone, author: user, assignee: user)
- create(:issue, title: "issue by assignee with searchTerm", project: project, milestone: milestone, author: user, assignee: user)
+ sign_in(user)
+
+ create(:issue, project: project)
+ create(:issue, project: project, title: "Bug report 1")
+ create(:issue, project: project, title: "Bug report 2")
+ create(:issue, project: project, title: "issue with 'single quotes'")
+ create(:issue, project: project, title: "issue with \"double quotes\"")
+ create(:issue, project: project, title: "issue with !@\#{$%^&*()-+")
+ create(:issue, project: project, title: "issue by assignee", milestone: milestone, author: user, assignee: user)
+ create(:issue, project: project, title: "issue by assignee with searchTerm", milestone: milestone, author: user, assignee: user)
issue = create(:issue,
title: "Bug 2",
diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb
index f89b4db9e62..6c09903a2f6 100644
--- a/spec/features/issues/move_spec.rb
+++ b/spec/features/issues/move_spec.rb
@@ -37,8 +37,8 @@ feature 'issue move to another project' do
edit_issue(issue)
end
- scenario 'moving issue to another project' do
- first('#move_to_project_id', visible: false).set(new_project.id)
+ scenario 'moving issue to another project', js: true do
+ find('#move_to_project_id', visible: false).set(new_project.id)
click_button('Save changes')
expect(current_url).to include project_path(new_project)
diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb
index 4bc9b49f889..6001476d0ca 100644
--- a/spec/features/issues/spam_issues_spec.rb
+++ b/spec/features/issues/spam_issues_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-describe 'New issue', feature: true do
+describe 'New issue', feature: true, js: true do
include StubENV
let(:project) { create(:project, :public) }
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 7afceb88cf9..e3213d24f6a 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -695,4 +695,21 @@ describe 'Issues', feature: true do
end
end
end
+
+ describe 'title issue#show', js: true do
+ include WaitForVueResource
+
+ it 'updates the title', js: true do
+ issue = create(:issue, author: @user, assignee: @user, project: project, title: 'new title')
+
+ visit namespace_project_issue_path(project.namespace, project, issue)
+
+ expect(page).to have_text("new title")
+
+ issue.update(title: "updated title")
+
+ wait_for_vue_resource
+ expect(page).to have_text("updated title")
+ end
+ end
end
diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb
index f1ad4a55246..d4fe67c224f 100644
--- a/spec/features/merge_requests/create_new_mr_spec.rb
+++ b/spec/features/merge_requests/create_new_mr_spec.rb
@@ -15,7 +15,7 @@ feature 'Create New Merge Request', feature: true, js: true do
it 'selects the source branch sha when a tag with the same name exists' do
visit namespace_project_merge_requests_path(project.namespace, project)
- click_link 'New Merge Request'
+ click_link 'New merge request'
expect(page).to have_content('Source branch')
expect(page).to have_content('Target branch')
@@ -27,8 +27,8 @@ feature 'Create New Merge Request', feature: true, js: true do
it 'selects the target branch sha when a tag with the same name exists' do
visit namespace_project_merge_requests_path(project.namespace, project)
-
- click_link 'New Merge Request'
+
+ click_link 'New merge request'
expect(page).to have_content('Source branch')
expect(page).to have_content('Target branch')
@@ -42,7 +42,7 @@ feature 'Create New Merge Request', feature: true, js: true do
it 'generates a diff for an orphaned branch' do
visit namespace_project_merge_requests_path(project.namespace, project)
- click_link 'New Merge Request'
+ page.has_link?('New Merge Request') ? click_link("New Merge Request") : click_link('New merge request')
expect(page).to have_content('Source branch')
expect(page).to have_content('Target branch')
@@ -70,6 +70,18 @@ feature 'Create New Merge Request', feature: true, js: true do
visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_project_id: private_project.id })
expect(page).not_to have_content private_project.path_with_namespace
+ expect(page).to have_content project.path_with_namespace
+ end
+ end
+
+ context 'when source project cannot be viewed by the current user' do
+ it 'does not leak the private project name & namespace' do
+ private_project = create(:project, :private)
+
+ visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { source_project_id: private_project.id })
+
+ expect(page).not_to have_content private_project.path_with_namespace
+ expect(page).to have_content project.path_with_namespace
end
end
diff --git a/spec/features/milestones/milestones_spec.rb b/spec/features/milestones/milestones_spec.rb
index 8de9942c54e..2fa3e72ab08 100644
--- a/spec/features/milestones/milestones_spec.rb
+++ b/spec/features/milestones/milestones_spec.rb
@@ -76,6 +76,7 @@ describe 'Milestone draggable', feature: true, js: true do
create(:issue, params.merge(title: 'Foo', project: project, milestone: milestone))
visit namespace_project_milestone_path(project.namespace, project, milestone)
+ scroll_into_view('.milestone-content')
drag_to(selector: '.issues-sortable-list', list_to_index: 1)
wait_for_ajax
@@ -86,8 +87,13 @@ describe 'Milestone draggable', feature: true, js: true do
visit namespace_project_milestone_path(project.namespace, project, milestone)
page.find("a[href='#tab-merge-requests']").click
+ scroll_into_view('.milestone-content')
drag_to(selector: '.merge_requests-sortable-list', list_to_index: 1)
wait_for_ajax
end
+
+ def scroll_into_view(selector)
+ page.evaluate_script("document.querySelector('#{selector}').scrollIntoView();")
+ end
end
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 641e2cf7402..cf393afccbb 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -23,6 +23,46 @@ feature 'Environments page', :feature, :js do
expect(page).to have_link('Available')
expect(page).to have_link('Stopped')
end
+
+ describe 'with one available environment' do
+ given(:environment) { create(:environment, project: project, state: :available) }
+
+ describe 'in available tab page' do
+ it 'should show one environment' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'available')
+ expect(page).to have_css('.environments-container')
+ expect(page.all('tbody > tr').length).to eq(1)
+ end
+ end
+
+ describe 'in stopped tab page' do
+ it 'should show no environments' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'stopped')
+ expect(page).to have_css('.environments-container')
+ expect(page).to have_content('You don\'t have any environments right now')
+ end
+ end
+ end
+
+ describe 'with one stopped environment' do
+ given(:environment) { create(:environment, project: project, state: :stopped) }
+
+ describe 'in available tab page' do
+ it 'should show no environments' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'available')
+ expect(page).to have_css('.environments-container')
+ expect(page).to have_content('You don\'t have any environments right now')
+ end
+ end
+
+ describe 'in stopped tab page' do
+ it 'should show one environment' do
+ visit namespace_project_environments_path(project.namespace, project, scope: 'stopped')
+ expect(page).to have_css('.environments-container')
+ expect(page.all('tbody > tr').length).to eq(1)
+ end
+ end
+ end
end
context 'without environments' do
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 2d1106ea3e8..583f479ec18 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -69,12 +69,8 @@ feature 'Import/Export - project import integration test', feature: true, js: tr
select2(namespace.id, from: '#project_namespace_id')
- # click on disabled element
- find(:link, 'GitLab export').trigger('click')
-
- page.within('.flash-container') do
- expect(page).to have_content('Please enter path and name')
- end
+ # Check for tooltip disabled import button
+ expect(find('.import_gitlab_project')['title']).to eq('Please enter a valid project name.')
end
end
diff --git a/spec/features/projects/merge_requests/list_spec.rb b/spec/features/projects/merge_requests/list_spec.rb
index 5dd58ad66a7..7e8a796c55d 100644
--- a/spec/features/projects/merge_requests/list_spec.rb
+++ b/spec/features/projects/merge_requests/list_spec.rb
@@ -17,4 +17,28 @@ feature 'Merge Requests List' do
expect(page).not_to have_selector('.js-new-board-list')
end
+
+ it 'should show an empty state' do
+ visit namespace_project_merge_requests_path(project.namespace, project)
+
+ expect(page).to have_selector('.empty-state')
+ end
+
+ it 'empty state should have a create merge request button' do
+ visit namespace_project_merge_requests_path(project.namespace, project)
+
+ expect(page).to have_link 'New merge request', href: new_namespace_project_merge_request_path(project.namespace, project)
+ end
+
+ context 'if there are merge requests' do
+ before do
+ create(:merge_request, assignee: user, source_project: project)
+
+ visit namespace_project_merge_requests_path(project.namespace, project)
+ end
+
+ it 'should not show an empty state' do
+ expect(page).not_to have_selector('.empty-state')
+ end
+ end
end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index fff8b9f3447..7bdaafd1beb 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -15,6 +15,10 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
let(:project) { create(:project, namespace: user.namespace) }
context 'when wiki is empty' do
+ scenario 'commit message field has value "Create home"' do
+ expect(page).to have_field('wiki[message]', with: 'Create home')
+ end
+
scenario 'directly from the wiki home page' do
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
@@ -37,6 +41,9 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
fill_in :new_wiki_path, with: 'foo'
click_button 'Create Page'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Create foo')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
@@ -51,6 +58,9 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
fill_in :new_wiki_path, with: 'Spaces in the name'
click_button 'Create Page'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Create spaces in the name')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
@@ -65,6 +75,9 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
fill_in :new_wiki_path, with: 'hyphens-in-the-name'
click_button 'Create Page'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Create hyphens in the name')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
@@ -80,6 +93,10 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
let(:project) { create(:project, namespace: create(:group, :public)) }
context 'when wiki is empty' do
+ scenario 'commit message field has value "Create home"' do
+ expect(page).to have_field('wiki[message]', with: 'Create home')
+ end
+
scenario 'directly from the wiki home page' do
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
@@ -101,6 +118,9 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
fill_in :new_wiki_path, with: 'foo'
click_button 'Create Page'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Create foo')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Create page'
diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
index aedc0333cb9..86cf520ea80 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -19,6 +19,9 @@ feature 'Projects > Wiki > User updates wiki page', feature: true do
scenario 'success when the wiki content is not empty' do
click_link 'Edit'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Save changes'
@@ -48,6 +51,9 @@ feature 'Projects > Wiki > User updates wiki page', feature: true do
scenario 'the home page' do
click_link 'Edit'
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
+
fill_in :wiki_content, with: 'My awesome wiki!'
click_button 'Save changes'
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index a6560a81096..e8ad28a00f0 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -119,13 +119,15 @@ describe "Search", feature: true do
visit namespace_project_path(project.namespace, project)
page.within '.search' do
- fill_in 'search', with: 'def'
+ fill_in 'search', with: 'application.js'
click_button 'Go'
end
click_link "Code"
expect(page).to have_selector('.file-content .code')
+
+ expect(page).to have_selector("span.line[lang='javascript']")
end
end
@@ -162,6 +164,8 @@ describe "Search", feature: true do
end
context 'click the links in the category search dropdown', js: true do
+ let!(:merge_request) { create(:merge_request, source_project: project, author: user, assignee: user) }
+
before do
page.find('#search').click
end
diff --git a/spec/fixtures/metrics.json b/spec/fixtures/metrics.json
new file mode 100644
index 00000000000..06427adce57
--- /dev/null
+++ b/spec/fixtures/metrics.json
@@ -0,0 +1 @@
+{"success":true,"metrics":{"memory_values":[{"metric":{},"values":[[1490935421.33,"9.832775297619047"],[1490935481.33,"9.8359375"],[1490935541.33,"9.837983630952381"],[1490935601.33,"9.840401785714286"],[1490935661.33,"9.84375"],[1490935721.33,"9.846168154761905"],[1490935781.33,"9.849516369047619"],[1490935841.33,"9.85249255952381"],[1490935901.33,"9.855096726190476"],[1490935961.33,"9.845796130952381"],[1490936021.33,"9.847284226190476"],[1490936081.33,"9.84468005952381"],[1490936141.33,"9.847470238095237"],[1490936201.33,"9.850818452380953"],[1490936261.33,"9.852864583333334"],[1490936321.33,"9.854910714285714"],[1490936381.33,"9.857700892857142"],[1490936441.33,"9.865513392857142"],[1490936501.33,"9.874813988095237"],[1490936561.33,"9.866071428571429"],[1490936621.33,"9.849330357142858"],[1490936681.33,"9.841331845238095"],[1490936741.33,"9.853236607142858"],[1490936801.33,"9.839657738095237"],[1490936861.33,"9.841517857142858"],[1490936921.33,"9.852864583333334"],[1490936981.33,"9.851376488095237"],[1490937041.33,"9.837611607142858"],[1490937101.33,"9.840401785714286"],[1490937161.33,"9.843377976190476"],[1490937221.33,"9.845796130952381"],[1490937281.33,"9.84858630952381"],[1490937341.33,"9.866071428571429"],[1490937401.33,"9.852864583333334"],[1490937461.33,"9.855840773809524"],[1490937521.33,"9.837797619047619"],[1490937581.33,"9.840959821428571"],[1490937641.33,"9.848958333333334"],[1490937701.33,"9.844308035714286"],[1490937761.33,"9.845982142857142"],[1490937821.33,"9.83984375"],[1490937881.33,"9.830171130952381"],[1490937941.33,"9.83686755952381"],[1490938001.33,"9.834263392857142"],[1490938061.33,"9.836309523809524"],[1490938121.33,"9.83984375"],[1490938181.33,"9.832775297619047"],[1490938241.33,"9.818266369047619"],[1490938301.33,"9.820126488095237"],[1490938361.33,"9.824032738095237"],[1490938421.33,"9.826078869047619"],[1490938481.33,"9.817708333333334"],[1490938541.33,"9.811755952380953"],[1490938601.33,"9.811197916666666"],[1490938661.33,"9.81156994047619"],[1490938721.33,"9.812313988095237"],[1490938781.33,"9.813058035714286"],[1490938841.33,"9.81343005952381"],[1490938901.33,"9.81547619047619"],[1490938961.33,"9.818824404761905"],[1490939021.33,"9.819754464285714"],[1490939081.33,"9.820684523809524"],[1490939141.33,"9.824776785714286"],[1490939201.33,"9.826078869047619"],[1490939261.33,"9.828311011904763"],[1490939321.33,"9.820870535714286"],[1490939381.33,"9.823846726190476"],[1490939441.33,"9.824404761904763"],[1490939501.33,"9.82905505952381"],[1490939561.33,"9.832775297619047"],[1490939621.33,"9.835565476190476"],[1490939681.33,"9.833333333333334"],[1490939741.33,"9.835379464285714"],[1490939801.33,"9.837239583333334"],[1490939861.33,"9.839285714285714"],[1490939921.33,"9.829613095238095"],[1490939981.33,"9.832403273809524"],[1490940041.33,"9.835751488095237"],[1490940101.33,"9.837797619047619"],[1490940161.33,"9.840959821428571"],[1490940221.33,"9.84375"],[1490940281.33,"9.846354166666666"],[1490940341.33,"9.853980654761905"],[1490940401.33,"9.852678571428571"],[1490940461.33,"9.861979166666666"],[1490940521.33,"9.857700892857142"],[1490940581.33,"9.861793154761905"],[1490940641.33,"9.86421130952381"],[1490940701.33,"9.867001488095237"],[1490940761.33,"9.867931547619047"],[1490940821.33,"9.859933035714286"],[1490940881.33,"9.86235119047619"],[1490940941.33,"9.865141369047619"],[1490941001.33,"9.866443452380953"],[1490941061.33,"9.868861607142858"],[1490941121.33,"9.871465773809524"],[1490941181.33,"9.873511904761905"],[1490941241.33,"9.875558035714286"],[1490941301.33,"9.87797619047619"],[1490941361.33,"9.881324404761905"],[1490941421.33,"9.888392857142858"],[1490941481.33,"9.888392857142858"],[1490941541.33,"9.89546130952381"],[1490941601.33,"9.898065476190476"],[1490941661.33,"9.885044642857142"],[1490941721.33,"9.872395833333334"],[1490941781.33,"9.870349702380953"],[1490941841.33,"9.873325892857142"],[1490941901.33,"9.875558035714286"],[1490941961.33,"9.878534226190476"],[1490942021.33,"9.87983630952381"],[1490942081.33,"9.884300595238095"],[1490942141.33,"9.891927083333334"],[1490942201.33,"9.890252976190476"],[1490942261.33,"9.891927083333334"],[1490942321.33,"9.893787202380953"],[1490942381.33,"9.892113095238095"],[1490942441.33,"9.900111607142858"],[1490942501.33,"9.893415178571429"],[1490942561.33,"9.895647321428571"],[1490942621.33,"9.889322916666666"],[1490942681.33,"9.883556547619047"],[1490942741.33,"9.885602678571429"],[1490942801.33,"9.88764880952381"],[1490942861.33,"9.898623511904763"],[1490942921.33,"9.89453125"],[1490942981.33,"9.885044642857142"],[1490943041.33,"9.874813988095237"],[1490943101.33,"9.880766369047619"],[1490943161.33,"9.868675595238095"],[1490943221.33,"9.864769345238095"],[1490943281.33,"9.852864583333334"],[1490943341.33,"9.855096726190476"],[1490943401.33,"9.857514880952381"],[1490943461.33,"9.859747023809524"],[1490943521.33,"9.861793154761905"],[1490943581.33,"9.864025297619047"],[1490943641.33,"9.857514880952381"],[1490943701.33,"9.859002976190476"],[1490943761.33,"9.860677083333334"],[1490943821.33,"9.864025297619047"],[1490943881.33,"9.86625744047619"],[1490943941.33,"9.873325892857142"],[1490944001.33,"9.876674107142858"],[1490944061.33,"9.888950892857142"],[1490944121.33,"9.878534226190476"],[1490944181.33,"9.880766369047619"],[1490944241.33,"9.884858630952381"],[1490944301.33,"9.870535714285714"],[1490944361.33,"9.864769345238095"],[1490944421.33,"9.851190476190476"],[1490944481.33,"9.85249255952381"],[1490944541.33,"9.85844494047619"],[1490944601.33,"9.855840773809524"],[1490944661.33,"9.868303571428571"],[1490944721.33,"9.859188988095237"],[1490944781.33,"9.860491071428571"],[1490944841.33,"9.863467261904763"],[1490944901.33,"9.864025297619047"],[1490944961.33,"9.857514880952381"],[1490945021.33,"9.843377976190476"],[1490945081.33,"9.836123511904763"],[1490945141.33,"9.837983630952381"],[1490945201.33,"9.84077380952381"],[1490945261.33,"9.847284226190476"],[1490945321.33,"9.849702380952381"],[1490945381.33,"9.827380952380953"],[1490945441.33,"9.82124255952381"],[1490945501.33,"9.822916666666666"],[1490945561.33,"9.824962797619047"],[1490945621.33,"9.814546130952381"],[1490945681.33,"9.805989583333334"],[1490945741.33,"9.791294642857142"],[1490945801.33,"9.786458333333334"],[1490945861.33,"9.77641369047619"],[1490945921.33,"9.76655505952381"],[1490945981.33,"9.76953125"],[1490946041.33,"9.742745535714286"],[1490946101.33,"9.753162202380953"],[1490946161.33,"9.739583333333334"],[1490946221.33,"9.742931547619047"],[1490946281.33,"9.743489583333334"],[1490946341.33,"9.746837797619047"],[1490946401.33,"9.749255952380953"],[1490946461.33,"9.737165178571429"],[1490946521.33,"9.739583333333334"],[1490946581.33,"9.74311755952381"],[1490946641.33,"9.751302083333334"],[1490946701.33,"9.761346726190476"],[1490946761.33,"9.747953869047619"],[1490946821.33,"9.75093005952381"],[1490946881.33,"9.755580357142858"],[1490946941.33,"9.759858630952381"],[1490947001.33,"9.761904761904763"],[1490947061.33,"9.77641369047619"],[1490947121.33,"9.768787202380953"],[1490947181.33,"9.772879464285714"],[1490947241.33,"9.777715773809524"],[1490947301.33,"9.779947916666666"],[1490947361.33,"9.772135416666666"],[1490947421.33,"9.77641369047619"],[1490947481.33,"9.783668154761905"],[1490947541.33,"9.780505952380953"],[1490947601.33,"9.777157738095237"],[1490947661.33,"9.759114583333334"],[1490947721.33,"9.761532738095237"],[1490947781.33,"9.763392857142858"],[1490947841.33,"9.765252976190476"],[1490947901.33,"9.760602678571429"],[1490947961.33,"9.751488095238095"],[1490948021.33,"9.757998511904763"],[1490948081.33,"9.759486607142858"],[1490948141.33,"9.754650297619047"],[1490948201.33,"9.728050595238095"],[1490948261.33,"9.73530505952381"],[1490948321.33,"9.718005952380953"],[1490948381.33,"9.732142857142858"],[1490948441.33,"9.725260416666666"],[1490948501.33,"9.728422619047619"],[1490948561.33,"9.72953869047619"],[1490948621.33,"9.733072916666666"],[1490948681.33,"9.736421130952381"],[1490948741.33,"9.749627976190476"],[1490948801.33,"9.740141369047619"],[1490948861.33,"9.74311755952381"],[1490948921.33,"9.736607142857142"],[1490948981.33,"9.744233630952381"],[1490949041.33,"9.723772321428571"],[1490949101.33,"9.731956845238095"],[1490949161.33,"9.732514880952381"],[1490949221.33,"9.734747023809524"],[1490949281.33,"9.737723214285714"],[1490949341.33,"9.737909226190476"],[1490949401.33,"9.742373511904763"],[1490949461.33,"9.744977678571429"],[1490949521.33,"9.748139880952381"],[1490949581.33,"9.751302083333334"],[1490949641.33,"9.757440476190476"],[1490949701.33,"9.756324404761905"],[1490949761.33,"9.749813988095237"],[1490949821.33,"9.739025297619047"],[1490949881.33,"9.726004464285714"],[1490949941.33,"9.728236607142858"],[1490950001.33,"9.732514880952381"],[1490950061.33,"9.735119047619047"],[1490950121.33,"9.737165178571429"],[1490950181.33,"9.739025297619047"],[1490950241.33,"9.740513392857142"],[1490950301.33,"9.749441964285714"],[1490950361.33,"9.736979166666666"],[1490950421.33,"9.741629464285714"],[1490950481.33,"9.743303571428571"],[1490950541.33,"9.74609375"],[1490950601.33,"9.75093005952381"],[1490950661.33,"9.724330357142858"],[1490950721.33,"9.726748511904763"],[1490950781.33,"9.733258928571429"],[1490950841.33,"9.744233630952381"],[1490950901.33,"9.734375"],[1490950961.33,"9.737537202380953"],[1490951021.33,"9.741071428571429"],[1490951081.33,"9.757254464285714"],[1490951141.33,"9.760044642857142"],[1490951201.33,"9.755952380952381"],[1490951261.33,"9.745349702380953"],[1490951321.33,"9.746651785714286"],[1490951381.33,"9.749441964285714"],[1490951441.33,"9.751674107142858"],[1490951501.33,"9.757998511904763"],[1490951561.33,"9.756510416666666"],[1490951621.33,"9.76264880952381"],[1490951681.33,"9.765625"],[1490951741.33,"9.757254464285714"],[1490951801.33,"9.751674107142858"],[1490951861.33,"9.754278273809524"],[1490951921.33,"9.744233630952381"],[1490951981.33,"9.745349702380953"],[1490952041.33,"9.748883928571429"],[1490952101.33,"9.753162202380953"],[1490952161.33,"9.747953869047619"],[1490952221.33,"9.750186011904763"],[1490952281.33,"9.751116071428571"],[1490952341.33,"9.753162202380953"],[1490952401.33,"9.758928571428571"],[1490952461.33,"9.758928571428571"],[1490952521.33,"9.755394345238095"],[1490952581.33,"9.758928571428571"],[1490952641.33,"9.761160714285714"],[1490952701.33,"9.763206845238095"],[1490952761.33,"9.767857142857142"],[1490952821.33,"9.765438988095237"],[1490952881.33,"9.768229166666666"],[1490952941.33,"9.780877976190476"],[1490953001.33,"9.77250744047619"],[1490953061.33,"9.784412202380953"],[1490953121.33,"9.77827380952381"],[1490953181.33,"9.781063988095237"],[1490953241.33,"9.783668154761905"],[1490953301.33,"9.787016369047619"],[1490953361.33,"9.784970238095237"],[1490953421.33,"9.787946428571429"],[1490953481.33,"9.788690476190476"],[1490953541.33,"9.790922619047619"],[1490953601.33,"9.792596726190476"],[1490953661.33,"9.79594494047619"],[1490953721.33,"9.79780505952381"],[1490953781.33,"9.800223214285714"],[1490953841.33,"9.794828869047619"],[1490953901.33,"9.799293154761905"],[1490953961.33,"9.801525297619047"],[1490954021.33,"9.786458333333334"],[1490954081.33,"9.773809523809524"],[1490954141.33,"9.767485119047619"],[1490954201.33,"9.760044642857142"],[1490954261.33,"9.751116071428571"],[1490954321.33,"9.752790178571429"],[1490954381.33,"9.753162202380953"],[1490954441.33,"9.744419642857142"],[1490954501.33,"9.73921130952381"],[1490954561.33,"9.74125744047619"],[1490954621.33,"9.743303571428571"],[1490954681.33,"9.745535714285714"],[1490954741.33,"9.746837797619047"],[1490954801.33,"9.749255952380953"],[1490954861.33,"9.744419642857142"],[1490954921.33,"9.745349702380953"],[1490954981.33,"9.74702380952381"],[1490955041.33,"9.738467261904763"],[1490955101.33,"9.740141369047619"],[1490955161.33,"9.747767857142858"],[1490955221.33,"9.750372023809524"],[1490955281.33,"9.747767857142858"],[1490955341.33,"9.739025297619047"],[1490955401.33,"9.745349702380953"],[1490955461.33,"9.730282738095237"],[1490955521.33,"9.73139880952381"],[1490955581.33,"9.722842261904763"],[1490955641.33,"9.725818452380953"],[1490955701.33,"9.72749255952381"],[1490955761.33,"9.72953869047619"],[1490955821.33,"9.731956845238095"],[1490955881.33,"9.735677083333334"],[1490955941.33,"9.738467261904763"],[1490956001.33,"9.735863095238095"],[1490956061.33,"9.743675595238095"],[1490956121.33,"9.730840773809524"],[1490956181.33,"9.734747023809524"],[1490956241.33,"9.736235119047619"],[1490956301.33,"9.736607142857142"],[1490956361.33,"9.73921130952381"],[1490956421.33,"9.742001488095237"],[1490956481.33,"9.743675595238095"],[1490956541.33,"9.744977678571429"],[1490956601.33,"9.748697916666666"],[1490956661.33,"9.760602678571429"],[1490956721.33,"9.751302083333334"],[1490956781.33,"9.754278273809524"],[1490956841.33,"9.756324404761905"],[1490956901.33,"9.758370535714286"],[1490956961.33,"9.760416666666666"],[1490957021.33,"9.763020833333334"],[1490957081.33,"9.766183035714286"],[1490957141.33,"9.764508928571429"],[1490957201.33,"9.767299107142858"],[1490957261.33,"9.768787202380953"],[1490957321.33,"9.771019345238095"],[1490957381.33,"9.773623511904763"],[1490957441.33,"9.775111607142858"],[1490957501.33,"9.779389880952381"],[1490957561.33,"9.780691964285714"],[1490957621.33,"9.788690476190476"],[1490957681.33,"9.794828869047619"],[1490957741.33,"9.779203869047619"],[1490957801.33,"9.787016369047619"],[1490957861.33,"9.783854166666666"],[1490957921.33,"9.78515625"],[1490957981.33,"9.786644345238095"],[1490958041.33,"9.787946428571429"],[1490958101.33,"9.800409226190476"],[1490958161.33,"9.787202380952381"],[1490958221.33,"9.789806547619047"],[1490958281.33,"9.791852678571429"],[1490958341.33,"9.788876488095237"],[1490958401.33,"9.78515625"],[1490958461.33,"9.7890625"],[1490958521.33,"9.791108630952381"],[1490958581.33,"9.792596726190476"],[1490958641.33,"9.794828869047619"],[1490958701.33,"9.793154761904763"],[1490958761.33,"9.799293154761905"],[1490958821.33,"9.797247023809524"],[1490958881.33,"9.794084821428571"],[1490958941.33,"9.796875"],[1490959001.33,"9.763950892857142"],[1490959061.33,"9.765997023809524"],[1490959121.33,"9.767671130952381"],[1490959181.33,"9.77046130952381"],[1490959241.33,"9.773809523809524"],[1490959301.33,"9.765252976190476"],[1490959361.33,"9.767485119047619"],[1490959421.33,"9.76953125"],[1490959481.33,"9.774553571428571"],[1490959541.33,"9.77734375"],[1490959601.33,"9.778459821428571"],[1490959661.33,"9.780877976190476"],[1490959721.33,"9.783296130952381"],[1490959781.33,"9.794828869047619"],[1490959841.33,"9.787016369047619"],[1490959901.33,"9.798735119047619"],[1490959961.33,"9.803013392857142"],[1490960021.33,"9.801525297619047"],[1490960081.33,"9.804873511904763"],[1490960141.33,"9.80078125"],[1490960201.33,"9.80375744047619"],[1490960261.33,"9.805059523809524"],[1490960321.33,"9.807849702380953"],[1490960381.33,"9.810825892857142"],[1490960441.33,"9.813058035714286"],[1490960501.33,"9.813616071428571"],[1490960561.33,"9.815104166666666"],[1490960621.33,"9.81733630952381"],[1490960681.33,"9.812872023809524"],[1490960741.33,"9.814546130952381"],[1490960801.33,"9.808035714285714"],[1490960861.33,"9.810081845238095"],[1490960921.33,"9.813058035714286"],[1490960981.33,"9.825892857142858"],[1490961041.33,"9.816964285714286"],[1490961101.33,"9.82421875"],[1490961161.33,"9.80952380952381"],[1490961221.33,"9.804315476190476"],[1490961281.33,"9.797619047619047"],[1490961341.33,"9.80078125"],[1490961401.33,"9.802827380952381"],[1490961461.33,"9.803199404761905"],[1490961521.33,"9.80952380952381"],[1490961581.33,"9.806919642857142"],[1490961641.33,"9.808779761904763"],[1490961701.33,"9.811197916666666"],[1490961761.33,"9.813244047619047"],[1490961821.33,"9.815662202380953"],[1490961881.33,"9.819940476190476"],[1490961941.33,"9.822172619047619"],[1490962001.33,"9.82328869047619"],[1490962061.33,"9.826822916666666"],[1490962121.33,"9.829241071428571"],[1490962181.33,"9.832589285714286"],[1490962241.33,"9.835565476190476"],[1490962301.33,"9.839471726190476"],[1490962361.33,"9.825520833333334"],[1490962421.33,"9.829427083333334"],[1490962481.33,"9.832217261904763"],[1490962541.33,"9.839285714285714"],[1490962601.33,"9.837611607142858"],[1490962661.33,"9.841145833333334"],[1490962721.33,"9.834077380952381"],[1490962781.33,"9.837239583333334"],[1490962841.33,"9.841703869047619"],[1490962901.33,"9.844308035714286"],[1490962961.33,"9.838727678571429"],[1490963021.33,"9.840587797619047"],[1490963081.33,"9.849516369047619"],[1490963141.33,"9.845238095238095"],[1490963201.33,"9.84375"],[1490963261.33,"9.838541666666666"],[1490963321.33,"9.841889880952381"],[1490963381.33,"9.846354166666666"],[1490963441.33,"9.832403273809524"],[1490963501.33,"9.833891369047619"],[1490963561.33,"9.808221726190476"],[1490963621.33,"9.812686011904763"],[1490963681.33,"9.814918154761905"],[1490963741.33,"9.817708333333334"],[1490963801.33,"9.80561755952381"],[1490963861.33,"9.80859375"],[1490963921.33,"9.811197916666666"],[1490963981.33,"9.802269345238095"],[1490964041.33,"9.798177083333334"],[1490964101.33,"9.80078125"],[1490964161.33,"9.815104166666666"],[1490964221.33,"9.806361607142858"]]}],"memory_current":[{"metric":{},"value":[1490964221.593,"9.806361607142858"]}],"cpu_values":[{"metric":{},"values":[[1490935421.446,"0.011520035833333402"],[1490935481.446,"0.010738020634921052"],[1490935541.446,"0.011830812658730162"],[1490935601.446,"0.011666519206349292"],[1490935661.446,"0.012397734365079505"],[1490935721.446,"0.012264678253967905"],[1490935781.446,"0.011701125396825458"],[1490935841.446,"0.011413869087301435"],[1490935901.446,"0.011355704404762157"],[1490935961.446,"0.01295611777777756"],[1490936021.446,"0.012283088253968812"],[1490936081.446,"0.011711742103174674"],[1490936141.446,"0.011066851150792879"],[1490936201.446,"0.011525933611111726"],[1490936261.446,"0.012260294246031015"],[1490936321.446,"0.011917795238095285"],[1490936381.446,"0.011402582301587626"],[1490936441.446,"0.012311798253968057"],[1490936501.446,"0.011604295476191046"],[1490936561.446,"0.012329014206349137"],[1490936621.446,"0.011401263769840977"],[1490936681.446,"0.012310593492063392"],[1490936741.446,"0.01244334305555575"],[1490936801.446,"0.01176146669320973"],[1490936861.446,"0.011186474629011792"],[1490936921.446,"0.013234800079365536"],[1490936981.446,"0.01217435722222217"],[1490937041.446,"0.011211570753967583"],[1490937101.446,"0.012066252420634934"],[1490937161.446,"0.012175381944444839"],[1490937221.446,"0.011215347936507976"],[1490937281.446,"0.012909065515873003"],[1490937341.446,"0.011718783452381023"],[1490937401.446,"0.011740557499999828"],[1490937461.446,"0.012024899960317205"],[1490937521.446,"0.011518551626984471"],[1490937581.446,"0.013295429607829826"],[1490937641.446,"0.013578758822130006"],[1490937701.446,"0.01170811908668783"],[1490937761.446,"0.011867610238095478"],[1490937821.446,"0.012601599007937034"],[1490937881.446,"0.011028959285714405"],[1490937941.446,"0.011972864523808899"],[1490938001.446,"0.012236090515873134"],[1490938061.446,"0.012468855793650629"],[1490938121.446,"0.012324049999999686"],[1490938181.446,"0.012271810317460288"],[1490938241.446,"0.013109732103174912"],[1490938301.446,"0.01201708535714284"],[1490938361.446,"0.01198280035714318"],[1490938421.446,"0.011631491547618469"],[1490938481.446,"0.012698120317460778"],[1490938541.446,"0.011908042499999686"],[1490938601.446,"0.012941332460317123"],[1490938661.446,"0.012009558055555753"],[1490938721.446,"0.011749238293651211"],[1490938781.446,"0.012597720873015857"],[1490938841.446,"0.012128174365079517"],[1490938901.446,"0.013411003452380428"],[1490938961.446,"0.012712377896825132"],[1490939021.446,"0.0126730261111118"],[1490939081.446,"0.012196438134920173"],[1490939141.446,"0.011617917341270696"],[1490939201.446,"0.012271590992062863"],[1490939261.446,"0.01196238253968261"],[1490939321.446,"0.012446522619048245"],[1490939381.446,"0.013146698134919643"],[1490939441.446,"0.013160663611111774"],[1490939501.446,"0.012921960039682278"],[1490939561.446,"0.012100972380952405"],[1490939621.446,"0.01235039095238153"],[1490939681.446,"0.013303590992062684"],[1490939741.446,"0.012064513055556225"],[1490939801.446,"0.011846763531745252"],[1490939861.446,"0.012280224007936782"],[1490939921.446,"0.012305159166666833"],[1490939981.446,"0.012107076111110887"],[1490940041.446,"0.013109447341269884"],[1490940101.446,"0.011668830198412932"],[1490940161.446,"0.011757771468254286"],[1490940221.446,"0.013607426447330252"],[1490940281.446,"0.012069082212503184"],[1490940341.446,"0.012702448174603309"],[1490940401.446,"0.012915864642857006"],[1490940461.446,"0.012882558941478554"],[1490940521.446,"0.01180430288917485"],[1490940581.446,"0.012561457142856586"],[1490940641.446,"0.013117287261905215"],[1490940701.446,"0.0119707260317455"],[1490940761.446,"0.012110876587301957"],[1490940821.446,"0.012900523174603096"],[1490940881.446,"0.012405300317460836"],[1490940941.446,"0.013397718690476127"],[1490941001.446,"0.011853019404761512"],[1490941061.446,"0.011410178968254279"],[1490941121.446,"0.01385021210317412"],[1490941181.446,"0.012158262658730703"],[1490941241.446,"0.012590782142857021"],[1490941301.446,"0.011902994444444289"],[1490941361.446,"0.012597971468253468"],[1490941421.446,"0.013460530436508394"],[1490941481.446,"0.012871132936507318"],[1490941541.446,"0.012321937023810644"],[1490941601.446,"0.012861435992063004"],[1490941661.446,"0.011904687658730493"],[1490941721.446,"0.013068603849206292"],[1490941781.446,"0.011558027420635053"],[1490941841.446,"0.011785108134920095"],[1490941901.446,"0.013018491984126938"],[1490941961.446,"0.012803318611111494"],[1490942021.446,"0.011276595873015969"],[1490942081.446,"0.012407365753968128"],[1490942141.446,"0.01261537746031769"],[1490942201.446,"0.011981626507936492"],[1490942261.446,"0.011779192579364465"],[1490942321.446,"0.012944439365080001"],[1490942381.446,"0.012563845515873258"],[1490942441.446,"0.012490993809523204"],[1490942501.446,"0.011721826547619399"],[1490942561.446,"0.012376904523809195"],[1490942621.446,"0.012627997539682608"],[1490942681.446,"0.012353236984126971"],[1490942741.446,"0.012143749162511788"],[1490942801.446,"0.01210106380777602"],[1490942861.446,"0.01323092650793727"],[1490942921.446,"0.01217811805555557"],[1490942981.446,"0.011703709655399819"],[1490943041.446,"0.01140056596399108"],[1490943101.446,"0.011589462460317477"],[1490943161.446,"0.011424534784915178"],[1490943221.446,"0.011720420858480131"],[1490943281.446,"0.011956359603174035"],[1490943341.446,"0.011627974444444375"],[1490943401.446,"0.012056417142857899"],[1490943461.446,"0.012875421865079256"],[1490943521.446,"0.011447757222222438"],[1490943581.446,"0.011686728412698438"],[1490943641.446,"0.012264428214285543"],[1490943701.446,"0.011396086150793258"],[1490943761.446,"0.012637377857143453"],[1490943821.446,"0.012229487817460189"],[1490943881.446,"0.012519327516820155"],[1490943941.446,"0.011632154440677021"],[1490944001.446,"0.0127011905614214"],[1490944061.446,"0.012041664776432408"],[1490944121.446,"0.011550796183789442"],[1490944181.446,"0.012340807579364546"],[1490944241.446,"0.012514561706348858"],[1490944301.446,"0.011591095515873378"],[1490944361.446,"0.011562522896825472"],[1490944421.446,"0.012653687499999684"],[1490944481.446,"0.012597878095237767"],[1490944541.446,"0.011373836746032411"],[1490944601.446,"0.011489111309523512"],[1490944661.446,"0.012365606547618906"],[1490944721.446,"0.011246835793650788"],[1490944781.446,"0.011556645833333596"],[1490944841.446,"0.0114839880952384"],[1490944901.446,"0.011559932103174322"],[1490944961.446,"0.011456621547618827"],[1490945021.446,"0.011137903531746323"],[1490945081.446,"0.011371503134920238"],[1490945141.446,"0.01262392527777806"],[1490945201.446,"0.011231213571428417"],[1490945261.446,"0.011834045595238011"],[1490945321.446,"0.011222574087301793"],[1490945381.446,"0.01139294579365124"],[1490945441.446,"0.011876671865079205"],[1490945501.446,"0.012003088888888104"],[1490945561.446,"0.011232171746032069"],[1490945621.446,"0.01189458067460394"],[1490945681.446,"0.011593709801586787"],[1490945741.446,"0.01179023611111146"],[1490945801.446,"0.012056340952381187"],[1490945861.446,"0.011755026706348978"],[1490945921.446,"0.011906753412698057"],[1490945981.446,"0.011362850850868408"],[1490946041.446,"0.011567284784873766"],[1490946101.446,"0.01159940924603172"],[1490946161.446,"0.01169248444646143"],[1490946221.446,"0.011294826570231075"],[1490946281.446,"0.011797972936507535"],[1490946341.446,"0.011732454126984091"],[1490946401.446,"0.011992103412699077"],[1490946461.446,"0.011787900634920185"],[1490946521.446,"0.01170581265873045"],[1490946581.446,"0.011391009603175007"],[1490946641.446,"0.01205839841269773"],[1490946701.446,"0.01188169805555573"],[1490946761.446,"0.011459351746031153"],[1490946821.446,"0.012089251071429255"],[1490946881.446,"0.011159798611111122"],[1490946941.446,"0.012261993650793439"],[1490947001.446,"0.011150941865079526"],[1490947061.446,"0.011784560238095428"],[1490947121.446,"0.01146369333333352"],[1490947181.446,"0.011946112341269969"],[1490947241.446,"0.012244168452380742"],[1490947301.446,"0.01108276087301507"],[1490947361.446,"0.011391418571428976"],[1490947421.446,"0.012042411525379642"],[1490947481.446,"0.012082919141039653"],[1490947541.446,"0.011615924682540189"],[1490947601.446,"0.01218819496031727"],[1490947661.446,"0.011292488293650517"],[1490947721.446,"0.011232974365079479"],[1490947781.446,"0.011638264880952223"],[1490947841.446,"0.0115353722619047"],[1490947901.446,"0.011426710952381045"],[1490947961.446,"0.0121381246428574"],[1490948021.446,"0.011812514087301832"],[1490948081.446,"0.012050580317459442"],[1490948141.446,"0.011855329166666742"],[1490948201.446,"0.011649919960317898"],[1490948261.446,"0.01163187396825391"],[1490948321.446,"0.011266725634920935"],[1490948381.446,"0.011934722460317146"],[1490948441.446,"0.011368148333333088"],[1490948501.446,"0.011662377698413048"],[1490948561.446,"0.011039417341269188"],[1490948621.446,"0.012176113174603589"],[1490948681.446,"0.011265313531746158"],[1490948741.446,"0.01158711781746033"],[1490948801.446,"0.011557390912698215"],[1490948861.446,"0.012131684804188454"],[1490948921.446,"0.011474324082027133"],[1490948981.446,"0.011376334484127639"],[1490949041.446,"0.011627233571428175"],[1490949101.446,"0.012499916785714077"],[1490949161.446,"0.011920621706348947"],[1490949221.446,"0.011574053410790661"],[1490949281.446,"0.011837460242165967"],[1490949341.446,"0.011227153174603937"],[1490949401.446,"0.011635896944444115"],[1490949461.446,"0.011701339047618983"],[1490949521.446,"0.011847283650793895"],[1490949581.446,"0.0116057894841271"],[1490949641.446,"0.011789695753968094"],[1490949701.446,"0.011279284841269992"],[1490949761.446,"0.011470807460317041"],[1490949821.446,"0.012172255515873568"],[1490949881.446,"0.011721892103174175"],[1490949941.446,"0.010727560317460336"],[1490950001.446,"0.011509186269841303"],[1490950061.446,"0.01188623087301566"],[1490950121.446,"0.011476948452380968"],[1490950181.446,"0.01211593166666722"],[1490950241.446,"0.011757469444444444"],[1490950301.446,"0.011519936865079109"],[1490950361.446,"0.01165834781746044"],[1490950421.446,"0.010831068928571068"],[1490950481.446,"0.011977692023809912"],[1490950541.446,"0.011828264880952136"],[1490950601.446,"0.01191921916666625"],[1490950661.446,"0.011901336547619379"],[1490950721.446,"0.011776620238095158"],[1490950781.446,"0.011911536031746153"],[1490950841.446,"0.011467936309523809"],[1490950901.446,"0.012163667023809579"],[1490950961.446,"0.0116551746825399"],[1490951021.446,"0.011799408095237739"],[1490951081.446,"0.011845631309524084"],[1490951141.446,"0.011289116626983809"],[1490951201.446,"0.012258327777777984"],[1490951261.446,"0.012265819682539036"],[1490951321.446,"0.011346034166667811"],[1490951381.446,"0.011996446111110597"],[1490951441.446,"0.011511485714285046"],[1490951501.446,"0.011980616349206635"],[1490951561.446,"0.011565376031746316"],[1490951621.446,"0.010918043373016443"],[1490951681.446,"0.011479107380951632"],[1490951741.446,"0.012467024051997748"],[1490951801.446,"0.01235313125400671"],[1490951861.446,"0.012167793061507889"],[1490951921.446,"0.01249734373015914"],[1490951981.446,"0.011414617499999877"],[1490952041.446,"0.012559693849205949"],[1490952101.446,"0.012135384801587835"],[1490952161.446,"0.01195310698412663"],[1490952221.446,"0.011996730515873409"],[1490952281.446,"0.012245181626984071"],[1490952341.446,"0.01172794166666644"],[1490952401.446,"0.012153839325397124"],[1490952461.446,"0.01287662682539674"],[1490952521.446,"0.011412833611110576"],[1490952581.446,"0.0115385753968256"],[1490952641.446,"0.011953797142857927"],[1490952701.446,"0.012210606230158325"],[1490952761.446,"0.012193429836568915"],[1490952821.446,"0.01175164000191546"],[1490952881.446,"0.011686968928571266"],[1490952941.446,"0.01204885615079335"],[1490953001.446,"0.010858237182540066"],[1490953061.446,"0.012570554523809901"],[1490953121.446,"0.011606933412697877"],[1490953181.446,"0.011895175039682713"],[1490953241.446,"0.011877423888888992"],[1490953301.446,"0.01134354857142876"],[1490953361.446,"0.011999752857142089"],[1490953421.446,"0.011927079960317739"],[1490953481.446,"0.01172722273809559"],[1490953541.446,"0.0114388174999997"],[1490953601.446,"0.012584772738095138"],[1490953661.446,"0.011858990837323214"],[1490953721.446,"0.011489406427467985"],[1490953781.446,"0.011673106071428765"],[1490953841.446,"0.012389803452380168"],[1490953901.446,"0.010877735714285755"],[1490953961.446,"0.012098601984127518"],[1490954021.446,"0.011876002539682478"],[1490954081.446,"0.0119792138492057"],[1490954141.446,"0.01116768142857198"],[1490954201.446,"0.011819058452381173"],[1490954261.446,"0.011543723055555002"],[1490954321.446,"0.011877097777778114"],[1490954381.446,"0.011255818690476465"],[1490954441.446,"0.011544411269840424"],[1490954501.446,"0.011844739246031948"],[1490954561.446,"0.012498686626984624"],[1490954621.446,"0.011012790753967753"],[1490954681.446,"0.011763483769841236"],[1490954741.446,"0.011742064880952764"],[1490954801.446,"0.011329697023809454"],[1490954861.446,"0.011616721150793869"],[1490954921.446,"0.011935843650793056"],[1490954981.446,"0.012041806150794254"],[1490955041.446,"0.011776362817460298"],[1490955101.446,"0.011507964920634838"],[1490955161.446,"0.012249892380951723"],[1490955221.446,"0.011680689451964254"],[1490955281.446,"0.011966289381797203"],[1490955341.446,"0.011113054447726804"],[1490955401.446,"0.012155607703748966"],[1490955461.446,"0.011851554722222412"],[1490955521.446,"0.011899298531746077"],[1490955581.446,"0.01202313674603201"],[1490955641.446,"0.011739823253968055"],[1490955701.446,"0.011866135595237215"],[1490955761.446,"0.012171682563083994"],[1490955821.446,"0.01125473955952014"],[1490955881.446,"0.011791852817460289"],[1490955941.446,"0.011389896547619342"],[1490956001.446,"0.011801524404761971"],[1490956061.446,"0.011788201388888577"],[1490956121.446,"0.011472721388889214"],[1490956181.446,"0.012352298174603236"],[1490956241.446,"0.011831984404761721"],[1490956301.446,"0.0114478640476188"],[1490956361.446,"0.012315896944444986"],[1490956421.446,"0.01184387992063444"],[1490956481.446,"0.0108170579365078"],[1490956541.446,"0.012441825119047971"],[1490956601.446,"0.011650502579365023"],[1490956661.446,"0.011244622936507553"],[1490956721.446,"0.01138462460317496"],[1490956781.446,"0.012361013348424437"],[1490956841.446,"0.011687763677888905"],[1490956901.446,"0.011387440952381297"],[1490956961.446,"0.012246620039682158"],[1490957021.446,"0.010769535198412467"],[1490957081.446,"0.012311013690477024"],[1490957141.446,"0.011455958968253554"],[1490957201.446,"0.012126715198413286"],[1490957261.446,"0.011078292499999627"],[1490957321.446,"0.012041933253967746"],[1490957381.446,"0.01147051317460329"],[1490957441.446,"0.01173451460317538"],[1490957501.446,"0.011660740317459825"],[1490957561.446,"0.011851131269840753"],[1490957621.446,"0.012117949444444812"],[1490957681.446,"0.011214277301587397"],[1490957741.446,"0.011935565277777841"],[1490957801.446,"0.011180848809523986"],[1490957861.446,"0.011540955039682404"],[1490957921.446,"0.011678924523809829"],[1490957981.446,"0.01175049698412655"],[1490958041.446,"0.01179233821428546"],[1490958101.446,"0.011217207341269743"],[1490958161.446,"0.011623496111110998"],[1490958221.446,"0.011751017182540137"],[1490958281.446,"0.011548055515872839"],[1490958341.446,"0.01157145297619062"],[1490958401.446,"0.011809365079364814"],[1490958461.446,"0.011367088134920926"],[1490958521.446,"0.011220626785714515"],[1490958581.446,"0.012502413531745657"],[1490958641.446,"0.011674712222222085"],[1490958701.446,"0.010840117777778147"],[1490958761.446,"0.01169669242063464"],[1490958821.446,"0.01206404448412709"],[1490958881.446,"0.011476003253967956"],[1490958941.446,"0.011927363650794281"],[1490959001.446,"0.011834540039682623"],[1490959061.446,"0.011952310396106811"],[1490959121.446,"0.011641002569963536"],[1490959181.446,"0.011215335912698408"],[1490959241.446,"0.011801235515873079"],[1490959301.446,"0.012109150079365269"],[1490959361.446,"0.011696530238095701"],[1490959421.446,"0.01188721699431308"],[1490959481.446,"0.011013023946272025"],[1490959541.446,"0.011927455988174854"],[1490959601.446,"0.011773952156046168"],[1490959661.446,"0.011311449525742057"],[1490959721.446,"0.011926485873016056"],[1490959781.446,"0.012208613174603443"],[1490959841.446,"0.011077256706349554"],[1490959901.446,"0.012141572896825473"],[1490959961.446,"0.011884196547619123"],[1490960021.446,"0.01182910611111061"],[1490960081.446,"0.011089906190476237"],[1490960141.446,"0.011485851349206303"],[1490960201.446,"0.011621675079365073"],[1490960261.446,"0.011420984246031282"],[1490960321.446,"0.011702707664224543"],[1490960381.446,"0.011122996101531552"],[1490960441.446,"0.011923133293650747"],[1490960501.446,"0.012209551587301823"],[1490960561.446,"0.011541768293650705"],[1490960621.446,"0.01133343007936486"],[1490960681.446,"0.011718844880952742"],[1490960741.446,"0.01170618126984048"],[1490960801.446,"0.01158023575396868"],[1490960861.446,"0.012154581865079351"],[1490960921.446,"0.011287024246031918"],[1490960981.446,"0.012035483412697787"],[1490961041.446,"0.01206407186508005"],[1490961101.446,"0.011742228333332922"],[1490961161.446,"0.011460450952381294"],[1490961221.446,"0.011752177539682223"],[1490961281.446,"0.012416623373015778"],[1490961341.446,"0.01134374146825419"],[1490961401.446,"0.011742214642857577"],[1490961461.446,"0.01157076337301528"],[1490961521.446,"0.011251291190475883"],[1490961581.446,"0.010835279404761772"],[1490961641.446,"0.012082314722223412"],[1490961701.446,"0.011244282817460054"],[1490961761.446,"0.012600352738094536"],[1490961821.446,"0.011595374841270692"],[1490961881.446,"0.012047435158729298"],[1490961941.446,"0.012117879285714984"],[1490962001.446,"0.011105805912698236"],[1490962061.446,"0.011228379365079935"],[1490962121.446,"0.012051188888888457"],[1490962181.446,"0.011811605198411965"],[1490962241.446,"0.011438638690477312"],[1490962301.446,"0.011535638928571016"],[1490962361.446,"0.011846252277212543"],[1490962421.446,"0.011137096779830425"],[1490962481.446,"0.011301488807399701"],[1490962541.446,"0.011706436349206364"],[1490962601.446,"0.011607870952381014"],[1490962661.446,"0.01165941666666676"],[1490962721.446,"0.011457761706349363"],[1490962781.446,"0.012004376428571304"],[1490962841.446,"0.012380191230158676"],[1490962901.446,"0.011650816111111262"],[1490962961.446,"0.011339834484126858"],[1490963021.446,"0.011815001031746352"],[1490963081.446,"0.01215702742063424"],[1490963141.446,"0.011112767612387399"],[1490963201.446,"0.011991515394890143"],[1490963261.446,"0.011573327579365182"],[1490963321.446,"0.011559778809523533"],[1490963381.446,"0.012400119444444207"],[1490963441.446,"0.011127036507936056"],[1490963501.446,"0.012095518055556944"],[1490963561.446,"0.011203742460316668"],[1490963621.446,"0.012493672738095584"],[1490963681.446,"0.012086427023809085"],[1490963741.446,"0.01073350408730215"],[1490963801.446,"0.011784052619047683"],[1490963861.446,"0.011817165277777068"],[1490963921.446,"0.01162805619047661"],[1490963981.446,"0.01141054027777739"],[1490964041.446,"0.012398790952381392"],[1490964101.446,"0.011081906428571691"],[1490964161.446,"0.012049610714285322"],[1490964221.446,"0.011764468492063805"]]}],"cpu_current":[{"metric":{},"value":[1490964221.765,"0.011764468492063801"]}]},"last_update":"2017-03-31T12:43:41.618Z"}
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 70443d27f33..a7c3c281083 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -2,8 +2,10 @@ require 'spec_helper'
describe EventsHelper do
describe '#event_note' do
+ let(:user) { build(:user) }
+
before do
- allow(helper).to receive(:current_user).and_return(double)
+ allow(helper).to receive(:current_user).and_return(user)
end
it 'displays one line of plain text without alteration' do
@@ -60,11 +62,26 @@ describe EventsHelper do
expect(helper.event_note(input)).to eq(expected)
end
- it 'preserves style attribute within a tag' do
- input = '<span class="" style="background-color: #44ad8e; color: #FFFFFF;"></span>'
- expected = '<p><span style="background-color: #44ad8e; color: #FFFFFF;"></span></p>'
+ context 'labels formatting' do
+ let(:input) { 'this should be ~label_1' }
- expect(helper.event_note(input)).to eq(expected)
+ def format_event_note(project)
+ create(:label, title: 'label_1', project: project)
+
+ helper.event_note(input, { project: project })
+ end
+
+ it 'preserves style attribute for a label that can be accessed by current_user' do
+ project = create(:empty_project, :public)
+
+ expect(format_event_note(project)).to match(/span class=.*style=.*/)
+ end
+
+ it 'does not style a label that can not be accessed by current_user' do
+ project = create(:empty_project, :private)
+
+ expect(format_event_note(project)).to eq("<p>#{input}</p>")
+ end
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index fc6ad6419ac..44312ada438 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -167,6 +167,7 @@ describe ProjectsHelper do
before do
allow(project).to receive(:repository_storage_path).and_return('/base/repo/path')
+ allow(Settings.shared).to receive(:[]).with('path').and_return('/base/repo/export/path')
end
it 'removes the repo path' do
@@ -175,6 +176,13 @@ describe ProjectsHelper do
expect(sanitize_repo_path(project, import_error)).to eq('Could not clone [REPOS PATH]/namespace/test.git')
end
+
+ it 'removes the temporary repo path used for uploads/exports' do
+ repo = '/base/repo/export/path/tmp/project_exports/uploads/test.tar.gz'
+ import_error = "Unable to decompress #{repo}\n"
+
+ expect(sanitize_repo_path(project, import_error)).to eq('Unable to decompress [REPO EXPORT PATH]/uploads/test.tar.gz')
+ end
end
describe '#last_push_event' do
diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js
new file mode 100644
index 00000000000..19a4e55a9db
--- /dev/null
+++ b/spec/javascripts/blob/pdf/index_spec.js
@@ -0,0 +1,72 @@
+import renderPDF from '~/blob/pdf';
+import testPDF from './test.pdf';
+
+describe('PDF renderer', () => {
+ let viewer;
+ preloadFixtures('static/pdf_viewer.html.raw');
+
+ beforeEach(() => {
+ loadFixtures('static/pdf_viewer.html.raw');
+ viewer = document.getElementById('js-pdf-viewer');
+ viewer.dataset.endpoint = testPDF;
+ });
+
+ it('shows loading icon', () => {
+ renderPDF();
+
+ expect(
+ document.querySelector('.loading'),
+ ).not.toBeNull();
+ });
+
+ describe('successful response', () => {
+ beforeEach((done) => {
+ renderPDF();
+
+ setTimeout(() => {
+ done();
+ }, 500);
+ });
+
+ it('does not show loading icon', () => {
+ expect(
+ document.querySelector('.loading'),
+ ).toBeNull();
+ });
+
+ it('renders the PDF', () => {
+ expect(
+ document.querySelector('.pdf-viewer'),
+ ).not.toBeNull();
+ });
+
+ it('renders the PDF page', () => {
+ expect(
+ document.querySelector('.pdf-page'),
+ ).not.toBeNull();
+ });
+ });
+
+ describe('error getting file', () => {
+ beforeEach((done) => {
+ viewer.dataset.endpoint = 'invalid/endpoint';
+ renderPDF();
+
+ setTimeout(() => {
+ done();
+ }, 500);
+ });
+
+ it('does not show loading icon', () => {
+ expect(
+ document.querySelector('.loading'),
+ ).toBeNull();
+ });
+
+ it('shows error message', () => {
+ expect(
+ document.querySelector('.md').textContent.trim(),
+ ).toBe('An error occured whilst loading the file. Please try again later.');
+ });
+ });
+});
diff --git a/spec/javascripts/blob/pdf/test.pdf b/spec/javascripts/blob/pdf/test.pdf
new file mode 100644
index 00000000000..eb3d147fde3
--- /dev/null
+++ b/spec/javascripts/blob/pdf/test.pdf
Binary files differ
diff --git a/spec/javascripts/blob/sketch/index_spec.js b/spec/javascripts/blob/sketch/index_spec.js
new file mode 100644
index 00000000000..0e4431548c4
--- /dev/null
+++ b/spec/javascripts/blob/sketch/index_spec.js
@@ -0,0 +1,118 @@
+/* eslint-disable no-new */
+import JSZip from 'jszip';
+import SketchLoader from '~/blob/sketch';
+
+describe('Sketch viewer', () => {
+ const generateZipFileArrayBuffer = (zipFile, resolve, done) => {
+ zipFile
+ .generateAsync({ type: 'arrayBuffer' })
+ .then((content) => {
+ resolve(content);
+
+ setTimeout(() => {
+ done();
+ }, 100);
+ });
+ };
+
+ preloadFixtures('static/sketch_viewer.html.raw');
+
+ beforeEach(() => {
+ loadFixtures('static/sketch_viewer.html.raw');
+ });
+
+ describe('with error message', () => {
+ beforeEach((done) => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve, reject) => {
+ reject();
+
+ setTimeout(() => {
+ done();
+ });
+ }));
+
+ new SketchLoader(document.getElementById('js-sketch-viewer'));
+ });
+
+ it('renders error message', () => {
+ expect(
+ document.querySelector('#js-sketch-viewer p'),
+ ).not.toBeNull();
+
+ expect(
+ document.querySelector('#js-sketch-viewer p').textContent.trim(),
+ ).toContain('Cannot show preview.');
+ });
+
+ it('removes render the loading icon', () => {
+ expect(
+ document.querySelector('.js-loading-icon'),
+ ).toBeNull();
+ });
+ });
+
+ describe('success', () => {
+ beforeEach((done) => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
+ const zipFile = new JSZip();
+ zipFile.folder('previews')
+ .file('preview.png', 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA1JREFUeNoBAgD9/wAAAAIAAVMrnDAAAAAASUVORK5CYII=', {
+ base64: true,
+ });
+
+ generateZipFileArrayBuffer(zipFile, resolve, done);
+ }));
+
+ new SketchLoader(document.getElementById('js-sketch-viewer'));
+ });
+
+ it('does not render error message', () => {
+ expect(
+ document.querySelector('#js-sketch-viewer p'),
+ ).toBeNull();
+ });
+
+ it('removes render the loading icon', () => {
+ expect(
+ document.querySelector('.js-loading-icon'),
+ ).toBeNull();
+ });
+
+ it('renders preview img', () => {
+ const img = document.querySelector('#js-sketch-viewer img');
+
+ expect(img).not.toBeNull();
+ expect(img.classList.contains('img-responsive')).toBeTruthy();
+ });
+
+ it('renders link to image', () => {
+ const img = document.querySelector('#js-sketch-viewer img');
+ const link = document.querySelector('#js-sketch-viewer a');
+
+ expect(link.href).toBe(img.src);
+ expect(link.target).toBe('_blank');
+ });
+ });
+
+ describe('incorrect file', () => {
+ beforeEach((done) => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
+ const zipFile = new JSZip();
+
+ generateZipFileArrayBuffer(zipFile, resolve, done);
+ }));
+
+ new SketchLoader(document.getElementById('js-sketch-viewer'));
+ });
+
+ it('renders error message', () => {
+ expect(
+ document.querySelector('#js-sketch-viewer p'),
+ ).not.toBeNull();
+
+ expect(
+ document.querySelector('#js-sketch-viewer p').textContent.trim(),
+ ).toContain('Cannot show preview.');
+ });
+ });
+});
diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js
new file mode 100644
index 00000000000..3f598887603
--- /dev/null
+++ b/spec/javascripts/boards/board_list_spec.js
@@ -0,0 +1,201 @@
+/* global BoardService */
+/* global boardsMockInterceptor */
+/* global List */
+/* global listObj */
+/* global ListIssue */
+import Vue from 'vue';
+import _ from 'underscore';
+import Sortable from 'vendor/Sortable';
+import BoardList from '~/boards/components/board_list';
+import eventHub from '~/boards/eventhub';
+import '~/boards/mixins/sortable_default_options';
+import '~/boards/models/issue';
+import '~/boards/models/list';
+import '~/boards/stores/boards_store';
+import './mock_data';
+
+window.Sortable = Sortable;
+
+describe('Board list component', () => {
+ let component;
+
+ beforeEach((done) => {
+ const el = document.createElement('div');
+
+ document.body.appendChild(el);
+ Vue.http.interceptors.push(boardsMockInterceptor);
+ gl.boardService = new BoardService('/test/issue-boards/board', '', '1');
+ gl.issueBoards.BoardsStore.create();
+ gl.IssueBoardsApp = new Vue();
+
+ const BoardListComp = Vue.extend(BoardList);
+ const list = new List(listObj);
+ const issue = new ListIssue({
+ title: 'Testing',
+ iid: 1,
+ confidential: false,
+ labels: [],
+ });
+ list.issuesSize = 1;
+ list.issues.push(issue);
+
+ component = new BoardListComp({
+ el,
+ propsData: {
+ disabled: false,
+ list,
+ issues: list.issues,
+ loading: false,
+ issueLinkBase: '/issues',
+ rootPath: '/',
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor);
+ });
+
+ it('renders component', () => {
+ expect(
+ component.$el.classList.contains('board-list-component'),
+ ).toBe(true);
+ });
+
+ it('renders loading icon', (done) => {
+ component.loading = true;
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-list-loading'),
+ ).not.toBeNull();
+
+ done();
+ });
+ });
+
+ it('renders issues', () => {
+ expect(
+ component.$el.querySelectorAll('.card').length,
+ ).toBe(1);
+ });
+
+ it('sets data attribute with issue id', () => {
+ expect(
+ component.$el.querySelector('.card').getAttribute('data-issue-id'),
+ ).toBe('1');
+ });
+
+ it('shows new issue form', (done) => {
+ component.toggleForm();
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-new-issue-form'),
+ ).not.toBeNull();
+
+ expect(
+ component.$el.querySelector('.is-smaller'),
+ ).not.toBeNull();
+
+ done();
+ });
+ });
+
+ it('shows new issue form after eventhub event', (done) => {
+ eventHub.$emit(`hide-issue-form-${component.list.id}`);
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-new-issue-form'),
+ ).not.toBeNull();
+
+ expect(
+ component.$el.querySelector('.is-smaller'),
+ ).not.toBeNull();
+
+ done();
+ });
+ });
+
+ it('does not show new issue form for closed list', (done) => {
+ component.list.type = 'closed';
+ component.toggleForm();
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-new-issue-form'),
+ ).toBeNull();
+
+ done();
+ });
+ });
+
+ it('shows count list item', (done) => {
+ component.showCount = true;
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-list-count'),
+ ).not.toBeNull();
+
+ expect(
+ component.$el.querySelector('.board-list-count').textContent.trim(),
+ ).toBe('Showing all issues');
+
+ done();
+ });
+ });
+
+ it('shows how many more issues to load', (done) => {
+ component.showCount = true;
+ component.list.issuesSize = 20;
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-list-count').textContent.trim(),
+ ).toBe('Showing 1 of 20 issues');
+
+ done();
+ });
+ });
+
+ it('loads more issues after scrolling', (done) => {
+ spyOn(component.list, 'nextPage');
+ component.$refs.list.style.height = '100px';
+ component.$refs.list.style.overflow = 'scroll';
+
+ for (let i = 0; i < 19; i += 1) {
+ const issue = component.list.issues[0];
+ issue.id += 1;
+ component.list.issues.push(issue);
+ }
+
+ Vue.nextTick(() => {
+ component.$refs.list.scrollTop = 20000;
+
+ setTimeout(() => {
+ expect(component.list.nextPage).toHaveBeenCalled();
+
+ done();
+ });
+ });
+ });
+
+ it('shows loading more spinner', (done) => {
+ component.showCount = true;
+ component.list.loadingMore = true;
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.board-list-count .fa-spinner'),
+ ).not.toBeNull();
+
+ done();
+ });
+ });
+});
diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js
index 13840b42bd6..6348d97b0a5 100644
--- a/spec/javascripts/environments/environment_actions_spec.js
+++ b/spec/javascripts/environments/environment_actions_spec.js
@@ -19,6 +19,11 @@ describe('Actions Component', () => {
name: 'foo',
play_path: '#',
},
+ {
+ name: 'foo bar',
+ play_path: 'url',
+ playable: false,
+ },
];
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
@@ -49,4 +54,14 @@ describe('Actions Component', () => {
expect(spy).toHaveBeenCalledWith(actionsMock[0].play_path);
});
+
+ it('should render a disabled action when it\'s not playable', () => {
+ expect(
+ component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
+ ).toEqual('disabled');
+
+ expect(
+ component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
+ ).toEqual(true);
+ });
});
diff --git a/spec/javascripts/environments/environment_spec.js b/spec/javascripts/environments/environment_spec.js
index 9bcf617fcd8..4431baa4b96 100644
--- a/spec/javascripts/environments/environment_spec.js
+++ b/spec/javascripts/environments/environment_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import '~/flash';
import EnvironmentsComponent from '~/environments/components/environment';
-import { environment } from './mock_data';
+import { environment, folder } from './mock_data';
describe('Environment', () => {
preloadFixtures('static/environments/environments.html.raw');
@@ -179,4 +179,101 @@ describe('Environment', () => {
}, 0);
});
});
+
+ describe('expandable folders', () => {
+ const environmentsResponseInterceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify({
+ environments: [folder],
+ stopped_count: 0,
+ available_count: 1,
+ }), {
+ status: 200,
+ headers: {
+ 'X-nExt-pAge': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '1',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '2',
+ },
+ }));
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(environmentsResponseInterceptor);
+ component = new EnvironmentsComponent({
+ el: document.querySelector('#environments-list-view'),
+ });
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(
+ Vue.http.interceptors, environmentsResponseInterceptor,
+ );
+ });
+
+ it('should open a closed folder', (done) => {
+ setTimeout(() => {
+ component.$el.querySelector('.folder-name').click();
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
+ ).toContain('display: none');
+ expect(
+ component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
+ ).not.toContain('display: none');
+ done();
+ });
+ });
+ });
+
+ it('should close an opened folder', (done) => {
+ setTimeout(() => {
+ // open folder
+ component.$el.querySelector('.folder-name').click();
+
+ Vue.nextTick(() => {
+ // close folder
+ component.$el.querySelector('.folder-name').click();
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
+ ).toContain('display: none');
+ expect(
+ component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
+ ).not.toContain('display: none');
+ done();
+ });
+ });
+ });
+ });
+
+ it('should show children environments and a button to show all environments', (done) => {
+ setTimeout(() => {
+ // open folder
+ component.$el.querySelector('.folder-name').click();
+
+ Vue.nextTick(() => {
+ const folderInterceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify({
+ environments: [environment],
+ }), { status: 200 }));
+ };
+
+ Vue.http.interceptors.push(folderInterceptor);
+
+ // wait for next async request
+ setTimeout(() => {
+ expect(component.$el.querySelectorAll('.js-child-row').length).toEqual(1);
+ expect(component.$el.querySelector('td.text-center > a.btn').textContent).toContain('Show all');
+
+ Vue.http.interceptors = _.without(Vue.http.interceptors, folderInterceptor);
+ done();
+ });
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/environments/environments_store_spec.js b/spec/javascripts/environments/environments_store_spec.js
index 115d84b50f5..f617c4bdffe 100644
--- a/spec/javascripts/environments/environments_store_spec.js
+++ b/spec/javascripts/environments/environments_store_spec.js
@@ -1,38 +1,106 @@
import Store from '~/environments/stores/environments_store';
import { environmentsList, serverData } from './mock_data';
-(() => {
- describe('Store', () => {
- let store;
+describe('Store', () => {
+ let store;
- beforeEach(() => {
- store = new Store();
- });
+ beforeEach(() => {
+ store = new Store();
+ });
- it('should start with a blank state', () => {
- expect(store.state.environments.length).toEqual(0);
- expect(store.state.stoppedCounter).toEqual(0);
- expect(store.state.availableCounter).toEqual(0);
- expect(store.state.paginationInformation).toEqual({});
- });
+ it('should start with a blank state', () => {
+ expect(store.state.environments.length).toEqual(0);
+ expect(store.state.stoppedCounter).toEqual(0);
+ expect(store.state.availableCounter).toEqual(0);
+ expect(store.state.paginationInformation).toEqual({});
+ });
+ it('should store environments', () => {
+ store.storeEnvironments(serverData);
+ expect(store.state.environments.length).toEqual(serverData.length);
+ expect(store.state.environments[0]).toEqual(environmentsList[0]);
+ });
+
+ it('should store available count', () => {
+ store.storeAvailableCount(2);
+ expect(store.state.availableCounter).toEqual(2);
+ });
+
+ it('should store stopped count', () => {
+ store.storeStoppedCount(2);
+ expect(store.state.stoppedCounter).toEqual(2);
+ });
+
+ describe('store environments', () => {
it('should store environments', () => {
store.storeEnvironments(serverData);
expect(store.state.environments.length).toEqual(serverData.length);
- expect(store.state.environments[0]).toEqual(environmentsList[0]);
});
- it('should store available count', () => {
- store.storeAvailableCount(2);
- expect(store.state.availableCounter).toEqual(2);
+ it('should add folder keys when environment is a folder', () => {
+ const environment = {
+ name: 'bar',
+ size: 3,
+ id: 2,
+ };
+
+ store.storeEnvironments([environment]);
+ expect(store.state.environments[0].isFolder).toEqual(true);
+ expect(store.state.environments[0].folderName).toEqual('bar');
+ });
+
+ it('should extract content of `latest` key when provided', () => {
+ const environment = {
+ name: 'bar',
+ size: 3,
+ id: 2,
+ latest: {
+ last_deployment: {},
+ isStoppable: true,
+ },
+ };
+
+ store.storeEnvironments([environment]);
+ expect(store.state.environments[0].last_deployment).toEqual({});
+ expect(store.state.environments[0].isStoppable).toEqual(true);
});
- it('should store stopped count', () => {
- store.storeStoppedCount(2);
- expect(store.state.stoppedCounter).toEqual(2);
+ it('should store latest.name when the environment is not a folder', () => {
+ store.storeEnvironments(serverData);
+ expect(store.state.environments[0].name).toEqual(serverData[0].latest.name);
});
- it('should store pagination information', () => {
+ it('should store root level name when environment is a folder', () => {
+ store.storeEnvironments(serverData);
+ expect(store.state.environments[1].folderName).toEqual(serverData[1].name);
+ });
+ });
+
+ describe('toggleFolder', () => {
+ it('should toggle folder', () => {
+ store.storeEnvironments(serverData);
+
+ store.toggleFolder(store.state.environments[1]);
+ expect(store.state.environments[1].isOpen).toEqual(true);
+
+ store.toggleFolder(store.state.environments[1]);
+ expect(store.state.environments[1].isOpen).toEqual(false);
+ });
+ });
+
+ describe('setfolderContent', () => {
+ it('should store folder content', () => {
+ store.storeEnvironments(serverData);
+
+ store.setfolderContent(store.state.environments[1], serverData);
+
+ expect(store.state.environments[1].children.length).toEqual(serverData.length);
+ expect(store.state.environments[1].children[0].isChildren).toEqual(true);
+ });
+ });
+
+ describe('store pagination', () => {
+ it('should store normalized and integer pagination information', () => {
const pagination = {
'X-nExt-pAge': '2',
'X-page': '1',
@@ -55,4 +123,4 @@ import { environmentsList, serverData } from './mock_data';
expect(store.state.paginationInformation).toEqual(expectedResult);
});
});
-})();
+});
diff --git a/spec/javascripts/environments/mock_data.js b/spec/javascripts/environments/mock_data.js
index 30861481cc5..15e11aa686b 100644
--- a/spec/javascripts/environments/mock_data.js
+++ b/spec/javascripts/environments/mock_data.js
@@ -84,3 +84,19 @@ export const environment = {
updated_at: '2017-01-31T10:53:46.894Z',
},
};
+
+export const folder = {
+ folderName: 'build',
+ size: 5,
+ id: 12,
+ name: 'build/update-README',
+ state: 'available',
+ external_url: null,
+ environment_type: 'build',
+ last_deployment: null,
+ 'stop_action?': false,
+ environment_path: '/root/review-app/environments/12',
+ stop_path: '/root/review-app/environments/12/stop',
+ created_at: '2017-02-01T19:42:18.400Z',
+ updated_at: '2017-02-01T19:42:18.400Z',
+};
diff --git a/spec/javascripts/fixtures/pdf_viewer.html.haml b/spec/javascripts/fixtures/pdf_viewer.html.haml
new file mode 100644
index 00000000000..2e57beae54b
--- /dev/null
+++ b/spec/javascripts/fixtures/pdf_viewer.html.haml
@@ -0,0 +1 @@
+.file-content#js-pdf-viewer{ data: { endpoint: '/test' } }
diff --git a/spec/javascripts/fixtures/sketch_viewer.html.haml b/spec/javascripts/fixtures/sketch_viewer.html.haml
new file mode 100644
index 00000000000..f01bd00925a
--- /dev/null
+++ b/spec/javascripts/fixtures/sketch_viewer.html.haml
@@ -0,0 +1,2 @@
+.file-content#js-sketch-viewer{ data: { endpoint: '/test_sketch_file.sketch' } }
+ .js-loading-icon
diff --git a/spec/javascripts/issue_show/issue_title_spec.js b/spec/javascripts/issue_show/issue_title_spec.js
new file mode 100644
index 00000000000..806d728a874
--- /dev/null
+++ b/spec/javascripts/issue_show/issue_title_spec.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import issueTitle from '~/issue_show/issue_title';
+
+describe('Issue Title', () => {
+ let IssueTitleComponent;
+
+ beforeEach(() => {
+ IssueTitleComponent = Vue.extend(issueTitle);
+ });
+
+ it('should render a title', () => {
+ const component = new IssueTitleComponent({
+ propsData: {
+ initialTitle: 'wow',
+ endpoint: '/gitlab-org/gitlab-shell/issues/9/rendered_title',
+ },
+ }).$mount();
+
+ expect(component.$el.classList).toContain('title');
+ expect(component.$el.innerHTML).toContain('wow');
+ });
+});
diff --git a/spec/javascripts/lib/utils/number_utility_spec.js b/spec/javascripts/lib/utils/number_utility_spec.js
new file mode 100644
index 00000000000..5fde8be9123
--- /dev/null
+++ b/spec/javascripts/lib/utils/number_utility_spec.js
@@ -0,0 +1,41 @@
+import { formatRelevantDigits } from '~/lib/utils/number_utils';
+
+describe('Number Utils', () => {
+ describe('formatRelevantDigits', () => {
+ it('returns an empty string when the number is NaN', () => {
+ expect(formatRelevantDigits('fail')).toBe('');
+ });
+
+ it('returns 4 decimals when there is 4 plus digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('1000.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(4);
+ expect(leftFromDecimal.length).toBe(4);
+ });
+
+ it('returns 3 decimals when there is 1 digit to the left', () => {
+ const formattedNumber = formatRelevantDigits('0.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(3);
+ expect(leftFromDecimal.length).toBe(1);
+ });
+
+ it('returns 2 decimals when there is 2 digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('10.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(2);
+ expect(leftFromDecimal.length).toBe(2);
+ });
+
+ it('returns 1 decimal when there is 3 digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('100.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(1);
+ expect(leftFromDecimal.length).toBe(3);
+ });
+ });
+});
diff --git a/spec/javascripts/monitoring/prometheus_graph_spec.js b/spec/javascripts/monitoring/prometheus_graph_spec.js
index a3c1c5e1b7c..c2bcd9c0f7c 100644
--- a/spec/javascripts/monitoring/prometheus_graph_spec.js
+++ b/spec/javascripts/monitoring/prometheus_graph_spec.js
@@ -37,9 +37,11 @@ describe('PrometheusGraph', () => {
it('transforms the data', () => {
this.prometheusGraph.init(prometheusMockData.metrics);
- expect(this.prometheusGraph.data).toBeDefined();
- expect(this.prometheusGraph.data.cpu_values.length).toBe(121);
- expect(this.prometheusGraph.data.memory_values.length).toBe(121);
+ Object.keys(this.prometheusGraph.graphSpecificProperties, (key) => {
+ const graphProps = this.prometheusGraph.graphSpecificProperties[key];
+ expect(graphProps.data).toBeDefined();
+ expect(graphProps.data.length).toBe(121);
+ });
});
it('creates two graphs', () => {
@@ -68,7 +70,7 @@ describe('PrometheusGraph', () => {
expect($prometheusGraphContents.find('.label-y-axis-line')).toBeDefined();
expect($prometheusGraphContents.find('.label-axis-text')).toBeDefined();
expect($prometheusGraphContents.find('.rect-axis-text')).toBeDefined();
- expect($axisLabelContainer.find('rect').length).toBe(2);
+ expect($axisLabelContainer.find('rect').length).toBe(3);
expect($axisLabelContainer.find('text').length).toBe(4);
});
});
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index b30c5da8822..07dc51a7815 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -64,6 +64,7 @@ if (process.env.BABEL_ENV === 'coverage') {
'./snippet/snippet_bundle.js',
'./terminal/terminal_bundle.js',
'./users/users_bundle.js',
+ './issue_show/index.js',
];
describe('Uncovered files', function () {
diff --git a/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js
index dba998c7688..0910df61915 100644
--- a/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js
+++ b/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js
@@ -15,6 +15,11 @@ describe('Pipelines Actions dropdown', () => {
name: 'stop_review',
path: '/root/review-app/builds/1893/play',
},
+ {
+ name: 'foo',
+ path: '#',
+ playable: false,
+ },
];
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
@@ -59,4 +64,14 @@ describe('Pipelines Actions dropdown', () => {
expect(component.$el.querySelector('.fa-spinner')).toEqual(null);
});
+
+ it('should render a disabled action when it\'s not playable', () => {
+ expect(
+ component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
+ ).toEqual('disabled');
+
+ expect(
+ component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
+ ).toEqual(true);
+ });
});
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
new file mode 100644
index 00000000000..897288b8ad5
--- /dev/null
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe Banzai::Filter::MarkdownFilter, lib: true do
+ include FilterSpecHelper
+
+ context 'code block' do
+ it 'adds language to lang attribute when specified' do
+ result = filter("```html\nsome code\n```")
+
+ expect(result).to start_with("\n<pre><code lang=\"html\">")
+ end
+
+ it 'does not add language to lang attribute when not specified' do
+ result = filter("```\nsome code\n```")
+
+ expect(result).to start_with("\n<pre><code>")
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index b4cd5f63a15..fdbc65b5e00 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -49,11 +49,12 @@ describe Banzai::Filter::SanitizationFilter, lib: true do
instance = described_class.new('Foo')
3.times { instance.whitelist }
- expect(instance.whitelist[:transformers].size).to eq 5
+ expect(instance.whitelist[:transformers].size).to eq 4
end
- it 'allows syntax highlighting' do
- exp = act = %q{<pre class="code highlight white c"><code><span class="k">def</span></code></pre>}
+ it 'sanitizes `class` attribute from all elements' do
+ act = %q{<pre class="code highlight white c"><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>}
+ exp = %q{<pre><code>&lt;span class="k"&gt;def&lt;/span&gt;</code></pre>}
expect(filter(act).to_html).to eq exp
end
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 63fb1bb25c4..f61fc8ceb9e 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -12,14 +12,14 @@ describe Banzai::Filter::SyntaxHighlightFilter, lib: true do
context "when a valid language is specified" do
it "highlights as that language" do
- result = filter('<pre><code class="ruby">def fun end</code></pre>')
+ result = filter('<pre><code lang="ruby">def fun end</code></pre>')
expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre>')
end
end
context "when an invalid language is specified" do
it "highlights as plaintext" do
- result = filter('<pre><code class="gnuplot">This is a test</code></pre>')
+ result = filter('<pre><code lang="gnuplot">This is a test</code></pre>')
expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
end
end
@@ -30,7 +30,7 @@ describe Banzai::Filter::SyntaxHighlightFilter, lib: true do
end
it "highlights as plaintext" do
- result = filter('<pre><code class="ruby">This is a test</code></pre>')
+ result = filter('<pre><code lang="ruby">This is a test</code></pre>')
expect(result.to_html).to eq('<pre class="code highlight" lang="" v-pre="true"><code>This is a test</code></pre>')
end
end
diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb
index 4b08a02ec73..6675d26734e 100644
--- a/spec/lib/gitlab/backend/shell_spec.rb
+++ b/spec/lib/gitlab/backend/shell_spec.rb
@@ -69,6 +69,15 @@ describe Gitlab::Shell, lib: true do
expect(io).to have_received(:puts).with("key-42\tssh-rsa foo")
end
+ it 'handles multiple spaces in the key' do
+ io = spy(:io)
+ adder = described_class.new(io)
+
+ adder.add_key('key-42', "ssh-rsa foo")
+
+ expect(io).to have_received(:puts).with("key-42\tssh-rsa foo")
+ end
+
it 'raises an exception if the key contains a tab' do
expect do
described_class.new(StringIO.new).add_key('key-42', "ssh-rsa\tfoobar")
diff --git a/spec/lib/gitlab/git/attributes_spec.rb b/spec/lib/gitlab/git/attributes_spec.rb
index 9c011e34c11..1cfd8db09a5 100644
--- a/spec/lib/gitlab/git/attributes_spec.rb
+++ b/spec/lib/gitlab/git/attributes_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Git::Attributes, seed_helper: true do
let(:path) do
- File.join(SEED_REPOSITORY_PATH, 'with-git-attributes.git')
+ File.join(SEED_STORAGE_PATH, 'with-git-attributes.git')
end
subject { described_class.new(path) }
@@ -141,7 +141,7 @@ describe Gitlab::Git::Attributes, seed_helper: true do
end
it 'does not yield when the attributes file has an unsupported encoding' do
- path = File.join(SEED_REPOSITORY_PATH, 'with-invalid-git-attributes.git')
+ path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git')
attrs = described_class.new(path)
expect { |b| attrs.each_line(&b) }.not_to yield_control
diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb
index e169f5af6b6..8b041ac69b1 100644
--- a/spec/lib/gitlab/git/blame_spec.rb
+++ b/spec/lib/gitlab/git/blame_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
describe Gitlab::Git::Blame, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:blame) do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index b883526151e..3f494257545 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -3,7 +3,7 @@
require "spec_helper"
describe Gitlab::Git::Blob, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
describe 'initialize' do
let(:blob) { Gitlab::Git::Blob.new(name: 'test') }
diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb
index 78234b396c5..cdf1b8beee3 100644
--- a/spec/lib/gitlab/git/branch_spec.rb
+++ b/spec/lib/gitlab/git/branch_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Branch, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
subject { repository.branches }
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 5cf4631fbfc..3e44c577643 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Commit, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:commit) { Gitlab::Git::Commit.find(repository, SeedRepo::Commit::ID) }
let(:rugged_commit) do
repository.rugged.lookup(SeedRepo::Commit::ID)
@@ -9,7 +9,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
describe "Commit info" do
before do
- repo = Gitlab::Git::Repository.new(TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
@committer = {
email: 'mike@smith.com',
@@ -59,7 +59,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
after do
# Erase the new commit so other tests get the original repo
- repo = Gitlab::Git::Repository.new(TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
end
@@ -95,7 +95,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
end
context 'with broken repo' do
- let(:repository) { Gitlab::Git::Repository.new(TEST_BROKEN_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH) }
it 'returns nil' do
expect(Gitlab::Git::Commit.find(repository, SeedRepo::Commit::ID)).to be_nil
diff --git a/spec/lib/gitlab/git/compare_spec.rb b/spec/lib/gitlab/git/compare_spec.rb
index e28debe1494..7c45071ec45 100644
--- a/spec/lib/gitlab/git/compare_spec.rb
+++ b/spec/lib/gitlab/git/compare_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Compare, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:compare) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, false) }
let(:compare_straight) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, true) }
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 992126ef153..7253a2edeff 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Diff, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
before do
@raw_diff_hash = {
diff --git a/spec/lib/gitlab/git/encoding_helper_spec.rb b/spec/lib/gitlab/git/encoding_helper_spec.rb
index 83311536893..27bcc241b82 100644
--- a/spec/lib/gitlab/git/encoding_helper_spec.rb
+++ b/spec/lib/gitlab/git/encoding_helper_spec.rb
@@ -2,7 +2,7 @@ require "spec_helper"
describe Gitlab::Git::EncodingHelper do
let(:ext_class) { Class.new { extend Gitlab::Git::EncodingHelper } }
- let(:binary_string) { File.join(SEED_REPOSITORY_PATH, 'gitlab_logo.png') }
+ let(:binary_string) { File.join(SEED_STORAGE_PATH, 'gitlab_logo.png') }
describe '#encode!' do
[
diff --git a/spec/lib/gitlab/git/index_spec.rb b/spec/lib/gitlab/git/index_spec.rb
index d0c7ca60ddc..07d71f6777d 100644
--- a/spec/lib/gitlab/git/index_spec.rb
+++ b/spec/lib/gitlab/git/index_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::Git::Index, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:index) { described_class.new(repository) }
before do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index d4b7684adfd..7e8bb796e03 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Repository, seed_helper: true do
include Gitlab::Git::EncodingHelper
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
describe "Respond to" do
subject { repository }
@@ -14,6 +14,32 @@ describe Gitlab::Git::Repository, seed_helper: true do
it { is_expected.to respond_to(:tags) }
end
+ describe '#root_ref' do
+ context 'with gitaly disabled' do
+ before { allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false) }
+
+ it 'calls #discover_default_branch' do
+ expect(repository).to receive(:discover_default_branch)
+ repository.root_ref
+ end
+ end
+
+ context 'with gitaly enabled' do
+ before { stub_gitaly }
+
+ it 'gets the branch name from GitalyClient' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:default_branch_name)
+ repository.root_ref
+ end
+
+ it 'wraps GRPC exceptions' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:default_branch_name).
+ and_raise(GRPC::Unknown)
+ expect { repository.root_ref }.to raise_error(Gitlab::Git::CommandError)
+ end
+ end
+ end
+
describe "#discover_default_branch" do
let(:master) { 'master' }
let(:feature) { 'feature' }
@@ -55,6 +81,21 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
it { is_expected.to include("master") }
it { is_expected.not_to include("branch-from-space") }
+
+ context 'with gitaly enabled' do
+ before { stub_gitaly }
+
+ it 'gets the branch names from GitalyClient' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:branch_names)
+ subject
+ end
+
+ it 'wraps GRPC exceptions' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:branch_names).
+ and_raise(GRPC::Unknown)
+ expect { subject }.to raise_error(Gitlab::Git::CommandError)
+ end
+ end
end
describe '#tag_names' do
@@ -71,6 +112,21 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
it { is_expected.to include("v1.0.0") }
it { is_expected.not_to include("v5.0.0") }
+
+ context 'with gitaly enabled' do
+ before { stub_gitaly }
+
+ it 'gets the tag names from GitalyClient' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:tag_names)
+ subject
+ end
+
+ it 'wraps GRPC exceptions' do
+ expect_any_instance_of(Gitlab::GitalyClient::Ref).to receive(:tag_names).
+ and_raise(GRPC::Unknown)
+ expect { subject }.to raise_error(Gitlab::Git::CommandError)
+ end
+ end
end
shared_examples 'archive check' do |extenstion|
@@ -221,7 +277,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
context '#submodules' do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
context 'where repo has submodules' do
let(:submodules) { repository.submodules('master') }
@@ -290,9 +346,9 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe "#reset" do
- change_path = File.join(TEST_NORMAL_REPO_PATH, "CHANGELOG")
- untracked_path = File.join(TEST_NORMAL_REPO_PATH, "UNTRACKED")
- tracked_path = File.join(TEST_NORMAL_REPO_PATH, "files", "ruby", "popen.rb")
+ change_path = File.join(SEED_STORAGE_PATH, TEST_NORMAL_REPO_PATH, "CHANGELOG")
+ untracked_path = File.join(SEED_STORAGE_PATH, TEST_NORMAL_REPO_PATH, "UNTRACKED")
+ tracked_path = File.join(SEED_STORAGE_PATH, TEST_NORMAL_REPO_PATH, "files", "ruby", "popen.rb")
change_text = "New changelog text"
untracked_text = "This file is untracked"
@@ -311,7 +367,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
f.write(untracked_text)
end
- @normal_repo = Gitlab::Git::Repository.new(TEST_NORMAL_REPO_PATH)
+ @normal_repo = Gitlab::Git::Repository.new('default', TEST_NORMAL_REPO_PATH)
@normal_repo.reset("HEAD", :hard)
end
@@ -354,7 +410,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context "-b" do
before(:all) do
- @normal_repo = Gitlab::Git::Repository.new(TEST_NORMAL_REPO_PATH)
+ @normal_repo = Gitlab::Git::Repository.new('default', TEST_NORMAL_REPO_PATH)
@normal_repo.checkout(new_branch, { b: true }, "origin/feature")
end
@@ -382,7 +438,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context "without -b" do
context "and specifying a nonexistent branch" do
it "should not do anything" do
- normal_repo = Gitlab::Git::Repository.new(TEST_NORMAL_REPO_PATH)
+ normal_repo = Gitlab::Git::Repository.new('default', TEST_NORMAL_REPO_PATH)
expect { normal_repo.checkout(new_branch) }.to raise_error(Rugged::ReferenceError)
expect(normal_repo.rugged.branches[new_branch]).to be_nil
@@ -402,7 +458,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context "and with a valid branch" do
before(:all) do
- @normal_repo = Gitlab::Git::Repository.new(TEST_NORMAL_REPO_PATH)
+ @normal_repo = Gitlab::Git::Repository.new('default', TEST_NORMAL_REPO_PATH)
@normal_repo.rugged.branches.create("feature", "origin/feature")
@normal_repo.checkout("feature")
end
@@ -414,13 +470,13 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
it "should update the working directory" do
- File.open(File.join(TEST_NORMAL_REPO_PATH, ".gitignore"), "r") do |f|
+ File.open(File.join(SEED_STORAGE_PATH, TEST_NORMAL_REPO_PATH, ".gitignore"), "r") do |f|
expect(f.read.each_line.to_a).not_to include(".DS_Store\n")
end
end
after(:all) do
- FileUtils.rm_rf(TEST_NORMAL_REPO_PATH)
+ FileUtils.rm_rf(SEED_STORAGE_PATH, TEST_NORMAL_REPO_PATH)
ensure_seeds
end
end
@@ -429,7 +485,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#delete_branch" do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.delete_branch("feature")
end
@@ -449,7 +505,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#create_branch" do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
end
it "should create a new branch" do
@@ -496,7 +552,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_delete" do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.remote_delete("expendable")
end
@@ -512,7 +568,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_add" do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.remote_add("new_remote", SeedHelper::GITLAB_GIT_TEST_REPO_URL)
end
@@ -528,7 +584,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_update" do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.remote_update("expendable", url: TEST_NORMAL_REPO_PATH)
end
@@ -551,7 +607,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
before(:context) do
# Add new commits so that there's a renamed file in the commit history
- repo = Gitlab::Git::Repository.new(TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
commit_with_old_name = new_commit_edit_old_file(repo)
rename_commit = new_commit_move_file(repo)
@@ -560,7 +616,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
after(:context) do
# Erase our commits so other tests get the original repo
- repo = Gitlab::Git::Repository.new(TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
@@ -885,7 +941,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#autocrlf' do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.rugged.config['core.autocrlf'] = true
end
@@ -900,14 +956,14 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#autocrlf=' do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
@repo.rugged.config['core.autocrlf'] = false
end
it 'should set the autocrlf option to the provided option' do
@repo.autocrlf = :input
- File.open(File.join(TEST_MUTABLE_REPO_PATH, '.git', 'config')) do |config_file|
+ File.open(File.join(SEED_STORAGE_PATH, TEST_MUTABLE_REPO_PATH, '.git', 'config')) do |config_file|
expect(config_file.read).to match('autocrlf = input')
end
end
@@ -999,7 +1055,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe "#copy_gitattributes" do
- let(:attributes_path) { File.join(TEST_REPO_PATH, 'info/attributes') }
+ let(:attributes_path) { File.join(SEED_STORAGE_PATH, TEST_REPO_PATH, 'info/attributes') }
it "raises an error with invalid ref" do
expect { repository.copy_gitattributes("invalid") }.to raise_error(Gitlab::Git::Repository::InvalidRef)
@@ -1075,7 +1131,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe '#diffable' do
- info_dir_path = attributes_path = File.join(TEST_REPO_PATH, 'info')
+ info_dir_path = attributes_path = File.join(SEED_STORAGE_PATH, TEST_REPO_PATH, 'info')
attributes_path = File.join(info_dir_path, 'attributes')
before(:all) do
@@ -1143,7 +1199,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#local_branches' do
before(:all) do
- @repo = Gitlab::Git::Repository.new(TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
end
after(:all) do
@@ -1235,4 +1291,11 @@ describe Gitlab::Git::Repository, seed_helper: true do
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
end
+
+ def stub_gitaly
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(true)
+
+ stub = double(:stub)
+ allow(Gitaly::Ref::Stub).to receive(:new).and_return(stub)
+ end
end
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index ad469e94735..67a9c974298 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Tag, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
describe 'first tag' do
let(:tag) { repository.tags.first }
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 82685712b5b..4b76a43e6b5 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -2,7 +2,7 @@ require "spec_helper"
describe Gitlab::Git::Tree, seed_helper: true do
context :repo do
- let(:repository) { Gitlab::Git::Repository.new(TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
let(:tree) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID) }
it { expect(tree).to be_kind_of Array }
diff --git a/spec/lib/gitlab/gitaly_client/notifications_spec.rb b/spec/lib/gitlab/gitaly_client/notifications_spec.rb
index bb5d93994ad..39c2048fef8 100644
--- a/spec/lib/gitlab/gitaly_client/notifications_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/notifications_spec.rb
@@ -2,12 +2,15 @@ require 'spec_helper'
describe Gitlab::GitalyClient::Notifications do
describe '#post_receive' do
+ let(:project) { create(:empty_project) }
+ let(:repo_path) { project.repository.path_to_repo }
+ subject { described_class.new(project.repository_storage, project.full_path + '.git') }
+
it 'sends a post_receive message' do
- repo_path = create(:empty_project).repository.path_to_repo
expect_any_instance_of(Gitaly::Notifications::Stub).
- to receive(:post_receive).with(post_receive_request_with_repo_path(repo_path))
+ to receive(:post_receive).with(gitaly_request_with_repo_path(repo_path))
- described_class.new(repo_path).post_receive
+ subject.post_receive
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_spec.rb b/spec/lib/gitlab/gitaly_client/ref_spec.rb
new file mode 100644
index 00000000000..79c9ca993e4
--- /dev/null
+++ b/spec/lib/gitlab/gitaly_client/ref_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe Gitlab::GitalyClient::Ref do
+ let(:project) { create(:empty_project) }
+ let(:repo_path) { project.repository.path_to_repo }
+ let(:client) { Gitlab::GitalyClient::Ref.new(project.repository_storage, project.full_path + '.git') }
+
+ before do
+ allow(Gitlab.config.gitaly).to receive(:enabled).and_return(true)
+ end
+
+ describe '#branch_names' do
+ it 'sends a find_all_branch_names message' do
+ expect_any_instance_of(Gitaly::Ref::Stub).
+ to receive(:find_all_branch_names).with(gitaly_request_with_repo_path(repo_path)).
+ and_return([])
+
+ client.branch_names
+ end
+ end
+
+ describe '#tag_names' do
+ it 'sends a find_all_tag_names message' do
+ expect_any_instance_of(Gitaly::Ref::Stub).
+ to receive(:find_all_tag_names).with(gitaly_request_with_repo_path(repo_path)).
+ and_return([])
+
+ client.tag_names
+ end
+ end
+
+ describe '#default_branch_name' do
+ it 'sends a find_default_branch_name message' do
+ expect_any_instance_of(Gitaly::Ref::Stub).
+ to receive(:find_default_branch_name).with(gitaly_request_with_repo_path(repo_path)).
+ and_return(double(name: 'foo'))
+
+ client.default_branch_name
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index d1902766b99..a2e3b06989e 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -159,6 +159,8 @@ project:
- external_wiki_service
- kubernetes_service
- mock_ci_service
+- mock_deployment_service
+- mock_monitoring_service
- forked_project_link
- forked_from_project
- forked_project_links
diff --git a/spec/lib/gitlab/import_export/fork_spec.rb b/spec/lib/gitlab/import_export/fork_spec.rb
new file mode 100644
index 00000000000..c5ce06afd73
--- /dev/null
+++ b/spec/lib/gitlab/import_export/fork_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe 'forked project import', services: true do
+ let(:user) { create(:user) }
+ let!(:project_with_repo) { create(:project, :test_repo, name: 'test-repo-restorer', path: 'test-repo-restorer') }
+ let!(:project) { create(:empty_project) }
+ let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
+ let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: project.path_with_namespace) }
+ let(:forked_from_project) { create(:project) }
+ let(:fork_link) { create(:forked_project_link, forked_from_project: project_with_repo) }
+ let(:repo_saver) { Gitlab::ImportExport::RepoSaver.new(project: project_with_repo, shared: shared) }
+ let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.project_bundle_filename) }
+
+ let(:repo_restorer) do
+ Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: bundle_path, shared: shared, project: project)
+ end
+
+ let!(:merge_request) do
+ create(:merge_request, source_project: fork_link.forked_to_project, target_project: project_with_repo)
+ end
+
+ let(:saver) do
+ Gitlab::ImportExport::ProjectTreeSaver.new(project: project_with_repo, current_user: user, shared: shared)
+ end
+
+ let(:restorer) do
+ Gitlab::ImportExport::ProjectTreeRestorer.new(user: user, shared: shared, project: project)
+ end
+
+ before do
+ allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+
+ saver.save
+ repo_saver.save
+
+ repo_restorer.restore
+ restorer.restore
+ end
+
+ after do
+ FileUtils.rm_rf(export_path)
+ FileUtils.rm_rf(project_with_repo.repository.path_to_repo)
+ FileUtils.rm_rf(project.repository.path_to_repo)
+ end
+
+ it 'can access the MR' do
+ expect(project.merge_requests.first.ensure_ref_fetched.first).to include('refs/merge-requests/1/head')
+ end
+end
diff --git a/spec/lib/gitlab/import_export/hash_util_spec.rb b/spec/lib/gitlab/import_export/hash_util_spec.rb
new file mode 100644
index 00000000000..1c3a0b23ece
--- /dev/null
+++ b/spec/lib/gitlab/import_export/hash_util_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Gitlab::ImportExport::HashUtil, lib: true do
+ let(:stringified_array) { [{ 'test' => 1 }] }
+ let(:stringified_array_with_date) { [{ 'test_date' => '2016-04-06 06:17:44 +0200' }] }
+
+ describe '.deep_symbolize_array!' do
+ it 'symbolizes keys' do
+ expect { described_class.deep_symbolize_array!(stringified_array) }.to change {
+ stringified_array.first.keys.first
+ }.from('test').to(:test)
+ end
+ end
+
+ describe '.deep_symbolize_array_with_date!' do
+ it 'symbolizes keys' do
+ expect { described_class.deep_symbolize_array_with_date!(stringified_array_with_date) }.to change {
+ stringified_array_with_date.first.keys.first
+ }.from('test_date').to(:test_date)
+ end
+
+ it 'transforms date strings into Time objects' do
+ expect { described_class.deep_symbolize_array_with_date!(stringified_array_with_date) }.to change {
+ stringified_array_with_date.first.values.first.class
+ }.from(String).to(ActiveSupport::TimeWithZone)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/merge_request_parser_spec.rb b/spec/lib/gitlab/import_export/merge_request_parser_spec.rb
new file mode 100644
index 00000000000..349be4596b6
--- /dev/null
+++ b/spec/lib/gitlab/import_export/merge_request_parser_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe Gitlab::ImportExport::MergeRequestParser do
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, :test_repo, name: 'test-repo-restorer', path: 'test-repo-restorer') }
+ let(:forked_from_project) { create(:project) }
+ let(:fork_link) { create(:forked_project_link, forked_from_project: project) }
+
+ let!(:merge_request) do
+ create(:merge_request, source_project: fork_link.forked_to_project, target_project: project)
+ end
+
+ let(:parsed_merge_request) do
+ described_class.new(project,
+ merge_request.diff_head_sha,
+ merge_request,
+ merge_request.as_json).parse!
+ end
+
+ after do
+ FileUtils.rm_rf(project.repository.path_to_repo)
+ end
+
+ it 'has a source branch' do
+ expect(project.repository.branch_exists?(parsed_merge_request.source_branch)).to be true
+ end
+
+ it 'has a target branch' do
+ expect(project.repository.branch_exists?(parsed_merge_request.target_branch)).to be true
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index c36f12dbd82..af9c25acb02 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -82,6 +82,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do
expect(MergeRequestDiff.where.not(st_diffs: nil).count).to eq(9)
end
+ it 'has the correct time for merge request st_commits' do
+ st_commits = MergeRequestDiff.where.not(st_commits: nil).first.st_commits
+
+ expect(st_commits.first[:committed_date]).to be_kind_of(Time)
+ end
+
it 'has labels associated to label links, associated to issues' do
expect(Label.first.label_links.first.target).not_to be_nil
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index 012c22ec5ad..d2d89e3b019 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -79,6 +79,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
expect(saved_project_json['merge_requests'].first['merge_request_diff']).not_to be_empty
end
+ it 'has merge requests diff st_diffs' do
+ expect(saved_project_json['merge_requests'].first['merge_request_diff']['utf8_st_diffs']).not_to be_nil
+ end
+
it 'has merge requests comments' do
expect(saved_project_json['merge_requests'].first['notes']).not_to be_empty
end
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb
index 57e412b0cef..fcc23a75ca1 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::ImportExport::RelationFactory, lib: true do
relation_hash: relation_hash,
members_mapper: members_mapper,
user: user,
- project_id: project.id)
+ project: project)
end
context 'hook object' do
diff --git a/spec/lib/gitlab/import_export/repo_bundler_spec.rb b/spec/lib/gitlab/import_export/repo_saver_spec.rb
index a7f4e11271e..a7f4e11271e 100644
--- a/spec/lib/gitlab/import_export/repo_bundler_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_saver_spec.rb
diff --git a/spec/lib/gitlab/o_auth/user_spec.rb b/spec/lib/gitlab/o_auth/user_spec.rb
index 6c84a4c8b73..8f09266c3b3 100644
--- a/spec/lib/gitlab/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/o_auth/user_spec.rb
@@ -40,6 +40,15 @@ describe Gitlab::OAuth::User, lib: true do
let(:provider) { 'twitter' }
describe 'signup' do
+ it 'marks user as having password_automatically_set' do
+ stub_omniauth_config(allow_single_sign_on: ['twitter'], external_providers: ['twitter'])
+
+ oauth_user.save
+
+ expect(gl_user).to be_persisted
+ expect(gl_user).to be_password_automatically_set
+ end
+
shared_examples 'to verify compliance with allow_single_sign_on' do
context 'provider is marked as external' do
it 'marks user as external' do
diff --git a/spec/lib/gitlab/polling_interval_spec.rb b/spec/lib/gitlab/polling_interval_spec.rb
index 56c2847e26a..5ea8ecb1c30 100644
--- a/spec/lib/gitlab/polling_interval_spec.rb
+++ b/spec/lib/gitlab/polling_interval_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::PollingInterval, lib: true do
it 'sets value to -1' do
polling_interval.set_header(response, interval: 10_000)
- expect(headers['Poll-Interval']).to eq(-1)
+ expect(headers['Poll-Interval']).to eq('-1')
end
end
@@ -27,7 +27,7 @@ describe Gitlab::PollingInterval, lib: true do
it 'applies modifier to base interval' do
polling_interval.set_header(response, interval: 10_000)
- expect(headers['Poll-Interval']).to eq(3333)
+ expect(headers['Poll-Interval']).to eq('3333')
end
end
end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index 9a8096208db..e0ebea63eb4 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -41,8 +41,10 @@ describe Gitlab::ProjectSearchResults, lib: true do
subject { described_class.parse_search_result(search_result) }
- it "returns a valid OpenStruct object" do
- is_expected.to be_an OpenStruct
+ it "returns a valid FoundBlob" do
+ is_expected.to be_an Gitlab::SearchResults::FoundBlob
+ expect(subject.id).to be_nil
+ expect(subject.path).to eq('CHANGELOG')
expect(subject.filename).to eq('CHANGELOG')
expect(subject.basename).to eq('CHANGELOG')
expect(subject.ref).to eq('master')
@@ -53,6 +55,7 @@ describe Gitlab::ProjectSearchResults, lib: true do
context "when filename has extension" do
let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
+ it { expect(subject.path).to eq('CONTRIBUTE.md') }
it { expect(subject.filename).to eq('CONTRIBUTE.md') }
it { expect(subject.basename).to eq('CONTRIBUTE') }
end
@@ -60,6 +63,7 @@ describe Gitlab::ProjectSearchResults, lib: true do
context "when file under directory" do
let(:search_result) { "master:a/b/c.md:5:a b c\n" }
+ it { expect(subject.path).to eq('a/b/c.md') }
it { expect(subject.filename).to eq('a/b/c.md') }
it { expect(subject.basename).to eq('a/b/c') }
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 3bd2a3238fe..b703e9808a8 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -189,7 +189,7 @@ describe Gitlab::Workhorse, lib: true do
context 'when Gitaly is enabled' do
let(:gitaly_params) do
{
- GitalySocketPath: URI(Gitlab::GitalyClient.get_address('default')).path,
+ GitalyAddress: Gitlab::GitalyClient.get_address('default'),
}
end
@@ -207,31 +207,33 @@ describe Gitlab::Workhorse, lib: true do
expect(subject).to include(repo_param)
end
- {
- git_receive_pack: :post_receive_pack,
- git_upload_pack: :post_upload_pack
- }.each do |action_name, feature_flag|
- context "when #{action_name} action is passed" do
- let(:action) { action_name }
+ context "when git_upload_pack action is passed" do
+ let(:action) { 'git_upload_pack' }
+ let(:feature_flag) { :post_upload_pack }
- context 'when action is enabled by feature flag' do
- it 'includes Gitaly params in the returned value' do
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(true)
+ context 'when action is enabled by feature flag' do
+ it 'includes Gitaly params in the returned value' do
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(true)
- expect(subject).to include(gitaly_params)
- end
+ expect(subject).to include(gitaly_params)
end
+ end
- context 'when action is not enabled by feature flag' do
- it 'does not include Gitaly params in the returned value' do
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(false)
+ context 'when action is not enabled by feature flag' do
+ it 'does not include Gitaly params in the returned value' do
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(false)
- expect(subject).not_to include(gitaly_params)
- end
+ expect(subject).not_to include(gitaly_params)
end
end
end
+ context "when git_receive_pack action is passed" do
+ let(:action) { 'git_receive_pack' }
+
+ it { expect(subject).not_to include(gitaly_params) }
+ end
+
context "when info_refs action is passed" do
let(:action) { 'info_refs' }
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index 552229e9b07..09b1fda3796 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -53,6 +53,20 @@ describe Blob do
end
end
+ describe '#pdf?' do
+ it 'is falsey when file extension is not .pdf' do
+ git_blob = double(name: 'git_blob.txt')
+
+ expect(described_class.decorate(git_blob)).not_to be_pdf
+ end
+
+ it 'is truthy when file extension is .pdf' do
+ git_blob = double(name: 'git_blob.pdf')
+
+ expect(described_class.decorate(git_blob)).to be_pdf
+ end
+ end
+
describe '#ipython_notebook?' do
it 'is falsey when language is not Jupyter Notebook' do
git_blob = double(text?: true, language: double(name: 'JSON'))
@@ -67,6 +81,20 @@ describe Blob do
end
end
+ describe '#sketch?' do
+ it 'is falsey with image extension' do
+ git_blob = Gitlab::Git::Blob.new(name: "design.png")
+
+ expect(described_class.decorate(git_blob)).not_to be_sketch
+ end
+
+ it 'is truthy with sketch extension' do
+ git_blob = Gitlab::Git::Blob.new(name: "design.sketch")
+
+ expect(described_class.decorate(git_blob)).to be_sketch
+ end
+ end
+
describe '#video?' do
it 'is falsey with image extension' do
git_blob = Gitlab::Git::Blob.new(name: 'image.png')
@@ -88,11 +116,13 @@ describe Blob do
def stubbed_blob(overrides = {})
overrides.reverse_merge!(
+ name: nil,
image?: false,
language: nil,
lfs_pointer?: false,
svg?: false,
- text?: false
+ text?: false,
+ binary?: false
)
described_class.decorate(double).tap do |blob|
@@ -131,10 +161,20 @@ describe Blob do
expect(blob.to_partial_path(project)).to eq 'download'
end
+ it 'handles PDFs' do
+ blob = stubbed_blob(name: 'blob.pdf', pdf?: true)
+ expect(blob.to_partial_path(project)).to eq 'pdf'
+ end
+
it 'handles iPython notebooks' do
blob = stubbed_blob(text?: true, ipython_notebook?: true)
expect(blob.to_partial_path(project)).to eq 'notebook'
end
+
+ it 'handles Sketch files' do
+ blob = stubbed_blob(text?: true, sketch?: true, binary?: true)
+ expect(blob.to_partial_path(project)).to eq 'sketch'
+ end
end
describe '#size_within_svg_limits?' do
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index b8584301baa..4bdd46a581d 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -51,14 +51,6 @@ describe Issue, models: true do
expect(issue.closed_at).to eq(now)
end
-
- it 'sets closed_at to nil when issue is reopened' do
- issue = create(:issue, state: 'closed')
-
- issue.reopen
-
- expect(issue.closed_at).to be_nil
- end
end
describe '#to_reference' do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index a7e565ec645..e406d0a16bd 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -166,28 +166,44 @@ describe Namespace, models: true do
end
end
- context 'renaming a sub-group' do
+ context 'with subgroups' do
let(:parent) { create(:group, name: 'parent', path: 'parent') }
let(:child) { create(:group, name: 'child', path: 'child', parent: parent) }
let!(:project) { create(:project_empty_repo, path: 'the-project', namespace: child) }
- let(:uploads_dir) { File.join(CarrierWave.root, 'uploads', 'parent') }
- let(:pages_dir) { File.join(TestEnv.pages_path, 'parent') }
+ let(:uploads_dir) { File.join(CarrierWave.root, 'uploads') }
+ let(:pages_dir) { TestEnv.pages_path }
before do
- FileUtils.mkdir_p(File.join(uploads_dir, 'child', 'the-project'))
- FileUtils.mkdir_p(File.join(pages_dir, 'child', 'the-project'))
+ FileUtils.mkdir_p(File.join(uploads_dir, 'parent', 'child', 'the-project'))
+ FileUtils.mkdir_p(File.join(pages_dir, 'parent', 'child', 'the-project'))
end
- it 'correctly moves the repository, uploads and pages' do
- expected_repository_path = File.join(TestEnv.repos_path, 'parent', 'renamed', 'the-project.git')
- expected_upload_path = File.join(uploads_dir, 'renamed', 'the-project')
- expected_pages_path = File.join(pages_dir, 'renamed', 'the-project')
+ context 'renaming child' do
+ it 'correctly moves the repository, uploads and pages' do
+ expected_repository_path = File.join(TestEnv.repos_path, 'parent', 'renamed', 'the-project.git')
+ expected_upload_path = File.join(uploads_dir, 'parent', 'renamed', 'the-project')
+ expected_pages_path = File.join(pages_dir, 'parent', 'renamed', 'the-project')
- child.update_attributes!(path: 'renamed')
+ child.update_attributes!(path: 'renamed')
- expect(File.directory?(expected_repository_path)).to be(true)
- expect(File.directory?(expected_upload_path)).to be(true)
- expect(File.directory?(expected_pages_path)).to be(true)
+ expect(File.directory?(expected_repository_path)).to be(true)
+ expect(File.directory?(expected_upload_path)).to be(true)
+ expect(File.directory?(expected_pages_path)).to be(true)
+ end
+ end
+
+ context 'renaming parent' do
+ it 'correctly moves the repository, uploads and pages' do
+ expected_repository_path = File.join(TestEnv.repos_path, 'renamed', 'child', 'the-project.git')
+ expected_upload_path = File.join(uploads_dir, 'renamed', 'child', 'the-project')
+ expected_pages_path = File.join(pages_dir, 'renamed', 'child', 'the-project')
+
+ parent.update_attributes!(path: 'renamed')
+
+ expect(File.directory?(expected_repository_path)).to be(true)
+ expect(File.directory?(expected_upload_path)).to be(true)
+ expect(File.directory?(expected_pages_path)).to be(true)
+ end
end
end
end
@@ -299,4 +315,13 @@ describe Namespace, models: true do
to eq([namespace.owner_id])
end
end
+
+ describe '#all_projects' do
+ let(:group) { create(:group) }
+ let(:child) { create(:group, parent: group) }
+ let!(:project1) { create(:project_empty_repo, namespace: group) }
+ let!(:project2) { create(:project_empty_repo, namespace: child) }
+
+ it { expect(group.all_projects.to_a).to eq([project2, project1]) }
+ end
end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index bf7950ef1c9..e69eb0098dd 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -4,7 +4,7 @@ describe KubernetesService, models: true, caching: true do
include KubernetesHelpers
include ReactiveCachingHelpers
- let(:project) { create(:kubernetes_project) }
+ let(:project) { build_stubbed(:kubernetes_project) }
let(:service) { project.kubernetes_service }
# We use Kubeclient to interactive with the Kubernetes API. It will
@@ -32,7 +32,8 @@ describe KubernetesService, models: true, caching: true do
describe 'Validations' do
context 'when service is active' do
before { subject.active = true }
- it { is_expected.to validate_presence_of(:namespace) }
+
+ it { is_expected.not_to validate_presence_of(:namespace) }
it { is_expected.to validate_presence_of(:api_url) }
it { is_expected.to validate_presence_of(:token) }
@@ -55,7 +56,7 @@ describe KubernetesService, models: true, caching: true do
'a.b' => false,
'a*b' => false,
}.each do |namespace, validity|
- it "should validate #{namespace} as #{validity ? 'valid' : 'invalid'}" do
+ it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do
subject.namespace = namespace
expect(subject.valid?).to eq(validity)
@@ -66,24 +67,40 @@ describe KubernetesService, models: true, caching: true do
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
- let(:namespace_name) { "#{project.path}-#{project.id}" }
+ context 'without a project' do
+ it 'leaves the namespace unset' do
+ expect(described_class.new.namespace).to be_nil
+ end
+ end
+ end
+
+ describe '#fields' do
+ let(:kube_namespace) do
+ subject.fields.find { |h| h[:name] == 'namespace' }
+ end
+
+ context 'as template' do
+ before { subject.template = true }
- it 'defaults to the project name with ID' do
- expect(described_class.new(project: project).namespace).to eq(namespace_name)
+ it 'sets the namespace to the default' do
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:placeholder]).to eq(subject.class::TEMPLATE_PLACEHOLDER)
end
end
- context 'without a project' do
- it 'leaves the namespace unset' do
- expect(described_class.new.namespace).to be_nil
+ context 'with associated project' do
+ before { subject.project = project }
+
+ it 'sets the namespace to the default' do
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
end
end
end
@@ -138,38 +155,40 @@ describe KubernetesService, models: true, caching: true do
before do
subject.api_url = 'https://kube.domain.com'
subject.token = 'token'
- subject.namespace = 'my-project'
subject.ca_pem = 'CA PEM DATA'
+ subject.project = project
end
- it 'sets KUBE_URL' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true }
- )
- end
+ context 'namespace is provided' do
+ before { subject.namespace = 'my-project' }
- it 'sets KUBE_TOKEN' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_TOKEN', value: 'token', public: false }
- )
+ it 'sets the variables' do
+ expect(subject.predefined_variables).to include(
+ { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
+ { key: 'KUBE_TOKEN', value: 'token', public: false },
+ { key: 'KUBE_NAMESPACE', value: 'my-project', public: true },
+ { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
+ { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true },
+ )
+ end
end
- it 'sets KUBE_NAMESPACE' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_NAMESPACE', value: 'my-project', public: true }
- )
- end
+ context 'no namespace provided' do
+ it 'sets the variables' do
+ expect(subject.predefined_variables).to include(
+ { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
+ { key: 'KUBE_TOKEN', value: 'token', public: false },
+ { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
+ { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true },
+ )
+ end
- it 'sets KUBE_CA_PEM' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true }
- )
- end
+ it 'sets the KUBE_NAMESPACE' do
+ kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
- it 'sets KUBE_CA_PEM_FILE' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }
- )
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:value]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
+ end
end
end
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 4729adba11c..2b27ce6390a 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -12,6 +12,8 @@ describe API::Issues, api: true do
let(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: user.namespace ) }
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
let!(:closed_issue) do
create :closed_issue,
author: user,
@@ -38,7 +40,9 @@ describe API::Issues, api: true do
project: project,
milestone: milestone,
created_at: generate(:past_time),
- updated_at: 1.hour.ago
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
end
let!(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
@@ -61,6 +65,7 @@ describe API::Issues, api: true do
context "when unauthenticated" do
it "returns authentication error" do
get api("/issues")
+
expect(response).to have_http_status(401)
end
end
@@ -69,9 +74,7 @@ describe API::Issues, api: true do
it "returns an array of issues" do
get api("/issues", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+ expect_paginated_array_response(size: 2)
expect(json_response.first['title']).to eq(issue.title)
expect(json_response.last).to have_key('web_url')
end
@@ -79,41 +82,43 @@ describe API::Issues, api: true do
it 'returns an array of closed issues' do
get api('/issues?state=closed', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an array of opened issues' do
get api('/issues?state=opened', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(issue.id)
end
it 'returns an array of all issues' do
get api('/issues?state=all', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
expect(json_response.first['id']).to eq(issue.id)
expect(json_response.second['id']).to eq(closed_issue.id)
end
+ it 'returns issues matching given search string for title' do
+ get api("/issues?search=#{issue.title}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(issue.id)
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api("/issues?search=#{issue.description}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(issue.id)
+ end
+
it 'returns an array of labeled issues' do
get api("/issues?labels=#{label.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label.title])
end
@@ -126,29 +131,20 @@ describe API::Issues, api: true do
get api("/issues", user), labels: "#{label.title},#{label_b.title},#{label_c.title}"
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
end
it 'returns an empty array if no issue matches labels' do
get api('/issues?labels=foo,bar', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an array of labeled issues matching given state' do
get api("/issues?labels=#{label.title}&state=opened", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label.title])
expect(json_response.first['state']).to eq('opened')
end
@@ -156,47 +152,32 @@ describe API::Issues, api: true do
it 'returns unlabeled issues for "No Label" label' do
get api("/issues", user), labels: 'No Label'
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to be_empty
end
it 'returns an empty array if no issue matches labels and state filters' do
get api("/issues?labels=#{label.title}&state=closed", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no issue matches milestone' do
get api("/issues?milestone=#{empty_milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if milestone does not exist' do
get api("/issues?milestone=foo", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an array of issues in given milestone' do
get api("/issues?milestone=#{milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
expect(json_response.first['id']).to eq(issue.id)
expect(json_response.second['id']).to eq(closed_issue.id)
end
@@ -205,49 +186,36 @@ describe API::Issues, api: true do
get api("/issues?milestone=#{milestone.title}"\
'&state=closed', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an array of issues with no milestone' do
get api("/issues?milestone=#{no_milestone_title}", author)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(confidential_issue.id)
end
it 'returns an array of issues found by iids' do
get api('/issues', user), iids: [closed_issue.iid]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an empty array if iid does not exist' do
get api("/issues", user), iids: [99999]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'sorts by created_at descending by default' do
get api('/issues', user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 2)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -255,9 +223,8 @@ describe API::Issues, api: true do
get api('/issues?sort=asc', user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 2)
expect(response_dates).to eq(response_dates.sort)
end
@@ -265,9 +232,8 @@ describe API::Issues, api: true do
get api('/issues?order_by=updated_at', user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 2)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -275,9 +241,8 @@ describe API::Issues, api: true do
get api('/issues?order_by=updated_at&sort=asc', user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 2)
expect(response_dates).to eq(response_dates.sort)
end
@@ -316,7 +281,9 @@ describe API::Issues, api: true do
assignee: user,
project: group_project,
milestone: group_milestone,
- updated_at: 1.hour.ago
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
end
let!(:group_label) do
create(:label, title: 'group_lbl', color: '#FFAABB', project: group_project)
@@ -336,74 +303,65 @@ describe API::Issues, api: true do
it 'returns all group issues (including opened and closed)' do
get api(base_url, admin)
- expect(response).to have_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect_paginated_array_response(size: 3)
end
it 'returns group issues without confidential issues for non project members' do
get api("#{base_url}?state=opened", non_member)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['title']).to eq(group_issue.title)
end
it 'returns group confidential issues for author' do
get api("#{base_url}?state=opened", author)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
end
it 'returns group confidential issues for assignee' do
get api("#{base_url}?state=opened", assignee)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
end
it 'returns group issues with confidential issues for project members' do
get api("#{base_url}?state=opened", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
end
it 'returns group confidential issues for admin' do
get api("#{base_url}?state=opened", admin)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
end
it 'returns an array of labeled group issues' do
get api("#{base_url}?labels=#{group_label.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([group_label.title])
end
it 'returns an array of labeled group issues where all labels match' do
get api("#{base_url}?labels=#{group_label.title},foo,bar", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
+ end
+
+ it 'returns issues matching given search string for title' do
+ get api("#{base_url}?search=#{group_issue.title}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api("#{base_url}?search=#{group_issue.description}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an array of labeled issues when all labels matches' do
@@ -415,65 +373,45 @@ describe API::Issues, api: true do
get api("#{base_url}", user), labels: "#{group_label.title},#{label_b.title},#{label_c.title}"
- expect(response).to have_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
end
it 'returns an array of issues found by iids' do
get api(base_url, user), iids: [group_issue.iid]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an empty array if iid does not exist' do
get api(base_url, user), iids: [99999]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no group issue matches labels' do
get api("#{base_url}?labels=foo,bar", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no issue matches milestone' do
get api("#{base_url}?milestone=#{group_empty_milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if milestone does not exist' do
get api("#{base_url}?milestone=foo", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an array of issues in given milestone' do
get api("#{base_url}?state=opened&milestone=#{group_milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_issue.id)
end
@@ -481,10 +419,7 @@ describe API::Issues, api: true do
get api("#{base_url}?milestone=#{group_milestone.title}"\
'&state=closed', user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_closed_issue.id)
end
@@ -492,9 +427,8 @@ describe API::Issues, api: true do
get api("#{base_url}?milestone=#{no_milestone_title}", user)
expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_confidential_issue.id)
end
@@ -502,9 +436,8 @@ describe API::Issues, api: true do
get api(base_url, user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -512,9 +445,8 @@ describe API::Issues, api: true do
get api("#{base_url}?sort=asc", user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort)
end
@@ -522,9 +454,8 @@ describe API::Issues, api: true do
get api("#{base_url}?order_by=updated_at", user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -532,9 +463,8 @@ describe API::Issues, api: true do
get api("#{base_url}?order_by=updated_at&sort=asc", user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort)
end
end
@@ -563,79 +493,55 @@ describe API::Issues, api: true do
get api("/projects/#{restricted_project.id}/issues", non_member)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response).to eq([])
+ expect_paginated_array_response(size: 0)
end
it 'returns project issues without confidential issues for non project members' do
get api("#{base_url}/issues", non_member)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns project issues without confidential issues for project members with guest role' do
get api("#{base_url}/issues", guest)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns project confidential issues for author' do
get api("#{base_url}/issues", author)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect_paginated_array_response(size: 3)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns project confidential issues for assignee' do
get api("#{base_url}/issues", assignee)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect_paginated_array_response(size: 3)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns project issues with confidential issues for project members' do
get api("#{base_url}/issues", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect_paginated_array_response(size: 3)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns project confidential issues for admin' do
get api("#{base_url}/issues", admin)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(3)
+ expect_paginated_array_response(size: 3)
expect(json_response.first['title']).to eq(issue.title)
end
it 'returns an array of labeled project issues' do
get api("#{base_url}/issues?labels=#{label.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label.title])
end
@@ -648,74 +554,65 @@ describe API::Issues, api: true do
get api("#{base_url}/issues", user), labels: "#{label.title},#{label_b.title},#{label_c.title}"
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
end
+ it 'returns issues matching given search string for title' do
+ get api("#{base_url}/issues?search=#{issue.title}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(issue.id)
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api("#{base_url}/issues?search=#{issue.description}", user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(issue.id)
+ end
+
it 'returns an array of issues found by iids' do
get api("#{base_url}/issues", user), iids: [issue.iid]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(issue.id)
end
it 'returns an empty array if iid does not exist' do
get api("#{base_url}/issues", user), iids: [99999]
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if not all labels matches' do
get api("#{base_url}/issues?labels=#{label.title},foo", user)
- expect(response).to have_http_status(200)
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no project issue matches labels' do
get api("#{base_url}/issues?labels=foo,bar", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no issue matches milestone' do
get api("#{base_url}/issues?milestone=#{empty_milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an empty array if milestone does not exist' do
get api("#{base_url}/issues?milestone=foo", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(0)
+ expect_paginated_array_response(size: 0)
end
it 'returns an array of issues in given milestone' do
get api("#{base_url}/issues?milestone=#{milestone.title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
+ expect_paginated_array_response(size: 2)
expect(json_response.first['id']).to eq(issue.id)
expect(json_response.second['id']).to eq(closed_issue.id)
end
@@ -723,20 +620,14 @@ describe API::Issues, api: true do
it 'returns an array of issues matching state in milestone' do
get api("#{base_url}/issues?milestone=#{milestone.title}&state=closed", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an array of issues with no milestone' do
get api("#{base_url}/issues?milestone=#{no_milestone_title}", user)
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(confidential_issue.id)
end
@@ -744,9 +635,8 @@ describe API::Issues, api: true do
get api("#{base_url}/issues", user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -754,9 +644,8 @@ describe API::Issues, api: true do
get api("#{base_url}/issues?sort=asc", user)
response_dates = json_response.map { |issue| issue['created_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort)
end
@@ -764,9 +653,8 @@ describe API::Issues, api: true do
get api("#{base_url}/issues?order_by=updated_at", user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort.reverse)
end
@@ -774,9 +662,8 @@ describe API::Issues, api: true do
get api("#{base_url}/issues?order_by=updated_at&sort=asc", user)
response_dates = json_response.map { |issue| issue['updated_at'] }
- expect(response).to have_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
+
+ expect_paginated_array_response(size: 3)
expect(response_dates).to eq(response_dates.sort)
end
end
@@ -1457,4 +1344,11 @@ describe API::Issues, api: true do
include_examples 'time tracking endpoints', 'issue'
end
+
+ def expect_paginated_array_response(size: nil)
+ expect(response).to have_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(size) if size
+ end
end
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index 7fb728fed6f..598968aff70 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -306,6 +306,8 @@ describe API::Milestones, api: true do
end
it 'returns project merge_requests for a particular milestone' do
+ # eager-load another_merge_request
+ another_merge_request
get api("/projects/#{project.id}/milestones/#{milestone.id}/merge_requests", user)
expect(response).to have_http_status(200)
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 044b989e5ba..1cfac7353d4 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -461,6 +461,29 @@ describe API::Runner do
end
end
+ context 'when dependencies is an empty array' do
+ let!(:job) { create(:ci_build_tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let!(:job2) { create(:ci_build_tag, pipeline: pipeline, name: 'rubocop', stage: 'test', stage_idx: 0) }
+ let!(:empty_dependencies_job) do
+ create(:ci_build, pipeline: pipeline, token: 'test-job-token', name: 'empty_dependencies_job',
+ stage: 'deploy', stage_idx: 1,
+ options: { dependencies: [] })
+ end
+
+ before do
+ job.success
+ job2.success
+ end
+
+ it 'returns an empty array' do
+ request_job
+
+ expect(response).to have_http_status(201)
+ expect(json_response['id']).to eq(empty_dependencies_job.id)
+ expect(json_response['dependencies'].count).to eq(0)
+ end
+ end
+
context 'when job has no tags' do
before { job.update(tags: []) }
diff --git a/spec/serializers/build_action_entity_spec.rb b/spec/serializers/build_action_entity_spec.rb
index 0f7be8b2c39..54ac17447b1 100644
--- a/spec/serializers/build_action_entity_spec.rb
+++ b/spec/serializers/build_action_entity_spec.rb
@@ -17,5 +17,9 @@ describe BuildActionEntity do
it 'contains path to the action play' do
expect(subject[:path]).to include "builds/#{build.id}/play"
end
+
+ it 'contains whether it is playable' do
+ expect(subject[:playable]).to eq build.playable?
+ end
end
end
diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb
index 7dcdf54fd93..f76a5cf72d1 100644
--- a/spec/serializers/build_entity_spec.rb
+++ b/spec/serializers/build_entity_spec.rb
@@ -24,6 +24,10 @@ describe BuildEntity do
expect(subject).not_to include(/variables/)
end
+ it 'contains whether it is playable' do
+ expect(subject[:playable]).to eq build.playable?
+ end
+
it 'contains timestamps' do
expect(subject).to include(:created_at, :updated_at)
end
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index c8bd4d4601a..be9f9ea2dec 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -4,6 +4,8 @@ describe MergeRequests::BuildService, services: true do
include RepoHelpers
let(:project) { create(:project, :repository) }
+ let(:source_project) { nil }
+ let(:target_project) { nil }
let(:user) { create(:user) }
let(:issue_confidential) { false }
let(:issue) { create(:issue, project: project, title: 'A bug', confidential: issue_confidential) }
@@ -20,7 +22,9 @@ describe MergeRequests::BuildService, services: true do
MergeRequests::BuildService.new(project, user,
description: description,
source_branch: source_branch,
- target_branch: target_branch)
+ target_branch: target_branch,
+ source_project: source_project,
+ target_project: target_project)
end
before do
@@ -256,5 +260,41 @@ describe MergeRequests::BuildService, services: true do
)
end
end
+
+ context 'target_project is set and accessible by current_user' do
+ let(:target_project) { create(:project, :public, :repository)}
+ let(:commits) { Commit.decorate([commit_1], project) }
+
+ it 'sets target project correctly' do
+ expect(merge_request.target_project).to eq(target_project)
+ end
+ end
+
+ context 'target_project is set but not accessible by current_user' do
+ let(:target_project) { create(:project, :private, :repository)}
+ let(:commits) { Commit.decorate([commit_1], project) }
+
+ it 'sets target project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
+ context 'source_project is set and accessible by current_user' do
+ let(:source_project) { create(:project, :public, :repository)}
+ let(:commits) { Commit.decorate([commit_1], project) }
+
+ it 'sets target project correctly' do
+ expect(merge_request.source_project).to eq(source_project)
+ end
+ end
+
+ context 'source_project is set but not accessible by current_user' do
+ let(:source_project) { create(:project, :private, :repository)}
+ let(:commits) { Commit.decorate([commit_1], project) }
+
+ it 'sets target project correctly' do
+ expect(merge_request.source_project).to eq(project)
+ end
+ end
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 90cde705b85..5ec1ed8237b 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -221,26 +221,23 @@ describe SystemNoteService, services: true do
describe '.change_status' do
subject { described_class.change_status(noteable, project, author, status, source) }
- let(:status) { 'new_status' }
- let(:source) { nil }
+ context 'with status reopened' do
+ let(:status) { 'reopened' }
+ let(:source) { nil }
- it_behaves_like 'a system note' do
- let(:action) { 'status' }
+ it_behaves_like 'a system note' do
+ let(:action) { 'opened' }
+ end
end
context 'with a source' do
+ let(:status) { 'opened' }
let(:source) { double('commit', gfm_reference: 'commit 123456') }
it 'sets the note text' do
expect(subject.note).to eq "#{status} via commit 123456"
end
end
-
- context 'without a source' do
- it 'sets the note text' do
- expect(subject.note).to eq status
- end
- end
end
describe '.merge_when_pipeline_succeeds' do
@@ -298,9 +295,23 @@ describe SystemNoteService, services: true do
describe '.change_issue_confidentiality' do
subject { described_class.change_issue_confidentiality(noteable, project, author) }
- context 'when noteable responds to `confidential`' do
+ context 'issue has been made confidential' do
+ before do
+ noteable.update_attribute(:confidential, true)
+ end
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'confidential' }
+ end
+
+ it 'sets the note text' do
+ expect(subject.note).to eq 'made the issue confidential'
+ end
+ end
+
+ context 'issue has been made visible' do
it_behaves_like 'a system note' do
- let(:action) { 'confidentiality' }
+ let(:action) { 'visible' }
end
it 'sets the note text' do
diff --git a/spec/services/users/create_service_spec.rb b/spec/services/users/create_service_spec.rb
index 66f68650f81..a111aec2f89 100644
--- a/spec/services/users/create_service_spec.rb
+++ b/spec/services/users/create_service_spec.rb
@@ -122,6 +122,32 @@ describe Users::CreateService, services: true do
end
end
+ context 'when password_automatically_set parameter is true' do
+ let(:params) do
+ {
+ name: 'John Doe',
+ username: 'jduser',
+ email: 'jd@example.com',
+ password: 'mydummypass',
+ password_automatically_set: true
+ }
+ end
+
+ it 'persists the given attributes' do
+ user = service.execute
+ user.reload
+
+ expect(user).to have_attributes(
+ name: params[:name],
+ username: params[:username],
+ email: params[:email],
+ password: params[:password],
+ created_by_id: admin_user.id,
+ password_automatically_set: params[:password_automatically_set]
+ )
+ end
+ end
+
context 'when skip_confirmation parameter is true' do
let(:params) do
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true }
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index 51f1015f43c..c59b30c772d 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -180,7 +180,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it "takes the new namespace" do
expect(Gitlab::GithubImport::ProjectCreator).
to receive(:new).with(provider_repo, provider_repo.name, an_instance_of(Group), user, access_params, type: provider).
- and_return(double(execute: true))
+ and_return(double(execute: true))
post :create, target_namespace: provider_repo.name, format: :js
end
@@ -201,7 +201,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it "takes the current user's namespace" do
expect(Gitlab::GithubImport::ProjectCreator).
to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, access_params, type: provider).
- and_return(double(execute: true))
+ and_return(double(execute: true))
post :create, format: :js
end
@@ -229,7 +229,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
end
end
- context 'user has chosen a nested namespace and name for the project' do
+ context 'user has chosen an existing nested namespace and name for the project' do
let(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
let(:nested_namespace) { create(:namespace, name: 'bar', parent: parent_namespace, owner: user) }
let(:test_name) { 'test_name' }
@@ -242,5 +242,58 @@ shared_examples 'a GitHub-ish import controller: POST create' do
post :create, { target_namespace: nested_namespace.full_path, new_name: test_name, format: :js }
end
end
+
+ context 'user has chosen a non-existent nested namespaces and name for the project' do
+ let(:test_name) { 'test_name' }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::GithubImport::ProjectCreator).
+ to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::GithubImport::ProjectCreator).
+ to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+
+ it 'new namespace has the right parent' do
+ allow(Gitlab::GithubImport::ProjectCreator).
+ to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :js }
+
+ expect(Namespace.find_by_path_or_name('bar').parent.path).to eq('foo')
+ end
+ end
+
+ context 'user has chosen existent and non-existent nested namespaces and name for the project' do
+ let(:test_name) { 'test_name' }
+ let!(:parent_namespace) { create(:namespace, name: 'foo', owner: user) }
+
+ it 'takes the selected namespace and name' do
+ expect(Gitlab::GithubImport::ProjectCreator).
+ to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider).
+ and_return(double(execute: true))
+
+ post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js }
+ end
+
+ it 'creates the namespaces' do
+ allow(Gitlab::GithubImport::ProjectCreator).
+ to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider).
+ and_return(double(execute: true))
+
+ expect { post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js } }
+ .to change { Namespace.count }.by(2)
+ end
+ end
end
end
diff --git a/spec/support/drag_to_helper.rb b/spec/support/drag_to_helper.rb
index 0c0659d3ecd..ae149631ed9 100644
--- a/spec/support/drag_to_helper.rb
+++ b/spec/support/drag_to_helper.rb
@@ -3,11 +3,11 @@ module DragTo
evaluate_script("simulateDrag({scrollable: $('#{scrollable}').get(0), from: {el: $('#{selector}').eq(#{list_from_index}).get(0), index: #{from_index}}, to: {el: $('#{selector}').eq(#{list_to_index}).get(0), index: #{to_index}}});")
Timeout.timeout(Capybara.default_max_wait_time) do
- loop until drag_active?
+ loop while drag_active?
end
end
def drag_active?
- page.evaluate_script('window.SIMULATE_DRAG_ACTIVE').zero?
+ page.evaluate_script('window.SIMULATE_DRAG_ACTIVE').nonzero?
end
end
diff --git a/spec/support/issuables_list_metadata_shared_examples.rb b/spec/support/issuables_list_metadata_shared_examples.rb
index 7ea4073ef2b..3406e4c3161 100644
--- a/spec/support/issuables_list_metadata_shared_examples.rb
+++ b/spec/support/issuables_list_metadata_shared_examples.rb
@@ -33,4 +33,19 @@ shared_examples 'issuables list meta-data' do |issuable_type, action = nil|
expect(meta_data[id].upvotes).to eq(id + 2)
end
end
+
+ describe "when given empty collection" do
+ let(:project2) { create(:empty_project, :public) }
+
+ it "doesn't execute any queries with false conditions" do
+ get_action =
+ if action
+ proc { get action }
+ else
+ proc { get :index, namespace_id: project2.namespace, project_id: project2 }
+ end
+
+ expect(&get_action).not_to make_queries_matching(/WHERE (?:1=0|0=1)/)
+ end
+ end
end
diff --git a/spec/support/matchers/gitaly_matchers.rb b/spec/support/matchers/gitaly_matchers.rb
index d7a53820684..65dbc01f6e4 100644
--- a/spec/support/matchers/gitaly_matchers.rb
+++ b/spec/support/matchers/gitaly_matchers.rb
@@ -1,3 +1,3 @@
-RSpec::Matchers.define :post_receive_request_with_repo_path do |path|
+RSpec::Matchers.define :gitaly_request_with_repo_path do |path|
match { |actual| actual.repository.path == path }
end
diff --git a/spec/support/matchers/query_matcher.rb b/spec/support/matchers/query_matcher.rb
new file mode 100644
index 00000000000..ac8c4ab91d9
--- /dev/null
+++ b/spec/support/matchers/query_matcher.rb
@@ -0,0 +1,33 @@
+RSpec::Matchers.define :make_queries_matching do |matcher, expected_count = nil|
+ supports_block_expectations
+
+ match do |block|
+ @counter = query_count(matcher, &block)
+ if expected_count
+ @counter.count == expected_count
+ else
+ @counter.count > 0
+ end
+ end
+
+ failure_message_when_negated do |_|
+ if expected_count
+ "expected #{matcher} not to match #{expected_count} queries, got #{@counter.count} matches:\n\n#{@counter.inspect}"
+ else
+ "expected #{matcher} not to match any query, got #{@counter.count} matches:\n\n#{@counter.inspect}"
+ end
+ end
+
+ failure_message do |_|
+ if expected_count
+ "expected #{matcher} to match #{expected_count} queries, got #{@counter.count} matches:\n\n#{@counter.inspect}"
+ else
+ "expected #{matcher} to match at least one query, got #{@counter.count} matches:\n\n#{@counter.inspect}"
+ end
+ end
+
+ def query_count(regex, &block)
+ @recorder = ActiveRecord::QueryRecorder.new(&block).log
+ @recorder.select{ |q| q.match(regex) }
+ end
+end
diff --git a/spec/support/seed_helper.rb b/spec/support/seed_helper.rb
index f55fee28ff9..47b5f556e66 100644
--- a/spec/support/seed_helper.rb
+++ b/spec/support/seed_helper.rb
@@ -1,20 +1,22 @@
+require_relative 'test_env'
+
# This file is specific to specs in spec/lib/gitlab/git/
-SEED_REPOSITORY_PATH = File.expand_path('../../tmp/repositories', __dir__)
-TEST_REPO_PATH = File.join(SEED_REPOSITORY_PATH, 'gitlab-git-test.git')
-TEST_NORMAL_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "not-bare-repo.git")
-TEST_MUTABLE_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "mutable-repo.git")
-TEST_BROKEN_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "broken-repo.git")
+SEED_STORAGE_PATH = TestEnv.repos_path
+TEST_REPO_PATH = 'gitlab-git-test.git'.freeze
+TEST_NORMAL_REPO_PATH = 'not-bare-repo.git'.freeze
+TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'.freeze
+TEST_BROKEN_REPO_PATH = 'broken-repo.git'.freeze
module SeedHelper
GITLAB_GIT_TEST_REPO_URL = ENV.fetch('GITLAB_GIT_TEST_REPO_URL', 'https://gitlab.com/gitlab-org/gitlab-git-test.git').freeze
def ensure_seeds
- if File.exist?(SEED_REPOSITORY_PATH)
- FileUtils.rm_r(SEED_REPOSITORY_PATH)
+ if File.exist?(SEED_STORAGE_PATH)
+ FileUtils.rm_r(SEED_STORAGE_PATH)
end
- FileUtils.mkdir_p(SEED_REPOSITORY_PATH)
+ FileUtils.mkdir_p(SEED_STORAGE_PATH)
create_bare_seeds
create_normal_seeds
@@ -26,41 +28,45 @@ module SeedHelper
def create_bare_seeds
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{GITLAB_GIT_TEST_REPO_URL}),
- chdir: SEED_REPOSITORY_PATH,
+ chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
end
def create_normal_seeds
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone #{TEST_REPO_PATH} #{TEST_NORMAL_REPO_PATH}),
+ chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
end
def create_mutable_seeds
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone #{TEST_REPO_PATH} #{TEST_MUTABLE_REPO_PATH}),
+ chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
- system(git_env, *%w(git branch -t feature origin/feature),
- chdir: TEST_MUTABLE_REPO_PATH, out: '/dev/null', err: '/dev/null')
+ mutable_repo_full_path = File.join(SEED_STORAGE_PATH, TEST_MUTABLE_REPO_PATH)
+ system(git_env, *%W(#{Gitlab.config.git.bin_path} branch -t feature origin/feature),
+ chdir: mutable_repo_full_path, out: '/dev/null', err: '/dev/null')
system(git_env, *%W(#{Gitlab.config.git.bin_path} remote add expendable #{GITLAB_GIT_TEST_REPO_URL}),
- chdir: TEST_MUTABLE_REPO_PATH, out: '/dev/null', err: '/dev/null')
+ chdir: mutable_repo_full_path, out: '/dev/null', err: '/dev/null')
end
def create_broken_seeds
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} #{TEST_BROKEN_REPO_PATH}),
+ chdir: SEED_STORAGE_PATH,
out: '/dev/null',
err: '/dev/null')
- refs_path = File.join(TEST_BROKEN_REPO_PATH, 'refs')
+ refs_path = File.join(SEED_STORAGE_PATH, TEST_BROKEN_REPO_PATH, 'refs')
FileUtils.rm_r(refs_path)
end
def create_git_attributes
- dir = File.join(SEED_REPOSITORY_PATH, 'with-git-attributes.git', 'info')
+ dir = File.join(SEED_STORAGE_PATH, 'with-git-attributes.git', 'info')
FileUtils.mkdir_p(dir)
@@ -85,7 +91,7 @@ bla/bla.txt
end
def create_invalid_git_attributes
- dir = File.join(SEED_REPOSITORY_PATH, 'with-invalid-git-attributes.git', 'info')
+ dir = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git', 'info')
FileUtils.mkdir_p(dir)
diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb
index 1c383d0514d..9afe2e610b9 100644
--- a/spec/workers/process_commit_worker_spec.rb
+++ b/spec/workers/process_commit_worker_spec.rb
@@ -99,6 +99,13 @@ describe ProcessCommitWorker do
expect(metric.first_mentioned_in_commit_at).to eq(commit.committed_date)
end
+
+ it "doesn't execute any queries with false conditions" do
+ allow(commit).to receive(:safe_message).
+ and_return("Lorem Ipsum")
+
+ expect { worker.update_issue_metrics(commit, user) }.not_to make_queries_matching(/WHERE (?:1=0|0=1)/)
+ end
end
describe '#build_commit' do