/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import { fireEvent, render } from '@testing-library/react'; import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; import DSLService from 'public/services/requests/dsl'; import React from 'react'; import { Autocomplete } from './autocomplete'; import { parseGetSuggestions } from './autocomplete_logic'; import { AutocompleteItem, pipeCommands, statsCommands, } from '../../../../common/constants/autocomplete'; import { act } from 'react-dom/test-utils'; configure({ adapter: new Adapter() }); describe('renders autocomplete', function () { const query = ''; const tempQuery = ''; const handleQueryChange = jest.fn(); const handleQuerySearch = jest.fn(); const dslService = ({ http: jest.fn(), fetch: jest.fn(), fetchIndices: jest.fn(), fetchFields: jest.fn(), } as unknown) as DSLService; const getSuggestions = jest.fn(); const onItemSelect = jest.fn(); const utils = render( ); const searchBar = utils.getByPlaceholderText('Enter PPL query'); it('handles query change', () => { act(() => { fireEvent.change(searchBar, { target: { value: 'new query' } }); }); expect(handleQueryChange).toBeCalledWith('new query'); }); it('handles query search on shift enter', () => { act(() => { fireEvent.keyDown(searchBar, { keyCode: 13, shiftKey: true }); }); expect(handleQuerySearch).toBeCalled(); }); }); describe('autocomplete logic', function () { const dslService = ({ http: jest.fn(), fetch: jest .fn() .mockReturnValueOnce({ aggregations: { top_tags: { buckets: [{ key: 'data', doc_count: 1 }] } }, }) .mockReturnValueOnce({ aggregations: { top_tags: { buckets: [ { key: 1, doc_count: 1 }, { key: 0, doc_count: 1 }, ], }, }, }) .mockReturnValue({ aggregations: { top_tags: { buckets: [{ key: 24, doc_count: 1 }] } } }), fetchIndices: jest.fn().mockReturnValue([{ index: 'test_index' }]), fetchFields: jest.fn().mockReturnValue({ test_index: { mappings: { properties: { str_field: { type: 'string' }, bool_field: { type: 'boolean' }, num_field: { type: 'integer' }, }, }, }, }), } as unknown) as DSLService; it('suggests source if empty', async () => { const input = ''; const expected = [ { label: 'source', input, suggestion: 'source', itemName: 'source', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(dslService.fetchIndices).toBeCalled(); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest source after S', async () => { const input = 'S'; const expected = [ { label: 'source', input, suggestion: 'ource', itemName: 'source', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests = after source', async () => { const input = 'source '; const expected = [ { label: 'source =', input, suggestion: '=', itemName: '=', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests index after source =', async () => { const input = 'source = '; const expected = [ { label: 'source = test_index', input, suggestion: 'test_index', itemName: 'test_index', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest index after source = TeSt', async () => { const input = 'source = TeSt'; const expected = [ { label: 'source = test_index', input, suggestion: '_index', itemName: 'test_index', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests | after source = test_index', async () => { const input = 'source = test_index '; const expected = [ { label: 'source = test_index |', input, suggestion: '|', itemName: '|', }, { label: 'source = test_index,', input, suggestion: ',', itemName: ',', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests pipeCommands after |', async () => { const input = 'source = test_index | '; const expected = pipeCommands.map((c) => { return { label: `source = test_index | ${c.label}`, input, suggestion: c.label, itemName: c.label, }; }) as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(dslService.fetchFields).toBeCalled(); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest field after where StR_F', async () => { const input = 'source = test_index | where StR_F'; const expected = [ { label: 'source = test_index | where str_field', input, suggestion: 'ield', itemName: 'str_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests = after where str_field', async () => { const input = 'source = test_index | where str_field '; const expected = [ { label: 'source = test_index | where str_field =', input, suggestion: '=', itemName: '=', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(dslService.fetch).toBeCalled(); expect(suggestion).toStrictEqual(expected); }); it('suggests data after where str_field = ', async () => { const input = 'source = test_index | where str_field = '; const expected = [ { label: 'source = test_index | where str_field = "data"', input, suggestion: '"data"', itemName: '"data"', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest data after where str_field = "D', async () => { const input = 'source = test_index | where str_field = "D'; const expected = [ { label: 'source = test_index | where str_field = "data"', input, suggestion: 'ata"', itemName: '"data"', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests | after where str_field = "data"', async () => { const input = 'source = test_index | where str_field = "data" '; const expected = [ { label: 'source = test_index | where str_field = "data" |', input, suggestion: '|', itemName: '|', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest field after where BoOl_F', async () => { const input = 'source = test_index | where BoOl_F'; const expected = [ { label: 'source = test_index | where bool_field', input, suggestion: 'ield', itemName: 'bool_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests = after where bool_field', async () => { const input = 'source = test_index | where bool_field '; const expected = [ { label: 'source = test_index | where bool_field =', input, suggestion: '=', itemName: '=', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(dslService.fetch).toBeCalled(); expect(suggestion).toStrictEqual(expected); }); it('suggests data after where bool_field = ', async () => { const input = 'source = test_index | where bool_field = '; const expected = [ { label: 'source = test_index | where bool_field = True', input, suggestion: 'True', itemName: 'True', }, { label: 'source = test_index | where bool_field = False', input, suggestion: 'False', itemName: 'False', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest data after where bool_field = fA', async () => { const input = 'source = test_index | where bool_field = fA'; const expected = [ { label: 'source = test_index | where bool_field = False', input, suggestion: 'lse', itemName: 'False', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests | after where bool_field = True', async () => { const input = 'source = test_index | where bool_field = True '; const expected = [ { label: 'source = test_index | where bool_field = True |', input, suggestion: '|', itemName: '|', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest match( after where Ma', async () => { const input = 'source = test_index | where Ma'; const expected = [ { label: 'source = test_index | where match(', input, suggestion: 'tch(', itemName: 'match(', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after where match(', async () => { const input = 'source = test_index | where match( '; const expected = [ { label: 'source = test_index | where match( str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | where match( bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | where match( num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests , after where match( num_field', async () => { const input = 'source = test_index | where match( num_field '; const expected = [ { label: 'source = test_index | where match( num_field ,', input, suggestion: ',', itemName: ',', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(dslService.fetch).toBeCalled(); expect(suggestion).toStrictEqual(expected); }); it('suggests data after where match( num_field ,', async () => { const input = 'source = test_index | where match( num_field , '; const expected = [ { label: 'source = test_index | where match( num_field , 24', input, suggestion: '24', itemName: '24', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests ) after where match( num_field , 24', async () => { const input = 'source = test_index | where match( num_field , 24 '; const expected = [ { label: 'source = test_index | where match( num_field , 24 )', input, suggestion: ')', itemName: ')', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests | after where match( num_field , 24 )', async () => { const input = 'source = test_index | where match( num_field , 24 ) '; const expected = [ { label: 'source = test_index | where match( num_field , 24 ) |', input, suggestion: '|', itemName: '|', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests statsCommands after stats', async () => { const input = 'source = test_index | stats '; const expected = statsCommands.map((c) => { return { label: `source = test_index | stats ${c.label}`, input, suggestion: c.label, itemName: c.label, }; }) as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests by, comma, pipe after stats count()', async () => { const input = 'source = test_index | stats count() '; const expected = [',', '|', 'by'].map((suggestion) => { return { label: `source = test_index | stats count() ${suggestion}`, input, suggestion, itemName: suggestion, }; }) as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after stats count() by', async () => { const input = 'source = test_index | stats count() by '; const expected = [ { label: 'source = test_index | stats count() by span(', input, suggestion: 'span(', itemName: 'span(', }, { label: 'source = test_index | stats count() by str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | stats count() by bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | stats count() by num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests | after stats count() by str_field', async () => { const input = 'source = test_index | stats count() by str_field '; const expected = [ { label: 'source = test_index | stats count() by str_field |', input, suggestion: '|', itemName: '|', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests num_field after stats sum(', async () => { const input = 'source = test_index | stats sum( '; const expected = [ { label: 'source = test_index | stats sum( num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests by after stats sum( num_field )', async () => { const input = 'source = test_index | stats sum( num_field ) '; const expected = [ { label: 'source = test_index | stats sum( num_field ) ,', input, suggestion: ',', itemName: ',', }, { label: 'source = test_index | stats sum( num_field ) |', input, suggestion: '|', itemName: '|', }, { label: 'source = test_index | stats sum( num_field ) by', input, suggestion: 'by', itemName: 'by', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after stats sum( num_field ) by', async () => { const input = 'source = test_index | stats sum( num_field ) by '; const expected = [ { label: 'source = test_index | stats sum( num_field ) by span(', input, suggestion: 'span(', itemName: 'span(', }, { label: 'source = test_index | stats sum( num_field ) by str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | stats sum( num_field ) by bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | stats sum( num_field ) by num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest fields after FiE', async () => { const input = 'source = test_index | FiE'; const expected = [ { label: 'source = test_index | fields', input, suggestion: 'lds', itemName: 'fields', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after fields', async () => { const input = 'source = test_index | fields '; const expected = [ { label: 'source = test_index | fields +', input, suggestion: '+', itemName: '+', }, { label: 'source = test_index | fields -', input, suggestion: '-', itemName: '-', }, { label: 'source = test_index | fields str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | fields bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | fields num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests , after fields str_field', async () => { const input = 'source = test_index | fields str_field '; const expected = [ { label: 'source = test_index | fields str_field ,', input, suggestion: ',', itemName: ',', }, { label: 'source = test_index | fields str_field |', input, suggestion: '|', itemName: '|', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after fields str_field, ', async () => { const input = 'source = test_index | fields str_field , '; const expected = [ { label: 'source = test_index | fields str_field , str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | fields str_field , bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | fields str_field , num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('continues to suggest dedup after DE', async () => { const input = 'source = test_index | DE'; const expected = [ { label: 'source = test_index | dedup', input, suggestion: 'dup', itemName: 'dedup', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); it('suggests fields after dedup', async () => { const input = 'source = test_index | dedup '; const expected = [ { label: 'source = test_index | dedup str_field', input, suggestion: 'str_field', itemName: 'str_field', }, { label: 'source = test_index | dedup bool_field', input, suggestion: 'bool_field', itemName: 'bool_field', }, { label: 'source = test_index | dedup num_field', input, suggestion: 'num_field', itemName: 'num_field', }, ] as AutocompleteItem[]; const suggestion = await parseGetSuggestions('', input, dslService); expect(suggestion).toStrictEqual(expected); }); });