Autocomplete on multi indices (#164608)

## Summary

This PR makes autocomplete able to be activated right after `,` (comma).


![autocomplete-on-multi-indices](4f3d1530-c5ac-438f-a08a-ef2e4fe57d9c)

Fixes #163000

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))

### For maintainers

- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

## Release note

Fixes a bug that autocomplete does not work right after a comma.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Youhei Sakurai 2023-09-17 11:29:12 +09:00 committed by GitHub
parent 800a87df45
commit 46d790921a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 7 deletions

View file

@ -25,7 +25,7 @@ import * as utils from '../utils';
import { populateContext } from './engine';
import type { AutoCompleteContext, DataAutoCompleteRulesOneOf, ResultTerm } from './types';
import { URL_PATH_END_MARKER } from './components';
import { URL_PATH_END_MARKER, ConstantComponent } from './components';
let lastEvaluatedToken: Token | null = null;
@ -980,10 +980,38 @@ export default function ({
context.token = ret.token;
context.otherTokenValues = ret.otherTokenValues;
context.urlTokenPath = ret.urlTokenPath;
const components = getTopLevelUrlCompleteComponents(context.method);
populateContext(ret.urlTokenPath, context, editor, true, components);
context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet!, 'endpoint');
const components = getTopLevelUrlCompleteComponents(context.method);
const { tokenPath, predicate } = (() => {
const lastUrlTokenPath =
Array.isArray(context.urlTokenPath) && context.urlTokenPath.length !== 0
? context.urlTokenPath[context.urlTokenPath.length - 1]
: null;
// Checking the last chunk of path like 'c,d,' of 'GET /a/b/c,d,'
if (
Array.isArray(lastUrlTokenPath) &&
// true if neither c nor d equals to every ConstantComponent's name (such as _search)
!_.find(
components,
(c) => c instanceof ConstantComponent && _.find(lastUrlTokenPath, (p) => c.name === p)
)
) {
// will simulate autocomplete on 'GET /a/b/' with a filter by index
return {
tokenPath: context.urlTokenPath.slice(0, -1),
predicate: (term) => term.meta === 'index',
};
} else {
// will do nothing special
return { tokenPath: context.urlTokenPath, predicate: (term) => true };
}
})();
populateContext(tokenPath, context, editor, true, components);
context.autoCompleteSet = _.filter(
addMetaToTermsList(context.autoCompleteSet!, 'endpoint'),
predicate
);
}
function addUrlParamsAutoCompleteSetToContext(context: AutoCompleteContext, pos: Position) {
@ -1112,11 +1140,11 @@ export default function ({
if (
lastEvaluatedToken.position.column + 1 === currentToken.position.column &&
lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber &&
lastEvaluatedToken.type === 'url.slash' &&
(lastEvaluatedToken.type === 'url.slash' || lastEvaluatedToken.type === 'url.comma') &&
currentToken.type === 'url.part' &&
currentToken.value.length === 1
) {
// do not suppress autocomplete for a single character immediately following a slash in URL
// do not suppress autocomplete for a single character immediately following a slash or comma in URL
} else if (
lastEvaluatedToken.position.column < currentToken.position.column &&
lastEvaluatedToken.position.lineNumber === currentToken.position.lineNumber &&

View file

@ -273,7 +273,7 @@ GET _search
for (const char of ['/', '_']) {
await PageObjects.console.sleepForDebouncePeriod();
log.debug('Key type "%s"', char);
await PageObjects.console.enterText(char); // e.g. 'GET .kibana/' -> 'GET .kibana/_'
await PageObjects.console.enterText(char); // i.e. 'GET .kibana/' -> 'GET .kibana/_'
}
await retry.waitFor('autocomplete to be visible', () =>
@ -281,6 +281,37 @@ GET _search
);
expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true);
});
it('should activate auto-complete for multiple indices after comma in URL', async () => {
await PageObjects.console.enterText('GET /_cat/indices/.kibana');
await PageObjects.console.sleepForDebouncePeriod();
log.debug('Key type ","');
await PageObjects.console.enterText(','); // i.e. 'GET /_cat/indices/.kibana,'
await PageObjects.console.sleepForDebouncePeriod();
log.debug('Key type Ctrl+SPACE');
await PageObjects.console.pressCtrlSpace();
await retry.waitFor('autocomplete to be visible', () =>
PageObjects.console.isAutocompleteVisible()
);
expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(true);
});
it('should not activate auto-complete after comma following endpoint in URL', async () => {
await PageObjects.console.enterText('GET _search');
await PageObjects.console.sleepForDebouncePeriod();
log.debug('Key type ","');
await PageObjects.console.enterText(','); // i.e. 'GET _search,'
await PageObjects.console.sleepForDebouncePeriod();
log.debug('Key type Ctrl+SPACE');
await PageObjects.console.pressCtrlSpace();
expect(await PageObjects.console.isAutocompleteVisible()).to.be.eql(false);
});
});
describe('with a missing comma in query', () => {

View file

@ -429,6 +429,14 @@ export class ConsolePageObject extends FtrService {
await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], '/']);
}
public async pressCtrlSpace() {
const textArea = await this.testSubjects.find('console-textarea');
await textArea.pressKeys([
Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'],
Key.SPACE,
]);
}
public async clickContextMenu() {
const contextMenu = await this.testSubjects.find('toggleConsoleMenu');
await contextMenu.click();