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

512 lines (412 loc) 15.3 kB
var angular = require('angular'); var $ = require('jquery'); var _ = require('lodash'); var sinon = require('auto-release-sinon'); var expect = require('expect.js'); var ngMock = require('ngMock'); var getFakeRow = require('fixtures/fake_row'); describe('Doc Table', function () { require('plugins/kibana/discover/index'); var $parentScope; var $scope; var config; // Stub out a minimal mapping of 4 fields var mapping; beforeEach(ngMock.module('kibana', 'apps/discover')); beforeEach(ngMock.inject(function (_config_, $rootScope, Private) { config = _config_; $parentScope = $rootScope; $parentScope.indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern')); mapping = $parentScope.indexPattern.fields.byName; })); // Sets up the directive, take an element, and a list of properties to attach to the parent scope. var init = function ($elem, props) { ngMock.inject(function ($compile) { _.assign($parentScope, props); $compile($elem)($parentScope); $elem.scope().$digest(); $scope = $elem.isolateScope(); }); }; var destroy = function () { $scope.$destroy(); $parentScope.$destroy(); }; // For testing column removing/adding for the header and the rows // var columnTests = function (elemType, parentElem) { it('should create a time column if the timefield is defined', function (done) { var childElems = parentElem.find(elemType); expect(childElems.length).to.be(2); done(); }); it('should be able to add and remove columns', function (done) { var childElems; // Should include a column for toggling and the time column by default $parentScope.columns = ['bytes']; parentElem.scope().$digest(); childElems = parentElem.find(elemType); expect(childElems.length).to.be(3); expect($(childElems[2]).text()).to.contain('bytes'); $parentScope.columns = ['bytes', 'request_body']; parentElem.scope().$digest(); childElems = parentElem.find(elemType); expect(childElems.length).to.be(4); expect($(childElems[3]).text()).to.contain('request_body'); $parentScope.columns = ['request_body']; parentElem.scope().$digest(); childElems = parentElem.find(elemType); expect(childElems.length).to.be(3); expect($(childElems[2]).text()).to.contain('request_body'); done(); }); it('should create only the toggle column if there is no timeField', function (done) { delete parentElem.scope().indexPattern.timeFieldName; parentElem.scope().$digest(); var childElems = parentElem.find(elemType); expect(childElems.length).to.be(1); done(); }); }; describe('kbnTableHeader', function () { var $elem = angular.element( '<thead kbn-table-header columns="columns" index-pattern="indexPattern" sort="sort"></thead>' ); beforeEach(function () { init($elem, { columns: [], sorting: [], }); }); afterEach(function () { destroy(); }); describe('adding and removing columns', function () { columnTests('th', $elem); }); describe('sorting', function () { it('should have a sort function that sets the elements of the sort array', function (done) { expect($scope.sort).to.be.a(Function); done(); }); it('should have a headClasser function that determines the css classes of the sort icons', function (done) { expect($scope.headerClass).to.be.a(Function); done(); }); it('should sort asc by default, then by desc if already sorting', function (done) { var fields = ['bytes', '@timestamp']; // Should not be sorted at first expect($scope.sorting).to.eql(undefined); expect($scope.headerClass(fields[0])).to.contain('fa-sort-up'); $scope.sort(fields[0]); expect($scope.sorting).to.eql([fields[0], 'asc']); expect($scope.headerClass(fields[0])).to.contain('fa-sort-up'); $scope.sort(fields[0]); expect($scope.sorting).to.eql([fields[0], 'desc']); expect($scope.headerClass(fields[0])).to.contain('fa-sort-down'); $scope.sort(fields[0]); expect($scope.sorting).to.eql([fields[0], 'asc']); expect($scope.headerClass(fields[0])).to.contain('fa-sort-up'); $scope.sort(fields[1]); expect($scope.sorting).to.eql([fields[1], 'asc']); expect($scope.headerClass(fields[1])).to.contain('fa-sort-up'); // Should show the default sort for any other fields[0] expect($scope.headerClass(fields[0])).to.contain('fa-sort-up'); done(); }); it('should NOT sort unindexed fields', function (done) { $scope.sort('request_body'); expect($scope.sorting).to.be(undefined); done(); }); it('should NOT sort geo_point fields', function (done) { $scope.sort('point'); expect($scope.sorting).to.be(undefined); done(); }); }); describe('moving columns', function () { beforeEach(function () { $parentScope.columns = ['bytes', 'request_body', '@timestamp', 'point']; $elem.scope().$digest(); }); it('should move columns to the right', function () { $scope.moveRight('bytes'); expect($scope.columns[1]).to.be('bytes'); $scope.moveRight('bytes'); expect($scope.columns[2]).to.be('bytes'); }); it('shouldnt move the last column to the right', function () { expect($scope.columns[3]).to.be('point'); $scope.moveRight('point'); expect($scope.columns[3]).to.be('point'); }); it('should move columns to the left', function () { $scope.moveLeft('@timestamp'); expect($scope.columns[1]).to.be('@timestamp'); $scope.moveLeft('request_body'); expect($scope.columns[1]).to.be('request_body'); }); it('shouldnt move the first column to the left', function () { expect($scope.columns[0]).to.be('bytes'); $scope.moveLeft('bytes'); expect($scope.columns[0]).to.be('bytes'); }); }); }); describe('kbnTableRow', function () { var $elem = angular.element( '<tr kbn-table-row="row" ' + 'columns="columns" ' + 'sorting="sorting"' + 'filter="filter"' + 'index-pattern="indexPattern"' + '></tr>' ); beforeEach(function () { init($elem, { row: getFakeRow(0, mapping), columns: [], sorting: [], filter: sinon.spy(), maxLength: 50, }); // Ignore the metaFields (_id, _type, etc) since we don't have a mapping for them sinon.stub(config, 'get').withArgs('metaFields').returns([]); }); afterEach(function () { destroy(); }); describe('adding and removing columns', function () { columnTests('td', $elem); }); describe('details row', function () { it('should be an empty tr by default', function () { expect($elem.next().is('tr')).to.be(true); expect($elem.next().text()).to.be(''); }); it('should expand the detail row when the toggle arrow is clicked', function () { $elem.children(':first-child').click(); $scope.$digest(); expect($elem.next().text()).to.not.be(''); }); describe('expanded', function () { var $details; beforeEach(function () { // Open the row $scope.toggleRow(); $scope.$digest(); $details = $elem.next(); }); afterEach(function () { // Close the row $scope.toggleRow(); $scope.$digest(); }); it('should be a tr with something in it', function () { expect($details.is('tr')).to.be(true); expect($details.text()).to.not.be.empty(); }); }); }); }); describe('kbnTableRow meta', function () { var $elem = angular.element( '<tr kbn-table-row="row" ' + 'columns="columns" ' + 'sorting="sorting"' + 'filtering="filtering"' + 'index-pattern="indexPattern"' + '></tr>' ); var $details; beforeEach(function () { var row = getFakeRow(0, mapping); mapping._id = {indexed: true, type: 'string'}; row._source._id = 'foo'; init($elem, { row: row, columns: [], sorting: [], filtering: sinon.spy(), maxLength: 50, }); sinon.stub(config, 'get').withArgs('metaFields').returns(['_id']); // Open the row $scope.toggleRow(); $scope.$digest(); $details = $elem.next(); }); afterEach(function () { delete mapping._id; destroy(); }); it('should render even when the row source contains a field with the same name as a meta field', function () { expect($details.find('tr').length).to.be(_.keys($parentScope.indexPattern.flattenHit($scope.row)).length); }); }); describe('row diffing', function () { var $row; var $scope; var $root; var $before; beforeEach(ngMock.inject(function ($rootScope, $compile, Private) { $root = $rootScope; $root.row = getFakeRow(0, mapping); $root.columns = ['_source']; $root.sorting = []; $root.filtering = sinon.spy(); $root.maxLength = 50; $root.mapping = mapping; $root.indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern')); $row = $('<tr>') .attr({ 'kbn-table-row': 'row', 'columns': 'columns', 'sorting': 'sortin', 'filtering': 'filtering', 'index-pattern': 'indexPattern', }); $scope = $root.$new(); $compile($row)($scope); $root.$apply(); $before = $row.find('td'); expect($before).to.have.length(3); expect($before.eq(0).text().trim()).to.be(''); expect($before.eq(1).text().trim()).to.match(/^time_formatted/); })); afterEach(function () { $row.remove(); }); it('handles a new column', function () { $root.columns.push('bytes'); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(4); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after[2]).to.be($before[2]); expect($after.eq(3).text().trim()).to.match(/^bytes_formatted/); }); it('handles two new columns at once', function () { $root.columns.push('bytes'); $root.columns.push('request_body'); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(5); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after[2]).to.be($before[2]); expect($after.eq(3).text().trim()).to.match(/^bytes_formatted/); expect($after.eq(4).text().trim()).to.match(/^request_body_formatted/); }); it('handles three new columns in odd places', function () { $root.columns = [ '@timestamp', 'bytes', '_source', 'request_body' ]; $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(6); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after.eq(2).text().trim()).to.match(/^@timestamp_formatted/); expect($after.eq(3).text().trim()).to.match(/^bytes_formatted/); expect($after[4]).to.be($before[2]); expect($after.eq(5).text().trim()).to.match(/^request_body_formatted/); }); it('handles a removed column', function () { _.pull($root.columns, '_source'); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(2); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); }); it('handles two removed columns', function () { // first add a column $root.columns.push('@timestamp'); $root.$apply(); var $mid = $row.find('td'); expect($mid).to.have.length(4); $root.columns.pop(); $root.columns.pop(); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(2); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); }); it('handles three removed random columns', function () { // first add two column $root.columns.push('@timestamp', 'bytes'); $root.$apply(); var $mid = $row.find('td'); expect($mid).to.have.length(5); $root.columns[0] = false; // _source $root.columns[2] = false; // bytes $root.columns = $root.columns.filter(Boolean); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(3); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after.eq(2).text().trim()).to.match(/^@timestamp_formatted/); }); it('handles two columns with the same content', function () { $root.row.$$_partialFormatted.request_body = $root.row.$$_partialFormatted.bytes; $root.columns.length = 0; $root.columns.push('bytes'); $root.columns.push('request_body'); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(4); expect($after.eq(2).text().trim()).to.match(/^bytes_formatted/); expect($after.eq(3).text().trim()).to.match(/^bytes_formatted/); }); it('handles two columns swapping position', function () { $root.columns.push('bytes'); $root.$apply(); var $mid = $row.find('td'); expect($mid).to.have.length(4); $root.columns.reverse(); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(4); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after[2]).to.be($mid[3]); expect($after[3]).to.be($mid[2]); }); it('handles four columns all reversing position', function () { $root.columns.push('bytes', 'response', '@timestamp'); $root.$apply(); var $mid = $row.find('td'); expect($mid).to.have.length(6); $root.columns.reverse(); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(6); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after[2]).to.be($mid[5]); expect($after[3]).to.be($mid[4]); expect($after[4]).to.be($mid[3]); expect($after[5]).to.be($mid[2]); }); it('handles multiple columns with the same name', function () { $root.columns.push('bytes', 'bytes', 'bytes'); $root.$apply(); var $after = $row.find('td'); expect($after).to.have.length(6); expect($after[0]).to.be($before[0]); expect($after[1]).to.be($before[1]); expect($after[2]).to.be($before[2]); expect($after.eq(3).text().trim()).to.match(/^bytes_formatted/); expect($after.eq(4).text().trim()).to.match(/^bytes_formatted/); expect($after.eq(5).text().trim()).to.match(/^bytes_formatted/); }); }); });