Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
6af6593118
commit
2df4d5ca96
|
@ -26,18 +26,18 @@
|
|||
padding-top: $euiSizeS + 3px;
|
||||
box-shadow: 0 0 0 1px $euiFormBorderColor;
|
||||
|
||||
&:not(:focus):not(:invalid) {
|
||||
&:not(.kbnQueryBar__textarea--autoHeight):not(:invalid) {
|
||||
@include euiYScrollWithShadows;
|
||||
}
|
||||
|
||||
&:not(:focus) {
|
||||
&:not(.kbnQueryBar__textarea--autoHeight) {
|
||||
white-space: nowrap;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
// When focused, let it scroll
|
||||
&:focus {
|
||||
&.kbnQueryBar__textarea--autoHeight {
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
white-space: normal;
|
||||
|
|
|
@ -86,6 +86,8 @@ export function QueryLanguageSwitcher({
|
|||
isOpen={isPopoverOpen}
|
||||
closePopover={() => setIsPopoverOpen(false)}
|
||||
repositionOnScroll
|
||||
ownFocus={true}
|
||||
initialFocus={'[role="switch"]'}
|
||||
>
|
||||
<EuiPopoverTitle>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -21,13 +21,14 @@ import { render } from '@testing-library/react';
|
|||
import { EuiTextArea, EuiIcon } from '@elastic/eui';
|
||||
|
||||
import { QueryLanguageSwitcher } from './language_switcher';
|
||||
import { QueryStringInput } from './';
|
||||
import type QueryStringInputUI from './query_string_input';
|
||||
import QueryStringInputUI from './query_string_input';
|
||||
|
||||
import { coreMock } from '../../../../../core/public/mocks';
|
||||
import { dataPluginMock } from '../../mocks';
|
||||
import { stubIndexPatternWithFields } from '../../stubs';
|
||||
import { KibanaContextProvider } from 'src/plugins/kibana_react/public';
|
||||
import { KibanaContextProvider, withKibana } from 'src/plugins/kibana_react/public';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
const startMock = coreMock.createStart();
|
||||
|
||||
|
@ -62,12 +63,9 @@ const createMockStorage = () => ({
|
|||
clear: jest.fn(),
|
||||
});
|
||||
|
||||
function wrapQueryStringInputInContext(testProps: any, storage?: any) {
|
||||
const defaultOptions = {
|
||||
screenTitle: 'Another Screen',
|
||||
intl: null as any,
|
||||
};
|
||||
const QueryStringInput = withKibana(QueryStringInputUI);
|
||||
|
||||
function wrapQueryStringInputInContext(testProps: any, storage?: any) {
|
||||
const services = {
|
||||
...startMock,
|
||||
data: dataPluginMock.createStartContract(),
|
||||
|
@ -75,6 +73,11 @@ function wrapQueryStringInputInContext(testProps: any, storage?: any) {
|
|||
storage: storage || createMockStorage(),
|
||||
};
|
||||
|
||||
const defaultOptions = {
|
||||
screenTitle: 'Another Screen',
|
||||
intl: null as any,
|
||||
};
|
||||
|
||||
return (
|
||||
<I18nProvider>
|
||||
<KibanaContextProvider services={services}>
|
||||
|
@ -84,15 +87,12 @@ function wrapQueryStringInputInContext(testProps: any, storage?: any) {
|
|||
);
|
||||
}
|
||||
|
||||
// FAILING: https://github.com/elastic/kibana/issues/85715
|
||||
// FAILING: https://github.com/elastic/kibana/issues/89603
|
||||
// FAILING: https://github.com/elastic/kibana/issues/89641
|
||||
describe.skip('QueryStringInput', () => {
|
||||
describe('QueryStringInput', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it.skip('Should render the given query', async () => {
|
||||
it('Should render the given query', async () => {
|
||||
const { getByText } = render(
|
||||
wrapQueryStringInputInContext({
|
||||
query: kqlQuery,
|
||||
|
@ -228,7 +228,7 @@ describe.skip('QueryStringInput', () => {
|
|||
expect(mockCallback).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('Should fire onChangeQueryInputFocus callback on input blur', () => {
|
||||
it('Should fire onChangeQueryInputFocus after a delay', () => {
|
||||
const mockCallback = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
|
@ -243,10 +243,93 @@ describe.skip('QueryStringInput', () => {
|
|||
const inputWrapper = component.find(EuiTextArea).find('textarea');
|
||||
inputWrapper.simulate('blur');
|
||||
|
||||
jest.advanceTimersByTime(10);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(0);
|
||||
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(1);
|
||||
expect(mockCallback).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('Should not fire onChangeQueryInputFocus if input is focused back', () => {
|
||||
const mockCallback = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
wrapQueryStringInputInContext({
|
||||
query: kqlQuery,
|
||||
onChangeQueryInputFocus: mockCallback,
|
||||
indexPatterns: [stubIndexPatternWithFields],
|
||||
disableAutoFocus: true,
|
||||
})
|
||||
);
|
||||
|
||||
const inputWrapper = component.find(EuiTextArea).find('textarea');
|
||||
inputWrapper.simulate('blur');
|
||||
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(mockCallback).toHaveBeenCalledTimes(0);
|
||||
|
||||
inputWrapper.simulate('focus');
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(1);
|
||||
expect(mockCallback).toHaveBeenCalledWith(true);
|
||||
|
||||
jest.advanceTimersByTime(100);
|
||||
expect(mockCallback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Should call onSubmit after a delay when submitOnBlur is on and blurs input', () => {
|
||||
const mockCallback = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
wrapQueryStringInputInContext({
|
||||
query: kqlQuery,
|
||||
onSubmit: mockCallback,
|
||||
indexPatterns: [stubIndexPatternWithFields],
|
||||
disableAutoFocus: true,
|
||||
submitOnBlur: true,
|
||||
})
|
||||
);
|
||||
|
||||
const inputWrapper = component.find(EuiTextArea).find('textarea');
|
||||
inputWrapper.simulate('blur');
|
||||
|
||||
jest.advanceTimersByTime(10);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(0);
|
||||
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(1);
|
||||
expect(mockCallback).toHaveBeenCalledWith(kqlQuery);
|
||||
});
|
||||
|
||||
it("Shouldn't call onSubmit on blur by default", () => {
|
||||
const mockCallback = jest.fn();
|
||||
|
||||
const component = mount(
|
||||
wrapQueryStringInputInContext({
|
||||
query: kqlQuery,
|
||||
onSubmit: mockCallback,
|
||||
indexPatterns: [stubIndexPatternWithFields],
|
||||
disableAutoFocus: true,
|
||||
})
|
||||
);
|
||||
|
||||
const inputWrapper = component.find(EuiTextArea).find('textarea');
|
||||
inputWrapper.simulate('blur');
|
||||
|
||||
jest.advanceTimersByTime(10);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(0);
|
||||
|
||||
jest.advanceTimersByTime(100);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should use PersistedLog for recent search suggestions', async () => {
|
||||
const component = mount(
|
||||
wrapQueryStringInputInContext({
|
||||
|
|
|
@ -123,6 +123,12 @@ export default class QueryStringInputUI extends Component<Props, State> {
|
|||
private componentIsUnmounting = false;
|
||||
private queryBarInputDivRefInstance: RefObject<HTMLDivElement> = createRef();
|
||||
|
||||
/**
|
||||
* If any element within the container is currently focused
|
||||
* @private
|
||||
*/
|
||||
private isFocusWithin = false;
|
||||
|
||||
private getQueryString = () => {
|
||||
return toUser(this.props.query.query);
|
||||
};
|
||||
|
@ -492,29 +498,36 @@ export default class QueryStringInputUI extends Component<Props, State> {
|
|||
private onOutsideClick = () => {
|
||||
if (this.state.isSuggestionsVisible) {
|
||||
this.setState({ isSuggestionsVisible: false, index: null });
|
||||
}
|
||||
this.handleBlurHeight();
|
||||
if (this.props.onChangeQueryInputFocus) {
|
||||
this.props.onChangeQueryInputFocus(false);
|
||||
this.scheduleOnInputBlur();
|
||||
}
|
||||
};
|
||||
|
||||
private onInputBlur = () => {
|
||||
this.handleBlurHeight();
|
||||
if (this.props.onChangeQueryInputFocus) {
|
||||
this.props.onChangeQueryInputFocus(false);
|
||||
}
|
||||
if (isFunction(this.props.onBlur)) {
|
||||
this.props.onBlur();
|
||||
}
|
||||
if (this.props.submitOnBlur) {
|
||||
// Input blur triggers when the user selects something from autocomplete, so wait a bit to ensure that
|
||||
// the entire QueryStringInput component has actually blurred (e.g. from user clicking or tabbing away)
|
||||
setTimeout(() => {
|
||||
if (document.activeElement !== this.inputRef) {
|
||||
private blurTimeoutHandle: number | undefined;
|
||||
/**
|
||||
* Notify parent about input's blur after a delay only
|
||||
* if the focus didn't get back inside the input container
|
||||
* and if suggestions were closed
|
||||
* https://github.com/elastic/kibana/issues/92040
|
||||
*/
|
||||
private scheduleOnInputBlur = () => {
|
||||
clearTimeout(this.blurTimeoutHandle);
|
||||
this.blurTimeoutHandle = window.setTimeout(() => {
|
||||
if (!this.isFocusWithin && !this.state.isSuggestionsVisible && !this.componentIsUnmounting) {
|
||||
this.handleBlurHeight();
|
||||
if (this.props.onChangeQueryInputFocus) {
|
||||
this.props.onChangeQueryInputFocus(false);
|
||||
}
|
||||
|
||||
if (this.props.submitOnBlur) {
|
||||
this.onSubmit(this.props.query);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}, 50);
|
||||
};
|
||||
|
||||
private onInputBlur = () => {
|
||||
if (isFunction(this.props.onBlur)) {
|
||||
this.props.onBlur();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -604,6 +617,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
|
|||
|
||||
handleAutoHeight = () => {
|
||||
if (this.inputRef !== null && document.activeElement === this.inputRef) {
|
||||
this.inputRef.classList.add('kbnQueryBar__textarea--autoHeight');
|
||||
this.inputRef.style.setProperty('height', `${this.inputRef.scrollHeight}px`, 'important');
|
||||
}
|
||||
this.handleListUpdate();
|
||||
|
@ -612,6 +626,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
|
|||
handleRemoveHeight = () => {
|
||||
if (this.inputRef !== null) {
|
||||
this.inputRef.style.removeProperty('height');
|
||||
this.inputRef.classList.remove('kbnQueryBar__textarea--autoHeight');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -648,7 +663,16 @@ export default class QueryStringInputUI extends Component<Props, State> {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className={containerClassName}>
|
||||
<div
|
||||
className={containerClassName}
|
||||
onFocus={(e) => {
|
||||
this.isFocusWithin = true;
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
this.isFocusWithin = false;
|
||||
this.scheduleOnInputBlur();
|
||||
}}
|
||||
>
|
||||
{this.props.prepend}
|
||||
<EuiOutsideClickDetector onOutsideClick={this.onOutsideClick}>
|
||||
<div
|
||||
|
|
|
@ -196,6 +196,7 @@ export function SavedQueryManagementComponent({
|
|||
panelPaddingSize="none"
|
||||
buffer={-8}
|
||||
repositionOnScroll
|
||||
ownFocus={true}
|
||||
>
|
||||
<div
|
||||
className="kbnSavedQueryManagement__popover"
|
||||
|
|
|
@ -45,7 +45,8 @@ export function QueryBarProvider({ getService, getPageObjects }: FtrProviderCont
|
|||
|
||||
public async clearQuery(): Promise<void> {
|
||||
await this.setQuery('');
|
||||
await PageObjects.common.pressTabKey();
|
||||
await PageObjects.common.pressTabKey(); // move outside of input into language switcher
|
||||
await PageObjects.common.pressTabKey(); // move outside of language switcher so time picker appears
|
||||
}
|
||||
|
||||
public async submitQuery(): Promise<void> {
|
||||
|
|
Loading…
Reference in a new issue