[Field Formatters] Get rid of span ng-non-bindable (#113926)

* [Field Formatters] Get rid of span ng-non-bindable

* Remove span explicitly

* Remove span entirely

* Update src/plugins/field_formats/common/content_types/html_content_type.ts

Co-authored-by: Tim Roes <mail@timroes.de>

Co-authored-by: Tim Roes <mail@timroes.de>
This commit is contained in:
Maja Grubic 2021-10-07 14:10:18 +02:00 committed by GitHub
parent ea160a5072
commit d65715b6d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 97 deletions

View file

@ -29,17 +29,6 @@ export function formatHitProvider(dataView: DataView, defaultFormat: any) {
}
function formatHit(hit: Record<string, any>, type: string = 'html') {
if (type === 'text') {
// formatHit of type text is for react components to get rid of <span ng-non-bindable>
// since it's currently just used at the discover's doc view table, caching is not necessary
const flattened = dataView.flattenHit(hit);
const result: Record<string, any> = {};
for (const [key, value] of Object.entries(flattened)) {
result[key] = convert(hit, value, key, type);
}
return result;
}
const cached = formattedCache.get(hit);
if (cached) {
return cached;

View file

@ -14,7 +14,6 @@ import { DocViewer } from '../../../../../components/doc_viewer/doc_viewer';
import { FilterManager, IndexPattern } from '../../../../../../../../data/public';
import { TableCell } from './table_row/table_cell';
import { ElasticSearchHit, DocViewFilterFn } from '../../../../../doc_views/doc_views_types';
import { trimAngularSpan } from '../../../../../components/table/table_helper';
import { getContextUrl } from '../../../../../helpers/get_context_url';
import { getSingleDocUrl } from '../../../../../helpers/get_single_doc_url';
import { TableRowDetails } from './table_row_details';
@ -68,8 +67,7 @@ export const TableRow = ({
* Fill an element with the value of a field
*/
const displayField = (fieldName: string) => {
const text = indexPattern.formatField(row, fieldName);
const formattedField = trimAngularSpan(String(text));
const formattedField = indexPattern.formatField(row, fieldName);
// field formatters take care of escaping
// eslint-disable-next-line react/no-danger

View file

@ -9,7 +9,6 @@
import classNames from 'classnames';
import React, { Fragment, useState } from 'react';
import { FieldRecord } from './table';
import { trimAngularSpan } from './table_helper';
import { DocViewTableRowBtnCollapse } from './table_row_btn_collapse';
const COLLAPSE_LINE_LENGTH = 350;
@ -19,7 +18,7 @@ type TableFieldValueProps = FieldRecord['value'] & Pick<FieldRecord['field'], 'f
export const TableFieldValue = ({ formattedValue, field }: TableFieldValueProps) => {
const [fieldOpen, setFieldOpen] = useState(false);
const value = trimAngularSpan(String(formattedValue));
const value = String(formattedValue);
const isCollapsible = value.length > COLLAPSE_LINE_LENGTH;
const isCollapsed = isCollapsible && !fieldOpen;

View file

@ -1,14 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* Removes markup added by kibana fields html formatter
*/
export function trimAngularSpan(text: string): string {
return text.replace(/^<span ng-non-bindable>/, '').replace(/<\/span>$/, '');
}

View file

@ -50,7 +50,7 @@ export const setup = (
};
const wrap: HtmlContextTypeConvert = (value, options) => {
return `<span ng-non-bindable>${recurse(value, options)}</span>`;
return recurse(value, options);
};
return wrap;

View file

@ -26,14 +26,14 @@ describe('Color Format', () => {
jest.fn()
);
expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>99</span>');
expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99');
expect(colorer.convert(100, HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">100</span></span>'
'<span style="color:blue;background-color:yellow">100</span>'
);
expect(colorer.convert(150, HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">150</span></span>'
'<span style="color:blue;background-color:yellow">150</span>'
);
expect(colorer.convert(151, HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>151</span>');
expect(colorer.convert(151, HTML_CONTEXT_TYPE)).toBe('151');
});
test('should not convert invalid ranges', () => {
@ -51,7 +51,7 @@ describe('Color Format', () => {
jest.fn()
);
expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>99</span>');
expect(colorer.convert(99, HTML_CONTEXT_TYPE)).toBe('99');
});
});
@ -72,26 +72,26 @@ describe('Color Format', () => {
);
const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>B</span>');
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('B');
expect(converter('AAA', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AAA</span></span>'
'<span style="color:blue;background-color:yellow">AAA</span>'
);
expect(converter('AB', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB</span></span>'
'<span style="color:blue;background-color:yellow">AB</span>'
);
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>a</span>');
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('a');
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>B</span>');
expect(converter('B', HTML_CONTEXT_TYPE)).toBe('B');
expect(converter('AAA', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AAA</span></span>'
'<span style="color:blue;background-color:yellow">AAA</span>'
);
expect(converter('AB', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB</span></span>'
'<span style="color:blue;background-color:yellow">AB</span>'
);
expect(converter('AB <', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><span style="color:blue;background-color:yellow">AB &lt;</span></span>'
'<span style="color:blue;background-color:yellow">AB &lt;</span>'
);
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>a</span>');
expect(converter('a', HTML_CONTEXT_TYPE)).toBe('a');
});
test('returns original value (escaped) when regex is invalid', () => {
@ -110,7 +110,7 @@ describe('Color Format', () => {
);
const converter = colorer.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('<', HTML_CONTEXT_TYPE)).toBe('<span ng-non-bindable>&lt;</span>');
expect(converter('<', HTML_CONTEXT_TYPE)).toBe('&lt;');
});
});
});

View file

@ -28,7 +28,7 @@ describe('Source Format', () => {
};
expect(convertHtml(hit)).toBe(
'<span ng-non-bindable>{&quot;foo&quot;:&quot;bar&quot;,&quot;number&quot;:42,&quot;hello&quot;:&quot;&lt;h1&gt;World&lt;/h1&gt;&quot;,&quot;also&quot;:&quot;with \\&quot;quotes\\&quot; or &#39;single quotes&#39;&quot;}</span>'
'{&quot;foo&quot;:&quot;bar&quot;,&quot;number&quot;:42,&quot;hello&quot;:&quot;&lt;h1&gt;World&lt;/h1&gt;&quot;,&quot;also&quot;:&quot;with \\&quot;quotes\\&quot; or &#39;single quotes&#39;&quot;}'
);
});
@ -43,7 +43,7 @@ describe('Source Format', () => {
expect(
convertHtml(hit, { field: 'field', indexPattern: { formatHit: (h: string) => h }, hit })
).toMatchInlineSnapshot(
`"<span ng-non-bindable><dl class=\\"source truncate-by-height\\"><dt>foo:</dt><dd>bar</dd> <dt>number:</dt><dd>42</dd> <dt>hello:</dt><dd><h1>World</h1></dd> <dt>also:</dt><dd>with \\"quotes\\" or 'single quotes'</dd> </dl></span>"`
`"<dl class=\\"source truncate-by-height\\"><dt>foo:</dt><dd>bar</dd> <dt>number:</dt><dd>42</dd> <dt>hello:</dt><dd><h1>World</h1></dd> <dt>also:</dt><dd>with \\"quotes\\" or 'single quotes'</dd> </dl>"`
);
});
});

View file

@ -13,7 +13,7 @@ import { StringFormat } from './string';
* and we're not caring about in these tests.
*/
function stripSpan(input: string): string {
return input.replace(/^\<span ng-non-bindable\>(.*)\<\/span\>$/, '$1');
return input.replace(/^\<span\>(.*)\<\/span\>$/, '$1');
}
describe('String Format', () => {

View file

@ -14,7 +14,7 @@ describe('UrlFormat', () => {
const url = new UrlFormat({});
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><a href="http://elastic.co" target="_blank" rel="noopener noreferrer">http://elastic.co</a></span>'
'<a href="http://elastic.co" target="_blank" rel="noopener noreferrer">http://elastic.co</a>'
);
});
@ -22,7 +22,7 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'audio' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><audio controls preload="none" src="http://elastic.co"></span>'
'<audio controls preload="none" src="http://elastic.co">'
);
});
@ -31,8 +31,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;">'
);
});
@ -40,8 +40,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img', width: '12', height: '55' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:12px; max-height:55px;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:12px; max-height:55px;">'
);
});
@ -49,8 +49,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img', height: '55' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:55px;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:55px;">'
);
});
@ -58,8 +58,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img', width: '22' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:22px; max-height:none;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:22px; max-height:none;">'
);
});
@ -67,8 +67,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img', width: 'not a number' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;">'
);
});
@ -76,8 +76,8 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ type: 'img', height: 'not a number' });
expect(url.convert('http://elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;"></span>'
'<img src="http://elastic.co" alt="A dynamically-specified image located at http://elastic.co" ' +
'style="width:auto; height:auto; max-width:none; max-height:none;">'
);
});
});
@ -87,7 +87,7 @@ describe('UrlFormat', () => {
const url = new UrlFormat({ urlTemplate: 'http://{{ value }}' });
expect(url.convert('url', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><a href="http://url" target="_blank" rel="noopener noreferrer">http://url</a></span>'
'<a href="http://url" target="_blank" rel="noopener noreferrer">http://url</a>'
);
});
@ -106,7 +106,7 @@ describe('UrlFormat', () => {
});
expect(url.convert('php', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><a href="http://www.php.com" target="_blank" rel="noopener noreferrer">extension: php</a></span>'
'<a href="http://www.php.com" target="_blank" rel="noopener noreferrer">extension: php</a>'
);
});
@ -166,19 +166,19 @@ describe('UrlFormat', () => {
const converter = url.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('www.elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/app/www.elastic.co" target="_blank" rel="noopener noreferrer">www.elastic.co</a></span>'
'<a href="http://kibana/app/www.elastic.co" target="_blank" rel="noopener noreferrer">www.elastic.co</a>'
);
expect(converter('elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/app/elastic.co" target="_blank" rel="noopener noreferrer">elastic.co</a></span>'
'<a href="http://kibana/app/elastic.co" target="_blank" rel="noopener noreferrer">elastic.co</a>'
);
expect(converter('elastic')).toBe(
'<span ng-non-bindable><a href="http://kibana/app/elastic" target="_blank" rel="noopener noreferrer">elastic</a></span>'
'<a href="http://kibana/app/elastic" target="_blank" rel="noopener noreferrer">elastic</a>'
);
expect(converter('ftp://elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/app/ftp://elastic.co" target="_blank" rel="noopener noreferrer">ftp://elastic.co</a></span>'
'<a href="http://kibana/app/ftp://elastic.co" target="_blank" rel="noopener noreferrer">ftp://elastic.co</a>'
);
});
@ -191,19 +191,19 @@ describe('UrlFormat', () => {
const converter = url.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('www.elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/xyz/app/www.elastic.co" target="_blank" rel="noopener noreferrer">www.elastic.co</a></span>'
'<a href="http://kibana/xyz/app/www.elastic.co" target="_blank" rel="noopener noreferrer">www.elastic.co</a>'
);
expect(converter('elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/xyz/app/elastic.co" target="_blank" rel="noopener noreferrer">elastic.co</a></span>'
'<a href="http://kibana/xyz/app/elastic.co" target="_blank" rel="noopener noreferrer">elastic.co</a>'
);
expect(converter('elastic')).toBe(
'<span ng-non-bindable><a href="http://kibana/xyz/app/elastic" target="_blank" rel="noopener noreferrer">elastic</a></span>'
'<a href="http://kibana/xyz/app/elastic" target="_blank" rel="noopener noreferrer">elastic</a>'
);
expect(converter('ftp://elastic.co')).toBe(
'<span ng-non-bindable><a href="http://kibana/xyz/app/ftp://elastic.co" target="_blank" rel="noopener noreferrer">ftp://elastic.co</a></span>'
'<a href="http://kibana/xyz/app/ftp://elastic.co" target="_blank" rel="noopener noreferrer">ftp://elastic.co</a>'
);
});
@ -216,19 +216,17 @@ describe('UrlFormat', () => {
const converter = url.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('../app/kibana')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/abc/app/../app/kibana" target="_blank" rel="noopener noreferrer">../app/kibana</a></span>'
'<a href="http://kibana.host.com/abc/app/../app/kibana" target="_blank" rel="noopener noreferrer">../app/kibana</a>'
);
});
test('should fail gracefully if there are no parsedUrl provided', () => {
const url = new UrlFormat({});
expect(url.convert('../app/kibana', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable>../app/kibana</span>'
);
expect(url.convert('../app/kibana', HTML_CONTEXT_TYPE)).toBe('../app/kibana');
expect(url.convert('http://www.elastic.co', HTML_CONTEXT_TYPE)).toBe(
'<span ng-non-bindable><a href="http://www.elastic.co" target="_blank" rel="noopener noreferrer">http://www.elastic.co</a></span>'
'<a href="http://www.elastic.co" target="_blank" rel="noopener noreferrer">http://www.elastic.co</a>'
);
});
@ -242,15 +240,15 @@ describe('UrlFormat', () => {
const converter = url.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('#/foo')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/nbc/app/discover#/#/foo" target="_blank" rel="noopener noreferrer">#/foo</a></span>'
'<a href="http://kibana.host.com/nbc/app/discover#/#/foo" target="_blank" rel="noopener noreferrer">#/foo</a>'
);
expect(converter('/nbc/app/discover#/')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/nbc/app/discover#/" target="_blank" rel="noopener noreferrer">/nbc/app/discover#/</a></span>'
'<a href="http://kibana.host.com/nbc/app/discover#/" target="_blank" rel="noopener noreferrer">/nbc/app/discover#/</a>'
);
expect(converter('../foo/bar')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/nbc/app/../foo/bar" target="_blank" rel="noopener noreferrer">../foo/bar</a></span>'
'<a href="http://kibana.host.com/nbc/app/../foo/bar" target="_blank" rel="noopener noreferrer">../foo/bar</a>'
);
});
@ -263,23 +261,23 @@ describe('UrlFormat', () => {
const converter = url.getConverterFor(HTML_CONTEXT_TYPE) as Function;
expect(converter('10.22.55.66')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/app/10.22.55.66" target="_blank" rel="noopener noreferrer">10.22.55.66</a></span>'
'<a href="http://kibana.host.com/app/10.22.55.66" target="_blank" rel="noopener noreferrer">10.22.55.66</a>'
);
expect(converter('http://www.domain.name/app/kibana#/dashboard/')).toBe(
'<span ng-non-bindable><a href="http://www.domain.name/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">http://www.domain.name/app/kibana#/dashboard/</a></span>'
'<a href="http://www.domain.name/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">http://www.domain.name/app/kibana#/dashboard/</a>'
);
expect(converter('/app/kibana')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/app/kibana" target="_blank" rel="noopener noreferrer">/app/kibana</a></span>'
'<a href="http://kibana.host.com/app/kibana" target="_blank" rel="noopener noreferrer">/app/kibana</a>'
);
expect(converter('kibana#/dashboard/')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">kibana#/dashboard/</a></span>'
'<a href="http://kibana.host.com/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">kibana#/dashboard/</a>'
);
expect(converter('#/dashboard/')).toBe(
'<span ng-non-bindable><a href="http://kibana.host.com/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">#/dashboard/</a></span>'
'<a href="http://kibana.host.com/app/kibana#/dashboard/" target="_blank" rel="noopener noreferrer">#/dashboard/</a>'
);
});
});

View file

@ -88,7 +88,7 @@ describe('FieldFormat class', () => {
expect(text).not.toBe(html);
expect(text && text('formatted')).toBe('formatted');
expect(html && html('formatted')).toBe('<span ng-non-bindable>formatted</span>');
expect(html && html('formatted')).toBe('formatted');
});
test('can be an object, with separate text and html converter', () => {
@ -98,7 +98,7 @@ describe('FieldFormat class', () => {
expect(text).not.toBe(html);
expect(text && text('formatted text')).toBe('formatted text');
expect(html && html('formatted html')).toBe('<span ng-non-bindable>formatted html</span>');
expect(html && html('formatted html')).toBe('formatted html');
});
test('does not escape the output of the text converter', () => {
@ -110,10 +110,7 @@ describe('FieldFormat class', () => {
test('does escape the output of the text converter if used in an html context', () => {
const f = getTestFormat(undefined, constant('<script>alert("xxs");</script>'));
const expected = trimEnd(
trimStart(f.convert('', 'html'), '<span ng-non-bindable>'),
'</span>'
);
const expected = trimEnd(trimStart(f.convert('', 'html'), '<span>'), '</span>');
expect(expected).not.toContain('<');
});
@ -122,7 +119,7 @@ describe('FieldFormat class', () => {
const f = getTestFormat(undefined, constant('<img>'), constant('<img>'));
expect(f.convert('', 'text')).toBe('<img>');
expect(f.convert('', 'html')).toBe('<span ng-non-bindable><img></span>');
expect(f.convert('', 'html')).toBe('<img>');
});
});
@ -136,7 +133,7 @@ describe('FieldFormat class', () => {
test('formats a value as html, when specified via second param', () => {
const f = getTestFormat(undefined, constant('text'), constant('html'));
expect(f.convert('val', 'html')).toBe('<span ng-non-bindable>html</span>');
expect(f.convert('val', 'html')).toBe('html');
});
test('formats a value as " - " when no value is specified', () => {

View file

@ -75,14 +75,14 @@ describe('createFieldFormatter(fieldName, fieldFormatMap?, contextType?, hasColo
const formatter = createFieldFormatter('colorField', fieldFormatMap, 'html');
expect(formatter(value)).toBe(
'<span ng-non-bindable><span style="color:#D36086;background-color:#ffffff">1234567890</span></span>'
'<span style="color:#D36086;background-color:#ffffff">1234567890</span>'
);
});
it('should return number formatted value wrapped in span for colorField when color rules are applied', () => {
const formatter = createFieldFormatter('colorField', fieldFormatMap, 'html', true);
expect(formatter(value)).toBe('<span ng-non-bindable>1,234,567,890</span>');
expect(formatter(value)).toBe('1,234,567,890');
});
it('should return not formatted string value for colorField when color rules are applied', () => {
@ -95,7 +95,7 @@ describe('createFieldFormatter(fieldName, fieldFormatMap?, contextType?, hasColo
const formatter = createFieldFormatter('urlField', fieldFormatMap, 'html');
expect(formatter(value)).toBe(
'<span ng-non-bindable><a href="https://1234567890" target="_blank" rel="noopener noreferrer">1234567890</a></span>'
'<a href="https://1234567890" target="_blank" rel="noopener noreferrer">1234567890</a>'
);
});