summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-04-19 10:40:47 +0100
committerFilipa Lacerda <filipa@gitlab.com>2017-04-19 10:40:47 +0100
commit4038d50db0b33cb223108a6a0f4fd9b3e44a95c1 (patch)
tree66fae54ca5c037c35659bce506d0b6843067e985
parentbaaaf4e95979c128779c735a59cc4e0ecade0bf9 (diff)
parentbbd83376d625b8d9cb73cbc83c3c0eb71b1abf32 (diff)
downloadgitlab-ce-4038d50db0b33cb223108a6a0f4fd9b3e44a95c1.tar.gz
Merge branch 'master' into 30985-cancel-pipelines
* master: Fix container registry navigation menu highlights Resolve "Mini pipeline graph + status badge, when updating in real time don't change color and svg icon" Refactor group search out of global search disables test settings on chat notification services when repository is empty Disable initialization table pipeline for new merge request form Review changes, used eq instead of match Remove lighten blue and add blue-25 for background Fixed tests 29595 Customize experience callout design Remove unneeded format block Fixed tests 29595 Customize experience callout design Updated specs Remove helper [ci skip] Use favicon full path Improve gitaly_address error message
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_canceled.ico (renamed from app/assets/images/ci_favicons/icon_status_canceled.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_created.ico (renamed from app/assets/images/ci_favicons/icon_status_created.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_failed.ico (renamed from app/assets/images/ci_favicons/icon_status_failed.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_manual.ico (renamed from app/assets/images/ci_favicons/icon_status_manual.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_not_found.ico (renamed from app/assets/images/ci_favicons/icon_status_not_found.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_pending.ico (renamed from app/assets/images/ci_favicons/icon_status_pending.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_running.ico (renamed from app/assets/images/ci_favicons/icon_status_running.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_skipped.ico (renamed from app/assets/images/ci_favicons/icon_status_skipped.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_success.ico (renamed from app/assets/images/ci_favicons/icon_status_success.ico)bin5430 -> 5430 bytes
-rwxr-xr-xapp/assets/images/ci_favicons/favicon_status_warning.ico (renamed from app/assets/images/ci_favicons/icon_status_warning.ico)bin5430 -> 5430 bytes
-rw-r--r--app/assets/javascripts/ci_status_icons.js34
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js10
-rw-r--r--app/assets/javascripts/vue_pipelines_index/components/stage.js28
-rw-r--r--app/assets/stylesheets/pages/profile.scss59
-rw-r--r--app/models/project_services/chat_notification_service.rb2
-rw-r--r--app/serializers/status_entity.rb6
-rw-r--r--app/services/search/global_service.rb11
-rw-r--r--app/services/search/group_service.rb18
-rw-r--r--app/services/search_service.rb2
-rw-r--r--app/views/layouts/nav/_project.html.haml4
-rw-r--r--app/views/projects/merge_requests/_new_submit.html.haml2
-rw-r--r--app/views/projects/merge_requests/show/_pipelines.html.haml3
-rw-r--r--app/views/shared/_user_callout.html.haml17
-rw-r--r--changelogs/unreleased/29595-customize-experience-callout.yml4
-rw-r--r--changelogs/unreleased/31009-disable-test-settings-on-services-when-repository-is-empty.yml4
-rw-r--r--lib/gitlab/gitaly_client.rb2
-rw-r--r--spec/controllers/projects/builds_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb2
-rw-r--r--spec/javascripts/ci_status_icon_spec.js44
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js13
-rw-r--r--spec/javascripts/user_callout_spec.js1
-rw-r--r--spec/javascripts/vue_pipelines_index/stage_spec.js66
-rw-r--r--spec/models/project_services/chat_notification_service_spec.rb20
-rw-r--r--spec/serializers/build_serializer_spec.rb2
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb2
-rw-r--r--spec/services/search/global_service_spec.rb21
-rw-r--r--spec/services/search/group_service_spec.rb40
-rw-r--r--spec/views/layouts/nav/_project.html.haml_spec.rb37
39 files changed, 360 insertions, 98 deletions
diff --git a/app/assets/images/ci_favicons/icon_status_canceled.ico b/app/assets/images/ci_favicons/favicon_status_canceled.ico
index 5a19458f2a2..5a19458f2a2 100755
--- a/app/assets/images/ci_favicons/icon_status_canceled.ico
+++ b/app/assets/images/ci_favicons/favicon_status_canceled.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_created.ico b/app/assets/images/ci_favicons/favicon_status_created.ico
index 4dca9640cb3..4dca9640cb3 100755
--- a/app/assets/images/ci_favicons/icon_status_created.ico
+++ b/app/assets/images/ci_favicons/favicon_status_created.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_failed.ico b/app/assets/images/ci_favicons/favicon_status_failed.ico
index c961ff9a69b..c961ff9a69b 100755
--- a/app/assets/images/ci_favicons/icon_status_failed.ico
+++ b/app/assets/images/ci_favicons/favicon_status_failed.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_manual.ico b/app/assets/images/ci_favicons/favicon_status_manual.ico
index 5fbbc99ea7c..5fbbc99ea7c 100755
--- a/app/assets/images/ci_favicons/icon_status_manual.ico
+++ b/app/assets/images/ci_favicons/favicon_status_manual.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_not_found.ico b/app/assets/images/ci_favicons/favicon_status_not_found.ico
index 21afa9c72e6..21afa9c72e6 100755
--- a/app/assets/images/ci_favicons/icon_status_not_found.ico
+++ b/app/assets/images/ci_favicons/favicon_status_not_found.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_pending.ico b/app/assets/images/ci_favicons/favicon_status_pending.ico
index 8be32dab85a..8be32dab85a 100755
--- a/app/assets/images/ci_favicons/icon_status_pending.ico
+++ b/app/assets/images/ci_favicons/favicon_status_pending.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_running.ico b/app/assets/images/ci_favicons/favicon_status_running.ico
index f328ff1a5ed..f328ff1a5ed 100755
--- a/app/assets/images/ci_favicons/icon_status_running.ico
+++ b/app/assets/images/ci_favicons/favicon_status_running.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_skipped.ico b/app/assets/images/ci_favicons/favicon_status_skipped.ico
index b4394e1b4af..b4394e1b4af 100755
--- a/app/assets/images/ci_favicons/icon_status_skipped.ico
+++ b/app/assets/images/ci_favicons/favicon_status_skipped.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_success.ico b/app/assets/images/ci_favicons/favicon_status_success.ico
index 4f436c95242..4f436c95242 100755
--- a/app/assets/images/ci_favicons/icon_status_success.ico
+++ b/app/assets/images/ci_favicons/favicon_status_success.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/icon_status_warning.ico b/app/assets/images/ci_favicons/favicon_status_warning.ico
index 805cc20cdec..805cc20cdec 100755
--- a/app/assets/images/ci_favicons/icon_status_warning.ico
+++ b/app/assets/images/ci_favicons/favicon_status_warning.ico
Binary files differ
diff --git a/app/assets/javascripts/ci_status_icons.js b/app/assets/javascripts/ci_status_icons.js
new file mode 100644
index 00000000000..f16616873b2
--- /dev/null
+++ b/app/assets/javascripts/ci_status_icons.js
@@ -0,0 +1,34 @@
+import CANCELED_SVG from 'icons/_icon_status_canceled_borderless.svg';
+import CREATED_SVG from 'icons/_icon_status_created_borderless.svg';
+import FAILED_SVG from 'icons/_icon_status_failed_borderless.svg';
+import MANUAL_SVG from 'icons/_icon_status_manual_borderless.svg';
+import PENDING_SVG from 'icons/_icon_status_pending_borderless.svg';
+import RUNNING_SVG from 'icons/_icon_status_running_borderless.svg';
+import SKIPPED_SVG from 'icons/_icon_status_skipped_borderless.svg';
+import SUCCESS_SVG from 'icons/_icon_status_success_borderless.svg';
+import WARNING_SVG from 'icons/_icon_status_warning_borderless.svg';
+
+const StatusIconEntityMap = {
+ icon_status_canceled: CANCELED_SVG,
+ icon_status_created: CREATED_SVG,
+ icon_status_failed: FAILED_SVG,
+ icon_status_manual: MANUAL_SVG,
+ icon_status_pending: PENDING_SVG,
+ icon_status_running: RUNNING_SVG,
+ icon_status_skipped: SKIPPED_SVG,
+ icon_status_success: SUCCESS_SVG,
+ icon_status_warning: WARNING_SVG,
+};
+
+export {
+ CANCELED_SVG,
+ CREATED_SVG,
+ FAILED_SVG,
+ MANUAL_SVG,
+ PENDING_SVG,
+ RUNNING_SVG,
+ SKIPPED_SVG,
+ SUCCESS_SVG,
+ WARNING_SVG,
+ StatusIconEntityMap as default,
+};
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 33c900e264b..01c4b9821d3 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -368,9 +368,9 @@
});
};
- w.gl.utils.setFavicon = (iconName) => {
- if (faviconEl && iconName) {
- faviconEl.setAttribute('href', `/assets/${iconName}.ico`);
+ w.gl.utils.setFavicon = (faviconPath) => {
+ if (faviconEl && faviconPath) {
+ faviconEl.setAttribute('href', faviconPath);
}
};
@@ -385,8 +385,8 @@
url: pageUrl,
dataType: 'json',
success: function(data) {
- if (data && data.icon) {
- gl.utils.setFavicon(`ci_favicons/${data.icon}`);
+ if (data && data.favicon) {
+ gl.utils.setFavicon(data.favicon);
} else {
gl.utils.resetFavicon();
}
diff --git a/app/assets/javascripts/vue_pipelines_index/components/stage.js b/app/assets/javascripts/vue_pipelines_index/components/stage.js
index a2c29002707..b8cc3630611 100644
--- a/app/assets/javascripts/vue_pipelines_index/components/stage.js
+++ b/app/assets/javascripts/vue_pipelines_index/components/stage.js
@@ -1,32 +1,11 @@
/* global Flash */
-import canceledSvg from 'icons/_icon_status_canceled_borderless.svg';
-import createdSvg from 'icons/_icon_status_created_borderless.svg';
-import failedSvg from 'icons/_icon_status_failed_borderless.svg';
-import manualSvg from 'icons/_icon_status_manual_borderless.svg';
-import pendingSvg from 'icons/_icon_status_pending_borderless.svg';
-import runningSvg from 'icons/_icon_status_running_borderless.svg';
-import skippedSvg from 'icons/_icon_status_skipped_borderless.svg';
-import successSvg from 'icons/_icon_status_success_borderless.svg';
-import warningSvg from 'icons/_icon_status_warning_borderless.svg';
+import StatusIconEntityMap from '../../ci_status_icons';
export default {
data() {
- const svgsDictionary = {
- icon_status_canceled: canceledSvg,
- icon_status_created: createdSvg,
- icon_status_failed: failedSvg,
- icon_status_manual: manualSvg,
- icon_status_pending: pendingSvg,
- icon_status_running: runningSvg,
- icon_status_skipped: skippedSvg,
- icon_status_success: successSvg,
- icon_status_warning: warningSvg,
- };
-
return {
builds: '',
spinner: '<span class="fa fa-spinner fa-spin"></span>',
- svg: svgsDictionary[this.stage.status.icon],
};
},
@@ -89,6 +68,9 @@ export default {
triggerButtonClass() {
return `mini-pipeline-graph-dropdown-toggle has-tooltip js-builds-dropdown-button ci-status-icon-${this.stage.status.group}`;
},
+ svgHTML() {
+ return StatusIconEntityMap[this.stage.status.icon];
+ },
},
template: `
<div>
@@ -100,7 +82,7 @@ export default {
data-toggle="dropdown"
type="button"
:aria-label="stage.title">
- <span v-html="svg" aria-hidden="true"></span>
+ <span v-html="svgHTML" aria-hidden="true"></span>
<i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
<ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 8c6dd392865..fe084eb9397 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -289,8 +289,12 @@ table.u2f-registrations {
margin: 0 auto;
.bordered-box {
- border: 1px solid $border-color;
+ border: 1px solid $blue-300;
border-radius: $border-radius-default;
+ background-color: $blue-25;
+ position: relative;
+ display: flex;
+ justify-content: center;
}
.landing {
@@ -298,28 +302,59 @@ table.u2f-registrations {
margin-bottom: $gl-padding;
.close {
- margin-right: 20px;
- }
+ position: absolute;
+ right: 20px;
+ opacity: 1;
+
+ .dismiss-icon {
+ float: right;
+ cursor: pointer;
+ color: $blue-300;
+ }
- .dismiss-icon {
- float: right;
- cursor: pointer;
- color: $cycle-analytics-dismiss-icon-color;
+ &:hover {
+ background-color: transparent;
+ border: 0;
+
+ .dismiss-icon {
+ color: $blue-400;
+ }
+ }
}
.svg-container {
- text-align: center;
+ margin-right: 30px;
+ display: inline-block;
svg {
- width: 136px;
- height: 136px;
+ height: 110px;
+ vertical-align: top;
}
}
+
+ .user-callout-copy {
+ display: inline-block;
+ vertical-align: top;
+ }
}
@media(max-width: $screen-xs-max) {
- .inner-content {
- padding-left: 30px;
+ text-align: center;
+
+ .bordered-box {
+ display: block;
+ }
+
+ .landing {
+ .svg-container,
+ .user-callout-copy {
+ margin: 0;
+ display: block;
+
+ svg {
+ height: 75px;
+ }
+ }
}
}
}
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index fa782c6fbb7..f2dfb87dbda 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -22,7 +22,7 @@ class ChatNotificationService < Service
end
def can_test?
- valid?
+ super && valid?
end
def self.supported_events
diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb
index dfd9d1584a1..944472f3e51 100644
--- a/app/serializers/status_entity.rb
+++ b/app/serializers/status_entity.rb
@@ -1,8 +1,12 @@
class StatusEntity < Grape::Entity
include RequestAwareEntity
- expose :icon, :favicon, :text, :label, :group
+ expose :icon, :text, :label, :group
expose :has_details?, as: :has_details
expose :details_path
+
+ expose :favicon do |status|
+ ActionController::Base.helpers.image_path(File.join('ci_favicons', "#{status.favicon}.ico"))
+ end
end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 8409b592b72..ff188102b62 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -7,16 +7,13 @@ module Search
end
def execute
- group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
- projects = ProjectsFinder.new(current_user: current_user).execute
-
- if group
- projects = projects.inside_path(group.full_path)
- end
-
Gitlab::SearchResults.new(current_user, projects, params[:search])
end
+ def projects
+ @projects ||= ProjectsFinder.new(current_user: current_user).execute
+ end
+
def scope
@scope ||= begin
allowed_scopes = %w[issues merge_requests milestones]
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
new file mode 100644
index 00000000000..29478e3251f
--- /dev/null
+++ b/app/services/search/group_service.rb
@@ -0,0 +1,18 @@
+module Search
+ class GroupService < Search::GlobalService
+ attr_accessor :group
+
+ def initialize(user, group, params)
+ super(user, params)
+
+ @group = group
+ end
+
+ def projects
+ return Project.none unless group
+ return @projects if defined? @projects
+
+ @projects = super.inside_path(group.full_path)
+ end
+ end
+end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 8d46a8dab3e..22736c71725 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -54,6 +54,8 @@ class SearchService
Search::ProjectService.new(project, current_user, params)
elsif show_snippets?
Search::SnippetService.new(current_user, params)
+ elsif group
+ Search::GroupService.new(current_user, group, params)
else
Search::GlobalService.new(current_user, params)
end
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index e34cddeb3e2..37429c7cfc0 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -11,13 +11,13 @@
Project
- if project_nav_tab? :files
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases graphs network)) do
+ = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
= link_to project_files_path(@project), title: 'Repository', class: 'shortcuts-tree' do
%span
Repository
- if project_nav_tab? :container_registry
- = nav_link(controller: %w(container_registry)) do
+ = nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
%span
Registry
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index 03069804c86..da79ca2ee75 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -46,7 +46,7 @@
-# This tab is always loaded via AJAX
- if @pipelines.any?
#pipelines.pipelines.tab-pane
- = render 'projects/merge_requests/show/pipelines', endpoint: url_for(params.merge(format: :json))
+ = render 'projects/merge_requests/show/pipelines', endpoint: url_for(params.merge(format: :json)), disable_initialization: true
.mr-loading-status
= spinner
diff --git a/app/views/projects/merge_requests/show/_pipelines.html.haml b/app/views/projects/merge_requests/show/_pipelines.html.haml
index de4aa255bbd..2f1dbe87619 100644
--- a/app/views/projects/merge_requests/show/_pipelines.html.haml
+++ b/app/views/projects/merge_requests/show/_pipelines.html.haml
@@ -1,3 +1,4 @@
- endpoint_path = local_assigns[:endpoint] || pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :json)
+- disable_initialization = local_assigns.fetch(:disable_initialization, false)
-= render 'projects/commit/pipelines_list', endpoint: endpoint_path
+= render 'projects/commit/pipelines_list', endpoint: endpoint_path, disable_initialization: disable_initialization
diff --git a/app/views/shared/_user_callout.html.haml b/app/views/shared/_user_callout.html.haml
index 8f1293adcb1..8308baa7829 100644
--- a/app/views/shared/_user_callout.html.haml
+++ b/app/views/shared/_user_callout.html.haml
@@ -3,12 +3,11 @@
%button.btn.btn-default.close.js-close-callout{ type: 'button',
'aria-label' => 'Dismiss customize experience box' }
= icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
- .row
- .col-sm-3.col-xs-12.svg-container
- = custom_icon('icon_customization')
- .col-sm-8.col-xs-12.inner-content
- %h4
- Customize your experience
- %p
- Change syntax themes, default project pages, and more in preferences.
- = link_to 'Check it out', profile_preferences_path, class: 'btn btn-default js-close-callout'
+ .svg-container
+ = custom_icon('icon_customization')
+ .user-callout-copy
+ %h4
+ Customize your experience
+ %p
+ Change syntax themes, default project pages, and more in preferences.
+ = link_to 'Check it out', profile_preferences_path, class: 'btn btn-primary js-close-callout'
diff --git a/changelogs/unreleased/29595-customize-experience-callout.yml b/changelogs/unreleased/29595-customize-experience-callout.yml
new file mode 100644
index 00000000000..ec8393142c6
--- /dev/null
+++ b/changelogs/unreleased/29595-customize-experience-callout.yml
@@ -0,0 +1,4 @@
+---
+title: 29595 Update callout design
+merge_request:
+author:
diff --git a/changelogs/unreleased/31009-disable-test-settings-on-services-when-repository-is-empty.yml b/changelogs/unreleased/31009-disable-test-settings-on-services-when-repository-is-empty.yml
new file mode 100644
index 00000000000..6e43a032f20
--- /dev/null
+++ b/changelogs/unreleased/31009-disable-test-settings-on-services-when-repository-is-empty.yml
@@ -0,0 +1,4 @@
+---
+title: Disable test settings on chat notification services when repository is empty
+merge_request: 10759
+author:
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index bcdf1b1faa8..c69676a1dac 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -15,7 +15,7 @@ module Gitlab
end
unless URI(address).scheme.in?(%w(tcp unix))
- raise "Unsupported Gitaly address: #{address.inspect}"
+ raise "Unsupported Gitaly address: #{address.inspect} does not use URL scheme 'tcp' or 'unix'"
end
@addresses[name] = address
diff --git a/spec/controllers/projects/builds_controller_spec.rb b/spec/controllers/projects/builds_controller_spec.rb
index 13208d21918..faf3770f5e9 100644
--- a/spec/controllers/projects/builds_controller_spec.rb
+++ b/spec/controllers/projects/builds_controller_spec.rb
@@ -60,7 +60,7 @@ describe Projects::BuildsController do
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
- expect(json_response['favicon']).to eq status.favicon
+ expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico"
end
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 1739d40ab88..cc393bd24f2 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1208,7 +1208,7 @@ describe Projects::MergeRequestsController do
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
- expect(json_response['favicon']).to eq status.favicon
+ expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico"
end
end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index d8f9bfd0d37..d9192177a06 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -86,7 +86,7 @@ describe Projects::PipelinesController do
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
- expect(json_response['favicon']).to eq status.favicon
+ expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico"
end
end
end
diff --git a/spec/javascripts/ci_status_icon_spec.js b/spec/javascripts/ci_status_icon_spec.js
new file mode 100644
index 00000000000..c83416c15ef
--- /dev/null
+++ b/spec/javascripts/ci_status_icon_spec.js
@@ -0,0 +1,44 @@
+import * as icons from '~/ci_status_icons';
+
+describe('CI status icons', () => {
+ const statuses = [
+ 'canceled',
+ 'created',
+ 'failed',
+ 'manual',
+ 'pending',
+ 'running',
+ 'skipped',
+ 'success',
+ 'warning',
+ ];
+
+ statuses.forEach((status) => {
+ it(`should export a ${status} svg`, () => {
+ const key = `${status.toUpperCase()}_SVG`;
+
+ expect(Object.hasOwnProperty.call(icons, key)).toBe(true);
+ expect(icons[key]).toMatch(/^<svg/);
+ });
+ });
+
+ describe('default export map', () => {
+ const entityIconNames = [
+ 'icon_status_canceled',
+ 'icon_status_created',
+ 'icon_status_failed',
+ 'icon_status_manual',
+ 'icon_status_pending',
+ 'icon_status_running',
+ 'icon_status_skipped',
+ 'icon_status_success',
+ 'icon_status_warning',
+ ];
+
+ entityIconNames.forEach((iconName) => {
+ it(`should have a '${iconName}' key`, () => {
+ expect(Object.hasOwnProperty.call(icons.default, iconName)).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 03f3c206f44..56aabc16382 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -313,7 +313,7 @@ require('~/lib/utils/common_utils');
describe('gl.utils.setFavicon', () => {
it('should set page favicon to provided favicon', () => {
- const faviconName = 'custom_favicon';
+ const faviconPath = '//custom_favicon';
const fakeLink = {
setAttribute() {},
};
@@ -321,9 +321,9 @@ require('~/lib/utils/common_utils');
spyOn(window.document, 'getElementById').and.callFake(() => fakeLink);
spyOn(fakeLink, 'setAttribute').and.callFake((attr, val) => {
expect(attr).toEqual('href');
- expect(val.indexOf('/assets/custom_favicon.ico') > -1).toBe(true);
+ expect(val.indexOf(faviconPath) > -1).toBe(true);
});
- gl.utils.setFavicon(faviconName);
+ gl.utils.setFavicon(faviconPath);
});
});
@@ -345,13 +345,12 @@ require('~/lib/utils/common_utils');
describe('gl.utils.setCiStatusFavicon', () => {
it('should set page favicon to CI status favicon based on provided status', () => {
const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1/status.json`;
- const FAVICON_PATH = 'ci_favicons/';
- const FAVICON = 'icon_status_success';
+ const FAVICON_PATH = '//icon_status_success';
const spySetFavicon = spyOn(gl.utils, 'setFavicon').and.stub();
const spyResetFavicon = spyOn(gl.utils, 'resetFavicon').and.stub();
spyOn($, 'ajax').and.callFake(function (options) {
- options.success({ icon: FAVICON });
- expect(spySetFavicon).toHaveBeenCalledWith(FAVICON_PATH + FAVICON);
+ options.success({ favicon: FAVICON_PATH });
+ expect(spySetFavicon).toHaveBeenCalledWith(FAVICON_PATH);
options.success();
expect(spyResetFavicon).toHaveBeenCalled();
options.error();
diff --git a/spec/javascripts/user_callout_spec.js b/spec/javascripts/user_callout_spec.js
index c0375ebc61c..28d0c7dcd99 100644
--- a/spec/javascripts/user_callout_spec.js
+++ b/spec/javascripts/user_callout_spec.js
@@ -14,7 +14,6 @@ describe('UserCallout', function () {
this.userCallout = new UserCallout();
this.closeButton = $('.js-close-callout.close');
this.userCalloutBtn = $('.js-close-callout:not(.close)');
- this.userCalloutContainer = $('.user-callout');
});
it('hides when user clicks on the dismiss-icon', (done) => {
diff --git a/spec/javascripts/vue_pipelines_index/stage_spec.js b/spec/javascripts/vue_pipelines_index/stage_spec.js
new file mode 100644
index 00000000000..542661df2b0
--- /dev/null
+++ b/spec/javascripts/vue_pipelines_index/stage_spec.js
@@ -0,0 +1,66 @@
+import Vue from 'vue';
+import { SUCCESS_SVG } from '~/ci_status_icons';
+import Stage from '~/vue_pipelines_index/components/stage';
+
+function minify(string) {
+ return string.replace(/\s/g, '');
+}
+
+describe('Pipelines Stage', () => {
+ describe('data', () => {
+ let stageReturnValue;
+
+ beforeEach(() => {
+ stageReturnValue = Stage.data();
+ });
+
+ it('should return object with .builds and .spinner', () => {
+ expect(stageReturnValue).toEqual({
+ builds: '',
+ spinner: '<span class="fa fa-spinner fa-spin"></span>',
+ });
+ });
+ });
+
+ describe('computed', () => {
+ describe('svgHTML', function () {
+ let stage;
+ let svgHTML;
+
+ beforeEach(() => {
+ stage = { stage: { status: { icon: 'icon_status_success' } } };
+
+ svgHTML = Stage.computed.svgHTML.call(stage);
+ });
+
+ it("should return the correct icon for the stage's status", () => {
+ expect(svgHTML).toBe(SUCCESS_SVG);
+ });
+ });
+ });
+
+ describe('when mounted', () => {
+ let StageComponent;
+ let renderedComponent;
+ let stage;
+
+ beforeEach(() => {
+ stage = { status: { icon: 'icon_status_success' } };
+
+ StageComponent = Vue.extend(Stage);
+
+ renderedComponent = new StageComponent({
+ propsData: {
+ stage,
+ },
+ }).$mount();
+ });
+
+ it('should render the correct status svg', () => {
+ const minifiedComponent = minify(renderedComponent.$el.outerHTML);
+ const expectedSVG = minify(SUCCESS_SVG);
+
+ expect(minifiedComponent).toContain(expectedSVG);
+ });
+ });
+});
diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb
index c98e7ee14fd..592c90cda36 100644
--- a/spec/models/project_services/chat_notification_service_spec.rb
+++ b/spec/models/project_services/chat_notification_service_spec.rb
@@ -1,11 +1,29 @@
require 'spec_helper'
describe ChatNotificationService, models: true do
- describe "Associations" do
+ describe 'Associations' do
before do
allow(subject).to receive(:activated?).and_return(true)
end
it { is_expected.to validate_presence_of :webhook }
end
+
+ describe '#can_test?' do
+ context 'with empty repository' do
+ it 'returns false' do
+ subject.project = create(:empty_project, :empty_repo)
+
+ expect(subject.can_test?).to be false
+ end
+ end
+
+ context 'with repository' do
+ it 'returns true' do
+ subject.project = create(:project)
+
+ expect(subject.can_test?).to be true
+ end
+ end
+ end
end
diff --git a/spec/serializers/build_serializer_spec.rb b/spec/serializers/build_serializer_spec.rb
index 3cc791bca50..7f1abecfafe 100644
--- a/spec/serializers/build_serializer_spec.rb
+++ b/spec/serializers/build_serializer_spec.rb
@@ -38,7 +38,7 @@ describe BuildSerializer do
expect(subject[:text]).to eq(status.text)
expect(subject[:label]).to eq(status.label)
expect(subject[:icon]).to eq(status.icon)
- expect(subject[:favicon]).to eq(status.favicon)
+ expect(subject[:favicon]).to eq("/assets/ci_favicons/#{status.favicon}.ico")
end
end
end
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index f6249ab4664..ecde45a6d44 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -144,7 +144,7 @@ describe PipelineSerializer do
expect(subject[:text]).to eq(status.text)
expect(subject[:label]).to eq(status.label)
expect(subject[:icon]).to eq(status.icon)
- expect(subject[:favicon]).to eq(status.favicon)
+ expect(subject[:favicon]).to eq("/assets/ci_favicons/#{status.favicon}.ico")
end
end
end
diff --git a/spec/services/search/global_service_spec.rb b/spec/services/search/global_service_spec.rb
index 2531607acad..cbf4f56213d 100644
--- a/spec/services/search/global_service_spec.rb
+++ b/spec/services/search/global_service_spec.rb
@@ -40,27 +40,6 @@ describe Search::GlobalService, services: true do
expect(results.objects('projects')).to match_array [found_project]
end
-
- context 'nested group' do
- let!(:nested_group) { create(:group, :nested) }
- let!(:project) { create(:empty_project, namespace: nested_group) }
-
- before do
- project.add_master(user)
- end
-
- it 'returns result from nested group' do
- results = Search::GlobalService.new(user, search: project.path).execute
-
- expect(results.objects('projects')).to match_array [project]
- end
-
- it 'returns result from descendants when search inside group' do
- results = Search::GlobalService.new(user, search: project.path, group_id: nested_group.parent).execute
-
- expect(results.objects('projects')).to match_array [project]
- end
- end
end
end
end
diff --git a/spec/services/search/group_service_spec.rb b/spec/services/search/group_service_spec.rb
new file mode 100644
index 00000000000..38f264f6e7b
--- /dev/null
+++ b/spec/services/search/group_service_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Search::GroupService, services: true do
+ shared_examples_for 'group search' do
+ context 'finding projects by name' do
+ let(:user) { create(:user) }
+ let(:term) { "Project Name" }
+ let(:nested_group) { create(:group, :nested) }
+
+ # These projects shouldn't be found
+ let!(:outside_project) { create(:empty_project, :public, name: "Outside #{term}") }
+ let!(:private_project) { create(:empty_project, :private, namespace: nested_group, name: "Private #{term}" )}
+ let!(:other_project) { create(:empty_project, :public, namespace: nested_group, name: term.reverse) }
+
+ # These projects should be found
+ let!(:project1) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 1") }
+ let!(:project2) { create(:empty_project, :internal, namespace: nested_group, name: "Inner #{term} 2") }
+ let!(:project3) { create(:empty_project, :internal, namespace: nested_group.parent, name: "Outer #{term}") }
+
+ let(:results) { Search::GroupService.new(user, search_group, search: term).execute }
+ subject { results.objects('projects') }
+
+ context 'in parent group' do
+ let(:search_group) { nested_group.parent }
+
+ it { is_expected.to match_array([project1, project2, project3]) }
+ end
+
+ context 'in subgroup' do
+ let(:search_group) { nested_group }
+
+ it { is_expected.to match_array([project1, project2]) }
+ end
+ end
+ end
+
+ describe 'basic search' do
+ include_examples 'group search'
+ end
+end
diff --git a/spec/views/layouts/nav/_project.html.haml_spec.rb b/spec/views/layouts/nav/_project.html.haml_spec.rb
new file mode 100644
index 00000000000..fd1637ca91b
--- /dev/null
+++ b/spec/views/layouts/nav/_project.html.haml_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'layouts/nav/_project' do
+ describe 'container registry tab' do
+ before do
+ stub_container_registry_config(enabled: true)
+
+ assign(:project, create(:project))
+ allow(view).to receive(:current_ref).and_return('master')
+
+ allow(view).to receive(:can?).and_return(true)
+ allow(controller).to receive(:controller_name)
+ .and_return('repositories')
+ allow(controller).to receive(:controller_path)
+ .and_return('projects/registry/repositories')
+ end
+
+ it 'has both Registry and Repository tabs' do
+ render
+
+ expect(rendered).to have_text 'Repository'
+ expect(rendered).to have_text 'Registry'
+ end
+
+ it 'highlights only one tab' do
+ render
+
+ expect(rendered).to have_css('.active', count: 1)
+ end
+
+ it 'highlights container registry tab only' do
+ render
+
+ expect(rendered).to have_css('.active', text: 'Registry')
+ end
+ end
+end