summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-05-12 18:03:13 +0100
committerFilipa Lacerda <filipa@gitlab.com>2017-05-12 19:23:59 +0100
commit418f5d3f0c4a085c10c098684e8e572508585724 (patch)
tree5bc1605739360ed09619e14ab8ce6003417939cb
parent6e3960ab7ef1cb099e579da226d036e105f07405 (diff)
downloadgitlab-ce-24339-job-page-header-step-2.tar.gz
Adds reusable header component for job and pipeline24339-job-page-header-step-2
Adds timago reusable component port from ruby helper
-rw-r--r--app/assets/javascripts/builds/build_bundle.js22
-rw-r--r--app/assets/javascripts/builds/components/build_component.vue44
-rw-r--r--app/assets/javascripts/builds/mock.js1366
-rw-r--r--app/assets/javascripts/builds/services/build_service.js5
-rw-r--r--app/assets/javascripts/builds/stores/build_store.js39
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue70
-rw-r--r--app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue65
-rw-r--r--app/assets/javascripts/vue_shared/vue_resource_interceptor.js12
-rw-r--r--app/assets/stylesheets/pages/status.scss197
-rw-r--r--app/views/projects/builds/show.html.haml2
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js82
-rw-r--r--spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js65
12 files changed, 1857 insertions, 112 deletions
diff --git a/app/assets/javascripts/builds/build_bundle.js b/app/assets/javascripts/builds/build_bundle.js
index 2e39e8b84ed..94ae4dc1b9e 100644
--- a/app/assets/javascripts/builds/build_bundle.js
+++ b/app/assets/javascripts/builds/build_bundle.js
@@ -2,9 +2,27 @@ import Vue from 'vue';
import buildApp from './components/build_component.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({
- el: '#js-build-app-vue',
+ el: document.getElementById('js-build-app-vue'),
+
components: {
buildApp,
},
- render: createElement => createElement('build-app'),
+
+ data() {
+ const dataset = this.$options.el.dataset;
+
+ return {
+ endpoint: dataset.endpoint,
+ cssClass: dataset.class,
+ };
+ },
+
+ render(createElement) {
+ return createElement('build-app', {
+ props: {
+ endpoint: this.endpoint,
+ cssClass: this.cssClass,
+ },
+ });
+ },
}));
diff --git a/app/assets/javascripts/builds/components/build_component.vue b/app/assets/javascripts/builds/components/build_component.vue
index 55c34a1d5b0..16bd3ef2d9d 100644
--- a/app/assets/javascripts/builds/components/build_component.vue
+++ b/app/assets/javascripts/builds/components/build_component.vue
@@ -6,19 +6,30 @@ import Poll from '../../lib/utils/poll';
import BuildStore from '../stores/build_store';
import BuildService from '../services/build_service';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+import headerComponent from '../../vue_shared/components/header_ci_component.vue';
export default {
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ cssClass: {
+ type: String,
+ required: true,
+ },
+ },
+
components: {
loadingIcon,
+ headerComponent,
},
data() {
- const endpoint = '';
const store = new BuildStore();
return {
isLoading: false,
- endpoint,
store,
state: store.state,
};
@@ -60,15 +71,40 @@ export default {
// eslint-disable-next-line no-new
new Flash('An error occurred while fetching the job.');
},
+
+ postAction(action) {
+ this.service.postAction(action.path)
+ .then(() => {
+ this.service.get()
+ .then(this.successCallback)
+ .catch(this.errorCallback);
+ })
+ .catch(() => {
+ // show error
+ });
+ },
},
};
</script>
<template>
- <section>
- <loading-icon v-if="isLoading" />
+ <section :class="cssClass">
+ <loading-icon
+ v-if="isLoading"
+ label="Loading job details"
+ size="3"
+ />
<section v-else>
+ <header-component
+ :status="state.status"
+ item-name="Job"
+ :item-id="state.build.id"
+ :time="state.build.created_at"
+ :user="state.user"
+ :actions="state.actions"
+ @postAction="postAction"
+ />
</section>
</section>
</template>
diff --git a/app/assets/javascripts/builds/mock.js b/app/assets/javascripts/builds/mock.js
new file mode 100644
index 00000000000..fedaee0c043
--- /dev/null
+++ b/app/assets/javascripts/builds/mock.js
@@ -0,0 +1,1366 @@
+/* eslint-disable */
+
+// TO DELETE
+export default {
+ "id": 131,
+ "user": {
+ "name": "Root",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "active": false,
+ "coverage": null,
+ "path": "/root/review-app/pipelines/131",
+ "details": {
+ "status": {
+ "icon": "icon_status_failed",
+ "text": "failed",
+ "label": "failed",
+ "group": "failed",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_failed-5f8edf9ec029ce816326fba3b72e6d48c4699845c6d0a7a40cef401395117931.ico"
+ },
+ "duration": 13,
+ "finished_at": "2017-05-08T16:00:19.904Z",
+ "stages": [{
+ "name": "review",
+ "title": "review: passed",
+ "groups": [{
+ "name": "review_1",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4374",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4374/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4374,
+ "name": "review_1",
+ "build_path": "/root/review-app/builds/4374",
+ "retry_path": "/root/review-app/builds/4374/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:39.880Z",
+ "updated_at": "2017-05-08T14:57:52.639Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4374",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4374/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "review_2",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4376",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4376/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4376,
+ "name": "review_2",
+ "build_path": "/root/review-app/builds/4376",
+ "retry_path": "/root/review-app/builds/4376/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:39.973Z",
+ "updated_at": "2017-05-08T14:57:57.773Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4376",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4376/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "review_3",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4373",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4373/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4373,
+ "name": "review_3",
+ "build_path": "/root/review-app/builds/4373",
+ "retry_path": "/root/review-app/builds/4373/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:39.830Z",
+ "updated_at": "2017-05-08T14:57:47.117Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4373",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4373/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "stop_review",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_manual",
+ "text": "manual",
+ "label": "manual stop action",
+ "group": "manual",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4375",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_manual-9f78d05507152e2336b392a51b28708907bde24753767fd7f95d112839b95223.ico",
+ "action": {
+ "icon": "icon_action_stop",
+ "title": "Stop",
+ "path": "/root/review-app/builds/4375/play",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4375,
+ "name": "stop_review",
+ "build_path": "/root/review-app/builds/4375",
+ "retry_path": "/root/review-app/builds/4375/retry",
+ "play_path": "/root/review-app/builds/4375/play",
+ "playable": true,
+ "created_at": "2017-05-08T14:57:39.909Z",
+ "updated_at": "2017-05-08T14:57:41.755Z",
+ "status": {
+ "icon": "icon_status_manual",
+ "text": "manual",
+ "label": "manual stop action",
+ "group": "manual",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4375",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_manual-9f78d05507152e2336b392a51b28708907bde24753767fd7f95d112839b95223.ico",
+ "action": {
+ "icon": "icon_action_stop",
+ "title": "Stop",
+ "path": "/root/review-app/builds/4375/play",
+ "method": "post"
+ }
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#review",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico"
+ },
+ "path": "/root/review-app/pipelines/131#review",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=review"
+ }, {
+ "name": "staging",
+ "title": "staging: failed",
+ "groups": [{
+ "name": "staging",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_failed",
+ "text": "failed",
+ "label": "failed",
+ "group": "failed",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4377",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_failed-5f8edf9ec029ce816326fba3b72e6d48c4699845c6d0a7a40cef401395117931.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4377/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4377,
+ "name": "staging",
+ "build_path": "/root/review-app/builds/4377",
+ "retry_path": "/root/review-app/builds/4377/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:39.998Z",
+ "updated_at": "2017-05-08T16:00:11.544Z",
+ "status": {
+ "icon": "icon_status_failed",
+ "text": "failed",
+ "label": "failed",
+ "group": "failed",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4377",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_failed-5f8edf9ec029ce816326fba3b72e6d48c4699845c6d0a7a40cef401395117931.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4377/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "staging_1",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4378",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4378/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4378,
+ "name": "staging_1",
+ "build_path": "/root/review-app/builds/4378",
+ "retry_path": "/root/review-app/builds/4378/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.047Z",
+ "updated_at": "2017-05-08T14:58:02.434Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4378",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4378/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "staging_2",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4379",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4379/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4379,
+ "name": "staging_2",
+ "build_path": "/root/review-app/builds/4379",
+ "retry_path": "/root/review-app/builds/4379/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.085Z",
+ "updated_at": "2017-05-08T14:58:07.025Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4379",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4379/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }, {
+ "name": "staging_3",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4380",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4380/retry",
+ "method": "post"
+ }
+ },
+ "jobs": [{
+ "id": 4380,
+ "name": "staging_3",
+ "build_path": "/root/review-app/builds/4380",
+ "retry_path": "/root/review-app/builds/4380/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.109Z",
+ "updated_at": "2017-05-08T14:58:11.956Z",
+ "status": {
+ "icon": "icon_status_success",
+ "text": "passed",
+ "label": "passed",
+ "group": "success",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4380",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico",
+ "action": {
+ "icon": "icon_action_retry",
+ "title": "Retry",
+ "path": "/root/review-app/builds/4380/retry",
+ "method": "post"
+ }
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_failed",
+ "text": "failed",
+ "label": "failed",
+ "group": "failed",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#staging",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_failed-5f8edf9ec029ce816326fba3b72e6d48c4699845c6d0a7a40cef401395117931.ico"
+ },
+ "path": "/root/review-app/pipelines/131#staging",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=staging"
+ }, {
+ "name": "production",
+ "title": "production: skipped",
+ "groups": [{
+ "name": "prod_1",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4381",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4381,
+ "name": "prod_1",
+ "build_path": "/root/review-app/builds/4381",
+ "retry_path": "/root/review-app/builds/4381/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.135Z",
+ "updated_at": "2017-05-08T16:00:12.928Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4381",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "prod_2",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4382",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4382,
+ "name": "prod_2",
+ "build_path": "/root/review-app/builds/4382",
+ "retry_path": "/root/review-app/builds/4382/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.171Z",
+ "updated_at": "2017-05-08T16:00:12.653Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4382",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "prod_3",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4383",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4383,
+ "name": "prod_3",
+ "build_path": "/root/review-app/builds/4383",
+ "retry_path": "/root/review-app/builds/4383/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.296Z",
+ "updated_at": "2017-05-08T16:00:12.394Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4383",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "production",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped (not allowed)",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4384",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4384,
+ "name": "production",
+ "build_path": "/root/review-app/builds/4384",
+ "retry_path": "/root/review-app/builds/4384/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.338Z",
+ "updated_at": "2017-05-08T16:00:12.167Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped (not allowed)",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4384",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#production",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "path": "/root/review-app/pipelines/131#production",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=production"
+ }, {
+ "name": "stage1",
+ "title": "stage1: skipped",
+ "groups": [{
+ "name": "job_01",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4386",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4386,
+ "name": "job_01",
+ "build_path": "/root/review-app/builds/4386",
+ "retry_path": "/root/review-app/builds/4386/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.461Z",
+ "updated_at": "2017-05-08T16:00:13.751Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4386",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "job_02",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4387",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4387,
+ "name": "job_02",
+ "build_path": "/root/review-app/builds/4387",
+ "retry_path": "/root/review-app/builds/4387/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.520Z",
+ "updated_at": "2017-05-08T16:00:13.592Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4387",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "stage1",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4385",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4385,
+ "name": "stage1",
+ "build_path": "/root/review-app/builds/4385",
+ "retry_path": "/root/review-app/builds/4385/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.402Z",
+ "updated_at": "2017-05-08T16:00:13.531Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4385",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#stage1",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "path": "/root/review-app/pipelines/131#stage1",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=stage1"
+ }, {
+ "name": "stage2",
+ "title": "stage2: skipped",
+ "groups": [{
+ "name": "test",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4388",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4388,
+ "name": "test",
+ "build_path": "/root/review-app/builds/4388",
+ "retry_path": "/root/review-app/builds/4388/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.678Z",
+ "updated_at": "2017-05-08T16:00:14.608Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4388",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#stage2",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "path": "/root/review-app/pipelines/131#stage2",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=stage2"
+ }, {
+ "name": "stage3",
+ "title": "stage3: skipped",
+ "groups": [{
+ "name": "test1",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4390",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4390,
+ "name": "test1",
+ "build_path": "/root/review-app/builds/4390",
+ "retry_path": "/root/review-app/builds/4390/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.768Z",
+ "updated_at": "2017-05-08T16:00:15.495Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4390",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test2",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4391",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4391,
+ "name": "test2",
+ "build_path": "/root/review-app/builds/4391",
+ "retry_path": "/root/review-app/builds/4391/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.800Z",
+ "updated_at": "2017-05-08T16:00:15.784Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4391",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test3",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4389",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4389,
+ "name": "test3",
+ "build_path": "/root/review-app/builds/4389",
+ "retry_path": "/root/review-app/builds/4389/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.732Z",
+ "updated_at": "2017-05-08T16:00:15.121Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4389",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test4",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4392",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4392,
+ "name": "test4",
+ "build_path": "/root/review-app/builds/4392",
+ "retry_path": "/root/review-app/builds/4392/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.834Z",
+ "updated_at": "2017-05-08T16:00:16.084Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4392",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test5",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4393",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4393,
+ "name": "test5",
+ "build_path": "/root/review-app/builds/4393",
+ "retry_path": "/root/review-app/builds/4393/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.881Z",
+ "updated_at": "2017-05-08T16:00:16.539Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4393",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test6",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4394",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4394,
+ "name": "test6",
+ "build_path": "/root/review-app/builds/4394",
+ "retry_path": "/root/review-app/builds/4394/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.914Z",
+ "updated_at": "2017-05-08T16:00:17.071Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4394",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test7",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4395",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4395,
+ "name": "test7",
+ "build_path": "/root/review-app/builds/4395",
+ "retry_path": "/root/review-app/builds/4395/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.947Z",
+ "updated_at": "2017-05-08T16:00:17.402Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4395",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test8",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4396",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4396,
+ "name": "test8",
+ "build_path": "/root/review-app/builds/4396",
+ "retry_path": "/root/review-app/builds/4396/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:40.975Z",
+ "updated_at": "2017-05-08T16:00:17.611Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4396",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test9",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4397",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4397,
+ "name": "test9",
+ "build_path": "/root/review-app/builds/4397",
+ "retry_path": "/root/review-app/builds/4397/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.005Z",
+ "updated_at": "2017-05-08T16:00:17.714Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4397",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test10",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4398",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4398,
+ "name": "test10",
+ "build_path": "/root/review-app/builds/4398",
+ "retry_path": "/root/review-app/builds/4398/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.043Z",
+ "updated_at": "2017-05-08T16:00:17.534Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4398",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test11",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4399",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4399,
+ "name": "test11",
+ "build_path": "/root/review-app/builds/4399",
+ "retry_path": "/root/review-app/builds/4399/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.084Z",
+ "updated_at": "2017-05-08T16:00:17.324Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4399",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test12",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4400",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4400,
+ "name": "test12",
+ "build_path": "/root/review-app/builds/4400",
+ "retry_path": "/root/review-app/builds/4400/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.122Z",
+ "updated_at": "2017-05-08T16:00:16.646Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4400",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test13",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4401",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4401,
+ "name": "test13",
+ "build_path": "/root/review-app/builds/4401",
+ "retry_path": "/root/review-app/builds/4401/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.164Z",
+ "updated_at": "2017-05-08T16:00:16.318Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4401",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test14",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4402",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4402,
+ "name": "test14",
+ "build_path": "/root/review-app/builds/4402",
+ "retry_path": "/root/review-app/builds/4402/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.230Z",
+ "updated_at": "2017-05-08T16:00:15.968Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4402",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test15",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4403",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4403,
+ "name": "test15",
+ "build_path": "/root/review-app/builds/4403",
+ "retry_path": "/root/review-app/builds/4403/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.265Z",
+ "updated_at": "2017-05-08T16:00:15.708Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4403",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "test16",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4404",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4404,
+ "name": "test16",
+ "build_path": "/root/review-app/builds/4404",
+ "retry_path": "/root/review-app/builds/4404/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.304Z",
+ "updated_at": "2017-05-08T16:00:15.475Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4404",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#stage3",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "path": "/root/review-app/pipelines/131#stage3",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=stage3"
+ }, {
+ "name": "stage4",
+ "title": "stage4: skipped",
+ "groups": [{
+ "name": "stage4",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4405",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4405,
+ "name": "stage4",
+ "build_path": "/root/review-app/builds/4405",
+ "retry_path": "/root/review-app/builds/4405/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.353Z",
+ "updated_at": "2017-05-08T16:00:18.791Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4405",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "stage4_2",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4406",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4406,
+ "name": "stage4_2",
+ "build_path": "/root/review-app/builds/4406",
+ "retry_path": "/root/review-app/builds/4406/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.423Z",
+ "updated_at": "2017-05-08T16:00:19.007Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4406",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "stage4_3",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4407",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4407,
+ "name": "stage4_3",
+ "build_path": "/root/review-app/builds/4407",
+ "retry_path": "/root/review-app/builds/4407/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.478Z",
+ "updated_at": "2017-05-08T16:00:19.253Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4407",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }, {
+ "name": "stage4_4",
+ "size": 1,
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4408",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "jobs": [{
+ "id": 4408,
+ "name": "stage4_4",
+ "build_path": "/root/review-app/builds/4408",
+ "retry_path": "/root/review-app/builds/4408/retry",
+ "playable": false,
+ "created_at": "2017-05-08T14:57:41.533Z",
+ "updated_at": "2017-05-08T16:00:19.354Z",
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/builds/4408",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ }
+ }]
+ }],
+ "status": {
+ "icon": "icon_status_skipped",
+ "text": "skipped",
+ "label": "skipped",
+ "group": "skipped",
+ "has_details": true,
+ "details_path": "/root/review-app/pipelines/131#stage4",
+ "favicon": "/assets/ci_favicons/dev/favicon_status_skipped-9a4245cf6584dcf7ae1aad5c0e649784f19770cbf4deea9ec3416889083cbc42.ico"
+ },
+ "path": "/root/review-app/pipelines/131#stage4",
+ "dropdown_path": "/root/review-app/pipelines/131/stage.json?stage=stage4"
+ }],
+ "artifacts": [],
+ "manual_actions": [{
+ "name": "production",
+ "path": "/root/review-app/builds/4384/play",
+ "playable": false
+ }, {
+ "name": "stop_review",
+ "path": "/root/review-app/builds/4375/play",
+ "playable": true
+ }]
+ },
+ "flags": {
+ "latest": true,
+ "triggered": false,
+ "stuck": false,
+ "yaml_errors": false,
+ "retryable": true,
+ "cancelable": true
+ },
+ "ref": {
+ "name": "master",
+ "path": "/root/review-app/tree/master",
+ "tag": false,
+ "branch": true
+ },
+ "commit": {
+ "id": "d0672d958e785724593b6cbab15cacc1dbe4d65d",
+ "short_id": "d0672d95",
+ "title": "Update .gitlab-ci.yml",
+ "created_at": "2017-05-08T15:57:38.000+01:00",
+ "parent_ids": ["6431f5413b4465249444032f29256994c7bedc1a"],
+ "message": "Update .gitlab-ci.yml",
+ "author_name": "Root",
+ "author_email": "admin@example.com",
+ "authored_date": "2017-05-08T15:57:38.000+01:00",
+ "committer_name": "Root",
+ "committer_email": "admin@example.com",
+ "committed_date": "2017-05-08T15:57:38.000+01:00",
+ "author": {
+ "name": "Root",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "author_gravatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "commit_url": "http://localhost:3000/root/review-app/commit/d0672d958e785724593b6cbab15cacc1dbe4d65d",
+ "commit_path": "/root/review-app/commit/d0672d958e785724593b6cbab15cacc1dbe4d65d"
+ },
+ "retry_path": "/root/review-app/pipelines/131/retry",
+ "cancel_path": "/root/review-app/pipelines/131/cancel",
+ "created_at": "2017-05-08T14:57:39.781Z",
+ "updated_at": "2017-05-08T16:00:20.052Z"
+}
diff --git a/app/assets/javascripts/builds/services/build_service.js b/app/assets/javascripts/builds/services/build_service.js
index 0bf51580496..b06c4d2f391 100644
--- a/app/assets/javascripts/builds/services/build_service.js
+++ b/app/assets/javascripts/builds/services/build_service.js
@@ -11,4 +11,9 @@ export default class BuildService {
get() {
return this.build.get();
}
+
+ // eslint-disable-next-line class-methods-use-this
+ postAction(endpoint) {
+ return Vue.http.post(endpoint, {}, { emulateJSON: true });
+ }
}
diff --git a/app/assets/javascripts/builds/stores/build_store.js b/app/assets/javascripts/builds/stores/build_store.js
index cdae19c0c89..d37c357aa2d 100644
--- a/app/assets/javascripts/builds/stores/build_store.js
+++ b/app/assets/javascripts/builds/stores/build_store.js
@@ -3,7 +3,46 @@ export default class BuildStore {
this.state = {};
}
+ reset() {
+ this.state = {};
+ }
+
storeBuild(build = {}) {
this.state.build = build;
+
+ this.state.status = build.details.status;
+ this.state.commit = build.commit;
+
+ // TODO verfiy if this data is correct
+ this.state.user = build.user;
+
+ this.state.actions = [];
+
+ if (build.retry_path) {
+ this.state.actions.push({
+ label: 'Retry',
+ path: build.retry_path,
+ cssClass: 'btn btn-inverted-secondary',
+ type: 'button',
+ });
+ }
+
+ if (build.cancel_path) {
+ this.state.actions.push({
+ label: 'Cancel',
+ path: build.cancel_path,
+ cssClass: 'btn btn-danger',
+ type: 'button',
+ });
+ }
+
+ if (this.state.status.group === 'failed') {
+ this.state.actions.push({
+ label: 'New issue',
+ path: '', // TODO
+ cssClass: 'btn btn-new btn-inverted',
+ type: 'link',
+ });
+ }
}
}
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 0a952bc4dc7..d34a23a803d 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,4 +1,7 @@
<script>
+import ciIconBadge from './ci_badge_link.vue';
+import timeagoTooltip from './time_ago_tooltip.vue';
+
/**
* Renders header component for job and pipeline page based on UI mockups
* https://gitlab-org.gitlab.io/gitlab-design/hosted/27724-large-build-logs-spec-previews/
@@ -17,12 +20,12 @@ export default {
type: String,
required: true,
},
- itemID: {
- type: String,
+ itemId: {
+ type: Number,
required: true,
},
time: {
- type: Number,
+ type: String,
required: true,
},
user: {
@@ -36,12 +39,67 @@ export default {
},
components: {
- ciIconBage,
+ ciIconBadge,
+ timeagoTooltip,
+ },
+
+ methods: {
+ onClickAction(action) {
+ this.$emit('postAction', action);
+ },
},
};
</script>
<template>
- <div class="page-content-header">
+ <header class="page-content-header top-area">
+ <section class="header-main-content">
+
+ <ci-icon-badge :status="status" />
+
+ <strong>
+ {{itemName}} #{{itemId}}
+ </strong>
+
+ triggered
+
+ <timeago-tooltip :time="time" />
+
+ by
+
+ <a>
+ <!-- replace this with avatar component bryce is making -->
+ user image
+ </a>
+
+ <a
+ :href="user.web_url"
+ :title="user.email"
+ class="js-user-link commit-committer-link"
+ ref="tooltip">
+ {{user.name}}
+ </a>
+ </section>
+
+ <section
+ class="header-action-button nav-controls"
+ v-if="actions.length">
+ <template v-for="action in actions">
+ <a
+ v-if="action.type === 'link'"
+ :href="action.path"
+ :class="action.cssClass">
+ {{action.label}}
+ </a>
+
+ <button
+ v-else="action.type === 'button'"
+ @click="onClickAction(action)"
+ :class="action.cssClass"
+ type="button">
+ {{action.label}}
+ </button>
- </div>
+ </template>
+ </section>
+ </header>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
new file mode 100644
index 00000000000..caf9414edaa
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
@@ -0,0 +1,65 @@
+<script>
+import tooltipMixin from '../mixins/tooltip';
+import '../../lib/utils/datetime_utility';
+
+/**
+ * Port of ruby helper time_ago_with_tooltip
+ */
+
+export default {
+ props: {
+ time: {
+ type: String,
+ required: true,
+ },
+
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'top',
+ },
+
+ shortFormat: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+
+ htmlClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+
+ mixins: [tooltipMixin],
+
+ computed: {
+ cssClass() {
+ const className = this.shortFormat ? 'js-short-timeago' : 'js-timeago';
+ return `${className} ${this.htmlClass}`;
+ },
+
+ tooltipTitle() {
+ return gl.utils.formatDate(this.time);
+ },
+
+ timeFormated() {
+ const timeago = gl.utils.getTimeago();
+
+ return timeago.format(this.finishedTime);
+ },
+ },
+};
+</script>
+<template>
+ <time
+ :class="cssClass"
+ class="js-timeago js-timeago-render"
+ :title="tooltipTitle"
+ :data-placement="tooltipPlacement"
+ data-container="body"
+ ref="tooltip">
+ {{timeFormated}}
+ </time>
+</template>
diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
index d5f87588c28..992ef7ddad7 100644
--- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
+++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
@@ -22,3 +22,15 @@ Vue.http.interceptors.push((request, next) => {
}
next();
});
+
+// delete
+import mockData from '../builds/mock';
+
+Vue.http.interceptors.push((request, next) => {
+ if (request.url === '/root/review-app/builds/4449.json') {
+ next(request.respondWith(JSON.stringify(mockData), {
+ status: 200,
+ }));
+ }
+ next();
+});
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 4a284247143..ed14034251d 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -1,142 +1,141 @@
-.container-fluid {
- .ci-status {
- padding: 2px 7px 4px;
- margin-right: 10px;
- border: 1px solid $gray-darker;
- white-space: nowrap;
- border-radius: 4px;
-
- &:hover,
- &:focus {
- text-decoration: none;
- }
- svg {
- height: 13px;
- width: 13px;
- position: relative;
- top: 2px;
- overflow: visible;
- }
+.ci-status {
+ padding: 2px 7px 4px;
+ margin-right: 10px;
+ border: 1px solid $gray-darker;
+ white-space: nowrap;
+ border-radius: 4px;
- &.ci-failed,
- &.ci-failed_with_warnings {
- color: $red-500;
- border-color: $red-500;
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
- &:not(span):hover {
- background-color: $red-50;
- color: $red-600;
- border-color: $red-600;
+ svg {
+ height: 13px;
+ width: 13px;
+ position: relative;
+ top: 2px;
+ overflow: visible;
+ }
- svg {
- fill: $red-600;
- }
- }
+ &.ci-failed,
+ &.ci-failed_with_warnings {
+ color: $red-500;
+ border-color: $red-500;
+
+ &:not(span):hover {
+ background-color: $red-50;
+ color: $red-600;
+ border-color: $red-600;
svg {
- fill: $red-500;
+ fill: $red-600;
}
}
- &.ci-success,
- &.ci-success_with_warnings {
- color: $green-600;
- border-color: $green-500;
+ svg {
+ fill: $red-500;
+ }
+ }
- &:not(span):hover {
- background-color: $green-50;
- color: $green-700;
- border-color: $green-600;
+ &.ci-success,
+ &.ci-success_with_warnings {
+ color: $green-600;
+ border-color: $green-500;
- svg {
- fill: $green-600;
- }
- }
+ &:not(span):hover {
+ background-color: $green-50;
+ color: $green-700;
+ border-color: $green-600;
svg {
- fill: $green-500;
+ fill: $green-600;
}
}
- &.ci-canceled,
- &.ci-disabled {
- color: $gl-text-color;
- border-color: $gl-text-color;
+ svg {
+ fill: $green-500;
+ }
+ }
- &:not(span):hover {
- background-color: rgba($gl-text-color, .07);
- }
+ &.ci-canceled,
+ &.ci-disabled {
+ color: $gl-text-color;
+ border-color: $gl-text-color;
- svg {
- fill: $gl-text-color;
- }
+ &:not(span):hover {
+ background-color: rgba($gl-text-color, .07);
}
- &.ci-pending {
- color: $orange-600;
- border-color: $orange-500;
+ svg {
+ fill: $gl-text-color;
+ }
+ }
- &:not(span):hover {
- background-color: $orange-50;
- color: $orange-700;
- border-color: $orange-600;
+ &.ci-pending {
+ color: $orange-600;
+ border-color: $orange-500;
- svg {
- fill: $orange-600;
- }
- }
+ &:not(span):hover {
+ background-color: $orange-50;
+ color: $orange-700;
+ border-color: $orange-600;
svg {
- fill: $orange-500;
+ fill: $orange-600;
}
}
- &.ci-info,
- &.ci-running {
- color: $blue-500;
- border-color: $blue-500;
+ svg {
+ fill: $orange-500;
+ }
+ }
- &:not(span):hover {
- background-color: $blue-50;
- color: $blue-600;
- border-color: $blue-600;
+ &.ci-info,
+ &.ci-running {
+ color: $blue-500;
+ border-color: $blue-500;
- svg {
- fill: $blue-600;
- }
- }
+ &:not(span):hover {
+ background-color: $blue-50;
+ color: $blue-600;
+ border-color: $blue-600;
svg {
- fill: $blue-500;
+ fill: $blue-600;
}
}
- &.ci-created,
- &.ci-skipped {
- color: $gl-text-color-secondary;
- border-color: $gl-text-color-secondary;
+ svg {
+ fill: $blue-500;
+ }
+ }
- &:not(span):hover {
- background-color: rgba($gl-text-color-secondary, .07);
- }
+ &.ci-created,
+ &.ci-skipped {
+ color: $gl-text-color-secondary;
+ border-color: $gl-text-color-secondary;
- svg {
- fill: $gl-text-color-secondary;
- }
+ &:not(span):hover {
+ background-color: rgba($gl-text-color-secondary, .07);
}
- &.ci-manual {
- color: $gl-text-color;
- border-color: $gl-text-color;
+ svg {
+ fill: $gl-text-color-secondary;
+ }
+ }
- &:not(span):hover {
- background-color: rgba($gl-text-color, .07);
- }
+ &.ci-manual {
+ color: $gl-text-color;
+ border-color: $gl-text-color;
- svg {
- fill: $gl-text-color;
- }
+ &:not(span):hover {
+ background-color: rgba($gl-text-color, .07);
+ }
+
+ svg {
+ fill: $gl-text-color;
}
}
}
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 30d69a0656c..561d4b77c57 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -6,7 +6,7 @@
= page_specific_javascript_bundle_tag("common_vue")
= page_specific_javascript_bundle_tag("build")
-#js-build-app-vue{ class: container_class }
+#js-build-app-vue{ data: { endpoint: namespace_project_build_path(@project.namespace, @project, @build, :json ), class: container_class} }
.build-page
= render "header"
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
new file mode 100644
index 00000000000..55fd745cef4
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
@@ -0,0 +1,82 @@
+import Vue from 'vue';
+import headerCi from '~/vue_shared/components/header_ci_component.vue';
+
+fdescribe('Header CI Component', () => {
+ let HeaderCi;
+ let vm;
+ let props;
+
+ beforeEach(() => {
+ HeaderCi = Vue.extend(headerCi);
+
+ props = {
+ status: {
+ group: 'failed',
+ icon: 'ci-status-failed',
+ label: 'failed',
+ text: 'failed',
+ details_path: 'path',
+ },
+ itemName: 'job',
+ itemId: 123,
+ time: '2017-05-08T14:57:39.781Z',
+ user: {
+ web_url: 'path',
+ name: 'Foo',
+ username: 'foobar',
+ email: 'foo@bar.com',
+ avatar_url: 'link',
+ },
+ actions: [
+ {
+ label: 'Retry',
+ path: 'path',
+ type: 'button',
+ cssClass: 'btn',
+ },
+ {
+ label: 'Go',
+ path: 'path',
+ type: 'link',
+ cssClass: 'link',
+ },
+ ],
+ };
+
+ vm = new HeaderCi({
+ propsData: props,
+ }).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render status badge', () => {
+ expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
+ expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
+ expect(
+ vm.$el.querySelector('.ci-failed').getAttribute('href'),
+ ).toEqual(props.status.details_path);
+ });
+
+ it('should render item name and id', () => {
+ expect(vm.$el.querySelector('strong').textContent.trim()).toEqual('job #123');
+ });
+
+ it('should render timeago date', () => {
+ expect(vm.$el.querySelector('time')).toBeDefined();
+ });
+
+ it('should render user icon and name', () => {
+ expect(vm.$el.querySelector('.js-user-link').textContent.trim()).toEqual(props.user.name);
+ });
+
+ it('should render provided actions', () => {
+ expect(vm.$el.querySelector('.btn').tagName).toEqual('BUTTON');
+ expect(vm.$el.querySelector('.btn').textContent.trim()).toEqual(props.actions[0].label);
+ expect(vm.$el.querySelector('.link').tagName).toEqual('A');
+ expect(vm.$el.querySelector('.link').textContent.trim()).toEqual(props.actions[1].label);
+ expect(vm.$el.querySelector('.link').getAttribute('href')).toEqual(props.actions[0].path);
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
new file mode 100644
index 00000000000..303e37138e9
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
@@ -0,0 +1,65 @@
+import Vue from 'vue';
+import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import '~/lib/utils/datetime_utility';
+
+describe('Time ago with tooltip component', () => {
+ let TimeagoTooltip;
+ let vm;
+
+ beforeEach(() => {
+ TimeagoTooltip = Vue.extend(timeagoTooltip);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render timeago with a bootstrap tooltip', () => {
+ vm = new TimeagoTooltip({
+ propsData: {
+ time: '2017-05-08T14:57:39.781Z',
+ },
+ }).$mount();
+
+ expect(vm.$el.tagName).toEqual('TIME');
+ expect(vm.$el.classList.contains('js-timeago')).toEqual(true);
+ expect(
+ vm.$el.getAttribute('data-original-title'),
+ ).toEqual(gl.utils.formatDate('2017-05-08T14:57:39.781Z'));
+ expect(vm.$el.getAttribute('data-placement')).toEqual('top');
+ expect(vm.$el.textContent.trim()).toEqual(vm.$options.computed.timeFormated());
+ });
+
+ it('should render tooltip placed in bottom', () => {
+ vm = new TimeagoTooltip({
+ propsData: {
+ time: '2017-05-08T14:57:39.781Z',
+ tooltipPlacement: 'bottom',
+ },
+ }).$mount();
+
+ expect(vm.$el.getAttribute('data-placement')).toEqual('bottom');
+ });
+
+ it('should render short format class', () => {
+ vm = new TimeagoTooltip({
+ propsData: {
+ time: '2017-05-08T14:57:39.781Z',
+ shortFormat: true,
+ },
+ }).$mount();
+
+ expect(vm.$el.classList.contains('js-short-timeago')).toEqual(true);
+ });
+
+ it('should render provided html class', () => {
+ vm = new TimeagoTooltip({
+ propsData: {
+ time: '2017-05-08T14:57:39.781Z',
+ htmlClass: 'foo',
+ },
+ }).$mount();
+
+ expect(vm.$el.classList.contains('foo')).toEqual(true);
+ });
+});