UNPKG

@spalger/kibana

Version:

Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic

476 lines (390 loc) 14.2 kB
var sinon = require('auto-release-sinon'); var expect = require('expect.js'); var ngMock = require('ngMock'); var faker = require('faker'); var _ = require('lodash'); var MockState = require('fixtures/mock_state'); // global vars, injected and mocked in init() var kbnUrl; var $route; var $location; var $rootScope; var globalStateMock; var appState; require('ui/url'); function init() { ngMock.module('kibana/url', 'kibana', function ($provide) { $provide.service('$route', function () { return { reload: _.noop }; }); appState = { destroy: sinon.stub() }; $provide.service('getAppState', function () { return function () { return appState; }; }); $provide.service('globalState', function () { globalStateMock = new MockState(); globalStateMock.removeFromUrl = function (url) { return url; }; return globalStateMock; }); }); ngMock.inject(function ($injector) { $route = $injector.get('$route'); $location = $injector.get('$location'); $rootScope = $injector.get('$rootScope'); kbnUrl = $injector.get('kbnUrl'); }); } describe('kbnUrl', function () { beforeEach(function () { init(); }); describe('forcing reload', function () { it('schedules a listener for $locationChangeSuccess on the $rootScope', function () { $location.url('/url'); $route.current = { $$route: { regex: /.*/ } }; sinon.stub($rootScope, '$on'); expect($rootScope.$on.callCount).to.be(0); kbnUrl.change('/url'); sinon.assert.calledOnce(appState.destroy); expect($rootScope.$on.callCount).to.be(1); expect($rootScope.$on.firstCall.args[0]).to.be('$locationChangeSuccess'); }); it('handler unbinds the listener and calls reload', function () { $location.url('/url'); $route.current = { $$route: { regex: /.*/ } }; var unbind = sinon.stub(); sinon.stub($rootScope, '$on').returns(unbind); $route.reload = sinon.stub(); expect($rootScope.$on.callCount).to.be(0); kbnUrl.change('/url'); expect($rootScope.$on.callCount).to.be(1); var handler = $rootScope.$on.firstCall.args[1]; handler(); expect(unbind.callCount).to.be(1); expect($route.reload.callCount).to.be(1); }); it('reloads requested before the first are ignored', function () { $location.url('/url'); $route.current = { $$route: { regex: /.*/ } }; $route.reload = sinon.stub(); sinon.stub($rootScope, '$on').returns(sinon.stub()); expect($rootScope.$on.callCount).to.be(0); kbnUrl.change('/url'); expect($rootScope.$on.callCount).to.be(1); // don't call the first handler kbnUrl.change('/url'); expect($rootScope.$on.callCount).to.be(1); }); it('one reload can happen once the first has completed', function () { $location.url('/url'); $route.current = { $$route: { regex: /.*/ } }; $route.reload = sinon.stub(); sinon.stub($rootScope, '$on').returns(sinon.stub()); expect($rootScope.$on.callCount).to.be(0); kbnUrl.change('/url'); expect($rootScope.$on.callCount).to.be(1); // call the first handler $rootScope.$on.firstCall.args[1](); expect($route.reload.callCount).to.be(1); expect($rootScope.$on.callCount).to.be(1); kbnUrl.change('/url'); expect($rootScope.$on.callCount).to.be(2); }); }); describe('change', function () { it('should set $location.url', function () { sinon.stub($location, 'url'); expect($location.url.callCount).to.be(0); kbnUrl.change('/some-url'); expect($location.url.callCount).to.be(1); }); it('should uri encode replaced params', function () { var url = '/some/path/'; var params = { replace: faker.Lorem.words(3).join(' ') }; var check = encodeURIComponent(params.replace); sinon.stub($location, 'url'); kbnUrl.change(url + '{{replace}}', params); expect($location.url.firstCall.args[0]).to.be(url + check); }); it('should parse angular expression in substitutions and uri encode the results', function () { // build url by piecing together these parts var urlParts = ['/', '/', '?', '&', '#']; // make sure it can parse templates with weird spacing var wrappers = [ ['{{', '}}'], ['{{ ', ' }}'], ['{{', ' }}'], ['{{ ', '}}'], ['{{ ', ' }}']]; // make sure filters are evaluated via angular expressions var objIndex = 4; // used to case one replace as an object var filters = ['', 'uppercase', '', 'uppercase', 'rison']; // the words (template keys) used must all be unique var words = _.uniq(faker.Lorem.words(10)).slice(0, urlParts.length).map(function (word, i) { if (filters[i].length) { return word + '|' + filters[i]; } return word; }); var replacements = faker.Lorem.words(urlParts.length).map(function (word, i) { // make selected replacement into an object if (i === objIndex) { return { replace: word }; } return word; }); // build the url and test url var url = ''; var testUrl = ''; urlParts.forEach(function (part, i) { url += part + wrappers[i][0] + words[i] + wrappers[i][1]; var locals = {}; locals[words[i].split('|')[0]] = replacements[i]; testUrl += part + encodeURIComponent($rootScope.$eval(words[i], locals)); }); // create the locals replacement object var params = {}; replacements.forEach(function (replacement, i) { var word = words[i].split('|')[0]; params[word] = replacement; }); sinon.stub($location, 'url'); kbnUrl.change(url, params); expect($location.url.firstCall.args[0]).to.not.be(url); expect($location.url.firstCall.args[0]).to.be(testUrl); }); it('should handle dot notation', function () { var url = '/some/thing/{{that.is.substituted}}'; kbnUrl.change(url, { that: { is: { substituted: 'test' } } }); expect($location.url()).to.be('/some/thing/test'); }); it('should throw when params are missing', function () { var url = '/{{replace_me}}'; var params = {}; try { kbnUrl.change(url, params); throw new Error('this should not run'); } catch (err) { expect(err).to.be.an(Error); expect(err.message).to.match(/replace_me/); } }); it('should throw when filtered params are missing', function () { var url = '/{{replace_me|number}}'; var params = {}; try { kbnUrl.change(url, params); throw new Error('this should not run'); } catch (err) { expect(err).to.be.an(Error); expect(err.message).to.match(/replace_me\|number/); } }); it('should change the entire url', function () { var path = '/test/path'; var search = {search: 'test'}; var hash = 'hash'; var newPath = '/new/location'; $location.path(path).search(search).hash(hash); // verify the starting state expect($location.path()).to.be(path); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); kbnUrl.change(newPath); // verify the ending state expect($location.path()).to.be(newPath); expect($location.search()).to.eql({}); expect($location.hash()).to.be(''); }); }); describe('changePath', function () { it('should change just the path', function () { var path = '/test/path'; var search = {search: 'test'}; var hash = 'hash'; var newPath = '/new/location'; $location.path(path).search(search).hash(hash); // verify the starting state expect($location.path()).to.be(path); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); kbnUrl.changePath(newPath); // verify the ending state expect($location.path()).to.be(newPath); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); }); }); describe('redirect', function () { it('should change the entire url', function () { var path = '/test/path'; var search = {search: 'test'}; var hash = 'hash'; var newPath = '/new/location'; $location.path(path).search(search).hash(hash); // verify the starting state expect($location.path()).to.be(path); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); kbnUrl.redirect(newPath); // verify the ending state expect($location.path()).to.be(newPath); expect($location.search()).to.eql({}); expect($location.hash()).to.be(''); }); it('should replace the current history entry', function () { sinon.stub($location, 'replace'); $location.url('/some/path'); expect($location.replace.callCount).to.be(0); kbnUrl.redirect('/new/path/'); expect($location.replace.callCount).to.be(1); }); it('should call replace on $location', function () { sinon.stub(kbnUrl, '_shouldAutoReload').returns(false); sinon.stub($location, 'replace'); expect($location.replace.callCount).to.be(0); kbnUrl.redirect('/poop'); expect($location.replace.callCount).to.be(1); }); }); describe('redirectPath', function () { it('should only change the path', function () { var path = '/test/path'; var search = {search: 'test'}; var hash = 'hash'; var newPath = '/new/location'; $location .path(path) .search(search) .hash(hash); // verify the starting state expect($location.path()).to.be(path); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); kbnUrl.redirectPath(newPath); // verify the ending state expect($location.path()).to.be(newPath); expect($location.search()).to.eql(search); expect($location.hash()).to.be(hash); }); it('should call replace on $location', function () { sinon.stub(kbnUrl, '_shouldAutoReload').returns(false); sinon.stub($location, 'replace'); expect($location.replace.callCount).to.be(0); kbnUrl.redirectPath('/poop'); expect($location.replace.callCount).to.be(1); }); }); describe('_shouldAutoReload', function () { var next; var prev; beforeEach(function () { $route.current = { $$route: { regexp: /^\/is-current-route\/(\d+)/, reloadOnSearch: true } }; prev = { path: '/is-current-route/1', search: {} }; next = { path: '/is-current-route/1', search: {} }; }); it('returns false if the passed url doesn\'t match the current route', function () { next.path = '/not current'; expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); describe('if the passed url does match the route', function () { describe('and the route reloads on search', function () { describe('and the path is the same', function () { describe('and the search params are the same', function () { it('returns true', function () { expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true); }); }); describe('but the search params are different', function () { it('returns false', function () { next.search = {}; prev.search = { q: 'search term' }; expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); }); }); describe('and the path is different', function () { beforeEach(function () { next.path = '/not-same'; }); describe('and the search params are the same', function () { it('returns false', function () { expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); }); describe('but the search params are different', function () { it('returns false', function () { next.search = {}; prev.search = { q: 'search term' }; expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); }); }); }); describe('but the route does not reload on search', function () { beforeEach(function () { $route.current.$$route.reloadOnSearch = false; }); describe('and the path is the same', function () { describe('and the search params are the same', function () { it('returns true', function () { expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true); }); }); describe('but the search params are different', function () { it('returns true', function () { next.search = {}; prev.search = { q: 'search term' }; expect(kbnUrl._shouldAutoReload(next, prev)).to.be(true); }); }); }); describe('and the path is different', function () { beforeEach(function () { next.path = '/not-same'; }); describe('and the search params are the same', function () { it('returns false', function () { expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); }); describe('but the search params are different', function () { it('returns false', function () { next.search = {}; prev.search = { q: 'search term' }; expect(kbnUrl._shouldAutoReload(next, prev)).to.be(false); }); }); }); }); }); }); });