[IndexPatterns] Clean up StubIndexPattern (#108555) (#110026)

Co-authored-by: Anton Dosov <anton.dosov@elastic.co>
This commit is contained in:
Kibana Machine 2021-08-25 08:55:33 -04:00 committed by GitHub
parent 18b31701e3
commit 229d735fee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 829 additions and 875 deletions

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
type: string;
type?: string;
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
typeMeta: string;
typeMeta?: string;
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
type: string;
type?: string;
```

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
typeMeta: string;
typeMeta?: string;
```

View file

@ -6,71 +6,404 @@
* Side Public License, v 1.
*/
import { IFieldType } from '.';
import { FieldSpec, IndexPatternField } from '.';
export const stubFields: IFieldType[] = [
{
export const createIndexPatternFieldStub = ({ spec }: { spec: FieldSpec }): IndexPatternField => {
return new IndexPatternField(spec);
};
export const stubFieldSpecMap: Record<string, FieldSpec> = {
'machine.os': {
name: 'machine.os',
esTypes: ['text'],
type: 'string',
aggregatable: false,
searchable: false,
filterable: true,
},
{
'machine.os.raw': {
name: 'machine.os.raw',
type: 'string',
esTypes: ['keyword'],
aggregatable: true,
searchable: true,
filterable: true,
},
{
'not.filterable': {
name: 'not.filterable',
type: 'string',
esTypes: ['text'],
aggregatable: true,
searchable: false,
filterable: false,
},
{
bytes: {
name: 'bytes',
type: 'number',
esTypes: ['long'],
aggregatable: true,
searchable: true,
filterable: true,
},
{
'@timestamp': {
name: '@timestamp',
type: 'date',
esTypes: ['date'],
aggregatable: true,
searchable: true,
filterable: true,
},
{
clientip: {
name: 'clientip',
type: 'ip',
esTypes: ['ip'],
aggregatable: true,
searchable: true,
filterable: true,
},
{
'bool.field': {
name: 'bool.field',
type: 'boolean',
esTypes: ['boolean'],
aggregatable: true,
searchable: true,
filterable: true,
},
{
bytes_range: {
name: 'bytes_range',
type: 'number_range',
esTypes: ['integer_range'],
aggregatable: true,
searchable: true,
filterable: true,
},
];
};
export const stubFields: IndexPatternField[] = Object.values(stubFieldSpecMap).map((spec) =>
createIndexPatternFieldStub({ spec })
);
export const stubLogstashFieldSpecMap: Record<string, FieldSpec> = {
bytes: {
name: 'bytes',
type: 'number',
esTypes: ['long'],
aggregatable: true,
searchable: true,
count: 10,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
ssl: {
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
aggregatable: true,
searchable: true,
count: 20,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
'@timestamp': {
name: '@timestamp',
type: 'date',
esTypes: ['date'],
aggregatable: true,
searchable: true,
count: 30,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
time: {
name: 'time',
type: 'date',
esTypes: ['date'],
aggregatable: true,
searchable: true,
count: 30,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
'@tags': {
name: '@tags',
type: 'string',
esTypes: ['keyword'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
utc_time: {
name: 'utc_time',
type: 'date',
esTypes: ['date'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
phpmemory: {
name: 'phpmemory',
type: 'number',
esTypes: ['integer'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
ip: {
name: 'ip',
type: 'ip',
esTypes: ['ip'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
request_body: {
name: 'request_body',
type: 'attachment',
esTypes: ['attachment'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
point: {
name: 'point',
type: 'geo_point',
esTypes: ['geo_point'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
area: {
name: 'area',
type: 'geo_shape',
esTypes: ['geo_shape'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
hashed: {
name: 'hashed',
type: 'murmur3',
esTypes: ['murmur3'],
aggregatable: false,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
'geo.coordinates': {
name: 'geo.coordinates',
type: 'geo_point',
esTypes: ['geo_point'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
extension: {
name: 'extension',
type: 'string',
esTypes: ['text'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
'extension.keyword': {
name: 'extension.keyword',
type: 'string',
esTypes: ['keyword'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
subType: {
multi: {
parent: 'extension',
},
},
isMapped: true,
},
'machine.os': {
name: 'machine.os',
type: 'string',
esTypes: ['text'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
'machine.os.raw': {
name: 'machine.os.raw',
type: 'string',
esTypes: ['keyword'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
subType: {
multi: {
parent: 'machine.os',
},
},
isMapped: true,
},
'geo.src': {
name: 'geo.src',
type: 'string',
esTypes: ['keyword'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
_id: {
name: '_id',
type: 'string',
esTypes: ['_id'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
_type: {
name: '_type',
type: 'string',
esTypes: ['_type'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
_source: {
name: '_source',
type: '_source',
esTypes: ['_source'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
'non-filterable': {
name: 'non-filterable',
type: 'string',
esTypes: ['text'],
aggregatable: true,
searchable: false,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
'non-sortable': {
name: 'non-sortable',
type: 'string',
esTypes: ['text'],
aggregatable: false,
searchable: false,
count: 0,
readFromDocValues: false,
scripted: false,
isMapped: true,
},
custom_user_field: {
name: 'custom_user_field',
type: 'conflict',
esTypes: ['conflict'],
aggregatable: true,
searchable: true,
count: 0,
readFromDocValues: true,
scripted: false,
isMapped: true,
},
'script string': {
name: 'script string',
type: 'string',
esTypes: ['text'],
aggregatable: true,
searchable: false,
count: 0,
readFromDocValues: false,
script: "'i am a string'",
lang: 'expression',
scripted: true,
isMapped: false,
},
'script number': {
name: 'script number',
type: 'number',
esTypes: ['long'],
aggregatable: true,
searchable: false,
count: 0,
readFromDocValues: true,
script: '1234',
lang: 'expression',
scripted: true,
isMapped: false,
},
'script date': {
name: 'script date',
type: 'date',
esTypes: ['date'],
aggregatable: true,
searchable: false,
count: 0,
readFromDocValues: true,
script: '1234',
lang: 'painless',
scripted: true,
isMapped: false,
},
'script murmur3': {
name: 'script murmur3',
type: 'murmur3',
esTypes: ['murmur3'],
aggregatable: true,
searchable: false,
count: 0,
readFromDocValues: true,
script: '1234',
lang: 'expression',
scripted: true,
isMapped: false,
},
};
export const stubLogstashFields: IndexPatternField[] = Object.values(
stubLogstashFieldSpecMap
).map((spec) => createIndexPatternFieldStub({ spec }));

View file

@ -6,28 +6,50 @@
* Side Public License, v 1.
*/
import { IIndexPattern } from '.';
import { stubFields } from './field.stub';
import { stubFieldSpecMap, stubLogstashFieldSpecMap } from './field.stub';
import { createStubIndexPattern } from './index_patterns/index_pattern.stub';
export { createStubIndexPattern } from './index_patterns/index_pattern.stub';
import { SavedObject } from '../../../../core/types';
import { IndexPatternAttributes } from '../types';
export const stubIndexPattern: IIndexPattern = {
id: 'logstash-*',
fields: stubFields,
title: 'logstash-*',
timeFieldName: '@timestamp',
getTimeField: () => ({ name: '@timestamp', type: 'date' }),
};
export const stubIndexPattern = createStubIndexPattern({
spec: {
id: 'logstash-*',
fields: stubFieldSpecMap,
title: 'logstash-*',
timeFieldName: '@timestamp',
},
});
export const stubIndexPatternWithFields: IIndexPattern = {
id: '1234',
title: 'logstash-*',
fields: [
{
name: 'response',
type: 'number',
esTypes: ['integer'],
aggregatable: true,
filterable: true,
searchable: true,
export const stubIndexPatternWithoutTimeField = createStubIndexPattern({
spec: {
id: 'logstash-*',
fields: stubFieldSpecMap,
title: 'logstash-*',
},
});
export const stubLogstashIndexPattern = createStubIndexPattern({
spec: {
id: 'logstash-*',
title: 'logstash-*',
timeFieldName: 'time',
fields: stubLogstashFieldSpecMap,
},
});
export function stubbedSavedObjectIndexPattern(
id: string | null = null
): SavedObject<IndexPatternAttributes> {
return {
id: id ?? '',
type: 'index-pattern',
attributes: {
timeFieldName: 'time',
fields: JSON.stringify(stubLogstashFieldSpecMap),
title: 'title',
},
],
};
version: '2',
references: [],
};
}

View file

@ -785,7 +785,7 @@ Object {
},
},
"sourceFilters": undefined,
"timeFieldName": "timestamp",
"timeFieldName": "time",
"title": "title",
"type": "index-pattern",
"typeMeta": undefined,

View file

@ -1,76 +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.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { shouldReadFieldFromDocValues, castEsToKbnFieldTypeName } from '../../../../server';
function stubbedLogstashFields() {
return [
// |aggregatable
// | |searchable
// name esType | | |metadata | subType
['bytes', 'long', true, true, { count: 10 }],
['ssl', 'boolean', true, true, { count: 20 }],
['@timestamp', 'date', true, true, { count: 30 }],
['time', 'date', true, true, { count: 30 }],
['@tags', 'keyword', true, true],
['utc_time', 'date', true, true],
['phpmemory', 'integer', true, true],
['ip', 'ip', true, true],
['request_body', 'attachment', true, true],
['point', 'geo_point', true, true],
['area', 'geo_shape', true, true],
['hashed', 'murmur3', false, true],
['geo.coordinates', 'geo_point', true, true],
['extension', 'text', true, true],
['extension.keyword', 'keyword', true, true, {}, { multi: { parent: 'extension' } }],
['machine.os', 'text', true, true],
['machine.os.raw', 'keyword', true, true, {}, { multi: { parent: 'machine.os' } }],
['geo.src', 'keyword', true, true],
['_id', '_id', true, true],
['_type', '_type', true, true],
['_source', '_source', true, true],
['non-filterable', 'text', true, false],
['non-sortable', 'text', false, false],
['custom_user_field', 'conflict', true, true],
['script string', 'text', true, false, { script: "'i am a string'" }],
['script number', 'long', true, false, { script: '1234' }],
['script date', 'date', true, false, { script: '1234', lang: 'painless' }],
['script murmur3', 'murmur3', true, false, { script: '1234' }],
].map(function (row) {
const [name, esType, aggregatable, searchable, metadata = {}, subType = undefined] = row;
const {
count = 0,
script,
lang = script ? 'expression' : undefined,
scripted = !!script,
} = metadata;
// the conflict type is actually a kbnFieldType, we
// don't have any other way to represent it here
const type = esType === 'conflict' ? esType : castEsToKbnFieldTypeName(esType);
return {
name,
type,
esTypes: [esType],
readFromDocValues: shouldReadFieldFromDocValues(aggregatable, esType),
aggregatable,
searchable,
count,
script,
lang,
scripted,
subType,
isMapped: !scripted,
};
});
}
export default stubbedLogstashFields;

View file

@ -1,26 +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.
*/
// @ts-expect-error
import stubbedLogstashFields from './logstash_fields';
const mockLogstashFields = stubbedLogstashFields();
export function stubbedSavedObjectIndexPattern(id: string | null = null) {
return {
id,
type: 'index-pattern',
attributes: {
timeFieldName: 'timestamp',
customFormats: {},
fields: mockLogstashFields,
title: 'title',
},
version: '2',
};
}

View file

@ -8,12 +8,9 @@
import { IndexPattern } from './index_pattern';
// @ts-expect-error
import mockLogStashFields from './fixtures/logstash_fields';
import { stubbedSavedObjectIndexPattern } from './fixtures/stubbed_saved_object_index_pattern';
import { fieldFormatsMock } from '../../../../field_formats/common/mocks';
import { flattenHitWrapper } from './flatten_hit';
import { stubbedSavedObjectIndexPattern } from '../index_pattern.stub';
class MockFieldFormatter {}
@ -33,7 +30,7 @@ function create(id: string) {
type,
version,
timeFieldName,
fields,
fields: JSON.parse(fields),
title,
runtimeFieldMap: {},
},

View file

@ -0,0 +1,56 @@
/*
* 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 { IndexPattern } from './index_pattern';
import { IndexPatternSpec } from '../types';
import { FieldFormatsStartCommon } from '../../../../field_formats/common';
import { fieldFormatsMock } from '../../../../field_formats/common/mocks';
/**
* Create a custom stub index pattern. Use it in your unit tests where an {@link IndexPattern} expected.
* @param spec - Serialized index pattern object
* @param opts - Specify index pattern options
* @param deps - Optionally provide dependencies, you can provide a custom field formats implementation, by default a dummy mock is used
*
* @returns - an {@link IndexPattern} instance
*
*
* @example
*
* You can provide a custom implementation or assert calls using jest.spyOn:
*
* ```ts
* const indexPattern = createStubIndexPattern({spec: {title: 'logs-*'}});
* const spy = jest.spyOn(indexPattern, 'getFormatterForField');
*
* // use `spy` as a regular jest mock
*
* ```
*/
export const createStubIndexPattern = ({
spec,
opts,
deps,
}: {
spec: IndexPatternSpec;
opts?: {
shortDotsEnable?: boolean;
metaFields?: string[];
};
deps?: {
fieldFormats?: FieldFormatsStartCommon;
};
}): IndexPattern => {
const indexPattern = new IndexPattern({
spec,
metaFields: opts?.metaFields ?? ['_id', '_type', '_source'],
shortDotsEnable: opts?.shortDotsEnable,
fieldFormats: deps?.fieldFormats ?? fieldFormatsMock,
});
return indexPattern;
};

View file

@ -11,14 +11,14 @@ import { map, last } from 'lodash';
import { IndexPattern } from './index_pattern';
import { DuplicateField } from '../../../../kibana_utils/common';
// @ts-expect-error
import mockLogStashFields from './fixtures/logstash_fields';
import { stubbedSavedObjectIndexPattern } from './fixtures/stubbed_saved_object_index_pattern';
import { IndexPatternField } from '../fields';
import { fieldFormatsMock } from '../../../../field_formats/common/mocks';
import { FieldFormat } from '../../../../field_formats/common';
import { RuntimeField } from '../types';
import { stubLogstashFields } from '../field.stub';
import { stubbedSavedObjectIndexPattern } from '../index_pattern.stub';
class MockFieldFormatter {}
@ -55,7 +55,7 @@ function create(id: string) {
type,
version,
timeFieldName,
fields: { ...fields, runtime_field: runtimeField },
fields: { ...JSON.parse(fields), runtime_field: runtimeField },
title,
runtimeFieldMap,
},
@ -101,7 +101,7 @@ describe('IndexPattern', () => {
describe('getScriptedFields', () => {
test('should return all scripted fields', () => {
const scriptedNames = mockLogStashFields()
const scriptedNames = stubLogstashFields
.filter((item: IndexPatternField) => item.scripted === true)
.map((item: IndexPatternField) => item.name);
const respNames = map(indexPattern.getScriptedFields(), 'name');
@ -151,7 +151,7 @@ describe('IndexPattern', () => {
describe('getNonScriptedFields', () => {
test('should return all non-scripted fields', () => {
const notScriptedNames = mockLogStashFields()
const notScriptedNames = stubLogstashFields
.filter((item: IndexPatternField) => item.scripted === false)
.map((item: IndexPatternField) => item.name);
notScriptedNames.push('runtime_field');

View file

@ -9,8 +9,9 @@
import { defaults } from 'lodash';
import { IndexPatternsService, IndexPattern } from '.';
import { fieldFormatsMock } from '../../../../field_formats/common/mocks';
import { stubbedSavedObjectIndexPattern } from './fixtures/stubbed_saved_object_index_pattern';
import { UiSettingsCommon, SavedObjectsClientCommon, SavedObject } from '../types';
import { stubbedSavedObjectIndexPattern } from '../index_pattern.stub';
const createFieldsFetcher = jest.fn().mockImplementation(() => ({
getFieldsForWildcard: jest.fn().mockImplementation(() => {

View file

@ -7,3 +7,4 @@
*/
export * from './fields/fields.mocks';
export * from './index_patterns/index_pattern.stub';

View file

@ -54,10 +54,10 @@ export interface IIndexPattern extends IndexPatternBase {
* Interface for an index pattern saved object
*/
export interface IndexPatternAttributes {
type: string;
fields: string;
title: string;
typeMeta: string;
type?: string;
typeMeta?: string;
timeFieldName?: string;
intervalName?: string;
sourceFilters?: string;

View file

@ -11,17 +11,15 @@ import { AggConfig } from './agg_config';
import { AggConfigs } from './agg_configs';
import { AggTypesRegistryStart } from './agg_types_registry';
import { mockAggTypesRegistry } from './test_helpers';
import type { IndexPatternField } from '../../index_patterns';
import { IndexPattern } from '../../index_patterns/index_patterns/index_pattern';
import { stubIndexPattern, stubIndexPatternWithFields } from '../../../common/stubs';
import { IndexPattern } from '../../index_patterns/';
import { stubIndexPattern } from '../../stubs';
import { IEsSearchResponse } from '..';
describe('AggConfigs', () => {
let indexPattern: IndexPattern;
const indexPattern: IndexPattern = stubIndexPattern;
let typesRegistry: AggTypesRegistryStart;
beforeEach(() => {
indexPattern = stubIndexPatternWithFields as IndexPattern;
typesRegistry = mockAggTypesRegistry();
});
@ -229,11 +227,6 @@ describe('AggConfigs', () => {
});
describe('#toDsl', () => {
beforeEach(() => {
indexPattern = stubIndexPattern as IndexPattern;
indexPattern.fields.getByName = (name) => (({ name } as unknown) as IndexPatternField);
});
it('uses the sorted aggs', () => {
const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
@ -349,17 +342,9 @@ describe('AggConfigs', () => {
params: { field: 'bytes', timeShift: '1d' },
},
];
indexPattern.fields.push({
name: 'timestamp',
type: 'date',
esTypes: ['date'],
aggregatable: true,
filterable: true,
searchable: true,
} as IndexPatternField);
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
ac.timeFields = ['timestamp'];
ac.timeFields = ['@timestamp'];
ac.timeRange = {
from: '2021-05-05T00:00:00.000Z',
to: '2021-05-10T00:00:00.000Z',
@ -374,7 +359,7 @@ describe('AggConfigs', () => {
Object {
"0": Object {
"range": Object {
"timestamp": Object {
"@timestamp": Object {
"gte": "2021-05-05T00:00:00.000Z",
"lte": "2021-05-10T00:00:00.000Z",
},
@ -382,7 +367,7 @@ describe('AggConfigs', () => {
},
"86400000": Object {
"range": Object {
"timestamp": Object {
"@timestamp": Object {
"gte": "2021-05-04T00:00:00.000Z",
"lte": "2021-05-09T00:00:00.000Z",
},
@ -533,8 +518,6 @@ describe('AggConfigs', () => {
describe('#postFlightTransform', () => {
it('merges together splitted responses for multiple shifts', () => {
indexPattern = stubIndexPattern as IndexPattern;
indexPattern.fields.getByName = (name) => (({ name } as unknown) as IndexPatternField);
const configStates = [
{
enabled: true,
@ -691,8 +674,6 @@ describe('AggConfigs', () => {
});
it('shifts date histogram keys and renames doc_count properties for single shift', () => {
indexPattern = stubIndexPattern as IndexPattern;
indexPattern.fields.getByName = (name) => (({ name } as unknown) as IndexPatternField);
const configStates = [
{
enabled: true,

View file

@ -6,6 +6,6 @@
* Side Public License, v 1.
*/
export { stubIndexPattern, stubIndexPatternWithFields } from './index_patterns/index_pattern.stub';
export { stubFields } from './index_patterns/field.stub';
export * from './index_patterns/field.stub';
export * from './index_patterns/index_pattern.stub';
export * from './es_query/stubs';

View file

@ -1,115 +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.
*/
import sinon from 'sinon';
import { CoreSetup } from 'src/core/public';
import { SerializedFieldFormat } from 'src/plugins/expressions/public';
import { IFieldType, FieldSpec, fieldList } from '../../common/index_patterns';
import { IndexPattern, KBN_FIELD_TYPES } from '../';
import { getFieldFormatsRegistry } from '../test_utils';
import { flattenHitWrapper, formatHitProvider } from './index_patterns';
export function getStubIndexPattern(
pattern: string,
getConfig: (cfg: any) => any,
timeField: string | null,
fields: FieldSpec[] | IFieldType[],
core: CoreSetup
): IndexPattern {
return (new StubIndexPattern(
pattern,
getConfig,
timeField,
fields,
core
) as unknown) as IndexPattern;
}
export class StubIndexPattern {
id: string;
title: string;
popularizeField: Function;
timeFieldName: string | null;
isTimeBased: () => boolean;
getConfig: (cfg: any) => any;
getNonScriptedFields: Function;
getScriptedFields: Function;
getFieldByName: Function;
getSourceFiltering: Function;
metaFields: string[];
fieldFormatMap: Record<string, any>;
getComputedFields: Function;
flattenHit: Function;
formatHit: Record<string, any>;
fieldsFetcher: Record<string, any>;
formatField: Function;
getFormatterForField: () => { convert: Function; toJSON: Function };
_reindexFields: Function;
stubSetFieldFormat: Function;
fields?: FieldSpec[];
setFieldFormat: (fieldName: string, format: SerializedFieldFormat) => void;
constructor(
pattern: string,
getConfig: (cfg: any) => any,
timeField: string | null,
fields: FieldSpec[] | IFieldType[],
core: CoreSetup
) {
const registeredFieldFormats = getFieldFormatsRegistry(core);
this.id = pattern;
this.title = pattern;
this.popularizeField = sinon.stub();
this.timeFieldName = timeField;
this.isTimeBased = () => Boolean(this.timeFieldName);
this.getConfig = getConfig;
this.getNonScriptedFields = sinon.spy(IndexPattern.prototype.getNonScriptedFields);
this.getScriptedFields = sinon.spy(IndexPattern.prototype.getScriptedFields);
this.getFieldByName = sinon.spy(IndexPattern.prototype.getFieldByName);
this.getSourceFiltering = sinon.stub();
this.metaFields = ['_id', '_type', '_source'];
this.fieldFormatMap = {};
this.setFieldFormat = (fieldName: string, format: SerializedFieldFormat) => {
this.fieldFormatMap[fieldName] = format;
};
this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this);
this.flattenHit = flattenHitWrapper((this as unknown) as IndexPattern, this.metaFields);
this.formatHit = formatHitProvider(
(this as unknown) as IndexPattern,
registeredFieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING)
);
this.fieldsFetcher = { apiClient: { baseUrl: '' } };
this.formatField = this.formatHit.formatField;
this.getFormatterForField = () => ({
convert: () => '',
toJSON: () => '{}',
});
this._reindexFields = function () {
this.fields = fieldList((this.fields || fields) as FieldSpec[], false);
};
this.stubSetFieldFormat = function (
fieldName: string,
id: string,
params: Record<string, any>
) {
const FieldFormat = registeredFieldFormats.getType(id);
this.fieldFormatMap[fieldName] = new FieldFormat!(params);
this._reindexFields();
};
this._reindexFields();
return this;
}
}

View file

@ -0,0 +1,61 @@
/*
* 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 { CoreSetup } from 'kibana/public';
import { FieldFormatsStartCommon } from '../../../../field_formats/common';
import { getFieldFormatsRegistry } from '../../../../field_formats/public/mocks';
import * as commonStubs from '../../../common/stubs';
import { IndexPattern, IndexPatternSpec } from '../../../common';
import { coreMock } from '../../../../../core/public/mocks';
/**
* Create a custom stub index pattern. Use it in your unit tests where an {@link IndexPattern} expected.
* @param spec - Serialized index pattern object
* @param opts - Specify index pattern options
* @param deps - Optionally provide dependencies, you can provide a custom field formats implementation, by default client side registry with real formatters implementation is used
*
* @returns - an {@link IndexPattern} instance
*
* @remark - This is a client side version, a browser-agnostic version is available in {@link commonStubs | common}.
* The main difference is that client side version by default uses client side field formats service, where common version uses a dummy field formats mock.
*
* @example
*
* You can provide a custom implementation or assert calls using jest.spyOn:
*
* ```ts
* const indexPattern = createStubIndexPattern({spec: {title: 'logs-*'}});
* const spy = jest.spyOn(indexPattern, 'getFormatterForField');
*
* // use `spy` as a regular jest mock
*
* ```
*/
export const createStubIndexPattern = ({
spec,
opts,
deps,
}: {
spec: IndexPatternSpec;
opts?: {
shortDotsEnable?: boolean;
metaFields?: string[];
};
deps?: {
fieldFormats?: FieldFormatsStartCommon;
core?: CoreSetup;
};
}): IndexPattern => {
return commonStubs.createStubIndexPattern({
spec,
opts,
deps: {
fieldFormats:
deps?.fieldFormats ?? getFieldFormatsRegistry(deps?.core ?? coreMock.createSetup()),
},
});
};

View file

@ -1305,9 +1305,9 @@ export interface IndexPatternAttributes {
// (undocumented)
title: string;
// (undocumented)
type: string;
type?: string;
// (undocumented)
typeMeta: string;
typeMeta?: string;
}
// @public (undocumented)

View file

@ -8,8 +8,13 @@
import { stubIndexPattern, phraseFilter } from 'src/plugins/data/common/stubs';
import { getDisplayValueFromFilter } from './get_display_value';
import { FieldFormat } from '../../../../../field_formats/common';
describe('getDisplayValueFromFilter', () => {
beforeEach(() => {
jest.resetAllMocks();
});
it('returns the value if string', () => {
phraseFilter.meta.value = 'abc';
const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]);
@ -22,24 +27,26 @@ describe('getDisplayValueFromFilter', () => {
expect(displayValue).toBe('');
});
it('calls the value function if proivided', () => {
it('calls the value function if provided', () => {
// The type of value currently doesn't match how it's used. Refactor needed.
phraseFilter.meta.value = jest.fn((x) => {
return 'abc';
}) as any;
jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => undefined!);
const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]);
expect(displayValue).toBe('abc');
expect(phraseFilter.meta.value).toHaveBeenCalledWith(undefined);
});
it('calls the value function if proivided, with formatter', () => {
stubIndexPattern.getFormatterForField = jest.fn().mockReturnValue('banana');
it('calls the value function if provided, with formatter', () => {
const mockFormatter = new (FieldFormat.from((value: string) => 'banana' + value))();
jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => mockFormatter);
phraseFilter.meta.value = jest.fn((x) => {
return x + 'abc';
return x.convert('abc');
}) as any;
const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]);
expect(stubIndexPattern.getFormatterForField).toHaveBeenCalledTimes(1);
expect(phraseFilter.meta.value).toHaveBeenCalledWith('banana');
expect(phraseFilter.meta.value).toHaveBeenCalledWith(mockFormatter);
expect(displayValue).toBe('bananaabc');
});
});

View file

@ -7,3 +7,4 @@
*/
export * from '../common/stubs';
export { createStubIndexPattern } from './index_patterns/index_patterns/index_pattern.stub';

View file

@ -7,4 +7,3 @@
*/
export { getFieldFormatsRegistry } from '../../field_formats/public/mocks';
export { getStubIndexPattern, StubIndexPattern } from './index_patterns/index_pattern.stub';

View file

@ -19,7 +19,7 @@ import { coreMock } from '../../../../../core/public/mocks';
import { dataPluginMock } from '../../mocks';
import { KibanaContextProvider } from 'src/plugins/kibana_react/public';
import { I18nProvider } from '@kbn/i18n/react';
import { stubIndexPatternWithFields } from '../../stubs';
import { stubIndexPattern } from '../../stubs';
import { UI_SETTINGS } from '../../../common';
const startMock = coreMock.createStart();
@ -118,7 +118,7 @@ describe('QueryBarTopRowTopRow', () => {
query: kqlQuery,
screenTitle: 'Another Screen',
isDirty: false,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
timeHistory: mockTimeHistory,
})
);
@ -132,7 +132,7 @@ describe('QueryBarTopRowTopRow', () => {
wrapQueryBarTopRowInContext({
query: kqlQuery,
screenTitle: 'Another Screen',
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
timeHistory: mockTimeHistory,
disableAutoFocus: true,
isDirty: false,
@ -205,7 +205,7 @@ describe('QueryBarTopRowTopRow', () => {
const component = mount(
wrapQueryBarTopRowInContext({
query: kqlQuery,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
isDirty: false,
screenTitle: 'Another Screen',
showDatePicker: false,
@ -225,7 +225,7 @@ describe('QueryBarTopRowTopRow', () => {
query: kqlQuery,
isDirty: false,
screenTitle: 'Another Screen',
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
showQueryInput: false,
showDatePicker: false,
timeHistory: mockTimeHistory,

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { stubIndexPatternWithFields } from '../../stubs';
import { stubIndexPattern } from '../../stubs';
export const mockPersistedLog = {
add: jest.fn(),
@ -19,7 +19,7 @@ export const mockPersistedLogFactory = jest.fn<jest.Mocked<typeof mockPersistedL
export const mockFetchIndexPatterns = jest
.fn()
.mockReturnValue(Promise.resolve([stubIndexPatternWithFields]));
.mockReturnValue(Promise.resolve([stubIndexPattern]));
jest.mock('../../query/persisted_log', () => ({
PersistedLog: mockPersistedLogFactory,

View file

@ -25,7 +25,7 @@ import QueryStringInputUI from './query_string_input';
import { coreMock } from '../../../../../core/public/mocks';
import { dataPluginMock } from '../../mocks';
import { stubIndexPatternWithFields } from '../../stubs';
import { stubIndexPattern } from '../../stubs';
import { KibanaContextProvider, withKibana } from 'src/plugins/kibana_react/public';
jest.useFakeTimers();
@ -97,7 +97,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
})
);
@ -110,7 +110,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: luceneQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
})
);
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(luceneQuery.language);
@ -121,7 +121,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -135,7 +135,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
appName: 'discover',
})
@ -151,7 +151,7 @@ describe('QueryStringInput', () => {
{
query: kqlQuery,
onSubmit: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
appName: 'discover',
},
@ -169,7 +169,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: luceneQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableLanguageSwitcher: true,
})
);
@ -181,7 +181,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: luceneQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
iconType: 'search',
})
);
@ -195,7 +195,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -216,7 +216,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onBlur: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -235,7 +235,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onChangeQueryInputFocus: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -260,7 +260,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onChangeQueryInputFocus: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -287,7 +287,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
submitOnBlur: true,
})
@ -313,7 +313,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);
@ -335,7 +335,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onSubmit: noop,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
persistedLog: mockPersistedLog,
})
@ -374,7 +374,7 @@ describe('QueryStringInput', () => {
wrapQueryStringInputInContext({
query: kqlQuery,
onChange: mockCallback,
indexPatterns: [stubIndexPatternWithFields],
indexPatterns: [stubIndexPattern],
disableAutoFocus: true,
})
);

View file

@ -410,9 +410,9 @@ export interface IndexPatternAttributes {
// (undocumented)
title: string;
// (undocumented)
type: string;
type?: string;
// (undocumented)
typeMeta: string;
typeMeta?: string;
}
// @public (undocumented)

View file

@ -1,75 +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.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { shouldReadFieldFromDocValues, castEsToKbnFieldTypeName } from '../../../data/server';
function stubbedLogstashFields() {
return [
// |aggregatable
// | |searchable
// name esType | | |metadata | subType
['bytes', 'long', true, true, { count: 10 }],
['ssl', 'boolean', true, true, { count: 20 }],
['@timestamp', 'date', true, true, { count: 30 }],
['time', 'date', true, true, { count: 30 }],
['@tags', 'keyword', true, true],
['utc_time', 'date', true, true],
['phpmemory', 'integer', true, true],
['ip', 'ip', true, true],
['request_body', 'attachment', true, true],
['point', 'geo_point', true, true],
['area', 'geo_shape', true, true],
['hashed', 'murmur3', false, true],
['geo.coordinates', 'geo_point', true, true],
['extension', 'text', true, true],
['extension.keyword', 'keyword', true, true, {}, { multi: { parent: 'extension' } }],
['machine.os', 'text', true, true],
['machine.os.raw', 'keyword', true, true, {}, { multi: { parent: 'machine.os' } }],
['geo.src', 'keyword', true, true],
['_id', '_id', true, true],
['_type', '_type', true, true],
['_source', '_source', true, true],
['non-filterable', 'text', true, false],
['non-sortable', 'text', false, false],
['custom_user_field', 'conflict', true, true],
['script string', 'text', true, false, { script: "'i am a string'" }],
['script number', 'long', true, false, { script: '1234' }],
['script date', 'date', true, false, { script: '1234', lang: 'painless' }],
['script murmur3', 'murmur3', true, false, { script: '1234' }],
].map(function (row) {
const [name, esType, aggregatable, searchable, metadata = {}, subType = undefined] = row;
const {
count = 0,
script,
lang = script ? 'expression' : undefined,
scripted = !!script,
} = metadata;
// the conflict type is actually a kbnFieldType, we
// don't have any other way to represent it here
const type = esType === 'conflict' ? esType : castEsToKbnFieldTypeName(esType);
return {
name,
type,
esTypes: [esType],
readFromDocValues: shouldReadFieldFromDocValues(aggregatable, esType),
aggregatable,
searchable,
count,
script,
lang,
scripted,
subType,
};
});
}
export default stubbedLogstashFields;

View file

@ -1,47 +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.
*/
import stubbedLogstashFields from './logstash_fields';
import { getKbnFieldType } from '../../../data/common';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getStubIndexPattern } from '../../../data/public/test_utils';
import { uiSettingsServiceMock } from '../../../../core/public/mocks';
const uiSettingSetupMock = uiSettingsServiceMock.createSetupContract();
uiSettingSetupMock.get.mockImplementation((item, defaultValue) => {
return defaultValue;
});
export default function stubbedLogstashIndexPatternService() {
const mockLogstashFields = stubbedLogstashFields();
const fields = mockLogstashFields.map(function (field) {
const kbnType = getKbnFieldType(field.type);
if (!kbnType || kbnType.name === 'unknown') {
throw new TypeError(`unknown type ${field.type}`);
}
return {
...field,
sortable: 'sortable' in field ? !!field.sortable : kbnType.sortable,
filterable: 'filterable' in field ? !!field.filterable : kbnType.filterable,
displayName: field.name,
};
});
const indexPattern = getStubIndexPattern('logstash-*', (cfg) => cfg, 'time', fields, {
uiSettings: uiSettingSetupMock,
});
indexPattern.id = 'logstash-*';
indexPattern.isTimeNanosBased = () => false;
return indexPattern;
}

View file

@ -1,26 +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.
*/
// @ts-expect-error
import stubbedLogstashFields from '../__fixtures__/logstash_fields';
const mockLogstashFields = stubbedLogstashFields();
export function stubbedSavedObjectIndexPattern(id: string | null = null) {
return {
id,
type: 'index-pattern',
attributes: {
timeFieldName: 'timestamp',
customFormats: {},
fields: mockLogstashFields,
title: 'title',
},
version: '2',
};
}

View file

@ -7,27 +7,23 @@
*/
import { getDefaultSort } from './get_default_sort';
// @ts-expect-error
import FixturesStubbedLogstashIndexPatternProvider from '../../../../../../__fixtures__/stubbed_logstash_index_pattern';
import { IndexPattern } from '../../../../../../kibana_services';
import {
stubIndexPattern,
stubIndexPatternWithoutTimeField,
} from '../../../../../../../../data/common/stubs';
describe('getDefaultSort function', function () {
let indexPattern: IndexPattern;
beforeEach(() => {
indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern;
});
test('should be a function', function () {
expect(typeof getDefaultSort === 'function').toBeTruthy();
});
test('should return default sort for an index pattern with timeFieldName', function () {
expect(getDefaultSort(indexPattern, 'desc')).toEqual([['time', 'desc']]);
expect(getDefaultSort(indexPattern, 'asc')).toEqual([['time', 'asc']]);
expect(getDefaultSort(stubIndexPattern, 'desc')).toEqual([['@timestamp', 'desc']]);
expect(getDefaultSort(stubIndexPattern, 'asc')).toEqual([['@timestamp', 'asc']]);
});
test('should return default sort for an index pattern without timeFieldName', function () {
delete indexPattern.timeFieldName;
expect(getDefaultSort(indexPattern, 'desc')).toEqual([]);
expect(getDefaultSort(indexPattern, 'asc')).toEqual([]);
expect(getDefaultSort(stubIndexPatternWithoutTimeField, 'desc')).toEqual([]);
expect(getDefaultSort(stubIndexPatternWithoutTimeField, 'asc')).toEqual([]);
});
});

View file

@ -7,50 +7,44 @@
*/
import { getSort, getSortArray } from './get_sort';
// @ts-expect-error
import FixturesStubbedLogstashIndexPatternProvider from '../../../../../../__fixtures__/stubbed_logstash_index_pattern';
import { IndexPattern } from '../../../../../../kibana_services';
import {
stubIndexPattern,
stubIndexPatternWithoutTimeField,
} from '../../../../../../../../data/common/stubs';
describe('docTable', function () {
let indexPattern: IndexPattern;
beforeEach(() => {
indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern;
});
describe('getSort function', function () {
test('should be a function', function () {
expect(typeof getSort === 'function').toBeTruthy();
});
test('should return an array of objects', function () {
expect(getSort([['bytes', 'desc']], indexPattern)).toEqual([{ bytes: 'desc' }]);
delete indexPattern.timeFieldName;
expect(getSort([['bytes', 'desc']], indexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSort([['bytes', 'desc']], stubIndexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSort([['bytes', 'desc']], stubIndexPatternWithoutTimeField)).toEqual([
{ bytes: 'desc' },
]);
});
test('should passthrough arrays of objects', () => {
expect(getSort([{ bytes: 'desc' }], indexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSort([{ bytes: 'desc' }], stubIndexPattern)).toEqual([{ bytes: 'desc' }]);
});
test('should return an empty array when passed an unsortable field', function () {
expect(getSort([['non-sortable', 'asc']], indexPattern)).toEqual([]);
expect(getSort([['lol_nope', 'asc']], indexPattern)).toEqual([]);
expect(getSort([['non-sortable', 'asc']], stubIndexPattern)).toEqual([]);
expect(getSort([['lol_nope', 'asc']], stubIndexPattern)).toEqual([]);
delete indexPattern.timeFieldName;
expect(getSort([['non-sortable', 'asc']], indexPattern)).toEqual([]);
expect(getSort([['non-sortable', 'asc']], stubIndexPatternWithoutTimeField)).toEqual([]);
});
test('should return an empty array ', function () {
expect(getSort([], indexPattern)).toEqual([]);
expect(getSort([['foo', 'bar']], indexPattern)).toEqual([]);
expect(getSort([{ foo: 'bar' }], indexPattern)).toEqual([]);
expect(getSort([], stubIndexPattern)).toEqual([]);
expect(getSort([['foo', 'bar']], stubIndexPattern)).toEqual([]);
expect(getSort([{ foo: 'bar' }], stubIndexPattern)).toEqual([]);
});
test('should convert a legacy sort to an array of objects', function () {
expect(getSort(['foo', 'desc'], indexPattern)).toEqual([{ foo: 'desc' }]);
expect(getSort(['foo', 'asc'], indexPattern)).toEqual([{ foo: 'asc' }]);
expect(getSort(['foo', 'desc'], stubIndexPattern)).toEqual([{ foo: 'desc' }]);
expect(getSort(['foo', 'asc'], stubIndexPattern)).toEqual([{ foo: 'asc' }]);
});
});
@ -60,26 +54,26 @@ describe('docTable', function () {
});
test('should return an array of arrays for sortable fields', function () {
expect(getSortArray([['bytes', 'desc']], indexPattern)).toEqual([['bytes', 'desc']]);
expect(getSortArray([['bytes', 'desc']], stubIndexPattern)).toEqual([['bytes', 'desc']]);
});
test('should return an array of arrays from an array of elasticsearch sort objects', function () {
expect(getSortArray([{ bytes: 'desc' }], indexPattern)).toEqual([['bytes', 'desc']]);
expect(getSortArray([{ bytes: 'desc' }], stubIndexPattern)).toEqual([['bytes', 'desc']]);
});
test('should sort by an empty array when an unsortable field is given', function () {
expect(getSortArray([{ 'non-sortable': 'asc' }], indexPattern)).toEqual([]);
expect(getSortArray([{ lol_nope: 'asc' }], indexPattern)).toEqual([]);
expect(getSortArray([{ 'non-sortable': 'asc' }], stubIndexPattern)).toEqual([]);
expect(getSortArray([{ lol_nope: 'asc' }], stubIndexPattern)).toEqual([]);
delete indexPattern.timeFieldName;
expect(getSortArray([{ 'non-sortable': 'asc' }], indexPattern)).toEqual([]);
expect(getSortArray([{ 'non-sortable': 'asc' }], stubIndexPatternWithoutTimeField)).toEqual(
[]
);
});
test('should return an empty array when passed an empty sort array', () => {
expect(getSortArray([], indexPattern)).toEqual([]);
expect(getSortArray([], stubIndexPattern)).toEqual([]);
delete indexPattern.timeFieldName;
expect(getSortArray([], indexPattern)).toEqual([]);
expect(getSortArray([], stubIndexPatternWithoutTimeField)).toEqual([]);
});
});
});

View file

@ -7,35 +7,40 @@
*/
import { getSortForSearchSource } from './get_sort_for_search_source';
// @ts-expect-error
import FixturesStubbedLogstashIndexPatternProvider from '../../../../../../__fixtures__/stubbed_logstash_index_pattern';
import { IndexPattern } from '../../../../../../kibana_services';
import { SortOrder } from '../components/table_header/helpers';
import {
stubIndexPattern,
stubIndexPatternWithoutTimeField,
} from '../../../../../../../../data/common/stubs';
describe('getSortForSearchSource function', function () {
let indexPattern: IndexPattern;
beforeEach(() => {
indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern;
});
test('should be a function', function () {
expect(typeof getSortForSearchSource === 'function').toBeTruthy();
});
test('should return an object to use for searchSource when columns are given', function () {
const cols = [['bytes', 'desc']] as SortOrder[];
expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]);
delete indexPattern.timeFieldName;
expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ bytes: 'desc' }]);
expect(getSortForSearchSource(cols, stubIndexPattern)).toEqual([{ bytes: 'desc' }]);
expect(getSortForSearchSource(cols, stubIndexPattern, 'asc')).toEqual([{ bytes: 'desc' }]);
expect(getSortForSearchSource(cols, stubIndexPatternWithoutTimeField)).toEqual([
{ bytes: 'desc' },
]);
expect(getSortForSearchSource(cols, stubIndexPatternWithoutTimeField, 'asc')).toEqual([
{ bytes: 'desc' },
]);
});
test('should return an object to use for searchSource when no columns are given', function () {
const cols = [] as SortOrder[];
expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _doc: 'desc' }]);
expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _doc: 'asc' }]);
delete indexPattern.timeFieldName;
expect(getSortForSearchSource(cols, indexPattern)).toEqual([{ _score: 'desc' }]);
expect(getSortForSearchSource(cols, indexPattern, 'asc')).toEqual([{ _score: 'asc' }]);
expect(getSortForSearchSource(cols, stubIndexPattern)).toEqual([{ _doc: 'desc' }]);
expect(getSortForSearchSource(cols, stubIndexPattern, 'asc')).toEqual([{ _doc: 'asc' }]);
expect(getSortForSearchSource(cols, stubIndexPatternWithoutTimeField)).toEqual([
{ _score: 'desc' },
]);
expect(getSortForSearchSource(cols, stubIndexPatternWithoutTimeField, 'asc')).toEqual([
{ _score: 'asc' },
]);
});
});

View file

@ -8,11 +8,11 @@
import ReactDOM from 'react-dom/server';
import { formatRow, formatTopLevelObject } from './row_formatter';
import { stubbedSavedObjectIndexPattern } from '../../../../../../__mocks__/stubbed_saved_object_index_pattern';
import { IndexPattern } from '../../../../../../../../data/common/index_patterns/index_patterns';
import { fieldFormatsMock } from '../../../../../../../../field_formats/common/mocks';
import { setServices } from '../../../../../../kibana_services';
import { DiscoverServices } from '../../../../../../build_services';
import { stubbedSavedObjectIndexPattern } from '../../../../../../../../data/common/stubs';
describe('Row formatter', () => {
const hit = {
@ -36,7 +36,7 @@ describe('Row formatter', () => {
} = stubbedSavedObjectIndexPattern(id);
return new IndexPattern({
spec: { id, type, version, timeFieldName, fields, title },
spec: { id, type, version, timeFieldName, fields: JSON.parse(fields), title },
fieldFormats: fieldFormatsMock,
shortDotsEnable: false,
metaFields: [],

View file

@ -106,9 +106,64 @@ exports[`Discover IndexPattern Management renders correctly 1`] = `
}
}
selectedIndexPattern={
StubIndexPattern {
"_reindexFields": [Function],
IndexPattern {
"allowNoIndex": false,
"deleteFieldFormat": [Function],
"fieldAttrs": Object {},
"fieldFormatMap": Object {},
"fieldFormats": Object {
"deserialize": [MockFunction],
"getByFieldType": [MockFunction],
"getDefaultConfig": [MockFunction],
"getDefaultInstance": [MockFunction] {
"calls": Array [
Array [
"string",
],
Array [
"string",
],
Array [
"string",
],
],
"results": Array [
Object {
"type": "return",
"value": Object {
"convert": [MockFunction],
"getConverterFor": [MockFunction],
},
},
Object {
"type": "return",
"value": Object {
"convert": [MockFunction],
"getConverterFor": [MockFunction],
},
},
Object {
"type": "return",
"value": Object {
"convert": [MockFunction],
"getConverterFor": [MockFunction],
},
},
],
},
"getDefaultInstanceCacheResolver": [MockFunction],
"getDefaultInstancePlain": [MockFunction],
"getDefaultType": [MockFunction],
"getDefaultTypeName": [MockFunction],
"getInstance": [MockFunction],
"getType": [MockFunction],
"getTypeNameByEsTypes": [MockFunction],
"getTypeWithoutMetaParams": [MockFunction],
"has": [MockFunction],
"init": [MockFunction],
"parseDefaultTypeMap": [MockFunction],
"register": [MockFunction],
},
"fields": FldList [
Object {
"aggregatable": true,
@ -595,33 +650,29 @@ exports[`Discover IndexPattern Management renders correctly 1`] = `
"type": "murmur3",
},
],
"fieldsFetcher": Object {
"apiClient": Object {
"baseUrl": "",
},
},
"flattenHit": [Function],
"formatField": [Function],
"formatHit": [Function],
"getComputedFields": [Function],
"getConfig": [Function],
"getFieldByName": [Function],
"getFormatterForField": [Function],
"getNonScriptedFields": [Function],
"getScriptedFields": [Function],
"getSourceFiltering": [Function],
"getFieldAttrs": [Function],
"getOriginalSavedObjectBody": [Function],
"id": "logstash-*",
"isTimeBased": [Function],
"intervalName": undefined,
"metaFields": Array [
"_id",
"_type",
"_source",
],
"popularizeField": [Function],
"originalSavedObjectBody": Object {},
"resetOriginalSavedObjectBody": [Function],
"runtimeFieldMap": Object {},
"setFieldFormat": [Function],
"stubSetFieldFormat": [Function],
"shortDotsEnable": false,
"sourceFilters": undefined,
"timeFieldName": "time",
"title": "logstash-*",
"type": undefined,
"typeMeta": undefined,
"version": undefined,
}
}
services={

View file

@ -10,12 +10,9 @@ import React from 'react';
import { findTestSubject } from '@elastic/eui/lib/test';
import { mountWithIntl } from '@kbn/test/jest';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields';
import { DiscoverField } from './discover_field';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { IndexPatternField } from '../../../../../../../data/public';
import { getStubIndexPattern } from '../../../../../../../data/public/test_utils';
import { stubIndexPattern } from '../../../../../../../data/common/stubs';
jest.mock('../../../../../kibana_services', () => ({
getServices: () => ({
@ -48,14 +45,6 @@ function getComponent({
showDetails?: boolean;
field?: IndexPatternField;
}) {
const indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
const finalField =
field ??
new IndexPatternField({
@ -70,7 +59,7 @@ function getComponent({
});
const props = {
indexPattern,
indexPattern: stubIndexPattern,
field: finalField,
getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: 2, columns: [] })),
onAddFilter: jest.fn(),

View file

@ -9,25 +9,15 @@
import React from 'react';
import { findTestSubject } from '@elastic/eui/lib/test';
import { mountWithIntl } from '@kbn/test/jest';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields';
import { DiscoverFieldDetails } from './discover_field_details';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { IndexPatternField } from '../../../../../../../data/public';
import { getStubIndexPattern } from '../../../../../../../data/public/test_utils';
const indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
import { DiscoverFieldDetails } from './discover_field_details';
import { IndexPatternField } from '../../../../../../../data/public';
import { stubIndexPattern } from '../../../../../../../data/common/stubs';
describe('discover sidebar field details', function () {
const onAddFilter = jest.fn();
const defaultProps = {
indexPattern,
indexPattern: stubIndexPattern,
details: { buckets: [], error: '', exists: 1, total: 2, columns: [] },
onAddFilter,
};

View file

@ -10,12 +10,9 @@ import React from 'react';
import { mountWithIntl } from '@kbn/test/jest';
import { EuiContextMenuPanel, EuiPopover, EuiContextMenuItem } from '@elastic/eui';
import { findTestSubject } from '@kbn/test/jest';
import { getStubIndexPattern } from '../../../../../../../data/public/index_patterns/index_pattern.stub';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { DiscoverServices } from '../../../../../build_services';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields';
import { DiscoverIndexPatternManagement } from './discover_index_pattern_management';
import { stubLogstashIndexPattern } from '../../../../../../../data/common/stubs';
const mockServices = ({
history: () => ({
@ -54,13 +51,7 @@ const mockServices = ({
} as unknown) as DiscoverServices;
describe('Discover IndexPattern Management', () => {
const indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
const indexPattern = stubLogstashIndexPattern;
const editField = jest.fn();

View file

@ -11,36 +11,24 @@ import { ReactWrapper } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
// @ts-expect-error
import realHits from '../../../../../__fixtures__/real_hits.js';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields';
import { mountWithIntl } from '@kbn/test/jest';
import React from 'react';
import { DiscoverSidebarProps } from './discover_sidebar';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { IndexPatternAttributes } from '../../../../../../../data/common';
import { getStubIndexPattern } from '../../../../../../../data/public/test_utils';
import { SavedObject } from '../../../../../../../../core/types';
import { getDefaultFieldFilter } from './lib/field_filter';
import { DiscoverSidebar } from './discover_sidebar';
import { ElasticSearchHit } from '../../../../doc_views/doc_views_types';
import { discoverServiceMock as mockDiscoverServices } from '../../../../../__mocks__/services';
import { stubLogstashIndexPattern } from '../../../../../../../data/common/stubs';
jest.mock('../../../../../kibana_services', () => ({
getServices: () => mockDiscoverServices,
}));
jest.mock('./lib/get_index_pattern_field_list', () => ({
getIndexPatternFieldList: jest.fn((indexPattern) => indexPattern.fields),
}));
function getCompProps(): DiscoverSidebarProps {
const indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
const indexPattern = stubLogstashIndexPattern;
// @ts-expect-error _.each() is passing additional args to flattenHit
const hits = (each(cloneDeep(realHits), indexPattern.flattenHit) as Array<

View file

@ -12,13 +12,9 @@ import { ReactWrapper } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
// @ts-expect-error
import realHits from '../../../../../__fixtures__/real_hits.js';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields';
import { mountWithIntl } from '@kbn/test/jest';
import React from 'react';
import { coreMock } from '../../../../../../../../core/public/mocks';
import { IndexPatternAttributes } from '../../../../../../../data/common';
import { getStubIndexPattern } from '../../../../../../../data/public/test_utils';
import { SavedObject } from '../../../../../../../../core/types';
import {
DiscoverSidebarResponsive,
@ -28,6 +24,7 @@ import { DiscoverServices } from '../../../../../build_services';
import { ElasticSearchHit } from '../../../../doc_views/doc_views_types';
import { FetchStatus } from '../../../../types';
import { DataDocuments$ } from '../../services/use_saved_search';
import { stubLogstashIndexPattern } from '../../../../../../../data/common/stubs';
const mockServices = ({
history: () => ({
@ -56,18 +53,8 @@ jest.mock('../../../../../kibana_services', () => ({
getServices: () => mockServices,
}));
jest.mock('./lib/get_index_pattern_field_list', () => ({
getIndexPatternFieldList: jest.fn((indexPattern) => indexPattern.fields),
}));
function getCompProps(): DiscoverSidebarResponsiveProps {
const indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
const indexPattern = stubLogstashIndexPattern;
// @ts-expect-error _.each() is passing additional args to flattenHit
const hits = (each(cloneDeep(realHits), indexPattern.flattenHit) as Array<
@ -80,13 +67,6 @@ function getCompProps(): DiscoverSidebarResponsiveProps {
{ id: '2', attributes: { title: 'c' } } as SavedObject<IndexPatternAttributes>,
];
const fieldCounts: Record<string, number> = {};
for (const hit of hits) {
for (const key of Object.keys(indexPattern.flattenHit(hit))) {
fieldCounts[key] = (fieldCounts[key] || 0) + 1;
}
}
return {
columns: ['extension'],
documents$: new BehaviorSubject({

View file

@ -11,26 +11,14 @@
import _ from 'lodash';
// @ts-expect-error
import realHits from '../../../../../../__fixtures__/real_hits.js';
// @ts-expect-error
import stubbedLogstashFields from '../../../../../../__fixtures__/logstash_fields';
import { coreMock } from '../../../../../../../../../core/public/mocks';
import { IndexPattern } from '../../../../../../../../data/public';
import { getStubIndexPattern } from '../../../../../../../../data/public/test_utils';
// @ts-expect-error
import { fieldCalculator } from './field_calculator';
let indexPattern: IndexPattern;
import { stubLogstashIndexPattern as indexPattern } from '../../../../../../../../data/common/stubs';
describe('fieldCalculator', function () {
beforeEach(function () {
indexPattern = getStubIndexPattern(
'logstash-*',
(cfg: unknown) => cfg,
'time',
stubbedLogstashFields(),
coreMock.createSetup()
);
});
it('should have a _countMissing that counts nulls & undefineds in an array', function () {
const values = [
['foo', 'bar'],

View file

@ -10,21 +10,6 @@ import { SourceFormat } from './source';
import { HtmlContextTypeConvert } from '../types';
import { HTML_CONTEXT_TYPE } from '../content_types';
export const stubIndexPatternWithFields = {
id: '1234',
title: 'logstash-*',
fields: [
{
name: 'response',
type: 'number',
esTypes: ['integer'],
aggregatable: true,
filterable: true,
searchable: true,
},
],
};
describe('Source Format', () => {
let convertHtml: Function;
@ -55,9 +40,9 @@ describe('Source Format', () => {
also: 'with "quotes" or \'single quotes\'',
};
const indexPattern = { ...stubIndexPatternWithFields, formatHit: (h: string) => h };
expect(convertHtml(hit, { field: 'field', indexPattern, hit })).toMatchInlineSnapshot(
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>"`
);
});

View file

@ -53,6 +53,7 @@ export class SourceFormat extends FieldFormat {
}
const highlights = (hit && hit.highlight) || {};
// TODO: remove index pattern dependency
const formatted = indexPattern.formatHit(hit);
const highlightPairs: any[] = [];
const sourcePairs: any[] = [];

View file

@ -8,15 +8,36 @@
import { CoreSetup } from 'src/core/public';
import { baseFormattersPublic } from './lib/constants';
import { FieldFormatsRegistry } from '../common';
import type { FieldFormatsStart, FieldFormatsSetup } from '.';
import { FieldFormatsRegistry, FORMATS_UI_SETTINGS } from '../common';
import type { FieldFormatsSetup, FieldFormatsStart } from '.';
import { fieldFormatsMock } from '../common/mocks';
export const getFieldFormatsRegistry = (core: CoreSetup) => {
const fieldFormatsRegistry = new FieldFormatsRegistry();
const getConfig = core.uiSettings.get.bind(core.uiSettings);
fieldFormatsRegistry.init(getConfig, {}, baseFormattersPublic);
const getConfigWithFallbacks = (key: string) => {
switch (key) {
case FORMATS_UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP:
return (
getConfig(key) ??
`{
"ip": { "id": "ip", "params": {} },
"date": { "id": "date", "params": {} },
"date_nanos": { "id": "date_nanos", "params": {}, "es": true },
"number": { "id": "number", "params": {} },
"boolean": { "id": "boolean", "params": {} },
"histogram": { "id": "histogram", "params": {} },
"_source": { "id": "_source", "params": {} },
"_default_": { "id": "string", "params": {} }
}`
);
default:
return getConfig(key);
}
};
fieldFormatsRegistry.init(getConfigWithFallbacks, {}, baseFormattersPublic);
return fieldFormatsRegistry;
};

View file

@ -18,13 +18,11 @@ import { SavedObjectDecorator } from './decorators';
import { coreMock } from '../../../../core/public/mocks';
import { dataPluginMock, createSearchSourceMock } from '../../../../plugins/data/public/mocks';
import { getStubIndexPattern, StubIndexPattern } from '../../../../plugins/data/public/test_utils';
import { createStubIndexPattern } from '../../../../plugins/data/common/stubs';
import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public';
import { IndexPattern } from '../../../data/common/index_patterns';
import { IndexPattern } from '../../../data/common/index_patterns/index_patterns';
import { savedObjectsDecoratorRegistryMock } from './decorators/registry.mock';
const getConfig = (cfg: any) => cfg;
describe('Saved Object', () => {
const startMock = coreMock.createStart();
const dataStartMock = dataPluginMock.createStartContract();
@ -375,14 +373,9 @@ describe('Saved Object', () => {
type: 'dashboard',
} as SimpleSavedObject<SavedObjectAttributes>);
const indexPattern = getStubIndexPattern(
'my-index',
getConfig,
null,
[],
coreMock.createSetup()
);
indexPattern.title = indexPattern.id!;
const indexPattern = createStubIndexPattern({
spec: { id: 'my-index', title: 'my-index' },
});
savedObject.searchSource!.setField('index', indexPattern);
return savedObject.save(saveOptionsMock).then(() => {
const args = (savedObjectsClientStub.create as jest.Mock).mock.calls[0];
@ -416,13 +409,12 @@ describe('Saved Object', () => {
type: 'dashboard',
} as SimpleSavedObject<SavedObjectAttributes>);
const indexPattern = getStubIndexPattern(
'non-existant-index',
getConfig,
null,
[],
coreMock.createSetup()
);
const indexPattern = createStubIndexPattern({
spec: {
id: 'non-existant-index',
},
});
savedObject.searchSource!.setFields({ index: indexPattern });
return savedObject.save(saveOptionsMock).then(() => {
const args = (savedObjectsClientStub.create as jest.Mock).mock.calls[0];
@ -746,14 +738,12 @@ describe('Saved Object', () => {
const savedObject = new SavedObjectClass(config);
savedObject.hydrateIndexPattern = jest.fn().mockImplementation(() => {
const indexPattern = getStubIndexPattern(
indexPatternId,
getConfig,
null,
[],
coreMock.createSetup()
);
indexPattern.title = indexPattern.id!;
const indexPattern = createStubIndexPattern({
spec: {
id: indexPatternId,
title: indexPatternId,
},
});
savedObject.searchSource!.setField('index', indexPattern);
return Bluebird.resolve(indexPattern);
});
@ -762,7 +752,7 @@ describe('Saved Object', () => {
return savedObject.init!().then(() => {
expect(afterESRespCallback).toHaveBeenCalled();
const index = savedObject.searchSource!.getField('index');
expect(index instanceof StubIndexPattern).toBe(true);
expect(index instanceof IndexPattern).toBe(true);
expect(index!.id).toEqual(indexPatternId);
});
});

View file

@ -7,7 +7,7 @@
*/
import $ from 'jquery';
import moment from 'moment';
import moment from 'moment-timezone';
import angular from 'angular';
import 'angular-mocks';
import sinon from 'sinon';

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import angular, { IRootScopeService, IScope, ICompileService } from 'angular';
import angular, { ICompileService, IRootScopeService, IScope } from 'angular';
import 'angular-mocks';
import 'angular-sanitize';
import $ from 'jquery';
@ -16,11 +16,10 @@ import { initTableVisLegacyModule } from './table_vis_legacy_module';
import { initAngularBootstrap } from '../../../kibana_legacy/public/angular_bootstrap';
import { tableVisLegacyTypeDefinition } from './table_vis_legacy_type';
import { Vis } from '../../../visualizations/public';
import { stubFields } from '../../../data/public/stubs';
import { createStubIndexPattern, stubFieldSpecMap } from '../../../data/public/stubs';
import { tableVisLegacyResponseHandler } from './table_vis_legacy_response_handler';
import { coreMock } from '../../../../core/public/mocks';
import { IAggConfig, search } from '../../../data/public';
import { getStubIndexPattern } from '../../../data/public/test_utils';
import { IAggConfig, IndexPattern, search } from '../../../data/public';
import { searchServiceMock } from '../../../data/public/search/mocks';
const { createAggConfigs } = searchServiceMock.createStartContract().aggs;
@ -66,7 +65,7 @@ describe('Table Vis - Controller', () => {
let $el: JQuery<HTMLElement>;
let tableAggResponse: any;
let tabifiedResponse: any;
let stubIndexPattern: any;
let stubIndexPattern: IndexPattern;
const initLocalAngular = () => {
const tableVisModule = getAngularModule(
@ -92,13 +91,14 @@ describe('Table Vis - Controller', () => {
);
beforeEach(() => {
stubIndexPattern = getStubIndexPattern(
'logstash-*',
(cfg: any) => cfg,
'time',
stubFields,
coreMock.createSetup()
);
stubIndexPattern = createStubIndexPattern({
spec: {
id: 'logstash-*',
title: 'logstash-*',
timeFieldName: 'time',
fields: stubFieldSpecMap,
},
});
});
function getRangeVis(params?: object) {

View file

@ -1,75 +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.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { shouldReadFieldFromDocValues, castEsToKbnFieldTypeName } from '../../../data/server';
function stubbedLogstashFields() {
return [
// |aggregatable
// | |searchable
// name esType | | |metadata | subType
['bytes', 'long', true, true, { count: 10 }],
['ssl', 'boolean', true, true, { count: 20 }],
['@timestamp', 'date', true, true, { count: 30 }],
['time', 'date', true, true, { count: 30 }],
['@tags', 'keyword', true, true],
['utc_time', 'date', true, true],
['phpmemory', 'integer', true, true],
['ip', 'ip', true, true],
['request_body', 'attachment', true, true],
['point', 'geo_point', true, true],
['area', 'geo_shape', true, true],
['hashed', 'murmur3', false, true],
['geo.coordinates', 'geo_point', true, true],
['extension', 'text', true, true],
['extension.keyword', 'keyword', true, true, {}, { multi: { parent: 'extension' } }],
['machine.os', 'text', true, true],
['machine.os.raw', 'keyword', true, true, {}, { multi: { parent: 'machine.os' } }],
['geo.src', 'keyword', true, true],
['_id', '_id', true, true],
['_type', '_type', true, true],
['_source', '_source', true, true],
['non-filterable', 'text', true, false],
['non-sortable', 'text', false, false],
['custom_user_field', 'conflict', true, true],
['script string', 'text', true, false, { script: "'i am a string'" }],
['script number', 'long', true, false, { script: '1234' }],
['script date', 'date', true, false, { script: '1234', lang: 'painless' }],
['script murmur3', 'murmur3', true, false, { script: '1234' }],
].map(function (row) {
const [name, esType, aggregatable, searchable, metadata = {}, subType = undefined] = row;
const {
count = 0,
script,
lang = script ? 'expression' : undefined,
scripted = !!script,
} = metadata;
// the conflict type is actually a kbnFieldType, we
// don't have any other way to represent it here
const type = esType === 'conflict' ? esType : castEsToKbnFieldTypeName(esType);
return {
name,
type,
esTypes: [esType],
readFromDocValues: shouldReadFieldFromDocValues(aggregatable, esType),
aggregatable,
searchable,
count,
script,
lang,
scripted,
subType,
};
});
}
export default stubbedLogstashFields;

View file

@ -1,47 +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.
*/
import stubbedLogstashFields from './logstash_fields';
import { getKbnFieldType } from '../../../data/common';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getStubIndexPattern } from '../../../data/public/test_utils';
import { uiSettingsServiceMock } from '../../../../core/public/mocks';
const uiSettingSetupMock = uiSettingsServiceMock.createSetupContract();
uiSettingSetupMock.get.mockImplementation((item, defaultValue) => {
return defaultValue;
});
export default function stubbedLogstashIndexPatternService() {
const mockLogstashFields = stubbedLogstashFields();
const fields = mockLogstashFields.map(function (field) {
const kbnType = getKbnFieldType(field.type);
if (!kbnType || kbnType.name === 'unknown') {
throw new TypeError(`unknown type ${field.type}`);
}
return {
...field,
sortable: 'sortable' in field ? !!field.sortable : kbnType.sortable,
filterable: 'filterable' in field ? !!field.filterable : kbnType.filterable,
displayName: field.name,
};
});
const indexPattern = getStubIndexPattern('logstash-*', (cfg) => cfg, 'time', fields, {
uiSettings: uiSettingSetupMock,
});
indexPattern.id = 'logstash-*';
indexPattern.isTimeNanosBased = () => false;
return indexPattern;
}

View file

@ -26,7 +26,7 @@ jest.mock('./services', () => {
// eslint-disable-next-line
const { SearchSource } = require('../../data/common/search/search_source');
// eslint-disable-next-line
const fixturesStubbedLogstashIndexPatternProvider = require('./__fixtures__/stubbed_logstash_index_pattern');
const stubIndexPattern = require('../../data/common/stubs');
const visType = new BaseVisType({
name: 'pie',
title: 'pie',
@ -44,7 +44,7 @@ jest.mock('./services', () => {
getSearch: () => ({
searchSource: {
create: () => {
return new SearchSource({ index: fixturesStubbedLogstashIndexPatternProvider });
return new SearchSource({ index: stubIndexPattern });
},
},
}),

View file

@ -31,7 +31,7 @@ export async function rollupServiceProvider(
estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] | null
> {
if (rollupIndexPatternObject !== null) {
const parsedTypeMetaData = JSON.parse(rollupIndexPatternObject.attributes.typeMeta);
const parsedTypeMetaData = JSON.parse(rollupIndexPatternObject.attributes.typeMeta!);
const rollUpIndex: string = parsedTypeMetaData.params.rollup_index;
const { body: rollupCaps } = await asCurrentUser.rollup.getRollupIndexCaps({
index: rollUpIndex,

View file

@ -7,31 +7,32 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/dom';
import { render, mockCore, mockAppIndexPattern } from './rtl_helpers';
import { render, mockAppIndexPattern } from './rtl_helpers';
import { ExploratoryView } from './exploratory_view';
import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/test_utils';
import * as obsvInd from './utils/observability_index_patterns';
import { createStubIndexPattern } from '../../../../../../../src/plugins/data/common/stubs';
describe('ExploratoryView', () => {
mockAppIndexPattern();
beforeEach(() => {
const indexPattern = getStubIndexPattern(
'apm-*',
() => {},
'@timestamp',
[
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
searchable: true,
aggregatable: true,
readFromDocValues: true,
const indexPattern = createStubIndexPattern({
spec: {
id: 'apm-*',
title: 'apm-*',
timeFieldName: '@timestamp',
fields: {
'@timestamp': {
name: '@timestamp',
type: 'date',
esTypes: ['date'],
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
},
],
mockCore() as any
);
},
});
jest.spyOn(obsvInd, 'ObservabilityIndexPatterns').mockReturnValue({
getIndexPattern: jest.fn().mockReturnValue(indexPattern),

View file

@ -30,8 +30,7 @@ import * as fetcherHook from '../../../hooks/use_fetcher';
import * as useSeriesFilterHook from './hooks/use_series_filters';
import * as useHasDataHook from '../../../hooks/use_has_data';
import * as useValuesListHook from '../../../hooks/use_values_list';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/index_patterns/index_pattern.stub';
import indexPatternData from './configurations/test_data/test_index_pattern.json';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { setIndexPatterns } from '../../../../../../../src/plugins/data/public/services';
@ -39,6 +38,7 @@ import {
IndexPattern,
IndexPatternsContract,
} from '../../../../../../../src/plugins/data/common/index_patterns/index_patterns';
import { createStubIndexPattern } from '../../../../../../../src/plugins/data/common/stubs';
import { AppDataType, UrlFilter } from './types';
import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks';
import { ListItem } from '../../../hooks/use_values_list';
@ -320,10 +320,11 @@ export const mockHistory = {
},
};
export const mockIndexPattern = getStubIndexPattern(
'apm-*',
() => {},
'@timestamp',
JSON.parse(indexPatternData.attributes.fields),
mockCore() as any
);
export const mockIndexPattern = createStubIndexPattern({
spec: {
id: 'apm-*',
title: 'apm-*',
timeFieldName: '@timestamp',
fields: JSON.parse(indexPatternData.attributes.fields),
},
});

View file

@ -13,10 +13,7 @@ import { mount, ReactWrapper } from 'enzyme';
import { EditExceptionModal } from './';
import { useCurrentUser } from '../../../../common/lib/kibana';
import { useFetchIndex } from '../../../containers/source';
import {
stubIndexPattern,
stubIndexPatternWithFields,
} from 'src/plugins/data/common/index_patterns/index_pattern.stub';
import { stubIndexPattern, createStubIndexPattern } from 'src/plugins/data/common/stubs';
import { useAddOrUpdateException } from '../use_add_exception';
import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index';
import { getExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
@ -82,7 +79,21 @@ describe('When the edit exception modal is opened', () => {
(useFetchIndex as jest.Mock).mockImplementation(() => [
false,
{
indexPatterns: stubIndexPatternWithFields,
indexPatterns: createStubIndexPattern({
spec: {
id: '1234',
title: 'logstash-*',
fields: {
response: {
name: 'response',
type: 'number',
esTypes: ['integer'],
aggregatable: true,
searchable: true,
},
},
},
}),
},
]);
(useCurrentUser as jest.Mock).mockReturnValue({ username: 'test-username' });

View file

@ -8,7 +8,7 @@ import React from 'react';
import { EventFiltersForm } from '.';
import { RenderResult, act } from '@testing-library/react';
import { fireEvent, waitFor } from '@testing-library/dom';
import { stubIndexPatternWithFields } from 'src/plugins/data/common/index_patterns/index_pattern.stub';
import { stubIndexPattern } from 'src/plugins/data/common/stubs';
import { getInitialExceptionFromEvent } from '../../../store/utils';
import { useFetchIndex } from '../../../../../../common/containers/source';
import { ecsEventMock } from '../../../test_utils';
@ -52,7 +52,7 @@ describe('Event filter form', () => {
(useFetchIndex as jest.Mock).mockImplementation(() => [
false,
{
indexPatterns: stubIndexPatternWithFields,
indexPatterns: stubIndexPattern,
},
]);
(useCurrentUser as jest.Mock).mockReturnValue({ username: 'test-username' });