Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/javascripts/repo')
-rw-r--r--spec/javascripts/repo/components/new_branch_form_spec.js114
-rw-r--r--spec/javascripts/repo/components/new_dropdown/index_spec.js71
-rw-r--r--spec/javascripts/repo/components/new_dropdown/modal_spec.js198
-rw-r--r--spec/javascripts/repo/components/new_dropdown/upload_spec.js103
-rw-r--r--spec/javascripts/repo/components/repo_commit_section_spec.js203
-rw-r--r--spec/javascripts/repo/components/repo_edit_button_spec.js88
-rw-r--r--spec/javascripts/repo/components/repo_editor_spec.js63
-rw-r--r--spec/javascripts/repo/components/repo_file_buttons_spec.js90
-rw-r--r--spec/javascripts/repo/components/repo_file_options_spec.js33
-rw-r--r--spec/javascripts/repo/components/repo_file_spec.js143
-rw-r--r--spec/javascripts/repo/components/repo_loading_file_spec.js59
-rw-r--r--spec/javascripts/repo/components/repo_prev_directory_spec.js52
-rw-r--r--spec/javascripts/repo/components/repo_preview_spec.js32
-rw-r--r--spec/javascripts/repo/components/repo_sidebar_spec.js122
-rw-r--r--spec/javascripts/repo/components/repo_spec.js35
-rw-r--r--spec/javascripts/repo/components/repo_tab_spec.js104
-rw-r--r--spec/javascripts/repo/components/repo_tabs_spec.js47
-rw-r--r--spec/javascripts/repo/helpers.js20
-rw-r--r--spec/javascripts/repo/services/repo_service_spec.js171
19 files changed, 1013 insertions, 735 deletions
diff --git a/spec/javascripts/repo/components/new_branch_form_spec.js b/spec/javascripts/repo/components/new_branch_form_spec.js
new file mode 100644
index 00000000000..9a705a1f0ed
--- /dev/null
+++ b/spec/javascripts/repo/components/new_branch_form_spec.js
@@ -0,0 +1,114 @@
+import Vue from 'vue';
+import store from '~/repo/stores';
+import newBranchForm from '~/repo/components/new_branch_form.vue';
+import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
+import { resetStore } from '../helpers';
+
+describe('Multi-file editor new branch form', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(newBranchForm);
+
+ vm = createComponentWithStore(Component, store);
+
+ vm.$store.state.currentBranch = 'master';
+
+ vm.$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ describe('template', () => {
+ it('renders submit as disabled', () => {
+ expect(vm.$el.querySelector('.btn').getAttribute('disabled')).toBe('disabled');
+ });
+
+ it('enables the submit button when branch is not empty', (done) => {
+ vm.branchName = 'testing';
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.btn').getAttribute('disabled')).toBeNull();
+
+ done();
+ });
+ });
+
+ it('displays current branch creating from', (done) => {
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('p').textContent.replace(/\s+/g, ' ').trim()).toBe('Create from: master');
+
+ done();
+ });
+ });
+ });
+
+ describe('submitNewBranch', () => {
+ beforeEach(() => {
+ spyOn(vm, 'createNewBranch').and.returnValue(Promise.resolve());
+ });
+
+ it('sets to loading', () => {
+ vm.submitNewBranch();
+
+ expect(vm.loading).toBeTruthy();
+ });
+
+ it('hides current flash element', (done) => {
+ vm.$refs.flashContainer.innerHTML = '<div class="flash-alert"></div>';
+
+ vm.submitNewBranch();
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.flash-alert')).toBeNull();
+
+ done();
+ });
+ });
+
+ it('calls createdNewBranch with branchName', () => {
+ vm.branchName = 'testing';
+
+ vm.submitNewBranch();
+
+ expect(vm.createNewBranch).toHaveBeenCalledWith('testing');
+ });
+ });
+
+ describe('submitNewBranch with error', () => {
+ beforeEach(() => {
+ spyOn(vm, 'createNewBranch').and.returnValue(Promise.reject({
+ json: () => Promise.resolve({
+ message: 'error message',
+ }),
+ }));
+ });
+
+ it('sets loading to false', (done) => {
+ vm.loading = true;
+
+ vm.submitNewBranch();
+
+ setTimeout(() => {
+ expect(vm.loading).toBeFalsy();
+
+ done();
+ });
+ });
+
+ it('creates flash element', (done) => {
+ vm.submitNewBranch();
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.flash-alert')).not.toBeNull();
+ expect(vm.$el.querySelector('.flash-alert').textContent.trim()).toBe('error message');
+
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/repo/components/new_dropdown/index_spec.js b/spec/javascripts/repo/components/new_dropdown/index_spec.js
new file mode 100644
index 00000000000..93b10fc1fee
--- /dev/null
+++ b/spec/javascripts/repo/components/new_dropdown/index_spec.js
@@ -0,0 +1,71 @@
+import Vue from 'vue';
+import store from '~/repo/stores';
+import newDropdown from '~/repo/components/new_dropdown/index.vue';
+import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
+import { resetStore } from '../../helpers';
+
+describe('new dropdown component', () => {
+ let vm;
+
+ beforeEach(() => {
+ const component = Vue.extend(newDropdown);
+
+ vm = createComponentWithStore(component, store);
+
+ vm.$store.state.path = '';
+
+ vm.$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ it('renders new file and new directory links', () => {
+ expect(vm.$el.querySelectorAll('a')[0].textContent.trim()).toBe('New file');
+ expect(vm.$el.querySelectorAll('a')[1].textContent.trim()).toBe('New directory');
+ });
+
+ describe('createNewItem', () => {
+ it('sets modalType to blob when new file is clicked', () => {
+ vm.$el.querySelectorAll('a')[0].click();
+
+ expect(vm.modalType).toBe('blob');
+ });
+
+ it('sets modalType to tree when new directory is clicked', () => {
+ vm.$el.querySelectorAll('a')[1].click();
+
+ expect(vm.modalType).toBe('tree');
+ });
+
+ it('opens modal when link is clicked', (done) => {
+ vm.$el.querySelectorAll('a')[0].click();
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.modal')).not.toBeNull();
+
+ done();
+ });
+ });
+ });
+
+ describe('toggleModalOpen', () => {
+ it('closes modal after toggling', (done) => {
+ vm.toggleModalOpen();
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.modal')).not.toBeNull();
+ })
+ .then(vm.toggleModalOpen)
+ .then(() => {
+ expect(vm.$el.querySelector('.modal')).toBeNull();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/repo/components/new_dropdown/modal_spec.js b/spec/javascripts/repo/components/new_dropdown/modal_spec.js
new file mode 100644
index 00000000000..1ff7590ec79
--- /dev/null
+++ b/spec/javascripts/repo/components/new_dropdown/modal_spec.js
@@ -0,0 +1,198 @@
+import Vue from 'vue';
+import store from '~/repo/stores';
+import modal from '~/repo/components/new_dropdown/modal.vue';
+import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
+import { file, resetStore } from '../../helpers';
+
+describe('new file modal component', () => {
+ const Component = Vue.extend(modal);
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ ['tree', 'blob'].forEach((type) => {
+ describe(type, () => {
+ beforeEach(() => {
+ vm = createComponentWithStore(Component, store, {
+ type,
+ path: '',
+ }).$mount();
+
+ vm.entryName = 'testing';
+ });
+
+ it(`sets modal title as ${type}`, () => {
+ const title = type === 'tree' ? 'directory' : 'file';
+
+ expect(vm.$el.querySelector('.modal-title').textContent.trim()).toBe(`Create new ${title}`);
+ });
+
+ it(`sets button label as ${type}`, () => {
+ const title = type === 'tree' ? 'directory' : 'file';
+
+ expect(vm.$el.querySelector('.btn-success').textContent.trim()).toBe(`Create ${title}`);
+ });
+
+ it(`sets form label as ${type}`, () => {
+ const title = type === 'tree' ? 'Directory' : 'File';
+
+ expect(vm.$el.querySelector('.label-light').textContent.trim()).toBe(`${title} name`);
+ });
+
+ describe('createEntryInStore', () => {
+ it('calls createTempEntry', () => {
+ spyOn(vm, 'createTempEntry');
+
+ vm.createEntryInStore();
+
+ expect(vm.createTempEntry).toHaveBeenCalledWith({
+ name: 'testing',
+ type,
+ });
+ });
+
+ it('sets editMode to true', (done) => {
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.editMode).toBeTruthy();
+
+ done();
+ });
+ });
+
+ it('toggles blob view', (done) => {
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.currentBlobView).toBe('repo-editor');
+
+ done();
+ });
+ });
+
+ it('opens newly created file', (done) => {
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.openFiles.length).toBe(1);
+ expect(vm.$store.state.openFiles[0].name).toBe(type === 'blob' ? 'testing' : '.gitkeep');
+
+ done();
+ });
+ });
+
+ it(`creates ${type} in the current stores path`, (done) => {
+ vm.$store.state.path = 'app';
+
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.tree[0].path).toBe('app/testing');
+ expect(vm.$store.state.tree[0].name).toBe('testing');
+
+ if (type === 'tree') {
+ expect(vm.$store.state.tree[0].tree.length).toBe(1);
+ }
+
+ done();
+ });
+ });
+
+ if (type === 'blob') {
+ it('creates new file', (done) => {
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('testing');
+ expect(vm.$store.state.tree[0].type).toBe('blob');
+ expect(vm.$store.state.tree[0].tempFile).toBeTruthy();
+
+ done();
+ });
+ });
+
+ it('does not create temp file when file already exists', (done) => {
+ vm.$store.state.tree.push(file('testing', '1', type));
+
+ vm.createEntryInStore();
+
+ setTimeout(() => {
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('testing');
+ expect(vm.$store.state.tree[0].type).toBe('blob');
+ expect(vm.$store.state.tree[0].tempFile).toBeFalsy();
+
+ done();
+ });
+ });
+ } else {
+ it('creates new tree', () => {
+ vm.createEntryInStore();
+
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('testing');
+ expect(vm.$store.state.tree[0].type).toBe('tree');
+ expect(vm.$store.state.tree[0].tempFile).toBeTruthy();
+ expect(vm.$store.state.tree[0].tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].tree[0].name).toBe('.gitkeep');
+ });
+
+ it('creates multiple trees when entryName has slashes', () => {
+ vm.entryName = 'app/test';
+ vm.createEntryInStore();
+
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('app');
+ expect(vm.$store.state.tree[0].tree[0].name).toBe('test');
+ expect(vm.$store.state.tree[0].tree[0].tree[0].name).toBe('.gitkeep');
+ });
+
+ it('creates tree in existing tree', () => {
+ vm.$store.state.tree.push(file('app', '1', 'tree'));
+
+ vm.entryName = 'app/test';
+ vm.createEntryInStore();
+
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('app');
+ expect(vm.$store.state.tree[0].tempFile).toBeFalsy();
+ expect(vm.$store.state.tree[0].tree[0].tempFile).toBeTruthy();
+ expect(vm.$store.state.tree[0].tree[0].name).toBe('test');
+ expect(vm.$store.state.tree[0].tree[0].tree[0].name).toBe('.gitkeep');
+ });
+
+ it('does not create new tree when already exists', () => {
+ vm.$store.state.tree.push(file('app', '1', 'tree'));
+
+ vm.entryName = 'app';
+ vm.createEntryInStore();
+
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe('app');
+ expect(vm.$store.state.tree[0].tempFile).toBeFalsy();
+ expect(vm.$store.state.tree[0].tree.length).toBe(0);
+ });
+ }
+ });
+ });
+ });
+
+ it('focuses field on mount', () => {
+ document.body.innerHTML += '<div class="js-test"></div>';
+
+ vm = createComponentWithStore(Component, store, {
+ type: 'tree',
+ path: '',
+ }).$mount('.js-test');
+
+ expect(document.activeElement).toBe(vm.$refs.fieldName);
+
+ vm.$el.remove();
+ });
+});
diff --git a/spec/javascripts/repo/components/new_dropdown/upload_spec.js b/spec/javascripts/repo/components/new_dropdown/upload_spec.js
new file mode 100644
index 00000000000..bf7893029b1
--- /dev/null
+++ b/spec/javascripts/repo/components/new_dropdown/upload_spec.js
@@ -0,0 +1,103 @@
+import Vue from 'vue';
+import upload from '~/repo/components/new_dropdown/upload.vue';
+import store from '~/repo/stores';
+import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
+import { resetStore } from '../../helpers';
+
+describe('new dropdown upload', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(upload);
+
+ vm = createComponentWithStore(Component, store, {
+ path: '',
+ });
+
+ vm.$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ describe('readFile', () => {
+ beforeEach(() => {
+ spyOn(FileReader.prototype, 'readAsText');
+ spyOn(FileReader.prototype, 'readAsDataURL');
+ });
+
+ it('calls readAsText for text files', () => {
+ const file = {
+ type: 'text/html',
+ };
+
+ vm.readFile(file);
+
+ expect(FileReader.prototype.readAsText).toHaveBeenCalledWith(file);
+ });
+
+ it('calls readAsDataURL for non-text files', () => {
+ const file = {
+ type: 'images/png',
+ };
+
+ vm.readFile(file);
+
+ expect(FileReader.prototype.readAsDataURL).toHaveBeenCalledWith(file);
+ });
+ });
+
+ describe('createFile', () => {
+ const target = {
+ result: 'content',
+ };
+ const binaryTarget = {
+ result: 'base64,base64content',
+ };
+ const file = {
+ name: 'file',
+ };
+
+ it('creates new file', (done) => {
+ vm.createFile(target, file, true);
+
+ vm.$nextTick(() => {
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe(file.name);
+ expect(vm.$store.state.tree[0].content).toBe(target.result);
+
+ done();
+ });
+ });
+
+ it('creates new file in path', (done) => {
+ vm.$store.state.path = 'testing';
+ vm.createFile(target, file, true);
+
+ vm.$nextTick(() => {
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe(file.name);
+ expect(vm.$store.state.tree[0].content).toBe(target.result);
+ expect(vm.$store.state.tree[0].path).toBe(`testing/${file.name}`);
+
+ done();
+ });
+ });
+
+ it('splits content on base64 if binary', (done) => {
+ vm.createFile(binaryTarget, file, false);
+
+ vm.$nextTick(() => {
+ expect(vm.$store.state.tree.length).toBe(1);
+ expect(vm.$store.state.tree[0].name).toBe(file.name);
+ expect(vm.$store.state.tree[0].content).toBe(binaryTarget.result.split('base64,')[1]);
+ expect(vm.$store.state.tree[0].base64).toBe(true);
+
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/repo/components/repo_commit_section_spec.js b/spec/javascripts/repo/components/repo_commit_section_spec.js
index e604dcc152d..0f991e1b727 100644
--- a/spec/javascripts/repo/components/repo_commit_section_spec.js
+++ b/spec/javascripts/repo/components/repo_commit_section_spec.js
@@ -1,49 +1,43 @@
import Vue from 'vue';
+import store from '~/repo/stores';
+import service from '~/repo/services';
import repoCommitSection from '~/repo/components/repo_commit_section.vue';
-import RepoStore from '~/repo/stores/repo_store';
-import RepoService from '~/repo/services/repo_service';
+import getSetTimeoutPromise from '../../helpers/set_timeout_promise_helper';
+import { file, resetStore } from '../helpers';
describe('RepoCommitSection', () => {
- const branch = 'master';
- const projectUrl = 'projectUrl';
- const changedFiles = [{
- id: 0,
- changed: true,
- url: `/namespace/${projectUrl}/blob/${branch}/dir/file0.ext`,
- path: 'dir/file0.ext',
- newContent: 'a',
- }, {
- id: 1,
- changed: true,
- url: `/namespace/${projectUrl}/blob/${branch}/dir/file1.ext`,
- path: 'dir/file1.ext',
- newContent: 'b',
- }];
- const openedFiles = changedFiles.concat([{
- id: 2,
- url: `/namespace/${projectUrl}/blob/${branch}/dir/file2.ext`,
- path: 'dir/file2.ext',
- changed: false,
- }]);
-
- RepoStore.projectUrl = projectUrl;
-
- function createComponent(el) {
+ let vm;
+
+ function createComponent() {
const RepoCommitSection = Vue.extend(repoCommitSection);
- return new RepoCommitSection().$mount(el);
+ const comp = new RepoCommitSection({
+ store,
+ }).$mount();
+
+ comp.$store.state.currentBranch = 'master';
+ comp.$store.state.openFiles = [file(), file()];
+ comp.$store.state.openFiles.forEach(f => Object.assign(f, {
+ changed: true,
+ content: 'testing',
+ }));
+
+ return comp.$mount();
}
- it('renders a commit section', () => {
- RepoStore.isCommitable = true;
- RepoStore.currentBranch = branch;
- RepoStore.targetBranch = branch;
- RepoStore.openedFiles = openedFiles;
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
- const vm = createComponent();
+ it('renders a commit section', () => {
const changedFileElements = [...vm.$el.querySelectorAll('.changed-files > li')];
- const commitMessage = vm.$el.querySelector('#commit-message');
- const submitCommit = vm.$refs.submitCommit;
+ const submitCommit = vm.$el.querySelector('.btn');
const targetBranch = vm.$el.querySelector('.target-branch');
expect(vm.$el.querySelector(':scope > form')).toBeTruthy();
@@ -51,109 +45,70 @@ describe('RepoCommitSection', () => {
expect(changedFileElements.length).toEqual(2);
changedFileElements.forEach((changedFile, i) => {
- expect(changedFile.textContent.trim()).toEqual(changedFiles[i].path);
+ expect(changedFile.textContent.trim()).toEqual(vm.$store.getters.changedFiles[i].path);
});
- expect(commitMessage.tagName).toEqual('TEXTAREA');
- expect(commitMessage.name).toEqual('commit-message');
- expect(submitCommit.type).toEqual('submit');
expect(submitCommit.disabled).toBeTruthy();
expect(submitCommit.querySelector('.fa-spinner.fa-spin')).toBeFalsy();
expect(vm.$el.querySelector('.commit-summary').textContent.trim()).toEqual('Commit 2 files');
expect(targetBranch.querySelector(':scope > label').textContent.trim()).toEqual('Target branch');
- expect(targetBranch.querySelector('.help-block').textContent.trim()).toEqual(branch);
+ expect(targetBranch.querySelector('.help-block').textContent.trim()).toEqual('master');
});
- it('does not render if not isCommitable', () => {
- RepoStore.isCommitable = false;
- RepoStore.openedFiles = [{
- id: 0,
- changed: true,
- }];
+ describe('when submitting', () => {
+ let changedFiles;
- const vm = createComponent();
+ beforeEach(() => {
+ vm.commitMessage = 'testing';
+ changedFiles = JSON.parse(JSON.stringify(vm.$store.getters.changedFiles));
- expect(vm.$el.innerHTML).toBeFalsy();
- });
+ spyOn(service, 'commit').and.returnValue(Promise.resolve({
+ short_id: '1',
+ stats: {},
+ }));
+ });
- it('does not render if no changedFiles', () => {
- RepoStore.isCommitable = true;
- RepoStore.openedFiles = [];
+ it('allows you to submit', () => {
+ expect(vm.$el.querySelector('.btn').disabled).toBeTruthy();
+ });
- const vm = createComponent();
+ it('submits commit', (done) => {
+ vm.makeCommit();
+
+ // Wait for the branch check to finish
+ getSetTimeoutPromise()
+ .then(() => Vue.nextTick())
+ .then(() => {
+ const args = service.commit.calls.allArgs()[0];
+ const { commit_message, actions, branch: payloadBranch } = args[1];
+
+ expect(commit_message).toBe('testing');
+ expect(actions.length).toEqual(2);
+ expect(payloadBranch).toEqual('master');
+ expect(actions[0].action).toEqual('update');
+ expect(actions[1].action).toEqual('update');
+ expect(actions[0].content).toEqual(changedFiles[0].content);
+ expect(actions[1].content).toEqual(changedFiles[1].content);
+ expect(actions[0].file_path).toEqual(changedFiles[0].path);
+ expect(actions[1].file_path).toEqual(changedFiles[1].path);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
- expect(vm.$el.innerHTML).toBeFalsy();
- });
+ it('redirects to MR creation page if start new MR checkbox checked', (done) => {
+ spyOn(gl.utils, 'visitUrl');
+ vm.startNewMR = true;
- it('shows commit submit and summary if commitMessage and spinner if submitCommitsLoading', (done) => {
- const projectId = 'projectId';
- const commitMessage = 'commitMessage';
- RepoStore.isCommitable = true;
- RepoStore.currentBranch = branch;
- RepoStore.targetBranch = branch;
- RepoStore.openedFiles = openedFiles;
- RepoStore.projectId = projectId;
-
- // We need to append to body to get form `submit` events working
- // Otherwise we run into, "Form submission canceled because the form is not connected"
- // See https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm
- const el = document.createElement('div');
- document.body.appendChild(el);
-
- const vm = createComponent(el);
- const commitMessageEl = vm.$el.querySelector('#commit-message');
- const submitCommit = vm.$refs.submitCommit;
-
- vm.commitMessage = commitMessage;
-
- Vue.nextTick(() => {
- expect(commitMessageEl.value).toBe(commitMessage);
- expect(submitCommit.disabled).toBeFalsy();
-
- spyOn(vm, 'makeCommit').and.callThrough();
- spyOn(RepoService, 'commitFiles').and.callFake(() => Promise.resolve());
-
- submitCommit.click();
-
- Vue.nextTick(() => {
- expect(vm.makeCommit).toHaveBeenCalled();
- expect(submitCommit.querySelector('.fa-spinner.fa-spin')).toBeTruthy();
-
- const args = RepoService.commitFiles.calls.allArgs()[0];
- const { commit_message, actions, branch: payloadBranch } = args[0];
-
- expect(commit_message).toBe(commitMessage);
- expect(actions.length).toEqual(2);
- expect(payloadBranch).toEqual(branch);
- expect(actions[0].action).toEqual('update');
- expect(actions[1].action).toEqual('update');
- expect(actions[0].content).toEqual(openedFiles[0].newContent);
- expect(actions[1].content).toEqual(openedFiles[1].newContent);
- expect(actions[0].file_path).toEqual(openedFiles[0].path);
- expect(actions[1].file_path).toEqual(openedFiles[1].path);
-
- done();
- });
- });
- });
+ vm.makeCommit();
- describe('methods', () => {
- describe('resetCommitState', () => {
- it('should reset store vars and scroll to top', () => {
- const vm = {
- submitCommitsLoading: true,
- changedFiles: new Array(10),
- commitMessage: 'commitMessage',
- editMode: true,
- };
-
- repoCommitSection.methods.resetCommitState.call(vm);
-
- expect(vm.submitCommitsLoading).toEqual(false);
- expect(vm.changedFiles).toEqual([]);
- expect(vm.commitMessage).toEqual('');
- expect(vm.editMode).toEqual(false);
- });
+ getSetTimeoutPromise()
+ .then(() => Vue.nextTick())
+ .then(() => {
+ expect(gl.utils.visitUrl).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/repo/components/repo_edit_button_spec.js b/spec/javascripts/repo/components/repo_edit_button_spec.js
index 29dc2d21e4b..44018464b35 100644
--- a/spec/javascripts/repo/components/repo_edit_button_spec.js
+++ b/spec/javascripts/repo/components/repo_edit_button_spec.js
@@ -1,51 +1,83 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoEditButton from '~/repo/components/repo_edit_button.vue';
-import RepoStore from '~/repo/stores/repo_store';
+import { file, resetStore } from '../helpers';
describe('RepoEditButton', () => {
- function createComponent() {
+ let vm;
+
+ beforeEach(() => {
+ const f = file();
const RepoEditButton = Vue.extend(repoEditButton);
- return new RepoEditButton().$mount();
- }
+ vm = new RepoEditButton({
+ store,
+ });
- it('renders an edit button that toggles the view state', (done) => {
- RepoStore.isCommitable = true;
- RepoStore.changedFiles = [];
- RepoStore.binary = false;
- RepoStore.openedFiles = [{}, {}];
+ f.active = true;
+ vm.$store.dispatch('setInitialData', {
+ canCommit: true,
+ onTopOfBranch: true,
+ });
+ vm.$store.state.openFiles.push(f);
+ });
- const vm = createComponent();
+ afterEach(() => {
+ vm.$destroy();
- expect(vm.$el.tagName).toEqual('BUTTON');
- expect(vm.$el.textContent).toMatch('Edit');
+ resetStore(vm.$store);
+ });
- spyOn(vm, 'editCancelClicked').and.callThrough();
- spyOn(vm, 'toggleProjectRefsForm');
+ it('renders an edit button', () => {
+ vm.$mount();
- vm.$el.click();
+ expect(vm.$el.querySelector('.btn')).not.toBeNull();
+ expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Edit');
+ });
+
+ it('renders edit button with cancel text', () => {
+ vm.$store.state.editMode = true;
+
+ vm.$mount();
+
+ expect(vm.$el.querySelector('.btn')).not.toBeNull();
+ expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit');
+ });
+
+ it('toggles edit mode on click', (done) => {
+ vm.$mount();
+
+ vm.$el.querySelector('.btn').click();
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.btn').textContent.trim()).toBe('Cancel edit');
- Vue.nextTick(() => {
- expect(vm.editCancelClicked).toHaveBeenCalled();
- expect(vm.toggleProjectRefsForm).toHaveBeenCalled();
- expect(vm.$el.textContent).toMatch('Cancel edit');
done();
});
});
- it('does not render if not isCommitable', () => {
- RepoStore.isCommitable = false;
+ describe('discardPopupOpen', () => {
+ beforeEach(() => {
+ vm.$store.state.discardPopupOpen = true;
+ vm.$store.state.editMode = true;
+ vm.$store.state.openFiles[0].changed = true;
- const vm = createComponent();
+ vm.$mount();
+ });
- expect(vm.$el.innerHTML).toBeUndefined();
- });
+ it('renders popup', () => {
+ expect(vm.$el.querySelector('.modal')).not.toBeNull();
+ });
+
+ it('removes all changed files', (done) => {
+ vm.$el.querySelector('.btn-warning').click();
- describe('methods', () => {
- describe('editCancelClicked', () => {
- it('sets dialog to open when there are changedFiles');
+ vm.$nextTick(() => {
+ expect(vm.$store.getters.changedFiles.length).toBe(0);
+ expect(vm.$el.querySelector('.modal')).toBeNull();
- it('toggles editMode and calls toggleBlobView');
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/repo/components/repo_editor_spec.js b/spec/javascripts/repo/components/repo_editor_spec.js
index 85d55d171f9..979d2185076 100644
--- a/spec/javascripts/repo/components/repo_editor_spec.js
+++ b/spec/javascripts/repo/components/repo_editor_spec.js
@@ -1,49 +1,56 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoEditor from '~/repo/components/repo_editor.vue';
+import { file, resetStore } from '../helpers';
describe('RepoEditor', () => {
+ let vm;
+
beforeEach(() => {
+ const f = file();
const RepoEditor = Vue.extend(repoEditor);
- this.vm = new RepoEditor().$mount();
+ vm = new RepoEditor({
+ store,
+ });
+
+ f.active = true;
+ f.tempFile = true;
+ vm.$store.state.openFiles.push(f);
+ vm.$store.getters.activeFile.html = 'testing';
+ vm.monaco = true;
+
+ vm.$mount();
});
- it('renders an ide container', (done) => {
- this.vm.openedFiles = ['idiidid'];
- this.vm.binary = false;
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+ it('renders an ide container', (done) => {
Vue.nextTick(() => {
- expect(this.vm.shouldHideEditor).toBe(false);
- expect(this.vm.$el.id).toEqual('ide');
- expect(this.vm.$el.tagName).toBe('DIV');
+ expect(vm.shouldHideEditor).toBeFalsy();
+ expect(vm.$el.textContent.trim()).toBe('');
+
done();
});
});
- describe('when there are no open files', () => {
- it('does not render the ide', (done) => {
- this.vm.openedFiles = [];
+ describe('when open file is binary and not raw', () => {
+ beforeEach((done) => {
+ vm.$store.getters.activeFile.binary = true;
- Vue.nextTick(() => {
- expect(this.vm.shouldHideEditor).toBe(true);
- expect(this.vm.$el.tagName).not.toBeDefined();
- done();
- });
+ Vue.nextTick(done);
});
- });
- describe('when open file is binary and not raw', () => {
- it('does not render the IDE', (done) => {
- this.vm.binary = true;
- this.vm.activeFile = {
- raw: false,
- };
-
- Vue.nextTick(() => {
- expect(this.vm.shouldHideEditor).toBe(true);
- expect(this.vm.$el.tagName).not.toBeDefined();
- done();
- });
+ it('does not render the IDE', () => {
+ expect(vm.shouldHideEditor).toBeTruthy();
+ });
+
+ it('shows activeFile html', () => {
+ expect(vm.$el.textContent.trim()).toBe('testing');
});
});
});
diff --git a/spec/javascripts/repo/components/repo_file_buttons_spec.js b/spec/javascripts/repo/components/repo_file_buttons_spec.js
index dfab51710c3..d6e255e4810 100644
--- a/spec/javascripts/repo/components/repo_file_buttons_spec.js
+++ b/spec/javascripts/repo/components/repo_file_buttons_spec.js
@@ -1,75 +1,49 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoFileButtons from '~/repo/components/repo_file_buttons.vue';
-import RepoStore from '~/repo/stores/repo_store';
+import { file, resetStore } from '../helpers';
describe('RepoFileButtons', () => {
+ const activeFile = file();
+ let vm;
+
function createComponent() {
const RepoFileButtons = Vue.extend(repoFileButtons);
- return new RepoFileButtons().$mount();
- }
+ activeFile.rawPath = 'test';
+ activeFile.blamePath = 'test';
+ activeFile.commitsPath = 'test';
+ activeFile.active = true;
+ store.state.openFiles.push(activeFile);
- it('renders Raw, Blame, History, Permalink and Preview toggle', () => {
- const activeFile = {
- extension: 'md',
- url: 'url',
- raw_path: 'raw_path',
- blame_path: 'blame_path',
- commits_path: 'commits_path',
- permalink: 'permalink',
- };
- const activeFileLabel = 'activeFileLabel';
- RepoStore.openedFiles = new Array(1);
- RepoStore.activeFile = activeFile;
- RepoStore.activeFileLabel = activeFileLabel;
- RepoStore.editMode = true;
- RepoStore.binary = false;
+ return new RepoFileButtons({
+ store,
+ }).$mount();
+ }
- const vm = createComponent();
- const raw = vm.$el.querySelector('.raw');
- const blame = vm.$el.querySelector('.blame');
- const history = vm.$el.querySelector('.history');
+ afterEach(() => {
+ vm.$destroy();
- expect(vm.$el.id).toEqual('repo-file-buttons');
- expect(raw.href).toMatch(`/${activeFile.raw_path}`);
- expect(raw.textContent.trim()).toEqual('Raw');
- expect(blame.href).toMatch(`/${activeFile.blame_path}`);
- expect(blame.textContent.trim()).toEqual('Blame');
- expect(history.href).toMatch(`/${activeFile.commits_path}`);
- expect(history.textContent.trim()).toEqual('History');
- expect(vm.$el.querySelector('.permalink').textContent.trim()).toEqual('Permalink');
- expect(vm.$el.querySelector('.preview').textContent.trim()).toEqual(activeFileLabel);
+ resetStore(vm.$store);
});
- it('triggers rawPreviewToggle on preview click', () => {
- const activeFile = {
- extension: 'md',
- url: 'url',
- };
- RepoStore.openedFiles = new Array(1);
- RepoStore.activeFile = activeFile;
- RepoStore.editMode = true;
-
- const vm = createComponent();
- const preview = vm.$el.querySelector('.preview');
-
- spyOn(vm, 'rawPreviewToggle');
-
- preview.click();
-
- expect(vm.rawPreviewToggle).toHaveBeenCalled();
- });
+ it('renders Raw, Blame, History, Permalink and Preview toggle', (done) => {
+ vm = createComponent();
- it('does not render preview toggle if not canPreview', () => {
- const activeFile = {
- extension: 'abcd',
- url: 'url',
- };
- RepoStore.openedFiles = new Array(1);
- RepoStore.activeFile = activeFile;
+ vm.$nextTick(() => {
+ const raw = vm.$el.querySelector('.raw');
+ const blame = vm.$el.querySelector('.blame');
+ const history = vm.$el.querySelector('.history');
- const vm = createComponent();
+ expect(raw.href).toMatch(`/${activeFile.rawPath}`);
+ expect(raw.textContent.trim()).toEqual('Raw');
+ expect(blame.href).toMatch(`/${activeFile.blamePath}`);
+ expect(blame.textContent.trim()).toEqual('Blame');
+ expect(history.href).toMatch(`/${activeFile.commitsPath}`);
+ expect(history.textContent.trim()).toEqual('History');
+ expect(vm.$el.querySelector('.permalink').textContent.trim()).toEqual('Permalink');
- expect(vm.$el.querySelector('.preview')).toBeFalsy();
+ done();
+ });
});
});
diff --git a/spec/javascripts/repo/components/repo_file_options_spec.js b/spec/javascripts/repo/components/repo_file_options_spec.js
deleted file mode 100644
index 9759b4bf12d..00000000000
--- a/spec/javascripts/repo/components/repo_file_options_spec.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import Vue from 'vue';
-import repoFileOptions from '~/repo/components/repo_file_options.vue';
-
-describe('RepoFileOptions', () => {
- const projectName = 'projectName';
-
- function createComponent(propsData) {
- const RepoFileOptions = Vue.extend(repoFileOptions);
-
- return new RepoFileOptions({
- propsData,
- }).$mount();
- }
-
- it('renders the title and new file/folder buttons if isMini is true', () => {
- const vm = createComponent({
- isMini: true,
- projectName,
- });
-
- expect(vm.$el.classList.contains('repo-file-options')).toBeTruthy();
- expect(vm.$el.querySelector('.title').textContent).toEqual(projectName);
- });
-
- it('does not render if isMini is false', () => {
- const vm = createComponent({
- isMini: false,
- projectName,
- });
-
- expect(vm.$el.innerHTML).toBeFalsy();
- });
-});
diff --git a/spec/javascripts/repo/components/repo_file_spec.js b/spec/javascripts/repo/components/repo_file_spec.js
index 518a2d25ecf..c45f8a18d1f 100644
--- a/spec/javascripts/repo/components/repo_file_spec.js
+++ b/spec/javascripts/repo/components/repo_file_spec.js
@@ -1,136 +1,115 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoFile from '~/repo/components/repo_file.vue';
+import { file, resetStore } from '../helpers';
describe('RepoFile', () => {
const updated = 'updated';
- const file = {
- icon: 'icon',
- url: 'url',
- name: 'name',
- lastCommitMessage: 'message',
- lastCommitUpdate: Date.now(),
- level: 10,
- };
- const activeFile = {
- url: 'url',
- };
+ let vm;
function createComponent(propsData) {
const RepoFile = Vue.extend(repoFile);
return new RepoFile({
+ store,
propsData,
}).$mount();
}
- beforeEach(() => {
- spyOn(repoFile.mixins[0].methods, 'timeFormated').and.returnValue(updated);
+ afterEach(() => {
+ resetStore(vm.$store);
});
it('renders link, icon, name and last commit details', () => {
- const vm = createComponent({
- file,
- activeFile,
+ const RepoFile = Vue.extend(repoFile);
+ vm = new RepoFile({
+ store,
+ propsData: {
+ file: file(),
+ },
});
+ spyOn(vm, 'timeFormated').and.returnValue(updated);
+ vm.$mount();
+
const name = vm.$el.querySelector('.repo-file-name');
const fileIcon = vm.$el.querySelector('.file-icon');
- expect(vm.$el.classList.contains('active')).toBeTruthy();
- expect(vm.$el.querySelector(`.${file.icon}`).style.marginLeft).toEqual('100px');
- expect(name.title).toEqual(file.url);
- expect(name.href).toMatch(`/${file.url}`);
- expect(name.textContent.trim()).toEqual(file.name);
- expect(vm.$el.querySelector('.commit-message').textContent.trim()).toBe(file.lastCommitMessage);
+ expect(vm.$el.querySelector(`.${vm.file.icon}`).style.marginLeft).toEqual('0px');
+ expect(name.href).toMatch(`/${vm.file.url}`);
+ expect(name.textContent.trim()).toEqual(vm.file.name);
+ expect(vm.$el.querySelector('.commit-message').textContent.trim()).toBe(vm.file.lastCommit.message);
expect(vm.$el.querySelector('.commit-update').textContent.trim()).toBe(updated);
- expect(fileIcon.classList.contains(file.icon)).toBeTruthy();
- expect(fileIcon.style.marginLeft).toEqual(`${file.level * 10}px`);
+ expect(fileIcon.classList.contains(vm.file.icon)).toBeTruthy();
+ expect(fileIcon.style.marginLeft).toEqual(`${vm.file.level * 10}px`);
});
it('does render if hasFiles is true and is loading tree', () => {
- const vm = createComponent({
- file,
- activeFile,
- loading: {
- tree: true,
- },
- hasFiles: true,
+ vm = createComponent({
+ file: file(),
});
- expect(vm.$el.innerHTML).toBeTruthy();
expect(vm.$el.querySelector('.fa-spin.fa-spinner')).toBeFalsy();
});
it('renders a spinner if the file is loading', () => {
- file.loading = true;
- const vm = createComponent({
- file,
- activeFile,
- loading: {
- tree: true,
- },
- hasFiles: true,
+ const f = file();
+ f.loading = true;
+ vm = createComponent({
+ file: f,
});
- expect(vm.$el.innerHTML).toBeTruthy();
- expect(vm.$el.querySelector('.fa-spin.fa-spinner').style.marginLeft).toEqual(`${file.level * 10}px`);
+ expect(vm.$el.querySelector('.fa-spin.fa-spinner')).not.toBeNull();
+ expect(vm.$el.querySelector('.fa-spin.fa-spinner').style.marginLeft).toEqual(`${vm.file.level * 16}px`);
});
- it('does not render if loading tree', () => {
- const vm = createComponent({
- file,
- activeFile,
- loading: {
- tree: true,
- },
+ it('does not render commit message and datetime if mini', (done) => {
+ vm = createComponent({
+ file: file(),
});
+ vm.$store.state.openFiles.push(vm.file);
- expect(vm.$el.innerHTML).toBeFalsy();
- });
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.commit-message')).toBeFalsy();
+ expect(vm.$el.querySelector('.commit-update')).toBeFalsy();
- it('does not render commit message and datetime if mini', () => {
- const vm = createComponent({
- file,
- activeFile,
- isMini: true,
+ done();
});
-
- expect(vm.$el.querySelector('.commit-message')).toBeFalsy();
- expect(vm.$el.querySelector('.commit-update')).toBeFalsy();
});
- it('does not set active class if file is active file', () => {
- const vm = createComponent({
- file,
- activeFile: {},
+ it('fires clickedTreeRow when the link is clicked', () => {
+ vm = createComponent({
+ file: file(),
});
- expect(vm.$el.classList.contains('active')).toBeFalsy();
- });
+ spyOn(vm, 'clickedTreeRow');
- it('fires linkClicked when the link is clicked', () => {
- const vm = createComponent({
- file,
- activeFile,
- });
+ vm.$el.click();
- spyOn(vm, 'linkClicked');
+ expect(vm.clickedTreeRow).toHaveBeenCalledWith(vm.file);
+ });
- vm.$el.querySelector('.repo-file-name').click();
+ describe('submodule', () => {
+ let f;
- expect(vm.linkClicked).toHaveBeenCalledWith(file);
- });
+ beforeEach(() => {
+ f = file('submodule name', '123456789');
+ f.type = 'submodule';
- describe('methods', () => {
- describe('linkClicked', () => {
- const vm = jasmine.createSpyObj('vm', ['$emit']);
+ vm = createComponent({
+ file: f,
+ });
+ });
- it('$emits linkclicked with file obj', () => {
- const theFile = {};
+ afterEach(() => {
+ vm.$destroy();
+ });
- repoFile.methods.linkClicked.call(vm, theFile);
+ it('renders submodule short ID', () => {
+ expect(vm.$el.querySelector('.commit-sha').textContent.trim()).toBe('12345678');
+ });
- expect(vm.$emit).toHaveBeenCalledWith('linkclicked', theFile);
- });
+ it('renders ID next to submodule name', () => {
+ expect(vm.$el.querySelector('td').textContent.replace(/\s+/g, ' ')).toContain('submodule name @ 12345678');
});
});
});
diff --git a/spec/javascripts/repo/components/repo_loading_file_spec.js b/spec/javascripts/repo/components/repo_loading_file_spec.js
index a030314d749..031f2a9c0b2 100644
--- a/spec/javascripts/repo/components/repo_loading_file_spec.js
+++ b/spec/javascripts/repo/components/repo_loading_file_spec.js
@@ -1,12 +1,16 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoLoadingFile from '~/repo/components/repo_loading_file.vue';
+import { resetStore } from '../helpers';
describe('RepoLoadingFile', () => {
- function createComponent(propsData) {
+ let vm;
+
+ function createComponent() {
const RepoLoadingFile = Vue.extend(repoLoadingFile);
return new RepoLoadingFile({
- propsData,
+ store,
}).$mount();
}
@@ -28,52 +32,31 @@ describe('RepoLoadingFile', () => {
});
}
- it('renders 3 columns of animated LoC', () => {
- const vm = createComponent({
- loading: {
- tree: true,
- },
- hasFiles: false,
- });
- const columns = [...vm.$el.querySelectorAll('td')];
+ afterEach(() => {
+ vm.$destroy();
- expect(columns.length).toEqual(3);
- assertColumns(columns);
+ resetStore(vm.$store);
});
- it('renders 1 column of animated LoC if isMini', () => {
- const vm = createComponent({
- loading: {
- tree: true,
- },
- hasFiles: false,
- isMini: true,
- });
+ it('renders 3 columns of animated LoC', () => {
+ vm = createComponent();
const columns = [...vm.$el.querySelectorAll('td')];
- expect(columns.length).toEqual(1);
+ expect(columns.length).toEqual(3);
assertColumns(columns);
});
- it('does not render if tree is not loading', () => {
- const vm = createComponent({
- loading: {
- tree: false,
- },
- hasFiles: false,
- });
+ it('renders 1 column of animated LoC if isMini', (done) => {
+ vm = createComponent();
+ vm.$store.state.openFiles.push('test');
- expect(vm.$el.innerHTML).toBeFalsy();
- });
+ vm.$nextTick(() => {
+ const columns = [...vm.$el.querySelectorAll('td')];
- it('does not render if hasFiles is true', () => {
- const vm = createComponent({
- loading: {
- tree: true,
- },
- hasFiles: true,
- });
+ expect(columns.length).toEqual(1);
+ assertColumns(columns);
- expect(vm.$el.innerHTML).toBeFalsy();
+ done();
+ });
});
});
diff --git a/spec/javascripts/repo/components/repo_prev_directory_spec.js b/spec/javascripts/repo/components/repo_prev_directory_spec.js
index 34dde545e6a..7f82ae36a64 100644
--- a/spec/javascripts/repo/components/repo_prev_directory_spec.js
+++ b/spec/javascripts/repo/components/repo_prev_directory_spec.js
@@ -1,43 +1,45 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoPrevDirectory from '~/repo/components/repo_prev_directory.vue';
+import { resetStore } from '../helpers';
describe('RepoPrevDirectory', () => {
- function createComponent(propsData) {
+ let vm;
+ const parentLink = 'parent';
+ function createComponent() {
const RepoPrevDirectory = Vue.extend(repoPrevDirectory);
- return new RepoPrevDirectory({
- propsData,
- }).$mount();
- }
-
- it('renders a prev dir link', () => {
- const prevUrl = 'prevUrl';
- const vm = createComponent({
- prevUrl,
+ const comp = new RepoPrevDirectory({
+ store,
});
- const link = vm.$el.querySelector('a');
- spyOn(vm, 'linkClicked');
+ comp.$store.state.parentTreeUrl = parentLink;
+
+ return comp.$mount();
+ }
- expect(link.href).toMatch(`/${prevUrl}`);
- expect(link.textContent).toEqual('..');
+ beforeEach(() => {
+ vm = createComponent();
+ });
- link.click();
+ afterEach(() => {
+ vm.$destroy();
- expect(vm.linkClicked).toHaveBeenCalledWith(prevUrl);
+ resetStore(vm.$store);
});
- describe('methods', () => {
- describe('linkClicked', () => {
- const vm = jasmine.createSpyObj('vm', ['$emit']);
+ it('renders a prev dir link', () => {
+ const link = vm.$el.querySelector('a');
+
+ expect(link.href).toMatch(`/${parentLink}`);
+ expect(link.textContent).toEqual('...');
+ });
- it('$emits linkclicked with file obj', () => {
- const file = {};
+ it('clicking row triggers getTreeData', () => {
+ spyOn(vm, 'getTreeData');
- repoPrevDirectory.methods.linkClicked.call(vm, file);
+ vm.$el.querySelector('td').click();
- expect(vm.$emit).toHaveBeenCalledWith('linkclicked', file);
- });
- });
+ expect(vm.getTreeData).toHaveBeenCalledWith({ endpoint: parentLink });
});
});
diff --git a/spec/javascripts/repo/components/repo_preview_spec.js b/spec/javascripts/repo/components/repo_preview_spec.js
index 4920cf02083..8d1a87494cf 100644
--- a/spec/javascripts/repo/components/repo_preview_spec.js
+++ b/spec/javascripts/repo/components/repo_preview_spec.js
@@ -1,23 +1,37 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoPreview from '~/repo/components/repo_preview.vue';
-import RepoStore from '~/repo/stores/repo_store';
+import { file, resetStore } from '../helpers';
describe('RepoPreview', () => {
+ let vm;
+
function createComponent() {
+ const f = file();
const RepoPreview = Vue.extend(repoPreview);
- return new RepoPreview().$mount();
+ const comp = new RepoPreview({
+ store,
+ });
+
+ f.active = true;
+ f.html = 'test';
+
+ comp.$store.state.openFiles.push(f);
+
+ return comp.$mount();
}
- it('renders a div with the activeFile html', () => {
- const activeFile = {
- html: '<p class="file-content">html</p>',
- };
- RepoStore.activeFile = activeFile;
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
- const vm = createComponent();
+ it('renders a div with the activeFile html', () => {
+ vm = createComponent();
expect(vm.$el.tagName).toEqual('DIV');
- expect(vm.$el.innerHTML).toContain(activeFile.html);
+ expect(vm.$el.innerHTML).toContain('test');
});
});
diff --git a/spec/javascripts/repo/components/repo_sidebar_spec.js b/spec/javascripts/repo/components/repo_sidebar_spec.js
index abcff8e537e..7cb4dace491 100644
--- a/spec/javascripts/repo/components/repo_sidebar_spec.js
+++ b/spec/javascripts/repo/components/repo_sidebar_spec.js
@@ -1,111 +1,75 @@
import Vue from 'vue';
-import Helper from '~/repo/helpers/repo_helper';
-import RepoService from '~/repo/services/repo_service';
-import RepoStore from '~/repo/stores/repo_store';
+import store from '~/repo/stores';
import repoSidebar from '~/repo/components/repo_sidebar.vue';
+import { file, resetStore } from '../helpers';
describe('RepoSidebar', () => {
- function createComponent() {
+ let vm;
+
+ beforeEach(() => {
const RepoSidebar = Vue.extend(repoSidebar);
- return new RepoSidebar().$mount();
- }
+ vm = new RepoSidebar({
+ store,
+ });
+
+ vm.$store.state.isRoot = true;
+ vm.$store.state.tree.push(file());
+
+ vm.$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
it('renders a sidebar', () => {
- RepoStore.files = [{
- id: 0,
- }];
- RepoStore.openedFiles = [];
- const vm = createComponent();
const thead = vm.$el.querySelector('thead');
const tbody = vm.$el.querySelector('tbody');
expect(vm.$el.id).toEqual('sidebar');
expect(vm.$el.classList.contains('sidebar-mini')).toBeFalsy();
- expect(thead.querySelector('.name').textContent).toEqual('Name');
- expect(thead.querySelector('.last-commit').textContent).toEqual('Last Commit');
- expect(thead.querySelector('.last-update').textContent).toEqual('Last Update');
+ expect(thead.querySelector('.name').textContent.trim()).toEqual('Name');
+ expect(thead.querySelector('.last-commit').textContent.trim()).toEqual('Last commit');
+ expect(thead.querySelector('.last-update').textContent.trim()).toEqual('Last update');
expect(tbody.querySelector('.repo-file-options')).toBeFalsy();
expect(tbody.querySelector('.prev-directory')).toBeFalsy();
expect(tbody.querySelector('.loading-file')).toBeFalsy();
expect(tbody.querySelector('.file')).toBeTruthy();
});
- it('does not render a thead, renders repo-file-options and sets sidebar-mini class if isMini', () => {
- RepoStore.openedFiles = [{
- id: 0,
- }];
- const vm = createComponent();
-
- expect(vm.$el.classList.contains('sidebar-mini')).toBeTruthy();
- expect(vm.$el.querySelector('thead')).toBeFalsy();
- expect(vm.$el.querySelector('tbody .repo-file-options')).toBeTruthy();
- });
+ it('does not render a thead, renders repo-file-options and sets sidebar-mini class if isMini', (done) => {
+ vm.$store.state.openFiles.push(vm.$store.state.tree[0]);
- it('renders 5 loading files if tree is loading and not hasFiles', () => {
- RepoStore.loading = {
- tree: true,
- };
- RepoStore.files = [];
- const vm = createComponent();
+ Vue.nextTick(() => {
+ expect(vm.$el.classList.contains('sidebar-mini')).toBeTruthy();
+ expect(vm.$el.querySelector('thead')).toBeTruthy();
+ expect(vm.$el.querySelector('thead .repo-file-options')).toBeTruthy();
- expect(vm.$el.querySelectorAll('tbody .loading-file').length).toEqual(5);
+ done();
+ });
});
- it('renders a prev directory if isRoot', () => {
- RepoStore.files = [{
- id: 0,
- }];
- RepoStore.isRoot = true;
- const vm = createComponent();
+ it('renders 5 loading files if tree is loading', (done) => {
+ vm.$store.state.tree = [];
+ vm.$store.state.loading = true;
- expect(vm.$el.querySelector('tbody .prev-directory')).toBeTruthy();
- });
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelectorAll('tbody .loading-file').length).toEqual(5);
- describe('methods', () => {
- describe('fileClicked', () => {
- it('should fetch data for new file', () => {
- spyOn(Helper, 'getContent').and.callThrough();
- const file1 = {
- id: 0,
- url: '',
- };
- RepoStore.files = [file1];
- RepoStore.isRoot = true;
- const vm = createComponent();
-
- vm.fileClicked(file1);
-
- expect(Helper.getContent).toHaveBeenCalledWith(file1);
- });
-
- it('should hide files in directory if already open', () => {
- spyOn(RepoStore, 'removeChildFilesOfTree').and.callThrough();
- const file1 = {
- id: 0,
- type: 'tree',
- url: '',
- opened: true,
- };
- RepoStore.files = [file1];
- RepoStore.isRoot = true;
- const vm = createComponent();
-
- vm.fileClicked(file1);
-
- expect(RepoStore.removeChildFilesOfTree).toHaveBeenCalledWith(file1);
- });
+ done();
});
+ });
- describe('goToPreviousDirectoryClicked', () => {
- it('should hide files in directory if already open', () => {
- const prevUrl = 'foo/bar';
- const vm = createComponent();
+ it('renders a prev directory if is not root', (done) => {
+ vm.$store.state.isRoot = false;
- vm.goToPreviousDirectoryClicked(prevUrl);
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('tbody .prev-directory')).toBeTruthy();
- expect(RepoService.url).toEqual(prevUrl);
- });
+ done();
});
});
});
diff --git a/spec/javascripts/repo/components/repo_spec.js b/spec/javascripts/repo/components/repo_spec.js
new file mode 100644
index 00000000000..b32d2c13af8
--- /dev/null
+++ b/spec/javascripts/repo/components/repo_spec.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import store from '~/repo/stores';
+import repo from '~/repo/components/repo.vue';
+import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
+import { file, resetStore } from '../helpers';
+
+describe('repo component', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(repo);
+
+ vm = createComponentWithStore(Component, store).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ it('does not render panel right when no files open', () => {
+ expect(vm.$el.querySelector('.panel-right')).toBeNull();
+ });
+
+ it('renders panel right when files are open', (done) => {
+ vm.$store.state.tree.push(file());
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.panel-right')).toBeNull();
+
+ done();
+ });
+ });
+});
diff --git a/spec/javascripts/repo/components/repo_tab_spec.js b/spec/javascripts/repo/components/repo_tab_spec.js
index d2a790ad73a..df0ca55aafc 100644
--- a/spec/javascripts/repo/components/repo_tab_spec.js
+++ b/spec/javascripts/repo/components/repo_tab_spec.js
@@ -1,69 +1,107 @@
import Vue from 'vue';
+import store from '~/repo/stores';
import repoTab from '~/repo/components/repo_tab.vue';
+import { file, resetStore } from '../helpers';
describe('RepoTab', () => {
+ let vm;
+
function createComponent(propsData) {
const RepoTab = Vue.extend(repoTab);
return new RepoTab({
+ store,
propsData,
}).$mount();
}
+ afterEach(() => {
+ resetStore(vm.$store);
+ });
+
it('renders a close link and a name link', () => {
- const tab = {
- url: 'url',
- name: 'name',
- };
- const vm = createComponent({
- tab,
+ vm = createComponent({
+ tab: file(),
});
- const close = vm.$el.querySelector('.close');
- const name = vm.$el.querySelector(`a[title="${tab.url}"]`);
-
- spyOn(vm, 'closeTab');
- spyOn(vm, 'tabClicked');
+ vm.$store.state.openFiles.push(vm.tab);
+ const close = vm.$el.querySelector('.close-btn');
+ const name = vm.$el.querySelector(`a[title="${vm.tab.url}"]`);
expect(close.querySelector('.fa-times')).toBeTruthy();
- expect(name.textContent.trim()).toEqual(tab.name);
+ expect(name.textContent.trim()).toEqual(vm.tab.name);
+ });
+
+ it('calls setFileActive when clicking tab', () => {
+ vm = createComponent({
+ tab: file(),
+ });
+
+ spyOn(vm, 'setFileActive');
- close.click();
- name.click();
+ vm.$el.click();
- expect(vm.closeTab).toHaveBeenCalledWith(tab);
- expect(vm.tabClicked).toHaveBeenCalledWith(tab);
+ expect(vm.setFileActive).toHaveBeenCalledWith(vm.tab);
+ });
+
+ it('calls closeFile when clicking close button', () => {
+ vm = createComponent({
+ tab: file(),
+ });
+
+ spyOn(vm, 'closeFile');
+
+ vm.$el.querySelector('.close-btn').click();
+
+ expect(vm.closeFile).toHaveBeenCalledWith({ file: vm.tab });
});
it('renders an fa-circle icon if tab is changed', () => {
- const tab = {
- url: 'url',
- name: 'name',
- changed: true,
- };
- const vm = createComponent({
+ const tab = file();
+ tab.changed = true;
+ vm = createComponent({
tab,
});
- expect(vm.$el.querySelector('.close .fa-circle')).toBeTruthy();
+ expect(vm.$el.querySelector('.close-btn .fa-circle')).toBeTruthy();
});
describe('methods', () => {
describe('closeTab', () => {
- const vm = jasmine.createSpyObj('vm', ['$emit']);
+ it('does not close tab if is changed', (done) => {
+ const tab = file();
+ tab.changed = true;
+ tab.opened = true;
+ vm = createComponent({
+ tab,
+ });
+ vm.$store.state.openFiles.push(tab);
+ vm.$store.dispatch('setFileActive', tab);
+
+ vm.$el.querySelector('.close-btn').click();
- it('returns undefined and does not $emit if file is changed', () => {
- const file = { changed: true };
- const returnVal = repoTab.methods.closeTab.call(vm, file);
+ vm.$nextTick(() => {
+ expect(tab.opened).toBeTruthy();
- expect(returnVal).toBeUndefined();
- expect(vm.$emit).not.toHaveBeenCalled();
+ done();
+ });
});
- it('$emits tabclosed event with file obj', () => {
- const file = { changed: false };
- repoTab.methods.closeTab.call(vm, file);
+ it('closes tab when clicking close btn', (done) => {
+ const tab = file('lose');
+ tab.opened = true;
+ vm = createComponent({
+ tab,
+ });
+ vm.$store.state.openFiles.push(tab);
+ vm.$store.dispatch('setFileActive', tab);
+
+ vm.$el.querySelector('.close-btn').click();
+
+ vm.$nextTick(() => {
+ expect(tab.opened).toBeFalsy();
- expect(vm.$emit).toHaveBeenCalledWith('tabclosed', file);
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/repo/components/repo_tabs_spec.js b/spec/javascripts/repo/components/repo_tabs_spec.js
index a02b54efafc..d0246cc72e6 100644
--- a/spec/javascripts/repo/components/repo_tabs_spec.js
+++ b/spec/javascripts/repo/components/repo_tabs_spec.js
@@ -1,45 +1,38 @@
import Vue from 'vue';
-import RepoStore from '~/repo/stores/repo_store';
+import store from '~/repo/stores';
import repoTabs from '~/repo/components/repo_tabs.vue';
+import { file, resetStore } from '../helpers';
describe('RepoTabs', () => {
- const openedFiles = [{
- id: 0,
- active: true,
- }, {
- id: 1,
- }];
+ const openedFiles = [file(), file()];
+ let vm;
function createComponent() {
const RepoTabs = Vue.extend(repoTabs);
- return new RepoTabs().$mount();
+ return new RepoTabs({
+ store,
+ }).$mount();
}
- it('renders a list of tabs', () => {
- RepoStore.openedFiles = openedFiles;
-
- const vm = createComponent();
- const tabs = [...vm.$el.querySelectorAll(':scope > li')];
-
- expect(vm.$el.id).toEqual('tabs');
- expect(tabs.length).toEqual(3);
- expect(tabs[0].classList.contains('active')).toBeTruthy();
- expect(tabs[1].classList.contains('active')).toBeFalsy();
- expect(tabs[2].classList.contains('tabs-divider')).toBeTruthy();
+ afterEach(() => {
+ resetStore(vm.$store);
});
- describe('methods', () => {
- describe('tabClosed', () => {
- it('calls removeFromOpenedFiles with file obj', () => {
- const file = {};
+ it('renders a list of tabs', (done) => {
+ vm = createComponent();
+ openedFiles[0].active = true;
+ vm.$store.state.openFiles = openedFiles;
- spyOn(RepoStore, 'removeFromOpenedFiles');
+ vm.$nextTick(() => {
+ const tabs = [...vm.$el.querySelectorAll(':scope > li')];
- repoTabs.methods.tabClosed(file);
+ expect(tabs.length).toEqual(3);
+ expect(tabs[0].classList.contains('active')).toBeTruthy();
+ expect(tabs[1].classList.contains('active')).toBeFalsy();
+ expect(tabs[2].classList.contains('tabs-divider')).toBeTruthy();
- expect(RepoStore.removeFromOpenedFiles).toHaveBeenCalledWith(file);
- });
+ done();
});
});
});
diff --git a/spec/javascripts/repo/helpers.js b/spec/javascripts/repo/helpers.js
new file mode 100644
index 00000000000..376c291c64b
--- /dev/null
+++ b/spec/javascripts/repo/helpers.js
@@ -0,0 +1,20 @@
+import { decorateData } from '~/repo/stores/utils';
+import state from '~/repo/stores/state';
+
+export const resetStore = (store) => {
+ store.replaceState(state());
+};
+
+export const file = (name = 'name', id = name, type = '') => decorateData({
+ id,
+ type,
+ icon: 'icon',
+ url: 'url',
+ name,
+ path: name,
+ last_commit: {
+ id: '123',
+ message: 'test',
+ committed_date: new Date().toISOString(),
+ },
+});
diff --git a/spec/javascripts/repo/services/repo_service_spec.js b/spec/javascripts/repo/services/repo_service_spec.js
deleted file mode 100644
index 6f530770525..00000000000
--- a/spec/javascripts/repo/services/repo_service_spec.js
+++ /dev/null
@@ -1,171 +0,0 @@
-import axios from 'axios';
-import RepoService from '~/repo/services/repo_service';
-import RepoStore from '~/repo/stores/repo_store';
-import Api from '~/api';
-
-describe('RepoService', () => {
- it('has default json format param', () => {
- expect(RepoService.options.params.format).toBe('json');
- });
-
- describe('buildParams', () => {
- let newParams;
- const url = 'url';
-
- beforeEach(() => {
- newParams = {};
-
- spyOn(Object, 'assign').and.returnValue(newParams);
- });
-
- it('clones params', () => {
- const params = RepoService.buildParams(url);
-
- expect(Object.assign).toHaveBeenCalledWith({}, RepoService.options.params);
-
- expect(params).toBe(newParams);
- });
-
- it('sets and returns viewer params to richif urlIsRichBlob is true', () => {
- spyOn(RepoService, 'urlIsRichBlob').and.returnValue(true);
-
- const params = RepoService.buildParams(url);
-
- expect(params.viewer).toEqual('rich');
- });
-
- it('returns params urlIsRichBlob is false', () => {
- spyOn(RepoService, 'urlIsRichBlob').and.returnValue(false);
-
- const params = RepoService.buildParams(url);
-
- expect(params.viewer).toBeUndefined();
- });
-
- it('calls urlIsRichBlob with the objects url prop if no url arg is provided', () => {
- spyOn(RepoService, 'urlIsRichBlob');
- RepoService.url = url;
-
- RepoService.buildParams();
-
- expect(RepoService.urlIsRichBlob).toHaveBeenCalledWith(url);
- });
- });
-
- describe('urlIsRichBlob', () => {
- it('returns true for md extension', () => {
- const isRichBlob = RepoService.urlIsRichBlob('url.md');
-
- expect(isRichBlob).toBeTruthy();
- });
-
- it('returns false for js extension', () => {
- const isRichBlob = RepoService.urlIsRichBlob('url.js');
-
- expect(isRichBlob).toBeFalsy();
- });
- });
-
- describe('getContent', () => {
- const params = {};
- const url = 'url';
- const requestPromise = Promise.resolve();
-
- beforeEach(() => {
- spyOn(RepoService, 'buildParams').and.returnValue(params);
- spyOn(axios, 'get').and.returnValue(requestPromise);
- });
-
- it('calls buildParams and axios.get', () => {
- const request = RepoService.getContent(url);
-
- expect(RepoService.buildParams).toHaveBeenCalledWith(url);
- expect(axios.get).toHaveBeenCalledWith(url, {
- params,
- });
- expect(request).toBe(requestPromise);
- });
-
- it('uses object url prop if no url arg is provided', () => {
- RepoService.url = url;
-
- RepoService.getContent();
-
- expect(axios.get).toHaveBeenCalledWith(url, {
- params,
- });
- });
- });
-
- describe('getBase64Content', () => {
- const url = 'url';
- const response = { data: 'data' };
-
- beforeEach(() => {
- spyOn(RepoService, 'bufferToBase64');
- spyOn(axios, 'get').and.returnValue(Promise.resolve(response));
- });
-
- it('calls axios.get and bufferToBase64 on completion', (done) => {
- const request = RepoService.getBase64Content(url);
-
- expect(axios.get).toHaveBeenCalledWith(url, {
- responseType: 'arraybuffer',
- });
- expect(request).toEqual(jasmine.any(Promise));
-
- request.then(() => {
- expect(RepoService.bufferToBase64).toHaveBeenCalledWith(response.data);
- done();
- }).catch(done.fail);
- });
- });
-
- describe('commitFiles', () => {
- it('calls commitMultiple and .then commitFlash', (done) => {
- const projectId = 'projectId';
- const payload = {};
- RepoStore.projectId = projectId;
-
- spyOn(Api, 'commitMultiple').and.returnValue(Promise.resolve());
- spyOn(RepoService, 'commitFlash');
-
- const apiPromise = RepoService.commitFiles(payload);
-
- expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, payload);
-
- apiPromise.then(() => {
- expect(RepoService.commitFlash).toHaveBeenCalled();
- done();
- }).catch(done.fail);
- });
- });
-
- describe('commitFlash', () => {
- it('calls Flash with data.message', () => {
- const data = {
- message: 'message',
- };
- spyOn(window, 'Flash');
-
- RepoService.commitFlash(data);
-
- expect(window.Flash).toHaveBeenCalledWith(data.message);
- });
-
- it('calls Flash with success string if short_id and stats', () => {
- const data = {
- short_id: 'short_id',
- stats: {
- additions: '4',
- deletions: '5',
- },
- };
- spyOn(window, 'Flash');
-
- RepoService.commitFlash(data);
-
- expect(window.Flash).toHaveBeenCalledWith(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
- });
- });
-});