mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Merge pull request #2228 from w33ble/index-pattern-tests
Add _index_pattern tests
This commit is contained in:
commit
0c926e6ea7
9 changed files with 331 additions and 36 deletions
|
@ -14,12 +14,11 @@ define(function (require) {
|
|||
_(DocSource).inherits(SourceAbstract);
|
||||
function DocSource(initialState) {
|
||||
DocSource.Super.call(this, initialState);
|
||||
|
||||
// move onResults over to onUpdate, because that makes more sense
|
||||
this.onUpdate = this.onResults;
|
||||
this.onResults = void 0;
|
||||
}
|
||||
|
||||
DocSource.prototype.onUpdate = SourceAbstract.prototype.onResults;
|
||||
DocSource.prototype.onResults = void 0;
|
||||
|
||||
/*****
|
||||
* PUBLIC API
|
||||
*****/
|
||||
|
|
|
@ -5,7 +5,6 @@ define(function (require) {
|
|||
var errors = require('errors');
|
||||
var SourceAbstract = Private(require('components/courier/data_source/_abstract'));
|
||||
|
||||
|
||||
var FetchFailure = errors.FetchFailure;
|
||||
var RequestFailure = errors.RequestFailure;
|
||||
|
||||
|
|
|
@ -72,13 +72,7 @@ define(function (require) {
|
|||
// Give obj all of the values in _source.fields
|
||||
_.assign(self, resp._source);
|
||||
|
||||
if (self.id) {
|
||||
if (!self.fields) {
|
||||
return self.refreshFields();
|
||||
} else {
|
||||
setIndexedValue('fields');
|
||||
}
|
||||
}
|
||||
self._indexFields();
|
||||
|
||||
// Any time obj is updated, re-call applyESResp
|
||||
docSource.onUpdate().then(applyESResp, notify.fatal);
|
||||
|
@ -130,6 +124,16 @@ define(function (require) {
|
|||
});
|
||||
}
|
||||
|
||||
self._indexFields = function () {
|
||||
if (self.id) {
|
||||
if (!self.fields) {
|
||||
return self.refreshFields();
|
||||
} else {
|
||||
setIndexedValue('fields');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.addScriptedField = function (name, script, type) {
|
||||
type = type || 'string';
|
||||
|
||||
|
@ -145,6 +149,7 @@ define(function (require) {
|
|||
type: type,
|
||||
scripted: true,
|
||||
});
|
||||
|
||||
self.save();
|
||||
};
|
||||
|
||||
|
@ -153,18 +158,19 @@ define(function (require) {
|
|||
name: name,
|
||||
scripted: true
|
||||
});
|
||||
|
||||
self.fields.splice(fieldIndex, 1);
|
||||
|
||||
self.save();
|
||||
};
|
||||
|
||||
self.popularizeField = function (fieldName, unit) {
|
||||
if (_.isUndefined(unit)) unit = 1;
|
||||
if (unit == null) unit = 1;
|
||||
if (!(self.fields.byName && self.fields.byName[fieldName])) return;
|
||||
|
||||
var field = self.fields.byName[fieldName];
|
||||
if (!field.count && unit < 1) return;
|
||||
if (!field.count) field.count = 1;
|
||||
else field.count = field.count + (unit);
|
||||
field.count = field.count + (unit);
|
||||
self.save();
|
||||
};
|
||||
|
||||
|
|
31
test/unit/fixtures/logstash_fields.js
Normal file
31
test/unit/fixtures/logstash_fields.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
define(function (require) {
|
||||
function stubbedLogstashFields() {
|
||||
var sourceData = [
|
||||
{ name: 'bytes', type: 'number', indexed: true, analyzed: true, count: 10 },
|
||||
{ name: 'ssl', type: 'boolean', indexed: true, analyzed: true, count: 20 },
|
||||
{ name: '@timestamp', type: 'date', indexed: true, analyzed: true, count: 30 },
|
||||
{ name: 'utc_time', type: 'date', indexed: true, analyzed: true },
|
||||
{ name: 'phpmemory', type: 'number', indexed: true, analyzed: true },
|
||||
{ name: 'ip', type: 'ip', indexed: true, analyzed: true },
|
||||
{ name: 'request_body', type: 'attachment', indexed: true, analyzed: true },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true },
|
||||
{ name: 'point', type: 'geo_point', indexed: true, analyzed: true },
|
||||
{ name: 'area', type: 'geo_shape', indexed: true, analyzed: true },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true },
|
||||
{ name: 'machine.os', type: 'string', indexed: true, analyzed: true },
|
||||
{ name: 'geo.src', type: 'string', indexed: true, analyzed: true },
|
||||
{ name: '_type', type: 'string', indexed: true, analyzed: true },
|
||||
{ name: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false },
|
||||
{ name: 'scritped string', type: 'string', scripted: true, script: '\'i am a string\''},
|
||||
{ name: 'scritped number', type: 'number', scripted: true, script: '1234'},
|
||||
].map(function (field) {
|
||||
field.count = field.count || 0;
|
||||
field.scripted = field.scripted || false;
|
||||
return field;
|
||||
});
|
||||
|
||||
return sourceData;
|
||||
}
|
||||
|
||||
return stubbedLogstashFields;
|
||||
});
|
22
test/unit/fixtures/stubbed_doc_source_response.js
Normal file
22
test/unit/fixtures/stubbed_doc_source_response.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
define(function (require) {
|
||||
function stubbedDocSourceResponse(Private) {
|
||||
var mockLogstashFields = Private(require('fixtures/logstash_fields'));
|
||||
|
||||
return function (id, index) {
|
||||
index = index || '.kibana';
|
||||
return {
|
||||
_id: id,
|
||||
_index: index,
|
||||
_type: 'index-pattern',
|
||||
_version: 2,
|
||||
found: true,
|
||||
_source: {
|
||||
customFormats: '{}',
|
||||
fields: JSON.stringify(mockLogstashFields)
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return stubbedDocSourceResponse;
|
||||
});
|
|
@ -1,37 +1,24 @@
|
|||
define(function (require) {
|
||||
return function stubbedLogstashIndexPatternService(Private) {
|
||||
var StubIndexPattern = Private(require('test_utils/stub_index_pattern'));
|
||||
var fieldTypes = Private(require('components/index_patterns/_field_types'));
|
||||
var mockLogstashFields = Private(require('fixtures/logstash_fields'));
|
||||
var flattenSearchResponse = require('components/index_patterns/_flatten_search_response');
|
||||
var flattenHit = require('components/index_patterns/_flatten_hit');
|
||||
var fieldTypes = Private(require('components/index_patterns/_field_types'));
|
||||
var getComputedFields = require('components/index_patterns/_get_computed_fields');
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
var indexPattern = new StubIndexPattern('logstash-*', 'time', [
|
||||
{ name: 'bytes', type: 'number', indexed: true, analyzed: true, count: 10 },
|
||||
{ name: 'ssl', type: 'boolean', indexed: true, analyzed: true, count: 20 },
|
||||
{ name: '@timestamp', type: 'date', indexed: true, analyzed: true, count: 30 },
|
||||
{ name: 'utc_time', type: 'date', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'phpmemory', type: 'number', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'ip', type: 'ip', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'request_body', type: 'attachment', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'point', type: 'geo_point', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'area', type: 'geo_shape', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'extension', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'machine.os', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'geo.src', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: '_type', type: 'string', indexed: true, analyzed: true, count: 0 },
|
||||
{ name: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, count: 0 }
|
||||
].map(function (field) {
|
||||
var fields = mockLogstashFields.map(function (field) {
|
||||
field.displayName = field.name;
|
||||
var type = fieldTypes.byName[field.type];
|
||||
if (!type) throw new TypeError('unknown type ' + field.type);
|
||||
if (!_.has(field, 'sortable')) field.sortable = type.sortable;
|
||||
if (!_.has(field, 'filterable')) field.filterable = type.filterable;
|
||||
return field;
|
||||
}));
|
||||
});
|
||||
|
||||
var indexPattern = new StubIndexPattern('logstash-*', 'time', fields);
|
||||
|
||||
indexPattern.getComputedFields = _.bind(getComputedFields, indexPattern);
|
||||
indexPattern.flattenSearchResponse = _.bind(flattenSearchResponse, indexPattern);
|
||||
|
|
|
@ -124,7 +124,7 @@ define(function (require) {
|
|||
done();
|
||||
});
|
||||
|
||||
it('setting field.display should move the field into selected', function (done) {
|
||||
it('should move the field into selected when setting field.display', function (done) {
|
||||
var section = getSections($elem);
|
||||
indexPattern.fields.byName.bytes.display = true;
|
||||
$scope.$digest();
|
||||
|
|
250
test/unit/specs/components/index_pattern/_index_pattern.js
Normal file
250
test/unit/specs/components/index_pattern/_index_pattern.js
Normal file
|
@ -0,0 +1,250 @@
|
|||
define(function (require) {
|
||||
return ['index pattern', function () {
|
||||
var _ = require('lodash');
|
||||
var sinon = require('test_utils/auto_release_sinon');
|
||||
var Promise = require('bluebird');
|
||||
var errors = require('errors');
|
||||
var IndexedArray = require('utils/indexed_array/index');
|
||||
var IndexPattern;
|
||||
var mapper;
|
||||
var mappingSetup;
|
||||
var mockLogstashFields;
|
||||
var DocSource;
|
||||
var config;
|
||||
var docSourceResponse;
|
||||
var indexPatternId = 'test-pattern';
|
||||
var indexPattern;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private, $injector, _config_) {
|
||||
config = _config_;
|
||||
mockLogstashFields = Private(require('fixtures/logstash_fields'));
|
||||
docSourceResponse = Private(require('fixtures/stubbed_doc_source_response'));
|
||||
|
||||
DocSource = Private(require('components/courier/data_source/doc_source'));
|
||||
sinon.stub(DocSource.prototype, 'doIndex');
|
||||
sinon.stub(DocSource.prototype, 'fetch');
|
||||
|
||||
// stub mapper
|
||||
mapper = Private(require('components/index_patterns/_mapper'));
|
||||
sinon.stub(mapper, 'getFieldsForIndexPattern', function () {
|
||||
return Promise.resolve(_.filter(mockLogstashFields, { scripted: false }));
|
||||
});
|
||||
|
||||
// stub mappingSetup
|
||||
mappingSetup = Private(require('utils/mapping_setup'));
|
||||
sinon.stub(mappingSetup, 'isDefined', function () {
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
|
||||
IndexPattern = Private(require('components/index_patterns/_index_pattern'));
|
||||
}));
|
||||
|
||||
// create an indexPattern instance for each test
|
||||
beforeEach(function () {
|
||||
return create(indexPatternId).then(function (pattern) {
|
||||
indexPattern = pattern;
|
||||
});
|
||||
});
|
||||
|
||||
// helper function to create index patterns
|
||||
function create(id, payload) {
|
||||
var indexPattern = new IndexPattern(id);
|
||||
DocSource.prototype.doIndex.returns(Promise.resolve(id));
|
||||
payload = _.defaults(payload || {}, docSourceResponse(id));
|
||||
setDocsourcePayload(payload);
|
||||
return indexPattern.init();
|
||||
}
|
||||
|
||||
function setDocsourcePayload(payload) {
|
||||
DocSource.prototype.fetch.returns(Promise.resolve(payload));
|
||||
}
|
||||
|
||||
describe('api', function () {
|
||||
it('should have expected properties', function () {
|
||||
return create('test-pattern').then(function (indexPattern) {
|
||||
// methods
|
||||
expect(indexPattern).to.have.property('refreshFields');
|
||||
expect(indexPattern).to.have.property('popularizeField');
|
||||
expect(indexPattern).to.have.property('getFields');
|
||||
expect(indexPattern).to.have.property('getInterval');
|
||||
expect(indexPattern).to.have.property('addScriptedField');
|
||||
expect(indexPattern).to.have.property('removeScriptedField');
|
||||
expect(indexPattern).to.have.property('toString');
|
||||
expect(indexPattern).to.have.property('toJSON');
|
||||
expect(indexPattern).to.have.property('save');
|
||||
|
||||
// properties
|
||||
expect(indexPattern).to.have.property('fields');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('init', function () {
|
||||
it('should append the found fields', function () {
|
||||
expect(DocSource.prototype.fetch.callCount).to.be(1);
|
||||
expect(indexPattern.fields).to.have.length(mockLogstashFields.length);
|
||||
expect(indexPattern.fields).to.be.an(IndexedArray);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFields', function () {
|
||||
it('should return all non-scripted fields', function () {
|
||||
var indexed = _.where(mockLogstashFields, { scripted: false });
|
||||
expect(indexPattern.getFields()).to.eql(indexed);
|
||||
});
|
||||
|
||||
it('should return all scripted fields', function () {
|
||||
var scripted = _.where(mockLogstashFields, { scripted: true });
|
||||
expect(indexPattern.getFields('scripted')).to.eql(scripted);
|
||||
});
|
||||
});
|
||||
|
||||
describe('refresh fields', function () {
|
||||
// override the default indexPattern, with a truncated field list
|
||||
require('test_utils/no_digest_promises').activateForSuite();
|
||||
var indexPatternId = 'test-pattern';
|
||||
var indexPattern;
|
||||
var fieldLength;
|
||||
var truncatedFields;
|
||||
|
||||
beforeEach(function () {
|
||||
fieldLength = mockLogstashFields.length;
|
||||
truncatedFields = mockLogstashFields.slice(3);
|
||||
return create(indexPatternId, {
|
||||
_source: {
|
||||
customFormats: '{}',
|
||||
fields: JSON.stringify(truncatedFields)
|
||||
}
|
||||
}).then(function (pattern) {
|
||||
indexPattern = pattern;
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch fields from the doc source', function () {
|
||||
// ensure that we don't have all the fields
|
||||
expect(truncatedFields.length).to.not.equal(mockLogstashFields.length);
|
||||
expect(indexPattern.fields).to.have.length(truncatedFields.length);
|
||||
|
||||
// ensure that all fields will be included in the returned docSource
|
||||
setDocsourcePayload(docSourceResponse(indexPatternId));
|
||||
|
||||
// refresh fields, which will fetch
|
||||
return indexPattern.refreshFields().then(function () {
|
||||
// compare non-scripted fields to the mapper.getFieldsForIndexPattern fields
|
||||
return mapper.getFieldsForIndexPattern().then(function (fields) {
|
||||
expect(indexPattern.getFields()).to.eql(fields);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should preserve the scripted fields', function () {
|
||||
// ensure that all fields will be included in the returned docSource
|
||||
setDocsourcePayload(docSourceResponse(indexPatternId));
|
||||
|
||||
// add spy to indexPattern.getFields
|
||||
var getFieldsSpy = sinon.spy(indexPattern, 'getFields');
|
||||
|
||||
// refresh fields, which will fetch
|
||||
return indexPattern.refreshFields().then(function () {
|
||||
// called to append scripted fields to the response from mapper.getFieldsForIndexPattern
|
||||
expect(getFieldsSpy.callCount).to.equal(1);
|
||||
|
||||
var scripted = _.where(mockLogstashFields, { scripted: true });
|
||||
expect(_.filter(indexPattern.fields, { scripted: true })).to.eql(scripted);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('add and remove scripted fields', function () {
|
||||
it('should append the scripted field', function () {
|
||||
// keep a copy of the current scripted field count
|
||||
var saveSpy = sinon.spy(indexPattern, 'save');
|
||||
var oldCount = indexPattern.getFields('scripted').length;
|
||||
|
||||
// add a new scripted field
|
||||
var scriptedField = {
|
||||
name: 'new scripted field',
|
||||
script: 'false',
|
||||
type: 'boolean'
|
||||
};
|
||||
indexPattern.addScriptedField(scriptedField.name, scriptedField.script, scriptedField.type);
|
||||
indexPattern._indexFields(); // normally triggered by docSource.onUpdate()
|
||||
|
||||
var scriptedFields = indexPattern.getFields('scripted');
|
||||
expect(saveSpy.callCount).to.equal(1);
|
||||
expect(scriptedFields).to.have.length(oldCount + 1);
|
||||
expect(indexPattern.fields.byName[scriptedField.name].displayName).to.equal(scriptedField.name);
|
||||
});
|
||||
|
||||
it('should remove scripted field, by name', function () {
|
||||
var saveSpy = sinon.spy(indexPattern, 'save');
|
||||
var scriptedFields = indexPattern.getFields('scripted');
|
||||
var oldCount = scriptedFields.length;
|
||||
var scriptedField = _.last(scriptedFields);
|
||||
|
||||
indexPattern.removeScriptedField(scriptedField.name);
|
||||
|
||||
expect(saveSpy.callCount).to.equal(1);
|
||||
expect(indexPattern.getFields('scripted').length).to.equal(oldCount - 1);
|
||||
expect(indexPattern.fields.byName[scriptedField.name]).to.equal(undefined);
|
||||
});
|
||||
|
||||
it('should not allow duplicate names', function () {
|
||||
var scriptedFields = indexPattern.getFields('scripted');
|
||||
var scriptedField = _.last(scriptedFields);
|
||||
expect(function () {
|
||||
indexPattern.addScriptedField(scriptedField.name, '\'new script\'', 'string');
|
||||
}).to.throwError(function (e) {
|
||||
expect(e).to.be.a(errors.DuplicateField);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('popularizeField', function () {
|
||||
it('should increment the poplarity count by default', function () {
|
||||
var saveSpy = sinon.spy(indexPattern, 'save');
|
||||
var field = _.sample(indexPattern.fields);
|
||||
var oldCount = field.count;
|
||||
|
||||
indexPattern.popularizeField(field.name);
|
||||
|
||||
expect(saveSpy.callCount).to.equal(1);
|
||||
expect(field.count).to.equal(oldCount + 1);
|
||||
});
|
||||
|
||||
it('should increment the poplarity count', function () {
|
||||
var saveSpy = sinon.spy(indexPattern, 'save');
|
||||
var field = _.sample(indexPattern.fields);
|
||||
var oldCount = field.count;
|
||||
var incrementAmount = 4;
|
||||
|
||||
indexPattern.popularizeField(field.name, incrementAmount);
|
||||
|
||||
expect(saveSpy.callCount).to.equal(1);
|
||||
expect(field.count).to.equal(oldCount + incrementAmount);
|
||||
});
|
||||
|
||||
it('should decrement the poplarity count', function () {
|
||||
var saveSpy = sinon.spy(indexPattern, 'save');
|
||||
var field = _.sample(indexPattern.fields);
|
||||
var oldCount = field.count;
|
||||
var incrementAmount = 4;
|
||||
var decrementAmount = -2;
|
||||
|
||||
indexPattern.popularizeField(field.name, incrementAmount);
|
||||
indexPattern.popularizeField(field.name, decrementAmount);
|
||||
|
||||
expect(saveSpy.callCount).to.equal(2);
|
||||
expect(field.count).to.equal(oldCount + incrementAmount + decrementAmount);
|
||||
});
|
||||
|
||||
it('should not go below 0', function () {
|
||||
var field = _.sample(indexPattern.fields);
|
||||
var decrementAmount = -20000000;
|
||||
indexPattern.popularizeField(field.name, decrementAmount);
|
||||
expect(field.count).to.equal(0);
|
||||
});
|
||||
});
|
||||
}];
|
||||
});
|
|
@ -1,5 +1,6 @@
|
|||
define(function (require) {
|
||||
describe('Index Patterns', function () {
|
||||
run(require('specs/components/index_pattern/_index_pattern'));
|
||||
run(require('specs/components/index_pattern/_cast_mapping_type'));
|
||||
run(require('specs/components/index_pattern/_map_field'));
|
||||
run(require('specs/components/index_pattern/_pattern_to_wildcard'));
|
||||
|
@ -8,4 +9,4 @@ define(function (require) {
|
|||
|
||||
function run(mod) { describe(mod[0], mod[1]); }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue