From 25fcee16f5e1640b88bfc893cabdddbed5bc2551 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 7 Aug 2017 18:23:56 +0100 Subject: [PATCH] Init adding tests --- app/assets/javascripts/autosave.js | 5 - .../notes/components/issue_notes_app.vue | 12 +- .../javascripts/notes/stores/actions.js | 2 +- .../notes/components/issue_note_app_spec.js | 201 ++++++++++++++++-- spec/javascripts/notes/mock_data.js | 100 ++++++++- 5 files changed, 287 insertions(+), 33 deletions(-) diff --git a/app/assets/javascripts/autosave.js b/app/assets/javascripts/autosave.js index 6000c56665b..cfab6c40b34 100644 --- a/app/assets/javascripts/autosave.js +++ b/app/assets/javascripts/autosave.js @@ -2,11 +2,6 @@ import AccessorUtilities from './lib/utils/accessor'; window.Autosave = (function() { - /** - * - * @param {*} field the textarea - * @param {Array} key Array with: ['Note', type, id, ] - */ function Autosave(field, key) { this.field = field; this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); diff --git a/app/assets/javascripts/notes/components/issue_notes_app.vue b/app/assets/javascripts/notes/components/issue_notes_app.vue index 4c0351f701b..371addd937e 100644 --- a/app/assets/javascripts/notes/components/issue_notes_app.vue +++ b/app/assets/javascripts/notes/components/issue_notes_app.vue @@ -114,10 +114,12 @@ this.fetchNotes(); this.initPolling(); - this.$el.parentElement.addEventListener('toggleAward', (event) => { - const { awardName, noteId } = event.detail; - this.actionToggleAward({ awardName, noteId }); - }); + if (this.$el.parentElement) { + this.$el.parentElement.addEventListener('toggleAward', (event) => { + const { awardName, noteId } = event.detail; + this.actionToggleAward({ awardName, noteId }); + }); + } }, }; @@ -126,7 +128,7 @@
+ class="js-loading loading">
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 0c9eb046298..1ad7648e533 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -134,7 +134,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => { }; const pollSuccessCallBack = (resp, commit, state, getters) => { - if (resp.notes.length) { + if (resp.notes && resp.notes.length) { const { notesById } = getters; resp.notes.forEach((note) => { diff --git a/spec/javascripts/notes/components/issue_note_app_spec.js b/spec/javascripts/notes/components/issue_note_app_spec.js index df8d250ed5e..847cb2a23ff 100644 --- a/spec/javascripts/notes/components/issue_note_app_spec.js +++ b/spec/javascripts/notes/components/issue_note_app_spec.js @@ -1,36 +1,197 @@ -describe('issue_note_app', () => { +import Vue from 'vue'; +import issueNotesApp from '~/notes/components/issue_notes_app.vue'; +import * as mockData from '../mock_data'; - it('should set notes data', () => { +fdescribe('issue_note_app', () => { + let mountComponent; + beforeEach(() => { + const IssueNotesApp = Vue.extend(issueNotesApp); + + mountComponent = props => new IssueNotesApp({ + propsData: props, + }).$mount(); }); - it('should set issue data', () => { + describe('set data', () => { + let vm; + const responseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(responseInterceptor); + vm = mountComponent({ + issueData: mockData.issueDataMock, + notesData: mockData.notesDataMock, + userData: mockData.userDataMock, + }); + }); + + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor); + }); + + it('should set notes data', () => { + expect(vm.$store.state.notesData).toEqual(mockData.notesDataMock); + }); + + it('should set issue data', () => { + expect(vm.$store.state.issueData).toEqual(mockData.issueDataMock); + }); + + it('should set user data', () => { + expect(vm.$store.state.userData).toEqual(mockData.userDataMock); + }); + + it('should fetch notes', () => { + expect(vm.$store.state.notes).toEqual([]); + }); }); - it('should set user data', () => { + fdescribe('render', () => { + let vm; - }); + const responseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify(mockData.discussionResponse), { + status: 200, + })); + }; - it('should fetch notes', () => { - - }); - - it('should render list of notes', () => { - - }); - - it('should render form', () => { - - }); - - describe('while fetching', () => { - it('should render loading icon', () => { + beforeEach(() => { + Vue.http.interceptors.push(responseInterceptor); + vm = mountComponent({ + issueData: mockData.issueDataMock, + notesData: mockData.notesDataMock, + userData: mockData.userDataMock, + }); + }); + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor); + }); + it('should render list of notes', () => { + console.log(vm); }); it('should render form', () => { + expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM'); + expect( + vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'), + ).toEqual('Write a comment or drag your files here...'); + }); + }); + + describe('while fetching data', () => { + let vm; + beforeEach(() => { + vm = mountComponent({ + issueData: mockData.issueDataMock, + notesData: mockData.notesDataMock, + userData: mockData.userDataMock, + }); + }); + + it('should render loading icon', () => { + expect(vm.$el.querySelector('.js-loading')).toBeDefined(); + }); + + it('should render form', () => { + expect(vm.$el.querySelector('.js-main-target-form').tagName).toEqual('FORM'); + expect( + vm.$el.querySelector('.js-main-target-form textarea').getAttribute('placeholder'), + ).toEqual('Write a comment or drag your files here...'); + }); + }); + + describe('update note', () => { + describe('individual note', () => { + describe('shortup up key', () => { + it('shows correct editing form when user clicks up', () => { + }); + }); + + describe('dropdown', () => { + it('renders edit form', () => { + }); + }); + + it('updates the note and resets the edit form', () => {}); + }); + + describe('dicussion note note', () => { + describe('shortup up key', () => { + it('shows correct editing form when user clicks up', () => { + }); + }); + + describe('dropdown', () => { + it('renders edit form', () => { + }); + }); + + it('updates the note and resets the edit form', () => {}); + }); + }); + + describe('set target hash', () => { + it('updates the URL when the note date is clicked', () => { + + }); + + it('stores the correct hash', () => { + + }); + + it('updates visually the target note', () => { }); }); -}); \ No newline at end of file + + 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', () => {}); + 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 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', () => {}); + }); +}); diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js index 42d1bf9adc0..ce969f0f460 100644 --- a/spec/javascripts/notes/mock_data.js +++ b/spec/javascripts/notes/mock_data.js @@ -1,3 +1,5 @@ +/* eslint disable */ + export const notesDataMock = { discussionsPath: '/gitlab-org/gitlab-ce/issues/26/discussions.json', lastFetchedAt: '1501862675', @@ -17,7 +19,7 @@ export const userDataMock = { username: 'root', }; -export const issueData = { +export const issueDataMock = { assignees: [], author_id: 1, branch_name: null, @@ -218,4 +220,98 @@ export const discussionMock = { path: '/gitlab-org/gitlab-ce/notes/1437', }], individual_note: false, -}; \ No newline at end of file +}; + +export const discussionResponse = [{ + "id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", + "reply_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", + "expanded": true, + "notes": [{ + "id": 1390, + "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-01T17:09:33.762Z", + "updated_at": "2017-08-01T17:09:33.762Z", + "system": false, + "noteable_id": 98, + "noteable_type": "Issue", + "type": null, + "human_access": "Owner", + "note": "sdfdsaf", + "note_html": "\u003cp dir=\"auto\"\u003esdfdsaf\u003c/p\u003e", + "current_user": { + "can_edit": true + }, + "discussion_id": "0fb4e0e3f9276e55ff32eb4195add694aece4edd", + "emoji_awardable": true, + "award_emoji": [{ + "name": "baseball", + "user": { + "id": 1, + "name": "Root", + "username": "root" + } + }, { + "name": "art", + "user": { + "id": 1, + "name": "Root", + "username": "root" + } + }], + "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", + "path": "/gitlab-org/gitlab-ce/notes/1390" + }], + "individual_note": true +}, { + "id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", + "reply_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", + "expanded": true, + "notes": [{ + "id": 1391, + "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-02T10:51:38.685Z", + "updated_at": "2017-08-02T10:51:38.685Z", + "system": false, + "noteable_id": 98, + "noteable_type": "Issue", + "type": null, + "human_access": "Owner", + "note": "New note!", + "note_html": "\u003cp dir=\"auto\"\u003eNew note!\u003c/p\u003e", + "current_user": { + "can_edit": true + }, + "discussion_id": "70d5c92a4039a36c70100c6691c18c27e4b0a790", + "emoji_awardable": true, + "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", + "path": "/gitlab-org/gitlab-ce/notes/1391" + }], + "individual_note": true +}]; \ No newline at end of file