This commit is contained in:
Rashid Khan 2014-09-18 13:12:13 -07:00
parent d0a8d5d495
commit 5c8686f159
7 changed files with 240 additions and 158 deletions

View file

@ -14,7 +14,6 @@ define(function (require) {
restrict: 'E',
template: html,
replace: true,
require: '^discFieldChooser',
link: function ($scope, $elem) {
var detailsElem;
var detailScope = $scope.$new();
@ -53,10 +52,6 @@ define(function (require) {
}
};
$scope.displayButton = function (field) {
return field.display ? 'btn-danger' : '';
};
init();
}
};

View file

@ -4,7 +4,7 @@
</div>
<ul
bindonce class="list-unstyled discover-selected-fields" >
<discover-field field="field" ng-repeat="field in fields|filter:{display:true}" data="data">
<discover-field ng-repeat="field in fields|filter:{display:true}">
</discover-field>
</ul>
@ -83,18 +83,12 @@
ng-show="(fields | filter:filter.popularity).length > 0"
class="list-unstyled sidebar-well discover-popular-fields" ng-class="{ 'hidden-sm': !showFields, 'hidden-xs': !showFields }">
<li class="sidebar-item sidebar-list-header"><h6>Popular fields</h6></li>
<discover-field
ng-repeat="field in popularFields | filter:filter.isFieldFiltered"
field="field"
data="data">
<discover-field ng-repeat="field in popularFields | filter:filter.isFieldFiltered">
</discover-field>
</ul>
<ul bindonce class="list-unstyled discover-unpopular-fields" ng-class="{ 'hidden-sm': !showFields, 'hidden-xs': !showFields }">
<discover-field
ng-repeat="field in unpopularFields | filter:filter.isFieldFiltered"
field="field"
data="data">
<discover-field ng-repeat="field in unpopularFields | filter:filter.isFieldFiltered">
</discover-field>
</ul>

View file

@ -1,8 +1,8 @@
define(function (require) {
/* Extensions:
gif: 5
html: 8
php: 5 (thus 5 with phpmemory fields)
gif: 5
png: 2
_type:

View file

@ -69,7 +69,9 @@
'sinon/sinon',
'specs/apps/discover/hit_sort_fn',
'specs/apps/discover/directives/table',
'specs/apps/discover/directives/discover_field',
'specs/apps/discover/directives/field_chooser',
'specs/apps/discover/directives/field_calculator',
'specs/apps/discover/segmented_fetch',
'specs/directives/confirm-click',
'specs/directives/timepicker',

View file

@ -0,0 +1,82 @@
define(function (require) {
var angular = require('angular');
var $ = require('jquery');
var _ = require('lodash');
var sinon = require('test_utils/auto_release_sinon');
// Load the kibana app dependencies.
require('services/private');
require('apps/discover/components/field_chooser/discover_field');
var $parentScope, $scope, indexPattern;
var init = function ($elem, props) {
inject(function ($rootScope, $compile) {
$parentScope = $rootScope;
_.assign($parentScope, props);
$compile($elem)($parentScope);
$elem.scope().$digest();
$scope = $elem.scope();
});
};
var destroy = function () {
$scope.$destroy();
$parentScope.$destroy();
};
var details = {
'total': 379,
'exists': 379,
'missing': 0,
'buckets': [
{'value': 'info', 'count': 359, 'percent': '94.7'},
{'value': 'success', 'count': 135, 'percent': '35.6'},
{'value': 'security', 'count': 123, 'percent': '32.5'},
{'value': 'warning', 'count': 108, 'percent': '28.5'},
{'value': 'login', 'count': 17, 'percent': '4.5'}
]
};
describe('discoverField', function () {
var $elem;
beforeEach(module('kibana'));
beforeEach(function () {
$elem = angular.element('<discover-field></discover-field>');
inject(function (Private) {
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
});
init($elem, {
field: indexPattern.fields.byName.extension,
increaseFieldCounter: sinon.spy(),
toggle: function (field) {
indexPattern.fields.byName[field].display = !!!indexPattern.fields.byName[field].display;
}
});
});
afterEach(function () {
destroy();
});
describe('toggleDisplay', function () {
it('should exist', function (done) {
expect($scope.toggleDisplay).to.be.a(Function);
done();
});
it('should toggle the display of the field', function (done) {
$scope.toggleDisplay($scope.field);
expect($scope.field.display).to.be(true);
done();
});
it('should increase the field popularity', function (done) {
$scope.toggleDisplay($scope.field);
expect($scope.increaseFieldCounter.called).to.be(true);
done();
});
});
});
});

View file

@ -0,0 +1,152 @@
define(function (require) {
var angular = require('angular');
var $ = require('jquery');
var _ = require('lodash');
var sinon = require('test_utils/auto_release_sinon');
var fieldCalculator = require('apps/discover/components/field_chooser/lib/field_calculator');
// Load the kibana app dependencies.
require('services/private');
var indexPattern;
describe('fieldCalculator', function (done) {
beforeEach(module('kibana'));
beforeEach(function () {
inject(function (Private) {
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
});
});
it('should have a _countMissing that counts nulls & undefineds in an array', function (done) {
var values = [['foo', 'bar'], 'foo', 'foo', undefined, ['foo', 'bar'], 'bar', 'baz', null, null, null, 'foo', undefined];
expect(fieldCalculator._countMissing(values)).to.be(5);
done();
});
describe('_groupValues', function () {
var groups, params, values;
beforeEach(function () {
values = [['foo', 'bar'], 'foo', 'foo', undefined, ['foo', 'bar'], 'bar', 'baz', null, null, null, 'foo', undefined];
params = {};
groups = fieldCalculator._groupValues(values, params);
});
it('should have a _groupValues that counts values', function (done) {
expect(groups).to.be.an(Object);
done();
});
it('should throw an error if any value is a plain object', function (done) {
expect(function () { fieldCalculator._groupValues([{}, true, false], params); })
.to.throwError();
done();
});
it('should have a a key for value in the array when not grouping array terms', function (done) {
expect(_.keys(groups).length).to.be(3);
expect(groups['foo']).to.be.a(Object);
expect(groups['bar']).to.be.a(Object);
expect(groups['baz']).to.be.a(Object);
done();
});
it('should count array terms independently', function (done) {
expect(groups['foo,bar']).to.be(undefined);
expect(groups['foo'].count).to.be(5);
expect(groups['bar'].count).to.be(3);
expect(groups['baz'].count).to.be(1);
done();
});
describe('grouped array terms', function (done) {
beforeEach(function () {
params.grouped = true;
groups = fieldCalculator._groupValues(values, params);
});
it('should group array terms when passed params.grouped', function (done) {
expect(_.keys(groups).length).to.be(4);
expect(groups['foo,bar']).to.be.a(Object);
done();
});
it('should contain the original array as the value', function (done) {
expect(groups['foo,bar'].value).to.eql(['foo', 'bar']);
done();
});
it('should count the pairs seperately from the values they contain', function (done) {
expect(groups['foo,bar'].count).to.be(2);
expect(groups['foo'].count).to.be(3);
expect(groups['bar'].count).to.be(1);
done();
});
});
});
describe('getFieldValues', function () {
var hits = require('fixtures/real_hits.js');
it('Should return an array of values for _source fields', function () {
var extensions = fieldCalculator.getFieldValues(hits, indexPattern.fields.byName.extension);
expect(extensions).to.be.an(Array);
expect(_.filter(extensions, function (v) { return v === 'html'; }).length).to.be(8);
expect(_.uniq(_.clone(extensions)).sort()).to.eql(['gif', 'html', 'php', 'png']);
});
it('Should return an array of values for core meta fields', function () {
var types = fieldCalculator.getFieldValues(hits, indexPattern.fields.byName._type);
expect(types).to.be.an(Array);
expect(_.filter(types, function (v) { return v === 'apache'; }).length).to.be(18);
expect(_.uniq(_.clone(types)).sort()).to.eql(['apache', 'nginx']);
});
});
describe('getFieldValueCounts', function () {
var params;
beforeEach(function () {
params = {
data: require('fixtures/real_hits.js'),
field: indexPattern.fields.byName.extension,
count: 3
};
});
it('counts the top 3 values', function () {
var extensions = fieldCalculator.getFieldValueCounts(params);
expect(extensions).to.be.an(Object);
expect(extensions.buckets).to.be.an(Array);
expect(extensions.buckets.length).to.be(3);
expect(_.pluck(extensions.buckets, 'value')).to.eql(['html', 'php', 'gif']);
expect(extensions.error).to.be(undefined);
});
it('fails to analyze geo and attachment types', function () {
params.field = indexPattern.fields.byName.point;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
params.field = indexPattern.fields.byName.area;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
params.field = indexPattern.fields.byName.request_body;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
});
it('fails to analyze fields that are in the mapping, but not the data', function () {
params.field = indexPattern.fields.byName.ip;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
});
it('counts the total hits', function () {
expect(fieldCalculator.getFieldValueCounts(params).total).to.be(params.data.length);
});
it('counts the hits the field exists in', function () {
params.field = indexPattern.fields.byName.phpmemory;
expect(fieldCalculator.getFieldValueCounts(params).exists).to.be(5);
});
});
});
});

View file

@ -3,7 +3,6 @@ define(function (require) {
var $ = require('jquery');
var _ = require('lodash');
var sinon = require('test_utils/auto_release_sinon');
var fieldCalculator = require('apps/discover/components/field_chooser/lib/field_calculator');
// Load the kibana app dependencies.
require('services/private');
@ -11,7 +10,6 @@ define(function (require) {
var $parentScope, $scope, config, indexPattern;
// Sets up the directive, take an element, and a list of properties to attach to the parent scope.
var init = function ($elem, props) {
inject(function ($rootScope, $compile, _config_) {
@ -29,7 +27,6 @@ define(function (require) {
$parentScope.$destroy();
};
describe('discover field chooser directives', function () {
var $elem = angular.element(
'<disc-field-chooser' +
@ -48,7 +45,6 @@ define(function (require) {
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
});
init($elem, {
fields: _.map(indexPattern.fields.raw, function (v, i) { return _.merge(v, {display: false, rowCount: i}); }),
toggle: sinon.spy(),
@ -160,8 +156,6 @@ define(function (require) {
});
it('should recalculate the details on open fields if the data changes', function () {
$scope.details(field);
sinon.stub($scope, 'details');
$scope.data = [];
@ -176,143 +170,6 @@ define(function (require) {
$scope.$apply();
expect($scope.details.called).to.be(false);
});
});
describe('fieldCalculator', function (done) {
it('should have a _countMissing that counts nulls & undefineds in an array', function (done) {
var values = [['foo', 'bar'], 'foo', 'foo', undefined, ['foo', 'bar'], 'bar', 'baz', null, null, null, 'foo', undefined];
expect(fieldCalculator._countMissing(values)).to.be(5);
done();
});
describe('_groupValues', function () {
var groups, params, values;
beforeEach(function () {
values = [['foo', 'bar'], 'foo', 'foo', undefined, ['foo', 'bar'], 'bar', 'baz', null, null, null, 'foo', undefined];
params = {};
groups = fieldCalculator._groupValues(values, params);
});
it('should have a _groupValues that counts values', function (done) {
expect(groups).to.be.an(Object);
done();
});
it('should throw an error if any value is a plain object', function (done) {
expect(function () { fieldCalculator._groupValues([{}, true, false], params); })
.to.throwError();
done();
});
it('should have a a key for value in the array when not grouping array terms', function (done) {
expect(_.keys(groups).length).to.be(3);
expect(groups['foo']).to.be.a(Object);
expect(groups['bar']).to.be.a(Object);
expect(groups['baz']).to.be.a(Object);
done();
});
it('should count array terms independently', function (done) {
expect(groups['foo,bar']).to.be(undefined);
expect(groups['foo'].count).to.be(5);
expect(groups['bar'].count).to.be(3);
expect(groups['baz'].count).to.be(1);
done();
});
describe('grouped array terms', function (done) {
beforeEach(function () {
params.grouped = true;
groups = fieldCalculator._groupValues(values, params);
});
it('should group array terms when passed params.grouped', function (done) {
expect(_.keys(groups).length).to.be(4);
expect(groups['foo,bar']).to.be.a(Object);
done();
});
it('should contain the original array as the value', function (done) {
expect(groups['foo,bar'].value).to.eql(['foo', 'bar']);
done();
});
it('should count the pairs seperately from the values they contain', function (done) {
expect(groups['foo,bar'].count).to.be(2);
expect(groups['foo'].count).to.be(3);
expect(groups['bar'].count).to.be(1);
done();
});
});
});
describe('getFieldValues', function () {
var hits = require('fixtures/real_hits.js');
it('Should return an array of values for _source fields', function () {
var extensions = fieldCalculator.getFieldValues(hits, indexPattern.fields.byName.extension);
expect(extensions).to.be.an(Array);
expect(_.filter(extensions, function (v) { return v === 'html'; }).length).to.be(8);
expect(_.uniq(_.clone(extensions)).sort()).to.eql(['gif', 'html', 'php', 'png']);
});
it('Should return an array of values for core meta fields', function () {
var types = fieldCalculator.getFieldValues(hits, indexPattern.fields.byName._type);
expect(types).to.be.an(Array);
expect(_.filter(types, function (v) { return v === 'apache'; }).length).to.be(18);
expect(_.uniq(_.clone(types)).sort()).to.eql(['apache', 'nginx']);
});
});
describe('getFieldValueCounts', function () {
var params;
beforeEach(function () {
params = {
data: require('fixtures/real_hits.js'),
field: indexPattern.fields.byName.extension,
count: 3
};
});
it('counts the top 3 values', function () {
var extensions = fieldCalculator.getFieldValueCounts(params);
expect(extensions).to.be.an(Object);
expect(extensions.buckets).to.be.an(Array);
expect(extensions.buckets.length).to.be(3);
expect(_.pluck(extensions.buckets, 'value')).to.eql(['html', 'php', 'gif']);
expect(extensions.error).to.be(undefined);
});
it('fails to analyze geo and attachment types', function () {
params.field = indexPattern.fields.byName.point;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
params.field = indexPattern.fields.byName.area;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
params.field = indexPattern.fields.byName.request_body;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
});
it('fails to analyze fields that are in the mapping, but not the data', function () {
params.field = indexPattern.fields.byName.ip;
expect(fieldCalculator.getFieldValueCounts(params).error).to.not.be(undefined);
});
it('counts the total hits', function () {
expect(fieldCalculator.getFieldValueCounts(params).total).to.be(params.data.length);
});
it('counts the hits the field exists in', function () {
params.field = indexPattern.fields.byName.phpmemory;
expect(fieldCalculator.getFieldValueCounts(params).exists).to.be(5);
});
});
});
});
});