summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Ivan Vargas <jvargas@gitlab.com>2018-01-23 12:50:58 -0600
committerJose Ivan Vargas <jvargas@gitlab.com>2018-02-01 09:41:30 -0600
commit1123d9dc460353cbc3b46606cc2235f0433f35e1 (patch)
tree04807a5e04d880b37d7841118a868184c375f65d
parent449b0ebaf6f3ca65b48f372293117acc9a7e0abc (diff)
downloadgitlab-ce-35779-realtime-update-of-pipeline-status-in-files-view.tar.gz
Added more tests and corrected typos35779-realtime-update-of-pipeline-status-in-files-view
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js1
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js35
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue78
-rw-r--r--app/assets/stylesheets/pages/commits.scss10
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--features/project/project.feature1
-rw-r--r--features/steps/shared/project.rb1
-rw-r--r--spec/javascripts/commit/commit_pipeline_status_component_spec.js85
8 files changed, 131 insertions, 82 deletions
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 4c42fda16d7..55154cdddcb 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -5,7 +5,6 @@ import TreeView from '~/tree';
import BlobViewer from '~/blob/viewer/index';
import Activities from '~/activities';
import { ajaxGet } from '~/lib/utils/common_utils';
-import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
index f14c3f86687..c4b3356e478 100644
--- a/app/assets/javascripts/pages/projects/tree/show/index.js
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -15,24 +15,23 @@ export default () => {
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath));
const commitPipelineStatusEl = document.getElementById('commit-pipeline-status');
- const $statusLink = $('.ci-status-link');
- if ($statusLink.length > 0) {
- $statusLink.remove();
+ const statusLink = document.querySelector('.commit-actions .ci-status-link');
+ if (statusLink != null) {
+ statusLink.remove();
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: commitPipelineStatusEl,
+ components: {
+ commitPipelineStatus,
+ },
+ render(createElement) {
+ return createElement('commit-pipeline-status', {
+ props: {
+ endpoint: commitPipelineStatusEl.dataset.endpoint,
+ },
+ });
+ },
+ });
}
- commitPipelineStatusEl.classList.remove('hidden');
- // eslint-disable-next-line no-new
- new Vue({
- el: '#commit-pipeline-status',
- components: {
- commitPipelineStatus,
- },
- render(createElement) {
- return createElement('commit-pipeline-status', {
- props: {
- endpoint: commitPipelineStatusEl.dataset.endpoint,
- },
- });
- },
- });
};
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index e13acf8555a..63f20a0041d 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -1,8 +1,10 @@
<script>
import Visibility from 'visibilityjs';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
+ import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import Poll from '~/lib/utils/poll';
import Flash from '~/flash';
+ import { s__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import CommitPipelineService from '../services/commit_pipeline_service';
@@ -12,46 +14,54 @@
},
components: {
ciIcon,
+ loadingIcon,
},
props: {
endpoint: {
type: String,
required: true,
},
+ /* This prop can be used to replace some of the `render_commit_status`
+ used across GitLab, this way we could use this vue component and add a
+ realtime status where it makes sense
realtime: {
type: Boolean,
required: false,
default: true,
- },
+ }, */
},
data() {
return {
ciStatus: {},
isLoading: true,
- service: {},
- stageTitle: '',
};
},
+ computed: {
+ statusTitle() {
+ return sprintf(s__('Commits|Commit: %{commitText}'), { commitText: this.ciStatus.text });
+ },
+ },
mounted() {
this.service = new CommitPipelineService(this.endpoint);
- if (this.realtime) {
- this.initPolling();
- } else {
- this.fetchPipelineCommitData();
- }
+ this.initPolling();
},
methods: {
successCallback(res) {
- if (res.data.pipelines.length > 0) {
- this.ciStatus = res.data.pipelines[0].details.stages[0].status;
- this.stageTitle = res.data.pipelines[0].details.stages[0].title;
- this.isLoading = false;
- } else {
- this.isLoading = true;
+ const pipelines = res.data.pipelines;
+ if (pipelines.length > 0) {
+ // The pipeline entity always keeps the latest pipeline info on the `details.status`
+ this.ciStatus = pipelines[0].details.status;
}
+ this.isLoading = false;
},
- errorCallback(err) {
- Flash(err);
+ errorCallback() {
+ this.ciStatus = {
+ text: 'not found',
+ icon: 'status_notfound',
+ group: 'notfound',
+ };
+ this.isLoading = false;
+ Flash(s__('Something went wrong on our end'));
},
initPolling() {
this.poll = new Poll({
@@ -78,8 +88,8 @@
},
fetchPipelineCommitData() {
this.service.fetchData()
- .then(this.successCallback)
- .catch(this.errorCallback);
+ .then(this.successCallback)
+ .catch(this.errorCallback);
},
},
destroy() {
@@ -88,19 +98,23 @@
};
</script>
<template>
- <div
- v-if="isLoading">
- </div>
- <a
- v-else
- :href="ciStatus.details_path"
- >
- <ci-icon
- v-tooltip
- :title="stageTitle"
- :aria-label="stageTitle"
- data-container="body"
- :status="ciStatus"
+ <div>
+ <loading-icon
+ label="Loading pipeline status"
+ size="3"
+ v-if="isLoading"
/>
- </a>
+ <a
+ v-else
+ :href="ciStatus.details_path"
+ >
+ <ci-icon
+ v-tooltip
+ :title="statusTitle"
+ :aria-label="statusTitle"
+ data-container="body"
+ :status="ciStatus"
+ />
+ </a>
+ </div>
</template>
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index adfd72556b8..17801ed5910 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -196,6 +196,14 @@
@media (min-width: $screen-sm-min) {
font-size: 0;
+ div {
+ display: inline;
+ }
+
+ .fa-spinner {
+ font-size: 12px;
+ }
+
span {
font-size: 6px;
}
@@ -226,7 +234,7 @@
.ci-status-icon {
position: relative;
- top: 3px;
+ top: 1px;
}
}
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index c94e10947e6..90272ad9554 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -51,7 +51,7 @@
- if commit.status(ref)
= render_commit_status(commit, ref: ref)
- #commit-pipeline-status.hidden{ data: { endpoint: pipelines_project_commit_path(project, commit.id) } }
+ #commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id) } }
= link_to commit.short_id, link, class: "commit-sha btn btn-transparent btn-link"
= clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"))
= link_to_browse_code(project, commit)
diff --git a/features/project/project.feature b/features/project/project.feature
index bcd72c5c5a3..23817ef3ac9 100644
--- a/features/project/project.feature
+++ b/features/project/project.feature
@@ -23,7 +23,6 @@ Feature: Project
And I visit project "Shop" page
Then I should see project "Shop" README
- @javascript
Scenario: I should see last commit with CI
Given project "Shop" has CI enabled
Given project "Shop" has CI build
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index 923d54a6545..affbccccdf9 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -218,7 +218,6 @@ module SharedProject
end
step 'I should see last commit with CI status' do
- sleep 2
page.within ".blob-commit-info" do
expect(page).to have_content(project.commit.sha[0..6])
expect(page).to have_link("Commit: skipped")
diff --git a/spec/javascripts/commit/commit_pipeline_status_component_spec.js b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
index 2a52097e0d5..90f290e845e 100644
--- a/spec/javascripts/commit/commit_pipeline_status_component_spec.js
+++ b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
@@ -6,7 +6,7 @@ import mountComponent from '../helpers/vue_mount_component_helper';
describe('Commit pipeline status component', () => {
let vm;
- let component;
+ let Component;
let mock;
const mockCiStatus = {
details_path: '/root/hello-world/pipelines/1',
@@ -19,34 +19,25 @@ describe('Commit pipeline status component', () => {
};
beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet('/dummy/endpoint').reply(() => {
- const res = Promise.resolve([200, {
- pipelines: [
- {
- details: {
- stages: [
- {
- status: mockCiStatus,
- title: 'Commit: canceled',
- },
- ],
- },
- },
- ],
- }]);
- return res;
- });
- component = Vue.extend(commitPipelineStatus);
- });
-
- afterEach(() => {
- mock.reset();
+ Component = Vue.extend(commitPipelineStatus);
});
- describe('While polling pipeline data', () => {
+ describe('While polling pipeline data succesfully', () => {
beforeEach(() => {
- vm = mountComponent(component, {
+ mock = new MockAdapter(axios);
+ mock.onGet('/dummy/endpoint').reply(() => {
+ const res = Promise.resolve([200, {
+ pipelines: [
+ {
+ details: {
+ status: mockCiStatus,
+ },
+ },
+ ],
+ }]);
+ return res;
+ });
+ vm = mountComponent(Component, {
endpoint: '/dummy/endpoint',
});
});
@@ -54,18 +45,58 @@ describe('Commit pipeline status component', () => {
afterEach(() => {
vm.poll.stop();
vm.$destroy();
+ mock.restore();
+ });
+
+ it('shows the loading icon when polling is starting', (done) => {
+ expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.loading-container')).toBe(null);
+ done();
+ });
});
it('contains a ciStatus when the polling is succesful ', (done) => {
setTimeout(() => {
expect(vm.ciStatus).toEqual(mockCiStatus);
done();
- }, 1000);
+ });
});
it('contains a ci-status icon when polling is succesful', (done) => {
setTimeout(() => {
expect(vm.$el.querySelector('.ci-status-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.ci-status-icon').classList).toContain(`ci-status-icon-${mockCiStatus.group}`);
+ done();
+ });
+ });
+ });
+
+ describe('When polling data was not succesful', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet('/dummy/endpoint').reply(() => {
+ const res = Promise.reject([502, { }]);
+ return res;
+ });
+ vm = new Component({
+ props: {
+ endpoint: '/dummy/endpoint',
+ },
+ });
+ });
+
+ afterEach(() => {
+ vm.poll.stop();
+ vm.$destroy();
+ mock.restore();
+ });
+
+ it('calls an errorCallback', (done) => {
+ spyOn(vm, 'errorCallback').and.callThrough();
+ vm.$mount();
+ setTimeout(() => {
+ expect(vm.errorCallback.calls.count()).toEqual(1);
done();
});
});