Commit 0c1cf679 authored by Filipa Lacerda's avatar Filipa Lacerda

[ci skip] Adds tests for issue app

parent 23334ac0
...@@ -175,7 +175,6 @@ ...@@ -175,7 +175,6 @@
this.noteType = type; this.noteType = type;
}, },
editCurrentUserLastNote() { editCurrentUserLastNote() {
console.log('editCurrentUserLastNote')
if (this.note === '') { if (this.note === '') {
const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id); const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id);
...@@ -254,7 +253,7 @@ ...@@ -254,7 +253,7 @@
:disabled="isSubmitButtonDisabled" :disabled="isSubmitButtonDisabled"
name="button" name="button"
type="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" data-toggle="dropdown"
aria-label="Open comment type dropdown"> aria-label="Open comment type dropdown">
<i <i
...@@ -305,7 +304,7 @@ ...@@ -305,7 +304,7 @@
type="submit" type="submit"
v-if="canUpdateIssue" v-if="canUpdateIssue"
:class="actionButtonClassNames" :class="actionButtonClassNames"
class="btn btn-nr btn-comment btn-comment-and-close"> class="btn btn-comment btn-comment-and-close">
{{issueActionButtonTitle}} {{issueActionButtonTitle}}
</button> </button>
<button <button
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
return this.getNotesDataByProp('markdownDocs'); return this.getNotesDataByProp('markdownDocs');
}, },
quickActionsDocsUrl() { quickActionsDocsUrl() {
return this.getNotesDataByProp('quickActionsDocs'); return !this.isEditing ? this.getNotesDataByProp('quickActionsDocs') : undefined;
}, },
currentUserId() { currentUserId() {
return this.getUserDataByProp('id'); return this.getUserDataByProp('id');
...@@ -134,15 +134,15 @@ ...@@ -134,15 +134,15 @@
ref="textarea" ref="textarea"
slot="textarea" slot="textarea"
placeholder="Write a comment or drag your files here..." placeholder="Write a comment or drag your files here..."
@keydown.meta.enter="handleUpdate" @keydown.meta.enter="handleUpdate()"
@keydown.up="editMyLastNote" @keydown.up="editMyLastNote()"
@keydown.esc="cancelHandler(true)"> @keydown.esc="cancelHandler(true)">
</textarea> </textarea>
</markdown-field> </markdown-field>
<div class="note-form-actions clearfix"> <div class="note-form-actions clearfix">
<button <button
type="submit" type="submit"
@click="handleUpdate" @click="handleUpdate()"
:disabled="isDisabled" :disabled="isDisabled"
class="js-vue-issue-save btn btn-save"> class="js-vue-issue-save btn btn-save">
{{saveButtonTitle}} {{saveButtonTitle}}
......
...@@ -97,11 +97,11 @@ ...@@ -97,11 +97,11 @@
}, },
checkLocationHash() { checkLocationHash() {
const hash = gl.utils.getLocationHash(); const hash = gl.utils.getLocationHash();
const $el = $(`#${hash}`); const element = document.getElementById(hash);
if (hash && $el) { if (hash && element) {
this.setTargetNoteHash(hash); this.setTargetNoteHash(hash);
this.scrollToNoteIfNeeded($el); this.scrollToNoteIfNeeded($(element));
} }
}, },
}, },
......
import Vue from 'vue'; import Vue from 'vue';
import issueNotesApp from '~/notes/components/issue_notes_app.vue'; import issueNotesApp from '~/notes/components/issue_notes_app.vue';
import service from '~/notes/services/issue_notes_service'; import service from '~/notes/services/issue_notes_service';
import { keyboardDownEvent } from '../../issue_show/helpers';
import * as mockData from '../mock_data'; import * as mockData from '../mock_data';
describe('issue_note_app', () => { describe('issue_note_app', () => {
let mountComponent; 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(() => { beforeEach(() => {
const IssueNotesApp = Vue.extend(issueNotesApp); const IssueNotesApp = Vue.extend(issueNotesApp);
mountComponent = props => new IssueNotesApp({ mountComponent = (data) => {
propsData: props, const props = data || {
}).$mount(); issueData: mockData.issueDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
};
return new IssueNotesApp({
propsData: props,
}).$mount();
};
}); });
describe('set data', () => { afterEach(() => {
let vm; vm.$destroy();
});
describe('set data', () => {
const responseInterceptor = (request, next) => { const responseInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify([]), { next(request.respondWith(JSON.stringify([]), {
status: 200, status: 200,
...@@ -26,11 +48,7 @@ describe('issue_note_app', () => { ...@@ -26,11 +48,7 @@ describe('issue_note_app', () => {
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(responseInterceptor); Vue.http.interceptors.push(responseInterceptor);
vm = mountComponent({ vm = mountComponent();
issueData: mockData.issueDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
});
}); });
afterEach(() => { afterEach(() => {
...@@ -55,29 +73,17 @@ describe('issue_note_app', () => { ...@@ -55,29 +73,17 @@ describe('issue_note_app', () => {
}); });
describe('render', () => { describe('render', () => {
let vm;
const responseInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify(mockData.discussionResponse), {
status: 200,
}));
};
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(responseInterceptor); Vue.http.interceptors.push(individualNoteInterceptor);
vm = mountComponent({ vm = mountComponent();
issueData: mockData.issueDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
});
}); });
afterEach(() => { afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor); Vue.http.interceptors = _.without(Vue.http.interceptors, individualNoteInterceptor);
}); });
it('should render list of notes', (done) => { it('should render list of notes', (done) => {
const note = mockData.discussionResponse[0].notes[0]; const note = mockData.individualNoteServerResponse[0].notes[0];
setTimeout(() => { setTimeout(() => {
expect( expect(
...@@ -95,16 +101,17 @@ describe('issue_note_app', () => { ...@@ -95,16 +101,17 @@ describe('issue_note_app', () => {
vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'), vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'),
).toEqual('Write a comment or drag your files here...'); ).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', () => { describe('while fetching data', () => {
let vm;
beforeEach(() => { beforeEach(() => {
vm = mountComponent({ vm = mountComponent();
issueData: mockData.issueDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
});
}); });
it('should render loading icon', () => { it('should render loading icon', () => {
...@@ -121,104 +128,137 @@ describe('issue_note_app', () => { ...@@ -121,104 +128,137 @@ describe('issue_note_app', () => {
describe('update note', () => { describe('update note', () => {
describe('individual note', () => { describe('individual note', () => {
let vm;
const responseInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify(mockData.discussionResponse), {
status: 200,
}));
};
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(responseInterceptor); Vue.http.interceptors.push(individualNoteInterceptor);
spyOn(service, 'updateNote').and.callFake(() => Promise.resolve());
vm = mountComponent({ vm = mountComponent();
issueData: mockData.issueDataMock,
notesData: mockData.notesDataMock,
userData: mockData.userDataMock,
});
}); });
afterEach(() => { 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(() => { setTimeout(() => {
vm.$el.querySelector('.js-note-edit').click(); vm.$el.querySelector('.js-note-edit').click();
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$el.querySelector('.js-vue-issue-note-form')).toBeDefined(); expect(vm.$el.querySelector('.js-vue-issue-note-form')).toBeDefined();
done();
}); });
}, 0); }, 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', () => { expect(service.updateNote).toHaveBeenCalled();
it('renders edit form', () => { done();
});
}, 0);
}); });
it('updates the note and resets the edit form', () => {});
}); });
});
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('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 visually the target note', () => { 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('create new note', () => { describe('new note form', () => {
it('should show placeholder note while new comment is being posted', () => {}); beforeEach(() => {
it('should remove placeholder note when new comment is done posting', () => {}); vm = mountComponent();
it('should show actual note element when new comment is done posting', () => {});
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 render markdown docs url', () => {
const { markdownDocs } = mockData.notesDataMock;
expect(vm.$el.querySelector(`a[href="${markdownDocs}"]`).textContent.trim()).toEqual('Markdown');
}); });
it('should return generic quick action description when available quick actions list is not populated', () => { it('should render quick action docs url', () => {
const { quickActionsDocs } = mockData.notesDataMock;
expect(vm.$el.querySelector(`a[href="${quickActionsDocs}"]`).textContent.trim()).toEqual('quick actions');
}); });
}); });
describe('new note form', () => { describe('edit form', () => {
it('should render markdown docs url', () => { beforeEach(() => {
Vue.http.interceptors.push(individualNoteInterceptor);
vm = mountComponent();
}); });
it('should render quick action docs url', () => { afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, individualNoteInterceptor);
}); });
it('should preview markdown', () => { 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);
}); });
describe('discard draft', () => { it('should not render quick actions docs url', (done) => {
it('should reset form when reset button is clicked', () => { 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);
}); });
}); });
describe('edit form', () => { // TODO: FILIPA
it('should render markdown docs url', () => {}); describe('create new note', () => {
it('should not render quick actions docs url', () => {}); it('should show placeholder note while new comment is being posted', () => {});
it('should remove placeholder note when new comment is done posting', () => {});
it('should show actual note element when new comment is done posting', () => {});
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', () => {});
}); });
}); });
/* eslint disable */ /* eslint-disable */
export const notesDataMock = { export const notesDataMock = {
discussionsPath: '/gitlab-org/gitlab-ce/issues/26/discussions.json', discussionsPath: '/gitlab-org/gitlab-ce/issues/26/discussions.json',
lastFetchedAt: '1501862675', lastFetchedAt: '1501862675',
...@@ -222,96 +221,138 @@ export const discussionMock = { ...@@ -222,96 +221,138 @@ export const discussionMock = {
individual_note: false, individual_note: false,
}; };
export const discussionResponse = [{ export const individualNoteServerResponse = [{
"id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", "id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd",
"reply_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", "reply_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd",
"expanded": true, "expanded": true,
"notes": [{ "notes": [{
"id": 1390, "id": 1390,
"attachment": { "attachment": {
"url": null, "url": null,
"filename": null, "filename": null,
"image": false "image": false
}, },
"author": { "author": {
"id": 1, "id": 1,
"name": "Root", "name": "Root",
"username": "root", "username": "root",
"state": "active", "state": "active",
"avatar_url": null, "avatar_url": null,
"path": "/root" "path": "/root"
}, },
"created_at": "2017-08-01T17:09:33.762Z", "created_at": "2017-08-01T17:09:33.762Z",
"updated_at": "2017-08-01T17:09:33.762Z", "updated_at": "2017-08-01T17:09:33.762Z",
"system": false, "system": false,
"noteable_id": 98, "noteable_id": 98,
"noteable_type": "Issue", "noteable_type": "Issue",
"type": null, "type": null,
"human_access": "Owner", "human_access": "Owner",
"note": "sdfdsaf", "note": "sdfdsaf",
"note_html": "\u003cp dir=\"auto\"\u003esdfdsaf\u003c/p\u003e", "note_html": "\u003cp dir=\"auto\"\u003esdfdsaf\u003c/p\u003e",
"current_user": { "current_user": {
"can_edit": true "can_edit": true
}, },
"discussion_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", "discussion_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd",
"emoji_awardable": true, "emoji_awardable": true,
"award_emoji": [{ "award_emoji": [{
"name": "baseball", "name": "baseball",
"user": { "user": {
"id": 1, "id": 1,
"name": "Root", "name": "Root",
"username": "root" "username": "root"
} }
}, { }, {
"name": "art", "name": "art",
"user": { "user": {
"id": 1, "id": 1,
"name": "Root", "name": "Root",
"username": "root" "username": "root"
} }
}], }],
"toggle_award_path": "/gitlab-org/gitlab-ce/notes/1390/toggle_award_emoji", "toggle_award_path": "/gitlab-org/gitlab-ce/notes/1390/toggle_award_emoji",
"report_abuse_path": "/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F26%23note_1390\u0026user_id=1", "report_abuse_path": "/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F26%23note_1390\u0026user_id=1",
"path": "/gitlab-org/gitlab-ce/notes/1390" "path": "/gitlab-org/gitlab-ce/notes/1390"
}], }],
"individual_note": true "individual_note": true
}, { }, {
"id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", "id": "70d5c92a4039a36c70100c6691c18c27e4b0a790",
"reply_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", "reply_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790",
"expanded": true, "expanded": true,
"notes": [{ "notes": [{
"id": 1391, "id": 1391,
"attachment": { "attachment": {
"url": null, "url": null,
"filename": null, "filename": null,
"image": false "image": false
}, },
"author": { "author": {
"id": 1, "id": 1,
"name": "Root", "name": "Root",
"username": "root", "username": "root",
"state": "active", "state": "active",
"avatar_url": null, "avatar_url": null,
"path": "/root" "path": "/root"
}, },
"created_at": "2017-08-02T10:51:38.685Z", "created_at": "2017-08-02T10:51:38.685Z",
"updated_at": "2017-08-02T10:51:38.685Z", "updated_at": "2017-08-02T10:51:38.685Z",
"system": false, "system": false,
"noteable_id": 98, "noteable_id": 98,
"noteable_type": "Issue", "noteable_type": "Issue",
"type": null, "type": null,
"human_access": "Owner", "human_access": "Owner",
"note": "New note!", "note": "New note!",
"note_html": "\u003cp dir=\"auto\"\u003eNew note!\u003c/p\u003e", "note_html": "\u003cp dir=\"auto\"\u003eNew note!\u003c/p\u003e",
"current_user": { "current_user": {
"can_edit": true "can_edit": true
}, },
"discussion_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", "discussion_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790",
"emoji_awardable": true, "emoji_awardable": true,
"award_emoji": [], "award_emoji": [],
"toggle_award_path": "/gitlab-org/gitlab-ce/notes/1391/toggle_award_emoji", "toggle_award_path": "/gitlab-org/gitlab-ce/notes/1391/toggle_award_emoji",
"report_abuse_path": "/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F26%23note_1391\u0026user_id=1", "report_abuse_path": "/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F26%23note_1391\u0026user_id=1",
"path": "/gitlab-org/gitlab-ce/notes/1391" "path": "/gitlab-org/gitlab-ce/notes/1391"
}], }],
"individual_note": true "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
}];
\ No newline at end of file
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