Commit b80c7551 authored by Mike Greiling's avatar Mike Greiling Committed by Clement Ho

EE Port of "Add some way to mock and spy on default ES modules"

parent 4b542c17
{ {
"presets": [["latest", { "es2015": { "modules": false } }], "stage-2"], "presets": [["latest", { "es2015": { "modules": false } }], "stage-2"],
"env": { "env": {
"karma": {
"plugins": ["rewire"]
},
"coverage": { "coverage": {
"plugins": [ "plugins": [
[ [
...@@ -14,7 +17,8 @@ ...@@ -14,7 +17,8 @@
{ {
"process.env.BABEL_ENV": "coverage" "process.env.BABEL_ENV": "coverage"
} }
] ],
"rewire"
] ]
} }
} }
......
...@@ -141,3 +141,6 @@ export * from './actions/tree'; ...@@ -141,3 +141,6 @@ export * from './actions/tree';
export * from './actions/file'; export * from './actions/file';
export * from './actions/project'; export * from './actions/project';
export * from './actions/merge_request'; export * from './actions/merge_request';
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -43,3 +43,6 @@ export const collapseButtonTooltip = state => ...@@ -43,3 +43,6 @@ export const collapseButtonTooltip = state =>
export const hasMergeRequest = state => !!state.currentMergeRequestId; export const hasMergeRequest = state => !!state.currentMergeRequestId;
export const getStagedFile = state => path => state.stagedFiles.find(f => f.path === path); export const getStagedFile = state => path => state.stagedFiles.find(f => f.path === path);
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -185,3 +185,6 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState }) = ...@@ -185,3 +185,6 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState }) =
commit(types.UPDATE_LOADING, false); commit(types.UPDATE_LOADING, false);
}); });
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -27,3 +27,6 @@ export const branchName = (state, getters, rootState) => { ...@@ -27,3 +27,6 @@ export const branchName = (state, getters, rootState) => {
return rootState.currentBranchId; return rootState.currentBranchId;
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -315,3 +315,6 @@ export const scrollToNoteIfNeeded = (context, el) => { ...@@ -315,3 +315,6 @@ export const scrollToNoteIfNeeded = (context, el) => {
scrollToElement(el); scrollToElement(el);
} }
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -68,3 +68,6 @@ export const resolvedDiscussionCount = (state, getters) => { ...@@ -68,3 +68,6 @@ export const resolvedDiscussionCount = (state, getters) => {
return Object.keys(resolvedMap).length; return Object.keys(resolvedMap).length;
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -35,3 +35,6 @@ export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destr ...@@ -35,3 +35,6 @@ export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destr
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data); export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING); export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
export const isLoading = state => state.isLoading; export const isLoading = state => state.isLoading;
export const repos = state => state.repos; export const repos = state => state.repos;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -33,7 +33,7 @@ webpackConfig.plugins.push( ...@@ -33,7 +33,7 @@ webpackConfig.plugins.push(
}) })
); );
webpackConfig.devtool = 'cheap-inline-source-map'; webpackConfig.devtool = process.env.BABEL_ENV !== 'coverage' && 'cheap-inline-source-map';
// Karma configuration // Karma configuration
module.exports = function(config) { module.exports = function(config) {
......
...@@ -126,13 +126,51 @@ it('tests a promise rejection', (done) => { ...@@ -126,13 +126,51 @@ it('tests a promise rejection', (done) => {
}); });
``` ```
#### Stubbing #### Stubbing and Mocking
For unit tests, you should stub methods that are unrelated to the current unit you are testing. Jasmine provides useful helpers `spyOn`, `spyOnProperty`, `jasmine.createSpy`,
If you need to use a prototype method, instantiate an instance of the class and call it there instead of mocking the instance completely. and `jasmine.createSpyObject` to facilitate replacing methods with dummy
placeholders, and recalling when they are called and the arguments that are
passed to them. These tools should be used liberally, to test for expected
behavior, to mock responses, and to block unwanted side effects (such as a
method that would generate a network request or alter `window.location`). The
documentation for these methods can be found in the [jasmine introduction page](https://jasmine.github.io/2.0/introduction.html#section-Spies).
For integration tests, you should stub methods that will effect the stability of the test if they Sometimes you may need to spy on a method that is directly imported by another
execute their original behaviour. i.e. Network requests. module. GitLab has a custom `spyOnDependency` method which utilizes
[babel-plugin-rewire](https://github.com/speedskater/babel-plugin-rewire) to
achieve this. It can be used like so:
```javascript
// my_module.js
import { visitUrl } from '~/lib/utils/url_utility';
export default function doSomething() {
visitUrl('/foo/bar');
}
// my_module_spec.js
import doSomething from '~/my_module';
describe('my_module', () => {
it('does something', () => {
const visitUrl = spyOnDependency(doSomething, 'visitUrl');
doSomething();
expect(visitUrl).toHaveBeenCalledWith('/foo/bar');
});
});
```
Unlike `spyOn`, `spyOnDependency` expects its first parameter to be the default
export of a module who's import you want to stub, rather than an object which
contains a method you wish to stub (if the module does not have a default
export, one is be generated by the babel plugin). The second parameter is the
name of the import you wish to change. The result of the function is a Spy
object which can be treated like any other jasmine spy object.
Further documentation on the babel rewire pluign API can be found on
[its repository Readme doc](https://github.com/speedskater/babel-plugin-rewire#babel-plugin-rewire).
### Vue.js unit tests ### Vue.js unit tests
......
...@@ -153,3 +153,6 @@ export const fetchDependencyScanningReports = ({ state, dispatch }) => { ...@@ -153,3 +153,6 @@ export const fetchDependencyScanningReports = ({ state, dispatch }) => {
dispatch('receiveDependencyScanningError'); dispatch('receiveDependencyScanningError');
}); });
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -192,3 +192,6 @@ export const anyReportHasIssues = state => ...@@ -192,3 +192,6 @@ export const anyReportHasIssues = state =>
state.dast.newIssues.length > 0 || state.dast.newIssues.length > 0 ||
state.sastContainer.newIssues.length > 0 || state.sastContainer.newIssues.length > 0 ||
state.dependencyScanning.newIssues.length > 0; state.dependencyScanning.newIssues.length > 0;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
"eslint": "eslint --max-warnings 0 --ext .js,.vue .", "eslint": "eslint --max-warnings 0 --ext .js,.vue .",
"eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .", "eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .", "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .",
"karma": "karma start --single-run true config/karma.config.js", "karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js", "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "karma start config/karma.config.js", "karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
"prettier-staged": "node ./scripts/frontend/prettier.js", "prettier-staged": "node ./scripts/frontend/prettier.js",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save", "prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all", "prettier-all": "node ./scripts/frontend/prettier.js check-all",
...@@ -100,6 +100,9 @@ ...@@ -100,6 +100,9 @@
"axios-mock-adapter": "^1.10.0", "axios-mock-adapter": "^1.10.0",
"babel-eslint": "^8.0.2", "babel-eslint": "^8.0.2",
"babel-plugin-istanbul": "^4.1.5", "babel-plugin-istanbul": "^4.1.5",
"babel-plugin-rewire": "^1.1.0",
"babel-template": "^6.26.0",
"babel-types": "^6.26.0",
"commander": "^2.15.1", "commander": "^2.15.1",
"eslint": "^3.18.0", "eslint": "^3.18.0",
"eslint-config-airbnb-base": "^10.0.1", "eslint-config-airbnb-base": "^10.0.1",
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
"sandbox": false, "sandbox": false,
"setFixtures": false, "setFixtures": false,
"setStyleFixtures": false, "setStyleFixtures": false,
"spyOnDependency": false,
"spyOnEvent": false, "spyOnEvent": false,
"ClassSpecHelper": false "ClassSpecHelper": false
}, },
......
import Vue from 'vue'; import Vue from 'vue';
import addGitlabSlackApplication from 'ee/add_gitlab_slack_application/components/add_gitlab_slack_application.vue'; import addGitlabSlackApplication from 'ee/add_gitlab_slack_application/components/add_gitlab_slack_application.vue';
import GitlabSlackService from 'ee/add_gitlab_slack_application/services/gitlab_slack_service'; import GitlabSlackService from 'ee/add_gitlab_slack_application/services/gitlab_slack_service';
import * as UrlUtility from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('AddGitlabSlackApplication', () => { describe('AddGitlabSlackApplication', () => {
...@@ -113,7 +112,7 @@ describe('AddGitlabSlackApplication', () => { ...@@ -113,7 +112,7 @@ describe('AddGitlabSlackApplication', () => {
const addToSlackPromise = Promise.resolve({ data: { add_to_slack_link: redirectLink } }); const addToSlackPromise = Promise.resolve({ data: { add_to_slack_link: redirectLink } });
spyOn(GitlabSlackService, 'addToSlack').and.returnValue(addToSlackPromise); spyOn(GitlabSlackService, 'addToSlack').and.returnValue(addToSlackPromise);
spyOn(UrlUtility, 'redirectTo'); const redirectTo = spyOnDependency(addGitlabSlackApplication, 'redirectTo');
vm.popupOpen = true; vm.popupOpen = true;
...@@ -121,7 +120,7 @@ describe('AddGitlabSlackApplication', () => { ...@@ -121,7 +120,7 @@ describe('AddGitlabSlackApplication', () => {
.then(() => vm.$el.querySelector('.js-add-button').click()) .then(() => vm.$el.querySelector('.js-add-button').click())
.then(vm.$nextTick) .then(vm.$nextTick)
.then(addToSlackPromise) .then(addToSlackPromise)
.then(() => expect(UrlUtility.redirectTo).toHaveBeenCalledWith(redirectLink)) .then(() => expect(redirectTo).toHaveBeenCalledWith(redirectLink))
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
......
import $ from 'jquery'; import $ from 'jquery';
import '~/behaviors/quick_submit'; import '~/behaviors/quick_submit';
describe('Quick Submit behavior', () => { describe('Quick Submit behavior', function () {
const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options); const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options);
preloadFixtures('merge_requests/merge_request_with_task_list.html.raw'); preloadFixtures('merge_requests/merge_request_with_task_list.html.raw');
......
import $ from 'jquery'; import $ from 'jquery';
import BlobFileDropzone from '~/blob/blob_file_dropzone'; import BlobFileDropzone from '~/blob/blob_file_dropzone';
describe('BlobFileDropzone', () => { describe('BlobFileDropzone', function () {
preloadFixtures('blob/show.html.raw'); preloadFixtures('blob/show.html.raw');
beforeEach(() => { beforeEach(() => {
......
import CommentTypeToggle from '~/comment_type_toggle'; import CommentTypeToggle from '~/comment_type_toggle';
import * as dropLabSrc from '~/droplab/drop_lab';
import InputSetter from '~/droplab/plugins/input_setter'; import InputSetter from '~/droplab/plugins/input_setter';
describe('CommentTypeToggle', function () { describe('CommentTypeToggle', function () {
...@@ -59,14 +58,14 @@ describe('CommentTypeToggle', function () { ...@@ -59,14 +58,14 @@ describe('CommentTypeToggle', function () {
this.droplab = jasmine.createSpyObj('droplab', ['init']); this.droplab = jasmine.createSpyObj('droplab', ['init']);
spyOn(dropLabSrc, 'default').and.returnValue(this.droplab); this.droplabConstructor = spyOnDependency(CommentTypeToggle, 'DropLab').and.returnValue(this.droplab);
spyOn(this.commentTypeToggle, 'setConfig').and.returnValue(this.config); spyOn(this.commentTypeToggle, 'setConfig').and.returnValue(this.config);
CommentTypeToggle.prototype.initDroplab.call(this.commentTypeToggle); CommentTypeToggle.prototype.initDroplab.call(this.commentTypeToggle);
}); });
it('should instantiate a DropLab instance', function () { it('should instantiate a DropLab instance', function () {
expect(dropLabSrc.default).toHaveBeenCalled(); expect(this.droplabConstructor).toHaveBeenCalled();
}); });
it('should set .droplab', function () { it('should set .droplab', function () {
......
...@@ -4,7 +4,7 @@ import axios from '~/lib/utils/axios_utils'; ...@@ -4,7 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue'; import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Pipelines table in Commits and Merge requests', () => { describe('Pipelines table in Commits and Merge requests', function () {
const jsonFixtureName = 'pipelines/pipelines.json'; const jsonFixtureName = 'pipelines/pipelines.json';
let pipeline; let pipeline;
let PipelinesTable; let PipelinesTable;
......
import Hook from '~/droplab/hook'; import Hook from '~/droplab/hook';
import * as dropdownSrc from '~/droplab/drop_down';
describe('Hook', function () { describe('Hook', function () {
describe('class constructor', function () { describe('class constructor', function () {
...@@ -10,7 +9,7 @@ describe('Hook', function () { ...@@ -10,7 +9,7 @@ describe('Hook', function () {
this.config = {}; this.config = {};
this.dropdown = {}; this.dropdown = {};
spyOn(dropdownSrc, 'default').and.returnValue(this.dropdown); this.dropdownConstructor = spyOnDependency(Hook, 'DropDown').and.returnValue(this.dropdown);
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config); this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
}); });
...@@ -24,7 +23,7 @@ describe('Hook', function () { ...@@ -24,7 +23,7 @@ describe('Hook', function () {
}); });
it('should call DropDown constructor', function () { it('should call DropDown constructor', function () {
expect(dropdownSrc.default).toHaveBeenCalledWith(this.list, this.config); expect(this.dropdownConstructor).toHaveBeenCalledWith(this.list, this.config);
}); });
it('should set .type', function () { it('should set .type', function () {
......
...@@ -6,7 +6,6 @@ import epicHeader from 'ee/epics/epic_show/components/epic_header.vue'; ...@@ -6,7 +6,6 @@ import epicHeader from 'ee/epics/epic_show/components/epic_header.vue';
import epicSidebar from 'ee/epics/sidebar/components/sidebar_app.vue'; import epicSidebar from 'ee/epics/sidebar/components/sidebar_app.vue';
import issuableApp from '~/issue_show/components/app.vue'; import issuableApp from '~/issue_show/components/app.vue';
import issuableAppEventHub from '~/issue_show/event_hub'; import issuableAppEventHub from '~/issue_show/event_hub';
import * as urlUtils from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import issueShowData from 'spec/issue_show/mock_data'; import issueShowData from 'spec/issue_show/mock_data';
import { props } from '../mock_data'; import { props } from '../mock_data';
...@@ -108,7 +107,7 @@ describe('EpicShowApp', () => { ...@@ -108,7 +107,7 @@ describe('EpicShowApp', () => {
const deleteIssuable = jasmine.createSpy(); const deleteIssuable = jasmine.createSpy();
issuableAppEventHub.$on('delete.issuable', deleteIssuable); issuableAppEventHub.$on('delete.issuable', deleteIssuable);
spyOn(window, 'confirm').and.returnValue(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(urlUtils, 'visitUrl').and.callFake(() => {}); spyOnDependency(issuableApp, 'visitUrl');
vm.$el.querySelector('.detail-page-header .btn-remove').click(); vm.$el.querySelector('.detail-page-header .btn-remove').click();
expect(deleteIssuable).toHaveBeenCalled(); expect(deleteIssuable).toHaveBeenCalled();
......
...@@ -2,7 +2,6 @@ import Vue from 'vue'; ...@@ -2,7 +2,6 @@ import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import newEpic from 'ee/epics/new_epic/components/new_epic.vue'; import newEpic from 'ee/epics/new_epic/components/new_epic.vue';
import * as urlUtility from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('newEpic', () => { describe('newEpic', () => {
...@@ -40,7 +39,7 @@ describe('newEpic', () => { ...@@ -40,7 +39,7 @@ describe('newEpic', () => {
describe('creating epic', () => { describe('creating epic', () => {
it('should call createEpic service', (done) => { it('should call createEpic service', (done) => {
spyOn(urlUtility, 'visitUrl').and.callFake(() => {}); spyOnDependency(newEpic, 'visitUrl').and.callFake(done);
spyOn(vm.service, 'createEpic').and.callThrough(); spyOn(vm.service, 'createEpic').and.callThrough();
vm.title = 'test'; vm.title = 'test';
...@@ -48,12 +47,11 @@ describe('newEpic', () => { ...@@ -48,12 +47,11 @@ describe('newEpic', () => {
Vue.nextTick(() => { Vue.nextTick(() => {
vm.$el.querySelector('.btn-save').click(); vm.$el.querySelector('.btn-save').click();
expect(vm.service.createEpic).toHaveBeenCalled(); expect(vm.service.createEpic).toHaveBeenCalled();
done();
}); });
}); });
it('should redirect to epic url after epic creation', (done) => { it('should redirect to epic url after epic creation', (done) => {
spyOn(urlUtility, 'visitUrl').and.callFake((url) => { spyOnDependency(newEpic, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(gl.TEST_HOST); expect(url).toEqual(gl.TEST_HOST);
done(); done();
}); });
...@@ -66,7 +64,7 @@ describe('newEpic', () => { ...@@ -66,7 +64,7 @@ describe('newEpic', () => {
}); });
it('should toggle loading button while creating', (done) => { it('should toggle loading button while creating', (done) => {
spyOn(urlUtility, 'visitUrl').and.callFake(() => {}); spyOnDependency(newEpic, 'visitUrl').and.callFake(done);
vm.title = 'test'; vm.title = 'test';
Vue.nextTick(() => { Vue.nextTick(() => {
...@@ -76,7 +74,6 @@ describe('newEpic', () => { ...@@ -76,7 +74,6 @@ describe('newEpic', () => {
expect(loadingIcon).toBeNull(); expect(loadingIcon).toBeNull();
btnSave.click(); btnSave.click();
expect(loadingIcon).toBeDefined(); expect(loadingIcon).toBeDefined();
done();
}); });
}); });
}); });
......
import * as urlUtils from '~/lib/utils/url_utility';
import * as recentSearchesStoreSrc from '~/filtered_search/stores/recent_searches_store';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service'; import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error'; import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
import RecentSearchesRoot from '~/filtered_search/recent_searches_root'; import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
...@@ -11,7 +9,7 @@ import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dro ...@@ -11,7 +9,7 @@ import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dro
import FilteredSearchManager from '~/filtered_search/filtered_search_manager'; import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper'; import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Manager', () => { describe('Filtered Search Manager', function () {
let input; let input;
let manager; let manager;
let tokensContainer; let tokensContainer;
...@@ -74,18 +72,19 @@ describe('Filtered Search Manager', () => { ...@@ -74,18 +72,19 @@ describe('Filtered Search Manager', () => {
describe('class constructor', () => { describe('class constructor', () => {
const isLocalStorageAvailable = 'isLocalStorageAvailable'; const isLocalStorageAvailable = 'isLocalStorageAvailable';
let RecentSearchesStoreSpy;
beforeEach(() => { beforeEach(() => {
spyOn(RecentSearchesService, 'isAvailable').and.returnValue(isLocalStorageAvailable); spyOn(RecentSearchesService, 'isAvailable').and.returnValue(isLocalStorageAvailable);
spyOn(recentSearchesStoreSrc, 'default');
spyOn(RecentSearchesRoot.prototype, 'render'); spyOn(RecentSearchesRoot.prototype, 'render');
RecentSearchesStoreSpy = spyOnDependency(FilteredSearchManager, 'RecentSearchesStore');
}); });
it('should instantiate RecentSearchesStore with isLocalStorageAvailable', () => { it('should instantiate RecentSearchesStore with isLocalStorageAvailable', () => {
manager = new FilteredSearchManager({ page }); manager = new FilteredSearchManager({ page });
expect(RecentSearchesService.isAvailable).toHaveBeenCalled(); expect(RecentSearchesService.isAvailable).toHaveBeenCalled();
expect(recentSearchesStoreSrc.default).toHaveBeenCalledWith({ expect(RecentSearchesStoreSpy).toHaveBeenCalledWith({
isLocalStorageAvailable, isLocalStorageAvailable,
allowedKeys: FilteredSearchTokenKeys.getKeys(), allowedKeys: FilteredSearchTokenKeys.getKeys(),
}); });
...@@ -164,7 +163,7 @@ describe('Filtered Search Manager', () => { ...@@ -164,7 +163,7 @@ describe('Filtered Search Manager', () => {
it('should search with a single word', (done) => { it('should search with a single word', (done) => {
input.value = 'searchTerm'; input.value = 'searchTerm';
spyOn(urlUtils, 'visitUrl').and.callFake((url) => { spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`); expect(url).toEqual(`${defaultParams}&search=searchTerm`);
done(); done();
}); });
...@@ -175,7 +174,7 @@ describe('Filtered Search Manager', () => { ...@@ -175,7 +174,7 @@ describe('Filtered Search Manager', () => {
it('should search with multiple words', (done) => { it('should search with multiple words', (done) => {
input.value = 'awesome search terms'; input.value = 'awesome search terms';
spyOn(urlUtils, 'visitUrl').and.callFake((url) => { spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`); expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
done(); done();
}); });
...@@ -186,7 +185,7 @@ describe('Filtered Search Manager', () => { ...@@ -186,7 +185,7 @@ describe('Filtered Search Manager', () => {
it('should search with special characters', (done) => { it('should search with special characters', (done) => {
input.value = '~!@#$%^&*()_+{}:<>,.?/'; input.value = '~!@#$%^&*()_+{}:<>,.?/';
spyOn(urlUtils, 'visitUrl').and.callFake((url) => { spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`); expect(url).toEqual(`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`);
done(); done();
}); });
...@@ -200,7 +199,7 @@ describe('Filtered Search Manager', () => { ...@@ -200,7 +199,7 @@ describe('Filtered Search Manager', () => {
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')} ${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
`); `);
spyOn(urlUtils, 'visitUrl').and.callFake((url) => { spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(`${defaultParams}&label_name[]=bug`); expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
done(); done();
}); });
......
import RecentSearchesRoot from '~/filtered_search/recent_searches_root'; import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
import * as vueSrc from 'vue';
describe('RecentSearchesRoot', () => { describe('RecentSearchesRoot', () => {
describe('render', () => { describe('render', () => {
let recentSearchesRoot; let recentSearchesRoot;
let data; let data;
let template; let template;
let VueSpy;
beforeEach(() => { beforeEach(() => {
recentSearchesRoot = { recentSearchesRoot = {
...@@ -14,7 +14,7 @@ describe('RecentSearchesRoot', () => { ...@@ -14,7 +14,7 @@ describe('RecentSearchesRoot', () => {
}, },
}; };
spyOn(vueSrc, 'default').and.callFake((options) => { VueSpy = spyOnDependency(RecentSearchesRoot, 'Vue').and.callFake((options) => {
data = options.data; data = options.data;
template = options.template; template = options.template;
}); });
...@@ -23,7 +23,7 @@ describe('RecentSearchesRoot', () => { ...@@ -23,7 +23,7 @@ describe('RecentSearchesRoot', () => {
}); });
it('should instantiate Vue', () => { it('should instantiate Vue', () => {
expect(vueSrc.default).toHaveBeenCalled(); expect(VueSpy).toHaveBeenCalled();
expect(data()).toBe(recentSearchesRoot.store.state); expect(data()).toBe(recentSearchesRoot.store.state);
expect(template).toContain(':is-local-storage-available="isLocalStorageAvailable"'); expect(template).toContain(':is-local-storage-available="isLocalStorageAvailable"');
}); });
......
/* eslint-disable comma-dangle, no-param-reassign, no-unused-expressions, max-len */ /* eslint-disable comma-dangle, no-param-reassign, no-unused-expressions, max-len */
import $ from 'jquery'; import $ from 'jquery';
import '~/gl_dropdown'; import GLDropdown from '~/gl_dropdown';
import '~/lib/utils/common_utils'; import '~/lib/utils/common_utils';
import * as urlUtils from '~/lib/utils/url_utility';
describe('glDropdown', function describeDropdown() { describe('glDropdown', function describeDropdown() {
preloadFixtures('static/gl_dropdown.html.raw'); preloadFixtures('static/gl_dropdown.html.raw');
...@@ -138,13 +137,13 @@ describe('glDropdown', function describeDropdown() { ...@@ -138,13 +137,13 @@ describe('glDropdown', function describeDropdown() {
expect(this.dropdownContainerElement).toHaveClass('open'); expect(this.dropdownContainerElement).toHaveClass('open');
const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 1)) + 0; const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 1)) + 0;
navigateWithKeys('down', randomIndex, () => { navigateWithKeys('down', randomIndex, () => {
spyOn(urlUtils, 'visitUrl').and.stub(); const visitUrl = spyOnDependency(GLDropdown, 'visitUrl').and.stub();
navigateWithKeys('enter', null, () => { navigateWithKeys('enter', null, () => {
expect(this.dropdownContainerElement).not.toHaveClass('open'); expect(this.dropdownContainerElement).not.toHaveClass('open');
const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement); const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement);
expect(link).toHaveClass('is-active'); expect(link).toHaveClass('is-active');
const linkedLocation = link.attr('href'); const linkedLocation = link.attr('href');
if (linkedLocation && linkedLocation !== '#') expect(urlUtils.visitUrl).toHaveBeenCalledWith(linkedLocation); if (linkedLocation && linkedLocation !== '#') expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
}); });
}); });
}); });
......
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import * as utils from '~/lib/utils/url_utility';
import appComponent from '~/groups/components/app.vue'; import appComponent from '~/groups/components/app.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue'; import groupItemComponent from '~/groups/components/group_item.vue';
...@@ -177,7 +176,7 @@ describe('AppComponent', () => { ...@@ -177,7 +176,7 @@ describe('AppComponent', () => {
it('should fetch groups for provided page details and update window state', (done) => { it('should fetch groups for provided page details and update window state', (done) => {
spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockGroups)); spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise(mockGroups));
spyOn(vm, 'updateGroups').and.callThrough(); spyOn(vm, 'updateGroups').and.callThrough();
spyOn(utils, 'mergeUrlParams').and.callThrough(); const mergeUrlParams = spyOnDependency(appComponent, 'mergeUrlParams').and.callThrough();
spyOn(window.history, 'replaceState'); spyOn(window.history, 'replaceState');
spyOn($, 'scrollTo'); spyOn($, 'scrollTo');
...@@ -193,7 +192,7 @@ describe('AppComponent', () => { ...@@ -193,7 +192,7 @@ describe('AppComponent', () => {
setTimeout(() => { setTimeout(() => {
expect(vm.isLoading).toBe(false); expect(vm.isLoading).toBe(false);
expect($.scrollTo).toHaveBeenCalledWith(0); expect($.scrollTo).toHaveBeenCalledWith(0);
expect(utils.mergeUrlParams).toHaveBeenCalledWith({ page: 2 }, jasmine.any(String)); expect(mergeUrlParams).toHaveBeenCalledWith({ page: 2 }, jasmine.any(String));
expect(window.history.replaceState).toHaveBeenCalledWith({ expect(window.history.replaceState).toHaveBeenCalledWith({
page: jasmine.any(String), page: jasmine.any(String),
}, jasmine.any(String), jasmine.any(String)); }, jasmine.any(String), jasmine.any(String));
......
import Vue from 'vue'; import Vue from 'vue';
import * as urlUtils from '~/lib/utils/url_utility';
import groupItemComponent from '~/groups/components/group_item.vue'; import groupItemComponent from '~/groups/components/group_item.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupFolderComponent from '~/groups/components/group_folder.vue';
import eventHub from '~/groups/event_hub'; import eventHub from '~/groups/event_hub';
...@@ -135,13 +134,13 @@ describe('GroupItemComponent', () => { ...@@ -135,13 +134,13 @@ describe('GroupItemComponent', () => {
const group = Object.assign({}, mockParentGroupItem); const group = Object.assign({}, mockParentGroupItem);
group.childrenCount = 0; group.childrenCount = 0;
const newVm = createComponent(group); const newVm = createComponent(group);
spyOn(urlUtils, 'visitUrl').and.stub(); const visitUrl = spyOnDependency(groupItemComponent, 'visitUrl').and.stub();
spyOn(eventHub, '$emit'); spyOn(eventHub, '$emit');
newVm.onClickRowGroup(event); newVm.onClickRowGroup(event);
setTimeout(() => { setTimeout(() => {
expect(eventHub.$emit).not.toHaveBeenCalled(); expect(eventHub.$emit).not.toHaveBeenCalled();
expect(urlUtils.visitUrl).toHaveBeenCalledWith(newVm.group.relativePath); expect(visitUrl).toHaveBeenCalledWith(newVm.group.relativePath);
done(); done();
}, 0); }, 0);
}); });
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import './class_spec_helper'; import './class_spec_helper';
describe('ClassSpecHelper', () => { describe('ClassSpecHelper', function () {
describe('itShouldBeAStaticMethod', () => { describe('itShouldBeAStaticMethod', () => {
beforeEach(() => { beforeEach(() => {
class TestClass { class TestClass {
......
import * as urlUtils from '~/lib/utils/url_utility'; import actions, { stageAllChanges, unstageAllChanges } from '~/ide/stores/actions';
import store from '~/ide/stores'; import store from '~/ide/stores';
import * as actions from '~/ide/stores/actions';
import * as types from '~/ide/stores/mutation_types'; import * as types from '~/ide/stores/mutation_types';
import router from '~/ide/ide_router'; import router from '~/ide/ide_router';
import { resetStore, file } from '../helpers'; import { resetStore, file } from '../helpers';
...@@ -17,12 +16,12 @@ describe('Multi-file store actions', () => { ...@@ -17,12 +16,12 @@ describe('Multi-file store actions', () => {
describe('redirectToUrl', () => { describe('redirectToUrl', () => {
it('calls visitUrl', done => { it('calls visitUrl', done => {
spyOn(urlUtils, 'visitUrl'); const visitUrl = spyOnDependency(actions, 'visitUrl');
store store
.dispatch('redirectToUrl', 'test') .dispatch('redirectToUrl', 'test')
.then(() => { .then(() => {
expect(urlUtils.visitUrl).toHaveBeenCalledWith('test'); expect(visitUrl).toHaveBeenCalledWith('test');
done(); done();
}) })
...@@ -298,7 +297,7 @@ describe('Multi-file store actions', () => { ...@@ -298,7 +297,7 @@ describe('Multi-file store actions', () => {
store.state.changedFiles.push(file(), file('new')); store.state.changedFiles.push(file(), file('new'));
testAction( testAction(
actions.stageAllChanges, stageAllChanges,
null, null,
store.state, store.state,
[ [
...@@ -316,7 +315,7 @@ describe('Multi-file store actions', () => { ...@@ -316,7 +315,7 @@ describe('Multi-file store actions', () => {
store.state.stagedFiles.push(file(), file('new')); store.state.stagedFiles.push(file(), file('new'));
testAction( testAction(
actions.unstageAllChanges, unstageAllChanges,
null, null,
store.state, store.state,
[ [
......
import actions from '~/ide/stores/actions';
import store from '~/ide/stores'; import store from '~/ide/stores';
import service from '~/ide/services'; import service from '~/ide/services';
import router from '~/ide/ide_router'; import router from '~/ide/ide_router';
import * as urlUtils from '~/lib/utils/url_utility';
import eventHub from '~/ide/eventhub'; import eventHub from '~/ide/eventhub';
import * as consts from '~/ide/stores/modules/commit/constants'; import * as consts from '~/ide/stores/modules/commit/constants';
import { resetStore, file } from 'spec/ide/helpers'; import { resetStore, file } from 'spec/ide/helpers';
...@@ -307,8 +307,10 @@ describe('IDE commit module actions', () => { ...@@ -307,8 +307,10 @@ describe('IDE commit module actions', () => {
}); });
describe('commitChanges', () => { describe('commitChanges', () => {
let visitUrl;
beforeEach(() => { beforeEach(() => {
spyOn(urlUtils, 'visitUrl'); visitUrl = spyOnDependency(actions, 'visitUrl');
document.body.innerHTML += '<div class="flash-container"></div>'; document.body.innerHTML += '<div class="flash-container"></div>';
...@@ -461,7 +463,7 @@ describe('IDE commit module actions', () => { ...@@ -461,7 +463,7 @@ describe('IDE commit module actions', () => {
store store
.dispatch('commit/commitChanges') .dispatch('commit/commitChanges')
.then(() => { .then(() => {
expect(urlUtils.visitUrl).toHaveBeenCalledWith( expect(visitUrl).toHaveBeenCalledWith(
`webUrl/merge_requests/new?merge_request[source_branch]=${ `webUrl/merge_requests/new?merge_request[source_branch]=${
store.getters['commit/newBranchName'] store.getters['commit/newBranchName']
}&merge_request[target_branch]=master`, }&merge_request[target_branch]=master`,
......
...@@ -2,7 +2,6 @@ import Vue from 'vue'; ...@@ -2,7 +2,6 @@ import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import '~/behaviors/markdown/render_gfm'; import '~/behaviors/markdown/render_gfm';
import * as urlUtils from '~/lib/utils/url_utility';
import issuableApp from '~/issue_show/components/app.vue'; import issuableApp from '~/issue_show/components/app.vue';
import eventHub from '~/issue_show/event_hub'; import eventHub from '~/issue_show/event_hub';
import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper'; import setTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
...@@ -174,7 +173,7 @@ describe('Issuable output', () => { ...@@ -174,7 +173,7 @@ describe('Issuable output', () => {
}); });
it('does not redirect if issue has not moved', (done) => { it('does not redirect if issue has not moved', (done) => {
spyOn(urlUtils, 'visitUrl'); const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => { spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
resolve({ resolve({
data: { data: {
...@@ -187,16 +186,13 @@ describe('Issuable output', () => { ...@@ -187,16 +186,13 @@ describe('Issuable output', () => {
vm.updateIssuable(); vm.updateIssuable();
setTimeout(() => { setTimeout(() => {
expect( expect(visitUrl).not.toHaveBeenCalled();
urlUtils.visitUrl,
).not.toHaveBeenCalled();
done(); done();
}); });
}); });
it('redirects if returned web_url has changed', (done) => { it('redirects if returned web_url has changed', (done) => {
spyOn(urlUtils, 'visitUrl'); const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => { spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
resolve({ resolve({
data: { data: {
...@@ -209,10 +205,7 @@ describe('Issuable output', () => { ...@@ -209,10 +205,7 @@ describe('Issuable output', () => {
vm.updateIssuable(); vm.updateIssuable();
setTimeout(() => { setTimeout(() => {
expect( expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
urlUtils.visitUrl,
).toHaveBeenCalledWith('/testing-issue-move');
done(); done();
}); });
}); });
...@@ -340,7 +333,7 @@ describe('Issuable output', () => { ...@@ -340,7 +333,7 @@ describe('Issuable output', () => {
describe('deleteIssuable', () => { describe('deleteIssuable', () => {
it('changes URL when deleted', (done) => { it('changes URL when deleted', (done) => {
spyOn(urlUtils, 'visitUrl'); const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => { spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => {
resolve({ resolve({
data: { data: {
...@@ -352,16 +345,13 @@ describe('Issuable output', () => { ...@@ -352,16 +345,13 @@ describe('Issuable output', () => {
vm.deleteIssuable(); vm.deleteIssuable();
setTimeout(() => { setTimeout(() => {
expect( expect(visitUrl).toHaveBeenCalledWith('/test');
urlUtils.visitUrl,
).toHaveBeenCalledWith('/test');
done(); done();
}); });
}); });
it('stops polling when deleting', (done) => { it('stops polling when deleting', (done) => {
spyOn(urlUtils, 'visitUrl'); spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.poll, 'stop').and.callThrough(); spyOn(vm.poll, 'stop').and.callThrough();
spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => { spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => {
resolve({ resolve({
...@@ -377,7 +367,6 @@ describe('Issuable output', () => { ...@@ -377,7 +367,6 @@ describe('Issuable output', () => {
expect( expect(
vm.poll.stop, vm.poll.stop,
).toHaveBeenCalledWith(); ).toHaveBeenCalledWith();
done(); done();
}); });
}); });
......
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import descriptionComponent from '~/issue_show/components/description.vue'; import Description from '~/issue_show/components/description.vue';
import * as taskList from '~/task_list';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('Description component', () => { describe('Description component', () => {
...@@ -17,7 +16,7 @@ describe('Description component', () => { ...@@ -17,7 +16,7 @@ describe('Description component', () => {
}; };
beforeEach(() => { beforeEach(() => {
DescriptionComponent = Vue.extend(descriptionComponent); DescriptionComponent = Vue.extend(Description);
if (!document.querySelector('.issuable-meta')) { if (!document.querySelector('.issuable-meta')) {
const metaData = document.createElement('div'); const metaData = document.createElement('div');
...@@ -82,18 +81,20 @@ describe('Description component', () => { ...@@ -82,18 +81,20 @@ describe('Description component', () => {
}); });
describe('TaskList', () => { describe('TaskList', () => {
let TaskList;
beforeEach(() => { beforeEach(() => {
vm = mountComponent(DescriptionComponent, Object.assign({}, props, { vm = mountComponent(DescriptionComponent, Object.assign({}, props, {
issuableType: 'issuableType', issuableType: 'issuableType',
})); }));
spyOn(taskList, 'default'); TaskList = spyOnDependency(Description, 'TaskList');
}); });
it('re-inits the TaskList when description changed', (done) => { it('re-inits the TaskList when description changed', (done) => {
vm.descriptionHtml = 'changed'; vm.descriptionHtml = 'changed';
setTimeout(() => { setTimeout(() => {
expect(taskList.default).toHaveBeenCalled(); expect(TaskList).toHaveBeenCalled();
done(); done();
}); });
}); });
...@@ -103,7 +104,7 @@ describe('Description component', () => { ...@@ -103,7 +104,7 @@ describe('Description component', () => {
vm.descriptionHtml = 'changed'; vm.descriptionHtml = 'changed';
setTimeout(() => { setTimeout(() => {
expect(taskList.default).not.toHaveBeenCalled(); expect(TaskList).not.toHaveBeenCalled();
done(); done();
}); });
}); });
...@@ -112,7 +113,7 @@ describe('Description component', () => { ...@@ -112,7 +113,7 @@ describe('Description component', () => {
vm.descriptionHtml = 'changed'; vm.descriptionHtml = 'changed';
setTimeout(() => { setTimeout(() => {
expect(taskList.default).toHaveBeenCalledWith({ expect(TaskList).toHaveBeenCalledWith({
dataType: 'issuableType', dataType: 'issuableType',
fieldName: 'description', fieldName: 'description',
selector: '.detail-page-description', selector: '.detail-page-description',
......
...@@ -2,7 +2,6 @@ import $ from 'jquery'; ...@@ -2,7 +2,6 @@ import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { numberToHumanSize } from '~/lib/utils/number_utils'; import { numberToHumanSize } from '~/lib/utils/number_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import '~/lib/utils/datetime_utility'; import '~/lib/utils/datetime_utility';
import Job from '~/job'; import Job from '~/job';
import '~/breakpoints'; import '~/breakpoints';
...@@ -22,7 +21,7 @@ describe('Job', () => { ...@@ -22,7 +21,7 @@ describe('Job', () => {
beforeEach(() => { beforeEach(() => {
loadFixtures('builds/build-with-artifacts.html.raw'); loadFixtures('builds/build-with-artifacts.html.raw');
spyOn(urlUtils, 'visitUrl'); spyOnDependency(Job, 'visitUrl');
response = {}; response = {};
......
import csrf from '~/lib/utils/csrf'; import csrf from '~/lib/utils/csrf';
describe('csrf', () => { describe('csrf', function () {
beforeEach(() => { beforeEach(() => {
this.tokenKey = 'X-CSRF-Token'; this.tokenKey = 'X-CSRF-Token';
this.token = 'pH1cvjnP9grx2oKlhWEDvUZnJ8x2eXsIs1qzyHkF3DugSG5yTxR76CWeEZRhML2D1IeVB7NEW0t5l/axE4iJpQ=='; this.token = 'pH1cvjnP9grx2oKlhWEDvUZnJ8x2eXsIs1qzyHkF3DugSG5yTxR76CWeEZRhML2D1IeVB7NEW0t5l/axE4iJpQ==';
......
import * as imageUtility from '~/lib/utils/image_utility'; import { isImageLoaded } from '~/lib/utils/image_utility';
describe('imageUtility', () => { describe('imageUtility', () => {
describe('isImageLoaded', () => { describe('isImageLoaded', () => {
...@@ -8,7 +8,7 @@ describe('imageUtility', () => { ...@@ -8,7 +8,7 @@ describe('imageUtility', () => {
naturalHeight: 100, naturalHeight: 100,
}; };
expect(imageUtility.isImageLoaded(element)).toEqual(false); expect(isImageLoaded(element)).toEqual(false);
}); });
it('should return false when naturalHeight = 0', () => { it('should return false when naturalHeight = 0', () => {
...@@ -17,7 +17,7 @@ describe('imageUtility', () => { ...@@ -17,7 +17,7 @@ describe('imageUtility', () => {
naturalHeight: 0, naturalHeight: 0,
}; };
expect(imageUtility.isImageLoaded(element)).toEqual(false); expect(isImageLoaded(element)).toEqual(false);
}); });
it('should return true when image.complete and naturalHeight != 0', () => { it('should return true when image.complete and naturalHeight != 0', () => {
...@@ -26,7 +26,7 @@ describe('imageUtility', () => { ...@@ -26,7 +26,7 @@ describe('imageUtility', () => {
naturalHeight: 100, naturalHeight: 100,
}; };
expect(imageUtility.isImageLoaded(element)).toEqual(true); expect(isImageLoaded(element)).toEqual(true);
}); });
}); });
}); });
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
import $ from 'jquery'; import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import MergeRequestTabs from '~/merge_request_tabs'; import MergeRequestTabs from '~/merge_request_tabs';
import '~/commit/pipelines/pipelines_bundle'; import '~/commit/pipelines/pipelines_bundle';
import '~/breakpoints'; import '~/breakpoints';
...@@ -356,7 +355,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -356,7 +355,7 @@ import 'vendor/jquery.scrollTo';
describe('with note fragment hash', () => { describe('with note fragment hash', () => {
it('should expand and scroll to linked fragment hash #note_xxx', function (done) { it('should expand and scroll to linked fragment hash #note_xxx', function (done) {
spyOn(urlUtils, 'getLocationHash').and.returnValue(noteId); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue(noteId);
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
setTimeout(() => { setTimeout(() => {
...@@ -372,7 +371,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -372,7 +371,7 @@ import 'vendor/jquery.scrollTo';
}); });
it('should gracefully ignore non-existant fragment hash', function (done) { it('should gracefully ignore non-existant fragment hash', function (done) {
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist'); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
setTimeout(() => { setTimeout(() => {
...@@ -385,7 +384,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -385,7 +384,7 @@ import 'vendor/jquery.scrollTo';
describe('with line number fragment hash', () => { describe('with line number fragment hash', () => {
it('should gracefully ignore line number fragment hash', function () { it('should gracefully ignore line number fragment hash', function () {
spyOn(urlUtils, 'getLocationHash').and.returnValue(noteLineNumId); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue(noteLineNumId);
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0); expect(noteLineNumId.length).toBeGreaterThan(0);
...@@ -422,7 +421,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -422,7 +421,7 @@ import 'vendor/jquery.scrollTo';
describe('with note fragment hash', () => { describe('with note fragment hash', () => {
it('should expand and scroll to linked fragment hash #note_xxx', function (done) { it('should expand and scroll to linked fragment hash #note_xxx', function (done) {
spyOn(urlUtils, 'getLocationHash').and.returnValue(noteId); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue(noteId);
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
...@@ -439,7 +438,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -439,7 +438,7 @@ import 'vendor/jquery.scrollTo';
}); });
it('should gracefully ignore non-existant fragment hash', function (done) { it('should gracefully ignore non-existant fragment hash', function (done) {
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist'); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
setTimeout(() => { setTimeout(() => {
...@@ -451,7 +450,7 @@ import 'vendor/jquery.scrollTo'; ...@@ -451,7 +450,7 @@ import 'vendor/jquery.scrollTo';
describe('with line number fragment hash', () => { describe('with line number fragment hash', () => {
it('should gracefully ignore line number fragment hash', function () { it('should gracefully ignore line number fragment hash', function () {
spyOn(urlUtils, 'getLocationHash').and.returnValue(noteLineNumId); spyOnDependency(MergeRequestTabs, 'getLocationHash').and.returnValue(noteLineNumId);
this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0); expect(noteLineNumId.length).toBeGreaterThan(0);
......
import MonitoringStore from '~/monitoring/stores/monitoring_store'; import MonitoringStore from '~/monitoring/stores/monitoring_store';
import MonitoringMock, { deploymentData } from './mock_data'; import MonitoringMock, { deploymentData } from './mock_data';
describe('MonitoringStore', () => { describe('MonitoringStore', function () {
this.store = new MonitoringStore(); this.store = new MonitoringStore();
this.store.storeMetrics(MonitoringMock.data); this.store.storeMetrics(MonitoringMock.data);
......
...@@ -3,7 +3,6 @@ import $ from 'jquery'; ...@@ -3,7 +3,6 @@ import $ from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import 'autosize'; import 'autosize';
import '~/gl_form'; import '~/gl_form';
import '~/lib/utils/text_utility'; import '~/lib/utils/text_utility';
...@@ -222,7 +221,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper'; ...@@ -222,7 +221,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
}); });
it('sets target when hash matches', () => { it('sets target when hash matches', () => {
spyOn(urlUtils, 'getLocationHash').and.returnValue(hash); spyOnDependency(Notes, 'getLocationHash').and.returnValue(hash);
Notes.updateNoteTargetSelector($note); Notes.updateNoteTargetSelector($note);
...@@ -231,7 +230,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper'; ...@@ -231,7 +230,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
}); });
it('unsets target when hash does not match', () => { it('unsets target when hash does not match', () => {
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_doesnotexist'); spyOnDependency(Notes, 'getLocationHash').and.returnValue('note_doesnotexist');
Notes.updateNoteTargetSelector($note); Notes.updateNoteTargetSelector($note);
...@@ -239,7 +238,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper'; ...@@ -239,7 +238,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
}); });
it('unsets target when there is not a hash fragment anymore', () => { it('unsets target when there is not a hash fragment anymore', () => {
spyOn(urlUtils, 'getLocationHash').and.returnValue(null); spyOnDependency(Notes, 'getLocationHash').and.returnValue(null);
Notes.updateNoteTargetSelector($note); Notes.updateNoteTargetSelector($note);
......
/* global fixture */
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import * as utils from '~/lib/utils/url_utility';
import Pager from '~/pager'; import Pager from '~/pager';
describe('pager', () => { describe('pager', () => {
...@@ -25,7 +23,7 @@ describe('pager', () => { ...@@ -25,7 +23,7 @@ describe('pager', () => {
it('should use current url if data-href attribute not provided', () => { it('should use current url if data-href attribute not provided', () => {
const href = `${gl.TEST_HOST}/some_list`; const href = `${gl.TEST_HOST}/some_list`;
spyOn(utils, 'removeParams').and.returnValue(href); spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init(); Pager.init();
expect(Pager.url).toBe(href); expect(Pager.url).toBe(href);
}); });
...@@ -39,9 +37,9 @@ describe('pager', () => { ...@@ -39,9 +37,9 @@ describe('pager', () => {
it('keeps extra query parameters from url', () => { it('keeps extra query parameters from url', () => {
window.history.replaceState({}, null, '?filter=test&offset=100'); window.history.replaceState({}, null, '?filter=test&offset=100');
const href = `${gl.TEST_HOST}/some_list?filter=test`; const href = `${gl.TEST_HOST}/some_list?filter=test`;
spyOn(utils, 'removeParams').and.returnValue(href); const removeParams = spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init(); Pager.init();
expect(utils.removeParams).toHaveBeenCalledWith(['limit', 'offset']); expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']);
expect(Pager.url).toEqual(href); expect(Pager.url).toEqual(href);
}); });
}); });
......
...@@ -2,7 +2,6 @@ import Vue from 'vue'; ...@@ -2,7 +2,6 @@ import Vue from 'vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue'; import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
import * as urlUtility from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
...@@ -24,7 +23,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -24,7 +23,7 @@ describe('stop_jobs_modal.vue', () => {
describe('onSubmit', () => { describe('onSubmit', () => {
it('stops jobs and redirects to overview page', (done) => { it('stops jobs and redirects to overview page', (done) => {
const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`; const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`;
const redirectSpy = spyOn(urlUtility, 'redirectTo'); const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
spyOn(axios, 'post').and.callFake((url) => { spyOn(axios, 'post').and.callFake((url) => {
expect(url).toBe(props.url); expect(url).toBe(props.url);
return Promise.resolve({ return Promise.resolve({
...@@ -44,7 +43,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -44,7 +43,7 @@ describe('stop_jobs_modal.vue', () => {
it('displays error if stopping jobs failed', (done) => { it('displays error if stopping jobs failed', (done) => {
const dummyError = new Error('stopping jobs failed'); const dummyError = new Error('stopping jobs failed');
const redirectSpy = spyOn(urlUtility, 'redirectTo'); const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
spyOn(axios, 'post').and.callFake((url) => { spyOn(axios, 'post').and.callFake((url) => {
expect(url).toBe(props.url); expect(url).toBe(props.url);
return Promise.reject(dummyError); return Promise.reject(dummyError);
......
...@@ -3,7 +3,6 @@ import Vue from 'vue'; ...@@ -3,7 +3,6 @@ import Vue from 'vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue'; import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub'; import eventHub from '~/pages/milestones/shared/event_hub';
import * as urlUtility from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
...@@ -40,7 +39,7 @@ describe('delete_milestone_modal.vue', () => { ...@@ -40,7 +39,7 @@ describe('delete_milestone_modal.vue', () => {
}, },
}); });
}); });
const redirectSpy = spyOn(urlUtility, 'redirectTo'); const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit() vm.onSubmit()
.then(() => { .then(() => {
...@@ -60,7 +59,7 @@ describe('delete_milestone_modal.vue', () => { ...@@ -60,7 +59,7 @@ describe('delete_milestone_modal.vue', () => {
eventHub.$emit.calls.reset(); eventHub.$emit.calls.reset();
return Promise.reject(dummyError); return Promise.reject(dummyError);
}); });
const redirectSpy = spyOn(urlUtility, 'redirectTo'); const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit() vm.onSubmit()
.catch((error) => { .catch((error) => {
......
...@@ -6,7 +6,7 @@ const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout); ...@@ -6,7 +6,7 @@ const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout);
const cookieKey = 'pipeline_schedules_callout_dismissed'; const cookieKey = 'pipeline_schedules_callout_dismissed';
const docsUrl = 'help/ci/scheduled_pipelines'; const docsUrl = 'help/ci/scheduled_pipelines';
describe('Pipeline Schedule Callout', () => { describe('Pipeline Schedule Callout', function () {
beforeEach(() => { beforeEach(() => {
setFixtures(` setFixtures(`
<div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div> <div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div>
......
...@@ -9,8 +9,6 @@ import Sidebar from '~/right_sidebar'; ...@@ -9,8 +9,6 @@ import Sidebar from '~/right_sidebar';
(function() { (function() {
var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState; var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState;
this.sidebar = null;
$aside = null; $aside = null;
$toggle = null; $toggle = null;
...@@ -43,7 +41,7 @@ import Sidebar from '~/right_sidebar'; ...@@ -43,7 +41,7 @@ import Sidebar from '~/right_sidebar';
beforeEach(function() { beforeEach(function() {
loadFixtures(fixtureName); loadFixtures(fixtureName);
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
this.sidebar = new Sidebar(); new Sidebar(); // eslint-disable-line no-new
$aside = $('.right-sidebar'); $aside = $('.right-sidebar');
$page = $('.layout-page'); $page = $('.layout-page');
$icon = $aside.find('i'); $icon = $aside.find('i');
......
...@@ -4,7 +4,6 @@ import $ from 'jquery'; ...@@ -4,7 +4,6 @@ import $ from 'jquery';
import '~/gl_dropdown'; import '~/gl_dropdown';
import SearchAutocomplete from '~/search_autocomplete'; import SearchAutocomplete from '~/search_autocomplete';
import '~/lib/utils/common_utils'; import '~/lib/utils/common_utils';
import * as urlUtils from '~/lib/utils/url_utility';
describe('Search autocomplete dropdown', () => { describe('Search autocomplete dropdown', () => {
var assertLinks, var assertLinks,
...@@ -129,9 +128,6 @@ describe('Search autocomplete dropdown', () => { ...@@ -129,9 +128,6 @@ describe('Search autocomplete dropdown', () => {
beforeEach(function() { beforeEach(function() {
loadFixtures('static/search_autocomplete.html.raw'); loadFixtures('static/search_autocomplete.html.raw');
// Prevent turbolinks from triggering within gl_dropdown
spyOn(urlUtils, 'visitUrl').and.returnValue(true);
window.gon = {}; window.gon = {};
window.gon.current_user_id = userId; window.gon.current_user_id = userId;
window.gon.current_username = userName; window.gon.current_username = userName;
......
import findAndFollowLink from '~/shortcuts_dashboard_navigation'; import findAndFollowLink from '~/shortcuts_dashboard_navigation';
import * as urlUtility from '~/lib/utils/url_utility';
describe('findAndFollowLink', () => { describe('findAndFollowLink', () => {
it('visits a link when the selector exists', () => { it('visits a link when the selector exists', () => {
const href = '/some/path'; const href = '/some/path';
const locationSpy = spyOn(urlUtility, 'visitUrl'); const visitUrl = spyOnDependency(findAndFollowLink, 'visitUrl');
setFixtures(`<a class="my-shortcut" href="${href}">link</a>`); setFixtures(`<a class="my-shortcut" href="${href}">link</a>`);
findAndFollowLink('.my-shortcut'); findAndFollowLink('.my-shortcut');
expect(locationSpy).toHaveBeenCalledWith(href); expect(visitUrl).toHaveBeenCalledWith(href);
}); });
it('does not throw an exception when the selector does not exist', () => { it('does not throw an exception when the selector does not exist', () => {
const locationSpy = spyOn(urlUtility, 'visitUrl'); const visitUrl = spyOnDependency(findAndFollowLink, 'visitUrl');
// this should not throw an exception // this should not throw an exception
findAndFollowLink('.this-selector-does-not-exist'); findAndFollowLink('.this-selector-does-not-exist');
expect(locationSpy).not.toHaveBeenCalled(); expect(visitUrl).not.toHaveBeenCalled();
}); });
}); });
...@@ -4,7 +4,7 @@ import ShortcutsIssuable from '~/shortcuts_issuable'; ...@@ -4,7 +4,7 @@ import ShortcutsIssuable from '~/shortcuts_issuable';
initCopyAsGFM(); initCopyAsGFM();
describe('ShortcutsIssuable', () => { describe('ShortcutsIssuable', function () {
const fixtureName = 'merge_requests/diff_comment.html.raw'; const fixtureName = 'merge_requests/diff_comment.html.raw';
preloadFixtures(fixtureName); preloadFixtures(fixtureName);
beforeEach(() => { beforeEach(() => {
......
import _ from 'underscore'; import _ from 'underscore';
import Vue from 'vue'; import Vue from 'vue';
import * as urlUtils from '~/lib/utils/url_utility';
import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store'; import SidebarStore from '~/sidebar/stores/sidebar_store';
import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarService from '~/sidebar/services/sidebar_service';
import Mock from './mock_data'; import Mock from './mock_data';
describe('Sidebar mediator', () => { describe('Sidebar mediator', function() {
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(Mock.sidebarMockInterceptor); Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
this.mediator = new SidebarMediator(Mock.mediator); this.mediator = new SidebarMediator(Mock.mediator);
...@@ -87,12 +86,12 @@ describe('Sidebar mediator', () => { ...@@ -87,12 +86,12 @@ describe('Sidebar mediator', () => {
const moveToProjectId = 7; const moveToProjectId = 7;
this.mediator.store.setMoveToProjectId(moveToProjectId); this.mediator.store.setMoveToProjectId(moveToProjectId);
spyOn(this.mediator.service, 'moveIssue').and.callThrough(); spyOn(this.mediator.service, 'moveIssue').and.callThrough();
spyOn(urlUtils, 'visitUrl'); const visitUrl = spyOnDependency(SidebarMediator, 'visitUrl');
this.mediator.moveIssue() this.mediator.moveIssue()
.then(() => { .then(() => {
expect(this.mediator.service.moveIssue).toHaveBeenCalledWith(moveToProjectId); expect(this.mediator.service.moveIssue).toHaveBeenCalledWith(moveToProjectId);
expect(urlUtils.visitUrl).toHaveBeenCalledWith('/root/some-project/issues/5'); expect(visitUrl).toHaveBeenCalledWith('/root/some-project/issues/5');
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
......
...@@ -7,7 +7,7 @@ import SidebarService from '~/sidebar/services/sidebar_service'; ...@@ -7,7 +7,7 @@ import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue'; import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
import Mock from './mock_data'; import Mock from './mock_data';
describe('SidebarMoveIssue', () => { describe('SidebarMoveIssue', function () {
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(Mock.sidebarMockInterceptor); Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
this.mediator = new SidebarMediator(Mock.mediator); this.mediator = new SidebarMediator(Mock.mediator);
......
...@@ -31,7 +31,7 @@ const PARTICIPANT_LIST = [ ...@@ -31,7 +31,7 @@ const PARTICIPANT_LIST = [
{ ...PARTICIPANT, id: 3 }, { ...PARTICIPANT, id: 3 },
]; ];
describe('Sidebar store', () => { describe('Sidebar store', function () {
beforeEach(() => { beforeEach(() => {
this.store = new SidebarStore({ this.store = new SidebarStore({
currentUser: { currentUser: {
......
/* eslint-disable jasmine/no-global-setup */ /* eslint-disable jasmine/no-global-setup, jasmine/no-unsafe-spy, no-underscore-dangle */
import $ from 'jquery'; import $ from 'jquery';
import 'vendor/jasmine-jquery'; import 'vendor/jasmine-jquery';
import '~/commons'; import '~/commons';
...@@ -54,6 +55,17 @@ window.addEventListener('unhandledrejection', event => { ...@@ -54,6 +55,17 @@ window.addEventListener('unhandledrejection', event => {
console.error(event.reason.stack || event.reason); console.error(event.reason.stack || event.reason);
}); });
// Add global function to spy on a module's dependencies via rewire
window.spyOnDependency = (module, name) => {
const dependency = module.__GetDependency__(name);
const spy = jasmine.createSpy(name, dependency);
module.__Rewire__(name, spy);
return spy;
};
// Reset any rewired modules after each test (see babel-plugin-rewire)
afterEach(__rewire_reset_all__); // eslint-disable-line
// HACK: Chrome 59 disconnects if there are too many synchronous tests in a row // HACK: Chrome 59 disconnects if there are too many synchronous tests in a row
// because it appears to lock up the thread that communicates to Karma's socket // because it appears to lock up the thread that communicates to Karma's socket
// This async beforeEach gets called on every spec and releases the JS thread long // This async beforeEach gets called on every spec and releases the JS thread long
......
import $ from 'jquery'; import $ from 'jquery';
import * as urlUtils from '~/lib/utils/url_utility';
import Todos from '~/pages/dashboard/todos/index/todos'; import Todos from '~/pages/dashboard/todos/index/todos';
import '~/lib/utils/common_utils'; import '~/lib/utils/common_utils';
...@@ -18,7 +17,7 @@ describe('Todos', () => { ...@@ -18,7 +17,7 @@ describe('Todos', () => {
it('opens the todo url', (done) => { it('opens the todo url', (done) => {
const todoLink = todoItem.dataset.url; const todoLink = todoItem.dataset.url;
spyOn(urlUtils, 'visitUrl').and.callFake((url) => { spyOnDependency(Todos, 'visitUrl').and.callFake((url) => {
expect(url).toEqual(todoLink); expect(url).toEqual(todoLink);
done(); done();
}); });
...@@ -33,7 +32,7 @@ describe('Todos', () => { ...@@ -33,7 +32,7 @@ describe('Todos', () => {
beforeEach(() => { beforeEach(() => {
metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true }); metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true });
visitUrlSpy = spyOn(urlUtils, 'visitUrl').and.callFake(() => {}); visitUrlSpy = spyOnDependency(Todos, 'visitUrl').and.callFake(() => {});
windowOpenSpy = spyOn(window, 'open').and.callFake(() => {}); windowOpenSpy = spyOn(window, 'open').and.callFake(() => {});
}); });
......
...@@ -3,7 +3,7 @@ import U2FAuthenticate from '~/u2f/authenticate'; ...@@ -3,7 +3,7 @@ import U2FAuthenticate from '~/u2f/authenticate';
import 'vendor/u2f'; import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device'; import MockU2FDevice from './mock_u2f_device';
describe('U2FAuthenticate', () => { describe('U2FAuthenticate', function () {
preloadFixtures('u2f/authenticate.html.raw'); preloadFixtures('u2f/authenticate.html.raw');
beforeEach((done) => { beforeEach((done) => {
......
...@@ -3,7 +3,7 @@ import U2FRegister from '~/u2f/register'; ...@@ -3,7 +3,7 @@ import U2FRegister from '~/u2f/register';
import 'vendor/u2f'; import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device'; import MockU2FDevice from './mock_u2f_device';
describe('U2FRegister', () => { describe('U2FRegister', function () {
preloadFixtures('u2f/register.html.raw'); preloadFixtures('u2f/register.html.raw');
beforeEach((done) => { beforeEach((done) => {
......
import Vue from 'vue'; import Vue from 'vue';
import * as urlUtils from '~/lib/utils/url_utility';
import deploymentComponent from '~/vue_merge_request_widget/components/deployment.vue'; import deploymentComponent from '~/vue_merge_request_widget/components/deployment.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service'; import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import { getTimeago } from '~/lib/utils/datetime_utility'; import { getTimeago } from '~/lib/utils/datetime_utility';
...@@ -117,13 +116,13 @@ describe('Deployment component', () => { ...@@ -117,13 +116,13 @@ describe('Deployment component', () => {
it('should show a confirm dialog and call service.stopEnvironment when confirmed', (done) => { it('should show a confirm dialog and call service.stopEnvironment when confirmed', (done) => {
spyOn(window, 'confirm').and.returnValue(true); spyOn(window, 'confirm').and.returnValue(true);
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(true)); spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(true));
spyOn(urlUtils, 'visitUrl').and.returnValue(true); const visitUrl = spyOnDependency(deploymentComponent, 'visitUrl').and.returnValue(true);
vm = mockStopEnvironment(); vm = mockStopEnvironment();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(MRWidgetService.stopEnvironment).toHaveBeenCalledWith(deploymentMockData.stop_url); expect(MRWidgetService.stopEnvironment).toHaveBeenCalledWith(deploymentMockData.stop_url);
setTimeout(() => { setTimeout(() => {
expect(urlUtils.visitUrl).toHaveBeenCalledWith(url); expect(visitUrl).toHaveBeenCalledWith(url);
done(); done();
}, 333); }, 333);
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue'; import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
import eventHub from '~/vue_merge_request_widget/event_hub'; import eventHub from '~/vue_merge_request_widget/event_hub';
import * as simplePoll from '~/lib/utils/simple_poll';
const commitMessage = 'This is the commit message'; const commitMessage = 'This is the commit message';
const commitMessageWithDescription = 'This is the commit message description'; const commitMessageWithDescription = 'This is the commit message description';
...@@ -355,9 +354,9 @@ describe('ReadyToMerge', () => { ...@@ -355,9 +354,9 @@ describe('ReadyToMerge', () => {
describe('initiateMergePolling', () => { describe('initiateMergePolling', () => {
it('should call simplePoll', () => { it('should call simplePoll', () => {
spyOn(simplePoll, 'default'); const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateMergePolling(); vm.initiateMergePolling();
expect(simplePoll.default).toHaveBeenCalled(); expect(simplePoll).toHaveBeenCalled();
}); });
}); });
...@@ -457,11 +456,11 @@ describe('ReadyToMerge', () => { ...@@ -457,11 +456,11 @@ describe('ReadyToMerge', () => {
describe('initiateRemoveSourceBranchPolling', () => { describe('initiateRemoveSourceBranchPolling', () => {
it('should emit event and call simplePoll', () => { it('should emit event and call simplePoll', () => {
spyOn(eventHub, '$emit'); spyOn(eventHub, '$emit');
spyOn(simplePoll, 'default'); const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateRemoveSourceBranchPolling(); vm.initiateRemoveSourceBranchPolling();
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]); expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
expect(simplePoll.default).toHaveBeenCalled(); expect(simplePoll).toHaveBeenCalled();
}); });
}); });
...@@ -524,18 +523,20 @@ describe('ReadyToMerge', () => { ...@@ -524,18 +523,20 @@ describe('ReadyToMerge', () => {
}); });
describe('when user can merge and can delete branch', () => { describe('when user can merge and can delete branch', () => {
let customVm;
beforeEach(() => { beforeEach(() => {
this.customVm = createComponent({ customVm = createComponent({
mr: { canRemoveSourceBranch: true }, mr: { canRemoveSourceBranch: true },
}); });
}); });
it('isRemoveSourceBranchButtonDisabled should be false', () => { it('isRemoveSourceBranchButtonDisabled should be false', () => {
expect(this.customVm.isRemoveSourceBranchButtonDisabled).toBe(false); expect(customVm.isRemoveSourceBranchButtonDisabled).toBe(false);
}); });
it('should be enabled in rendered output', () => { it('should be enabled in rendered output', () => {
const checkboxElement = this.customVm.$el.querySelector('#remove-source-branch-input'); const checkboxElement = customVm.$el.querySelector('#remove-source-branch-input');
expect(checkboxElement).not.toBeNull(); expect(checkboxElement).not.toBeNull();
}); });
}); });
......
...@@ -670,6 +670,10 @@ babel-plugin-istanbul@^4.1.5: ...@@ -670,6 +670,10 @@ babel-plugin-istanbul@^4.1.5:
istanbul-lib-instrument "^1.7.5" istanbul-lib-instrument "^1.7.5"
test-exclude "^4.1.1" test-exclude "^4.1.1"
babel-plugin-rewire@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-rewire/-/babel-plugin-rewire-1.1.0.tgz#a6b966d9d8c06c03d95dcda2eec4e2521519549b"
babel-plugin-syntax-async-functions@^6.8.0: babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0" version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment