[Regression] Histogram aggregation always shows an error message (#63484)

* WIP [Regression] Histogram aggregation always shows an error message

Closes: #62624

* make getInternalStartServices private

* fix ts issues

* remove createSearchSource from static contract

* fix some jest test

* move searh_source to static contract

* fix types

* fix function tests

* fix jest / add createStartServicesGetter

* fix comments: saved_object_management

* maps: fix PR comments

* maps: update types

* fix heck_published_api_changes

* move searchSource into runtime contract

* cleanup

* fix ts error

* cleanup

* remove extra dependencies

* fix Discover

* fix Discover JEST

* fix PR comments

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Alexey Antonov 2020-04-22 19:21:14 +03:00 committed by GitHub
parent 54ca7ed8a1
commit 0a6da70a89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
109 changed files with 1011 additions and 1296 deletions

View file

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md)
## createSearchSource variable
Deserializes a json string and a set of referenced objects to a `SearchSource` instance. Use this method to re-create the search source serialized using `searchSource.serialize`<!-- -->.
This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service
<b>Signature:</b>
```typescript
createSearchSource: (indexPatterns: Pick<import("../../index_patterns/index_patterns").IndexPatternsService, "get" | "clearCache" | "getFieldsForTimePattern" | "getFieldsForWildcard" | "getIds" | "getTitles" | "getFields" | "getCache" | "getDefault" | "make">) => (searchSourceJson: string, references: SavedObjectReference[]) => Promise<SearchSource>
```

View file

@ -4,6 +4,8 @@
## ISearchSource type
\*
<b>Signature:</b>
```typescript

View file

@ -21,7 +21,6 @@
| [RequestTimeoutError](./kibana-plugin-plugins-data-public.requesttimeouterror.md) | Class used to signify that a request timed out. Useful for applications to conditionally handle this type of error differently than other errors. |
| [SearchError](./kibana-plugin-plugins-data-public.searcherror.md) | |
| [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) | |
| [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) | |
| [TimeHistory](./kibana-plugin-plugins-data-public.timehistory.md) | |
## Enumerations
@ -101,7 +100,6 @@
| [castEsToKbnFieldTypeName](./kibana-plugin-plugins-data-public.castestokbnfieldtypename.md) | Get the KbnFieldType name for an esType string |
| [connectToQueryState](./kibana-plugin-plugins-data-public.connecttoquerystate.md) | Helper to setup two-way syncing of global data and a state container |
| [createSavedQueryService](./kibana-plugin-plugins-data-public.createsavedqueryservice.md) | |
| [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md) | Deserializes a json string and a set of referenced objects to a <code>SearchSource</code> instance. Use this method to re-create the search source serialized using <code>searchSource.serialize</code>.<!-- -->This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service |
| [ES\_SEARCH\_STRATEGY](./kibana-plugin-plugins-data-public.es_search_strategy.md) | |
| [esFilters](./kibana-plugin-plugins-data-public.esfilters.md) | |
| [esKuery](./kibana-plugin-plugins-data-public.eskuery.md) | |
@ -140,7 +138,7 @@
| [IpRangeKey](./kibana-plugin-plugins-data-public.iprangekey.md) | |
| [ISearch](./kibana-plugin-plugins-data-public.isearch.md) | |
| [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) | |
| [ISearchSource](./kibana-plugin-plugins-data-public.isearchsource.md) | |
| [ISearchSource](./kibana-plugin-plugins-data-public.isearchsource.md) | \* |
| [MatchAllFilter](./kibana-plugin-plugins-data-public.matchallfilter.md) | |
| [ParsedInterval](./kibana-plugin-plugins-data-public.parsedinterval.md) | |
| [PhraseFilter](./kibana-plugin-plugins-data-public.phrasefilter.md) | |

View file

@ -27,8 +27,9 @@ search: {
InvalidEsCalendarIntervalError: typeof InvalidEsCalendarIntervalError;
InvalidEsIntervalFormatError: typeof InvalidEsIntervalFormatError;
isDateHistogramBucketAggConfig: typeof isDateHistogramBucketAggConfig;
isNumberType: (agg: import("./search").AggConfig) => boolean;
isStringType: (agg: import("./search").AggConfig) => boolean;
isType: (type: string) => (agg: import("./search").AggConfig) => boolean;
isType: (...types: string[]) => (agg: import("./search").AggConfig) => boolean;
isValidEsInterval: typeof isValidEsInterval;
isValidInterval: typeof isValidInterval;
parentPipelineType: string;

View file

@ -1,20 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [(constructor)](./kibana-plugin-plugins-data-public.searchsource._constructor_.md)
## SearchSource.(constructor)
Constructs a new instance of the `SearchSource` class
<b>Signature:</b>
```typescript
constructor(fields?: SearchSourceFields);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| fields | <code>SearchSourceFields</code> | |

View file

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [create](./kibana-plugin-plugins-data-public.searchsource.create.md)
## SearchSource.create() method
<b>Signature:</b>
```typescript
create(): SearchSource;
```
<b>Returns:</b>
`SearchSource`

View file

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [createChild](./kibana-plugin-plugins-data-public.searchsource.createchild.md)
## SearchSource.createChild() method
<b>Signature:</b>
```typescript
createChild(options?: {}): SearchSource;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | <code>{}</code> | |
<b>Returns:</b>
`SearchSource`

View file

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [createCopy](./kibana-plugin-plugins-data-public.searchsource.createcopy.md)
## SearchSource.createCopy() method
<b>Signature:</b>
```typescript
createCopy(): SearchSource;
```
<b>Returns:</b>
`SearchSource`

View file

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [destroy](./kibana-plugin-plugins-data-public.searchsource.destroy.md)
## SearchSource.destroy() method
Completely destroy the SearchSource. {<!-- -->undefined<!-- -->}
<b>Signature:</b>
```typescript
destroy(): void;
```
<b>Returns:</b>
`void`

View file

@ -1,25 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [fetch](./kibana-plugin-plugins-data-public.searchsource.fetch.md)
## SearchSource.fetch() method
Fetch this source and reject the returned Promise on error
<b>Signature:</b>
```typescript
fetch(options?: FetchOptions): Promise<any>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | <code>FetchOptions</code> | |
<b>Returns:</b>
`Promise<any>`

View file

@ -1,25 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getField](./kibana-plugin-plugins-data-public.searchsource.getfield.md)
## SearchSource.getField() method
Get fields from the fields
<b>Signature:</b>
```typescript
getField<K extends keyof SearchSourceFields>(field: K, recurse?: boolean): SearchSourceFields[K];
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| field | <code>K</code> | |
| recurse | <code>boolean</code> | |
<b>Returns:</b>
`SearchSourceFields[K]`

View file

@ -1,49 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getFields](./kibana-plugin-plugins-data-public.searchsource.getfields.md)
## SearchSource.getFields() method
<b>Signature:</b>
```typescript
getFields(): {
type?: string | undefined;
query?: import("../..").Query | undefined;
filter?: Filter | Filter[] | (() => Filter | Filter[] | undefined) | undefined;
sort?: Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric> | Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric>[] | undefined;
highlight?: any;
highlightAll?: boolean | undefined;
aggs?: any;
from?: number | undefined;
size?: number | undefined;
source?: string | boolean | string[] | undefined;
version?: boolean | undefined;
fields?: string | boolean | string[] | undefined;
index?: import("../..").IndexPattern | undefined;
searchAfter?: import("./types").EsQuerySearchAfter | undefined;
timeout?: string | undefined;
terminate_after?: number | undefined;
};
```
<b>Returns:</b>
`{
type?: string | undefined;
query?: import("../..").Query | undefined;
filter?: Filter | Filter[] | (() => Filter | Filter[] | undefined) | undefined;
sort?: Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric> | Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric>[] | undefined;
highlight?: any;
highlightAll?: boolean | undefined;
aggs?: any;
from?: number | undefined;
size?: number | undefined;
source?: string | boolean | string[] | undefined;
version?: boolean | undefined;
fields?: string | boolean | string[] | undefined;
index?: import("../..").IndexPattern | undefined;
searchAfter?: import("./types").EsQuerySearchAfter | undefined;
timeout?: string | undefined;
terminate_after?: number | undefined;
}`

View file

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getId](./kibana-plugin-plugins-data-public.searchsource.getid.md)
## SearchSource.getId() method
<b>Signature:</b>
```typescript
getId(): string;
```
<b>Returns:</b>
`string`

View file

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getOwnField](./kibana-plugin-plugins-data-public.searchsource.getownfield.md)
## SearchSource.getOwnField() method
Get the field from our own fields, don't traverse up the chain
<b>Signature:</b>
```typescript
getOwnField<K extends keyof SearchSourceFields>(field: K): SearchSourceFields[K];
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| field | <code>K</code> | |
<b>Returns:</b>
`SearchSourceFields[K]`

View file

@ -1,17 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getParent](./kibana-plugin-plugins-data-public.searchsource.getparent.md)
## SearchSource.getParent() method
Get the parent of this SearchSource {<!-- -->undefined\|searchSource<!-- -->}
<b>Signature:</b>
```typescript
getParent(): SearchSource | undefined;
```
<b>Returns:</b>
`SearchSource | undefined`

View file

@ -1,15 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [getSearchRequestBody](./kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md)
## SearchSource.getSearchRequestBody() method
<b>Signature:</b>
```typescript
getSearchRequestBody(): Promise<any>;
```
<b>Returns:</b>
`Promise<any>`

View file

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [history](./kibana-plugin-plugins-data-public.searchsource.history.md)
## SearchSource.history property
<b>Signature:</b>
```typescript
history: SearchRequest[];
```

View file

@ -1,46 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md)
## SearchSource class
<b>Signature:</b>
```typescript
export declare class SearchSource
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(fields)](./kibana-plugin-plugins-data-public.searchsource._constructor_.md) | | Constructs a new instance of the <code>SearchSource</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [history](./kibana-plugin-plugins-data-public.searchsource.history.md) | | <code>SearchRequest[]</code> | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [create()](./kibana-plugin-plugins-data-public.searchsource.create.md) | | |
| [createChild(options)](./kibana-plugin-plugins-data-public.searchsource.createchild.md) | | |
| [createCopy()](./kibana-plugin-plugins-data-public.searchsource.createcopy.md) | | |
| [destroy()](./kibana-plugin-plugins-data-public.searchsource.destroy.md) | | Completely destroy the SearchSource. {<!-- -->undefined<!-- -->} |
| [fetch(options)](./kibana-plugin-plugins-data-public.searchsource.fetch.md) | | Fetch this source and reject the returned Promise on error |
| [getField(field, recurse)](./kibana-plugin-plugins-data-public.searchsource.getfield.md) | | Get fields from the fields |
| [getFields()](./kibana-plugin-plugins-data-public.searchsource.getfields.md) | | |
| [getId()](./kibana-plugin-plugins-data-public.searchsource.getid.md) | | |
| [getOwnField(field)](./kibana-plugin-plugins-data-public.searchsource.getownfield.md) | | Get the field from our own fields, don't traverse up the chain |
| [getParent()](./kibana-plugin-plugins-data-public.searchsource.getparent.md) | | Get the parent of this SearchSource {<!-- -->undefined\|searchSource<!-- -->} |
| [getSearchRequestBody()](./kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md) | | |
| [onRequestStart(handler)](./kibana-plugin-plugins-data-public.searchsource.onrequeststart.md) | | Add a handler that will be notified whenever requests start |
| [serialize()](./kibana-plugin-plugins-data-public.searchsource.serialize.md) | | Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.<!-- -->The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named <code>kibanaSavedObjectMeta.searchSourceJSON.index</code> and <code>kibanaSavedObjectMeta.searchSourceJSON.filter[&lt;number&gt;].meta.index</code>.<!-- -->Using <code>createSearchSource</code>, the instance can be re-created. |
| [setField(field, value)](./kibana-plugin-plugins-data-public.searchsource.setfield.md) | | |
| [setFields(newFields)](./kibana-plugin-plugins-data-public.searchsource.setfields.md) | | |
| [setParent(parent, options)](./kibana-plugin-plugins-data-public.searchsource.setparent.md) | | Set a searchSource that this source should inherit from |
| [setPreferredSearchStrategyId(searchStrategyId)](./kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md) | | \*\*\* PUBLIC API \*\*\* |

View file

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [onRequestStart](./kibana-plugin-plugins-data-public.searchsource.onrequeststart.md)
## SearchSource.onRequestStart() method
Add a handler that will be notified whenever requests start
<b>Signature:</b>
```typescript
onRequestStart(handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise<unknown>): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| handler | <code>(searchSource: ISearchSource, options?: FetchOptions) =&gt; Promise&lt;unknown&gt;</code> | |
<b>Returns:</b>
`void`

View file

@ -1,27 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [serialize](./kibana-plugin-plugins-data-public.searchsource.serialize.md)
## SearchSource.serialize() method
Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.
The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named `kibanaSavedObjectMeta.searchSourceJSON.index` and `kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index`<!-- -->.
Using `createSearchSource`<!-- -->, the instance can be re-created.
<b>Signature:</b>
```typescript
serialize(): {
searchSourceJSON: string;
references: SavedObjectReference[];
};
```
<b>Returns:</b>
`{
searchSourceJSON: string;
references: SavedObjectReference[];
}`

View file

@ -1,23 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [setField](./kibana-plugin-plugins-data-public.searchsource.setfield.md)
## SearchSource.setField() method
<b>Signature:</b>
```typescript
setField<K extends keyof SearchSourceFields>(field: K, value: SearchSourceFields[K]): this;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| field | <code>K</code> | |
| value | <code>SearchSourceFields[K]</code> | |
<b>Returns:</b>
`this`

View file

@ -1,22 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [setFields](./kibana-plugin-plugins-data-public.searchsource.setfields.md)
## SearchSource.setFields() method
<b>Signature:</b>
```typescript
setFields(newFields: SearchSourceFields): this;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| newFields | <code>SearchSourceFields</code> | |
<b>Returns:</b>
`this`

View file

@ -1,25 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [setParent](./kibana-plugin-plugins-data-public.searchsource.setparent.md)
## SearchSource.setParent() method
Set a searchSource that this source should inherit from
<b>Signature:</b>
```typescript
setParent(parent?: ISearchSource, options?: SearchSourceOptions): this;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| parent | <code>ISearchSource</code> | |
| options | <code>SearchSourceOptions</code> | |
<b>Returns:</b>
`this`

View file

@ -1,24 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) &gt; [setPreferredSearchStrategyId](./kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md)
## SearchSource.setPreferredSearchStrategyId() method
\*\*\* PUBLIC API \*\*\*
<b>Signature:</b>
```typescript
setPreferredSearchStrategyId(searchStrategyId: string): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| searchStrategyId | <code>string</code> | |
<b>Returns:</b>
`void`

View file

@ -40,6 +40,11 @@ exports[`renders ControlsTab 1`] = `
"timefilter": Object {},
},
},
"search": Object {
"searchSource": Object {
"create": [MockFunction],
},
},
},
}
}
@ -96,6 +101,11 @@ exports[`renders ControlsTab 1`] = `
"timefilter": Object {},
},
},
"search": Object {
"searchSource": Object {
"create": [MockFunction],
},
},
},
}
}

View file

@ -21,7 +21,6 @@ import expect from '@kbn/expect';
import { Control } from './control';
import { ControlParams } from '../editor_utils';
import { FilterManager as BaseFilterManager } from './filter_manager/filter_manager';
import { SearchSource } from '../legacy_imports';
function createControlParams(id: string, label: string): ControlParams {
return {
@ -51,18 +50,12 @@ class ControlMock extends Control<BaseFilterManager> {
destroy() {}
}
const mockKbnApi: SearchSource = {} as SearchSource;
describe('hasChanged', () => {
let control: ControlMock;
beforeEach(() => {
control = new ControlMock(
createControlParams('3', 'control'),
mockFilterManager,
false,
mockKbnApi
);
control = new ControlMock(createControlParams('3', 'control'), mockFilterManager, false);
});
afterEach(() => {
@ -93,20 +86,17 @@ describe('ancestors', () => {
grandParentControl = new ControlMock(
createControlParams('1', 'grandparent control'),
mockFilterManager,
false,
mockKbnApi
false
);
parentControl = new ControlMock(
createControlParams('2', 'parent control'),
mockFilterManager,
false,
mockKbnApi
false
);
childControl = new ControlMock(
createControlParams('3', 'child control'),
mockFilterManager,
false,
mockKbnApi
false
);
});

View file

@ -23,7 +23,6 @@ import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { Filter } from '../../../../../plugins/data/public';
import { SearchSource as SearchSourceClass } from '../legacy_imports';
import { ControlParams, ControlParamsOptions, CONTROL_TYPES } from '../editor_utils';
import { RangeFilterManager } from './filter_manager/range_filter_manager';
import { PhraseFilterManager } from './filter_manager/phrase_filter_manager';
@ -61,8 +60,7 @@ export abstract class Control<FilterManager extends BaseFilterManager> {
constructor(
public controlParams: ControlParams,
public filterManager: FilterManager,
public useTimeFilter: boolean,
public SearchSource: SearchSourceClass
public useTimeFilter: boolean
) {
this.id = controlParams.id;
this.controlParams = controlParams;

View file

@ -17,11 +17,16 @@
* under the License.
*/
import { PhraseFilter, IndexPattern, TimefilterContract } from '../../../../../plugins/data/public';
import { SearchSource as SearchSourceClass, SearchSourceFields } from '../legacy_imports';
import {
SearchSourceFields,
PhraseFilter,
IndexPattern,
TimefilterContract,
DataPublicPluginStart,
} from '../../../../../plugins/data/public';
export function createSearchSource(
SearchSource: SearchSourceClass,
{ create }: DataPublicPluginStart['search']['searchSource'],
initialState: SearchSourceFields | null,
indexPattern: IndexPattern,
aggs: any,
@ -29,7 +34,8 @@ export function createSearchSource(
filters: PhraseFilter[] = [],
timefilter: TimefilterContract
) {
const searchSource = initialState ? new SearchSource(initialState) : new SearchSource();
const searchSource = create(initialState || {});
// Do not not inherit from rootSearchSource to avoid picking up time and globals
searchSource.setParent(undefined);
searchSource.setField('filter', () => {

View file

@ -21,98 +21,17 @@ import { listControlFactory, ListControl } from './list_control_factory';
import { ControlParams, CONTROL_TYPES } from '../editor_utils';
import { getDepsMock, getSearchSourceMock } from '../test_utils';
const MockSearchSource = getSearchSourceMock();
const deps = getDepsMock();
jest.doMock('./create_search_source.ts', () => ({
createSearchSource: MockSearchSource,
}));
describe('hasValue', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
const useTimeFilter = false;
let listControl: ListControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, MockSearchSource, deps);
describe('listControlFactory', () => {
const searchSourceMock = getSearchSourceMock();
const deps = getDepsMock({
searchSource: {
create: searchSourceMock,
},
});
test('should be false when control has no value', () => {
expect(listControl.hasValue()).toBe(false);
});
test('should be true when control has value', () => {
listControl.set([{ value: 'selected option', label: 'selection option' }]);
expect(listControl.hasValue()).toBe(true);
});
test('should be true when control has value that is the string "false"', () => {
listControl.set([{ value: 'false', label: 'selection option' }]);
expect(listControl.hasValue()).toBe(true);
});
});
describe('fetch', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
const useTimeFilter = false;
let listControl: ListControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, MockSearchSource, deps);
});
test('should pass in timeout parameters from injected vars', async () => {
await listControl.fetch();
expect(MockSearchSource).toHaveBeenCalledWith({
timeout: `1000ms`,
terminate_after: 100000,
});
});
test('should set selectOptions to results of terms aggregation', async () => {
await listControl.fetch();
expect(listControl.selectOptions).toEqual([
'Zurich Airport',
'Xi an Xianyang International Airport',
]);
});
});
describe('fetch with ancestors', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
const useTimeFilter = false;
let listControl: ListControl;
let parentControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, MockSearchSource, deps);
const parentControlParams: ControlParams = {
id: 'parent',
describe('hasValue', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
@ -120,26 +39,104 @@ describe('fetch with ancestors', () => {
indexPattern: {} as any,
parent: 'parent',
};
parentControl = await listControlFactory(
parentControlParams,
useTimeFilter,
MockSearchSource,
deps
);
parentControl.clear();
listControl.setAncestors([parentControl]);
});
const useTimeFilter = false;
describe('ancestor does not have value', () => {
test('should disable control', async () => {
await listControl.fetch();
expect(listControl.isEnabled()).toBe(false);
let listControl: ListControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, deps);
});
test('should reset lastAncestorValues', async () => {
listControl.lastAncestorValues = 'last ancestor value';
test('should be false when control has no value', () => {
expect(listControl.hasValue()).toBe(false);
});
test('should be true when control has value', () => {
listControl.set([{ value: 'selected option', label: 'selection option' }]);
expect(listControl.hasValue()).toBe(true);
});
test('should be true when control has value that is the string "false"', () => {
listControl.set([{ value: 'false', label: 'selection option' }]);
expect(listControl.hasValue()).toBe(true);
});
});
describe('fetch', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
const useTimeFilter = false;
let listControl: ListControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, deps);
});
test('should pass in timeout parameters from injected vars', async () => {
await listControl.fetch();
expect(listControl.lastAncestorValues).toBeUndefined();
expect(searchSourceMock).toHaveBeenCalledWith({
timeout: `1000ms`,
terminate_after: 100000,
});
});
test('should set selectOptions to results of terms aggregation', async () => {
await listControl.fetch();
expect(listControl.selectOptions).toEqual([
'Zurich Airport',
'Xi an Xianyang International Airport',
]);
});
});
describe('fetch with ancestors', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
const useTimeFilter = false;
let listControl: ListControl;
let parentControl;
beforeEach(async () => {
listControl = await listControlFactory(controlParams, useTimeFilter, deps);
const parentControlParams: ControlParams = {
id: 'parent',
fieldName: 'myField',
options: {} as any,
type: CONTROL_TYPES.LIST,
label: 'test',
indexPattern: {} as any,
parent: 'parent',
};
parentControl = await listControlFactory(parentControlParams, useTimeFilter, deps);
parentControl.clear();
listControl.setAncestors([parentControl]);
});
describe('ancestor does not have value', () => {
test('should disable control', async () => {
await listControl.fetch();
expect(listControl.isEnabled()).toBe(false);
});
test('should reset lastAncestorValues', async () => {
listControl.lastAncestorValues = 'last ancestor value';
await listControl.fetch();
expect(listControl.lastAncestorValues).toBeUndefined();
});
});
});
});

View file

@ -19,14 +19,17 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { SearchSource as SearchSourceClass, SearchSourceFields } from '../legacy_imports';
import { Control, noValuesDisableMsg, noIndexPatternMsg } from './control';
import { PhraseFilterManager } from './filter_manager/phrase_filter_manager';
import { createSearchSource } from './create_search_source';
import { ControlParams } from '../editor_utils';
import { InputControlVisDependencies } from '../plugin';
import { IFieldType, TimefilterContract } from '../../../../../plugins/data/public';
import {
IFieldType,
TimefilterContract,
SearchSourceFields,
DataPublicPluginStart,
} from '../../../../../plugins/data/public';
function getEscapedQuery(query = '') {
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html#_standard_operators
@ -75,6 +78,7 @@ const termsAgg = ({ field, size, direction, query }: TermsAggArgs) => {
export class ListControl extends Control<PhraseFilterManager> {
private getInjectedVar: InputControlVisDependencies['core']['injectedMetadata']['getInjectedVar'];
private timefilter: TimefilterContract;
private searchSource: DataPublicPluginStart['search']['searchSource'];
abortController?: AbortController;
lastAncestorValues: any;
@ -86,12 +90,13 @@ export class ListControl extends Control<PhraseFilterManager> {
controlParams: ControlParams,
filterManager: PhraseFilterManager,
useTimeFilter: boolean,
SearchSource: SearchSourceClass,
searchSource: DataPublicPluginStart['search']['searchSource'],
deps: InputControlVisDependencies
) {
super(controlParams, filterManager, useTimeFilter, SearchSource);
super(controlParams, filterManager, useTimeFilter);
this.getInjectedVar = deps.core.injectedMetadata.getInjectedVar;
this.timefilter = deps.data.query.timefilter.timefilter;
this.searchSource = searchSource;
}
fetch = async (query?: string) => {
@ -143,7 +148,7 @@ export class ListControl extends Control<PhraseFilterManager> {
query,
});
const searchSource = createSearchSource(
this.SearchSource,
this.searchSource,
initialSearchSourceState,
indexPattern,
aggs,
@ -202,7 +207,6 @@ export class ListControl extends Control<PhraseFilterManager> {
export async function listControlFactory(
controlParams: ControlParams,
useTimeFilter: boolean,
SearchSource: SearchSourceClass,
deps: InputControlVisDependencies
) {
const [, { data: dataPluginStart }] = await deps.core.getStartServices();
@ -225,7 +229,7 @@ export async function listControlFactory(
deps.data.query.filterManager
),
useTimeFilter,
SearchSource,
dataPluginStart.search.searchSource,
deps
);
return listControl;

View file

@ -21,71 +21,77 @@ import { rangeControlFactory } from './range_control_factory';
import { ControlParams, CONTROL_TYPES } from '../editor_utils';
import { getDepsMock, getSearchSourceMock } from '../test_utils';
const deps = getDepsMock();
describe('fetch', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myNumberField',
options: {},
type: CONTROL_TYPES.RANGE,
label: 'test',
indexPattern: {} as any,
parent: {} as any,
};
const useTimeFilter = false;
test('should set min and max from aggregation results', async () => {
const esSearchResponse = {
aggregations: {
maxAgg: { value: 100 },
minAgg: { value: 10 },
},
describe('rangeControlFactory', () => {
describe('fetch', () => {
const controlParams: ControlParams = {
id: '1',
fieldName: 'myNumberField',
options: {},
type: CONTROL_TYPES.RANGE,
label: 'test',
indexPattern: {} as any,
parent: {} as any,
};
const rangeControl = await rangeControlFactory(
controlParams,
useTimeFilter,
getSearchSourceMock(esSearchResponse),
deps
);
await rangeControl.fetch();
const useTimeFilter = false;
expect(rangeControl.isEnabled()).toBe(true);
expect(rangeControl.min).toBe(10);
expect(rangeControl.max).toBe(100);
});
test('should set min and max from aggregation results', async () => {
const esSearchResponse = {
aggregations: {
maxAgg: { value: 100 },
minAgg: { value: 10 },
},
};
const searchSourceMock = getSearchSourceMock(esSearchResponse);
const deps = getDepsMock({
searchSource: {
create: searchSourceMock,
},
});
test('should disable control when there are 0 hits', async () => {
// ES response when the query does not match any documents
const esSearchResponse = {
aggregations: {
maxAgg: { value: null },
minAgg: { value: null },
},
};
const rangeControl = await rangeControlFactory(
controlParams,
useTimeFilter,
getSearchSourceMock(esSearchResponse),
deps
);
await rangeControl.fetch();
const rangeControl = await rangeControlFactory(controlParams, useTimeFilter, deps);
await rangeControl.fetch();
expect(rangeControl.isEnabled()).toBe(false);
});
expect(rangeControl.isEnabled()).toBe(true);
expect(rangeControl.min).toBe(10);
expect(rangeControl.max).toBe(100);
});
test('should disable control when response is empty', async () => {
// ES response for dashboardonly user who does not have read permissions on index is 200 (which is weird)
// and there is not aggregations key
const esSearchResponse = {};
const rangeControl = await rangeControlFactory(
controlParams,
useTimeFilter,
getSearchSourceMock(esSearchResponse),
deps
);
await rangeControl.fetch();
test('should disable control when there are 0 hits', async () => {
// ES response when the query does not match any documents
const esSearchResponse = {
aggregations: {
maxAgg: { value: null },
minAgg: { value: null },
},
};
const searchSourceMock = getSearchSourceMock(esSearchResponse);
const deps = getDepsMock({
searchSource: {
create: searchSourceMock,
},
});
expect(rangeControl.isEnabled()).toBe(false);
const rangeControl = await rangeControlFactory(controlParams, useTimeFilter, deps);
await rangeControl.fetch();
expect(rangeControl.isEnabled()).toBe(false);
});
test('should disable control when response is empty', async () => {
// ES response for dashboardonly user who does not have read permissions on index is 200 (which is weird)
// and there is not aggregations key
const esSearchResponse = {};
const searchSourceMock = getSearchSourceMock(esSearchResponse);
const deps = getDepsMock({
searchSource: {
create: searchSourceMock,
},
});
const rangeControl = await rangeControlFactory(controlParams, useTimeFilter, deps);
await rangeControl.fetch();
expect(rangeControl.isEnabled()).toBe(false);
});
});
});

View file

@ -20,13 +20,16 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { SearchSource as SearchSourceClass } from '../legacy_imports';
import { Control, noValuesDisableMsg, noIndexPatternMsg } from './control';
import { RangeFilterManager } from './filter_manager/range_filter_manager';
import { createSearchSource } from './create_search_source';
import { ControlParams } from '../editor_utils';
import { InputControlVisDependencies } from '../plugin';
import { IFieldType, TimefilterContract } from '../.../../../../../../plugins/data/public';
import {
IFieldType,
TimefilterContract,
DataPublicPluginStart,
} from '../.../../../../../../plugins/data/public';
const minMaxAgg = (field?: IFieldType) => {
const aggBody: any = {};
@ -52,6 +55,8 @@ const minMaxAgg = (field?: IFieldType) => {
};
export class RangeControl extends Control<RangeFilterManager> {
private searchSource: DataPublicPluginStart['search']['searchSource'];
timefilter: TimefilterContract;
abortController: any;
min: any;
@ -61,11 +66,12 @@ export class RangeControl extends Control<RangeFilterManager> {
controlParams: ControlParams,
filterManager: RangeFilterManager,
useTimeFilter: boolean,
SearchSource: SearchSourceClass,
searchSource: DataPublicPluginStart['search']['searchSource'],
deps: InputControlVisDependencies
) {
super(controlParams, filterManager, useTimeFilter, SearchSource);
super(controlParams, filterManager, useTimeFilter);
this.timefilter = deps.data.query.timefilter.timefilter;
this.searchSource = searchSource;
}
async fetch() {
@ -83,7 +89,7 @@ export class RangeControl extends Control<RangeFilterManager> {
const fieldName = this.filterManager.fieldName;
const aggs = minMaxAgg(indexPattern.fields.getByName(fieldName));
const searchSource = createSearchSource(
this.SearchSource,
this.searchSource,
null,
indexPattern,
aggs,
@ -129,7 +135,6 @@ export class RangeControl extends Control<RangeFilterManager> {
export async function rangeControlFactory(
controlParams: ControlParams,
useTimeFilter: boolean,
SearchSource: SearchSourceClass,
deps: InputControlVisDependencies
): Promise<RangeControl> {
const [, { data: dataPluginStart }] = await deps.core.getStartServices();
@ -144,7 +149,7 @@ export async function rangeControlFactory(
deps.data.query.filterManager
),
useTimeFilter,
SearchSource,
dataPluginStart.search.searchSource,
deps
);
}

View file

@ -22,8 +22,6 @@ import { createInputControlVisFn } from './input_control_fn';
// eslint-disable-next-line
import { functionWrapper } from '../../../../plugins/expressions/common/expression_functions/specs/tests/utils';
jest.mock('./legacy_imports.ts');
describe('interpreter/functions#input_control_vis', () => {
const fn = functionWrapper(createInputControlVisFn());
const visConfig = {
@ -48,8 +46,9 @@ describe('interpreter/functions#input_control_vis', () => {
pinFilters: false,
};
it('returns an object with the correct structure', async () => {
test('returns an object with the correct structure', async () => {
const actual = await fn(null, { visConfig: JSON.stringify(visConfig) });
expect(actual).toMatchSnapshot();
});
});

View file

@ -1,26 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Class } from '@kbn/utility-types';
import { SearchSource as SearchSourceClass, ISearchSource } from '../../../../plugins/data/public';
export { SearchSourceFields } from '../../../../plugins/data/public';
export type SearchSource = Class<ISearchSource>;
export const SearchSource = SearchSourceClass;

View file

@ -19,6 +19,7 @@
import React from 'react';
import { InputControlVisDependencies } from '../plugin';
import { getSearchSourceMock } from './get_search_service_mock';
const fields = [] as any;
fields.push({ name: 'myField' } as any);
@ -26,13 +27,20 @@ fields.getByName = (name: any) => {
return fields.find(({ name: n }: { name: string }) => n === name);
};
export const getDepsMock = (): InputControlVisDependencies =>
export const getDepsMock = ({
searchSource = {
create: getSearchSourceMock(),
},
} = {}): InputControlVisDependencies =>
({
core: {
getStartServices: jest.fn().mockReturnValue([
null,
{
data: {
search: {
searchSource,
},
ui: {
IndexPatternSelect: () => (<div />) as any,
},
@ -58,6 +66,11 @@ export const getDepsMock = (): InputControlVisDependencies =>
},
},
data: {
search: {
searchSource: {
create: getSearchSourceMock(),
},
},
query: {
filterManager: {
fieldName: 'myField',

View file

@ -17,9 +17,7 @@
* under the License.
*/
import { SearchSource } from '../legacy_imports';
export const getSearchSourceMock = (esSearchResponse?: any): SearchSource =>
export const getSearchSourceMock = (esSearchResponse?: any) =>
jest.fn().mockImplementation(() => ({
setParent: jest.fn(),
setField: jest.fn(),

View file

@ -21,8 +21,6 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nStart } from 'kibana/public';
import { SearchSource } from './legacy_imports';
import { InputControlVis } from './components/vis/input_control_vis';
import { getControlFactory } from './control/control_factory';
import { getLineageMap } from './lineage';
@ -102,7 +100,8 @@ export const createInputControlVisController = (deps: InputControlVisDependencie
const controlFactoryPromises = controlParamsList.map(controlParams => {
const factory = getControlFactory(controlParams);
return factory(controlParams, this.visParams?.useTimeFilter, SearchSource, deps);
return factory(controlParams, this.visParams?.useTimeFilter, deps);
});
const controls = await Promise.all<RangeControl | ListControl>(controlFactoryPromises);

View file

@ -42,6 +42,7 @@ import {
DocViewerComponent,
SavedSearch,
} from '../../../../../plugins/discover/public';
import { SavedObjectKibanaServices } from '../../../../../plugins/saved_objects/public';
export interface DiscoverServices {
addBasePath: (path: string) => string;
@ -65,12 +66,13 @@ export interface DiscoverServices {
uiSettings: IUiSettingsClient;
visualizations: VisualizationsStart;
}
export async function buildServices(
core: CoreStart,
plugins: DiscoverStartPlugins,
getHistory: () => History
): Promise<DiscoverServices> {
const services = {
const services: SavedObjectKibanaServices = {
savedObjectsClient: core.savedObjects.client,
indexPatterns: plugins.data.indexPatterns,
search: plugins.data.search,

View file

@ -77,7 +77,6 @@ export {
IndexPattern,
indexPatterns,
IFieldType,
SearchSource,
ISearchSource,
EsQuerySortValue,
SortDirection,

View file

@ -19,7 +19,6 @@
import sinon from 'sinon';
import moment from 'moment';
import { SearchSource } from '../../../../../../../../../plugins/data/public';
export function createIndexPatternsStub() {
return {
@ -46,17 +45,15 @@ export function createSearchSourceStub(hits, timeField) {
}),
};
searchSourceStub.setParent = sinon
.stub(SearchSource.prototype, 'setParent')
.returns(searchSourceStub);
searchSourceStub.setField = sinon
.stub(SearchSource.prototype, 'setField')
.returns(searchSourceStub);
searchSourceStub.getField = sinon.stub(SearchSource.prototype, 'getField').callsFake(key => {
searchSourceStub.setParent = sinon.spy(() => searchSourceStub);
searchSourceStub.setField = sinon.spy(() => searchSourceStub);
searchSourceStub.getField = sinon.spy(key => {
const previousSetCall = searchSourceStub.setField.withArgs(key).lastCall;
return previousSetCall ? previousSetCall.args[1] : null;
});
searchSourceStub.fetch = sinon.stub(SearchSource.prototype, 'fetch').callsFake(() =>
searchSourceStub.fetch = sinon.spy(() =>
Promise.resolve({
hits: {
hits: searchSourceStub._stubHits,
@ -65,13 +62,6 @@ export function createSearchSourceStub(hits, timeField) {
})
);
searchSourceStub._restore = () => {
searchSourceStub.setParent.restore();
searchSourceStub.setField.restore();
searchSourceStub.getField.restore();
searchSourceStub.fetch.restore();
};
return searchSourceStub;
}
@ -81,8 +71,7 @@ export function createSearchSourceStub(hits, timeField) {
export function createContextSearchSourceStub(hits, timeField = '@timestamp') {
const searchSourceStub = createSearchSourceStub(hits, timeField);
searchSourceStub.fetch.restore();
searchSourceStub.fetch = sinon.stub(SearchSource.prototype, 'fetch').callsFake(() => {
searchSourceStub.fetch = sinon.spy(() => {
const timeField = searchSourceStub._stubTimeField;
const lastQuery = searchSourceStub.setField.withArgs('query').lastCall.args[1];
const timeRange = lastQuery.query.constant_score.filter.range[timeField];
@ -99,6 +88,7 @@ export function createContextSearchSourceStub(hits, timeField = '@timestamp') {
moment(hit[timeField]).isSameOrBefore(timeRange.lte)
)
.sort(sortFunction);
return Promise.resolve({
hits: {
hits: filteredHits,

View file

@ -31,10 +31,6 @@ describe('context app', function() {
fetchAnchor = fetchAnchorProvider(createIndexPatternsStub(), searchSourceStub);
});
afterEach(() => {
searchSourceStub._restore();
});
it('should use the `fetch` method of the SearchSource', function() {
return fetchAnchor('INDEX_PATTERN_ID', 'id', [
{ '@timestamp': 'desc' },

View file

@ -21,6 +21,7 @@ import moment from 'moment';
import * as _ from 'lodash';
import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs';
import { fetchContextProvider } from './context';
import { setServices } from '../../../../kibana_services';
const MS_PER_DAY = 24 * 60 * 60 * 1000;
const ANCHOR_TIMESTAMP = new Date(MS_PER_DAY).toJSON();
@ -31,10 +32,21 @@ const ANCHOR_TIMESTAMP_3000 = new Date(MS_PER_DAY * 3000).toJSON();
describe('context app', function() {
describe('function fetchPredecessors', function() {
let fetchPredecessors;
let searchSourceStub;
let mockSearchSource;
beforeEach(() => {
searchSourceStub = createContextSearchSourceStub([], '@timestamp', MS_PER_DAY * 8);
mockSearchSource = createContextSearchSourceStub([], '@timestamp', MS_PER_DAY * 8);
setServices({
data: {
search: {
searchSource: {
create: jest.fn().mockImplementation(() => mockSearchSource),
},
},
},
});
fetchPredecessors = (
indexPatternId,
timeField,
@ -65,17 +77,13 @@ describe('context app', function() {
};
});
afterEach(() => {
searchSourceStub._restore();
});
it('should perform exactly one query when enough hits are returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 3000 + 2),
searchSourceStub._createStubHit(MS_PER_DAY * 3000 + 1),
searchSourceStub._createStubHit(MS_PER_DAY * 3000),
searchSourceStub._createStubHit(MS_PER_DAY * 2000),
searchSourceStub._createStubHit(MS_PER_DAY * 1000),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 2),
mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 1),
mockSearchSource._createStubHit(MS_PER_DAY * 3000),
mockSearchSource._createStubHit(MS_PER_DAY * 2000),
mockSearchSource._createStubHit(MS_PER_DAY * 1000),
];
return fetchPredecessors(
@ -89,18 +97,18 @@ describe('context app', function() {
3,
[]
).then(hits => {
expect(searchSourceStub.fetch.calledOnce).toBe(true);
expect(hits).toEqual(searchSourceStub._stubHits.slice(0, 3));
expect(mockSearchSource.fetch.calledOnce).toBe(true);
expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3));
});
});
it('should perform multiple queries with the last being unrestricted when too few hits are returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 3010),
searchSourceStub._createStubHit(MS_PER_DAY * 3002),
searchSourceStub._createStubHit(MS_PER_DAY * 3000),
searchSourceStub._createStubHit(MS_PER_DAY * 2998),
searchSourceStub._createStubHit(MS_PER_DAY * 2990),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 3010),
mockSearchSource._createStubHit(MS_PER_DAY * 3002),
mockSearchSource._createStubHit(MS_PER_DAY * 3000),
mockSearchSource._createStubHit(MS_PER_DAY * 2998),
mockSearchSource._createStubHit(MS_PER_DAY * 2990),
];
return fetchPredecessors(
@ -114,7 +122,7 @@ describe('context app', function() {
6,
[]
).then(hits => {
const intervals = searchSourceStub.setField.args
const intervals = mockSearchSource.setField.args
.filter(([property]) => property === 'query')
.map(([, { query }]) =>
_.get(query, ['constant_score', 'filter', 'range', '@timestamp'])
@ -129,16 +137,16 @@ describe('context app', function() {
expect(Object.keys(_.last(intervals))).toEqual(['format', 'gte']);
expect(intervals.length).toBeGreaterThan(1);
expect(hits).toEqual(searchSourceStub._stubHits.slice(0, 3));
expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3));
});
});
it('should perform multiple queries until the expected hit count is returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 1700),
searchSourceStub._createStubHit(MS_PER_DAY * 1200),
searchSourceStub._createStubHit(MS_PER_DAY * 1100),
searchSourceStub._createStubHit(MS_PER_DAY * 1000),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 1700),
mockSearchSource._createStubHit(MS_PER_DAY * 1200),
mockSearchSource._createStubHit(MS_PER_DAY * 1100),
mockSearchSource._createStubHit(MS_PER_DAY * 1000),
];
return fetchPredecessors(
@ -152,7 +160,7 @@ describe('context app', function() {
3,
[]
).then(hits => {
const intervals = searchSourceStub.setField.args
const intervals = mockSearchSource.setField.args
.filter(([property]) => property === 'query')
.map(([, { query }]) =>
_.get(query, ['constant_score', 'filter', 'range', '@timestamp'])
@ -163,7 +171,7 @@ describe('context app', function() {
// should have stopped before reaching MS_PER_DAY * 1700
expect(moment(_.last(intervals).lte).valueOf()).toBeLessThan(MS_PER_DAY * 1700);
expect(intervals.length).toBeGreaterThan(1);
expect(hits).toEqual(searchSourceStub._stubHits.slice(-3));
expect(hits).toEqual(mockSearchSource._stubHits.slice(-3));
});
});
@ -195,7 +203,7 @@ describe('context app', function() {
3,
[]
).then(() => {
const setParentSpy = searchSourceStub.setParent;
const setParentSpy = mockSearchSource.setParent;
expect(setParentSpy.alwaysCalledWith(undefined)).toBe(true);
expect(setParentSpy.called).toBe(true);
});
@ -214,7 +222,7 @@ describe('context app', function() {
[]
).then(() => {
expect(
searchSourceStub.setField.calledWith('sort', [{ '@timestamp': 'asc' }, { _doc: 'asc' }])
mockSearchSource.setField.calledWith('sort', [{ '@timestamp': 'asc' }, { _doc: 'asc' }])
).toBe(true);
});
});

View file

@ -21,6 +21,7 @@ import moment from 'moment';
import * as _ from 'lodash';
import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs';
import { setServices } from '../../../../kibana_services';
import { fetchContextProvider } from './context';
@ -32,10 +33,20 @@ const ANCHOR_TIMESTAMP_3000 = new Date(MS_PER_DAY * 3000).toJSON();
describe('context app', function() {
describe('function fetchSuccessors', function() {
let fetchSuccessors;
let searchSourceStub;
let mockSearchSource;
beforeEach(() => {
searchSourceStub = createContextSearchSourceStub([], '@timestamp');
mockSearchSource = createContextSearchSourceStub([], '@timestamp');
setServices({
data: {
search: {
searchSource: {
create: jest.fn().mockImplementation(() => mockSearchSource),
},
},
},
});
fetchSuccessors = (
indexPatternId,
@ -67,17 +78,13 @@ describe('context app', function() {
};
});
afterEach(() => {
searchSourceStub._restore();
});
it('should perform exactly one query when enough hits are returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 5000),
searchSourceStub._createStubHit(MS_PER_DAY * 4000),
searchSourceStub._createStubHit(MS_PER_DAY * 3000),
searchSourceStub._createStubHit(MS_PER_DAY * 3000 - 1),
searchSourceStub._createStubHit(MS_PER_DAY * 3000 - 2),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 5000),
mockSearchSource._createStubHit(MS_PER_DAY * 4000),
mockSearchSource._createStubHit(MS_PER_DAY * 3000),
mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 1),
mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 2),
];
return fetchSuccessors(
@ -91,18 +98,18 @@ describe('context app', function() {
3,
[]
).then(hits => {
expect(searchSourceStub.fetch.calledOnce).toBe(true);
expect(hits).toEqual(searchSourceStub._stubHits.slice(-3));
expect(mockSearchSource.fetch.calledOnce).toBe(true);
expect(hits).toEqual(mockSearchSource._stubHits.slice(-3));
});
});
it('should perform multiple queries with the last being unrestricted when too few hits are returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 3010),
searchSourceStub._createStubHit(MS_PER_DAY * 3002),
searchSourceStub._createStubHit(MS_PER_DAY * 3000),
searchSourceStub._createStubHit(MS_PER_DAY * 2998),
searchSourceStub._createStubHit(MS_PER_DAY * 2990),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 3010),
mockSearchSource._createStubHit(MS_PER_DAY * 3002),
mockSearchSource._createStubHit(MS_PER_DAY * 3000),
mockSearchSource._createStubHit(MS_PER_DAY * 2998),
mockSearchSource._createStubHit(MS_PER_DAY * 2990),
];
return fetchSuccessors(
@ -116,7 +123,7 @@ describe('context app', function() {
6,
[]
).then(hits => {
const intervals = searchSourceStub.setField.args
const intervals = mockSearchSource.setField.args
.filter(([property]) => property === 'query')
.map(([, { query }]) =>
_.get(query, ['constant_score', 'filter', 'range', '@timestamp'])
@ -131,18 +138,18 @@ describe('context app', function() {
expect(Object.keys(_.last(intervals))).toEqual(['format', 'lte']);
expect(intervals.length).toBeGreaterThan(1);
expect(hits).toEqual(searchSourceStub._stubHits.slice(-3));
expect(hits).toEqual(mockSearchSource._stubHits.slice(-3));
});
});
it('should perform multiple queries until the expected hit count is returned', function() {
searchSourceStub._stubHits = [
searchSourceStub._createStubHit(MS_PER_DAY * 3000),
searchSourceStub._createStubHit(MS_PER_DAY * 3000 - 1),
searchSourceStub._createStubHit(MS_PER_DAY * 3000 - 2),
searchSourceStub._createStubHit(MS_PER_DAY * 2800),
searchSourceStub._createStubHit(MS_PER_DAY * 2200),
searchSourceStub._createStubHit(MS_PER_DAY * 1000),
mockSearchSource._stubHits = [
mockSearchSource._createStubHit(MS_PER_DAY * 3000),
mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 1),
mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 2),
mockSearchSource._createStubHit(MS_PER_DAY * 2800),
mockSearchSource._createStubHit(MS_PER_DAY * 2200),
mockSearchSource._createStubHit(MS_PER_DAY * 1000),
];
return fetchSuccessors(
@ -156,7 +163,7 @@ describe('context app', function() {
4,
[]
).then(hits => {
const intervals = searchSourceStub.setField.args
const intervals = mockSearchSource.setField.args
.filter(([property]) => property === 'query')
.map(([, { query }]) =>
_.get(query, ['constant_score', 'filter', 'range', '@timestamp'])
@ -168,7 +175,7 @@ describe('context app', function() {
expect(moment(_.last(intervals).gte).valueOf()).toBeGreaterThan(MS_PER_DAY * 2200);
expect(intervals.length).toBeGreaterThan(1);
expect(hits).toEqual(searchSourceStub._stubHits.slice(0, 4));
expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 4));
});
});
@ -200,7 +207,7 @@ describe('context app', function() {
3,
[]
).then(() => {
const setParentSpy = searchSourceStub.setParent;
const setParentSpy = mockSearchSource.setParent;
expect(setParentSpy.alwaysCalledWith(undefined)).toBe(true);
expect(setParentSpy.called).toBe(true);
});
@ -219,7 +226,7 @@ describe('context app', function() {
[]
).then(() => {
expect(
searchSourceStub.setField.calledWith('sort', [{ '@timestamp': 'desc' }, { _doc: 'desc' }])
mockSearchSource.setField.calledWith('sort', [{ '@timestamp': 'desc' }, { _doc: 'desc' }])
).toBe(true);
});
});

View file

@ -27,8 +27,8 @@ import {
Filter,
IndexPatternsContract,
IndexPattern,
SearchSource,
} from '../../../../../../../../../plugins/data/public';
import { getServices } from '../../../../kibana_services';
export type SurrDocType = 'successors' | 'predecessors';
export interface EsHitRecord {
@ -115,7 +115,10 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract) {
}
async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) {
return new SearchSource()
const { data } = getServices();
return data.search.searchSource
.create()
.setParent(undefined)
.setField('index', indexPattern)
.setField('filter', filters);

View file

@ -20,7 +20,7 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { getServices, SearchSource } from '../../../../kibana_services';
import { getServices } from '../../../../kibana_services';
import { fetchAnchorProvider } from '../api/anchor';
import { fetchContextProvider } from '../api/context';
@ -29,8 +29,8 @@ import { FAILURE_REASONS, LOADING_STATUS } from './constants';
import { MarkdownSimple } from '../../../../../../../../../plugins/kibana_react/public';
export function QueryActionsProvider(Promise) {
const { filterManager, indexPatterns } = getServices();
const fetchAnchor = fetchAnchorProvider(indexPatterns, new SearchSource());
const { filterManager, indexPatterns, data } = getServices();
const fetchAnchor = fetchAnchorProvider(indexPatterns, data.search.searchSource.create());
const { fetchSurroundingDocs } = fetchContextProvider(indexPatterns);
const { setPredecessorCount, setQueryParameters, setSuccessorCount } = getQueryParameterActions(
filterManager,

View file

@ -17,17 +17,19 @@
* under the License.
*/
import { searchSourceMock } from '../../../../data/public/mocks';
import { dataPluginMock } from '../../../../data/public/mocks';
import { SavedObjectDashboard } from '../../saved_dashboards';
export function getSavedDashboardMock(
config?: Partial<SavedObjectDashboard>
): SavedObjectDashboard {
const searchSource = dataPluginMock.createStartContract();
return {
id: '123',
title: 'my dashboard',
panelsJSON: '[]',
searchSource: searchSourceMock,
searchSource: searchSource.search.searchSource.create(),
copyOnSave: false,
timeRestore: false,
timeTo: 'now',

View file

@ -365,8 +365,6 @@ export {
SearchResponse,
SearchError,
ISearchSource,
SearchSource,
createSearchSource,
SearchSourceFields,
EsQuerySortValue,
SortDirection,

View file

@ -68,7 +68,7 @@ const createStartContract = (): Start => {
};
};
export { searchSourceMock } from './search/mocks';
export { createSearchSourceMock } from './search/mocks';
export { getCalculateAutoTimeExpression } from './search/aggs';
export const dataPluginMock = {

View file

@ -24,13 +24,13 @@ import {
Plugin,
PackageInfo,
} from 'src/core/public';
import { Storage, IStorageWrapper } from '../../kibana_utils/public';
import { Storage, IStorageWrapper, createStartServicesGetter } from '../../kibana_utils/public';
import {
DataPublicPluginSetup,
DataPublicPluginStart,
DataSetupDependencies,
DataStartDependencies,
GetInternalStartServicesFn,
InternalStartServices,
} from './types';
import { AutocompleteService } from './autocomplete';
import { SearchService } from './search/search_service';
@ -48,8 +48,6 @@ import {
setQueryService,
setSearchService,
setUiSettings,
getFieldFormats,
getNotifications,
} from './services';
import { createSearchBar } from './ui/search_bar/create_search_bar';
import { esaggs } from './search/expressions';
@ -104,15 +102,21 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
core: CoreSetup,
{ expressions, uiActions }: DataSetupDependencies
): DataPublicPluginSetup {
setInjectedMetadata(core.injectedMetadata);
const startServices = createStartServicesGetter(core.getStartServices);
const getInternalStartServices = (): InternalStartServices => {
const { core: coreStart, self }: any = startServices();
return {
fieldFormats: self.fieldFormats,
notifications: coreStart.notifications,
uiSettings: coreStart.uiSettings,
searchService: self.search,
injectedMetadata: coreStart.injectedMetadata,
};
};
expressions.registerFunction(esaggs);
const getInternalStartServices: GetInternalStartServicesFn = () => ({
fieldFormats: getFieldFormats(),
notifications: getNotifications(),
});
const queryService = this.queryService.setup({
uiSettings: core.uiSettings,
storage: this.storage,
@ -150,6 +154,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
setNotifications(notifications);
setOverlays(overlays);
setUiSettings(uiSettings);
setInjectedMetadata(core.injectedMetadata);
const fieldFormats = this.fieldFormatsService.start();
setFieldFormats(fieldFormats);
@ -160,7 +165,10 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
const query = this.queryService.start(savedObjects);
setQueryService(query);
const search = this.searchService.start(core, { fieldFormats, indexPatterns });
const search = this.searchService.start(core, {
indexPatterns,
fieldFormats,
});
setSearchService(search);
uiActions.attachAction(APPLY_FILTER_TRIGGER, uiActions.getAction(ACTION_GLOBAL_APPLY_FILTER));

View file

@ -12,8 +12,8 @@ import { Assign } from '@kbn/utility-types';
import { Breadcrumb } from '@elastic/eui';
import { Component } from 'react';
import { CoreSetup } from 'src/core/public';
import { CoreStart } from 'src/core/public';
import { CoreStart as CoreStart_2 } from 'kibana/public';
import { CoreStart } from 'kibana/public';
import { CoreStart as CoreStart_2 } from 'src/core/public';
import { EuiButtonEmptyProps } from '@elastic/eui';
import { EuiComboBoxProps } from '@elastic/eui';
import { EuiConfirmModalProps } from '@elastic/eui';
@ -210,9 +210,6 @@ export const connectToQueryState: <S extends QueryState>({ timefilter: { timefil
// @public (undocumented)
export const createSavedQueryService: (savedObjectsClient: Pick<import("../../../../../core/public").SavedObjectsClient, "update" | "find" | "get" | "delete" | "create" | "bulkCreate" | "bulkGet" | "bulkUpdate">) => SavedQueryService;
// @public
export const createSearchSource: (indexPatterns: Pick<import("../../index_patterns/index_patterns").IndexPatternsService, "get" | "clearCache" | "getFieldsForTimePattern" | "getFieldsForWildcard" | "getIds" | "getTitles" | "getFields" | "getCache" | "getDefault" | "make">) => (searchSourceJson: string, references: SavedObjectReference[]) => Promise<SearchSource>;
// Warning: (ae-missing-release-tag) "CustomFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@ -637,21 +634,21 @@ export type IAggType = AggType;
// Warning: (ae-missing-release-tag) "IDataPluginServices" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface IDataPluginServices extends Partial<CoreStart> {
export interface IDataPluginServices extends Partial<CoreStart_2> {
// (undocumented)
appName: string;
// (undocumented)
data: DataPublicPluginStart;
// (undocumented)
http: CoreStart['http'];
http: CoreStart_2['http'];
// (undocumented)
notifications: CoreStart['notifications'];
notifications: CoreStart_2['notifications'];
// (undocumented)
savedObjects: CoreStart['savedObjects'];
savedObjects: CoreStart_2['savedObjects'];
// (undocumented)
storage: IStorageWrapper;
// (undocumented)
uiSettings: CoreStart['uiSettings'];
uiSettings: CoreStart_2['uiSettings'];
}
// Warning: (ae-missing-release-tag) "IEsSearchRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@ -1099,7 +1096,7 @@ export type ISearch<T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY> =
// @public (undocumented)
export interface ISearchContext {
// (undocumented)
core: CoreStart_2;
core: CoreStart;
// (undocumented)
getSearchStrategy: <T extends TStrategyTypes>(name: T) => TSearchStrategyProvider<T>;
}
@ -1117,7 +1114,7 @@ export interface ISearchOptions {
signal?: AbortSignal;
}
// Warning: (ae-missing-release-tag) "ISearchSource" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-forgotten-export) The symbol "SearchSource" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export type ISearchSource = Pick<SearchSource, keyof SearchSource>;
@ -1312,7 +1309,7 @@ export class Plugin implements Plugin_2<DataPublicPluginSetup, DataPublicPluginS
// Warning: (ae-forgotten-export) The symbol "DataStartDependencies" needs to be exported by the entry point index.d.ts
//
// (undocumented)
start(core: CoreStart, { uiActions }: DataStartDependencies): DataPublicPluginStart;
start(core: CoreStart_2, { uiActions }: DataStartDependencies): DataPublicPluginStart;
// (undocumented)
stop(): void;
}
@ -1631,61 +1628,6 @@ export type SearchRequest = any;
// @public (undocumented)
export type SearchResponse = any;
// Warning: (ae-missing-release-tag) "SearchSource" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class SearchSource {
constructor(fields?: SearchSourceFields);
// (undocumented)
create(): SearchSource;
// (undocumented)
createChild(options?: {}): SearchSource;
// (undocumented)
createCopy(): SearchSource;
destroy(): void;
fetch(options?: FetchOptions): Promise<any>;
getField<K extends keyof SearchSourceFields>(field: K, recurse?: boolean): SearchSourceFields[K];
// (undocumented)
getFields(): {
type?: string | undefined;
query?: import("../..").Query | undefined;
filter?: Filter | Filter[] | (() => Filter | Filter[] | undefined) | undefined;
sort?: Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric> | Record<string, import("./types").SortDirection | import("./types").SortDirectionNumeric>[] | undefined;
highlight?: any;
highlightAll?: boolean | undefined;
aggs?: any;
from?: number | undefined;
size?: number | undefined;
source?: string | boolean | string[] | undefined;
version?: boolean | undefined;
fields?: string | boolean | string[] | undefined;
index?: import("../..").IndexPattern | undefined;
searchAfter?: import("./types").EsQuerySearchAfter | undefined;
timeout?: string | undefined;
terminate_after?: number | undefined;
};
// (undocumented)
getId(): string;
getOwnField<K extends keyof SearchSourceFields>(field: K): SearchSourceFields[K];
getParent(): SearchSource | undefined;
// (undocumented)
getSearchRequestBody(): Promise<any>;
// (undocumented)
history: SearchRequest[];
onRequestStart(handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise<unknown>): void;
serialize(): {
searchSourceJSON: string;
references: SavedObjectReference[];
};
// (undocumented)
setField<K extends keyof SearchSourceFields>(field: K, value: SearchSourceFields[K]): this;
// (undocumented)
setFields(newFields: SearchSourceFields): this;
// Warning: (ae-forgotten-export) The symbol "SearchSourceOptions" needs to be exported by the entry point index.d.ts
setParent(parent?: ISearchSource, options?: SearchSourceOptions): this;
setPreferredSearchStrategyId(searchStrategyId: string): void;
}
// Warning: (ae-missing-release-tag) "SearchSourceFields" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@ -1876,21 +1818,21 @@ export type TSearchStrategyProvider<T extends TStrategyTypes> = (context: ISearc
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:383:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:381:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:381:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:381:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:381:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:386:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts

View file

@ -25,13 +25,15 @@ import { AggParamType } from '../aggs/param_types/agg';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../src/core/public/mocks';
import { AggTypeDependencies } from './agg_type';
import { InternalStartServices } from '../../types';
describe('AggParams class', () => {
const aggTypesDependencies: AggTypeDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
describe('constructor args', () => {

View file

@ -21,19 +21,21 @@ import { AggType, AggTypeConfig, AggTypeDependencies } from './agg_type';
import { IAggConfig } from './agg_config';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../types';
describe('AggType Class', () => {
let dependencies: AggTypeDependencies;
beforeEach(() => {
dependencies = {
getInternalStartServices: () => ({
fieldFormats: {
...fieldFormatsServiceMock.createStartContract(),
getDefaultInstance: jest.fn(() => 'default') as any,
},
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: {
...fieldFormatsServiceMock.createStartContract(),
getDefaultInstance: jest.fn(() => 'default') as any,
},
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -32,6 +32,7 @@ import { RangeFilter } from '../../../../../common';
import { coreMock, notificationServiceMock } from '../../../../../../../core/public/mocks';
import { queryServiceMock } from '../../../../query/mocks';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('date_histogram', () => {
@ -47,10 +48,11 @@ describe('AggConfig Filters', () => {
aggTypesDependencies = {
uiSettings,
query: queryServiceMock.createSetupContract(),
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
mockDataServices();

View file

@ -28,6 +28,7 @@ import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../bucket_agg_type';
import { coreMock, notificationServiceMock } from '../../../../../../../core/public/mocks';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('Date range', () => {
@ -38,10 +39,11 @@ describe('AggConfig Filters', () => {
aggTypesDependencies = {
uiSettings,
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -24,6 +24,7 @@ import { mockAggTypesRegistry } from '../../test_helpers';
import { IBucketAggConfig } from '../bucket_agg_type';
import { coreMock, notificationServiceMock } from '../../../../../../../core/public/mocks';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('filters', () => {
@ -34,10 +35,11 @@ describe('AggConfig Filters', () => {
aggTypesDependencies = {
uiSettings,
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -26,16 +26,18 @@ import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../bucket_agg_type';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../core/public/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('IP range', () => {
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const typesRegistry = mockAggTypesRegistry([
getIpRangeBucketAgg({
getInternalStartServices: () => ({
fieldFormats,
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats,
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
}),
]);
const getAggConfigs = (aggs: CreateAggConfigParams[]) => {

View file

@ -26,6 +26,7 @@ import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../bucket_agg_type';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../core/public/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('range', () => {
@ -33,10 +34,11 @@ describe('AggConfig Filters', () => {
beforeEach(() => {
aggTypesDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
mockDataServices();

View file

@ -27,6 +27,7 @@ import { Filter, ExistsFilter } from '../../../../../common';
import { RangeBucketAggDependencies } from '../range';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../core/public/mocks';
import { InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('terms', () => {
@ -34,10 +35,11 @@ describe('AggConfig Filters', () => {
beforeEach(() => {
aggTypesDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -23,6 +23,7 @@ import { AggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { InternalStartServices } from '../../../types';
describe('date_range params', () => {
let aggTypesDependencies: DateRangeBucketAggDependencies;
@ -32,10 +33,11 @@ describe('date_range params', () => {
aggTypesDependencies = {
uiSettings,
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -24,6 +24,7 @@ import { BUCKET_TYPES } from './bucket_agg_types';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { BucketAggType, IBucketAggConfig } from './bucket_agg_type';
import { InternalStartServices } from '../../../types';
describe('Geohash Agg', () => {
let aggTypesDependencies: GeoHashBucketAggDependencies;
@ -31,10 +32,11 @@ describe('Geohash Agg', () => {
beforeEach(() => {
aggTypesDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
geoHashBucketAgg = getGeoHashBucketAgg(aggTypesDependencies);

View file

@ -29,6 +29,7 @@ import {
} from './histogram';
import { BucketAggType } from './bucket_agg_type';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { InternalStartServices } from '../../../types';
describe('Histogram Agg', () => {
let aggTypesDependencies: HistogramBucketAggDependencies;
@ -38,10 +39,11 @@ describe('Histogram Agg', () => {
aggTypesDependencies = {
uiSettings,
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -24,6 +24,7 @@ import { BUCKET_TYPES } from './bucket_agg_types';
import { FieldFormatsGetConfigFn, NumberFormat } from '../../../../common';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
const buckets = [
{
@ -50,10 +51,11 @@ describe('Range Agg', () => {
beforeEach(() => {
aggTypesDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
mockDataServices();

View file

@ -26,6 +26,7 @@ import {
} from './significant_terms';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('Significant Terms Agg', () => {
describe('order agg editor UI', () => {
@ -34,10 +35,11 @@ describe('Significant Terms Agg', () => {
beforeEach(() => {
aggTypesDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
});

View file

@ -24,6 +24,7 @@ import { isBucketAggType } from './buckets/bucket_agg_type';
import { isMetricAggType } from './metrics/metric_agg_type';
import { QueryStart } from '../../query';
import { FieldFormatsStart } from '../../field_formats';
import { InternalStartServices } from '../../types';
describe('AggTypesComponent', () => {
const coreSetup = coreMock.createSetup();
@ -32,10 +33,11 @@ describe('AggTypesComponent', () => {
const aggTypes = getAggTypes({
uiSettings: coreSetup.uiSettings,
query: {} as QueryStart,
getInternalStartServices: () => ({
notifications: coreStart.notifications,
fieldFormats: {} as FieldFormatsStart,
}),
getInternalStartServices: () =>
(({
notifications: coreStart.notifications,
fieldFormats: {} as FieldFormatsStart,
} as unknown) as InternalStartServices),
});
const { buckets, metrics } = aggTypes;

View file

@ -23,14 +23,16 @@ import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('AggTypeMetricMedianProvider class', () => {
let aggConfigs: IAggConfigs;
const aggTypesDependencies: MedianMetricAggDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
beforeEach(() => {

View file

@ -25,14 +25,15 @@ import { AggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { GetInternalStartServicesFn } from '../../../types';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../types';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
describe('parent pipeline aggs', function() {
const getInternalStartServices: GetInternalStartServicesFn = () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
});
const getInternalStartServices: GetInternalStartServicesFn = () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices);
const typesRegistry = mockAggTypesRegistry();

View file

@ -27,14 +27,16 @@ import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('AggTypesMetricsPercentileRanksProvider class', function() {
let aggConfigs: IAggConfigs;
const aggTypesDependencies: PercentileRanksMetricAggDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
beforeEach(() => {

View file

@ -27,14 +27,16 @@ import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('AggTypesMetricsPercentilesProvider class', () => {
let aggConfigs: IAggConfigs;
const aggTypesDependencies: PercentilesMetricAggDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
beforeEach(() => {

View file

@ -26,14 +26,15 @@ import { AggConfigs } from '../agg_configs';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
import { mockAggTypesRegistry } from '../test_helpers';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { GetInternalStartServicesFn } from '../../../types';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../types';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
describe('sibling pipeline aggs', () => {
const getInternalStartServices: GetInternalStartServicesFn = () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
});
const getInternalStartServices: GetInternalStartServicesFn = () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices);
const typesRegistry = mockAggTypesRegistry();

View file

@ -27,13 +27,15 @@ import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('AggTypeMetricStandardDeviationProvider class', () => {
const aggTypesDependencies: StdDeviationMetricAggDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
const typesRegistry = mockAggTypesRegistry([getStdDeviationMetricAgg(aggTypesDependencies)]);
const getAggConfigs = (customLabel?: string) => {

View file

@ -25,15 +25,17 @@ import { IMetricAggConfig } from './metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../common';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('Top hit metric', () => {
let aggDsl: Record<string, any>;
let aggConfig: IMetricAggConfig;
const aggTypesDependencies: TopHitMetricAggDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
const init = ({

View file

@ -23,13 +23,15 @@ import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../common';
import { IAggConfig } from '../agg_config';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
describe('Field', () => {
const fieldParamTypeDependencies: FieldParamTypeDependencies = {
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
const indexPattern = {

View file

@ -17,7 +17,6 @@
* under the License.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { coreMock, notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry';
import { getAggTypes } from '../agg_types';
@ -25,6 +24,7 @@ import { BucketAggType } from '../buckets/bucket_agg_type';
import { MetricAggType } from '../metrics/metric_agg_type';
import { queryServiceMock } from '../../../query/mocks';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { InternalStartServices } from '../../../types';
/**
* Testing utility which creates a new instance of AggTypesRegistry,
@ -53,14 +53,19 @@ export function mockAggTypesRegistry<T extends BucketAggType<any> | MetricAggTyp
}
});
} else {
const core = coreMock.createSetup();
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
const aggTypes = getAggTypes({
uiSettings: core.uiSettings,
uiSettings: coreSetup.uiSettings,
query: queryServiceMock.createSetupContract(),
getInternalStartServices: () => ({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
}),
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
uiSettings: coreStart.uiSettings,
injectedMetadata: coreStart.injectedMetadata,
} as unknown) as InternalStartServices),
});
aggTypes.buckets.forEach(type => registrySetup.registerBucket(type));

View file

@ -30,7 +30,7 @@ import { PersistedState } from '../../../../../plugins/visualizations/public';
import { Adapters } from '../../../../../plugins/inspector/public';
import { IAggConfigs } from '../aggs';
import { ISearchSource, SearchSource } from '../search_source';
import { ISearchSource } from '../search_source';
import { tabifyAggResponse } from '../tabify';
import { Filter, Query, serializeFieldFormat, TimeRange } from '../../../common';
import { FilterManager, getTime } from '../../query';
@ -253,7 +253,8 @@ export const esaggs = (): ExpressionFunctionDefinition<typeof name, Input, Argum
const aggs = searchService.aggs.createAggConfigs(indexPattern, aggConfigsState);
// we should move searchSource creation inside courier request handler
const searchSource = new SearchSource();
const searchSource = searchService.searchSource.create();
searchSource.setField('index', indexPattern);
searchSource.setField('size', 0);

View file

@ -18,7 +18,7 @@
*/
import { IUiSettingsClient } from '../../../../../core/public';
import { ISearchStart } from '../types';
import { ISearchStartLegacy } from '../types';
export type SearchRequest = any;
export type SearchResponse = any;
@ -29,7 +29,7 @@ export interface FetchOptions {
}
export interface FetchHandlers {
searchService: ISearchStart;
legacySearchService: ISearchStartLegacy;
config: IUiSettingsClient;
esShardTimeout: number;
}

View file

@ -55,10 +55,10 @@ export {
export {
ISearchSource,
SearchSource,
SearchSourceDependencies,
SearchSourceFields,
EsQuerySortValue,
SortDirection,
createSearchSource,
} from './search_source';
export { SearchInterceptor } from './search_interceptor';

View file

@ -54,7 +54,7 @@ describe('callClient', () => {
test('Passes the additional arguments it is given to the search strategy', () => {
const searchRequests = [{ _searchStrategyId: 0 }];
const args = { searchService: {}, config: {}, esShardTimeout: 0 } as FetchHandlers;
const args = { legacySearchService: {}, config: {}, esShardTimeout: 0 } as FetchHandlers;
callClient(searchRequests, [], args);

View file

@ -62,10 +62,10 @@ describe('defaultSearchStrategy', function() {
},
],
esShardTimeout: 0,
searchService,
legacySearchService: searchService.__LEGACY,
};
es = searchArgs.searchService.__LEGACY.esClient;
es = searchArgs.legacySearchService.esClient;
});
test('does not send max_concurrent_shard_requests by default', async () => {

View file

@ -32,11 +32,11 @@ export const defaultSearchStrategy: SearchStrategyProvider = {
function msearch({
searchRequests,
searchService,
legacySearchService,
config,
esShardTimeout,
}: SearchStrategySearchParams) {
const es = searchService.__LEGACY.esClient;
const es = legacySearchService.esClient;
const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => {
const inlineHeader = {
index: index.title || index,

View file

@ -20,20 +20,19 @@
import { searchAggsSetupMock, searchAggsStartMock } from './aggs/mocks';
import { AggTypeFieldFilters } from './aggs/param_types/filter';
import { ISearchStart } from './types';
import { searchSourceMock, createSearchSourceMock } from './search_source/mocks';
export * from './search_source/mocks';
export const searchSetupMock = {
const searchSetupMock = {
aggs: searchAggsSetupMock(),
registerSearchStrategyContext: jest.fn(),
registerSearchStrategyProvider: jest.fn(),
};
export const searchStartMock: jest.Mocked<ISearchStart> = {
const searchStartMock: jest.Mocked<ISearchStart> = {
aggs: searchAggsStartMock(),
setInterceptor: jest.fn(),
search: jest.fn(),
createSearchSource: jest.fn(),
searchSource: searchSourceMock,
__LEGACY: {
AggConfig: jest.fn() as any,
AggType: jest.fn(),
@ -48,3 +47,5 @@ export const searchStartMock: jest.Mocked<ISearchStart> = {
},
},
};
export { searchSetupMock, searchStartMock, createSearchSourceMock };

View file

@ -20,13 +20,18 @@
import { Plugin, CoreSetup, CoreStart, PackageInfo } from '../../../../core/public';
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
import {
createSearchSourceFromJSON,
SearchSource,
SearchSourceDependencies,
SearchSourceFields,
} from './search_source';
import { ISearchSetup, ISearchStart, TSearchStrategyProvider, TSearchStrategiesMap } from './types';
import { TStrategyTypes } from './strategy_types';
import { getEsClient, LegacyApiCaller } from './legacy';
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
import { esSearchStrategyProvider } from './es_search';
import { IndexPatternsContract } from '../index_patterns/index_patterns';
import { createSearchSource } from './search_source';
import { QuerySetup } from '../query';
import { GetInternalStartServicesFn } from '../types';
import { SearchInterceptor } from './search_interceptor';
@ -43,8 +48,8 @@ import {
parentPipelineAggHelper,
siblingPipelineAggHelper,
} from './aggs';
import { FieldFormatsStart } from '../field_formats';
import { ISearchGeneric } from './i_search';
interface SearchServiceSetupDependencies {
packageInfo: PackageInfo;
@ -52,9 +57,9 @@ interface SearchServiceSetupDependencies {
getInternalStartServices: GetInternalStartServicesFn;
}
interface SearchStartDependencies {
fieldFormats: FieldFormatsStart;
interface SearchServiceStartDependencies {
indexPatterns: IndexPatternsContract;
fieldFormats: FieldFormatsStart;
}
/**
@ -117,10 +122,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
};
}
public start(
core: CoreStart,
{ fieldFormats, indexPatterns }: SearchStartDependencies
): ISearchStart {
public start(core: CoreStart, dependencies: SearchServiceStartDependencies): ISearchStart {
/**
* A global object that intercepts all searches and provides convenience methods for cancelling
* all pending search requests, as well as getting the number of pending search requests.
@ -135,40 +137,54 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
const aggTypesStart = this.aggTypesRegistry.start();
const search: ISearchGeneric = (request, options, strategyName) => {
const strategyProvider = this.getSearchStrategy(strategyName || DEFAULT_SEARCH_STRATEGY);
const searchStrategy = strategyProvider({
core,
getSearchStrategy: this.getSearchStrategy,
});
return this.searchInterceptor.search(searchStrategy.search as any, request, options);
};
const legacySearch = {
esClient: this.esClient!,
AggConfig,
AggType,
aggTypeFieldFilters,
FieldParamType,
MetricAggType,
parentPipelineAggHelper,
siblingPipelineAggHelper,
};
const searchSourceDependencies: SearchSourceDependencies = {
uiSettings: core.uiSettings,
injectedMetadata: core.injectedMetadata,
search,
legacySearch,
};
return {
aggs: {
calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings),
createAggConfigs: (indexPattern, configStates = [], schemas) => {
return new AggConfigs(indexPattern, configStates, {
fieldFormats: dependencies.fieldFormats,
typesRegistry: aggTypesStart,
fieldFormats,
});
},
types: aggTypesStart,
},
search: (request, options, strategyName) => {
const strategyProvider = this.getSearchStrategy(strategyName || DEFAULT_SEARCH_STRATEGY);
const { search } = strategyProvider({
core,
getSearchStrategy: this.getSearchStrategy,
});
return this.searchInterceptor.search(search as any, request, options);
search,
searchSource: {
create: (fields?: SearchSourceFields) => new SearchSource(fields, searchSourceDependencies),
fromJSON: createSearchSourceFromJSON(dependencies.indexPatterns, searchSourceDependencies),
},
setInterceptor: (searchInterceptor: SearchInterceptor) => {
// TODO: should an intercepror have a destroy method?
this.searchInterceptor = searchInterceptor;
},
createSearchSource: createSearchSource(indexPatterns),
__LEGACY: {
esClient: this.esClient!,
AggConfig,
AggType,
aggTypeFieldFilters,
FieldParamType,
MetricAggType,
parentPipelineAggHelper,
siblingPipelineAggHelper,
},
__LEGACY: legacySearch,
};
}

View file

@ -16,30 +16,43 @@
* specific language governing permissions and limitations
* under the License.
*/
import { createSearchSource as createSearchSourceFactory } from './create_search_source';
import { createSearchSourceFromJSON } from './create_search_source';
import { IIndexPattern } from '../../../common/index_patterns';
import { IndexPatternsContract } from '../../index_patterns/index_patterns';
import { Filter } from '../../../common/es_query/filters';
import { coreMock } from '../../../../../core/public/mocks';
import { dataPluginMock } from '../../mocks';
describe('createSearchSource', function() {
let createSearchSource: ReturnType<typeof createSearchSourceFactory>;
describe('createSearchSource', () => {
const indexPatternMock: IIndexPattern = {} as IIndexPattern;
let indexPatternContractMock: jest.Mocked<IndexPatternsContract>;
let dependencies: any;
let createSearchSource: ReturnType<typeof createSearchSourceFromJSON>;
beforeEach(() => {
const core = coreMock.createStart();
const data = dataPluginMock.createStartContract();
dependencies = {
searchService: data.search,
uiSettings: core.uiSettings,
injectedMetadata: core.injectedMetadata,
};
indexPatternContractMock = ({
get: jest.fn().mockReturnValue(Promise.resolve(indexPatternMock)),
} as unknown) as jest.Mocked<IndexPatternsContract>;
createSearchSource = createSearchSourceFactory(indexPatternContractMock);
createSearchSource = createSearchSourceFromJSON(indexPatternContractMock, dependencies);
});
it('should fail if JSON is invalid', () => {
test('should fail if JSON is invalid', () => {
expect(createSearchSource('{', [])).rejects.toThrow();
expect(createSearchSource('0', [])).rejects.toThrow();
expect(createSearchSource('"abcdefg"', [])).rejects.toThrow();
});
it('should set fields', async () => {
test('should set fields', async () => {
const searchSource = await createSearchSource(
JSON.stringify({
highlightAll: true,
@ -50,6 +63,7 @@ describe('createSearchSource', function() {
}),
[]
);
expect(searchSource.getOwnField('highlightAll')).toBe(true);
expect(searchSource.getOwnField('query')).toEqual({
query: '',
@ -57,7 +71,7 @@ describe('createSearchSource', function() {
});
});
it('should resolve referenced index pattern', async () => {
test('should resolve referenced index pattern', async () => {
const searchSource = await createSearchSource(
JSON.stringify({
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
@ -70,11 +84,12 @@ describe('createSearchSource', function() {
},
]
);
expect(indexPatternContractMock.get).toHaveBeenCalledWith('123-456');
expect(searchSource.getOwnField('index')).toBe(indexPatternMock);
});
it('should set filters and resolve referenced index patterns', async () => {
test('should set filters and resolve referenced index patterns', async () => {
const searchSource = await createSearchSource(
JSON.stringify({
filter: [
@ -110,6 +125,7 @@ describe('createSearchSource', function() {
]
);
const filters = searchSource.getOwnField('filter') as Filter[];
expect(filters[0]).toMatchInlineSnapshot(`
Object {
"$state": Object {
@ -135,7 +151,7 @@ describe('createSearchSource', function() {
`);
});
it('should migrate legacy queries on the fly', async () => {
test('should migrate legacy queries on the fly', async () => {
const searchSource = await createSearchSource(
JSON.stringify({
highlightAll: true,
@ -143,6 +159,7 @@ describe('createSearchSource', function() {
}),
[]
);
expect(searchSource.getOwnField('query')).toEqual({
query: 'a:b',
language: 'lucene',

View file

@ -16,11 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
import _ from 'lodash';
import { transform, defaults, isFunction } from 'lodash';
import { SavedObjectReference } from 'kibana/public';
import { migrateLegacyQuery } from '../../../../kibana_legacy/public';
import { InvalidJSONProperty } from '../../../../kibana_utils/public';
import { SearchSource } from './search_source';
import { SearchSourceDependencies, SearchSource, ISearchSource } from './search_source';
import { IndexPatternsContract } from '../../index_patterns/index_patterns';
import { SearchSourceFields } from './types';
@ -38,12 +38,16 @@ import { SearchSourceFields } from './types';
* returned by `serializeSearchSource` and `references`, a list of references including the ones
* returned by `serializeSearchSource`.
*
*
* @public */
export const createSearchSource = (indexPatterns: IndexPatternsContract) => async (
export const createSearchSourceFromJSON = (
indexPatterns: IndexPatternsContract,
searchSourceDependencies: SearchSourceDependencies
) => async (
searchSourceJson: string,
references: SavedObjectReference[]
) => {
const searchSource = new SearchSource();
): Promise<ISearchSource> => {
const searchSource = new SearchSource({}, searchSourceDependencies);
// if we have a searchSource, set its values based on the searchSourceJson field
let searchSourceValues: Record<string, unknown>;
@ -90,17 +94,17 @@ export const createSearchSource = (indexPatterns: IndexPatternsContract) => asyn
}
const searchSourceFields = searchSource.getFields();
const fnProps = _.transform(
const fnProps = transform(
searchSourceFields,
function(dynamic, val, name) {
if (_.isFunction(val) && name) dynamic[name] = val;
if (isFunction(val) && name) dynamic[name] = val;
},
{}
);
// This assignment might hide problems because the type of values passed from the parsed JSON
// might not fit the SearchSourceFields interface.
const newFields: SearchSourceFields = _.defaults(searchSourceValues, fnProps);
const newFields: SearchSourceFields = defaults(searchSourceValues, fnProps);
searchSource.setFields(newFields);
const query = searchSource.getOwnField('query');

View file

@ -17,6 +17,6 @@
* under the License.
*/
export * from './search_source';
export { createSearchSource } from './create_search_source';
export { SearchSource, ISearchSource, SearchSourceDependencies } from './search_source';
export { createSearchSourceFromJSON } from './create_search_source';
export { SortDirection, EsQuerySortValue, SearchSourceFields } from './types';

View file

@ -17,9 +17,15 @@
* under the License.
*/
import { ISearchSource } from './search_source';
import {
injectedMetadataServiceMock,
uiSettingsServiceMock,
} from '../../../../../core/public/mocks';
export const searchSourceMock: MockedKeys<ISearchSource> = {
import { ISearchSource, SearchSource } from './search_source';
import { SearchSourceFields } from './types';
export const searchSourceInstanceMock: MockedKeys<ISearchSource> = {
setPreferredSearchStrategyId: jest.fn(),
setFields: jest.fn().mockReturnThis(),
setField: jest.fn().mockReturnThis(),
@ -39,3 +45,21 @@ export const searchSourceMock: MockedKeys<ISearchSource> = {
history: [],
serialize: jest.fn(),
};
export const searchSourceMock = {
create: jest.fn().mockReturnValue(searchSourceInstanceMock),
fromJSON: jest.fn().mockReturnValue(searchSourceInstanceMock),
};
export const createSearchSourceMock = (fields?: SearchSourceFields) =>
new SearchSource(fields, {
search: jest.fn(),
legacySearch: {
esClient: {
search: jest.fn(),
msearch: jest.fn(),
},
},
uiSettings: uiSettingsServiceMock.createStartContract(),
injectedMetadata: injectedMetadataServiceMock.createStartContract(),
});

View file

@ -16,28 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Observable } from 'rxjs';
import { SearchSource } from './search_source';
import { IndexPattern, SortDirection } from '../..';
import { mockDataServices } from '../aggs/test_helpers';
import { setSearchService } from '../../services';
import { searchStartMock } from '../mocks';
import { fetchSoon } from '../legacy';
import { CoreStart } from 'kibana/public';
import { Observable } from 'rxjs';
// Setup search service mock
searchStartMock.search = jest.fn(() => {
return new Observable(subscriber => {
setTimeout(() => {
subscriber.next({
rawResponse: '',
});
subscriber.complete();
}, 100);
});
}) as any;
setSearchService(searchStartMock);
import { IUiSettingsClient } from '../../../../../core/public';
import { dataPluginMock } from '../../../../data/public/mocks';
import { coreMock } from '../../../../../core/public/mocks';
jest.mock('../legacy', () => ({
fetchSoon: jest.fn().mockResolvedValue({}),
@ -48,48 +33,70 @@ const getComputedFields = () => ({
scriptFields: [],
docvalueFields: [],
});
const mockSource = { excludes: ['foo-*'] };
const mockSource2 = { excludes: ['bar-*'] };
const indexPattern = ({
title: 'foo',
getComputedFields,
getSourceFiltering: () => mockSource,
} as unknown) as IndexPattern;
const indexPattern2 = ({
title: 'foo',
getComputedFields,
getSourceFiltering: () => mockSource2,
} as unknown) as IndexPattern;
describe('SearchSource', function() {
let uiSettingsMock: jest.Mocked<CoreStart['uiSettings']>;
describe('SearchSource', () => {
let mockSearchMethod: any;
let searchSourceDependencies: any;
beforeEach(() => {
const { core } = mockDataServices();
uiSettingsMock = core.uiSettings;
jest.clearAllMocks();
const core = coreMock.createStart();
const data = dataPluginMock.createStartContract();
mockSearchMethod = jest.fn(() => {
return new Observable(subscriber => {
setTimeout(() => {
subscriber.next({
rawResponse: '',
});
subscriber.complete();
}, 100);
});
});
searchSourceDependencies = {
search: mockSearchMethod,
legacySearch: data.search.__LEGACY,
injectedMetadata: core.injectedMetadata,
uiSettings: core.uiSettings,
};
});
describe('#setField()', function() {
it('sets the value for the property', function() {
const searchSource = new SearchSource();
describe('#setField()', () => {
test('sets the value for the property', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('aggs', 5);
expect(searchSource.getField('aggs')).toBe(5);
});
});
describe('#getField()', function() {
it('gets the value for the property', function() {
const searchSource = new SearchSource();
describe('#getField()', () => {
test('gets the value for the property', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('aggs', 5);
expect(searchSource.getField('aggs')).toBe(5);
});
});
describe(`#setField('index')`, function() {
describe('auto-sourceFiltering', function() {
describe('new index pattern assigned', function() {
it('generates a searchSource filter', async function() {
const searchSource = new SearchSource();
describe(`#setField('index')`, () => {
describe('auto-sourceFiltering', () => {
describe('new index pattern assigned', () => {
test('generates a searchSource filter', async () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
expect(searchSource.getField('index')).toBe(undefined);
expect(searchSource.getField('source')).toBe(undefined);
searchSource.setField('index', indexPattern);
@ -98,8 +105,8 @@ describe('SearchSource', function() {
expect(request._source).toBe(mockSource);
});
it('removes created searchSource filter on removal', async function() {
const searchSource = new SearchSource();
test('removes created searchSource filter on removal', async () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('index', indexPattern);
searchSource.setField('index', undefined);
const request = await searchSource.getSearchRequestBody();
@ -107,9 +114,9 @@ describe('SearchSource', function() {
});
});
describe('new index pattern assigned over another', function() {
it('replaces searchSource filter with new', async function() {
const searchSource = new SearchSource();
describe('new index pattern assigned over another', () => {
test('replaces searchSource filter with new', async () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('index', indexPattern);
searchSource.setField('index', indexPattern2);
expect(searchSource.getField('index')).toBe(indexPattern2);
@ -117,8 +124,8 @@ describe('SearchSource', function() {
expect(request._source).toBe(mockSource2);
});
it('removes created searchSource filter on removal', async function() {
const searchSource = new SearchSource();
test('removes created searchSource filter on removal', async () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('index', indexPattern);
searchSource.setField('index', indexPattern2);
searchSource.setField('index', undefined);
@ -130,8 +137,8 @@ describe('SearchSource', function() {
});
describe('#onRequestStart()', () => {
it('should be called when starting a request', async () => {
const searchSource = new SearchSource({ index: indexPattern });
test('should be called when starting a request', async () => {
const searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies);
const fn = jest.fn();
searchSource.onRequestStart(fn);
const options = {};
@ -139,9 +146,9 @@ describe('SearchSource', function() {
expect(fn).toBeCalledWith(searchSource, options);
});
it('should not be called on parent searchSource', async () => {
const parent = new SearchSource();
const searchSource = new SearchSource({ index: indexPattern });
test('should not be called on parent searchSource', async () => {
const parent = new SearchSource({}, searchSourceDependencies);
const searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies);
const fn = jest.fn();
searchSource.onRequestStart(fn);
@ -154,9 +161,12 @@ describe('SearchSource', function() {
expect(parentFn).not.toBeCalled();
});
it('should be called on parent searchSource if callParentStartHandlers is true', async () => {
const parent = new SearchSource();
const searchSource = new SearchSource({ index: indexPattern }).setParent(parent, {
test('should be called on parent searchSource if callParentStartHandlers is true', async () => {
const parent = new SearchSource({}, searchSourceDependencies);
const searchSource = new SearchSource(
{ index: indexPattern },
searchSourceDependencies
).setParent(parent, {
callParentStartHandlers: true,
});
@ -174,19 +184,21 @@ describe('SearchSource', function() {
describe('#legacy fetch()', () => {
beforeEach(() => {
uiSettingsMock.get.mockImplementation(() => {
return true; // batchSearches = true
});
const core = coreMock.createStart();
searchSourceDependencies = {
...searchSourceDependencies,
uiSettings: {
...core.uiSettings,
get: jest.fn(() => {
return true; // batchSearches = true
}),
} as IUiSettingsClient,
};
});
afterEach(() => {
uiSettingsMock.get.mockImplementation(() => {
return false; // batchSearches = false
});
});
it('should call msearch', async () => {
const searchSource = new SearchSource({ index: indexPattern });
test('should call msearch', async () => {
const searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies);
const options = {};
await searchSource.fetch(options);
expect(fetchSoon).toBeCalledTimes(1);
@ -194,18 +206,19 @@ describe('SearchSource', function() {
});
describe('#search service fetch()', () => {
it('should call msearch', async () => {
const searchSource = new SearchSource({ index: indexPattern });
test('should call msearch', async () => {
const searchSource = new SearchSource({ index: indexPattern }, searchSourceDependencies);
const options = {};
await searchSource.fetch(options);
expect(searchStartMock.search).toBeCalledTimes(1);
expect(mockSearchMethod).toBeCalledTimes(1);
});
});
describe('#serialize', function() {
it('should reference index patterns', () => {
describe('#serialize', () => {
test('should reference index patterns', () => {
const indexPattern123 = { id: '123' } as IndexPattern;
const searchSource = new SearchSource();
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('index', indexPattern123);
const { searchSourceJSON, references } = searchSource.serialize();
expect(references[0].id).toEqual('123');
@ -213,8 +226,8 @@ describe('SearchSource', function() {
expect(JSON.parse(searchSourceJSON).indexRefName).toEqual(references[0].name);
});
it('should add other fields', () => {
const searchSource = new SearchSource();
test('should add other fields', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('highlightAll', true);
searchSource.setField('from', 123456);
const { searchSourceJSON } = searchSource.serialize();
@ -222,8 +235,8 @@ describe('SearchSource', function() {
expect(JSON.parse(searchSourceJSON).from).toEqual(123456);
});
it('should omit sort and size', () => {
const searchSource = new SearchSource();
test('should omit sort and size', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
searchSource.setField('highlightAll', true);
searchSource.setField('from', 123456);
searchSource.setField('sort', { field: SortDirection.asc });
@ -232,8 +245,8 @@ describe('SearchSource', function() {
expect(Object.keys(JSON.parse(searchSourceJSON))).toEqual(['highlightAll', 'from']);
});
it('should serialize filters', () => {
const searchSource = new SearchSource();
test('should serialize filters', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
const filter = [
{
query: 'query',
@ -249,8 +262,8 @@ describe('SearchSource', function() {
expect(JSON.parse(searchSourceJSON).filter).toEqual(filter);
});
it('should reference index patterns in filters separately from index field', () => {
const searchSource = new SearchSource();
test('should reference index patterns in filters separately from index field', () => {
const searchSource = new SearchSource({}, searchSourceDependencies);
const indexPattern123 = { id: '123' } as IndexPattern;
searchSource.setField('index', indexPattern123);
const filter = [

View file

@ -69,34 +69,45 @@
* `appSearchSource`.
*/
import _ from 'lodash';
import { uniqueId, uniq, extend, pick, difference, set, omit, keys, isFunction } from 'lodash';
import { map } from 'rxjs/operators';
import { SavedObjectReference } from 'kibana/public';
import { CoreStart, SavedObjectReference } from 'kibana/public';
import { normalizeSortRequest } from './normalize_sort_request';
import { filterDocvalueFields } from './filter_docvalue_fields';
import { fieldWildcardFilter } from '../../../../kibana_utils/public';
import { IIndexPattern, SearchRequest } from '../..';
import { IIndexPattern, ISearchGeneric, SearchRequest } from '../..';
import { SearchSourceOptions, SearchSourceFields } from './types';
import { FetchOptions, RequestFailure, getSearchParams, handleResponse } from '../fetch';
import { getSearchService, getUiSettings, getInjectedMetadata } from '../../services';
import { getEsQueryConfig, buildEsQuery, Filter } from '../../../common';
import { getHighlightRequest } from '../../../common/field_formats';
import { fetchSoon } from '../legacy';
import { ISearchStartLegacy } from '../types';
export type ISearchSource = Pick<SearchSource, keyof SearchSource>;
export interface SearchSourceDependencies {
uiSettings: CoreStart['uiSettings'];
search: ISearchGeneric;
legacySearch: ISearchStartLegacy;
injectedMetadata: CoreStart['injectedMetadata'];
}
/** @public **/
export class SearchSource {
private id: string = _.uniqueId('data_source');
private id: string = uniqueId('data_source');
private searchStrategyId?: string;
private parent?: SearchSource;
private requestStartHandlers: Array<
(searchSource: ISearchSource, options?: FetchOptions) => Promise<unknown>
(searchSource: SearchSource, options?: FetchOptions) => Promise<unknown>
> = [];
private inheritOptions: SearchSourceOptions = {};
public history: SearchRequest[] = [];
private fields: SearchSourceFields;
private readonly dependencies: SearchSourceDependencies;
constructor(private fields: SearchSourceFields = {}) {}
constructor(fields: SearchSourceFields = {}, dependencies: SearchSourceDependencies) {
this.fields = fields;
this.dependencies = dependencies;
}
/** ***
* PUBLIC API
@ -147,11 +158,11 @@ export class SearchSource {
}
create() {
return new SearchSource();
return new SearchSource({}, this.dependencies);
}
createCopy() {
const newSearchSource = new SearchSource();
const newSearchSource = new SearchSource({}, this.dependencies);
newSearchSource.setFields({ ...this.fields });
// when serializing the internal fields we lose the internal classes used in the index
// pattern, so we have to set it again to workaround this behavior
@ -161,7 +172,7 @@ export class SearchSource {
}
createChild(options = {}) {
const childSearchSource = new SearchSource();
const childSearchSource = new SearchSource({}, this.dependencies);
childSearchSource.setParent(this, options);
return childSearchSource;
}
@ -191,16 +202,17 @@ export class SearchSource {
* @return {Observable<SearchResponse<unknown>>}
*/
private fetch$(searchRequest: SearchRequest, signal?: AbortSignal) {
const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number;
const searchParams = getSearchParams(getUiSettings(), esShardTimeout);
const { search, injectedMetadata, uiSettings } = this.dependencies;
const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number;
const searchParams = getSearchParams(uiSettings, esShardTimeout);
const params = {
index: searchRequest.index.title || searchRequest.index,
body: searchRequest.body,
...searchParams,
};
return getSearchService()
.search({ params, indexType: searchRequest.indexType }, { signal })
.pipe(map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)));
return search({ params, indexType: searchRequest.indexType }, { signal }).pipe(
map(({ rawResponse }) => handleResponse(searchRequest, rawResponse))
);
}
/**
@ -208,7 +220,9 @@ export class SearchSource {
* @return {Promise<SearchResponse<unknown>>}
*/
private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) {
const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number;
const { injectedMetadata, legacySearch, uiSettings } = this.dependencies;
const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number;
return await fetchSoon(
searchRequest,
{
@ -216,8 +230,8 @@ export class SearchSource {
...options,
},
{
searchService: getSearchService(),
config: getUiSettings(),
legacySearchService: legacySearch,
config: uiSettings,
esShardTimeout,
}
);
@ -228,13 +242,14 @@ export class SearchSource {
* @async
*/
async fetch(options: FetchOptions = {}) {
const { uiSettings } = this.dependencies;
await this.requestIsStarting(options);
const searchRequest = await this.flatten();
this.history = [searchRequest];
let response;
if (getUiSettings().get('courier:batchSearches')) {
if (uiSettings.get('courier:batchSearches')) {
response = await this.legacyFetch(searchRequest, options);
} else {
response = this.fetch$(searchRequest, options.abortSignal).toPromise();
@ -253,7 +268,7 @@ export class SearchSource {
* @return {undefined}
*/
onRequestStart(
handler: (searchSource: ISearchSource, options?: FetchOptions) => Promise<unknown>
handler: (searchSource: SearchSource, options?: FetchOptions) => Promise<unknown>
) {
this.requestStartHandlers.push(handler);
}
@ -326,13 +341,15 @@ export class SearchSource {
}
};
const { uiSettings } = this.dependencies;
switch (key) {
case 'filter':
return addToRoot('filters', (data.filters || []).concat(val));
case 'query':
return addToRoot(key, (data[key] || []).concat(val));
case 'fields':
const fields = _.uniq((data[key] || []).concat(val));
const fields = uniq((data[key] || []).concat(val));
return addToRoot(key, fields);
case 'index':
case 'type':
@ -346,7 +363,7 @@ export class SearchSource {
const sort = normalizeSortRequest(
val,
this.getField('index'),
getUiSettings().get('sort:options')
uiSettings.get('sort:options')
);
return addToBody(key, sort);
default:
@ -389,7 +406,7 @@ export class SearchSource {
body.stored_fields = computedFields.storedFields;
body.script_fields = body.script_fields || {};
_.extend(body.script_fields, computedFields.scriptFields);
extend(body.script_fields, computedFields.scriptFields);
const defaultDocValueFields = computedFields.docvalueFields
? computedFields.docvalueFields
@ -400,9 +417,11 @@ export class SearchSource {
body._source = index.getSourceFiltering();
}
const { uiSettings } = this.dependencies;
if (body._source) {
// exclude source fields for this index pattern specified by the user
const filter = fieldWildcardFilter(body._source.excludes, getUiSettings().get('metaFields'));
const filter = fieldWildcardFilter(body._source.excludes, uiSettings.get('metaFields'));
body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) =>
filter(docvalueField.field)
);
@ -412,19 +431,19 @@ export class SearchSource {
if (fields) {
// filter out the docvalue_fields, and script_fields to only include those that we are concerned with
body.docvalue_fields = filterDocvalueFields(body.docvalue_fields, fields);
body.script_fields = _.pick(body.script_fields, fields);
body.script_fields = pick(body.script_fields, fields);
// request the remaining fields from both stored_fields and _source
const remainingFields = _.difference(fields, _.keys(body.script_fields));
const remainingFields = difference(fields, keys(body.script_fields));
body.stored_fields = remainingFields;
_.set(body, '_source.includes', remainingFields);
set(body, '_source.includes', remainingFields);
}
const esQueryConfigs = getEsQueryConfig(getUiSettings());
const esQueryConfigs = getEsQueryConfig(uiSettings);
body.query = buildEsQuery(index, query, filters, esQueryConfigs);
if (highlightAll && body.query) {
body.highlight = getHighlightRequest(body.query, getUiSettings().get('doc_table:highlight'));
body.highlight = getHighlightRequest(body.query, uiSettings.get('doc_table:highlight'));
delete searchRequest.highlightAll;
}
@ -467,7 +486,7 @@ export class SearchSource {
const {
filter: originalFilters,
...searchSourceFields
}: Omit<SearchSourceFields, 'sort' | 'size'> = _.omit(this.getFields(), ['sort', 'size']);
}: Omit<SearchSourceFields, 'sort' | 'size'> = omit(this.getFields(), ['sort', 'size']);
let serializedSearchSourceFields: Omit<SearchSourceFields, 'sort' | 'size' | 'filter'> & {
indexRefName?: string;
filter?: Array<Omit<Filter, 'meta'> & { meta: Filter['meta'] & { indexRefName?: string } }>;
@ -524,10 +543,13 @@ export class SearchSource {
return filterField;
}
if (_.isFunction(filterField)) {
if (isFunction(filterField)) {
return this.getFilters(filterField());
}
return [filterField];
}
}
/** @public **/
export type ISearchSource = Pick<SearchSource, keyof SearchSource>;

View file

@ -17,13 +17,13 @@
* under the License.
*/
import { CoreStart } from 'kibana/public';
import { createSearchSource } from './search_source';
import { CoreStart, SavedObjectReference } from 'kibana/public';
import { SearchAggsSetup, SearchAggsStart, SearchAggsStartLegacy } from './aggs';
import { ISearch, ISearchGeneric } from './i_search';
import { TStrategyTypes } from './strategy_types';
import { LegacyApiCaller } from './legacy/es_client';
import { SearchInterceptor } from './search_interceptor';
import { ISearchSource, SearchSourceFields } from './search_source';
export interface ISearchContext {
core: CoreStart;
@ -60,7 +60,7 @@ export type TRegisterSearchStrategyProvider = <T extends TStrategyTypes>(
searchStrategyProvider: TSearchStrategyProvider<T>
) => void;
interface ISearchStartLegacy {
export interface ISearchStartLegacy {
esClient: LegacyApiCaller;
}
@ -81,6 +81,12 @@ export interface ISearchStart {
aggs: SearchAggsStart;
setInterceptor: (searchInterceptor: SearchInterceptor) => void;
search: ISearchGeneric;
createSearchSource: ReturnType<typeof createSearchSource>;
searchSource: {
create: (fields?: SearchSourceFields) => ISearchSource;
fromJSON: (
searchSourceJson: string,
references: SavedObjectReference[]
) => Promise<ISearchSource>;
};
__LEGACY: ISearchStartLegacy & SearchAggsStartLegacy;
}

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { NotificationsStart, CoreSetup, CoreStart } from 'src/core/public';
import { NotificationsStart, CoreStart } from 'src/core/public';
import { FieldFormatsStart } from './field_formats';
import { createGetterSetter } from '../../kibana_utils/public';
import { IndexPatternsContract } from './index_patterns';
@ -48,7 +48,7 @@ export const [getQueryService, setQueryService] = createGetterSetter<
>('Query');
export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter<
CoreSetup['injectedMetadata']
CoreStart['injectedMetadata']
>('InjectedMetadata');
export const [getSearchService, setSearchService] = createGetterSetter<

View file

@ -75,8 +75,11 @@ export interface IDataPluginServices extends Partial<CoreStart> {
/** @internal **/
export interface InternalStartServices {
fieldFormats: FieldFormatsStart;
notifications: CoreStart['notifications'];
readonly fieldFormats: FieldFormatsStart;
readonly notifications: CoreStart['notifications'];
readonly uiSettings: CoreStart['uiSettings'];
readonly searchService: DataPublicPluginStart['search'];
readonly injectedMetadata: CoreStart['injectedMetadata'];
}
/** @internal **/

View file

@ -17,9 +17,9 @@
* under the License.
*/
import _ from 'lodash';
import { EsResponse, SavedObject, SavedObjectConfig } from '../../types';
import { EsResponse, SavedObject, SavedObjectConfig, SavedObjectKibanaServices } from '../../types';
import { expandShorthand, SavedObjectNotFound } from '../../../../kibana_utils/public';
import { DataPublicPluginStart, IndexPattern } from '../../../../data/public';
import { IndexPattern } from '../../../../data/public';
/**
* A given response of and ElasticSearch containing a plain saved object is applied to the given
@ -29,7 +29,7 @@ export async function applyESResp(
resp: EsResponse,
savedObject: SavedObject,
config: SavedObjectConfig,
createSearchSource: DataPublicPluginStart['search']['createSearchSource']
dependencies: SavedObjectKibanaServices
) {
const mapping = expandShorthand(config.mapping);
const esType = config.type || '';
@ -65,7 +65,10 @@ export async function applyESResp(
if (config.searchSource) {
try {
savedObject.searchSource = await createSearchSource(meta.searchSourceJSON, resp.references);
savedObject.searchSource = await dependencies.search.searchSource.fromJSON(
meta.searchSourceJSON,
resp.references
);
} catch (error) {
if (
error.constructor.name === 'SavedObjectNotFound' &&

View file

@ -16,8 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import _ from 'lodash';
import { SearchSource } from '../../../../data/public';
import { once } from 'lodash';
import { hydrateIndexPattern } from './hydrate_index_pattern';
import { intializeSavedObject } from './initialize_saved_object';
import { serializeSavedObject } from './serialize_saved_object';
@ -55,7 +54,9 @@ export function buildSavedObject(
savedObject.isSaving = false;
savedObject.defaults = config.defaults || {};
// optional search source which this object configures
savedObject.searchSource = config.searchSource ? new SearchSource() : undefined;
savedObject.searchSource = config.searchSource
? services.search.searchSource.create()
: undefined;
// the id of the document
savedObject.id = config.id || void 0;
// the migration version of the document, should only be set on imports
@ -79,10 +80,9 @@ export function buildSavedObject(
* @return {Promise}
* @resolved {SavedObject}
*/
savedObject.init = _.once(() => intializeSavedObject(savedObject, savedObjectsClient, config));
savedObject.init = once(() => intializeSavedObject(savedObject, savedObjectsClient, config));
savedObject.applyESResp = (resp: EsResponse) =>
applyESResp(resp, savedObject, config, services.search.createSearchSource);
savedObject.applyESResp = (resp: EsResponse) => applyESResp(resp, savedObject, config, services);
/**
* Serialize this object

View file

@ -28,9 +28,8 @@ import {
// @ts-ignore
import StubIndexPattern from 'test_utils/stub_index_pattern';
import { InvalidJSONProperty } from '../../../kibana_utils/public';
import { coreMock } from '../../../../core/public/mocks';
import { dataPluginMock } from '../../../../plugins/data/public/mocks';
import { dataPluginMock, createSearchSourceMock } from '../../../../plugins/data/public/mocks';
import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public';
import { IIndexPattern } from '../../../data/common/index_patterns';
@ -40,9 +39,9 @@ describe('Saved Object', () => {
const startMock = coreMock.createStart();
const dataStartMock = dataPluginMock.createStartContract();
const saveOptionsMock = {} as SavedObjectSaveOpts;
const savedObjectsClientStub = startMock.savedObjects.client;
let SavedObjectClass: new (config: SavedObjectConfig) => SavedObject;
const savedObjectsClientStub = startMock.savedObjects.client;
/**
* Returns a fake doc response with the given index and id, of type dashboard
@ -99,16 +98,22 @@ describe('Saved Object', () => {
function createInitializedSavedObject(config: SavedObjectConfig = {}) {
const savedObject = new SavedObjectClass(config);
savedObject.title = 'my saved object';
return savedObject.init!();
}
beforeEach(() => {
(dataStartMock.search.createSearchSource as jest.Mock).mockReset();
SavedObjectClass = createSavedObjectClass({
SavedObjectClass = createSavedObjectClass(({
savedObjectsClient: savedObjectsClientStub,
indexPatterns: dataStartMock.indexPatterns,
search: dataStartMock.search,
} as SavedObjectKibanaServices);
search: {
...dataStartMock.search,
searchSource: {
...dataStartMock.search.searchSource,
create: createSearchSourceMock,
},
},
} as unknown) as SavedObjectKibanaServices);
});
describe('save', () => {
@ -411,27 +416,6 @@ describe('Saved Object', () => {
});
});
it('forwards thrown exceptions from createSearchSource', async () => {
(dataStartMock.search.createSearchSource as jest.Mock).mockImplementation(() => {
throw new InvalidJSONProperty('');
});
const savedObject = await createInitializedSavedObject({
type: 'dashboard',
searchSource: true,
});
const response = {
found: true,
_source: {},
};
try {
await savedObject.applyESResp(response);
throw new Error('applyESResp should have failed, but did not.');
} catch (err) {
expect(err instanceof InvalidJSONProperty).toBe(true);
}
});
it('preserves original defaults if not overridden', () => {
const id = 'anid';
const preserveMeValue = 'here to stay!';
@ -589,42 +573,45 @@ describe('Saved Object', () => {
it('passes references to search source parsing function', async () => {
const savedObject = new SavedObjectClass({ type: 'dashboard', searchSource: true });
return savedObject.init!().then(() => {
const searchSourceJSON = JSON.stringify({
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
filter: [
{
meta: {
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
},
},
],
});
const response = {
found: true,
_source: {
kibanaSavedObjectMeta: {
searchSourceJSON,
await savedObject.init!();
const searchSourceJSON = JSON.stringify({
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
filter: [
{
meta: {
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
},
},
references: [
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
type: 'index-pattern',
id: 'my-index-1',
},
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
type: 'index-pattern',
id: 'my-index-2',
},
],
};
savedObject.applyESResp(response);
expect(dataStartMock.search.createSearchSource).toBeCalledWith(
searchSourceJSON,
response.references
);
],
});
const response = {
found: true,
_source: {
kibanaSavedObjectMeta: {
searchSourceJSON,
},
},
references: [
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
type: 'index-pattern',
id: 'my-index-1',
},
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
type: 'index-pattern',
id: 'my-index-2',
},
],
};
const result = await savedObject.applyESResp(response);
expect(result._source).toEqual({
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index","filter":[{"meta":{"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index"}}]}',
},
});
});
});

View file

@ -25,6 +25,7 @@ import {
} from './resolve_saved_objects';
import { SavedObject, SavedObjectLoader } from '../../../saved_objects/public';
import { IndexPatternsContract } from '../../../data/public';
import { dataPluginMock } from '../../../data/public/mocks';
class SavedObjectNotFound extends Error {
constructor(options: Record<string, any>) {
@ -233,6 +234,19 @@ describe('resolveSavedObjects', () => {
});
describe('resolveIndexPatternConflicts', () => {
let dependencies: Parameters<typeof resolveIndexPatternConflicts>[3];
beforeEach(() => {
const search = dataPluginMock.createStartContract().search;
dependencies = {
indexPatterns: ({
get: (id: string) => Promise.resolve({ id }),
} as unknown) as IndexPatternsContract,
search,
};
});
it('should resave resolutions', async () => {
const save = jest.fn();
@ -284,11 +298,13 @@ describe('resolveSavedObjects', () => {
const overwriteAll = false;
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll, ({
get: (id: string) => Promise.resolve({ id }),
} as unknown) as IndexPatternsContract);
expect(conflictedIndexPatterns[0].obj.searchSource!.getField('index')!.id).toEqual('2');
expect(conflictedIndexPatterns[1].obj.searchSource!.getField('index')!.id).toEqual('4');
await resolveIndexPatternConflicts(
resolutions,
conflictedIndexPatterns,
overwriteAll,
dependencies
);
expect(save.mock.calls.length).toBe(2);
expect(save).toHaveBeenCalledWith({ confirmOverwrite: !overwriteAll });
});
@ -345,13 +361,13 @@ describe('resolveSavedObjects', () => {
const overwriteAll = false;
await resolveIndexPatternConflicts(resolutions, conflictedIndexPatterns, overwriteAll, ({
get: (id: string) => Promise.resolve({ id }),
} as unknown) as IndexPatternsContract);
await resolveIndexPatternConflicts(
resolutions,
conflictedIndexPatterns,
overwriteAll,
dependencies
);
expect(conflictedIndexPatterns[0].obj.searchSource!.getField('filter')).toEqual([
{ meta: { index: 'newFilterIndex' } },
]);
expect(save.mock.calls.length).toBe(2);
});
});

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { cloneDeep } from 'lodash';
import { OverlayStart, SavedObjectReference } from 'src/core/public';
import { SavedObject, SavedObjectLoader } from '../../../saved_objects/public';
import { IndexPatternsContract, IIndexPattern, createSearchSource } from '../../../data/public';
import { IndexPatternsContract, IIndexPattern, DataPublicPluginStart } from '../../../data/public';
type SavedObjectsRawDoc = Record<string, any>;
@ -162,7 +162,10 @@ export async function resolveIndexPatternConflicts(
resolutions: Array<{ oldId: string; newId: string }>,
conflictedIndexPatterns: any[],
overwriteAll: boolean,
indexPatterns: IndexPatternsContract
dependencies: {
indexPatterns: IndexPatternsContract;
search: DataPublicPluginStart['search'];
}
) {
let importCount = 0;
@ -208,7 +211,7 @@ export async function resolveIndexPatternConflicts(
// The user decided to skip this conflict so do nothing
return;
}
obj.searchSource = await createSearchSource(indexPatterns)(
obj.searchSource = await dependencies.search.searchSource.fromJSON(
JSON.stringify(serializedSearchSource),
replacedReferences
);

View file

@ -187,6 +187,7 @@ const SavedObjectsTablePage = ({
actionRegistry={actionRegistry}
savedObjectsClient={coreStart.savedObjects.client}
indexPatterns={dataStart.indexPatterns}
search={dataStart.search}
http={coreStart.http}
overlays={coreStart.overlays}
notifications={coreStart.notifications}

View file

@ -256,6 +256,41 @@ exports[`SavedObjectsTable import should show the flyout 1`] = `
"openModal": [MockFunction],
}
}
search={
Object {
"__LEGACY": Object {
"AggConfig": [MockFunction],
"AggType": [MockFunction],
"FieldParamType": [MockFunction],
"MetricAggType": [MockFunction],
"aggTypeFieldFilters": AggTypeFieldFilters {
"filters": Set {},
},
"esClient": Object {
"msearch": [MockFunction],
"search": [MockFunction],
},
"parentPipelineAggHelper": [MockFunction],
"siblingPipelineAggHelper": [MockFunction],
},
"aggs": Object {
"calculateAutoTimeExpression": [Function],
"createAggConfigs": [MockFunction],
"types": Object {
"get": [Function],
"getAll": [Function],
"getBuckets": [Function],
"getMetrics": [Function],
},
},
"search": [MockFunction],
"searchSource": Object {
"create": [MockFunction],
"fromJSON": [MockFunction],
},
"setInterceptor": [MockFunction],
}
}
serviceRegistry={
Object {
"all": [MockFunction],

View file

@ -33,6 +33,7 @@ import { coreMock } from '../../../../../../core/public/mocks';
import { serviceRegistryMock } from '../../../services/service_registry.mock';
import { Flyout, FlyoutProps, FlyoutState } from './flyout';
import { ShallowWrapper } from 'enzyme';
import { dataPluginMock } from '../../../../../data/public/mocks';
const mockFile = ({
name: 'foo.ndjson',
@ -56,6 +57,7 @@ describe('Flyout', () => {
beforeEach(() => {
const { http, overlays } = coreMock.createStart();
const search = dataPluginMock.createStartContract().search;
defaultProps = {
close: jest.fn(),
@ -68,6 +70,7 @@ describe('Flyout', () => {
http,
allowedTypes: ['search', 'index-pattern', 'visualization'],
serviceRegistry: serviceRegistryMock.create(),
search,
};
});
@ -499,7 +502,10 @@ describe('Flyout', () => {
component.instance().resolutions,
mockConflictedIndexPatterns,
true,
defaultProps.indexPatterns
{
search: defaultProps.search,
indexPatterns: defaultProps.indexPatterns,
}
);
expect(saveObjectsMock).toHaveBeenCalledWith(
mockConflictedSavedObjectsLinkedToSavedSearches,

View file

@ -48,7 +48,11 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { OverlayStart, HttpStart } from 'src/core/public';
import { IndexPatternsContract, IIndexPattern } from '../../../../../data/public';
import {
IndexPatternsContract,
IIndexPattern,
DataPublicPluginStart,
} from '../../../../../data/public';
import {
importFile,
importLegacyFile,
@ -75,6 +79,7 @@ export interface FlyoutProps {
indexPatterns: IndexPatternsContract;
overlays: OverlayStart;
http: HttpStart;
search: DataPublicPluginStart['search'];
}
export interface FlyoutState {
@ -362,7 +367,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
failedImports,
} = this.state;
const { serviceRegistry, indexPatterns } = this.props;
const { serviceRegistry, indexPatterns, search } = this.props;
this.setState({
error: undefined,
@ -388,7 +393,10 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
resolutions,
conflictedIndexPatterns!,
isOverwriteAllChecked,
indexPatterns
{
indexPatterns,
search,
}
);
}
this.setState({

View file

@ -88,6 +88,7 @@ describe('SavedObjectsTable', () => {
let overlays: ReturnType<typeof overlayServiceMock.createStartContract>;
let notifications: ReturnType<typeof notificationServiceMock.createStartContract>;
let savedObjects: ReturnType<typeof savedObjectsServiceMock.createStartContract>;
let search: ReturnType<typeof dataPluginMock.createStartContract>['search'];
const shallowRender = (overrides: Partial<SavedObjectsTableProps> = {}) => {
return (shallowWithI18nProvider(
@ -106,6 +107,7 @@ describe('SavedObjectsTable', () => {
overlays = overlayServiceMock.createStartContract();
notifications = notificationServiceMock.createStartContract();
savedObjects = savedObjectsServiceMock.createStartContract();
search = dataPluginMock.createStartContract().search;
const applications = applicationServiceMock.createStartContract();
applications.capabilities = {
@ -141,6 +143,7 @@ describe('SavedObjectsTable', () => {
perPageConfig: 15,
goInspectObject: () => {},
canGoInApp: () => true,
search,
};
findObjectsMock.mockImplementation(() => ({

Some files were not shown because too many files have changed in this diff Show more