mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
commit
f5eac5d92f
8 changed files with 439 additions and 247 deletions
|
@ -8,19 +8,18 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<span class="pull-right text-info hintbox-label" ng-click="editor.showUrlTemplateHelp = !editor.showUrlTemplateHelp">
|
||||
<span class="pull-right text-info hintbox-label" ng-click="editor.showUrlTmplHelp = !editor.showUrlTmplHelp">
|
||||
<i class="fa fa-info"></i> Url Template Help
|
||||
</span>
|
||||
|
||||
<label>Template</label>
|
||||
<text ng-model="editor.formatParams.format">
|
||||
<div class="hintbox" ng-if="editor.showUrlTemplateHelp">
|
||||
<label>Url Template</label>
|
||||
<div class="hintbox" ng-if="editor.showUrlTmplHelp">
|
||||
<h4 class="hintbox-heading">
|
||||
<i class="fa fa-question-circle text-info"></i> Url Template Help
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
If a field only contains part of a url then a "Url Template" can be used to format the value as a complete url. The format is a string which uses double curly brace notation <code ng-bind="'\{\{ \}\}'"></code> to inject values. The following values can be accessed:
|
||||
If a field only contains part of a url then a "Url Template" can be used to format the value as a complete url. The format is a string which uses double curly brace notation <code>{­{ }­}</code> to inject values. The following values can be accessed:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
|
@ -31,10 +30,98 @@
|
|||
<strong>rawValue</strong> — The unescaped value
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<caption>Examples</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value</th>
|
||||
<th>Template</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1234</td>
|
||||
<td>http://company.net/profiles?user_id={­{value}­}</td>
|
||||
<td>http://company.net/profiles?user_id=1234</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>users/admin</td>
|
||||
<td>http://company.net/groups?id={­{value}­}</td>
|
||||
<td>http://company.net/groups?id=users%2Fadmin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>/images/favicon.ico</td>
|
||||
<td>http://www.site.com{­{rawValue}­}</td>
|
||||
<td>http://www.site.com/images/favicon.ico</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<field-format-editor-pattern
|
||||
ng-model="editor.formatParams.template"
|
||||
inputs="url.sampleInputs">
|
||||
</field-format-editor-pattern>
|
||||
<input ng-model="editor.formatParams.urlTemplate" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<span class="pull-right text-info hintbox-label" ng-click="editor.showLabelTmplHelp = !editor.showLabelTmplHelp">
|
||||
<i class="fa fa-info"></i> Label Template Help
|
||||
</span>
|
||||
|
||||
<label>Label Template</label>
|
||||
<div class="hintbox" ng-if="editor.showLabelTmplHelp">
|
||||
<h4 class="hintbox-heading">
|
||||
<i class="fa fa-question-circle text-info"></i> Label Template Help
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
If the url in this field is large, it might be useful to provide an alternate template for the text version of the url. This will be displayed instead of the url, but will still link to the url. The format is a string which uses double curly brace notation <code>{­{ }­}</code> to inject values. The following values can be accessed:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<strong>value</strong> — The fields value
|
||||
</li>
|
||||
<li>
|
||||
<strong>url</strong> — The formatted url
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<caption>Examples</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value</th>
|
||||
<th>Url/Label Template</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="2">1234</td>
|
||||
<td>http://company.net/profiles?user_id={­{value}­}</td>
|
||||
<td rowspan="2">
|
||||
<a href="http://company.net/profiles?user_id=1234">User #1234</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>User #{­{value}­}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">/assets/main.css</td>
|
||||
<td>http://site.com{­{rawValue}­}</td>
|
||||
<td rowspan="2">
|
||||
<a href="http://site.com/assets/main.css">View Asset</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>View Asset</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<input ng-model="editor.formatParams.labelTemplate" class="form-control">
|
||||
</div>
|
||||
|
||||
<field-format-editor-samples inputs="url.sampleInputs"></field-format-editor-samples>
|
||||
|
|
|
@ -35,7 +35,8 @@ define(function (require) {
|
|||
Url.templateMatchRE = /{{([\s\S]+?)}}/g;
|
||||
Url.paramDefaults = {
|
||||
type: 'a',
|
||||
template: null
|
||||
urlTemplate: null,
|
||||
labelTemplate: null
|
||||
};
|
||||
|
||||
Url.urlTypes = [
|
||||
|
@ -43,25 +44,45 @@ define(function (require) {
|
|||
{ id: 'img', name: 'Image' }
|
||||
];
|
||||
|
||||
Url.prototype._formatUrl = function (value) {
|
||||
var template = this.param('urlTemplate');
|
||||
if (!template) return value;
|
||||
|
||||
return this._compileTemplate(template)({
|
||||
value: encodeURIComponent(value),
|
||||
rawValue: value
|
||||
});
|
||||
};
|
||||
|
||||
Url.prototype._formatLabel = function (value, url) {
|
||||
var template = this.param('labelTemplate');
|
||||
if (url == null) url = this._formatUrl(value);
|
||||
if (!template) return url;
|
||||
|
||||
return this._compileTemplate(template)({
|
||||
value: value,
|
||||
url: url
|
||||
});
|
||||
};
|
||||
|
||||
Url.prototype._convert = {
|
||||
text: function (value) {
|
||||
var template = this.param('template');
|
||||
return !template ? value : this._compileTemplate(template)(value);
|
||||
return this._formatLabel(value);
|
||||
},
|
||||
|
||||
html: function (rawValue, field, hit) {
|
||||
var url = _.escape(this.convert(rawValue, 'text'));
|
||||
var value = _.escape(rawValue);
|
||||
var url = _.escape(this._formatUrl(rawValue));
|
||||
var label = _.escape(this._formatLabel(rawValue, url));
|
||||
|
||||
switch (this.param('type')) {
|
||||
case 'img': return '<img src="' + url + '" alt="' + value + '" title="' + value + '">';
|
||||
case 'img':
|
||||
return '<img src="' + url + '" alt="' + label + '" title="' + label + '">';
|
||||
default:
|
||||
var urlDisplay = url;
|
||||
if (hit && hit.highlight && hit.highlight[field.name]) {
|
||||
urlDisplay = highlightFilter(url, hit.highlight[field.name]);
|
||||
label = highlightFilter(label, hit.highlight[field.name]);
|
||||
}
|
||||
|
||||
return '<a href="' + url + '" target="_blank">' + urlDisplay + '</a>';
|
||||
return '<a href="' + url + '" target="_blank">' + label + '</a>';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -72,12 +93,7 @@ define(function (require) {
|
|||
return (i % 2) ? part.trim() : part;
|
||||
});
|
||||
|
||||
return function (val) {
|
||||
var locals = {
|
||||
value: encodeURIComponent(val),
|
||||
rawValue: val
|
||||
};
|
||||
|
||||
return function (locals) {
|
||||
// replace all the odd bits with their local var
|
||||
var output = '';
|
||||
var i = -1;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@hintbox-background-color: @gray-lighter;
|
||||
@hintbox-spacing-vertical: 10px;
|
||||
@hintbox-spacing-horizontal: 12px;
|
||||
@hintbox-table-border-color: #BFC9CA;
|
||||
|
||||
.hintbox {
|
||||
padding: @hintbox-spacing-vertical @hintbox-spacing-horizontal;
|
||||
|
@ -38,4 +39,25 @@
|
|||
> * + * {
|
||||
margin-top: @hintbox-spacing-vertical;
|
||||
}
|
||||
|
||||
// https://github.com/twbs/bootstrap/blob/2aa102bfd40859d15790febed1939e0111a6fb1a/less/tables.less#L88-L106
|
||||
.table-bordered {
|
||||
border: 1px solid @hintbox-table-border-color;
|
||||
> thead,
|
||||
> tbody,
|
||||
> tfoot {
|
||||
> tr {
|
||||
> th,
|
||||
> td {
|
||||
border: 1px solid @hintbox-table-border-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
> thead > tr {
|
||||
> th,
|
||||
> td {
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
115
test/unit/specs/components/stringify/_conformance.js
Normal file
115
test/unit/specs/components/stringify/_conformance.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
|
||||
var fieldFormats;
|
||||
var FieldFormat;
|
||||
var config;
|
||||
|
||||
var formatIds = [
|
||||
'bytes',
|
||||
'date',
|
||||
'ip',
|
||||
'number',
|
||||
'percent',
|
||||
'string',
|
||||
'url',
|
||||
'_source'
|
||||
];
|
||||
|
||||
return ['conformance', function () {
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private, $injector) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
FieldFormat = Private(require('components/index_patterns/_field_format/FieldFormat'));
|
||||
config = $injector.get('config');
|
||||
}));
|
||||
|
||||
formatIds.forEach(function (id) {
|
||||
var instance;
|
||||
var Type;
|
||||
|
||||
beforeEach(function () {
|
||||
Type = fieldFormats.getType(id);
|
||||
instance = fieldFormats.getInstance(id);
|
||||
});
|
||||
|
||||
describe(id + ' Type', function () {
|
||||
it('has an id', function () {
|
||||
expect(Type.id).to.be.a('string');
|
||||
});
|
||||
|
||||
it('has a title', function () {
|
||||
expect(Type.title).to.be.a('string');
|
||||
});
|
||||
|
||||
it('declares compatible field formats as a string or array', function () {
|
||||
expect(Type.fieldType).to.be.ok();
|
||||
expect(_.isString(Type.fieldType) || _.isArray(Type.fieldType)).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(id + ' Instance', function () {
|
||||
it('extends FieldFormat', function () {
|
||||
expect(instance).to.be.a(FieldFormat);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('registers all of the fieldFormats', function () {
|
||||
expect(_.difference(fieldFormats.raw, formatIds.map(fieldFormats.getType))).to.eql([]);
|
||||
});
|
||||
|
||||
describe('Bytes format', basicPatternTests('bytes', require('numeral')));
|
||||
describe('Percent Format', basicPatternTests('percent', require('numeral')));
|
||||
describe('Date Format', basicPatternTests('date', require('moment')));
|
||||
|
||||
describe('Number Format', function () {
|
||||
basicPatternTests('number', require('numeral'))();
|
||||
|
||||
it('tries to parse strings', function () {
|
||||
var number = new (fieldFormats.getType('number'))({ pattern: '0.0b' });
|
||||
expect(number.convert(123.456)).to.be('123.5B');
|
||||
expect(number.convert('123.456')).to.be('123.5B');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function basicPatternTests(id, lib) {
|
||||
var confKey = id === 'date' ? 'dateFormat' : 'format:' + id + ':defaultPattern';
|
||||
|
||||
return function () {
|
||||
it('converts using the format:' + id + ':defaultPattern config', function () {
|
||||
var inst = fieldFormats.getInstance(id);
|
||||
[
|
||||
'0b',
|
||||
'0 b',
|
||||
'0.[000] b',
|
||||
'0.[000]b',
|
||||
'0.[0]b'
|
||||
].forEach(function (pattern) {
|
||||
var num = _.random(-10000, 10000, true);
|
||||
config.set(confKey, pattern);
|
||||
expect(inst.convert(num)).to.be(lib(num).format(pattern));
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the pattern param if available', function () {
|
||||
var num = _.random(-10000, 10000, true);
|
||||
var defFormat = '0b';
|
||||
var customFormat = '0.00000%';
|
||||
|
||||
config.set(confKey, defFormat);
|
||||
var defInst = fieldFormats.getInstance(id);
|
||||
|
||||
var Type = fieldFormats.getType(id);
|
||||
var customInst = new Type({ pattern: customFormat });
|
||||
|
||||
expect(defInst.convert(num)).to.not.be(customInst.convert(num));
|
||||
expect(defInst.convert(num)).to.be(lib(num).format(defFormat));
|
||||
expect(customInst.convert(num)).to.be(lib(num).format(customFormat));
|
||||
});
|
||||
};
|
||||
}
|
||||
}];
|
||||
});
|
16
test/unit/specs/components/stringify/_ip.js
Normal file
16
test/unit/specs/components/stringify/_ip.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
define(function (require) {
|
||||
return ['IP Address Format', function () {
|
||||
var fieldFormats;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
}));
|
||||
|
||||
it('convers a value from a decimal to a string', function () {
|
||||
var ip = fieldFormats.getInstance('ip');
|
||||
expect(ip.convert(1186489492)).to.be('70.184.100.148');
|
||||
});
|
||||
|
||||
}];
|
||||
});
|
34
test/unit/specs/components/stringify/_source.js
Normal file
34
test/unit/specs/components/stringify/_source.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
define(function (require) {
|
||||
return ['_source formatting', function () {
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
|
||||
var fieldFormats;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
}));
|
||||
|
||||
describe('Source format', function () {
|
||||
var indexPattern;
|
||||
var hits;
|
||||
var format;
|
||||
var convertHtml;
|
||||
|
||||
beforeEach(inject(function (Private) {
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
hits = Private(require('fixtures/hits'));
|
||||
format = fieldFormats.getInstance('_source');
|
||||
convertHtml = format.getConverterFor('html');
|
||||
}));
|
||||
|
||||
it('uses the _source, field, and hit to create a <dl>', function () {
|
||||
var hit = _.first(hits);
|
||||
var $dl = $(convertHtml(hit._source, indexPattern.fields.byName._source, hit));
|
||||
expect($dl.is('dl')).to.be.ok();
|
||||
expect($dl.find('dt')).to.have.length(_.keys(indexPattern.flattenHit(hit)).length);
|
||||
});
|
||||
});
|
||||
}];
|
||||
});
|
119
test/unit/specs/components/stringify/_url.js
Normal file
119
test/unit/specs/components/stringify/_url.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
define(function (require) {
|
||||
return ['Url Format', function () {
|
||||
var $ = require('jquery');
|
||||
var fieldFormats;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
}));
|
||||
|
||||
describe('Url Format', function () {
|
||||
var Url;
|
||||
|
||||
beforeEach(function () {
|
||||
Url = fieldFormats.getType('url');
|
||||
});
|
||||
|
||||
it('ouputs a simple <a> tab by default', function () {
|
||||
var url = new Url();
|
||||
|
||||
var $a = $(url.convert('http://elastic.co', 'html'));
|
||||
expect($a.is('a')).to.be(true);
|
||||
expect($a.size()).to.be(1);
|
||||
expect($a.attr('href')).to.be('http://elastic.co');
|
||||
expect($a.attr('target')).to.be('_blank');
|
||||
expect($a.children().size()).to.be(0);
|
||||
});
|
||||
|
||||
it('outputs an <image> if type === "img"', function () {
|
||||
var url = new Url({ type: 'img' });
|
||||
|
||||
var $img = $(url.convert('http://elastic.co', 'html'));
|
||||
expect($img.is('img')).to.be(true);
|
||||
expect($img.attr('src')).to.be('http://elastic.co');
|
||||
});
|
||||
|
||||
describe('url template', function () {
|
||||
it('accepts a template', function () {
|
||||
var url = new Url({ urlTemplate: 'url: {{ value }}' });
|
||||
var $a = $(url.convert('url', 'html'));
|
||||
expect($a.is('a')).to.be(true);
|
||||
expect($a.size()).to.be(1);
|
||||
expect($a.attr('href')).to.be('url: url');
|
||||
expect($a.attr('target')).to.be('_blank');
|
||||
expect($a.children().size()).to.be(0);
|
||||
});
|
||||
|
||||
it('only outputs the url if the contentType === "text"', function () {
|
||||
var url = new Url();
|
||||
expect(url.convert('url', 'text')).to.be('url');
|
||||
});
|
||||
});
|
||||
|
||||
describe('label template', function () {
|
||||
it('accepts a template', function () {
|
||||
var url = new Url({ labelTemplate: 'extension: {{ value }}' });
|
||||
var $a = $(url.convert('php', 'html'));
|
||||
expect($a.is('a')).to.be(true);
|
||||
expect($a.size()).to.be(1);
|
||||
expect($a.attr('href')).to.be('php');
|
||||
expect($a.html()).to.be('extension: php');
|
||||
});
|
||||
|
||||
it('uses the label template for text formating', function () {
|
||||
var url = new Url({ labelTemplate: 'external {{value }}'});
|
||||
expect(url.convert('url', 'text')).to.be('external url');
|
||||
});
|
||||
|
||||
it('can use the raw value', function () {
|
||||
var url = new Url({
|
||||
labelTemplate: 'external {{value}}'
|
||||
});
|
||||
expect(url.convert('url?', 'text')).to.be('external url?');
|
||||
});
|
||||
|
||||
it('can use the url', function () {
|
||||
var url = new Url({
|
||||
urlTemplate: 'http://google.com/{{value}}',
|
||||
labelTemplate: 'external {{url}}'
|
||||
});
|
||||
expect(url.convert('url?', 'text')).to.be('external http://google.com/url%3F');
|
||||
});
|
||||
});
|
||||
|
||||
describe('templating', function () {
|
||||
it('ignores unknown variables', function () {
|
||||
var url = new Url({ urlTemplate: '{{ not really a var }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
it('does not allow executing code in variable expressions', function () {
|
||||
window.SHOULD_NOT_BE_TRUE = false;
|
||||
var url = new Url({ urlTemplate: '{{ (window.SHOULD_NOT_BE_TRUE = true) && value }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
describe('', function () {
|
||||
before(function () {
|
||||
Object.prototype.cantStopMeNow = {
|
||||
toString: function () {
|
||||
return 'fail';
|
||||
},
|
||||
cantStopMeNow: null
|
||||
};
|
||||
});
|
||||
|
||||
it('does not get values from the prototype chain', function () {
|
||||
var url = new Url({ urlTemplate: '{{ cantStopMeNow }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
after(function () {
|
||||
delete Object.prototype.cantStopMeNow;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}];
|
||||
});
|
|
@ -1,229 +1,12 @@
|
|||
define(function (require) {
|
||||
describe('Stringify Component', function () {
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
run(require('specs/components/stringify/_conformance'));
|
||||
run(require('specs/components/stringify/_ip'));
|
||||
run(require('specs/components/stringify/_source'));
|
||||
run(require('specs/components/stringify/_url'));
|
||||
|
||||
var fieldFormats;
|
||||
var FieldFormat;
|
||||
var config;
|
||||
var $rootScope;
|
||||
|
||||
var formatIds = [
|
||||
'bytes',
|
||||
'date',
|
||||
'ip',
|
||||
'number',
|
||||
'percent',
|
||||
'string',
|
||||
'url',
|
||||
'_source'
|
||||
];
|
||||
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private, $injector) {
|
||||
fieldFormats = Private(require('registry/field_formats'));
|
||||
FieldFormat = Private(require('components/index_patterns/_field_format/FieldFormat'));
|
||||
config = $injector.get('config');
|
||||
$rootScope = $injector.get('$rootScope');
|
||||
}));
|
||||
|
||||
it('registers all of the fieldFormats', function () {
|
||||
expect(_.difference(fieldFormats.raw, formatIds.map(fieldFormats.getType))).to.eql([]);
|
||||
});
|
||||
|
||||
describe('conformance', function () {
|
||||
formatIds.forEach(function (id) {
|
||||
var instance;
|
||||
var Type;
|
||||
|
||||
beforeEach(function () {
|
||||
Type = fieldFormats.getType(id);
|
||||
instance = fieldFormats.getInstance(id);
|
||||
});
|
||||
|
||||
describe(id + ' Type', function () {
|
||||
it('has an id', function () {
|
||||
expect(Type.id).to.be.a('string');
|
||||
});
|
||||
|
||||
it('has a title', function () {
|
||||
expect(Type.title).to.be.a('string');
|
||||
});
|
||||
|
||||
it('declares compatible field formats as a string or array', function () {
|
||||
expect(Type.fieldType).to.be.ok();
|
||||
expect(_.isString(Type.fieldType) || _.isArray(Type.fieldType)).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(id + ' Instance', function () {
|
||||
it('extends FieldFormat', function () {
|
||||
expect(instance).to.be.a(FieldFormat);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Bytes format', basicPatternTests('bytes', require('numeral')));
|
||||
describe('Percent Format', basicPatternTests('percent', require('numeral')));
|
||||
describe('Date Format', basicPatternTests('date', require('moment')));
|
||||
|
||||
describe('Number Format', function () {
|
||||
basicPatternTests('number', require('numeral'))();
|
||||
|
||||
it('tries to parse strings', function () {
|
||||
var number = new (fieldFormats.getType('number'))({ pattern: '0.0b' });
|
||||
expect(number.convert(123.456)).to.be('123.5B');
|
||||
expect(number.convert('123.456')).to.be('123.5B');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function basicPatternTests(id, lib) {
|
||||
var confKey = id === 'date' ? 'dateFormat' : 'format:' + id + ':defaultPattern';
|
||||
|
||||
return function () {
|
||||
it('converts using the format:' + id + ':defaultPattern config', function () {
|
||||
var inst = fieldFormats.getInstance(id);
|
||||
[
|
||||
'0b',
|
||||
'0 b',
|
||||
'0.[000] b',
|
||||
'0.[000]b',
|
||||
'0.[0]b'
|
||||
].forEach(function (pattern) {
|
||||
var num = _.random(-10000, 10000, true);
|
||||
config.set(confKey, pattern);
|
||||
expect(inst.convert(num)).to.be(lib(num).format(pattern));
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the pattern param if available', function () {
|
||||
var num = _.random(-10000, 10000, true);
|
||||
var defFormat = '0b';
|
||||
var customFormat = '0.00000%';
|
||||
|
||||
config.set(confKey, defFormat);
|
||||
var defInst = fieldFormats.getInstance(id);
|
||||
|
||||
var Type = fieldFormats.getType(id);
|
||||
var customInst = new Type({ pattern: customFormat });
|
||||
|
||||
expect(defInst.convert(num)).to.not.be(customInst.convert(num));
|
||||
expect(defInst.convert(num)).to.be(lib(num).format(defFormat));
|
||||
expect(customInst.convert(num)).to.be(lib(num).format(customFormat));
|
||||
});
|
||||
};
|
||||
function run(suite) {
|
||||
describe(suite[0], suite[1]);
|
||||
}
|
||||
|
||||
describe('Ip format', function () {
|
||||
it('convers a value from a decimal to a string', function () {
|
||||
var ip = fieldFormats.getInstance('ip');
|
||||
expect(ip.convert(1186489492)).to.be('70.184.100.148');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Url Format', function () {
|
||||
var Url;
|
||||
|
||||
beforeEach(function () {
|
||||
Url = fieldFormats.getType('url');
|
||||
});
|
||||
|
||||
it('ouputs a simple <a> tab by default', function () {
|
||||
var url = new Url();
|
||||
|
||||
var $a = $(url.convert('http://elastic.co', 'html'));
|
||||
expect($a.is('a')).to.be(true);
|
||||
expect($a.size()).to.be(1);
|
||||
expect($a.attr('href')).to.be('http://elastic.co');
|
||||
expect($a.attr('target')).to.be('_blank');
|
||||
expect($a.children().size()).to.be(0);
|
||||
});
|
||||
|
||||
it('outputs an <image> if type === "img"', function () {
|
||||
var url = new Url({ type: 'img' });
|
||||
|
||||
var $img = $(url.convert('http://elastic.co', 'html'));
|
||||
expect($img.is('img')).to.be(true);
|
||||
expect($img.attr('src')).to.be('http://elastic.co');
|
||||
});
|
||||
|
||||
it('only outputs the url if the contentType === "text"', function () {
|
||||
var url = new Url();
|
||||
expect(url.convert('url', 'text')).to.be('url');
|
||||
});
|
||||
|
||||
describe('template', function () {
|
||||
|
||||
it('accepts a template', function () {
|
||||
var url = new Url({ template: 'url: {{ value }}' });
|
||||
var $a = $(url.convert('url', 'html'));
|
||||
expect($a.is('a')).to.be(true);
|
||||
expect($a.size()).to.be(1);
|
||||
expect($a.attr('href')).to.be('url: url');
|
||||
expect($a.attr('target')).to.be('_blank');
|
||||
expect($a.children().size()).to.be(0);
|
||||
});
|
||||
|
||||
it('renders for text contentType', function () {
|
||||
var url = new Url({ template: 'url: {{ value }}' });
|
||||
expect(url.convert('url', 'text')).to.be('url: url');
|
||||
});
|
||||
|
||||
it('ignores unknown variables', function () {
|
||||
var url = new Url({ template: '{{ not really a var }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
it('does not allow executing code in variable expressions', function () {
|
||||
window.SHOULD_NOT_BE_TRUE = false;
|
||||
var url = new Url({ template: '{{ (window.SHOULD_NOT_BE_TRUE = true) && value }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
describe('', function () {
|
||||
before(function () {
|
||||
Object.prototype.cantStopMeNow = {
|
||||
toString: function () {
|
||||
return 'fail';
|
||||
},
|
||||
cantStopMeNow: null
|
||||
};
|
||||
});
|
||||
|
||||
it('does not get values from the prototype chain', function () {
|
||||
var url = new Url({ template: '{{ cantStopMeNow }}' });
|
||||
expect(url.convert('url', 'text')).to.be('');
|
||||
});
|
||||
|
||||
after(function () {
|
||||
delete Object.prototype.cantStopMeNow;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Source format', function () {
|
||||
var indexPattern;
|
||||
var hits;
|
||||
var format;
|
||||
var convertHtml;
|
||||
|
||||
beforeEach(inject(function (Private) {
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
hits = Private(require('fixtures/hits'));
|
||||
format = fieldFormats.getInstance('_source');
|
||||
convertHtml = format.getConverterFor('html');
|
||||
}));
|
||||
|
||||
it('uses the _source, field, and hit to create a <dl>', function () {
|
||||
var hit = _.first(hits);
|
||||
var $dl = $(convertHtml(hit._source, indexPattern.fields.byName._source, hit));
|
||||
expect($dl.is('dl')).to.be.ok();
|
||||
expect($dl.find('dt')).to.have.length(_.keys(indexPattern.flattenHit(hit)).length);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue