diff options
Diffstat (limited to 'spec/frontend/notes/components/noteable_note_spec.js')
-rw-r--r-- | spec/frontend/notes/components/noteable_note_spec.js | 214 |
1 files changed, 131 insertions, 83 deletions
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js index fe78e086403..112983f3ac2 100644 --- a/spec/frontend/notes/components/noteable_note_spec.js +++ b/spec/frontend/notes/components/noteable_note_spec.js @@ -1,5 +1,6 @@ import { mount, createLocalVue } from '@vue/test-utils'; import { escape } from 'lodash'; +import waitForPromises from 'helpers/wait_for_promises'; import NoteActions from '~/notes/components/note_actions.vue'; import NoteBody from '~/notes/components/note_body.vue'; import NoteHeader from '~/notes/components/note_header.vue'; @@ -13,7 +14,7 @@ describe('issue_note', () => { let wrapper; const findMultilineComment = () => wrapper.find('[data-testid="multiline-comment"]'); - beforeEach(() => { + const createWrapper = (props = {}) => { store = createStore(); store.dispatch('setNoteableData', noteableDataMock); store.dispatch('setNotesData', notesDataMock); @@ -23,6 +24,7 @@ describe('issue_note', () => { store, propsData: { note, + ...props, }, localVue, stubs: [ @@ -33,14 +35,18 @@ describe('issue_note', () => { 'multiline-comment-form', ], }); - }); + }; afterEach(() => { wrapper.destroy(); }); describe('mutiline comments', () => { - it('should render if has multiline comment', () => { + beforeEach(() => { + createWrapper(); + }); + + it('should render if has multiline comment', async () => { const position = { line_range: { start: { @@ -69,9 +75,8 @@ describe('issue_note', () => { line, }); - return wrapper.vm.$nextTick().then(() => { - expect(findMultilineComment().text()).toEqual('Comment on lines 1 to 2'); - }); + await wrapper.vm.$nextTick(); + expect(findMultilineComment().text()).toBe('Comment on lines 1 to 2'); }); it('should only render if it has everything it needs', () => { @@ -147,108 +152,151 @@ describe('issue_note', () => { }); }); - it('should render user information', () => { - const { author } = note; - const avatar = wrapper.find(UserAvatarLink); - const avatarProps = avatar.props(); + describe('rendering', () => { + beforeEach(() => { + createWrapper(); + }); - expect(avatarProps.linkHref).toBe(author.path); - expect(avatarProps.imgSrc).toBe(author.avatar_url); - expect(avatarProps.imgAlt).toBe(author.name); - expect(avatarProps.imgSize).toBe(40); - }); + it('should render user information', () => { + const { author } = note; + const avatar = wrapper.findComponent(UserAvatarLink); + const avatarProps = avatar.props(); - it('should render note header content', () => { - const noteHeader = wrapper.find(NoteHeader); - const noteHeaderProps = noteHeader.props(); + expect(avatarProps.linkHref).toBe(author.path); + expect(avatarProps.imgSrc).toBe(author.avatar_url); + expect(avatarProps.imgAlt).toBe(author.name); + expect(avatarProps.imgSize).toBe(40); + }); - expect(noteHeaderProps.author).toEqual(note.author); - expect(noteHeaderProps.createdAt).toEqual(note.created_at); - expect(noteHeaderProps.noteId).toEqual(note.id); - }); + it('should render note header content', () => { + const noteHeader = wrapper.findComponent(NoteHeader); + const noteHeaderProps = noteHeader.props(); - it('should render note actions', () => { - const { author } = note; - const noteActions = wrapper.find(NoteActions); - const noteActionsProps = noteActions.props(); - - expect(noteActionsProps.authorId).toBe(author.id); - expect(noteActionsProps.noteId).toBe(note.id); - expect(noteActionsProps.noteUrl).toBe(note.noteable_note_url); - expect(noteActionsProps.accessLevel).toBe(note.human_access); - expect(noteActionsProps.canEdit).toBe(note.current_user.can_edit); - expect(noteActionsProps.canAwardEmoji).toBe(note.current_user.can_award_emoji); - expect(noteActionsProps.canDelete).toBe(note.current_user.can_edit); - expect(noteActionsProps.canReportAsAbuse).toBe(true); - expect(noteActionsProps.canResolve).toBe(false); - expect(noteActionsProps.reportAbusePath).toBe(note.report_abuse_path); - expect(noteActionsProps.resolvable).toBe(false); - expect(noteActionsProps.isResolved).toBe(false); - expect(noteActionsProps.isResolving).toBe(false); - expect(noteActionsProps.resolvedBy).toEqual({}); - }); + expect(noteHeaderProps.author).toBe(note.author); + expect(noteHeaderProps.createdAt).toBe(note.created_at); + expect(noteHeaderProps.noteId).toBe(note.id); + }); - it('should render issue body', () => { - const noteBody = wrapper.find(NoteBody); - const noteBodyProps = noteBody.props(); + it('should render note actions', () => { + const { author } = note; + const noteActions = wrapper.findComponent(NoteActions); + const noteActionsProps = noteActions.props(); - expect(noteBodyProps.note).toEqual(note); - expect(noteBodyProps.line).toBe(null); - expect(noteBodyProps.canEdit).toBe(note.current_user.can_edit); - expect(noteBodyProps.isEditing).toBe(false); - expect(noteBodyProps.helpPagePath).toBe(''); - }); + expect(noteActionsProps.authorId).toBe(author.id); + expect(noteActionsProps.noteId).toBe(note.id); + expect(noteActionsProps.noteUrl).toBe(note.noteable_note_url); + expect(noteActionsProps.accessLevel).toBe(note.human_access); + expect(noteActionsProps.canEdit).toBe(note.current_user.can_edit); + expect(noteActionsProps.canAwardEmoji).toBe(note.current_user.can_award_emoji); + expect(noteActionsProps.canDelete).toBe(note.current_user.can_edit); + expect(noteActionsProps.canReportAsAbuse).toBe(true); + expect(noteActionsProps.canResolve).toBe(false); + expect(noteActionsProps.reportAbusePath).toBe(note.report_abuse_path); + expect(noteActionsProps.resolvable).toBe(false); + expect(noteActionsProps.isResolved).toBe(false); + expect(noteActionsProps.isResolving).toBe(false); + expect(noteActionsProps.resolvedBy).toEqual({}); + }); - it('prevents note preview xss', (done) => { - const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; - const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`; - const alertSpy = jest.spyOn(window, 'alert'); - store.hotUpdate({ - actions: { - updateNote() {}, - setSelectedCommentPositionHover() {}, - }, + it('should render issue body', () => { + const noteBody = wrapper.findComponent(NoteBody); + const noteBodyProps = noteBody.props(); + + expect(noteBodyProps.note).toBe(note); + expect(noteBodyProps.line).toBe(null); + expect(noteBodyProps.canEdit).toBe(note.current_user.can_edit); + expect(noteBodyProps.isEditing).toBe(false); + expect(noteBodyProps.helpPagePath).toBe(''); }); - const noteBodyComponent = wrapper.find(NoteBody); - noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {}); + it('prevents note preview xss', async () => { + const noteBody = + '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert(1)" />'; + const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {}); + const noteBodyComponent = wrapper.findComponent(NoteBody); + + store.hotUpdate({ + actions: { + updateNote() {}, + setSelectedCommentPositionHover() {}, + }, + }); + + noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {}); - setImmediate(() => { + await waitForPromises(); expect(alertSpy).not.toHaveBeenCalled(); - expect(wrapper.vm.note.note_html).toEqual(escape(noteBody)); - done(); + expect(wrapper.vm.note.note_html).toBe(escape(noteBody)); }); }); describe('cancel edit', () => { - it('restores content of updated note', (done) => { + beforeEach(() => { + createWrapper(); + }); + + it('restores content of updated note', async () => { const updatedText = 'updated note text'; store.hotUpdate({ actions: { updateNote() {}, }, }); - const noteBody = wrapper.find(NoteBody); + const noteBody = wrapper.findComponent(NoteBody); noteBody.vm.resetAutoSave = () => {}; noteBody.vm.$emit('handleFormUpdate', updatedText, null, () => {}); - wrapper.vm - .$nextTick() - .then(() => { - const noteBodyProps = noteBody.props(); - - expect(noteBodyProps.note.note_html).toBe(updatedText); - noteBody.vm.$emit('cancelForm'); - }) - .then(() => wrapper.vm.$nextTick()) - .then(() => { - const noteBodyProps = noteBody.props(); - - expect(noteBodyProps.note.note_html).toBe(note.note_html); - }) - .then(done) - .catch(done.fail); + await wrapper.vm.$nextTick(); + let noteBodyProps = noteBody.props(); + + expect(noteBodyProps.note.note_html).toBe(updatedText); + + noteBody.vm.$emit('cancelForm'); + await wrapper.vm.$nextTick(); + + noteBodyProps = noteBody.props(); + + expect(noteBodyProps.note.note_html).toBe(note.note_html); + }); + }); + + describe('formUpdateHandler', () => { + const updateNote = jest.fn(); + const params = ['', null, jest.fn(), '']; + + const updateActions = () => { + store.hotUpdate({ + actions: { + updateNote, + setSelectedCommentPositionHover() {}, + }, + }); + }; + + afterEach(() => updateNote.mockReset()); + + it('responds to handleFormUpdate', () => { + createWrapper(); + updateActions(); + wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', ...params); + expect(wrapper.emitted('handleUpdateNote')).toBeTruthy(); + }); + + it('does not stringify empty position', () => { + createWrapper(); + updateActions(); + wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', ...params); + expect(updateNote.mock.calls[0][1].note.note.position).toBeUndefined(); + }); + + it('stringifies populated position', () => { + const position = { test: true }; + const expectation = JSON.stringify(position); + createWrapper({ note: { ...note, position } }); + updateActions(); + wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', ...params); + expect(updateNote.mock.calls[0][1].note.note.position).toBe(expectation); }); }); }); |