diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
index b168602b64927..e139b326b7500 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
@@ -7,5 +7,5 @@
Signature:
```typescript
-QueryStringInput: React.FC>
+QueryStringInput: React.FC>
```
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 340a378b946ec..c8110dbfd0041 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -51,7 +51,6 @@ import { ErrorToastOptions } from 'src/core/public/notifications';
import { EuiButtonEmptyProps } from '@elastic/eui';
import { EuiComboBoxProps } from '@elastic/eui';
import { EuiConfirmModalProps } from '@elastic/eui';
-import { EuiFieldText } from '@elastic/eui';
import { EuiGlobalToastListToast } from '@elastic/eui';
import { ExclusiveUnion } from '@elastic/eui';
import { ExistsParams } from 'elasticsearch';
@@ -1482,7 +1481,7 @@ export interface QueryState {
// Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
-export const QueryStringInput: React.FC>;
+export const QueryStringInput: React.FC>;
// @public (undocumented)
export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField;
diff --git a/src/plugins/data/public/ui/query_string_input/_query_bar.scss b/src/plugins/data/public/ui/query_string_input/_query_bar.scss
index f95fe748dfdae..007be9da63e49 100644
--- a/src/plugins/data/public/ui/query_string_input/_query_bar.scss
+++ b/src/plugins/data/public/ui/query_string_input/_query_bar.scss
@@ -1,3 +1,41 @@
+.kbnQueryBar__wrap {
+ max-width: 100%;
+ z-index: $euiZContentMenu;
+}
+
+// Uses the append style, but no bordering
+.kqlQueryBar__languageSwitcherButton {
+ border-right: none !important;
+}
+
+.kbnQueryBar__textarea {
+ z-index: $euiZContentMenu;
+ resize: none !important; // When in the group, it will autosize
+ height: $euiSizeXXL;
+ // Unlike most inputs within layout control groups, the text area still needs a border.
+ // These adjusts help it sit above the control groups shadow to line up correctly.
+ padding-top: $euiSizeS + 3px !important;
+ transform: translateY(-2px);
+ padding: $euiSizeS - 1px;
+
+ &:not(:focus) {
+ @include euiYScrollWithShadows;
+ white-space: nowrap;
+ overflow-y: hidden;
+ overflow-x: hidden;
+ border: none;
+ box-shadow: none;
+ }
+
+ // When focused, let it scroll
+ &:focus {
+ overflow-x: auto;
+ overflow-y: auto;
+ width: calc(100% + 1px); // To overtake the group's fake border
+ white-space: normal;
+ }
+}
+
@include euiBreakpoint('xs', 's') {
.kbnQueryBar--withDatePicker {
> :first-child {
@@ -16,5 +54,11 @@
// sass-lint:disable-block no-important
flex-grow: 0 !important;
flex-basis: auto !important;
+ margin-right: -$euiSizeXS !important;
+
+ &.kbnQueryBar__datePickerWrapper-isHidden {
+ width: 0;
+ overflow: hidden;
+ }
}
}
diff --git a/src/plugins/data/public/ui/query_string_input/language_switcher.tsx b/src/plugins/data/public/ui/query_string_input/language_switcher.tsx
index a4c93d0044c9a..4d51b173f6743 100644
--- a/src/plugins/data/public/ui/query_string_input/language_switcher.tsx
+++ b/src/plugins/data/public/ui/query_string_input/language_switcher.tsx
@@ -60,7 +60,7 @@ export function QueryLanguageSwitcher(props: Props) {
setIsPopoverOpen(!isPopoverOpen)}
- className="euiFormControlLayout__append"
+ className="euiFormControlLayout__append kqlQueryBar__languageSwitcherButton"
data-test-subj={'switchQueryLanguageButton'}
>
{props.language === 'lucene' ? luceneLabel : kqlLabel}
diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
index 4b0dc579c39ce..86bf30ba0e374 100644
--- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx
@@ -69,6 +69,7 @@ interface Props {
export function QueryBarTopRow(props: Props) {
const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false);
+ const [isQueryInputFocused, setIsQueryInputFocused] = useState(false);
const kibana = useKibana();
const { uiSettings, notifications, storage, appName, docLinks } = kibana.services;
@@ -107,6 +108,10 @@ export function QueryBarTopRow(props: Props) {
});
}
+ function onChangeQueryInputFocus(isFocused: boolean) {
+ setIsQueryInputFocused(isFocused);
+ }
+
function onTimeChange({
start,
end,
@@ -182,6 +187,7 @@ export function QueryBarTopRow(props: Props) {
query={props.query!}
screenTitle={props.screenTitle}
onChange={onQueryChange}
+ onChangeQueryInputFocus={onChangeQueryInputFocus}
onSubmit={onInputSubmit}
persistedLog={persistedLog}
dataTestSubj={props.dataTestSubj}
@@ -268,8 +274,12 @@ export function QueryBarTopRow(props: Props) {
};
});
+ const wrapperClasses = classNames('kbnQueryBar__datePickerWrapper', {
+ 'kbnQueryBar__datePickerWrapper-isHidden': isQueryInputFocused,
+ });
+
return (
-
+
);
diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx
index 755716aee8f48..0397c34d0c2b8 100644
--- a/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx
@@ -23,7 +23,7 @@ import {
mockPersistedLogFactory,
} from './query_string_input.test.mocks';
-import { EuiFieldText } from '@elastic/eui';
+import { EuiTextArea } from '@elastic/eui';
import React from 'react';
import { QueryLanguageSwitcher } from './language_switcher';
import { QueryStringInput, QueryStringInputUI } from './query_string_input';
@@ -102,7 +102,7 @@ describe('QueryStringInput', () => {
indexPatterns: [stubIndexPatternWithFields],
})
);
- expect(component.find(EuiFieldText).props().value).toBe(kqlQuery.query);
+ expect(component.find(EuiTextArea).props().value).toBe(kqlQuery.query);
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(kqlQuery.language);
});
@@ -117,7 +117,7 @@ describe('QueryStringInput', () => {
expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(luceneQuery.language);
});
- it('Should disable autoFocus on EuiFieldText when disableAutoFocus prop is true', () => {
+ it('Should disable autoFocus on EuiTextArea when disableAutoFocus prop is true', () => {
const component = mount(
wrapQueryStringInputInContext({
query: kqlQuery,
@@ -126,7 +126,7 @@ describe('QueryStringInput', () => {
disableAutoFocus: true,
})
);
- expect(component.find(EuiFieldText).prop('autoFocus')).toBeFalsy();
+ expect(component.find(EuiTextArea).prop('autoFocus')).toBeFalsy();
});
it('Should create a unique PersistedLog based on the appName and query language', () => {
@@ -179,7 +179,7 @@ describe('QueryStringInput', () => {
const instance = component.find('QueryStringInputUI').instance() as QueryStringInputUI;
const input = instance.inputRef;
- const inputWrapper = component.find(EuiFieldText).find('input');
+ const inputWrapper = component.find(EuiTextArea).find('textarea');
inputWrapper.simulate('keyDown', { target: input, keyCode: 13, key: 'Enter', metaKey: true });
expect(mockCallback).toHaveBeenCalledTimes(1);
@@ -199,7 +199,7 @@ describe('QueryStringInput', () => {
const instance = component.find('QueryStringInputUI').instance() as QueryStringInputUI;
const input = instance.inputRef;
- const inputWrapper = component.find(EuiFieldText).find('input');
+ const inputWrapper = component.find(EuiTextArea).find('textarea');
inputWrapper.simulate('keyDown', { target: input, keyCode: 13, key: 'Enter', metaKey: true });
expect(mockPersistedLog.add).toHaveBeenCalledWith('response:200');
diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
index c746449f14c26..6f72aa829d8f3 100644
--- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
@@ -22,13 +22,14 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import {
- EuiFieldText,
+ EuiTextArea,
EuiOutsideClickDetector,
PopoverAnchorPosition,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiLink,
+ htmlIdGenerator,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -49,13 +50,14 @@ interface Props {
query: Query;
disableAutoFocus?: boolean;
screenTitle?: string;
- prepend?: React.ComponentProps['prepend'];
+ prepend?: any;
persistedLog?: PersistedLog;
bubbleSubmitEvent?: boolean;
placeholder?: string;
languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition;
onBlur?: () => void;
onChange?: (query: Query) => void;
+ onChangeQueryInputFocus?: (isFocused: boolean) => void;
onSubmit?: (query: Query) => void;
dataTestSubj?: string;
}
@@ -93,7 +95,7 @@ export class QueryStringInputUI extends Component {
indexPatterns: [],
};
- public inputRef: HTMLInputElement | null = null;
+ public inputRef: HTMLTextAreaElement | null = null;
private persistedLog: PersistedLog | undefined;
private abortController?: AbortController;
@@ -223,27 +225,32 @@ export class QueryStringInputUI extends Component {
this.onChange({ query: value, language: this.props.query.language });
};
- private onInputChange = (event: React.ChangeEvent) => {
+ private onInputChange = (event: React.ChangeEvent) => {
this.onQueryStringChange(event.target.value);
+ if (event.target.value === '') {
+ this.handleRemoveHeight();
+ } else {
+ this.handleAutoHeight();
+ }
};
- private onClickInput = (event: React.MouseEvent) => {
- if (event.target instanceof HTMLInputElement) {
+ private onClickInput = (event: React.MouseEvent) => {
+ if (event.target instanceof HTMLTextAreaElement) {
this.onQueryStringChange(event.target.value);
}
};
- private onKeyUp = (event: React.KeyboardEvent) => {
+ private onKeyUp = (event: React.KeyboardEvent) => {
if ([KEY_CODES.LEFT, KEY_CODES.RIGHT, KEY_CODES.HOME, KEY_CODES.END].includes(event.keyCode)) {
this.setState({ isSuggestionsVisible: true });
- if (event.target instanceof HTMLInputElement) {
+ if (event.target instanceof HTMLTextAreaElement) {
this.onQueryStringChange(event.target.value);
}
}
};
- private onKeyDown = (event: React.KeyboardEvent) => {
- if (event.target instanceof HTMLInputElement) {
+ private onKeyDown = (event: React.KeyboardEvent) => {
+ if (event.target instanceof HTMLTextAreaElement) {
const { isSuggestionsVisible, index } = this.state;
const preventDefault = event.preventDefault.bind(event);
const { target, key, metaKey } = event;
@@ -258,16 +265,19 @@ export class QueryStringInputUI extends Component {
switch (event.keyCode) {
case KEY_CODES.DOWN:
- event.preventDefault();
if (isSuggestionsVisible && index !== null) {
+ event.preventDefault();
this.incrementIndex(index);
- } else {
+ // Note to engineers. `isSuggestionVisible` does not mean the suggestions are visible.
+ // This should likely be fixed, it's more that suggestions can be shown.
+ } else if ((isSuggestionsVisible && index == null) || this.getQueryString() === '') {
+ event.preventDefault();
this.setState({ isSuggestionsVisible: true, index: 0 });
}
break;
case KEY_CODES.UP:
- event.preventDefault();
if (isSuggestionsVisible && index !== null) {
+ event.preventDefault();
this.decrementIndex(index);
}
break;
@@ -439,6 +449,17 @@ export class QueryStringInputUI extends Component {
if (this.state.isSuggestionsVisible) {
this.setState({ isSuggestionsVisible: false, index: null });
}
+ this.handleBlurHeight();
+ if (this.props.onChangeQueryInputFocus) {
+ this.props.onChangeQueryInputFocus(false);
+ }
+ };
+
+ private onInputBlur = () => {
+ this.handleBlurHeight();
+ if (this.props.onChangeQueryInputFocus) {
+ this.props.onChangeQueryInputFocus(false);
+ }
};
private onClickSuggestion = (suggestion: QuerySuggestion) => {
@@ -460,6 +481,8 @@ export class QueryStringInputUI extends Component {
this.setState({ index });
};
+ textareaId = htmlIdGenerator()();
+
public componentDidMount() {
const parsedQuery = fromUser(toUser(this.props.query.query));
if (!isEqual(this.props.query.query, parsedQuery)) {
@@ -468,6 +491,8 @@ export class QueryStringInputUI extends Component {
this.initPersistedLog();
this.fetchIndexPatterns().then(this.updateSuggestions);
+
+ window.addEventListener('resize', this.handleAutoHeight);
}
public componentDidUpdate(prevProps: Props) {
@@ -485,15 +510,18 @@ export class QueryStringInputUI extends Component {
}
if (this.state.selectionStart !== null && this.state.selectionEnd !== null) {
- if (this.inputRef) {
- // For some reason the type guard above does not make the compiler happy
- // @ts-ignore
+ if (this.inputRef != null) {
this.inputRef.setSelectionRange(this.state.selectionStart, this.state.selectionEnd);
}
this.setState({
selectionStart: null,
selectionEnd: null,
});
+ if (document.activeElement !== null && document.activeElement.id === this.textareaId) {
+ this.handleAutoHeight();
+ } else {
+ this.handleRemoveHeight();
+ }
}
}
@@ -501,8 +529,37 @@ export class QueryStringInputUI extends Component {
if (this.abortController) this.abortController.abort();
this.updateSuggestions.cancel();
this.componentIsUnmounting = true;
+ window.removeEventListener('resize', this.handleAutoHeight);
}
+ handleAutoHeight = () => {
+ if (this.inputRef !== null && document.activeElement === this.inputRef) {
+ this.inputRef.style.setProperty('height', `${this.inputRef.scrollHeight}px`, 'important');
+ }
+ };
+
+ handleRemoveHeight = () => {
+ if (this.inputRef !== null) {
+ this.inputRef.style.removeProperty('height');
+ }
+ };
+
+ handleBlurHeight = () => {
+ if (this.inputRef !== null) {
+ this.handleRemoveHeight();
+ this.inputRef.scrollTop = 0;
+ }
+ };
+
+ handleOnFocus = () => {
+ if (this.props.onChangeQueryInputFocus) {
+ this.props.onChangeQueryInputFocus(true);
+ }
+ requestAnimationFrame(() => {
+ this.handleAutoHeight();
+ });
+ };
+
public render() {
const isSuggestionsVisible = this.state.isSuggestionsVisible && {
'aria-controls': 'kbnTypeahead__items',
@@ -511,20 +568,24 @@ export class QueryStringInputUI extends Component {
const ariaCombobox = { ...isSuggestionsVisible, role: 'combobox' };
return (
-
-
-
-
-
+ {this.props.prepend}
+
+
+
+
{
onKeyUp={this.onKeyUp}
onChange={this.onInputChange}
onClick={this.onClickInput}
- onBlur={this.props.onBlur}
+ onBlur={this.onInputBlur}
+ onFocus={this.handleOnFocus}
+ className="kbnQueryBar__textarea"
fullWidth
- autoFocus={!this.props.disableAutoFocus}
- inputRef={(node) => {
+ rows={1}
+ id={this.textareaId}
+ autoFocus={
+ this.props.onChangeQueryInputFocus ? false : !this.props.disableAutoFocus
+ }
+ inputRef={(node: any) => {
if (node) {
this.inputRef = node;
}
@@ -550,7 +617,6 @@ export class QueryStringInputUI extends Component {
defaultMessage: 'Start typing to search and filter the {pageType} page',
values: { pageType: this.services.appName },
})}
- type="text"
aria-autocomplete="list"
aria-controls={this.state.isSuggestionsVisible ? 'kbnTypeahead__items' : undefined}
aria-activedescendant={
@@ -559,29 +625,29 @@ export class QueryStringInputUI extends Component {
: undefined
}
role="textbox"
- prepend={this.props.prepend}
- append={
-
- }
data-test-subj={this.props.dataTestSubj || 'queryInput'}
- />
+ >
+ {this.getQueryString()}
+
-
-
-
-
+
+
+
+
+
+
);
}
}
diff --git a/src/plugins/data/public/ui/typeahead/_suggestion.scss b/src/plugins/data/public/ui/typeahead/_suggestion.scss
index 3a215ceddcd00..81c05f1a8a78c 100644
--- a/src/plugins/data/public/ui/typeahead/_suggestion.scss
+++ b/src/plugins/data/public/ui/typeahead/_suggestion.scss
@@ -16,7 +16,7 @@ $kbnTypeaheadTypes: (
color: $euiTextColor;
background-color: $euiColorEmptyShade;
position: absolute;
- top: -1px;
+ top: -2px;
z-index: $euiZContentMenu;
width: 100%;
border-bottom-left-radius: $euiBorderRadius;
@@ -56,7 +56,6 @@ $kbnTypeaheadTypes: (
.kbnTypeahead__item.active {
background-color: $euiColorLightestShade;
-
.kbnSuggestionItem__callout {
background: $euiColorEmptyShade;
}
@@ -130,7 +129,6 @@ $kbnTypeaheadTypes: (
align-items: center;
}
-
.kbnSuggestionItem__text {
flex-grow: 0; /* 2 */
flex-basis: auto; /* 2 */
@@ -142,16 +140,15 @@ $kbnTypeaheadTypes: (
color: $euiTextColor;
}
-
.kbnSuggestionItem__description {
color: $euiColorDarkShade;
overflow: hidden;
text-overflow: ellipsis;
margin-left: $euiSizeXL;
-
+
&:empty {
flex-grow: 0;
- margin-left:0;
+ margin-left: 0;
}
}
diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js
index 906f0b83e99e7..949a01ff7873a 100644
--- a/test/functional/apps/discover/_discover.js
+++ b/test/functional/apps/discover/_discover.js
@@ -218,6 +218,8 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.common.navigateToApp('discover');
await PageObjects.header.awaitKibanaChrome();
await queryBar.setQuery('');
+ // To remove focus of the of the search bar so date/time picker can show
+ await PageObjects.discover.selectIndexPattern(defaultSettings.defaultIndex);
await PageObjects.timePicker.setDefaultAbsoluteRange();
log.debug(
diff --git a/x-pack/plugins/security_solution/cypress/integration/cases.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases.spec.ts
index efd9ece8aec56..9438c28f05fef 100644
--- a/x-pack/plugins/security_solution/cypress/integration/cases.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/cases.spec.ts
@@ -99,6 +99,6 @@ describe('Cases', () => {
cy.get(TIMELINE_TITLE).should('have.attr', 'value', case1.timeline.title);
cy.get(TIMELINE_DESCRIPTION).should('have.attr', 'value', case1.timeline.description);
- cy.get(TIMELINE_QUERY).should('have.attr', 'value', case1.timeline.query);
+ cy.get(TIMELINE_QUERY).invoke('text').should('eq', case1.timeline.query);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts b/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts
index 0c3424576e4cf..6b3fc9e751ea4 100644
--- a/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts
@@ -27,74 +27,67 @@ import {
describe('ml conditional links', () => {
it('sets the KQL from a single IP with a value for the query', () => {
loginAndWaitForPageWithoutDateRange(mlNetworkSingleIpKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(process.name: "conhost.exe" or process.name: "sc.exe")'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should('eq', '(process.name: "conhost.exe" or process.name: "sc.exe")');
});
it('sets the KQL from a multiple IPs with a null for the query', () => {
loginAndWaitForPageWithoutDateRange(mlNetworkMultipleIpNullKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '((source.ip: "127.0.0.1" or destination.ip: "127.0.0.1") or (source.ip: "127.0.0.2" or destination.ip: "127.0.0.2"))'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should(
+ 'eq',
+ '((source.ip: "127.0.0.1" or destination.ip: "127.0.0.1") or (source.ip: "127.0.0.2" or destination.ip: "127.0.0.2"))'
+ );
});
it('sets the KQL from a multiple IPs with a value for the query', () => {
loginAndWaitForPageWithoutDateRange(mlNetworkMultipleIpKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '((source.ip: "127.0.0.1" or destination.ip: "127.0.0.1") or (source.ip: "127.0.0.2" or destination.ip: "127.0.0.2")) and ((process.name: "conhost.exe" or process.name: "sc.exe"))'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should(
+ 'eq',
+ '((source.ip: "127.0.0.1" or destination.ip: "127.0.0.1") or (source.ip: "127.0.0.2" or destination.ip: "127.0.0.2")) and ((process.name: "conhost.exe" or process.name: "sc.exe"))'
+ );
});
it('sets the KQL from a $ip$ with a value for the query', () => {
loginAndWaitForPageWithoutDateRange(mlNetworkKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(process.name: "conhost.exe" or process.name: "sc.exe")'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should('eq', '(process.name: "conhost.exe" or process.name: "sc.exe")');
});
it('sets the KQL from a single host name with a value for query', () => {
loginAndWaitForPageWithoutDateRange(mlHostSingleHostKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(process.name: "conhost.exe" or process.name: "sc.exe")'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should('eq', '(process.name: "conhost.exe" or process.name: "sc.exe")');
});
it('sets the KQL from a multiple host names with null for query', () => {
loginAndWaitForPageWithoutDateRange(mlHostMultiHostNullKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(host.name: "siem-windows" or host.name: "siem-suricata")'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should('eq', '(host.name: "siem-windows" or host.name: "siem-suricata")');
});
it('sets the KQL from a multiple host names with a value for query', () => {
loginAndWaitForPageWithoutDateRange(mlHostMultiHostKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(host.name: "siem-windows" or host.name: "siem-suricata") and ((process.name: "conhost.exe" or process.name: "sc.exe"))'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should(
+ 'eq',
+ '(host.name: "siem-windows" or host.name: "siem-suricata") and ((process.name: "conhost.exe" or process.name: "sc.exe"))'
+ );
});
it('sets the KQL from a undefined/null host name but with a value for query', () => {
loginAndWaitForPageWithoutDateRange(mlHostVariableHostKqlQuery);
- cy.get(KQL_INPUT).should(
- 'have.attr',
- 'value',
- '(process.name: "conhost.exe" or process.name: "sc.exe")'
- );
+ cy.get(KQL_INPUT)
+ .invoke('text')
+ .should('eq', '(process.name: "conhost.exe" or process.name: "sc.exe")');
});
it('redirects from a single IP with a null for the query', () => {
diff --git a/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts
index a3a927cbea7d4..81af9ece9ed45 100644
--- a/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts
@@ -154,12 +154,12 @@ describe('url state', () => {
it('sets kql on network page', () => {
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.urlKqlNetworkNetwork);
- cy.get(KQL_INPUT).should('have.attr', 'value', 'source.ip: "10.142.0.9"');
+ cy.get(KQL_INPUT).invoke('text').should('eq', 'source.ip: "10.142.0.9"');
});
it('sets kql on hosts page', () => {
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.urlKqlHostsHosts);
- cy.get(KQL_INPUT).should('have.attr', 'value', 'source.ip: "10.142.0.9"');
+ cy.get(KQL_INPUT).invoke('text').should('eq', 'source.ip: "10.142.0.9"');
});
it('sets the url state when kql is set', () => {
@@ -230,8 +230,7 @@ describe('url state', () => {
it('Do not clears kql when navigating to a new page', () => {
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.urlKqlHostsHosts);
navigateFromHeaderTo(NETWORK);
-
- cy.get(KQL_INPUT).should('have.attr', 'value', 'source.ip: "10.142.0.9"');
+ cy.get(KQL_INPUT).invoke('text').should('eq', 'source.ip: "10.142.0.9"');
});
it.skip('sets and reads the url state for timeline by id', () => {
diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
index eca5885e7b3d9..88ae582b58891 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
@@ -82,7 +82,7 @@ export const fillAboutRuleAndContinue = (rule: CustomRule | MachineLearningRule)
export const fillDefineCustomRuleAndContinue = (rule: CustomRule) => {
cy.get(CUSTOM_QUERY_INPUT).type(rule.customQuery);
- cy.get(CUSTOM_QUERY_INPUT).should('have.attr', 'value', rule.customQuery);
+ cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', rule.customQuery);
cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true });
cy.get(CUSTOM_QUERY_INPUT).should('not.exist');
@@ -91,7 +91,7 @@ export const fillDefineCustomRuleAndContinue = (rule: CustomRule) => {
export const fillDefineCustomRuleWithImportedQueryAndContinue = (rule: CustomRule) => {
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
cy.get(TIMELINE(rule.timelineId)).click();
- cy.get(CUSTOM_QUERY_INPUT).should('have.attr', 'value', rule.customQuery);
+ cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', rule.customQuery);
cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true });
cy.get(CUSTOM_QUERY_INPUT).should('not.exist');
diff --git a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts
index 9e17433090c2b..761fd2c1e6a0b 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts
@@ -58,7 +58,7 @@ export const createNewTimeline = () => {
};
export const executeTimelineKQL = (query: string) => {
- cy.get(`${SEARCH_OR_FILTER_CONTAINER} input`).type(`${query} {enter}`);
+ cy.get(`${SEARCH_OR_FILTER_CONTAINER} textarea`).type(`${query} {enter}`);
};
export const expandFirstTimelineEventDetails = () => {
diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx
index a3cab1cfabd71..aac83ce650d86 100644
--- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx
@@ -214,15 +214,18 @@ describe('QueryBar ', () => {
/>
);
- const queryInput = wrapper.find(QueryBar).find('input[data-test-subj="queryInput"]');
+ let queryInput = wrapper.find(QueryBar).find('textarea[data-test-subj="queryInput"]');
queryInput.simulate('change', { target: { value: 'host.name:*' } });
- expect(queryInput.html()).toContain('value="host.name:*"');
+ wrapper.update();
+ queryInput = wrapper.find(QueryBar).find('textarea[data-test-subj="queryInput"]');
+ expect(queryInput.props().children).toBe('host.name:*');
wrapper.setProps({ filterQueryDraft: null });
wrapper.update();
+ queryInput = wrapper.find(QueryBar).find('textarea[data-test-subj="queryInput"]');
- expect(queryInput.html()).toContain('value=""');
+ expect(queryInput.props().children).toBe('');
});
});
@@ -258,7 +261,7 @@ describe('QueryBar ', () => {
const onSubmitQueryRef = searchBarProps.onQuerySubmit;
const onSavedQueryRef = searchBarProps.onSavedQueryUpdated;
- const queryInput = wrapper.find(QueryBar).find('input[data-test-subj="queryInput"]');
+ const queryInput = wrapper.find(QueryBar).find('textarea[data-test-subj="queryInput"]');
queryInput.simulate('change', { target: { value: 'hello: world' } });
wrapper.update();