diff options
Diffstat (limited to 'spec/frontend/ide/components/commit_sidebar')
3 files changed, 294 insertions, 25 deletions
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js index 129180bb46e..c62df4a3795 100644 --- a/spec/frontend/ide/components/commit_sidebar/form_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js @@ -5,11 +5,14 @@ import store from '~/ide/stores'; import CommitForm from '~/ide/components/commit_sidebar/form.vue'; import { leftSidebarViews } from '~/ide/constants'; import { resetStore } from '../../helpers'; +import waitForPromises from 'helpers/wait_for_promises'; describe('IDE commit form', () => { const Component = Vue.extend(CommitForm); let vm; + const beginCommitButton = () => vm.$el.querySelector('[data-testid="begin-commit-button"]'); + beforeEach(() => { store.state.changedFiles.push('test'); store.state.currentProjectId = 'abcproject'; @@ -25,8 +28,15 @@ describe('IDE commit form', () => { resetStore(vm.$store); }); - it('enables button when has changes', () => { - expect(vm.$el.querySelector('[disabled]')).toBe(null); + it('enables begin commit button when there are changes', () => { + expect(beginCommitButton()).not.toHaveAttr('disabled'); + }); + + it('disables begin commit button when there are no changes', async () => { + store.state.changedFiles = []; + await vm.$nextTick(); + + expect(beginCommitButton()).toHaveAttr('disabled'); }); describe('compact', () => { @@ -37,8 +47,8 @@ describe('IDE commit form', () => { }); it('renders commit button in compact mode', () => { - expect(vm.$el.querySelector('.btn-primary')).not.toBeNull(); - expect(vm.$el.querySelector('.btn-primary').textContent).toContain('Commit'); + expect(beginCommitButton()).not.toBeNull(); + expect(beginCommitButton().textContent).toContain('Commit'); }); it('does not render form', () => { @@ -54,7 +64,7 @@ describe('IDE commit form', () => { }); it('shows form when clicking commit button', () => { - vm.$el.querySelector('.btn-primary').click(); + beginCommitButton().click(); return vm.$nextTick(() => { expect(vm.$el.querySelector('form')).not.toBeNull(); @@ -62,31 +72,117 @@ describe('IDE commit form', () => { }); it('toggles activity bar view when clicking commit button', () => { - vm.$el.querySelector('.btn-primary').click(); + beginCommitButton().click(); return vm.$nextTick(() => { expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name); }); }); - it('collapses if lastCommitMsg is set to empty and current view is not commit view', () => { + it('collapses if lastCommitMsg is set to empty and current view is not commit view', async () => { store.state.lastCommitMsg = 'abc'; store.state.currentActivityView = leftSidebarViews.edit.name; + await vm.$nextTick(); - return vm - .$nextTick() - .then(() => { - // if commit message is set, form is uncollapsed - expect(vm.isCompact).toBe(false); + // if commit message is set, form is uncollapsed + expect(vm.isCompact).toBe(false); - store.state.lastCommitMsg = ''; + store.state.lastCommitMsg = ''; + await vm.$nextTick(); - return vm.$nextTick(); - }) - .then(() => { - // collapsed when set to empty - expect(vm.isCompact).toBe(true); - }); + // collapsed when set to empty + expect(vm.isCompact).toBe(true); + }); + + it('collapses if in commit view but there are no changes and vice versa', async () => { + store.state.currentActivityView = leftSidebarViews.commit.name; + await vm.$nextTick(); + + // expanded by default if there are changes + expect(vm.isCompact).toBe(false); + + store.state.changedFiles = []; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.changedFiles.push('test'); + await vm.$nextTick(); + + // uncollapsed once again + expect(vm.isCompact).toBe(false); + }); + + it('collapses if switched from commit view to edit view and vice versa', async () => { + store.state.currentActivityView = leftSidebarViews.edit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.currentActivityView = leftSidebarViews.commit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(false); + + store.state.currentActivityView = leftSidebarViews.edit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + }); + + describe('when window height is less than MAX_WINDOW_HEIGHT', () => { + let oldHeight; + + beforeEach(() => { + oldHeight = window.innerHeight; + window.innerHeight = 700; + }); + + afterEach(() => { + window.innerHeight = oldHeight; + }); + + it('stays collapsed when switching from edit view to commit view and back', async () => { + store.state.currentActivityView = leftSidebarViews.edit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.currentActivityView = leftSidebarViews.commit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.currentActivityView = leftSidebarViews.edit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + }); + + it('stays uncollapsed if changes are added or removed', async () => { + store.state.currentActivityView = leftSidebarViews.commit.name; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.changedFiles = []; + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + + store.state.changedFiles.push('test'); + await vm.$nextTick(); + + expect(vm.isCompact).toBe(true); + }); + + it('uncollapses when clicked on Commit button in the edit view', async () => { + store.state.currentActivityView = leftSidebarViews.edit.name; + beginCommitButton().click(); + await waitForPromises(); + + expect(vm.isCompact).toBe(false); + }); }); }); @@ -118,7 +214,7 @@ describe('IDE commit form', () => { }); it('always opens itself in full view current activity view is not commit view when clicking commit button', () => { - vm.$el.querySelector('.btn-primary').click(); + beginCommitButton().click(); return vm.$nextTick(() => { expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name); diff --git a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js index ebb41448905..7ce628d4da7 100644 --- a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js @@ -1,17 +1,22 @@ import Vue from 'vue'; import { trimText } from 'helpers/text_helper'; import { createComponentWithStore } from 'helpers/vue_mount_component_helper'; -import store from '~/ide/stores'; +import { createStore } from '~/ide/stores'; import listItem from '~/ide/components/commit_sidebar/list_item.vue'; -import router from '~/ide/ide_router'; -import { file, resetStore } from '../../helpers'; +import { createRouter } from '~/ide/ide_router'; +import { file } from '../../helpers'; describe('Multi-file editor commit sidebar list item', () => { let vm; let f; let findPathEl; + let store; + let router; beforeEach(() => { + store = createStore(); + router = createRouter(store); + const Component = Vue.extend(listItem); f = file('test-file'); @@ -28,8 +33,6 @@ describe('Multi-file editor commit sidebar list item', () => { afterEach(() => { vm.$destroy(); - - resetStore(store); }); const findPathText = () => trimText(findPathEl.textContent); diff --git a/spec/frontend/ide/components/commit_sidebar/message_field_spec.js b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js new file mode 100644 index 00000000000..d6ea8b9a4bd --- /dev/null +++ b/spec/frontend/ide/components/commit_sidebar/message_field_spec.js @@ -0,0 +1,170 @@ +import Vue from 'vue'; +import createComponent from 'helpers/vue_mount_component_helper'; +import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue'; + +describe('IDE commit message field', () => { + const Component = Vue.extend(CommitMessageField); + let vm; + + beforeEach(() => { + setFixtures('<div id="app"></div>'); + + vm = createComponent( + Component, + { + text: '', + placeholder: 'testing', + }, + '#app', + ); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('adds is-focused class on focus', done => { + vm.$el.querySelector('textarea').focus(); + + vm.$nextTick(() => { + expect(vm.$el.querySelector('.is-focused')).not.toBeNull(); + + done(); + }); + }); + + it('removed is-focused class on blur', done => { + vm.$el.querySelector('textarea').focus(); + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelector('.is-focused')).not.toBeNull(); + + vm.$el.querySelector('textarea').blur(); + + return vm.$nextTick(); + }) + .then(() => { + expect(vm.$el.querySelector('.is-focused')).toBeNull(); + + done(); + }) + .then(done) + .catch(done.fail); + }); + + it('emits input event on input', () => { + jest.spyOn(vm, '$emit').mockImplementation(); + + const textarea = vm.$el.querySelector('textarea'); + textarea.value = 'testing'; + + textarea.dispatchEvent(new Event('input')); + + expect(vm.$emit).toHaveBeenCalledWith('input', 'testing'); + }); + + describe('highlights', () => { + describe('subject line', () => { + it('does not highlight less than 50 characters', done => { + vm.text = 'text less than 50 chars'; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelector('.highlights span').textContent).toContain( + 'text less than 50 chars', + ); + + expect(vm.$el.querySelector('mark').style.display).toBe('none'); + }) + .then(done) + .catch(done.fail); + }); + + it('highlights characters over 50 length', done => { + vm.text = + 'text less than 50 chars that should not highlighted. text more than 50 should be highlighted'; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelector('.highlights span').textContent).toContain( + 'text less than 50 chars that should not highlighte', + ); + + expect(vm.$el.querySelector('mark').style.display).not.toBe('none'); + expect(vm.$el.querySelector('mark').textContent).toBe( + 'd. text more than 50 should be highlighted', + ); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('body text', () => { + it('does not highlight body text less tan 72 characters', done => { + vm.text = 'subject line\nbody content'; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2); + expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none'); + }) + .then(done) + .catch(done.fail); + }); + + it('highlights body text more than 72 characters', done => { + vm.text = + 'subject line\nbody content that will be highlighted when it is more than 72 characters in length'; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2); + expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none'); + expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length'); + }) + .then(done) + .catch(done.fail); + }); + + it('highlights body text & subject line', done => { + vm.text = + 'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length'; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2); + expect(vm.$el.querySelectorAll('mark').length).toBe(2); + + expect(vm.$el.querySelectorAll('mark')[0].textContent).toContain('d'); + expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length'); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + + describe('scrolling textarea', () => { + it('updates transform of highlights', done => { + vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content'; + + vm.$nextTick() + .then(() => { + vm.$el.querySelector('textarea').scrollTo(0, 50); + + vm.handleScroll(); + }) + .then(vm.$nextTick) + .then(() => { + expect(vm.scrollTop).toBe(50); + expect(vm.$el.querySelector('.highlights').style.transform).toBe( + 'translate3d(0, -50px, 0)', + ); + }) + .then(done) + .catch(done.fail); + }); + }); +}); |