summaryrefslogtreecommitdiff
path: root/spec/javascripts/lib
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2017-05-23 02:10:29 +0800
committerLin Jen-Shin <godfat@godfat.org>2017-05-23 02:10:29 +0800
commit1a4130d3a6cfb4956f8bb1186cc499ea549d8e18 (patch)
tree076adcb3e6f3800a1a7bbc6809839d5cb3b3f372 /spec/javascripts/lib
parent3c8a6fba67998eb17240b15db85f8d1c8aff338e (diff)
parent18a6d9c5326bc2b90a1f0cc8664d638a39885924 (diff)
downloadgitlab-ce-27377-preload-pipeline-entity.tar.gz
Merge remote-tracking branch 'upstream/master' into 27377-preload-pipeline-entity27377-preload-pipeline-entity
* upstream/master: (2534 commits) Update VERSION to 9.3.0-pre Update CHANGELOG.md for 9.2.0 removes unnecessary redundacy in usage ping doc Respect the typo as rubocop said Add a test to ensure this works on MySQL Change pipelines schedules help page path change domain to hostname in usage ping doc Fixes broken MySQL migration for retried Show password field mask while editing service settings Add notes for supported schedulers and cloud providers Move environment monitoring to environments doc Add docs for change of Cache/Artifact restore order" Avoid resource intensive login checks if password is not provided Change translation for 'coding' by 'desarrollo' for Spanish Add to docs: issues multiple assignees rename "Add emoji" and "Award emoji" to "Add reaction" where appropriate Add project and group notification settings info 32570 Fix border-bottom for project activity tab Add users endpoint to frontend API class Rename users on mysql ...
Diffstat (limited to 'spec/javascripts/lib')
-rw-r--r--spec/javascripts/lib/utils/accessor_spec.js78
-rw-r--r--spec/javascripts/lib/utils/ajax_cache_spec.js158
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js124
-rw-r--r--spec/javascripts/lib/utils/number_utility_spec.js48
-rw-r--r--spec/javascripts/lib/utils/poll_spec.js152
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js150
6 files changed, 543 insertions, 167 deletions
diff --git a/spec/javascripts/lib/utils/accessor_spec.js b/spec/javascripts/lib/utils/accessor_spec.js
new file mode 100644
index 00000000000..b768d6f2a68
--- /dev/null
+++ b/spec/javascripts/lib/utils/accessor_spec.js
@@ -0,0 +1,78 @@
+import AccessorUtilities from '~/lib/utils/accessor';
+
+describe('AccessorUtilities', () => {
+ const testError = new Error('test error');
+
+ describe('isPropertyAccessSafe', () => {
+ let base;
+
+ it('should return `true` if access is safe', () => {
+ base = { testProp: 'testProp' };
+
+ expect(AccessorUtilities.isPropertyAccessSafe(base, 'testProp')).toBe(true);
+ });
+
+ it('should return `false` if access throws an error', () => {
+ base = { get testProp() { throw testError; } };
+
+ expect(AccessorUtilities.isPropertyAccessSafe(base, 'testProp')).toBe(false);
+ });
+
+ it('should return `false` if property is undefined', () => {
+ base = {};
+
+ expect(AccessorUtilities.isPropertyAccessSafe(base, 'testProp')).toBe(false);
+ });
+ });
+
+ describe('isFunctionCallSafe', () => {
+ const base = {};
+
+ it('should return `true` if calling is safe', () => {
+ base.func = () => {};
+
+ expect(AccessorUtilities.isFunctionCallSafe(base, 'func')).toBe(true);
+ });
+
+ it('should return `false` if calling throws an error', () => {
+ base.func = () => { throw new Error('test error'); };
+
+ expect(AccessorUtilities.isFunctionCallSafe(base, 'func')).toBe(false);
+ });
+
+ it('should return `false` if function is undefined', () => {
+ base.func = undefined;
+
+ expect(AccessorUtilities.isFunctionCallSafe(base, 'func')).toBe(false);
+ });
+ });
+
+ describe('isLocalStorageAccessSafe', () => {
+ beforeEach(() => {
+ spyOn(window.localStorage, 'setItem');
+ spyOn(window.localStorage, 'removeItem');
+ });
+
+ it('should return `true` if access is safe', () => {
+ expect(AccessorUtilities.isLocalStorageAccessSafe()).toBe(true);
+ });
+
+ it('should return `false` if access to .setItem isnt safe', () => {
+ window.localStorage.setItem.and.callFake(() => { throw testError; });
+
+ expect(AccessorUtilities.isLocalStorageAccessSafe()).toBe(false);
+ });
+
+ it('should set a test item if access is safe', () => {
+ AccessorUtilities.isLocalStorageAccessSafe();
+
+ expect(window.localStorage.setItem).toHaveBeenCalledWith('isLocalStorageAccessSafe', 'true');
+ });
+
+ it('should remove the test item if access is safe', () => {
+ AccessorUtilities.isLocalStorageAccessSafe();
+
+ expect(window.localStorage.removeItem).toHaveBeenCalledWith('isLocalStorageAccessSafe');
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/ajax_cache_spec.js b/spec/javascripts/lib/utils/ajax_cache_spec.js
new file mode 100644
index 00000000000..e1747a82329
--- /dev/null
+++ b/spec/javascripts/lib/utils/ajax_cache_spec.js
@@ -0,0 +1,158 @@
+import AjaxCache from '~/lib/utils/ajax_cache';
+
+describe('AjaxCache', () => {
+ const dummyEndpoint = '/AjaxCache/dummyEndpoint';
+ const dummyResponse = {
+ important: 'dummy data',
+ };
+
+ beforeEach(() => {
+ AjaxCache.internalStorage = { };
+ AjaxCache.pendingRequests = { };
+ });
+
+ describe('get', () => {
+ it('returns undefined if cache is empty', () => {
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(undefined);
+ });
+
+ it('returns undefined if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(undefined);
+ });
+
+ it('returns matching data', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ const data = AjaxCache.get(dummyEndpoint);
+
+ expect(data).toBe(dummyResponse);
+ });
+ });
+
+ describe('hasData', () => {
+ it('returns false if cache is empty', () => {
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
+ });
+
+ it('returns false if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(false);
+ });
+
+ it('returns true if data is available', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ expect(AjaxCache.hasData(dummyEndpoint)).toBe(true);
+ });
+ });
+
+ describe('remove', () => {
+ it('does nothing if cache is empty', () => {
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage).toEqual({ });
+ });
+
+ it('does nothing if cache contains no matching data', () => {
+ AjaxCache.internalStorage['not matching'] = dummyResponse;
+
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage['not matching']).toBe(dummyResponse);
+ });
+
+ it('removes matching data', () => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+
+ AjaxCache.remove(dummyEndpoint);
+
+ expect(AjaxCache.internalStorage).toEqual({ });
+ });
+ });
+
+ describe('retrieve', () => {
+ let ajaxSpy;
+
+ beforeEach(() => {
+ spyOn(jQuery, 'ajax').and.callFake(url => ajaxSpy(url));
+ });
+
+ it('stores and returns data from Ajax call if cache is empty', (done) => {
+ ajaxSpy = (url) => {
+ expect(url).toBe(dummyEndpoint);
+ const deferred = $.Deferred();
+ deferred.resolve(dummyResponse);
+ return deferred.promise();
+ };
+
+ AjaxCache.retrieve(dummyEndpoint)
+ .then((data) => {
+ expect(data).toBe(dummyResponse);
+ expect(AjaxCache.internalStorage[dummyEndpoint]).toBe(dummyResponse);
+ })
+ .then(done)
+ .catch(fail);
+ });
+
+ it('makes no Ajax call if request is pending', () => {
+ const responseDeferred = $.Deferred();
+
+ ajaxSpy = (url) => {
+ expect(url).toBe(dummyEndpoint);
+ // neither reject nor resolve to keep request pending
+ return responseDeferred.promise();
+ };
+
+ const unexpectedResponse = data => fail(`Did not expect response: ${data}`);
+
+ AjaxCache.retrieve(dummyEndpoint)
+ .then(unexpectedResponse)
+ .catch(fail);
+
+ AjaxCache.retrieve(dummyEndpoint)
+ .then(unexpectedResponse)
+ .catch(fail);
+
+ expect($.ajax.calls.count()).toBe(1);
+ });
+
+ it('returns undefined if Ajax call fails and cache is empty', (done) => {
+ const dummyStatusText = 'exploded';
+ const dummyErrorMessage = 'server exploded';
+ ajaxSpy = (url) => {
+ expect(url).toBe(dummyEndpoint);
+ const deferred = $.Deferred();
+ deferred.reject(null, dummyStatusText, dummyErrorMessage);
+ return deferred.promise();
+ };
+
+ AjaxCache.retrieve(dummyEndpoint)
+ .then(data => fail(`Received unexpected data: ${JSON.stringify(data)}`))
+ .catch((error) => {
+ expect(error.message).toBe(`${dummyEndpoint}: ${dummyErrorMessage}`);
+ expect(error.textStatus).toBe(dummyStatusText);
+ done();
+ })
+ .catch(fail);
+ });
+
+ it('makes no Ajax call if matching data exists', (done) => {
+ AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
+ ajaxSpy = () => fail(new Error('expected no Ajax call!'));
+
+ AjaxCache.retrieve(dummyEndpoint)
+ .then((data) => {
+ expect(data).toBe(dummyResponse);
+ })
+ .then(done)
+ .catch(fail);
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 7cf39d37181..e9bffd74d90 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -1,4 +1,6 @@
-require('~/lib/utils/common_utils');
+/* eslint-disable promise/catch-or-return */
+
+import '~/lib/utils/common_utils';
(() => {
describe('common_utils', () => {
@@ -39,6 +41,16 @@ require('~/lib/utils/common_utils');
const paramsArray = gl.utils.getUrlParamsArray();
expect(paramsArray[0][0] !== '?').toBe(true);
});
+
+ it('should decode params', () => {
+ history.pushState('', '', '?label_name%5B%5D=test');
+
+ expect(
+ gl.utils.getUrlParamsArray()[0],
+ ).toBe('label_name[]=test');
+
+ history.pushState('', '', '?');
+ });
});
describe('gl.utils.handleLocationHash', () => {
@@ -46,6 +58,10 @@ require('~/lib/utils/common_utils');
spyOn(window.document, 'getElementById').and.callThrough();
});
+ afterEach(() => {
+ window.history.pushState({}, null, '');
+ });
+
function expectGetElementIdToHaveBeenCalledWith(elementId) {
expect(window.document.getElementById).toHaveBeenCalledWith(elementId);
}
@@ -75,11 +91,56 @@ require('~/lib/utils/common_utils');
});
});
+ describe('gl.utils.setParamInURL', () => {
+ afterEach(() => {
+ window.history.pushState({}, null, '');
+ });
+
+ it('should return the parameter', () => {
+ window.history.replaceState({}, null, '');
+
+ expect(gl.utils.setParamInURL('page', 156)).toBe('?page=156');
+ expect(gl.utils.setParamInURL('page', '156')).toBe('?page=156');
+ });
+
+ it('should update the existing parameter when its a number', () => {
+ window.history.pushState({}, null, '?page=15');
+
+ expect(gl.utils.setParamInURL('page', 16)).toBe('?page=16');
+ expect(gl.utils.setParamInURL('page', '16')).toBe('?page=16');
+ expect(gl.utils.setParamInURL('page', true)).toBe('?page=true');
+ });
+
+ it('should update the existing parameter when its a string', () => {
+ window.history.pushState({}, null, '?scope=all');
+
+ expect(gl.utils.setParamInURL('scope', 'finished')).toBe('?scope=finished');
+ });
+
+ it('should update the existing parameter when more than one parameter exists', () => {
+ window.history.pushState({}, null, '?scope=all&page=15');
+
+ expect(gl.utils.setParamInURL('scope', 'finished')).toBe('?scope=finished&page=15');
+ });
+
+ it('should add a new parameter to the end of the existing ones', () => {
+ window.history.pushState({}, null, '?scope=all');
+
+ expect(gl.utils.setParamInURL('page', 16)).toBe('?scope=all&page=16');
+ expect(gl.utils.setParamInURL('page', '16')).toBe('?scope=all&page=16');
+ expect(gl.utils.setParamInURL('page', true)).toBe('?scope=all&page=true');
+ });
+ });
+
describe('gl.utils.getParameterByName', () => {
beforeEach(() => {
window.history.pushState({}, null, '?scope=all&p=2');
});
+ afterEach(() => {
+ window.history.replaceState({}, null, null);
+ });
+
it('should return valid parameter', () => {
const value = gl.utils.getParameterByName('scope');
expect(value).toBe('all');
@@ -261,5 +322,66 @@ require('~/lib/utils/common_utils');
});
}, 10000);
});
+
+ describe('gl.utils.setFavicon', () => {
+ it('should set page favicon to provided favicon', () => {
+ const faviconPath = '//custom_favicon';
+ const fakeLink = {
+ setAttribute() {},
+ };
+
+ spyOn(window.document, 'getElementById').and.callFake(() => fakeLink);
+ spyOn(fakeLink, 'setAttribute').and.callFake((attr, val) => {
+ expect(attr).toEqual('href');
+ expect(val.indexOf(faviconPath) > -1).toBe(true);
+ });
+ gl.utils.setFavicon(faviconPath);
+ });
+ });
+
+ describe('gl.utils.resetFavicon', () => {
+ it('should reset page favicon to tanuki', () => {
+ const fakeLink = {
+ setAttribute() {},
+ };
+
+ spyOn(window.document, 'getElementById').and.callFake(() => fakeLink);
+ spyOn(fakeLink, 'setAttribute').and.callFake((attr, val) => {
+ expect(attr).toEqual('href');
+ expect(val).toMatch(/favicon/);
+ });
+ gl.utils.resetFavicon();
+ });
+ });
+
+ describe('gl.utils.setCiStatusFavicon', () => {
+ it('should set page favicon to CI status favicon based on provided status', () => {
+ const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1/status.json`;
+ const FAVICON_PATH = '//icon_status_success';
+ const spySetFavicon = spyOn(gl.utils, 'setFavicon').and.stub();
+ const spyResetFavicon = spyOn(gl.utils, 'resetFavicon').and.stub();
+ spyOn($, 'ajax').and.callFake(function (options) {
+ options.success({ favicon: FAVICON_PATH });
+ expect(spySetFavicon).toHaveBeenCalledWith(FAVICON_PATH);
+ options.success();
+ expect(spyResetFavicon).toHaveBeenCalled();
+ options.error();
+ expect(spyResetFavicon).toHaveBeenCalled();
+ });
+
+ gl.utils.setCiStatusFavicon(BUILD_URL);
+ });
+ });
+
+ describe('gl.utils.ajaxPost', () => {
+ it('should perform `$.ajax` call and do `POST` request', () => {
+ const requestURL = '/some/random/api';
+ const data = { keyname: 'value' };
+ const ajaxSpy = spyOn($, 'ajax').and.callFake(() => {});
+
+ gl.utils.ajaxPost(requestURL, data);
+ expect(ajaxSpy.calls.allArgs()[0][0].type).toEqual('POST');
+ });
+ });
});
})();
diff --git a/spec/javascripts/lib/utils/number_utility_spec.js b/spec/javascripts/lib/utils/number_utility_spec.js
new file mode 100644
index 00000000000..90b12c9f115
--- /dev/null
+++ b/spec/javascripts/lib/utils/number_utility_spec.js
@@ -0,0 +1,48 @@
+import { formatRelevantDigits, bytesToKiB } from '~/lib/utils/number_utils';
+
+describe('Number Utils', () => {
+ describe('formatRelevantDigits', () => {
+ it('returns an empty string when the number is NaN', () => {
+ expect(formatRelevantDigits('fail')).toBe('');
+ });
+
+ it('returns 4 decimals when there is 4 plus digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('1000.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(4);
+ expect(leftFromDecimal.length).toBe(4);
+ });
+
+ it('returns 3 decimals when there is 1 digit to the left', () => {
+ const formattedNumber = formatRelevantDigits('0.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(3);
+ expect(leftFromDecimal.length).toBe(1);
+ });
+
+ it('returns 2 decimals when there is 2 digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('10.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(2);
+ expect(leftFromDecimal.length).toBe(2);
+ });
+
+ it('returns 1 decimal when there is 3 digits to the left', () => {
+ const formattedNumber = formatRelevantDigits('100.1234567');
+ const rightFromDecimal = formattedNumber.split('.')[1];
+ const leftFromDecimal = formattedNumber.split('.')[0];
+ expect(rightFromDecimal.length).toBe(1);
+ expect(leftFromDecimal.length).toBe(3);
+ });
+ });
+
+ describe('bytesToKiB', () => {
+ it('calculates KiB for the given bytes', () => {
+ expect(bytesToKiB(1024)).toEqual(1);
+ expect(bytesToKiB(1000)).toEqual(0.9765625);
+ });
+ });
+});
diff --git a/spec/javascripts/lib/utils/poll_spec.js b/spec/javascripts/lib/utils/poll_spec.js
index e3429c2a1cb..22f30191ab9 100644
--- a/spec/javascripts/lib/utils/poll_spec.js
+++ b/spec/javascripts/lib/utils/poll_spec.js
@@ -1,140 +1,118 @@
-import Vue from 'vue';
-import VueResource from 'vue-resource';
import Poll from '~/lib/utils/poll';
-Vue.use(VueResource);
+const waitForAllCallsToFinish = (service, waitForCount, successCallback) => {
+ const timer = () => {
+ setTimeout(() => {
+ if (service.fetch.calls.count() === waitForCount) {
+ successCallback();
+ } else {
+ timer();
+ }
+ }, 0);
+ };
+
+ timer();
+};
+
+function mockServiceCall(service, response, shouldFail = false) {
+ const action = shouldFail ? Promise.reject : Promise.resolve;
+ const responseObject = response;
-class ServiceMock {
- constructor(endpoint) {
- this.service = Vue.resource(endpoint);
- }
+ if (!responseObject.headers) responseObject.headers = {};
- fetch() {
- return this.service.get();
- }
+ service.fetch.and.callFake(action.bind(Promise, responseObject));
}
describe('Poll', () => {
- let callbacks;
+ const service = jasmine.createSpyObj('service', ['fetch']);
+ const callbacks = jasmine.createSpyObj('callbacks', ['success', 'error']);
- beforeEach(() => {
- callbacks = {
- success: () => {},
- error: () => {},
- };
-
- spyOn(callbacks, 'success');
- spyOn(callbacks, 'error');
+ afterEach(() => {
+ callbacks.success.calls.reset();
+ callbacks.error.calls.reset();
+ service.fetch.calls.reset();
});
it('calls the success callback when no header for interval is provided', (done) => {
- const successInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 200 }));
- };
-
- Vue.http.interceptors.push(successInterceptor);
+ mockServiceCall(service, { status: 200 });
new Poll({
- resource: new ServiceMock('endpoint'),
+ resource: service,
method: 'fetch',
successCallback: callbacks.success,
errorCallback: callbacks.error,
}).makeRequest();
- setTimeout(() => {
+ waitForAllCallsToFinish(service, 1, () => {
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
- done();
- }, 0);
- Vue.http.interceptors = _.without(Vue.http.interceptors, successInterceptor);
+ done();
+ });
});
it('calls the error callback whe the http request returns an error', (done) => {
- const errorInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 500 }));
- };
-
- Vue.http.interceptors.push(errorInterceptor);
+ mockServiceCall(service, { status: 500 }, true);
new Poll({
- resource: new ServiceMock('endpoint'),
+ resource: service,
method: 'fetch',
successCallback: callbacks.success,
errorCallback: callbacks.error,
}).makeRequest();
- setTimeout(() => {
+ waitForAllCallsToFinish(service, 1, () => {
expect(callbacks.success).not.toHaveBeenCalled();
expect(callbacks.error).toHaveBeenCalled();
- done();
- }, 0);
- Vue.http.interceptors = _.without(Vue.http.interceptors, errorInterceptor);
+ done();
+ });
});
it('should call the success callback when the interval header is -1', (done) => {
- const intervalInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 200, headers: { 'poll-interval': -1 } }));
- };
-
- Vue.http.interceptors.push(intervalInterceptor);
+ mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } });
new Poll({
- resource: new ServiceMock('endpoint'),
+ resource: service,
method: 'fetch',
successCallback: callbacks.success,
errorCallback: callbacks.error,
- }).makeRequest();
-
- setTimeout(() => {
+ }).makeRequest().then(() => {
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
- done();
- }, 0);
- Vue.http.interceptors = _.without(Vue.http.interceptors, intervalInterceptor);
+ done();
+ }).catch(done.fail);
});
it('starts polling when http status is 200 and interval header is provided', (done) => {
- const pollInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 200, headers: { 'poll-interval': 2 } }));
- };
-
- Vue.http.interceptors.push(pollInterceptor);
-
- const service = new ServiceMock('endpoint');
- spyOn(service, 'fetch').and.callThrough();
+ mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
- new Poll({
+ const Polling = new Poll({
resource: service,
method: 'fetch',
data: { page: 1 },
successCallback: callbacks.success,
errorCallback: callbacks.error,
- }).makeRequest();
+ });
+
+ Polling.makeRequest();
+
+ waitForAllCallsToFinish(service, 2, () => {
+ Polling.stop();
- setTimeout(() => {
expect(service.fetch.calls.count()).toEqual(2);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
- done();
- }, 5);
- Vue.http.interceptors = _.without(Vue.http.interceptors, pollInterceptor);
+ done();
+ });
});
describe('stop', () => {
it('stops polling when method is called', (done) => {
- const pollInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 200, headers: { 'poll-interval': 2 } }));
- };
-
- Vue.http.interceptors.push(pollInterceptor);
-
- const service = new ServiceMock('endpoint');
- spyOn(service, 'fetch').and.callThrough();
+ mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
resource: service,
@@ -150,28 +128,19 @@ describe('Poll', () => {
Polling.makeRequest();
- setTimeout(() => {
+ waitForAllCallsToFinish(service, 1, () => {
expect(service.fetch.calls.count()).toEqual(1);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(Polling.stop).toHaveBeenCalled();
- done();
- }, 100);
- Vue.http.interceptors = _.without(Vue.http.interceptors, pollInterceptor);
+ done();
+ });
});
});
describe('restart', () => {
it('should restart polling when its called', (done) => {
- const pollInterceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), { status: 200, headers: { 'poll-interval': 2 } }));
- };
-
- Vue.http.interceptors.push(pollInterceptor);
-
- const service = new ServiceMock('endpoint');
-
- spyOn(service, 'fetch').and.callThrough();
+ mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
resource: service,
@@ -187,17 +156,20 @@ describe('Poll', () => {
});
spyOn(Polling, 'stop').and.callThrough();
+ spyOn(Polling, 'restart').and.callThrough();
Polling.makeRequest();
- setTimeout(() => {
+ waitForAllCallsToFinish(service, 2, () => {
+ Polling.stop();
+
expect(service.fetch.calls.count()).toEqual(2);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(Polling.stop).toHaveBeenCalled();
- done();
- }, 10);
+ expect(Polling.restart).toHaveBeenCalled();
- Vue.http.interceptors = _.without(Vue.http.interceptors, pollInterceptor);
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index 4200e943121..ca1b1b7cc3c 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -1,110 +1,108 @@
-require('~/lib/utils/text_utility');
+import '~/lib/utils/text_utility';
-(() => {
- describe('text_utility', () => {
- describe('gl.text.getTextWidth', () => {
- it('returns zero width when no text is passed', () => {
- expect(gl.text.getTextWidth('')).toBe(0);
- });
+describe('text_utility', () => {
+ describe('gl.text.getTextWidth', () => {
+ it('returns zero width when no text is passed', () => {
+ expect(gl.text.getTextWidth('')).toBe(0);
+ });
- it('returns zero width when no text is passed and font is passed', () => {
- expect(gl.text.getTextWidth('', '100px sans-serif')).toBe(0);
- });
+ it('returns zero width when no text is passed and font is passed', () => {
+ expect(gl.text.getTextWidth('', '100px sans-serif')).toBe(0);
+ });
- it('returns width when text is passed', () => {
- expect(gl.text.getTextWidth('foo') > 0).toBe(true);
- });
+ it('returns width when text is passed', () => {
+ expect(gl.text.getTextWidth('foo') > 0).toBe(true);
+ });
- it('returns bigger width when font is larger', () => {
- const largeFont = gl.text.getTextWidth('foo', '100px sans-serif');
- const regular = gl.text.getTextWidth('foo', '10px sans-serif');
- expect(largeFont > regular).toBe(true);
- });
+ it('returns bigger width when font is larger', () => {
+ const largeFont = gl.text.getTextWidth('foo', '100px sans-serif');
+ const regular = gl.text.getTextWidth('foo', '10px sans-serif');
+ expect(largeFont > regular).toBe(true);
});
+ });
- describe('gl.text.pluralize', () => {
- it('returns pluralized', () => {
- expect(gl.text.pluralize('test', 2)).toBe('tests');
- });
+ describe('gl.text.pluralize', () => {
+ it('returns pluralized', () => {
+ expect(gl.text.pluralize('test', 2)).toBe('tests');
+ });
- it('returns pluralized when count is 0', () => {
- expect(gl.text.pluralize('test', 0)).toBe('tests');
- });
+ it('returns pluralized when count is 0', () => {
+ expect(gl.text.pluralize('test', 0)).toBe('tests');
+ });
- it('does not return pluralized', () => {
- expect(gl.text.pluralize('test', 1)).toBe('test');
- });
+ it('does not return pluralized', () => {
+ expect(gl.text.pluralize('test', 1)).toBe('test');
});
+ });
- describe('gl.text.highCountTrim', () => {
- it('returns 99+ for count >= 100', () => {
- expect(gl.text.highCountTrim(105)).toBe('99+');
- expect(gl.text.highCountTrim(100)).toBe('99+');
- });
+ describe('gl.text.highCountTrim', () => {
+ it('returns 99+ for count >= 100', () => {
+ expect(gl.text.highCountTrim(105)).toBe('99+');
+ expect(gl.text.highCountTrim(100)).toBe('99+');
+ });
- it('returns exact number for count < 100', () => {
- expect(gl.text.highCountTrim(45)).toBe(45);
- });
+ it('returns exact number for count < 100', () => {
+ expect(gl.text.highCountTrim(45)).toBe(45);
});
+ });
- describe('gl.text.insertText', () => {
- let textArea;
+ describe('gl.text.insertText', () => {
+ let textArea;
- beforeAll(() => {
- textArea = document.createElement('textarea');
- document.querySelector('body').appendChild(textArea);
- });
+ beforeAll(() => {
+ textArea = document.createElement('textarea');
+ document.querySelector('body').appendChild(textArea);
+ });
- afterAll(() => {
- textArea.parentNode.removeChild(textArea);
- });
+ afterAll(() => {
+ textArea.parentNode.removeChild(textArea);
+ });
- describe('without selection', () => {
- it('inserts the tag on an empty line', () => {
- const initialValue = '';
+ describe('without selection', () => {
+ it('inserts the tag on an empty line', () => {
+ const initialValue = '';
- textArea.value = initialValue;
- textArea.selectionStart = 0;
- textArea.selectionEnd = 0;
+ textArea.value = initialValue;
+ textArea.selectionStart = 0;
+ textArea.selectionEnd = 0;
- gl.text.insertText(textArea, textArea.value, '*', null, '', false);
+ gl.text.insertText(textArea, textArea.value, '*', null, '', false);
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
+ expect(textArea.value).toEqual(`${initialValue}* `);
+ });
- it('inserts the tag on a new line if the current one is not empty', () => {
- const initialValue = 'some text';
+ it('inserts the tag on a new line if the current one is not empty', () => {
+ const initialValue = 'some text';
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- gl.text.insertText(textArea, textArea.value, '*', null, '', false);
+ gl.text.insertText(textArea, textArea.value, '*', null, '', false);
- expect(textArea.value).toEqual(`${initialValue}\n* `);
- });
+ expect(textArea.value).toEqual(`${initialValue}\n* `);
+ });
- it('inserts the tag on the same line if the current line only contains spaces', () => {
- const initialValue = ' ';
+ it('inserts the tag on the same line if the current line only contains spaces', () => {
+ const initialValue = ' ';
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- gl.text.insertText(textArea, textArea.value, '*', null, '', false);
+ gl.text.insertText(textArea, textArea.value, '*', null, '', false);
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
+ expect(textArea.value).toEqual(`${initialValue}* `);
+ });
- it('inserts the tag on the same line if the current line only contains tabs', () => {
- const initialValue = '\t\t\t';
+ it('inserts the tag on the same line if the current line only contains tabs', () => {
+ const initialValue = '\t\t\t';
- textArea.value = initialValue;
- textArea.setSelectionRange(initialValue.length, initialValue.length);
+ textArea.value = initialValue;
+ textArea.setSelectionRange(initialValue.length, initialValue.length);
- gl.text.insertText(textArea, textArea.value, '*', null, '', false);
+ gl.text.insertText(textArea, textArea.value, '*', null, '', false);
- expect(textArea.value).toEqual(`${initialValue}* `);
- });
+ expect(textArea.value).toEqual(`${initialValue}* `);
});
});
});
-})();
+});