diff --git a/src/ui/public/agg_table/agg_table.js b/src/ui/public/agg_table/agg_table.js
index dfd38d17206b8..3b1a5dd7f1251 100644
--- a/src/ui/public/agg_table/agg_table.js
+++ b/src/ui/public/agg_table/agg_table.js
@@ -10,7 +10,7 @@ uiModules
.get('kibana')
.directive('kbnAggTable', function ($filter, config, Private, compileRecursiveDirective) {
const fieldFormats = Private(RegistryFieldFormatsProvider);
- const numberFormatter = fieldFormats.getDefaultInstance('number').getConverterFor('html');
+ const numberFormatter = fieldFormats.getDefaultInstance('number').getConverterFor('text');
return {
restrict: 'E',
@@ -130,7 +130,7 @@ uiModules
return prev + curr[i].value;
}, 0);
}
- const formatter = agg.fieldFormatter('html');
+ const formatter = agg.fieldFormatter('text');
switch ($scope.totalFunc) {
case 'sum':
diff --git a/src/ui/public/index_patterns/__tests__/_field_format.js b/src/ui/public/index_patterns/__tests__/_field_format.js
index ca8fb8d90fcdf..69443d68e3516 100644
--- a/src/ui/public/index_patterns/__tests__/_field_format.js
+++ b/src/ui/public/index_patterns/__tests__/_field_format.js
@@ -2,6 +2,7 @@ import _ from 'lodash';
import expect from 'expect.js';
import ngMock from 'ng_mock';
import IndexPatternsFieldFormatFieldFormatProvider from 'ui/index_patterns/_field_format/field_format';
+
describe('FieldFormat class', function () {
let FieldFormat;
@@ -86,7 +87,7 @@ describe('FieldFormat class', function () {
const html = f.getConverterFor('html');
expect(text).to.not.be(html);
expect(text('formatted')).to.be('formatted');
- expect(html('formatted')).to.be('formatted');
+ expect(html('formatted')).to.be('formatted');
});
it('can be an object, with seperate text and html converter', function () {
@@ -100,7 +101,7 @@ describe('FieldFormat class', function () {
const html = f.getConverterFor('html');
expect(text).to.not.be(html);
expect(text('formatted text')).to.be('formatted text');
- expect(html('formatted html')).to.be('formatted html');
+ expect(html('formatted html')).to.be('formatted html');
});
it('does not escape the output of the text converter', function () {
@@ -112,7 +113,8 @@ describe('FieldFormat class', function () {
it('does escape the output of the text converter if used in an html context', function () {
TestFormat.prototype._convert = _.constant('');
const f = new TestFormat();
- expect(f.convert('', 'html')).to.not.contain('<');
+ expect(_.trimRight(_.trimLeft(f.convert('', 'html'), ''), ''))
+ .to.not.contain('<');
});
it('does not escape the output of an html specific converter', function () {
@@ -123,7 +125,7 @@ describe('FieldFormat class', function () {
const f = new TestFormat();
expect(f.convert('', 'text')).to.be('');
- expect(f.convert('', 'html')).to.be('');
+ expect(f.convert('', 'html')).to.be('');
});
});
@@ -145,7 +147,7 @@ describe('FieldFormat class', function () {
};
const f = new TestFormat();
- expect(f.convert('val', 'html')).to.be('html');
+ expect(f.convert('val', 'html')).to.be('html');
});
it('formats a value as " - " when no value is specified', function () {
diff --git a/src/ui/public/index_patterns/_field_format/__tests__/content_types.js b/src/ui/public/index_patterns/_field_format/__tests__/content_types.js
new file mode 100644
index 0000000000000..8fdb5acfdd485
--- /dev/null
+++ b/src/ui/public/index_patterns/_field_format/__tests__/content_types.js
@@ -0,0 +1,99 @@
+import angular from 'angular';
+import $ from 'jquery';
+import ngMock from 'ng_mock';
+import sinon from 'sinon';
+import expect from 'expect.js';
+import { escape } from 'lodash';
+
+import { IndexPatternsFieldFormatContentTypesProvider } from '../content_types';
+
+describe('index_patterns/_field_format/content_types', () => {
+
+ let render;
+ const callMe = sinon.stub();
+ afterEach(() => callMe.reset());
+
+ function getAllContents(node) {
+ return [...node.childNodes].reduce((acc, child) => {
+ return acc.concat(child, getAllContents(child));
+ }, []);
+ }
+
+ angular.module('testApp', [])
+ .directive('testDirective', () => ({
+ restrict: 'EACM',
+ link: callMe
+ }));
+
+ beforeEach(ngMock.module('testApp'));
+ beforeEach(ngMock.inject(($injector) => {
+ const contentTypes = new IndexPatternsFieldFormatContentTypesProvider();
+ const $rootScope = $injector.get('$rootScope');
+ const $compile = $injector.get('$compile');
+
+ $rootScope.callMe = callMe;
+
+ render = (convert) => {
+ const $el = $('
');
+ const { html } = contentTypes.setup({ _convert: { html: convert } });
+ $compile($el.html(html(`
+
+
+
{{callMe()}}
+
+
+ `)))($rootScope);
+ return $el;
+ };
+ }));
+
+ it('no element directive', () => {
+ const $el = render(value => `
+
${escape(value)}
+ `);
+
+ expect($el.find('test-directive')).to.have.length(1);
+ sinon.assert.notCalled(callMe);
+ });
+
+ it('no attribute directive', () => {
+ const $el = render(value => `
+
${escape(value)}
+ `);
+
+ expect($el.find('[test-directive]')).to.have.length(1);
+ sinon.assert.notCalled(callMe);
+ });
+
+ it('no comment directive', () => {
+ const $el = render(value => `
+
+
${escape(value)}
+ `);
+
+ const comments = getAllContents($el.get(0))
+ .filter(node => node.nodeType === 8);
+
+ expect(comments).to.have.length(1);
+ expect(comments[0].textContent).to.contain('test-directive');
+ sinon.assert.notCalled(callMe);
+ });
+
+ it('no class directive', () => {
+ const $el = render(value => `
+
${escape(value)}
+ `);
+
+ expect($el.find('.test-directive')).to.have.length(1);
+ sinon.assert.notCalled(callMe);
+ });
+
+ it('no interpolation', () => {
+ const $el = render(value => `
+
${escape(value)}
+ `);
+
+ expect($el.find('.foo')).to.have.length(1);
+ sinon.assert.notCalled(callMe);
+ });
+});
diff --git a/src/ui/public/index_patterns/_field_format/content_types.js b/src/ui/public/index_patterns/_field_format/content_types.js
index 4da552e024a1a..55203de053d3e 100644
--- a/src/ui/public/index_patterns/_field_format/content_types.js
+++ b/src/ui/public/index_patterns/_field_format/content_types.js
@@ -5,7 +5,7 @@ export default function contentTypesProvider() {
const types = {
html: function (format, convert) {
- return function recurse(value, field, hit) {
+ function recurse(value, field, hit) {
if (value == null) {
return _.asPrettyString(value);
}
@@ -22,6 +22,10 @@ export default function contentTypesProvider() {
});
return subVals.join(',' + (useMultiLine ? '\n' : ' '));
+ }
+
+ return function (...args) {
+ return `
${recurse(...args)}`;
};
},
diff --git a/src/ui/public/stringify/__tests__/_color.js b/src/ui/public/stringify/__tests__/_color.js
index c918155b3164c..d82f3c1e59a9d 100644
--- a/src/ui/public/stringify/__tests__/_color.js
+++ b/src/ui/public/stringify/__tests__/_color.js
@@ -21,10 +21,14 @@ describe('Color Format', function () {
background: 'yellow'
}]
});
- expect(colorer.convert(99, 'html')).to.eql('99');
- expect(colorer.convert(100, 'html')).to.eql('
100');
- expect(colorer.convert(150, 'html')).to.eql('
150');
- expect(colorer.convert(151, 'html')).to.eql('151');
+ expect(colorer.convert(99, 'html')).to.eql('
99');
+ expect(colorer.convert(100, 'html')).to.eql(
+ '
100'
+ );
+ expect(colorer.convert(150, 'html')).to.eql(
+ '
150'
+ );
+ expect(colorer.convert(151, 'html')).to.eql('
151');
});
it('should not convert invalid ranges', function () {
@@ -36,7 +40,7 @@ describe('Color Format', function () {
background: 'yellow'
}]
});
- expect(colorer.convert(99, 'html')).to.eql('99');
+ expect(colorer.convert(99, 'html')).to.eql('
99');
});
});
@@ -52,15 +56,23 @@ describe('Color Format', function () {
});
const converter = colorer.getConverterFor('html');
- expect(converter('B', 'html')).to.eql('B');
- expect(converter('AAA', 'html')).to.eql('
AAA');
- expect(converter('AB', 'html')).to.eql('
AB');
- expect(converter('a', 'html')).to.eql('a');
+ expect(converter('B', 'html')).to.eql('
B');
+ expect(converter('AAA', 'html')).to.eql(
+ '
AAA'
+ );
+ expect(converter('AB', 'html')).to.eql(
+ '
AB'
+ );
+ expect(converter('a', 'html')).to.eql('
a');
- expect(converter('B', 'html')).to.eql('B');
- expect(converter('AAA', 'html')).to.eql('
AAA');
- expect(converter('AB', 'html')).to.eql('
AB');
- expect(converter('a', 'html')).to.eql('a');
+ expect(converter('B', 'html')).to.eql('
B');
+ expect(converter('AAA', 'html')).to.eql(
+ '
AAA'
+ );
+ expect(converter('AB', 'html')).to.eql(
+ '
AB'
+ );
+ expect(converter('a', 'html')).to.eql('
a');
});
});
});
diff --git a/src/ui/public/stringify/__tests__/_source.js b/src/ui/public/stringify/__tests__/_source.js
index 3f734eabbe7ba..0efa0c3352409 100644
--- a/src/ui/public/stringify/__tests__/_source.js
+++ b/src/ui/public/stringify/__tests__/_source.js
@@ -29,12 +29,14 @@ describe('_source formatting', function () {
it('should use the text content type if a field is not passed', function () {
const hit = _.first(hits);
- expect(convertHtml(hit._source)).to.be(JSON.stringify(hit._source));
+ expect(convertHtml(hit._source)).to.be(`
${JSON.stringify(hit._source)}`);
});
it('uses the _source, field, and hit to create a
', function () {
const hit = _.first(hits);
- const $dl = $(convertHtml(hit._source, indexPattern.fields.byName._source, hit));
+ const $nonBindable = $(convertHtml(hit._source, indexPattern.fields.byName._source, hit));
+ expect($nonBindable.is('span[ng-non-bindable]')).to.be.ok();
+ const $dl = $nonBindable.children();
expect($dl.is('dl')).to.be.ok();
expect($dl.find('dt')).to.have.length(_.keys(indexPattern.flattenHit(hit)).length);
});
diff --git a/src/ui/public/stringify/__tests__/_url.js b/src/ui/public/stringify/__tests__/_url.js
index d7dafd717fa88..d3a32773dfa80 100644
--- a/src/ui/public/stringify/__tests__/_url.js
+++ b/src/ui/public/stringify/__tests__/_url.js
@@ -11,6 +11,11 @@ describe('Url Format', function () {
fieldFormats = Private(RegistryFieldFormatsProvider);
}));
+ const unwrap = $el => {
+ expect($el.is('span[ng-non-bindable]')).to.be.ok();
+ return $el.children();
+ };
+
describe('Url Format', function () {
let Url;
@@ -21,7 +26,7 @@ describe('Url Format', function () {
it('ouputs a simple tab by default', function () {
const url = new Url();
- const $a = $(url.convert('http://elastic.co', 'html'));
+ const $a = unwrap($(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');
@@ -32,7 +37,7 @@ describe('Url Format', function () {
it('outputs an if type === "img"', function () {
const url = new Url({ type: 'img' });
- const $img = $(url.convert('http://elastic.co', 'html'));
+ const $img = unwrap($(url.convert('http://elastic.co', 'html')));
expect($img.is('img')).to.be(true);
expect($img.attr('src')).to.be('http://elastic.co');
});
@@ -40,7 +45,7 @@ describe('Url Format', function () {
describe('url template', function () {
it('accepts a template', function () {
const url = new Url({ urlTemplate: 'url: {{ value }}' });
- const $a = $(url.convert('url', 'html'));
+ const $a = unwrap($(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');
@@ -57,7 +62,7 @@ describe('Url Format', function () {
describe('label template', function () {
it('accepts a template', function () {
const url = new Url({ labelTemplate: 'extension: {{ value }}' });
- const $a = $(url.convert('php', 'html'));
+ const $a = unwrap($(url.convert('php', 'html')));
expect($a.is('a')).to.be(true);
expect($a.size()).to.be(1);
expect($a.attr('href')).to.be('php');