Commit 59f93de0 authored by Fatih Acet's avatar Fatih Acet 🤙

Merge branch 'backport-epic-tasklist' into 'master'

Backport epic tasklist

See merge request gitlab-org/gitlab-ce!15556
parents 18137b85 52eac5bb
......@@ -16,6 +16,10 @@ export default {
required: true,
type: String,
},
updateEndpoint: {
required: true,
type: String,
},
canUpdate: {
required: true,
type: Boolean,
......@@ -262,6 +266,8 @@ export default {
:description-text="state.descriptionText"
:updated-at="state.updatedAt"
:task-status="state.taskStatus"
:issuable-type="issuableType"
:update-url="updateEndpoint"
/>
<edited-component
v-if="hasUpdated"
......
......@@ -22,6 +22,16 @@
required: false,
default: '',
},
issuableType: {
type: String,
required: false,
default: 'issue',
},
updateUrl: {
type: String,
required: false,
default: null,
},
},
data() {
return {
......@@ -48,7 +58,7 @@
if (this.canUpdate) {
// eslint-disable-next-line no-new
new TaskList({
dataType: 'issue',
dataType: this.issuableType,
fieldName: 'description',
selector: '.detail-page-description',
});
......@@ -95,7 +105,9 @@
<textarea
class="hidden js-task-list-field"
v-if="descriptionText"
v-model="descriptionText">
v-model="descriptionText"
:data-update-url="updateUrl"
>
</textarea>
</div>
</template>
......@@ -212,6 +212,7 @@ module IssuablesHelper
def issuable_initial_data(issuable)
data = {
endpoint: issuable_path(issuable),
updateEndpoint: "#{issuable_path(issuable)}.json",
canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
issuableRef: issuable.to_reference,
......
......@@ -174,6 +174,7 @@ describe IssuablesHelper do
expected_data = {
'endpoint' => "/#{@project.full_path}/issues/#{issue.iid}",
'updateEndpoint' => "/#{@project.full_path}/issues/#{issue.iid}.json",
'canUpdate' => true,
'canDestroy' => true,
'issuableRef' => "##{issue.iid}",
......
......@@ -35,11 +35,12 @@ describe('Issuable output', () => {
canUpdate: true,
canDestroy: true,
endpoint: '/gitlab-org/gitlab-shell/issues/9/realtime_changes',
updateEndpoint: gl.TEST_HOST,
issuableRef: '#1',
initialTitleHtml: '',
initialTitleText: '',
initialDescriptionHtml: '',
initialDescriptionText: '',
initialDescriptionHtml: 'test',
initialDescriptionText: 'test',
markdownPreviewPath: '/',
markdownDocsPath: '/',
projectNamespace: '/',
......
import Vue from 'vue';
import descriptionComponent from '~/issue_show/components/description.vue';
import * as taskList from '~/task_list';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Description component', () => {
let vm;
let DescriptionComponent;
const props = {
canUpdate: true,
descriptionHtml: 'test',
descriptionText: 'test',
updatedAt: new Date().toString(),
taskStatus: '',
updateUrl: gl.TEST_HOST,
};
beforeEach(() => {
const Component = Vue.extend(descriptionComponent);
DescriptionComponent = Vue.extend(descriptionComponent);
if (!document.querySelector('.issuable-meta')) {
const metaData = document.createElement('div');
......@@ -15,15 +26,11 @@ describe('Description component', () => {
document.body.appendChild(metaData);
}
vm = new Component({
propsData: {
canUpdate: true,
descriptionHtml: 'test',
descriptionText: 'test',
updatedAt: new Date().toString(),
taskStatus: '',
},
}).$mount();
vm = mountComponent(DescriptionComponent, props);
});
afterEach(() => {
vm.$destroy();
});
it('animates description changes', (done) => {
......@@ -44,34 +51,46 @@ describe('Description component', () => {
});
});
// TODO: gl.TaskList no longer exists. rewrite these tests once we have a way to rewire ES modules
// it('re-inits the TaskList when description changed', (done) => {
// spyOn(gl, 'TaskList');
// vm.descriptionHtml = 'changed';
//
// setTimeout(() => {
// expect(
// gl.TaskList,
// ).toHaveBeenCalled();
//
// done();
// });
// });
// it('does not re-init the TaskList when canUpdate is false', (done) => {
// spyOn(gl, 'TaskList');
// vm.canUpdate = false;
// vm.descriptionHtml = 'changed';
//
// setTimeout(() => {
// expect(
// gl.TaskList,
// ).not.toHaveBeenCalled();
//
// done();
// });
// });
describe('TaskList', () => {
beforeEach(() => {
vm = mountComponent(DescriptionComponent, Object.assign({}, props, {
issuableType: 'issuableType',
}));
spyOn(taskList, 'default');
});
it('re-inits the TaskList when description changed', (done) => {
vm.descriptionHtml = 'changed';
setTimeout(() => {
expect(taskList.default).toHaveBeenCalled();
done();
});
});
it('does not re-init the TaskList when canUpdate is false', (done) => {
vm.canUpdate = false;
vm.descriptionHtml = 'changed';
setTimeout(() => {
expect(taskList.default).not.toHaveBeenCalled();
done();
});
});
it('calls with issuableType dataType', (done) => {
vm.descriptionHtml = 'changed';
setTimeout(() => {
expect(taskList.default).toHaveBeenCalledWith({
dataType: 'issuableType',
fieldName: 'description',
selector: '.detail-page-description',
});
done();
});
});
});
describe('taskStatus', () => {
it('adds full taskStatus', (done) => {
......@@ -126,4 +145,8 @@ describe('Description component', () => {
});
});
});
it('sets data-update-url', () => {
expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(gl.TEST_HOST);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment