[ci skip] Adds tests for issue app
This commit is contained in:
parent
23334ac0a1
commit
0c1cf67975
5 changed files with 282 additions and 202 deletions
|
@ -175,7 +175,6 @@
|
|||
this.noteType = type;
|
||||
},
|
||||
editCurrentUserLastNote() {
|
||||
console.log('editCurrentUserLastNote')
|
||||
if (this.note === '') {
|
||||
const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id);
|
||||
|
||||
|
@ -254,7 +253,7 @@
|
|||
:disabled="isSubmitButtonDisabled"
|
||||
name="button"
|
||||
type="button"
|
||||
class="btn btn-nr comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
|
||||
class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-label="Open comment type dropdown">
|
||||
<i
|
||||
|
@ -305,7 +304,7 @@
|
|||
type="submit"
|
||||
v-if="canUpdateIssue"
|
||||
:class="actionButtonClassNames"
|
||||
class="btn btn-nr btn-comment btn-comment-and-close">
|
||||
class="btn btn-comment btn-comment-and-close">
|
||||
{{issueActionButtonTitle}}
|
||||
</button>
|
||||
<button
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
return this.getNotesDataByProp('markdownDocs');
|
||||
},
|
||||
quickActionsDocsUrl() {
|
||||
return this.getNotesDataByProp('quickActionsDocs');
|
||||
return !this.isEditing ? this.getNotesDataByProp('quickActionsDocs') : undefined;
|
||||
},
|
||||
currentUserId() {
|
||||
return this.getUserDataByProp('id');
|
||||
|
@ -134,15 +134,15 @@
|
|||
ref="textarea"
|
||||
slot="textarea"
|
||||
placeholder="Write a comment or drag your files here..."
|
||||
@keydown.meta.enter="handleUpdate"
|
||||
@keydown.up="editMyLastNote"
|
||||
@keydown.meta.enter="handleUpdate()"
|
||||
@keydown.up="editMyLastNote()"
|
||||
@keydown.esc="cancelHandler(true)">
|
||||
</textarea>
|
||||
</markdown-field>
|
||||
<div class="note-form-actions clearfix">
|
||||
<button
|
||||
type="submit"
|
||||
@click="handleUpdate"
|
||||
@click="handleUpdate()"
|
||||
:disabled="isDisabled"
|
||||
class="js-vue-issue-save btn btn-save">
|
||||
{{saveButtonTitle}}
|
||||
|
|
|
@ -97,11 +97,11 @@
|
|||
},
|
||||
checkLocationHash() {
|
||||
const hash = gl.utils.getLocationHash();
|
||||
const $el = $(`#${hash}`);
|
||||
const element = document.getElementById(hash);
|
||||
|
||||
if (hash && $el) {
|
||||
if (hash && element) {
|
||||
this.setTargetNoteHash(hash);
|
||||
this.scrollToNoteIfNeeded($el);
|
||||
this.scrollToNoteIfNeeded($(element));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,23 +1,45 @@
|
|||
import Vue from 'vue';
|
||||
import issueNotesApp from '~/notes/components/issue_notes_app.vue';
|
||||
import service from '~/notes/services/issue_notes_service';
|
||||
import { keyboardDownEvent } from '../../issue_show/helpers';
|
||||
import * as mockData from '../mock_data';
|
||||
|
||||
describe('issue_note_app', () => {
|
||||
let mountComponent;
|
||||
let vm;
|
||||
|
||||
const individualNoteInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify(mockData.individualNoteServerResponse), {
|
||||
status: 200,
|
||||
}));
|
||||
};
|
||||
|
||||
const discussionNoteInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify(mockData.discussionNoteServerResponse), {
|
||||
status: 200,
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const IssueNotesApp = Vue.extend(issueNotesApp);
|
||||
|
||||
mountComponent = props => new IssueNotesApp({
|
||||
mountComponent = (data) => {
|
||||
const props = data || {
|
||||
issueData: mockData.issueDataMock,
|
||||
notesData: mockData.notesDataMock,
|
||||
userData: mockData.userDataMock,
|
||||
};
|
||||
|
||||
return new IssueNotesApp({
|
||||
propsData: props,
|
||||
}).$mount();
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('set data', () => {
|
||||
let vm;
|
||||
|
||||
const responseInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify([]), {
|
||||
status: 200,
|
||||
|
@ -26,11 +48,7 @@ describe('issue_note_app', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(responseInterceptor);
|
||||
vm = mountComponent({
|
||||
issueData: mockData.issueDataMock,
|
||||
notesData: mockData.notesDataMock,
|
||||
userData: mockData.userDataMock,
|
||||
});
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -55,29 +73,17 @@ describe('issue_note_app', () => {
|
|||
});
|
||||
|
||||
describe('render', () => {
|
||||
let vm;
|
||||
|
||||
const responseInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify(mockData.discussionResponse), {
|
||||
status: 200,
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(responseInterceptor);
|
||||
vm = mountComponent({
|
||||
issueData: mockData.issueDataMock,
|
||||
notesData: mockData.notesDataMock,
|
||||
userData: mockData.userDataMock,
|
||||
});
|
||||
Vue.http.interceptors.push(individualNoteInterceptor);
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor);
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, individualNoteInterceptor);
|
||||
});
|
||||
|
||||
it('should render list of notes', (done) => {
|
||||
const note = mockData.discussionResponse[0].notes[0];
|
||||
const note = mockData.individualNoteServerResponse[0].notes[0];
|
||||
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
|
@ -95,16 +101,17 @@ describe('issue_note_app', () => {
|
|||
vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
|
||||
).toEqual('Write a comment or drag your files here...');
|
||||
});
|
||||
|
||||
it('should render form comment button as disabled', () => {
|
||||
expect(
|
||||
vm.$el.querySelector('.js-note-new-discussion').getAttribute('disabled'),
|
||||
).toEqual('disabled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('while fetching data', () => {
|
||||
let vm;
|
||||
beforeEach(() => {
|
||||
vm = mountComponent({
|
||||
issueData: mockData.issueDataMock,
|
||||
notesData: mockData.notesDataMock,
|
||||
userData: mockData.userDataMock,
|
||||
});
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
it('should render loading icon', () => {
|
||||
|
@ -121,63 +128,132 @@ describe('issue_note_app', () => {
|
|||
|
||||
describe('update note', () => {
|
||||
describe('individual note', () => {
|
||||
let vm;
|
||||
|
||||
const responseInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify(mockData.discussionResponse), {
|
||||
status: 200,
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(responseInterceptor);
|
||||
|
||||
vm = mountComponent({
|
||||
issueData: mockData.issueDataMock,
|
||||
notesData: mockData.notesDataMock,
|
||||
userData: mockData.userDataMock,
|
||||
});
|
||||
|
||||
Vue.http.interceptors.push(individualNoteInterceptor);
|
||||
spyOn(service, 'updateNote').and.callFake(() => Promise.resolve());
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor);
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, individualNoteInterceptor);
|
||||
});
|
||||
|
||||
it('renders edit form', () => {
|
||||
it('renders edit form', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-vue-issue-note-form')).toBeDefined();
|
||||
done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('updates the note and resets the edit form', () => {});
|
||||
});
|
||||
it('calls the service to update the note', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
Vue.nextTick(() => {
|
||||
vm.$el.querySelector('.js-vue-issue-note-form').value = 'this is a note';
|
||||
vm.$el.querySelector('.js-vue-issue-save').click();
|
||||
|
||||
describe('dicussion note note', () => {
|
||||
it('renders edit form', () => {
|
||||
expect(service.updateNote).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
|
||||
it('updates the note and resets the edit form', () => {});
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('set target hash', () => {
|
||||
it('updates the URL when the note date is clicked', () => {
|
||||
|
||||
describe('dicussion note', () => {
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(discussionNoteInterceptor);
|
||||
spyOn(service, 'updateNote').and.callFake(() => Promise.resolve());
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
it('stores the correct hash', () => {
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, discussionNoteInterceptor);
|
||||
});
|
||||
|
||||
it('updates visually the target note', () => {
|
||||
it('renders edit form', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-vue-issue-note-form')).toBeDefined();
|
||||
done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('updates the note and resets the edit form', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
Vue.nextTick(() => {
|
||||
vm.$el.querySelector('.js-vue-issue-note-form').value = 'this is a note';
|
||||
vm.$el.querySelector('.js-vue-issue-save').click();
|
||||
|
||||
expect(service.updateNote).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('new note form', () => {
|
||||
beforeEach(() => {
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
it('should render markdown docs url', () => {
|
||||
const { markdownDocs } = mockData.notesDataMock;
|
||||
expect(vm.$el.querySelector(`a[href="${markdownDocs}"]`).textContent.trim()).toEqual('Markdown');
|
||||
});
|
||||
|
||||
it('should render quick action docs url', () => {
|
||||
const { quickActionsDocs } = mockData.notesDataMock;
|
||||
expect(vm.$el.querySelector(`a[href="${quickActionsDocs}"]`).textContent.trim()).toEqual('quick actions');
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit form', () => {
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(individualNoteInterceptor);
|
||||
vm = mountComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(Vue.http.interceptors, individualNoteInterceptor);
|
||||
});
|
||||
|
||||
it('should render markdown docs url', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
const { markdownDocs } = mockData.notesDataMock;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(
|
||||
vm.$el.querySelector(`.edit-note a[href="${markdownDocs}"]`).textContent.trim(),
|
||||
).toEqual('Markdown is supported');
|
||||
done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should not render quick actions docs url', (done) => {
|
||||
setTimeout(() => {
|
||||
vm.$el.querySelector('.js-note-edit').click();
|
||||
const { quickActionsDocs } = mockData.notesDataMock;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(
|
||||
vm.$el.querySelector(`.edit-note a[href="${quickActionsDocs}"]`),
|
||||
).toEqual(null);
|
||||
done();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: FILIPA
|
||||
describe('create new note', () => {
|
||||
it('should show placeholder note while new comment is being posted', () => {});
|
||||
it('should remove placeholder note when new comment is done posting', () => {});
|
||||
|
@ -185,40 +261,4 @@ describe('issue_note_app', () => {
|
|||
it('should show flash error message when new comment failed to be posted', () => {});
|
||||
it('should show flash error message when comment failed to be updated', () => {});
|
||||
});
|
||||
|
||||
describe('quick actions', () => {
|
||||
it('should return executing quick action description when note has single quick action', () => {
|
||||
});
|
||||
|
||||
it('should return generic multiple quick action description when note has multiple quick actions', () => {
|
||||
});
|
||||
|
||||
it('should return generic quick action description when available quick actions list is not populated', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('new note form', () => {
|
||||
it('should render markdown docs url', () => {
|
||||
|
||||
});
|
||||
|
||||
it('should render quick action docs url', () => {
|
||||
|
||||
});
|
||||
|
||||
it('should preview markdown', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('discard draft', () => {
|
||||
it('should reset form when reset button is clicked', () => {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit form', () => {
|
||||
it('should render markdown docs url', () => {});
|
||||
it('should not render quick actions docs url', () => {});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint disable */
|
||||
|
||||
/* eslint-disable */
|
||||
export const notesDataMock = {
|
||||
discussionsPath: '/gitlab-org/gitlab-ce/issues/26/discussions.json',
|
||||
lastFetchedAt: '1501862675',
|
||||
|
@ -222,7 +221,7 @@ export const discussionMock = {
|
|||
individual_note: false,
|
||||
};
|
||||
|
||||
export const discussionResponse = [{
|
||||
export const individualNoteServerResponse = [{
|
||||
"id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd",
|
||||
"reply_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd",
|
||||
"expanded": true,
|
||||
|
@ -315,3 +314,45 @@ export const discussionResponse = [{
|
|||
}],
|
||||
"individual_note": true
|
||||
}];
|
||||
|
||||
export const discussionNoteServerResponse = [{
|
||||
"id": "a3ed36e29b1957efb3b68c53e2d7a2b24b1df052",
|
||||
"reply_id": "a3ed36e29b1957efb3b68c53e2d7a2b24b1df052",
|
||||
"expanded": true,
|
||||
"notes": [{
|
||||
"id": 1471,
|
||||
"attachment": {
|
||||
"url": null,
|
||||
"filename": null,
|
||||
"image": false
|
||||
},
|
||||
"author": {
|
||||
"id": 1,
|
||||
"name": "Root",
|
||||
"username": "root",
|
||||
"state": "active",
|
||||
"avatar_url": null,
|
||||
"path": "/root"
|
||||
},
|
||||
"created_at": "2017-08-08T16:53:00.666Z",
|
||||
"updated_at": "2017-08-08T16:53:00.666Z",
|
||||
"system": false,
|
||||
"noteable_id": 124,
|
||||
"noteable_type": "Issue",
|
||||
"noteable_iid": 29,
|
||||
"type": "DiscussionNote",
|
||||
"human_access": "Owner",
|
||||
"note": "Adding a comment",
|
||||
"note_html": "\u003cp dir=\"auto\"\u003eAdding a comment\u003c/p\u003e",
|
||||
"current_user": {
|
||||
"can_edit": true
|
||||
},
|
||||
"discussion_id": "a3ed36e29b1957efb3b68c53e2d7a2b24b1df052",
|
||||
"emoji_awardable": true,
|
||||
"award_emoji": [],
|
||||
"toggle_award_path": "/gitlab-org/gitlab-ce/notes/1471/toggle_award_emoji",
|
||||
"report_abuse_path": "/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F29%23note_1471\u0026user_id=1",
|
||||
"path": "/gitlab-org/gitlab-ce/notes/1471"
|
||||
}],
|
||||
"individual_note": false
|
||||
}];
|
Loading…
Reference in a new issue