summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Eastwood <contact@ericeastwood.com>2017-03-22 21:39:09 -0500
committerEric Eastwood <contact@ericeastwood.com>2017-04-03 23:32:24 -0500
commit93b08c8ce384b9a31830fddbe6164f8848e540b3 (patch)
tree3afe49e8f171040559915073251777707f0c0d01
parent36cfb0a7bd60285d1545be1fbc01452ab6c431e8 (diff)
downloadgitlab-ce-29539-fix-pipelines-container-width-with-parallel-diff-for-9-0-stable-merge.tar.gz
Reset container width when switching to pipelines MR tab29539-fix-pipelines-container-width-with-parallel-diff-for-9-0-stable-merge
Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/29539 Conflicts: app/assets/javascripts/commit/pipelines/pipelines_table.js app/assets/javascripts/merge_request_tabs.js spec/javascripts/commit/pipelines/pipelines_spec.js
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js5
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.js142
-rw-r--r--app/assets/javascripts/merge_request_tabs.js36
-rw-r--r--app/assets/javascripts/vue_pipelines_index/pipelines.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/pipelines_table.js72
-rw-r--r--lib/tasks/karma.rake5
-rw-r--r--spec/javascripts/commit/pipelines/pipelines_spec.js32
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb12
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js40
-rw-r--r--spec/javascripts/vue_shared/components/pipelines_table_spec.js15
10 files changed, 217 insertions, 147 deletions
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index b5a988df897..87a9cc13a7e 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -2,7 +2,8 @@
/* global Vue, CommitsPipelineStore, PipelinesService, Flash */
window.Vue = require('vue');
-require('./pipelines_table');
+const PipelinesTable = require('./pipelines_table');
+
/**
* Commits View > Pipelines Tab > Pipelines Table.
* Merge Request View > Pipelines Tab > Pipelines Table.
@@ -21,7 +22,7 @@ $(() => {
}
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
- gl.commits.pipelines.PipelinesTableBundle = new gl.commits.pipelines.PipelinesTableView();
+ gl.commits.pipelines.PipelinesTableBundle = new PipelinesTable();
if (pipelineTableViewEl && pipelineTableViewEl.dataset.disableInitialization === undefined) {
gl.commits.pipelines.PipelinesTableBundle.$mount(pipelineTableViewEl);
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js
index 631ed34851c..4e770ab7c31 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js
@@ -5,9 +5,9 @@ window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
require('../../lib/utils/common_utils');
require('../../vue_shared/vue_resource_interceptor');
-require('../../vue_shared/components/pipelines_table');
require('./pipelines_service');
const PipelineStore = require('./pipelines_store');
+const PipelinesTableComponent = require('../../vue_shared/components/pipelines_table');
/**
*
@@ -19,86 +19,78 @@ const PipelineStore = require('./pipelines_store');
* Necessary SVG in the table are provided as props. This should be refactored
* as soon as we have Webpack and can load them directly into JS files.
*/
+module.exports = Vue.component('pipelines-table', {
+ components: {
+ 'pipelines-table-component': PipelinesTableComponent,
+ },
-(() => {
- window.gl = window.gl || {};
- gl.commits = gl.commits || {};
- gl.commits.pipelines = gl.commits.pipelines || {};
+ /**
+ * Accesses the DOM to provide the needed data.
+ * Returns the necessary props to render `pipelines-table-component` component.
+ *
+ * @return {Object}
+ */
+ data() {
+ const store = new PipelineStore();
- gl.commits.pipelines.PipelinesTableView = Vue.component('pipelines-table', {
+ return {
+ endpoint: null,
+ store,
+ state: store.state,
+ isLoading: false,
+ };
+ },
- components: {
- 'pipelines-table-component': gl.pipelines.PipelinesTableComponent,
- },
+ /**
+ * When the component is about to be mounted, tell the service to fetch the data
+ *
+ * A request to fetch the pipelines will be made.
+ * In case of a successfull response we will store the data in the provided
+ * store, in case of a failed response we need to warn the user.
+ *
+ */
+ beforeMount() {
+ this.endpoint = this.$el.dataset.endpoint;
+ const pipelinesService = new gl.commits.pipelines.PipelinesService(this.endpoint);
- /**
- * Accesses the DOM to provide the needed data.
- * Returns the necessary props to render `pipelines-table-component` component.
- *
- * @return {Object}
- */
- data() {
- const pipelinesTableData = document.querySelector('#commit-pipeline-table-view').dataset;
- const store = new PipelineStore();
+ this.isLoading = true;
+ return pipelinesService.all()
+ .then(response => response.json())
+ .then((json) => {
+ // depending of the endpoint the response can either bring a `pipelines` key or not.
+ const pipelines = json.pipelines || json;
+ this.store.storePipelines(pipelines);
+ this.isLoading = false;
+ })
+ .catch(() => {
+ this.isLoading = false;
+ new Flash('An error occurred while fetching the pipelines, please reload the page again.', 'alert');
+ });
+ },
- return {
- endpoint: pipelinesTableData.endpoint,
- store,
- state: store.state,
- isLoading: false,
- };
- },
+ beforeUpdate() {
+ if (this.state.pipelines.length && this.$children) {
+ PipelineStore.startTimeAgoLoops.call(this, Vue);
+ }
+ },
- /**
- * When the component is about to be mounted, tell the service to fetch the data
- *
- * A request to fetch the pipelines will be made.
- * In case of a successfull response we will store the data in the provided
- * store, in case of a failed response we need to warn the user.
- *
- */
- beforeMount() {
- const pipelinesService = new gl.commits.pipelines.PipelinesService(this.endpoint);
-
- this.isLoading = true;
- return pipelinesService.all()
- .then(response => response.json())
- .then((json) => {
- // depending of the endpoint the response can either bring a `pipelines` key or not.
- const pipelines = json.pipelines || json;
- this.store.storePipelines(pipelines);
- this.isLoading = false;
- })
- .catch(() => {
- this.isLoading = false;
- new Flash('An error occurred while fetching the pipelines, please reload the page again.', 'alert');
- });
- },
-
- beforeUpdate() {
- if (this.state.pipelines.length && this.$children) {
- PipelineStore.startTimeAgoLoops.call(this, Vue);
- }
- },
-
- template: `
- <div class="pipelines">
- <div class="realtime-loading" v-if="isLoading">
- <i class="fa fa-spinner fa-spin"></i>
- </div>
+ template: `
+ <div class="pipelines">
+ <div class="realtime-loading" v-if="isLoading">
+ <i class="fa fa-spinner fa-spin"></i>
+ </div>
- <div class="blank-state blank-state-no-icon"
- v-if="!isLoading && state.pipelines.length === 0">
- <h2 class="blank-state-title js-blank-state-title">
- No pipelines to show
- </h2>
- </div>
+ <div class="blank-state blank-state-no-icon"
+ v-if="!isLoading && state.pipelines.length === 0">
+ <h2 class="blank-state-title js-blank-state-title">
+ No pipelines to show
+ </h2>
+ </div>
- <div class="table-holder pipelines"
- v-if="!isLoading && state.pipelines.length > 0">
- <pipelines-table-component :pipelines="state.pipelines"/>
- </div>
+ <div class="table-holder pipelines"
+ v-if="!isLoading && state.pipelines.length > 0">
+ <pipelines-table-component :pipelines="state.pipelines"/>
</div>
- `,
- });
-})();
+ </div>
+ `,
+});
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 190336dbd20..3f0ad6490b5 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -3,9 +3,12 @@
/* global Cookies */
/* global Flash */
-require('./breakpoints');
-window.Cookies = require('js-cookie');
-require('./flash');
+import Cookies from 'js-cookie';
+
+import './breakpoints';
+import './flash';
+
+const PipelinesTable = require('./commit/pipelines/pipelines_table');
/* eslint-disable max-len */
// MergeRequestTabs
@@ -97,6 +100,13 @@ require('./flash');
.off('click', this.clickTab);
}
+ destroy() {
+ this.unbindEvents();
+ if (this.commitPipelinesTable) {
+ this.commitPipelinesTable.$destroy();
+ }
+ }
+
showTab(e) {
e.preventDefault();
this.activateTab($(e.target).data('action'));
@@ -131,12 +141,8 @@ require('./flash');
offset: 0,
});
} else if (action === 'pipelines') {
- if (this.pipelinesLoaded) {
- return;
- }
- const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
- gl.commits.pipelines.PipelinesTableBundle.$mount(pipelineTableViewEl);
- this.pipelinesLoaded = true;
+ this.resetViewContainer();
+ this.loadPipelines();
} else {
this.expandView();
this.resetViewContainer();
@@ -225,6 +231,18 @@ require('./flash');
});
}
+ loadPipelines() {
+ if (this.pipelinesLoaded) {
+ return;
+ }
+ const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
+ // Could already be mounted from the `pipelines_bundle`
+ if (pipelineTableViewEl) {
+ this.commitPipelinesTable = new PipelinesTable().$mount(pipelineTableViewEl);
+ }
+ this.pipelinesLoaded = true;
+ }
+
loadDiff(source) {
if (this.diffsLoaded) {
return;
diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js b/app/assets/javascripts/vue_pipelines_index/pipelines.js
index 601ef41e917..4732092ab14 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipelines.js
+++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js
@@ -2,17 +2,18 @@
/* eslint-disable no-param-reassign */
window.Vue = require('vue');
+
require('../vue_shared/components/table_pagination');
require('./store');
-require('../vue_shared/components/pipelines_table');
const CommitPipelinesStoreWithTimeAgo = require('../commit/pipelines/pipelines_store');
+const PipelinesTableComponent = require('../vue_shared/components/pipelines_table');
((gl) => {
gl.VuePipelines = Vue.extend({
components: {
'gl-pagination': gl.VueGlPagination,
- 'pipelines-table-component': gl.pipelines.PipelinesTableComponent,
+ 'pipelines-table-component': PipelinesTableComponent,
},
data() {
diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table.js b/app/assets/javascripts/vue_shared/components/pipelines_table.js
index 0d8f85db965..c534bb85bf1 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table.js
+++ b/app/assets/javascripts/vue_shared/components/pipelines_table.js
@@ -8,45 +8,39 @@ require('./pipelines_table_row');
* Given an array of objects, renders a table.
*/
-(() => {
- window.gl = window.gl || {};
- gl.pipelines = gl.pipelines || {};
-
- gl.pipelines.PipelinesTableComponent = Vue.component('pipelines-table-component', {
-
- props: {
- pipelines: {
- type: Array,
- required: true,
- default: () => ([]),
- },
-
+module.exports = {
+ props: {
+ pipelines: {
+ type: Array,
+ required: true,
+ default: () => ([]),
},
- components: {
- 'pipelines-table-row-component': gl.pipelines.PipelinesTableRowComponent,
- },
+ },
+
+ components: {
+ 'pipelines-table-row-component': gl.pipelines.PipelinesTableRowComponent,
+ },
- template: `
- <table class="table ci-table">
- <thead>
- <tr>
- <th class="js-pipeline-status pipeline-status">Status</th>
- <th class="js-pipeline-info pipeline-info">Pipeline</th>
- <th class="js-pipeline-commit pipeline-commit">Commit</th>
- <th class="js-pipeline-stages pipeline-stages">Stages</th>
- <th class="js-pipeline-date pipeline-date"></th>
- <th class="js-pipeline-actions pipeline-actions"></th>
- </tr>
- </thead>
- <tbody>
- <template v-for="model in pipelines"
- v-bind:model="model">
- <tr is="pipelines-table-row-component"
- :pipeline="model"></tr>
- </template>
- </tbody>
- </table>
- `,
- });
-})();
+ template: `
+ <table class="table ci-table">
+ <thead>
+ <tr>
+ <th class="js-pipeline-status pipeline-status">Status</th>
+ <th class="js-pipeline-info pipeline-info">Pipeline</th>
+ <th class="js-pipeline-commit pipeline-commit">Commit</th>
+ <th class="js-pipeline-stages pipeline-stages">Stages</th>
+ <th class="js-pipeline-date pipeline-date"></th>
+ <th class="js-pipeline-actions pipeline-actions"></th>
+ </tr>
+ </thead>
+ <tbody>
+ <template v-for="model in pipelines"
+ v-bind:model="model">
+ <tr is="pipelines-table-row-component"
+ :pipeline="model"></tr>
+ </template>
+ </tbody>
+ </table>
+ `,
+};
diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake
index 40465ea3bf0..62a12174efa 100644
--- a/lib/tasks/karma.rake
+++ b/lib/tasks/karma.rake
@@ -1,9 +1,10 @@
unless Rails.env.production?
namespace :karma do
desc 'GitLab | Karma | Generate fixtures for JavaScript tests'
- RSpec::Core::RakeTask.new(:fixtures) do |t|
+ RSpec::Core::RakeTask.new(:fixtures, [:pattern]) do |t, args|
+ args.with_defaults(pattern: 'spec/javascripts/fixtures/*.rb')
ENV['NO_KNAPSACK'] = 'true'
- t.pattern = 'spec/javascripts/fixtures/*.rb'
+ t.pattern = args[:pattern]
t.rspec_opts = '--format documentation'
end
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js
index f09c57978a1..5b76e2303ab 100644
--- a/spec/javascripts/commit/pipelines/pipelines_spec.js
+++ b/spec/javascripts/commit/pipelines/pipelines_spec.js
@@ -1,15 +1,18 @@
/* global pipeline, Vue */
+const PipelinesTable = require('~/commit/pipelines/pipelines_table');
+
require('~/flash');
require('~/commit/pipelines/pipelines_store');
require('~/commit/pipelines/pipelines_service');
-require('~/commit/pipelines/pipelines_table');
require('~/vue_shared/vue_resource_interceptor');
const pipeline = require('./mock_data');
describe('Pipelines table in Commits and Merge requests', () => {
preloadFixtures('static/pipelines_table.html.raw');
+ let component;
+
beforeEach(() => {
loadFixtures('static/pipelines_table.html.raw');
});
@@ -24,19 +27,20 @@ describe('Pipelines table in Commits and Merge requests', () => {
beforeEach(() => {
Vue.http.interceptors.push(pipelinesEmptyResponse);
+
+ component = new PipelinesTable({
+ el: document.querySelector('#commit-pipeline-table-view'),
+ });
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, pipelinesEmptyResponse,
);
+ component.$destroy();
});
it('should render the empty state', (done) => {
- const component = new gl.commits.pipelines.PipelinesTableView({
- el: document.querySelector('#commit-pipeline-table-view'),
- });
-
setTimeout(() => {
expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain('No pipelines to show');
done();
@@ -53,19 +57,20 @@ describe('Pipelines table in Commits and Merge requests', () => {
beforeEach(() => {
Vue.http.interceptors.push(pipelinesResponse);
+
+ component = new PipelinesTable({
+ el: document.querySelector('#commit-pipeline-table-view'),
+ });
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, pipelinesResponse,
);
+ component.$destroy();
});
it('should render a table with the received pipelines', (done) => {
- const component = new gl.commits.pipelines.PipelinesTableView({
- el: document.querySelector('#commit-pipeline-table-view'),
- });
-
setTimeout(() => {
expect(component.$el.querySelectorAll('table > tbody > tr').length).toEqual(1);
done();
@@ -83,19 +88,20 @@ describe('Pipelines table in Commits and Merge requests', () => {
beforeEach(() => {
Vue.http.interceptors.push(pipelinesErrorResponse);
+
+ component = new PipelinesTable({
+ el: document.querySelector('#commit-pipeline-table-view'),
+ });
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, pipelinesErrorResponse,
);
+ component.$destroy();
});
it('should render empty state', (done) => {
- const component = new gl.commits.pipelines.PipelinesTableView({
- el: document.querySelector('#commit-pipeline-table-view'),
- });
-
setTimeout(() => {
expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain('No pipelines to show');
done();
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index ee893b76c84..fddeaaf504d 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -6,6 +6,15 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, namespace: namespace, path: 'merge-requests-project') }
+ let(:merge_request) { create(:merge_request, :with_diffs, source_project: project, target_project: project, description: '- [ ] Task List Item') }
+ let(:pipeline) do
+ create(
+ :ci_pipeline,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha
+ )
+ end
render_views
@@ -18,7 +27,8 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
end
it 'merge_requests/merge_request_with_task_list.html.raw' do |example|
- merge_request = create(:merge_request, :with_diffs, source_project: project, target_project: project, description: '- [ ] Task List Item')
+ create(:ci_build, :pending, pipeline: pipeline)
+
render_merge_request(example.description, merge_request)
end
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 7506e6ab49e..7b9632be84e 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -38,6 +38,10 @@ require('vendor/jquery.scrollTo');
}
});
+ afterEach(function () {
+ this.class.destroy();
+ });
+
describe('#activateTab', function () {
beforeEach(function () {
spyOn($, 'ajax').and.callFake(function () {});
@@ -200,6 +204,42 @@ require('vendor/jquery.scrollTo');
expect(this.subject('show')).toBe('/foo/bar/merge_requests/1');
});
});
+
+ describe('#tabShown', () => {
+ beforeEach(function () {
+ loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ });
+
+ describe('with "Side-by-side"/parallel diff view', () => {
+ beforeEach(function () {
+ this.class.diffViewType = () => 'parallel';
+ });
+
+ it('maintains `container-limited` for pipelines tab', function (done) {
+ const asyncClick = function (selector) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ document.querySelector(selector).click();
+ resolve();
+ });
+ });
+ };
+
+ asyncClick('.merge-request-tabs .pipelines-tab a')
+ .then(() => asyncClick('.merge-request-tabs .diffs-tab a'))
+ .then(() => asyncClick('.merge-request-tabs .pipelines-tab a'))
+ .then(() => {
+ const hasContainerLimitedClass = document.querySelector('.content-wrapper .container-fluid').classList.contains('container-limited');
+ expect(hasContainerLimitedClass).toBe(true);
+ })
+ .then(done)
+ .catch((err) => {
+ done.fail(`Something went wrong clicking MR tabs: ${err.message}\n${err.stack}`);
+ });
+ });
+ });
+ });
+
describe('#loadDiff', function () {
it('requires an absolute pathname', function () {
spyOn($, 'ajax').and.callFake(function (options) {
diff --git a/spec/javascripts/vue_shared/components/pipelines_table_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_spec.js
index 54d81e2ea7d..905ac0ec723 100644
--- a/spec/javascripts/vue_shared/components/pipelines_table_spec.js
+++ b/spec/javascripts/vue_shared/components/pipelines_table_spec.js
@@ -1,6 +1,9 @@
-require('~/vue_shared/components/pipelines_table');
require('~/lib/utils/datetime_utility');
+const Vue = require('vue');
const pipeline = require('../../commit/pipelines/mock_data');
+const PipelinesTable = require('~/vue_shared/components/pipelines_table');
+
+const PipelinesTableComponent = Vue.extend(PipelinesTable);
describe('Pipelines Table', () => {
preloadFixtures('static/environments/element.html.raw');
@@ -12,7 +15,7 @@ describe('Pipelines Table', () => {
describe('table', () => {
let component;
beforeEach(() => {
- component = new gl.pipelines.PipelinesTableComponent({
+ component = new PipelinesTableComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
pipelines: [],
@@ -21,6 +24,10 @@ describe('Pipelines Table', () => {
});
});
+ afterEach(() => {
+ component.$destroy();
+ });
+
it('should render a table', () => {
expect(component.$el).toEqual('TABLE');
});
@@ -37,7 +44,7 @@ describe('Pipelines Table', () => {
describe('without data', () => {
it('should render an empty table', () => {
- const component = new gl.pipelines.PipelinesTableComponent({
+ const component = new PipelinesTableComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
pipelines: [],
@@ -50,7 +57,7 @@ describe('Pipelines Table', () => {
describe('with data', () => {
it('should render rows', () => {
- const component = new gl.pipelines.PipelinesTableComponent({
+ const component = new PipelinesTableComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
pipelines: [pipeline],