mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[FieldFormats] Add editors tests (#107770)
This commit is contained in:
parent
7d6a2b520f
commit
6450df1885
16 changed files with 655 additions and 55 deletions
|
@ -43,6 +43,7 @@ exports[`BytesFormatEditor should render normally 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="numberEditorFormatPattern"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
placeholder="0,0.[000]b"
|
||||
|
|
|
@ -45,6 +45,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = `
|
|||
Object {
|
||||
"available": [Function],
|
||||
"color": "danger",
|
||||
"data-test-subj": "colorEditorRemoveColor",
|
||||
"description": "Delete color format",
|
||||
"icon": "trash",
|
||||
"name": "Delete",
|
||||
|
@ -83,6 +84,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = `
|
|||
size="m"
|
||||
/>
|
||||
<EuiButton
|
||||
data-test-subj="colorEditorAddColor"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
|
@ -144,6 +146,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] =
|
|||
Object {
|
||||
"available": [Function],
|
||||
"color": "danger",
|
||||
"data-test-subj": "colorEditorRemoveColor",
|
||||
"description": "Delete color format",
|
||||
"icon": "trash",
|
||||
"name": "Delete",
|
||||
|
@ -175,6 +178,7 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] =
|
|||
size="m"
|
||||
/>
|
||||
<EuiButton
|
||||
data-test-subj="colorEditorAddColor"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
|
@ -236,6 +240,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`]
|
|||
Object {
|
||||
"available": [Function],
|
||||
"color": "danger",
|
||||
"data-test-subj": "colorEditorRemoveColor",
|
||||
"description": "Delete color format",
|
||||
"icon": "trash",
|
||||
"name": "Delete",
|
||||
|
@ -267,6 +272,7 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`]
|
|||
size="m"
|
||||
/>
|
||||
<EuiButton
|
||||
data-test-subj="colorEditorAddColor"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
|
|
|
@ -96,6 +96,7 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
return (
|
||||
<EuiFieldText
|
||||
value={value}
|
||||
data-test-subj={`colorEditorKeyPattern ${item.index}`}
|
||||
onChange={(e) => {
|
||||
this.onColorChange(
|
||||
{
|
||||
|
@ -120,6 +121,7 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
return (
|
||||
<EuiFieldText
|
||||
value={value}
|
||||
data-test-subj={`colorEditorKeyRange ${item.index}`}
|
||||
onChange={(e) => {
|
||||
this.onColorChange(
|
||||
{
|
||||
|
@ -144,6 +146,7 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
return (
|
||||
<EuiColorPicker
|
||||
color={color}
|
||||
data-test-subj={`colorEditorColorPicker ${item.index}`}
|
||||
onChange={(newColor) => {
|
||||
this.onColorChange(
|
||||
{
|
||||
|
@ -168,6 +171,7 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
return (
|
||||
<EuiColorPicker
|
||||
color={color}
|
||||
data-test-subj={`colorEditorBackgroundPicker ${item.index}`}
|
||||
onChange={(newColor) => {
|
||||
this.onColorChange(
|
||||
{
|
||||
|
@ -220,6 +224,7 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
icon: 'trash',
|
||||
color: 'danger',
|
||||
available: () => items.length > 1,
|
||||
'data-test-subj': 'colorEditorRemoveColor',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -229,7 +234,12 @@ export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorForm
|
|||
<Fragment>
|
||||
<EuiBasicTable items={items} columns={columns} />
|
||||
<EuiSpacer size="m" />
|
||||
<EuiButton iconType="plusInCircle" size="s" onClick={this.addColor}>
|
||||
<EuiButton
|
||||
iconType="plusInCircle"
|
||||
size="s"
|
||||
onClick={this.addColor}
|
||||
data-test-subj={'colorEditorAddColor'}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="indexPatternFieldEditor.color.addColorButton"
|
||||
defaultMessage="Add color"
|
||||
|
|
|
@ -19,6 +19,7 @@ exports[`DurationFormatEditor should not render show suffix on dynamic output 1`
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorInputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
@ -49,6 +50,7 @@ exports[`DurationFormatEditor should not render show suffix on dynamic output 1`
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorOutputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
@ -198,6 +200,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorInputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
@ -228,6 +231,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorOutputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
@ -310,6 +314,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorInputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
@ -340,6 +345,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
|
|||
labelType="label"
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="durationEditorOutputFormat"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
|
|
@ -103,6 +103,7 @@ export class DurationFormatEditor extends DefaultFormatEditor<
|
|||
error={hasDecimalError ? null : error}
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj={'durationEditorInputFormat'}
|
||||
value={formatParams.inputFormat}
|
||||
options={format.type.inputFormats.map((fmt: InputFormat) => {
|
||||
return {
|
||||
|
@ -126,6 +127,7 @@ export class DurationFormatEditor extends DefaultFormatEditor<
|
|||
isInvalid={!!error}
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj={'durationEditorOutputFormat'}
|
||||
value={formatParams.outputFormat}
|
||||
options={format.type.outputFormats.map((fmt: OutputFormat) => {
|
||||
return {
|
||||
|
|
|
@ -43,6 +43,7 @@ exports[`NumberFormatEditor should render normally 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="numberEditorFormatPattern"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
placeholder="0,0.[000]"
|
||||
|
|
|
@ -66,6 +66,7 @@ export class NumberFormatEditor extends DefaultFormatEditor<NumberFormatEditorPa
|
|||
error={error}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj={'numberEditorFormatPattern'}
|
||||
value={formatParams.pattern}
|
||||
placeholder={defaultPattern}
|
||||
onChange={(e) => {
|
||||
|
|
|
@ -43,6 +43,7 @@ exports[`PercentFormatEditor should render normally 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="numberEditorFormatPattern"
|
||||
isInvalid={false}
|
||||
onChange={[Function]}
|
||||
placeholder="0,0.[000]%"
|
||||
|
|
|
@ -28,6 +28,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn
|
|||
Object {
|
||||
"available": [Function],
|
||||
"color": "danger",
|
||||
"data-test-subj": "staticLookupEditorRemoveEntry",
|
||||
"description": "Delete entry",
|
||||
"icon": "trash",
|
||||
"name": "Delete",
|
||||
|
@ -67,6 +68,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn
|
|||
size="m"
|
||||
/>
|
||||
<EuiButton
|
||||
data-test-subj="staticLookupEditorAddEntry"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
|
@ -96,6 +98,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="staticLookupEditorUnknownValue"
|
||||
onChange={[Function]}
|
||||
placeholder="Leave blank to keep value as-is"
|
||||
value="test value"
|
||||
|
@ -135,6 +138,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = `
|
|||
Object {
|
||||
"available": [Function],
|
||||
"color": "danger",
|
||||
"data-test-subj": "staticLookupEditorRemoveEntry",
|
||||
"description": "Delete entry",
|
||||
"icon": "trash",
|
||||
"name": "Delete",
|
||||
|
@ -168,6 +172,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = `
|
|||
size="m"
|
||||
/>
|
||||
<EuiButton
|
||||
data-test-subj="staticLookupEditorAddEntry"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
|
@ -197,6 +202,7 @@ exports[`StaticLookupFormatEditor should render normally 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="staticLookupEditorUnknownValue"
|
||||
onChange={[Function]}
|
||||
placeholder="Leave blank to keep value as-is"
|
||||
value=""
|
||||
|
|
|
@ -81,6 +81,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor<StaticLookupFo
|
|||
return (
|
||||
<EuiFieldText
|
||||
value={value || ''}
|
||||
data-test-subj={`staticLookupEditorKey ${item.index}`}
|
||||
onChange={(e) => {
|
||||
this.onLookupChange(
|
||||
{
|
||||
|
@ -105,6 +106,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor<StaticLookupFo
|
|||
return (
|
||||
<EuiFieldText
|
||||
value={value || ''}
|
||||
data-test-subj={`staticLookupEditorValue ${item.index}`}
|
||||
onChange={(e) => {
|
||||
this.onLookupChange(
|
||||
{
|
||||
|
@ -136,6 +138,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor<StaticLookupFo
|
|||
type: 'icon',
|
||||
icon: 'trash',
|
||||
color: 'danger',
|
||||
'data-test-subj': 'staticLookupEditorRemoveEntry',
|
||||
available: () => items.length > 1,
|
||||
},
|
||||
],
|
||||
|
@ -147,7 +150,12 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor<StaticLookupFo
|
|||
<Fragment>
|
||||
<EuiBasicTable items={items} columns={columns} style={{ maxWidth: '400px' }} />
|
||||
<EuiSpacer size="m" />
|
||||
<EuiButton iconType="plusInCircle" size="s" onClick={this.addLookup}>
|
||||
<EuiButton
|
||||
iconType="plusInCircle"
|
||||
size="s"
|
||||
onClick={this.addLookup}
|
||||
data-test-subj={'staticLookupEditorAddEntry'}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="indexPatternFieldEditor.staticLookup.addEntryButton"
|
||||
defaultMessage="Add entry"
|
||||
|
@ -164,6 +172,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor<StaticLookupFo
|
|||
>
|
||||
<EuiFieldText
|
||||
value={formatParams.unknownKeyValue || ''}
|
||||
data-test-subj={'staticLookupEditorUnknownValue'}
|
||||
placeholder={i18n.translate(
|
||||
'indexPatternFieldEditor.staticLookup.leaveBlankPlaceholder',
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ exports[`TruncateFormatEditor should render normally 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
data-test-subj="truncateEditorLength"
|
||||
defaultValue={5}
|
||||
isInvalid={false}
|
||||
min={1}
|
||||
|
|
|
@ -48,6 +48,7 @@ export class TruncateFormatEditor extends DefaultFormatEditor<TruncateFormatEdit
|
|||
<EuiFieldNumber
|
||||
defaultValue={formatParams.fieldLength}
|
||||
min={1}
|
||||
data-test-subj={'truncateEditorLength'}
|
||||
onChange={(e) => {
|
||||
if (e.target.checkValidity()) {
|
||||
this.onChange({
|
||||
|
|
|
@ -15,6 +15,7 @@ import { RandomnessService } from './randomness';
|
|||
import { SecurityServiceProvider } from './security';
|
||||
import { EsDeleteAllIndicesProvider } from './es_delete_all_indices';
|
||||
import { SavedObjectInfoService } from './saved_object_info';
|
||||
import { IndexPatternsService } from './index_patterns';
|
||||
|
||||
export const services = {
|
||||
deployment: DeploymentService,
|
||||
|
@ -26,4 +27,5 @@ export const services = {
|
|||
security: SecurityServiceProvider,
|
||||
esDeleteAllIndices: EsDeleteAllIndicesProvider,
|
||||
savedObjectInfo: SavedObjectInfoService,
|
||||
indexPatterns: IndexPatternsService,
|
||||
};
|
||||
|
|
35
test/common/services/index_patterns.ts
Normal file
35
test/common/services/index_patterns.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { FtrService } from '../ftr_provider_context';
|
||||
import { IndexPatternSpec } from '../../../src/plugins/data/common';
|
||||
|
||||
export class IndexPatternsService extends FtrService {
|
||||
private readonly kibanaServer = this.ctx.getService('kibanaServer');
|
||||
|
||||
/**
|
||||
* Create a new index pattern
|
||||
*/
|
||||
async create(
|
||||
indexPattern: { title: string },
|
||||
{ override = false }: { override: boolean } = { override: false }
|
||||
): Promise<IndexPatternSpec> {
|
||||
const response = await this.kibanaServer.request<{
|
||||
index_pattern: IndexPatternSpec;
|
||||
}>({
|
||||
path: '/api/index_patterns/index_pattern',
|
||||
method: 'POST',
|
||||
body: {
|
||||
override,
|
||||
index_pattern: indexPattern,
|
||||
},
|
||||
});
|
||||
|
||||
return response.data.index_pattern;
|
||||
}
|
||||
}
|
|
@ -1,53 +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.
|
||||
*/
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const browser = getService('browser');
|
||||
const PageObjects = getPageObjects(['settings']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('field formatter', function () {
|
||||
this.tags(['skipFirefox']);
|
||||
|
||||
before(async function () {
|
||||
await browser.setWindowSize(1200, 800);
|
||||
await esArchiver.load('test/functional/fixtures/es_archiver/discover');
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await kibanaServer.uiSettings.update({});
|
||||
});
|
||||
|
||||
after(async function afterAll() {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await esArchiver.emptyKibanaIndex();
|
||||
});
|
||||
|
||||
describe('set and change field formatter', function describeIndexTests() {
|
||||
// addresses https://github.com/elastic/kibana/issues/93349
|
||||
it('can change format more than once', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaIndexPatterns();
|
||||
await PageObjects.settings.clickIndexPatternLogstash();
|
||||
await PageObjects.settings.clickAddField();
|
||||
await PageObjects.settings.setFieldType('Long');
|
||||
const formatRow = await testSubjects.find('formatRow');
|
||||
const formatRowToggle = (
|
||||
await formatRow.findAllByCssSelector('[data-test-subj="toggle"]')
|
||||
)[0];
|
||||
|
||||
await formatRowToggle.click();
|
||||
await PageObjects.settings.setFieldFormat('duration');
|
||||
await PageObjects.settings.setFieldFormat('bytes');
|
||||
await PageObjects.settings.setFieldFormat('duration');
|
||||
await testSubjects.click('euiFlyoutCloseButton');
|
||||
await PageObjects.settings.closeIndexPatternFieldEditor();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
571
test/functional/apps/management/_field_formatter.ts
Normal file
571
test/functional/apps/management/_field_formatter.ts
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { ES_FIELD_TYPES } from '@kbn/field-types';
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { FIELD_FORMAT_IDS } from '../../../../src/plugins/field_formats/common';
|
||||
import { WebElementWrapper } from '../../services/lib/web_element_wrapper';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const browser = getService('browser');
|
||||
const PageObjects = getPageObjects(['settings', 'common']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const es = getService('es');
|
||||
const indexPatterns = getService('indexPatterns');
|
||||
const toasts = getService('toasts');
|
||||
|
||||
describe('field formatter', function () {
|
||||
this.tags(['skipFirefox']);
|
||||
|
||||
before(async function () {
|
||||
await browser.setWindowSize(1200, 800);
|
||||
await esArchiver.load('test/functional/fixtures/es_archiver/discover');
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await kibanaServer.uiSettings.update({});
|
||||
});
|
||||
|
||||
after(async function afterAll() {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await esArchiver.emptyKibanaIndex();
|
||||
});
|
||||
|
||||
describe('set and change field formatter', function describeIndexTests() {
|
||||
// addresses https://github.com/elastic/kibana/issues/93349
|
||||
it('can change format more than once', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaIndexPatterns();
|
||||
await PageObjects.settings.clickIndexPatternLogstash();
|
||||
await PageObjects.settings.clickAddField();
|
||||
await PageObjects.settings.setFieldType('Long');
|
||||
const formatRow = await testSubjects.find('formatRow');
|
||||
const formatRowToggle = (
|
||||
await formatRow.findAllByCssSelector('[data-test-subj="toggle"]')
|
||||
)[0];
|
||||
|
||||
await formatRowToggle.click();
|
||||
await PageObjects.settings.setFieldFormat('duration');
|
||||
await PageObjects.settings.setFieldFormat('bytes');
|
||||
await PageObjects.settings.setFieldFormat('duration');
|
||||
await testSubjects.click('euiFlyoutCloseButton');
|
||||
await PageObjects.settings.closeIndexPatternFieldEditor();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* The purpose of these tests is to cover **editing experience** of different field formats editors,
|
||||
* The logic of each converter is extensively covered by unit tests.
|
||||
* TODO: these tests also could check field formats behaviour with different combinations of browser locale, timezone and ui settings
|
||||
*/
|
||||
describe('field format editors', () => {
|
||||
describe('String format', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.TEXT,
|
||||
fieldValue: 'A regular text',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'A regular text',
|
||||
|
||||
// check available formats for ES_FIELD_TYPES.TEXT
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.COLOR,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.TRUNCATE,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.TEXT,
|
||||
fieldValue: 'A regular text',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'a regular text',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'lower');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'a keyword',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'A KEYWORD',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'upper');
|
||||
},
|
||||
// check available formats for ES_FIELD_TYPES.KEYWORD
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.COLOR,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.TRUNCATE,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'a keyword',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'A Keyword',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'title');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'com.organizations.project.ClassName',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'c.o.p.ClassName',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'short');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'SGVsbG8gd29ybGQ=',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: 'Hello world',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'base64');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: '%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: '안녕 키바나',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.selectValue('stringEditorTransform', 'urlparam');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: '123456789',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.TRUNCATE,
|
||||
expectFormattedValue: '123...',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('truncateEditorLength', '3');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.INTEGER,
|
||||
fieldValue: 324,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STRING,
|
||||
expectFormattedValue: '324',
|
||||
// check available formats for ES_FIELD_TYPES.INTEGER
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.BYTES,
|
||||
FIELD_FORMAT_IDS.COLOR,
|
||||
FIELD_FORMAT_IDS.DURATION,
|
||||
FIELD_FORMAT_IDS.NUMBER,
|
||||
FIELD_FORMAT_IDS.PERCENT,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('Number format', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 324,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.NUMBER,
|
||||
expectFormattedValue: '324',
|
||||
// check available formats for ES_FIELD_TYPES.LONG
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.BYTES,
|
||||
FIELD_FORMAT_IDS.COLOR,
|
||||
FIELD_FORMAT_IDS.DURATION,
|
||||
FIELD_FORMAT_IDS.NUMBER,
|
||||
FIELD_FORMAT_IDS.PERCENT,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 324,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.NUMBER,
|
||||
expectFormattedValue: '+324',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('numberEditorFormatPattern', '+0,0');
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('URL format', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 100,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.URL,
|
||||
expectFormattedValue: 'https://elastic.co/?value=100',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue(
|
||||
'urlEditorUrlTemplate',
|
||||
'https://elastic.co/?value={{value}}'
|
||||
);
|
||||
},
|
||||
expect: async (renderedValueContainer) => {
|
||||
expect(
|
||||
await (await renderedValueContainer.findByTagName('a')).getAttribute('href')
|
||||
).to.be('https://elastic.co/?value=100');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 100,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.URL,
|
||||
expectFormattedValue: 'url label',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue(
|
||||
'urlEditorUrlTemplate',
|
||||
'https://elastic.co/?value={{value}}'
|
||||
);
|
||||
await testSubjects.setValue('urlEditorLabelTemplate', 'url label');
|
||||
},
|
||||
expect: async (renderedValueContainer) => {
|
||||
expect(
|
||||
await (await renderedValueContainer.findByTagName('a')).getAttribute('href')
|
||||
).to.be('https://elastic.co/?value=100');
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('Date format', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.DATE,
|
||||
fieldValue: '2021-08-05T15:05:37.151Z',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.DATE,
|
||||
expectFormattedValue: 'Aug 5, 2021',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('dateEditorPattern', 'MMM D, YYYY');
|
||||
},
|
||||
// check available formats for ES_FIELD_TYPES.DATE
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.DATE,
|
||||
FIELD_FORMAT_IDS.DATE_NANOS,
|
||||
FIELD_FORMAT_IDS.RELATIVE_DATE,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.DATE_NANOS,
|
||||
fieldValue: '2015-01-01T12:10:30.123456789Z',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.DATE,
|
||||
expectFormattedValue: 'Jan 1, 2015 @ 12:10:30.123',
|
||||
// check available formats for ES_FIELD_TYPES.DATE_NANOS
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.DATE,
|
||||
FIELD_FORMAT_IDS.DATE_NANOS,
|
||||
FIELD_FORMAT_IDS.RELATIVE_DATE,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.DATE_NANOS,
|
||||
fieldValue: '2015-01-01T12:10:30.123456789Z',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.DATE_NANOS,
|
||||
expectFormattedValue: 'Jan 1, 2015 @ 12:10:30.123456789',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('Static lookup format', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'look me up',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
expectFormattedValue: 'looked up!',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.click('staticLookupEditorAddEntry');
|
||||
await testSubjects.setValue('~staticLookupEditorKey', 'look me up');
|
||||
await testSubjects.setValue('~staticLookupEditorValue', 'looked up!');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.BOOLEAN,
|
||||
fieldValue: 'true',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
// check available formats for ES_FIELD_TYPES.BOOLEAN
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
expectFormattedValue: 'yes',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.click('staticLookupEditorAddEntry');
|
||||
await testSubjects.setValue('~staticLookupEditorKey', 'true');
|
||||
await testSubjects.setValue('~staticLookupEditorValue', 'yes');
|
||||
await testSubjects.setValue('staticLookupEditorUnknownValue', 'no');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.BOOLEAN,
|
||||
fieldValue: 'false',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
expectFormattedValue: 'no',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.click('staticLookupEditorAddEntry');
|
||||
await testSubjects.setValue('~staticLookupEditorKey', 'true');
|
||||
await testSubjects.setValue('~staticLookupEditorValue', 'yes');
|
||||
await testSubjects.setValue('staticLookupEditorUnknownValue', 'no');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.BOOLEAN,
|
||||
fieldValue: 'false',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
expectFormattedValue: 'false',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.click('staticLookupEditorAddEntry');
|
||||
await testSubjects.setValue('~staticLookupEditorKey', 'true');
|
||||
await testSubjects.setValue('~staticLookupEditorValue', 'yes');
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('Other formats', () => {
|
||||
testFormatEditors([
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 123292,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.DURATION,
|
||||
expectFormattedValue: '2 minutes',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('durationEditorInputFormat', 'milliseconds');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.DOUBLE,
|
||||
fieldValue: 0.1,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.PERCENT,
|
||||
// check available formats for ES_FIELD_TYPES.DOUBLE
|
||||
expectFormatterTypes: [
|
||||
FIELD_FORMAT_IDS.BOOLEAN,
|
||||
FIELD_FORMAT_IDS.BYTES,
|
||||
FIELD_FORMAT_IDS.COLOR,
|
||||
FIELD_FORMAT_IDS.DURATION,
|
||||
FIELD_FORMAT_IDS.NUMBER,
|
||||
FIELD_FORMAT_IDS.PERCENT,
|
||||
FIELD_FORMAT_IDS.STATIC_LOOKUP,
|
||||
FIELD_FORMAT_IDS.STRING,
|
||||
FIELD_FORMAT_IDS.URL,
|
||||
],
|
||||
expectFormattedValue: '10.0%',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('numberEditorFormatPattern', '0.0%');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.LONG,
|
||||
fieldValue: 1990000000,
|
||||
applyFormatterType: FIELD_FORMAT_IDS.BYTES,
|
||||
expectFormattedValue: '2GB',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.setValue('numberEditorFormatPattern', '0b');
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldType: ES_FIELD_TYPES.KEYWORD,
|
||||
fieldValue: 'red',
|
||||
applyFormatterType: FIELD_FORMAT_IDS.COLOR,
|
||||
expectFormattedValue: 'red',
|
||||
beforeSave: async () => {
|
||||
await testSubjects.click('colorEditorAddColor');
|
||||
await testSubjects.setValue('~colorEditorKeyPattern', 'red');
|
||||
await testSubjects.setValue('~colorEditorColorPicker', '#ffffff');
|
||||
await testSubjects.setValue('~colorEditorBackgroundPicker', '#ff0000');
|
||||
},
|
||||
expect: async (renderedValueContainer) => {
|
||||
const span = await renderedValueContainer.findByTagName('span');
|
||||
expect(await span.getComputedStyle('color')).to.be('rgba(255, 255, 255, 1)');
|
||||
expect(await span.getComputedStyle('background-color')).to.be('rgba(255, 0, 0, 1)');
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Runs a field format editors tests covering data setup, editing a field and checking a resulting formatting in Discover app
|
||||
* TODO: might be useful to reuse this util for runtime fields formats tests
|
||||
* @param specs - {@link FieldFormatEditorSpecDescriptor}
|
||||
*/
|
||||
function testFormatEditors(specs: FieldFormatEditorSpecDescriptor[]) {
|
||||
const indexTitle = 'field_formats_management_functional_tests';
|
||||
let indexPatternId: string;
|
||||
let testDocumentId: string;
|
||||
|
||||
before(async () => {
|
||||
if ((await es.indices.exists({ index: indexTitle })).body) {
|
||||
await es.indices.delete({ index: indexTitle });
|
||||
}
|
||||
|
||||
await es.indices.create({
|
||||
index: indexTitle,
|
||||
body: {
|
||||
mappings: {
|
||||
properties: specs.reduce((properties, spec, index) => {
|
||||
properties[`${index}`] = { type: spec.fieldType };
|
||||
return properties;
|
||||
}, {} as Record<string, { type: ES_FIELD_TYPES }>),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const docResult = await es.index({
|
||||
index: indexTitle,
|
||||
body: specs.reduce((properties, spec, index) => {
|
||||
properties[`${index}`] = spec.fieldValue;
|
||||
return properties;
|
||||
}, {} as Record<string, FieldFormatEditorSpecDescriptor['fieldValue']>),
|
||||
refresh: 'wait_for',
|
||||
});
|
||||
testDocumentId = docResult.body._id;
|
||||
|
||||
const indexPatternResult = await indexPatterns.create(
|
||||
{ title: indexTitle },
|
||||
{ override: true }
|
||||
);
|
||||
indexPatternId = indexPatternResult.id!;
|
||||
});
|
||||
|
||||
describe('edit formats', () => {
|
||||
before(async () => {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaIndexPatterns();
|
||||
await PageObjects.settings.clickIndexPatternByName(indexTitle);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
try {
|
||||
await PageObjects.settings.controlChangeSave();
|
||||
} catch (e) {
|
||||
// in case previous test failed in a state when save is disabled
|
||||
await PageObjects.settings.controlChangeCancel();
|
||||
}
|
||||
|
||||
await toasts.dismissAllToasts(); // dismiss "saved" toast, otherwise it could overlap save button for a next test
|
||||
});
|
||||
|
||||
specs.forEach((spec, index) => {
|
||||
const fieldName = `${index}`;
|
||||
it(
|
||||
`edit field format of "${fieldName}" field to "${spec.applyFormatterType}"` +
|
||||
spec.expectFormatterTypes
|
||||
? `, and check available formats types`
|
||||
: '',
|
||||
async () => {
|
||||
await PageObjects.settings.filterField(fieldName);
|
||||
await PageObjects.settings.openControlsByName(fieldName);
|
||||
await PageObjects.settings.toggleRow('formatRow');
|
||||
|
||||
if (spec.expectFormatterTypes) {
|
||||
expect(
|
||||
(
|
||||
await Promise.all(
|
||||
(
|
||||
await (await testSubjects.find('editorSelectedFormatId')).findAllByTagName(
|
||||
'option'
|
||||
)
|
||||
).map((option) => option.getAttribute('value'))
|
||||
)
|
||||
).filter(Boolean)
|
||||
).to.eql(spec.expectFormatterTypes);
|
||||
}
|
||||
|
||||
await PageObjects.settings.setFieldFormat(spec.applyFormatterType);
|
||||
if (spec.beforeSave) {
|
||||
await spec.beforeSave(await testSubjects.find('formatRow'));
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('check formats', async () => {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('discover', {
|
||||
hash: `/doc/${indexPatternId}/${indexTitle}?id=${testDocumentId}`,
|
||||
});
|
||||
await testSubjects.exists('doc-hit');
|
||||
});
|
||||
|
||||
specs.forEach((spec, index) => {
|
||||
it(`check field format of "${index}" field`, async () => {
|
||||
const renderedValue = await testSubjects.find(`tableDocViewRow-${index}-value`);
|
||||
const text = await renderedValue.getVisibleText();
|
||||
expect(text).to.be(spec.expectFormattedValue);
|
||||
if (spec.expect) {
|
||||
await spec.expect(renderedValue);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes a field format editor test
|
||||
*/
|
||||
interface FieldFormatEditorSpecDescriptor {
|
||||
/**
|
||||
* Raw field value to put into document
|
||||
*/
|
||||
fieldValue: string | number | boolean | null;
|
||||
/**
|
||||
* Explicitly specify a type for a {@link fieldValue}
|
||||
*/
|
||||
fieldType: ES_FIELD_TYPES;
|
||||
/**
|
||||
* Type of a field formatter to apply
|
||||
*/
|
||||
applyFormatterType: FIELD_FORMAT_IDS;
|
||||
|
||||
/**
|
||||
* Optionally check available formats for {@link fieldType}
|
||||
*/
|
||||
expectFormatterTypes?: FIELD_FORMAT_IDS[];
|
||||
|
||||
/**
|
||||
* Function to execute before field format is applied.
|
||||
* Use it set specific configuration params for applied field formatter
|
||||
* @param formatRowContainer - field format editor container
|
||||
*/
|
||||
beforeSave?: (formatRowContainer: WebElementWrapper) => Promise<void>;
|
||||
|
||||
/**
|
||||
* An expected formatted value rendered by Discover app,
|
||||
* Use this for final assertion
|
||||
*/
|
||||
expectFormattedValue: string;
|
||||
|
||||
/**
|
||||
* Run additional assertions on rendered element
|
||||
*/
|
||||
expect?: (renderedValueContainer: WebElementWrapper) => Promise<void>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue