diff --git a/CHANGELOG.md b/CHANGELOG.md index 003e2a0cef6..cf3ae6026f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ **Bug fixes** - Fixed an issue in `EuiTooltip` because IE1 didn't support `document.contains()` ([#1190](https://github.com/elastic/eui/pull/1190)) +- Fixed some issues around parsing string values in EuiSearchBar / EuiQuery ([#1189](https://github.com/elastic/eui/pull/1189)) ## [`4.0.0`](https://github.com/elastic/eui/tree/v4.0.0) diff --git a/src/components/search_bar/query/default_syntax.js b/src/components/search_bar/query/default_syntax.js index 7d0ce661048..3bced52e84d 100644 --- a/src/components/search_bar/query/default_syntax.js +++ b/src/components/search_bar/query/default_syntax.js @@ -107,11 +107,11 @@ containsOrValues )* space? ")" { return [ head, ...tail ]; } rangeValue - = number + = numberWord / date containsValue - = number + = numberWord / date / booleanWord / word @@ -152,6 +152,11 @@ boolean number = [\\-]?[0-9]+("."[0-9]+)* { return Exp.number(text(), location()); } +// only match numbers followed by whitespace or end of input +numberWord + = num:number &space { return num; } + / num:number !. { return num; } + date = "'" expression:((!"'" .)+ { return text(); }) "'" { return Exp.date(expression, location()); @@ -210,14 +215,20 @@ const resolveFieldValue = (field, valueExpression, ctx) => { if (isArray(valueExpression)) { return valueExpression.map(exp => resolveFieldValue(field, exp, ctx)); } - const { type, expression, location } = valueExpression; + const { location } = valueExpression; + let { type, expression } = valueExpression; if (schema && !schema.fields[field] && schema.strict) { error(`Unknown field \`${field}\``, location); } const schemaField = schema && schema.fields[field]; if (schemaField && schemaField.type !== type && schema.strict) { - const valueDesc = schemaField.valueDescription || `a ${schemaField.type} value`; - error(`Expected ${valueDesc} for field \`${field}\`, but found \`${expression}\``, location); + if (schemaField.type === 'string') { + expression = valueExpression.expression = expression.toString(); + type = valueExpression.type = 'string'; + } else { + const valueDesc = schemaField.valueDescription || `a ${schemaField.type} value`; + error(`Expected ${valueDesc} for field \`${field}\`, but found \`${expression}\``, location); + } } switch(type) { diff --git a/src/components/search_bar/query/default_syntax.test.js b/src/components/search_bar/query/default_syntax.test.js index febf66d133c..9805d5f81a2 100644 --- a/src/components/search_bar/query/default_syntax.test.js +++ b/src/components/search_bar/query/default_syntax.test.js @@ -777,6 +777,36 @@ describe('defaultSyntax', () => { expect(printedQuery).toBe(query); }); + test('number type', () => { + const query = 'count:15'; + const ast = defaultSyntax.parse(query); + + expect(ast).toBeDefined(); + expect(ast.clauses).toHaveLength(1); + + const clause = ast.getSimpleFieldClause('count'); + expect(clause).toBeDefined(); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); + expect(clause.field).toBe('count'); + expect(clause.value).toBe(15); + }); + + test('string that starts with a number', () => { + const query = 'count:15n'; + const ast = defaultSyntax.parse(query); + + expect(ast).toBeDefined(); + expect(ast.clauses).toHaveLength(1); + + const clause = ast.getSimpleFieldClause('count'); + expect(clause).toBeDefined(); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); + expect(clause.field).toBe('count'); + expect(clause.value).toBe('15n'); + }); + test('strict schema - flags - listed', () => { const query = `is:active`; @@ -933,4 +963,26 @@ describe('defaultSyntax', () => { }).toThrow('Unknown field `name`'); }); + test('strict schema - string fields have their values coerced', () => { + const query = `name:15`; + const schema = { + strict: true, + fields: { + name: { + type: 'string' + } + } + }; + const ast = defaultSyntax.parse(query, { schema }); + + expect(ast).toBeDefined(); + expect(ast.clauses).toHaveLength(1); + + const clause = ast.getSimpleFieldClause('name'); + expect(clause).toBeDefined(); + expect(AST.Field.isInstance(clause)).toBe(true); + expect(AST.Match.isMustClause(clause)).toBe(true); + expect(clause.field).toBe('name'); + expect(clause.value).toBe('15'); + }); });