diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fbd775d6ba5..cddd9da31638 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# [`master`](https://github.com/elastic/eui/tree/master)
-No public interface changes since `0.0.25`.
+No public interface changes since `0.0.24`.
# [`0.0.24`](https://github.com/elastic/eui/tree/v0.0.24)
@@ -18,7 +18,8 @@ No public interface changes since `0.0.25`.
# [`0.0.23`](https://github.com/elastic/eui/tree/v0.0.23)
-- Added `EuiInMemoryTable`, which encapsulates sorting, searching, selection, and pagination state and logic ([#390](https://github.com/elastic/eui/pull/390))
+- Added `EuiInMemoryTable`, which encapsulates sorting, searching, selection, and pagination state
+and logic ([#390](https://github.com/elastic/eui/pull/390))
- Added stack trace information to `EuiErrorBoundary` ([#428](https://github.com/elastic/eui/pull/428))
**Bug fixes**
diff --git a/src-docs/src/views/search_bar/search_bar.js b/src-docs/src/views/search_bar/search_bar.js
index 4f7a7f83ebf4..5598c3e583cc 100644
--- a/src-docs/src/views/search_bar/search_bar.js
+++ b/src-docs/src/views/search_bar/search_bar.js
@@ -1,89 +1,72 @@
-import React, { Component, Fragment } from 'react';
-
+import React, { Fragment } from 'react';
+import { Random } from '../../../../src/services/random';
import {
- EuiHealth,
- EuiCallOut,
- EuiSpacer,
- EuiFlexGroup,
- EuiFlexItem,
- EuiCodeBlock,
- EuiIcon,
- EuiTitle,
- EuiSwitch,
- EuiBasicTable,
EuiSearchBar,
-} from '../../../../src/components';
-
-import {
- Query,
- Random,
-} from '../../../../src/services';
-
+ Query
+} from '../../../../src/components/search_bar';
+import { EuiHealth } from '../../../../src/components/health';
+import { EuiCallOut } from '../../../../src/components/call_out';
+import { EuiSpacer } from '../../../../src/components/spacer/spacer';
+import { EuiFlexGroup } from '../../../../src/components/flex/flex_group';
+import { EuiFlexItem } from '../../../../src/components/flex/flex_item';
+import { EuiCodeBlock } from '../../../../src/components/code';
import { times } from 'lodash';
+import { EuiIcon } from '../../../../src/components/icon/icon';
+import { EuiTitle } from '../../../../src/components/title';
+import { EuiSwitch } from '../../../../src/components/form/switch/switch';
+import { EuiBasicTable } from '../../../../src/components/basic_table';
const random = new Random();
-const tags = [{
- name: 'marketing', status: 'off',
-}, {
- name: 'finance', status: 'on',
-}, {
- name: 'eng', status: 'on',
-}, {
- name: 'sales', status: 'processing',
-}, {
- name: 'ga', status: 'on',
-}];
+const tags = [
+ { value: 'marketing', view: (
- While the user can use the syntax described above to enter queries in the search box, it is possible + While the user can us the syntax described above to enter queries in the search box, it is possible provide the user help with the syntax using filters. The filters are UI controls that can manipulate the query. The available filters are:
diff --git a/src-docs/src/views/table_of_records/column_data_types.js b/src-docs/src/views/table_of_records/column_data_types.js index 7a4ae897779d..f42e79bde14e 100644 --- a/src-docs/src/views/table_of_records/column_data_types.js +++ b/src-docs/src/views/table_of_records/column_data_types.js @@ -14,7 +14,7 @@ const random = new Random(); const records = times(5, (index) => { return { id: index, - string: random.oneOf(['Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan']), + string: random.oneOf('Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan'), number: random.integer({ min: 0, max: 2000000 }), boolean: random.boolean(), date: random.date({ min: new Date(1971, 0, 0), max: new Date(1990, 0, 0) }) diff --git a/src-docs/src/views/table_of_records/full_featured.js b/src-docs/src/views/table_of_records/full_featured.js index f9830daa9e28..0083cd329fc4 100644 --- a/src-docs/src/views/table_of_records/full_featured.js +++ b/src-docs/src/views/table_of_records/full_featured.js @@ -26,11 +26,11 @@ const random = new Random(); const people = times(20, (index) => { return { id: index, - firstName: random.oneOf(['Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan']), - lastName: random.oneOf(['van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel']), - nickname: random.oneOf(['martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'whack']), + firstName: random.oneOf('Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan'), + lastName: random.oneOf('van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel'), + nickname: random.oneOf('martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'whack'), dateOfBirth: random.date({ min: new Date(1971, 0, 0), max: new Date(1990, 0, 0) }), - country: random.oneOf(['us', 'nl', 'cz', 'za', 'au']), + country: random.oneOf('us', 'nl', 'cz', 'za', 'au'), online: random.boolean() }; }); diff --git a/src-docs/src/views/table_of_records/implicit_record_action.js b/src-docs/src/views/table_of_records/implicit_record_action.js index 77d7056a29a4..6ef27a990358 100644 --- a/src-docs/src/views/table_of_records/implicit_record_action.js +++ b/src-docs/src/views/table_of_records/implicit_record_action.js @@ -19,11 +19,11 @@ const random = new Random(); const people = times(20, (index) => { return { id: index, - firstName: random.oneOf(['Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan']), - lastName: random.oneOf(['van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel']), - nickname: random.oneOf(['martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'whack']), + firstName: random.oneOf('Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan'), + lastName: random.oneOf('van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel'), + nickname: random.oneOf('martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'whack'), dateOfBirth: random.date({ min: new Date(1971, 0, 0), max: new Date(1990, 0, 0) }), - country: random.oneOf(['us', 'nl', 'cz', 'za', 'au']), + country: random.oneOf('us', 'nl', 'cz', 'za', 'au'), online: random.boolean() }; }); diff --git a/src-docs/src/views/tables/data_store.js b/src-docs/src/views/tables/data_store.js index c324b549cb59..8dfdcfc69038 100644 --- a/src-docs/src/views/tables/data_store.js +++ b/src-docs/src/views/tables/data_store.js @@ -35,11 +35,11 @@ const createUsers = (countries) => { return times(20, (index) => { return { id: index, - firstName: random.oneOf(['Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan']), - lastName: random.oneOf(['van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel']), - github: random.oneOf(['martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'jordansissel']), + firstName: random.oneOf('Martijn', 'Elissa', 'Clinton', 'Igor', 'Karl', 'Drew', 'Honza', 'Rashid', 'Jordan'), + lastName: random.oneOf('van Groningen', 'Weve', 'Gormley', 'Motov', 'Minarik', 'Raines', 'Král', 'Khan', 'Sissel'), + github: random.oneOf('martijnvg', 'elissaw', 'clintongormley', 'imotov', 'karmi', 'drewr', 'HonzaKral', 'rashidkpc', 'jordansissel'), dateOfBirth: random.date({ min: new Date(1971, 0, 0), max: new Date(1990, 0, 0) }), - nationality: random.oneOf(countries.map(country => country.code)), + nationality: random.oneOf(...countries.map(country => country.code)), online: random.boolean() }; }); diff --git a/src/components/basic_table/collapsed_item_actions.test.js b/src/components/basic_table/collapsed_item_actions.test.js index f83fadfbe1fd..d90e82d64e11 100644 --- a/src/components/basic_table/collapsed_item_actions.test.js +++ b/src/components/basic_table/collapsed_item_actions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { CollapsedItemActions } from './collapsed_item_actions'; describe('CollapsedItemActions', () => { diff --git a/src/components/basic_table/custom_item_action.test.js b/src/components/basic_table/custom_item_action.test.js index 63a4708a0d7e..3bfa026bec6c 100644 --- a/src/components/basic_table/custom_item_action.test.js +++ b/src/components/basic_table/custom_item_action.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { CustomItemAction } from './custom_item_action'; describe('CustomItemAction', () => { diff --git a/src/components/basic_table/default_item_action.test.js b/src/components/basic_table/default_item_action.test.js index 59caeb22ab32..47950bb56383 100644 --- a/src/components/basic_table/default_item_action.test.js +++ b/src/components/basic_table/default_item_action.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { DefaultItemAction } from './default_item_action'; import { Random } from '../../services/random'; @@ -13,7 +13,7 @@ describe('DefaultItemAction', () => { action: { name: 'action1', description: 'action 1', - type: random.oneOf([undefined, 'button', 'foobar']), + type: random.oneOf(undefined, 'button', 'foobar'), onClick: () => {} }, enabled: true, diff --git a/src/components/basic_table/expanded_item_actions.test.js b/src/components/basic_table/expanded_item_actions.test.js index 19d54b76aad4..ebc154bd79f7 100644 --- a/src/components/basic_table/expanded_item_actions.test.js +++ b/src/components/basic_table/expanded_item_actions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { ExpandedItemActions } from './expanded_item_actions'; describe('ExpandedItemActions', () => { diff --git a/src/components/basic_table/in_memory_table.js b/src/components/basic_table/in_memory_table.js index c8f840dad1c7..3ba3455e53a3 100644 --- a/src/components/basic_table/in_memory_table.js +++ b/src/components/basic_table/in_memory_table.js @@ -8,14 +8,13 @@ import { import { defaults as paginationBarDefaults } from './pagination_bar'; -import { Query } from '../../services/query'; import { isBoolean, isString } from '../../services/predicate'; import { Comparators } from '../../services/sort'; import { + Query, QueryType, SearchFiltersFiltersType, - SearchBoxConfigPropTypes, - EuiSearchBar, + SearchBoxConfigPropTypes, EuiSearchBar } from '../search_bar'; import { EuiSpacer } from '../spacer/spacer'; diff --git a/src/components/basic_table/pagination_bar.test.js b/src/components/basic_table/pagination_bar.test.js index 58d2da80f4f9..688ed411eaab 100644 --- a/src/components/basic_table/pagination_bar.test.js +++ b/src/components/basic_table/pagination_bar.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { PaginationBar } from './pagination_bar'; describe('PaginationBar', () => { diff --git a/src/components/index.js b/src/components/index.js index e072c7e0bceb..b99f97ab8a3f 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -209,7 +209,7 @@ export { } from './progress'; export { - EuiSearchBar, + EuiSearchBar } from './search_bar'; export { diff --git a/src/components/search_bar/__snapshots__/search_bar.test.js.snap b/src/components/search_bar/__snapshots__/search_bar.test.js.snap index 198258883755..99c45e8b4196 100644 --- a/src/components/search_bar/__snapshots__/search_bar.test.js.snap +++ b/src/components/search_bar/__snapshots__/search_bar.test.js.snap @@ -92,7 +92,7 @@ exports[`SearchBar render - provided query, filters 1`] = ` onChange={[Function]} query={ Query { - "ast": _Ast { + "ast": _AST { "_clauses": Array [ Object { "match": "must", diff --git a/src/components/search_bar/__snapshots__/search_filters.test.js.snap b/src/components/search_bar/__snapshots__/search_filters.test.js.snap index 8c072425f5d1..269c295f2e73 100644 --- a/src/components/search_bar/__snapshots__/search_filters.test.js.snap +++ b/src/components/search_bar/__snapshots__/search_filters.test.js.snap @@ -24,7 +24,7 @@ exports[`EuiSearchFilters render - with filters 1`] = ` onChange={[Function]} query={ Query { - "ast": _Ast { + "ast": _AST { "_clauses": Array [], "_indexedClauses": Object { "field": Object {}, @@ -62,7 +62,7 @@ exports[`EuiSearchFilters render - with filters 1`] = ` onChange={[Function]} query={ Query { - "ast": _Ast { + "ast": _AST { "_clauses": Array [], "_indexedClauses": Object { "field": Object {}, diff --git a/src/components/search_bar/filters/field_value_selection_filter.js b/src/components/search_bar/filters/field_value_selection_filter.js index ded96fe7baed..cc149f22a688 100644 --- a/src/components/search_bar/filters/field_value_selection_filter.js +++ b/src/components/search_bar/filters/field_value_selection_filter.js @@ -10,7 +10,7 @@ import { EuiFilterSelectItem, EuiFilterButton } from '../../filter_group'; import { EuiLoadingChart } from '../../loading/loading_chart'; import { EuiSpacer } from '../../spacer/spacer'; import { EuiIcon } from '../../icon/icon'; -import { Query } from '../../../services/query'; +import { Query } from '../query'; const FieldValueOptionType = PropTypes.shape({ value: PropTypes.any.isRequired, diff --git a/src/components/search_bar/filters/field_value_selection_filter.test.js b/src/components/search_bar/filters/field_value_selection_filter.test.js index fd659e635eff..ef88afc2ea27 100644 --- a/src/components/search_bar/filters/field_value_selection_filter.test.js +++ b/src/components/search_bar/filters/field_value_selection_filter.test.js @@ -1,8 +1,8 @@ import React from 'react'; -import { shallow } from 'enzyme'; import { requiredProps } from '../../../test'; +import { shallow } from 'enzyme/build/index'; import { FieldValueSelectionFilter } from './field_value_selection_filter'; -import { Query } from '../../../services/query'; +import { Query } from '../query'; describe('FieldValueSelectionFilter', () => { diff --git a/src/components/search_bar/filters/field_value_toggle_filter.js b/src/components/search_bar/filters/field_value_toggle_filter.js index 7c9b1fd7cb74..92e3405c451f 100644 --- a/src/components/search_bar/filters/field_value_toggle_filter.js +++ b/src/components/search_bar/filters/field_value_toggle_filter.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { EuiFilterButton } from '../../filter_group'; import { isNil } from '../../../services/predicate'; import { EuiPropTypes } from '../../../utils/prop_types'; -import { Query } from '../../../services/query'; +import { Query } from '../query'; export const FieldValueToggleFilterConfigType = PropTypes.shape({ type: EuiPropTypes.is('field_value_toggle').isRequired, diff --git a/src/components/search_bar/filters/field_value_toggle_filter.test.js b/src/components/search_bar/filters/field_value_toggle_filter.test.js index ad90e02dde40..10a84a3a9958 100644 --- a/src/components/search_bar/filters/field_value_toggle_filter.test.js +++ b/src/components/search_bar/filters/field_value_toggle_filter.test.js @@ -1,7 +1,7 @@ import React from 'react'; -import { shallow } from 'enzyme'; import { requiredProps } from '../../../test'; -import { Query } from '../../../services/query'; +import { shallow } from 'enzyme/build/index'; +import { Query } from '../query'; import { FieldValueToggleFilter } from './field_value_toggle_filter'; describe('FieldValueToggleFilter', () => { diff --git a/src/components/search_bar/filters/field_value_toggle_group_filter.js b/src/components/search_bar/filters/field_value_toggle_group_filter.js index 350670ca28b7..b4b31ce8d5fa 100644 --- a/src/components/search_bar/filters/field_value_toggle_group_filter.js +++ b/src/components/search_bar/filters/field_value_toggle_group_filter.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { EuiFilterButton } from '../../filter_group'; import { EuiPropTypes } from '../../../utils/prop_types'; -import { Query } from '../../../services/query'; +import { Query } from '../query'; export const FieldValueToggleGroupFilterItemType = PropTypes.shape({ value: PropTypes.string.isRequired, diff --git a/src/components/search_bar/filters/field_value_toggle_group_filter.test.js b/src/components/search_bar/filters/field_value_toggle_group_filter.test.js index f7fb294403ab..586a772b186f 100644 --- a/src/components/search_bar/filters/field_value_toggle_group_filter.test.js +++ b/src/components/search_bar/filters/field_value_toggle_group_filter.test.js @@ -1,7 +1,7 @@ import React from 'react'; -import { shallow } from 'enzyme'; import { requiredProps } from '../../../test'; -import { Query } from '../../../services/query'; +import { shallow } from 'enzyme/build/index'; +import { Query } from '../query'; import { FieldValueToggleGroupFilter } from './field_value_toggle_group_filter'; describe('TermToggleGroupFilter', () => { diff --git a/src/components/search_bar/filters/is_filter.js b/src/components/search_bar/filters/is_filter.js index ce1e54ea97ce..4d040f36810f 100644 --- a/src/components/search_bar/filters/is_filter.js +++ b/src/components/search_bar/filters/is_filter.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { EuiFilterButton } from '../../filter_group'; import { isNil } from '../../../services/predicate'; import { EuiPropTypes } from '../../../utils/prop_types'; -import { Query } from '../../../services/query'; +import { Query } from '../query'; export const IsFilterConfigType = PropTypes.shape({ type: EuiPropTypes.is('is').isRequired, diff --git a/src/components/search_bar/filters/is_filter.test.js b/src/components/search_bar/filters/is_filter.test.js index 891bc0e22654..94db9f5df920 100644 --- a/src/components/search_bar/filters/is_filter.test.js +++ b/src/components/search_bar/filters/is_filter.test.js @@ -1,8 +1,8 @@ import React from 'react'; -import { shallow } from 'enzyme'; import { requiredProps } from '../../../test'; -import { Query } from '../../../services/query'; +import { shallow } from 'enzyme/build/index'; import { IsFilter } from './is_filter'; +import { Query } from '../query'; describe('IsFilter', () => { diff --git a/src/components/search_bar/index.js b/src/components/search_bar/index.js index a203e6fc36f7..891749863134 100644 --- a/src/components/search_bar/index.js +++ b/src/components/search_bar/index.js @@ -1,4 +1,5 @@ export { EuiSearchBar } from './search_bar'; +export { Query } from './query'; export { QueryType } from './search_bar'; export { SearchBoxConfigPropTypes } from './search_box'; export { SearchFiltersFiltersType } from './search_filters'; diff --git a/src/services/query/__snapshots__/ast_to_es.test.js.snap b/src/components/search_bar/query/__snapshots__/ast_to_es.test.js.snap similarity index 89% rename from src/services/query/__snapshots__/ast_to_es.test.js.snap rename to src/components/search_bar/query/__snapshots__/ast_to_es.test.js.snap index 71f38298994e..5dbc177361f9 100644 --- a/src/services/query/__snapshots__/ast_to_es.test.js.snap +++ b/src/components/search_bar/query/__snapshots__/ast_to_es.test.js.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`astToEs ast - '' 1`] = ` +exports[`astToES ast - '' 1`] = ` Object { "match_all": Object {}, } `; -exports[`astToEs ast - '-group:es group:kibana -group:beats group:logstash' 1`] = ` +exports[`astToES ast - '-group:es group:kibana -group:beats group:logstash' 1`] = ` Object { "bool": Object { "must": Array [ @@ -33,7 +33,7 @@ Object { } `; -exports[`astToEs ast - 'is:online group:kibana john' 1`] = ` +exports[`astToES ast - 'is:online group:kibana john' 1`] = ` Object { "bool": Object { "must": Array [ @@ -60,7 +60,7 @@ Object { } `; -exports[`astToEs ast - 'john -doe is:online group:eng group:es -group:kibana -is:active' 1`] = ` +exports[`astToES ast - 'john -doe is:online group:eng group:es -group:kibana -is:active' 1`] = ` Object { "bool": Object { "must": Array [ @@ -107,7 +107,7 @@ Object { } `; -exports[`astToEs ast - 'john -sales' 1`] = ` +exports[`astToES ast - 'john -sales' 1`] = ` Object { "bool": Object { "must": Array [ @@ -128,7 +128,7 @@ Object { } `; -exports[`astToEs ast - 'john group:(eng or "marketing org") -group:"kibana team" 1`] = ` +exports[`astToES ast - 'john group:(eng or "marketing org") -group:"kibana team" 1`] = ` Object { "bool": Object { "must": Array [ @@ -168,7 +168,7 @@ Object { } `; -exports[`astToEs ast - 'john group:(eng or es) -group:kibana' 1`] = ` +exports[`astToES ast - 'john group:(eng or es) -group:kibana' 1`] = ` Object { "bool": Object { "must": Array [ diff --git a/src/services/query/ast.js b/src/components/search_bar/query/ast.js similarity index 93% rename from src/services/query/ast.js rename to src/components/search_bar/query/ast.js index 15bc356a04fc..89fbe1d52487 100644 --- a/src/services/query/ast.js +++ b/src/components/search_bar/query/ast.js @@ -1,4 +1,4 @@ -import { isArray, isNil } from '../predicate'; +import { isArray, isNil } from '../../../services/predicate'; export const Match = Object.freeze({ MUST: 'must', @@ -68,9 +68,10 @@ const Is = Object.freeze({ * * This AST is immutable - every "mutating" operation returns a newly mutated AST. */ -export class _Ast { +export class _AST { + static create(clauses) { - return new _Ast(clauses); + return new _AST(clauses); } constructor(clauses = []) { @@ -141,7 +142,7 @@ export class _Ast { const existingClause = this.getOrFieldClause(field); if (!existingClause) { const newClause = must ? Field.must(field, [ value ]) : Field.mustNot(field, [ value ]); - return new _Ast([ ...this._clauses, newClause ]); + return new _AST([ ...this._clauses, newClause ]); } const clauses = this._clauses.map(clause => { if (clause === existingClause) { @@ -149,13 +150,13 @@ export class _Ast { } return clause; }); - return new _Ast(clauses); + return new _AST(clauses); } removeOrFieldValue(field, value) { const existingClause = this.getOrFieldClause(field, value); if (!existingClause) { - return new _Ast([ ...this._clauses ]); + return new _AST([ ...this._clauses ]); } const clauses = this._clauses.reduce((clauses, clause) => { if (clause !== existingClause) { @@ -169,14 +170,14 @@ export class _Ast { clauses.push({ ...clause, value: filteredValue }); return clauses; }, []); - return new _Ast(clauses); + return new _AST(clauses); } removeOrFieldClauses(field) { const clauses = this._clauses.filter(clause => { return !Field.isInstance(clause) || clause.field !== field || !isArray(clause.value); }); - return new _Ast(clauses); + return new _AST(clauses); } hasSimpleFieldClause(field, value = undefined) { @@ -199,17 +200,17 @@ export class _Ast { removeSimpleFieldValue(field, value) { const existingClause = this.getSimpleFieldClause(field, value); if (!existingClause) { - return new _Ast([ ...this._clauses ]); + return new _AST([ ...this._clauses ]); } const clauses = this._clauses.filter(clause => clause !== existingClause); - return new _Ast(clauses); + return new _AST(clauses); } removeSimpleFieldClauses(field) { const clauses = this._clauses.filter(clause => { return !Field.isInstance(clause) || clause.field !== field || isArray(clause.value); }); - return new _Ast(clauses); + return new _AST(clauses); } getIsClauses() { @@ -221,7 +222,7 @@ export class _Ast { } removeIsClause(flag) { - return new _Ast(this._clauses.filter(clause => !Is.isInstance(clause) || clause.flag !== flag)); + return new _AST(this._clauses.filter(clause => !Is.isInstance(clause) || clause.flag !== flag)); } /** @@ -279,14 +280,14 @@ export class _Ast { if (!added) { newClauses.push(newClause); } - return new _Ast(newClauses); + return new _AST(newClauses); } } -export const Ast = Object.freeze({ +export const AST = Object.freeze({ Match, Term, Field, Is, - create: (clauses) => new _Ast(clauses) + create: (clauses) => new _AST(clauses) }); diff --git a/src/services/query/ast_to_es.js b/src/components/search_bar/query/ast_to_es.js similarity index 93% rename from src/services/query/ast_to_es.js rename to src/components/search_bar/query/ast_to_es.js index 9fcb263db0dd..354e13e761db 100644 --- a/src/services/query/ast_to_es.js +++ b/src/components/search_bar/query/ast_to_es.js @@ -1,5 +1,5 @@ -import { Ast } from './ast'; -import { isArray } from '../predicate'; +import { AST } from './ast'; +import { isArray } from '../../../services/predicate'; export const _termValuesToQuery = (values, options) => { const body = { @@ -74,7 +74,7 @@ export const _isFlagToQuery = (flag, on) => { const collectTerms = (ast) => { return ast.getTermClauses().reduce((values, clause) => { - if (Ast.Match.isMustClause(clause)) { + if (AST.Match.isMustClause(clause)) { values.must.push(clause.value); } else { values.mustNot.push(clause.value); @@ -93,7 +93,7 @@ const collectFields = (ast) => { }; return ast.getFieldClauses().reduce((fields, clause) => { - if (Ast.Match.isMustClause(clause)) { + if (AST.Match.isMustClause(clause)) { if (isArray(clause.value)) { fieldArray(fields.must.or, clause.field).push(...clause.value); } else { @@ -113,7 +113,7 @@ const collectFields = (ast) => { }); }; -export const astToEs = (ast, options = {}) => { +export const astToES = (ast, options = {}) => { if (ast.clauses.length === 0) { return { match_all: {} }; @@ -141,7 +141,7 @@ export const astToEs = (ast, options = {}) => { return fieldValuesToQuery(field, fields.must.or[field], 'or'); })); must.push(...ast.getIsClauses().map(clause => { - return isFlagToQuery(clause.flag, Ast.Match.isMustClause(clause)); + return isFlagToQuery(clause.flag, AST.Match.isMustClause(clause)); })); const mustNot = []; diff --git a/src/components/search_bar/query/ast_to_es.test.js b/src/components/search_bar/query/ast_to_es.test.js new file mode 100644 index 000000000000..fde2aea9c8e3 --- /dev/null +++ b/src/components/search_bar/query/ast_to_es.test.js @@ -0,0 +1,69 @@ +import { astToES } from './ast_to_es'; +import { AST } from './ast'; + +describe('astToES', () => { + + test(`ast - ''`, () => { + const query = astToES(AST.create([])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - 'john -sales'`, () => { + const query = astToES(AST.create([ + AST.Term.must('john'), + AST.Term.mustNot('sales'), + ])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - '-group:es group:kibana -group:beats group:logstash'`, () => { + const query = astToES(AST.create([ + AST.Field.mustNot('group', 'es'), + AST.Field.must('group', 'kibana'), + AST.Field.mustNot('group', 'beats'), + AST.Field.must('group', 'logstash') + ])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - 'is:online group:kibana john'`, () => { + const query = astToES(AST.create([ + AST.Is.must('online'), + AST.Field.must('group', 'kibana'), + AST.Term.must('john') + ])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - 'john -doe is:online group:eng group:es -group:kibana -is:active'`, () => { + const query = astToES(AST.create([ + AST.Term.must('john'), + AST.Term.mustNot('doe'), + AST.Is.must('online'), + AST.Field.must('group', 'eng'), + AST.Field.must('group', 'es'), + AST.Field.mustNot('group', 'kibana'), + AST.Is.mustNot('active') + ])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - 'john group:(eng or es) -group:kibana'`, () => { + const query = astToES(AST.create([ + AST.Term.must('john'), + AST.Field.must('group', ['eng', 'es']), + AST.Field.mustNot('group', 'kibana') + ])); + expect(query).toMatchSnapshot(); + }); + + test(`ast - 'john group:(eng or "marketing org") -group:"kibana team"`, () => { + const query = astToES(AST.create([ + AST.Term.must('john'), + AST.Field.must('group', ['eng', 'marketing org']), + AST.Field.mustNot('group', 'kibana team') + ])); + expect(query).toMatchSnapshot(); + }); + +}); diff --git a/src/services/query/default_syntax.js b/src/components/search_bar/query/default_syntax.js similarity index 75% rename from src/services/query/default_syntax.js rename to src/components/search_bar/query/default_syntax.js index 482906fb47e6..b66d84fc374e 100644 --- a/src/services/query/default_syntax.js +++ b/src/components/search_bar/query/default_syntax.js @@ -1,5 +1,5 @@ -import { Ast } from './ast'; -import { isArray } from '../predicate'; +import { AST } from './ast'; +import { isArray } from '../../../services/predicate'; import peg from 'pegjs-inline-precompile'; // eslint-disable-line import/no-unresolved const unescapeValue = (value) => { @@ -12,7 +12,7 @@ const escapeValue = (value) => { const parser = peg` { - const { Ast, unescapeValue } = options; + const { AST, unescapeValue } = options; } Query @@ -32,19 +32,19 @@ Clause / TermClause TermClause - = space? "-" value:termValue { return Ast.Term.mustNot(value); } - / space? value:termValue { return Ast.Term.must(value); } + = space? "-" value:termValue { return AST.Term.mustNot(value); } + / space? value:termValue { return AST.Term.must(value); } IsClause - = space? "-" value:IsValue { return Ast.Is.mustNot(value); } - / space? value:IsValue { return Ast.Is.must(value); } + = space? "-" value:IsValue { return AST.Is.mustNot(value); } + / space? value:IsValue { return AST.Is.must(value); } IsValue = "is:" value:value { return value; } FieldClause - = space? "-" fv:FieldAndValue { return Ast.Field.mustNot(fv.field, fv.value); } - / space? fv:FieldAndValue { return Ast.Field.must(fv.field, fv.value); } + = space? "-" fv:FieldAndValue { return AST.Field.mustNot(fv.field, fv.value); } + / space? fv:FieldAndValue { return AST.Field.must(fv.field, fv.value); } FieldAndValue = field:fieldName ":" value:fieldValue { return {field, value}; } @@ -105,22 +105,22 @@ const printValue = (value) => { export const defaultSyntax = Object.freeze({ parse: (query) => { - const clauses = parser.parse(query, { Ast, unescapeValue }); - return Ast.create(clauses); + const clauses = parser.parse(query, { AST, unescapeValue }); + return AST.create(clauses); }, print: (ast) => { return ast.clauses.reduce((text, clause) => { - const prefix = Ast.Match.isMustClause(clause) ? '' : '-'; + const prefix = AST.Match.isMustClause(clause) ? '' : '-'; switch (clause.type) { - case Ast.Field.TYPE: + case AST.Field.TYPE: if (isArray(clause.value)) { return `${text} ${prefix}${escapeValue(clause.field)}:(${clause.value.map(val => printValue(val)).join(' or ')})`; } return `${text} ${prefix}${escapeValue(clause.field)}:${printValue(clause.value)}`; - case Ast.Is.TYPE: + case AST.Is.TYPE: return `${text} ${prefix}is:${escapeValue(clause.flag)}`; - case Ast.Term.TYPE: + case AST.Term.TYPE: return `${text} ${prefix}${printValue(clause.value)}`; default: return text; diff --git a/src/services/query/default_syntax.test.js b/src/components/search_bar/query/default_syntax.test.js similarity index 73% rename from src/services/query/default_syntax.test.js rename to src/components/search_bar/query/default_syntax.test.js index e018a52cc550..c0c0a1f35378 100644 --- a/src/services/query/default_syntax.test.js +++ b/src/components/search_bar/query/default_syntax.test.js @@ -1,5 +1,5 @@ import { defaultSyntax } from './default_syntax'; -import { Ast } from './ast'; +import { AST } from './ast'; describe('defaultSyntax', () => { @@ -25,20 +25,20 @@ describe('defaultSyntax', () => { let clause = ast.getTermClause('-'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('-'); clause = ast.getTermClause(':'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.value).toBe(':'); clause = ast.getTermClause('\\'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('\\'); const printedQuery = defaultSyntax.print(ast); @@ -55,8 +55,8 @@ describe('defaultSyntax', () => { const clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); @@ -74,8 +74,8 @@ describe('defaultSyntax', () => { const clause = ast.getSimpleFieldClause('n:ame', 'jo:hn'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('n:ame'); expect(clause.value).toBe('jo:hn'); @@ -93,15 +93,15 @@ describe('defaultSyntax', () => { let clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); clause = ast.getSimpleFieldClause('age', '6'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('6'); @@ -119,22 +119,22 @@ describe('defaultSyntax', () => { let clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); clause = ast.getSimpleFieldClause('age', '6'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('6'); clause = ast.getSimpleFieldClause('age', '5'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('5'); @@ -152,22 +152,22 @@ describe('defaultSyntax', () => { let clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); clause = ast.getSimpleFieldClause('age', '6'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('6'); clause = ast.getSimpleFieldClause('age', '5'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.field).toBe('age'); expect(clause.value).toBe('5'); @@ -185,14 +185,14 @@ describe('defaultSyntax', () => { let clause = ast.getTermClause('foo'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('foo'); clause = ast.getTermClause('bar'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('bar'); const printedQuery = defaultSyntax.print(ast); @@ -209,14 +209,14 @@ describe('defaultSyntax', () => { let clause = ast.getTermClause('foo'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('foo'); clause = ast.getTermClause('bar'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.value).toBe('bar'); const printedQuery = defaultSyntax.print(ast); @@ -233,34 +233,34 @@ describe('defaultSyntax', () => { let clause = ast.getTermClause('foo'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('foo'); clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); clause = ast.getTermClause('bar'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.value).toBe('bar'); clause = ast.getSimpleFieldClause('age', '5'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('5'); clause = ast.getSimpleFieldClause('name', 'joe'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('joe'); @@ -278,47 +278,47 @@ describe('defaultSyntax', () => { let clause = ast.getTermClause('foo'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('foo'); clause = ast.getSimpleFieldClause('name', 'john'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.field).toBe('name'); expect(clause.value).toBe('john'); clause = ast.getTermClause('bar'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.value).toBe('bar'); clause = ast.getSimpleFieldClause('age', '5'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('age'); expect(clause.value).toBe('5'); clause = ast.getSimpleFieldClause('name', 'joe'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('name'); expect(clause.value).toBe('joe'); clause = ast.getIsClause('open'); expect(clause).toBeDefined(); - expect(Ast.Is.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Is.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.flag).toBe('open'); clause = ast.getIsClause('liberal'); expect(clause).toBeDefined(); - expect(Ast.Is.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Is.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.flag).toBe('liberal'); const printedQuery = defaultSyntax.print(ast); @@ -335,8 +335,8 @@ describe('defaultSyntax', () => { const clause = ast.getTermClause('foo bar'); expect(clause).toBeDefined(); - expect(Ast.Term.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Term.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.value).toBe('foo bar'); const printedQuery = defaultSyntax.print(ast); @@ -353,8 +353,8 @@ describe('defaultSyntax', () => { const clause = ast.getSimpleFieldClause('field', 'foo bar'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('field'); expect(clause.value).toBe('foo bar'); @@ -372,8 +372,8 @@ describe('defaultSyntax', () => { const clause = ast.getOrFieldClause('field'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('field'); expect(clause.value).toHaveLength(2); expect(clause.value).toContain('foo'); @@ -393,8 +393,8 @@ describe('defaultSyntax', () => { let clause = ast.getOrFieldClause('field1'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('field1'); expect(clause.value).toHaveLength(2); expect(clause.value).toContain('foo'); @@ -402,8 +402,8 @@ describe('defaultSyntax', () => { clause = ast.getSimpleFieldClause('field2'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(false); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(false); expect(clause.field).toBe('field2'); expect(clause.value).toBe('baz'); @@ -421,8 +421,8 @@ describe('defaultSyntax', () => { const clause = ast.getSimpleFieldClause('f'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('f'); expect(clause.value).toBe('this is a relaxed phrase'); @@ -440,8 +440,8 @@ describe('defaultSyntax', () => { const clause = ast.getOrFieldClause('f'); expect(clause).toBeDefined(); - expect(Ast.Field.isInstance(clause)).toBe(true); - expect(Ast.Match.isMustClause(clause)).toBe(true); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); expect(clause.field).toBe('f'); expect(clause.value).toHaveLength(1); expect(clause.value).toContain('foo'); diff --git a/src/services/query/execute_ast.js b/src/components/search_bar/query/execute_ast.js similarity index 92% rename from src/services/query/execute_ast.js rename to src/components/search_bar/query/execute_ast.js index 60cbbeae1c0f..f825f40c73c3 100644 --- a/src/services/query/execute_ast.js +++ b/src/components/search_bar/query/execute_ast.js @@ -1,20 +1,20 @@ import { get } from 'lodash'; -import { isString, isArray } from '../predicate'; +import { isString, isArray } from '../../../services/predicate'; import { must } from './must'; import { mustNot } from './must_not'; -import { Ast } from './ast'; +import { AST } from './ast'; const EXPLAIN_FIELD = '__explain'; const matchers = { - [Ast.Match.MUST]: must, - [Ast.Match.MUST_NOT]: mustNot + [AST.Match.MUST]: must, + [AST.Match.MUST_NOT]: mustNot }; const defaultIsClauseMatcher = (record, clause, explain) => { const { type, flag, match } = clause; const value = get(record, clause.flag); - const must = Ast.Match.isMustClause(clause); + const must = AST.Match.isMustClause(clause); const hit = !!value === must; if (explain && hit) { explain.push({ hit, type, flag, match }); @@ -57,7 +57,7 @@ const termClauseMatcher = (record, fields, clauses = [], explain) => { if (!matcher) { // unknown matcher return true; } - if (Ast.Match.isMustClause(clause)) { + if (AST.Match.isMustClause(clause)) { return fields.some(field => { const recordValue = get(record, field); const hit = matcher(recordValue, value); diff --git a/src/services/query/execute_ast.test.js b/src/components/search_bar/query/execute_ast.test.js similarity index 72% rename from src/services/query/execute_ast.test.js rename to src/components/search_bar/query/execute_ast.test.js index 0541481bef63..3ea911775cbb 100644 --- a/src/services/query/execute_ast.test.js +++ b/src/components/search_bar/query/execute_ast.test.js @@ -1,6 +1,6 @@ -import { Ast } from './ast'; +import { AST } from './ast'; import { executeAst } from './execute_ast'; -import { Random } from '../random'; +import { Random } from '../../../services/random'; const random = new Random(); @@ -11,8 +11,8 @@ describe('execute ast', () => { { name: 'john doe' }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'john') + const result = executeAst(AST.create([ + AST.Field.must('name', 'john') ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('john doe'); @@ -23,8 +23,8 @@ describe('execute ast', () => { { name: 'john' }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.mustNot('name', 'john') + const result = executeAst(AST.create([ + AST.Field.mustNot('name', 'john') ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('joe'); @@ -35,20 +35,20 @@ describe('execute ast', () => { { name: 'john' }, { name: 'joe' } ]; - let result = executeAst(Ast.create([ - Ast.Field.must('name', ['john', 'doe']) + let result = executeAst(AST.create([ + AST.Field.must('name', ['john', 'doe']) ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('john'); - result = executeAst(Ast.create([ - Ast.Field.must('name', ['joe', 'doe']) + result = executeAst(AST.create([ + AST.Field.must('name', ['joe', 'doe']) ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('joe'); - result = executeAst(Ast.create([ - Ast.Field.must('name', ['foo', 'bar']) + result = executeAst(AST.create([ + AST.Field.must('name', ['foo', 'bar']) ]), items); expect(result).toHaveLength(0); }); @@ -58,8 +58,8 @@ describe('execute ast', () => { { name: 'john' }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'foo') + const result = executeAst(AST.create([ + AST.Field.must('name', 'foo') ]), items); expect(result).toHaveLength(0); }); @@ -69,9 +69,9 @@ describe('execute ast', () => { { name: 'john' }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'john'), - Ast.Field.must('name', 'joe') + const result = executeAst(AST.create([ + AST.Field.must('name', 'john'), + AST.Field.must('name', 'joe') ]), items); expect(result).toHaveLength(0); }); @@ -81,9 +81,9 @@ describe('execute ast', () => { { name: 'john', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'foo'), - Ast.Field.must('age', '7') + const result = executeAst(AST.create([ + AST.Field.must('name', 'foo'), + AST.Field.must('age', '7') ]), items); expect(result).toHaveLength(0); }); @@ -93,9 +93,9 @@ describe('execute ast', () => { { name: 'john', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'john'), - Ast.Field.must('age', '5') + const result = executeAst(AST.create([ + AST.Field.must('name', 'john'), + AST.Field.must('age', '5') ]), items); expect(result).toHaveLength(1); }); @@ -105,9 +105,9 @@ describe('execute ast', () => { { name: 'john', description: 'doe', age: 5 }, { name: 'joe' } ]; - const value = random.oneOf(['john', 'doe']); - const result = executeAst(Ast.create([ - Ast.Term.must(value) + const value = random.oneOf('john', 'doe'); + const result = executeAst(AST.create([ + AST.Term.must(value) ]), items); expect(result).toHaveLength(1); }); @@ -119,8 +119,8 @@ describe('execute ast', () => { { name: 'john', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Term.must('5') + const result = executeAst(AST.create([ + AST.Term.must('5') ]), items); expect(result).toHaveLength(0); }); @@ -130,8 +130,8 @@ describe('execute ast', () => { { name: 'john', description: 'doe', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Term.must('john') + const result = executeAst(AST.create([ + AST.Term.must('john') ]), items, { defaultFields: [ 'name' ] }); expect(result).toHaveLength(1); }); @@ -141,8 +141,8 @@ describe('execute ast', () => { { name: 'john', description: 'doe', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Term.must('doe') + const result = executeAst(AST.create([ + AST.Term.must('doe') ]), items, { defaultFields: [ 'name' ] }); expect(result).toHaveLength(0); }); @@ -152,8 +152,8 @@ describe('execute ast', () => { { name: 'john', description: 'doe', age: 5 }, { name: 'joe' } ]; - const result = executeAst(Ast.create([ - Ast.Term.mustNot('john') + const result = executeAst(AST.create([ + AST.Term.mustNot('john') ]), items, { defaultFields: [ 'name' ] }); expect(result).toHaveLength(1); expect(result[0].name).toBe('joe'); @@ -164,8 +164,8 @@ describe('execute ast', () => { { name: 'john', open: true }, { name: 'joe', open: false } ]; - const result = executeAst(Ast.create([ - Ast.Is.must('open') + const result = executeAst(AST.create([ + AST.Is.must('open') ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('john'); @@ -176,8 +176,8 @@ describe('execute ast', () => { { name: 'john', open: true }, { name: 'joe', open: false } ]; - const result = executeAst(Ast.create([ - Ast.Is.mustNot('open') + const result = executeAst(AST.create([ + AST.Is.mustNot('open') ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('joe'); @@ -188,8 +188,8 @@ describe('execute ast', () => { { name: 'john', open: true }, { name: 'joe', open: false } ]; - const result = executeAst(Ast.create([ - Ast.Is.must('closed') + const result = executeAst(AST.create([ + AST.Is.must('closed') ]), items); expect(result).toHaveLength(0); }); @@ -199,8 +199,8 @@ describe('execute ast', () => { { name: 'john', open: true }, { name: 'joe', open: false } ]; - const result = executeAst(Ast.create([ - Ast.Is.mustNot('closed') + const result = executeAst(AST.create([ + AST.Is.mustNot('closed') ]), items); expect(result).toHaveLength(2); }); @@ -212,11 +212,11 @@ describe('execute ast', () => { { text: 'foo bar', age: 7 }, { text: 'bar', age: 7 }, ]; - const result = executeAst(Ast.create([ - Ast.Is.mustNot('open'), - Ast.Field.must('age', '7'), - Ast.Term.must('bar'), - Ast.Term.mustNot('foo') + const result = executeAst(AST.create([ + AST.Is.mustNot('open'), + AST.Field.must('age', '7'), + AST.Term.must('bar'), + AST.Term.mustNot('foo') ]), items); expect(result).toHaveLength(1); expect(result[0].text).toBe('bar'); @@ -230,8 +230,8 @@ describe('execute ast', () => { { text: 'foo bar', age: 7 }, { text: 'bar', age: 7 }, ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', 'John Doe'), + const result = executeAst(AST.create([ + AST.Field.must('name', 'John Doe'), ]), items); expect(result).toHaveLength(1); expect(result[0].name).toBe('john doe'); @@ -244,8 +244,8 @@ describe('execute ast', () => { { name: 'foo bar', age: 7 }, { name: 'bar', age: 7 }, ]; - const result = executeAst(Ast.create([ - Ast.Field.must('name', [ 'john', 'bar' ]), + const result = executeAst(AST.create([ + AST.Field.must('name', [ 'john', 'bar' ]), ]), items); expect(result).toHaveLength(3); const names = result.map(item => item.name); diff --git a/src/services/query/index.js b/src/components/search_bar/query/index.js similarity index 53% rename from src/services/query/index.js rename to src/components/search_bar/query/index.js index f6ddbd44ea22..60e75e781d8a 100644 --- a/src/services/query/index.js +++ b/src/components/search_bar/query/index.js @@ -1,2 +1,2 @@ export { Query } from './query'; -export { Ast } from './ast'; +export { AST } from './ast'; diff --git a/src/services/query/must.js b/src/components/search_bar/query/must.js similarity index 95% rename from src/services/query/must.js rename to src/components/search_bar/query/must.js index 6d0db460a63a..7c02950cc90c 100644 --- a/src/services/query/must.js +++ b/src/components/search_bar/query/must.js @@ -1,7 +1,7 @@ import { isArray, isBoolean, isNumber, isString -} from '../predicate'; +} from '../../../services/predicate'; import moment from 'moment/moment'; const defaultOptions = { diff --git a/src/services/query/must_not.js b/src/components/search_bar/query/must_not.js similarity index 95% rename from src/services/query/must_not.js rename to src/components/search_bar/query/must_not.js index 1f37ee18a9ce..eadd7e410b5c 100644 --- a/src/services/query/must_not.js +++ b/src/components/search_bar/query/must_not.js @@ -1,7 +1,7 @@ import { isArray, isBoolean, isNumber, isString -} from '../predicate'; +} from '../../../services/predicate'; import moment from 'moment/moment'; const defaultOptions = { diff --git a/src/services/query/query.js b/src/components/search_bar/query/query.js similarity index 92% rename from src/services/query/query.js rename to src/components/search_bar/query/query.js index 4da9733b464a..6c358dede704 100644 --- a/src/services/query/query.js +++ b/src/components/search_bar/query/query.js @@ -1,8 +1,8 @@ import { defaultSyntax } from './default_syntax'; import { executeAst } from './execute_ast'; -import { isNil, isString } from '../predicate'; -import { astToEs } from './ast_to_es'; -import { Ast } from './ast'; +import { isNil, isString } from '../../../services/predicate'; +import { astToES } from './ast_to_es'; +import { AST } from './ast'; /** * This is the consumer interface for the query - it's effectively a wrapper construct around @@ -10,26 +10,27 @@ import { Ast } from './ast'; * It is immutable - all mutating operations return a new (mutated) query instance. */ export class Query { + static parse(text, syntax = defaultSyntax) { return new Query(syntax.parse(text), syntax, text); } static isMust(clause) { - return Ast.Match.isMustClause(clause); + return AST.Match.isMustClause(clause); } static MATCH_ALL = Query.parse(''); static isTerm(clause) { - return Ast.Term.isInstance(clause); + return AST.Term.isInstance(clause); } static isIs(clause) { - return Ast.Is.isInstance(clause); + return AST.Is.isInstance(clause); } static isField(clause) { - return Ast.Field.isInstance(clause); + return AST.Field.isInstance(clause); } constructor(ast, syntax = defaultSyntax, text = undefined) { @@ -93,12 +94,12 @@ export class Query { } addMustIsClause(flag) { - const ast = this.ast.addClause(Ast.Is.must(flag)); + const ast = this.ast.addClause(AST.Is.must(flag)); return new Query(ast, this.syntax); } addMustNotIsClause(flag) { - const ast = this.ast.addClause(Ast.Is.mustNot(flag)); + const ast = this.ast.addClause(AST.Is.mustNot(flag)); return new Query(ast, this.syntax); } @@ -162,6 +163,7 @@ export class Query { */ static toESQuery(query, options = {}) { const q = isString(query) ? Query.parse(query) : query; - return astToEs(q.ast, options); + return astToES(q.ast, options); } + } diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js index 24f29684d612..4bcd92666564 100644 --- a/src/components/search_bar/search_bar.js +++ b/src/components/search_bar/search_bar.js @@ -1,5 +1,4 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; import { isString } from '../../services/predicate'; import { EuiFlexGroup } from '../flex/flex_group'; import { @@ -10,7 +9,8 @@ import { EuiSearchFilters, SearchFiltersFiltersType } from './search_filters'; -import { Query } from '../../services/query'; +import PropTypes from 'prop-types'; +import { Query } from './query'; import { EuiFlexItem } from '../flex/flex_item'; export const QueryType = PropTypes.oneOfType([ PropTypes.instanceOf(Query), PropTypes.string ]); @@ -57,7 +57,8 @@ const resolveQuery = (query) => { return isString(query) ? Query.parse(query) : query; }; -export class EuiSearchBar extends Component { +export class EuiSearchBar extends React.Component { + static propTypes = SearchBoxConfigPropTypes; constructor(props) { diff --git a/src/components/search_bar/search_bar.test.js b/src/components/search_bar/search_bar.test.js index 0726f52c8967..2827f0a42dac 100644 --- a/src/components/search_bar/search_bar.test.js +++ b/src/components/search_bar/search_bar.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { EuiSearchBar } from './search_bar'; describe('SearchBar', () => { diff --git a/src/components/search_bar/search_box.js b/src/components/search_bar/search_box.js index 0e39fe2399df..4793255435ea 100644 --- a/src/components/search_bar/search_box.js +++ b/src/components/search_bar/search_box.js @@ -1,13 +1,14 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; import { EuiFieldSearch } from '../form/field_search/field_search'; +import PropTypes from 'prop-types'; export const SearchBoxConfigPropTypes = { placeholder: PropTypes.string, incremental: PropTypes.bool }; -export class EuiSearchBox extends Component { +export class EuiSearchBox extends React.Component { + static propTypes = { query: PropTypes.string.isRequired, onSearch: PropTypes.func.isRequired, // (queryText) => void diff --git a/src/components/search_bar/search_box.test.js b/src/components/search_bar/search_box.test.js index a49991981537..fca73f1fb99f 100644 --- a/src/components/search_bar/search_box.test.js +++ b/src/components/search_bar/search_box.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { EuiSearchBox } from './search_box'; describe('EuiSearchBox', () => { diff --git a/src/components/search_bar/search_filters.js b/src/components/search_bar/search_filters.js index 91984c51ddfe..c104cac40aa6 100644 --- a/src/components/search_bar/search_filters.js +++ b/src/components/search_bar/search_filters.js @@ -1,12 +1,13 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { createFilter, FilterConfigType } from './filters'; -import { Query } from '../../services/query'; +import { Query } from './query'; import { EuiFilterGroup } from '../../components/filter_group'; export const SearchFiltersFiltersType = PropTypes.arrayOf(FilterConfigType); -export class EuiSearchFilters extends Component { +export class EuiSearchFilters extends React.Component { + static propTypes = { query: PropTypes.instanceOf(Query).isRequired, onChange: PropTypes.func.isRequired, diff --git a/src/components/search_bar/search_filters.test.js b/src/components/search_bar/search_filters.test.js index 5ce460610825..b3aa186346ad 100644 --- a/src/components/search_bar/search_filters.test.js +++ b/src/components/search_bar/search_filters.test.js @@ -1,8 +1,8 @@ import React from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { EuiSearchFilters } from './search_filters'; -import { Query } from '../../services/query'; +import { Query } from './query'; describe('EuiSearchFilters', () => { diff --git a/src/components/table_of_records/collapsed_record_actions.test.js b/src/components/table_of_records/collapsed_record_actions.test.js index 5d424cb536b1..db36e1da597b 100644 --- a/src/components/table_of_records/collapsed_record_actions.test.js +++ b/src/components/table_of_records/collapsed_record_actions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { CollapsedRecordActions } from './collapsed_record_actions'; describe('CollapsedRecordActions', () => { diff --git a/src/components/table_of_records/custom_record_action.test.js b/src/components/table_of_records/custom_record_action.test.js index bf64729cc6cc..4e2da17f5f64 100644 --- a/src/components/table_of_records/custom_record_action.test.js +++ b/src/components/table_of_records/custom_record_action.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { CustomRecordAction } from './custom_record_action'; describe('CustomRecordAction', () => { diff --git a/src/components/table_of_records/default_record_action.test.js b/src/components/table_of_records/default_record_action.test.js index ec625d643dd5..58a100b7f3f4 100644 --- a/src/components/table_of_records/default_record_action.test.js +++ b/src/components/table_of_records/default_record_action.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { DefaultRecordAction } from './default_record_action'; import { Random } from '../../services/random'; @@ -13,7 +13,7 @@ describe('DefaultRecordAction', () => { action: { name: 'action1', description: 'action 1', - type: random.oneOf([undefined, 'button', 'foobar']), + type: random.oneOf(undefined, 'button', 'foobar'), onClick: () => {} }, enabled: true, diff --git a/src/components/table_of_records/expanded_record_actions.test.js b/src/components/table_of_records/expanded_record_actions.test.js index d3e6af9a653a..c4a337b43d78 100644 --- a/src/components/table_of_records/expanded_record_actions.test.js +++ b/src/components/table_of_records/expanded_record_actions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { ExpandedRecordActions } from './expanded_record_actions'; describe('ExpandedRecordActions', () => { diff --git a/src/components/table_of_records/pagination_bar.test.js b/src/components/table_of_records/pagination_bar.test.js index 004d00587cf9..bdf6021f5a92 100644 --- a/src/components/table_of_records/pagination_bar.test.js +++ b/src/components/table_of_records/pagination_bar.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { shallow } from 'enzyme/build/index'; import { PaginationBar } from './pagination_bar'; describe('PaginationBar', () => { diff --git a/src/services/index.js b/src/services/index.js index f95bee4f9ea9..9a6b0e6f7348 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -36,15 +36,6 @@ export { checkHrefAndOnClick, } from './prop_types'; -export { - Ast, - Query, -} from './query'; - -export { - Random -} from './random'; - export { getSecureRelForTarget, } from './security'; @@ -61,3 +52,6 @@ export { noOverflowPlacement, } from './overflow'; +export { + Random +} from './random'; diff --git a/src/services/query/ast_to_es.test.js b/src/services/query/ast_to_es.test.js deleted file mode 100644 index 61c4f3a8995e..000000000000 --- a/src/services/query/ast_to_es.test.js +++ /dev/null @@ -1,67 +0,0 @@ -import { astToEs } from './ast_to_es'; -import { Ast } from './ast'; - -describe('astToEs', () => { - test(`ast - ''`, () => { - const query = astToEs(Ast.create([])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - 'john -sales'`, () => { - const query = astToEs(Ast.create([ - Ast.Term.must('john'), - Ast.Term.mustNot('sales'), - ])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - '-group:es group:kibana -group:beats group:logstash'`, () => { - const query = astToEs(Ast.create([ - Ast.Field.mustNot('group', 'es'), - Ast.Field.must('group', 'kibana'), - Ast.Field.mustNot('group', 'beats'), - Ast.Field.must('group', 'logstash') - ])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - 'is:online group:kibana john'`, () => { - const query = astToEs(Ast.create([ - Ast.Is.must('online'), - Ast.Field.must('group', 'kibana'), - Ast.Term.must('john') - ])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - 'john -doe is:online group:eng group:es -group:kibana -is:active'`, () => { - const query = astToEs(Ast.create([ - Ast.Term.must('john'), - Ast.Term.mustNot('doe'), - Ast.Is.must('online'), - Ast.Field.must('group', 'eng'), - Ast.Field.must('group', 'es'), - Ast.Field.mustNot('group', 'kibana'), - Ast.Is.mustNot('active') - ])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - 'john group:(eng or es) -group:kibana'`, () => { - const query = astToEs(Ast.create([ - Ast.Term.must('john'), - Ast.Field.must('group', ['eng', 'es']), - Ast.Field.mustNot('group', 'kibana') - ])); - expect(query).toMatchSnapshot(); - }); - - test(`ast - 'john group:(eng or "marketing org") -group:"kibana team"`, () => { - const query = astToEs(Ast.create([ - Ast.Term.must('john'), - Ast.Field.must('group', ['eng', 'marketing org']), - Ast.Field.mustNot('group', 'kibana team') - ])); - expect(query).toMatchSnapshot(); - }); -}); diff --git a/src/services/random.js b/src/services/random.js index 8e85384a09b7..03294e35e35b 100644 --- a/src/services/random.js +++ b/src/services/random.js @@ -27,7 +27,7 @@ export class Random { return min + delta; } - oneOf(values) { + oneOf(...values) { return values[Math.floor(this._rand() * values.length)]; } @@ -35,7 +35,7 @@ export class Random { const count = this.integer({ min: 0, max: values.length, ...options }); const copy = [...values]; return times(count, () => { - const value = this.oneOf(copy); + const value = this.oneOf(...copy); copy.splice(copy.indexOf(value), 1); return value; });